[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH v4 17/32] target-xtensa: implement exceptions
From: |
Blue Swirl |
Subject: |
Re: [Qemu-devel] [PATCH v4 17/32] target-xtensa: implement exceptions |
Date: |
Sun, 4 Sep 2011 18:22:16 +0000 |
On Thu, Sep 1, 2011 at 8:45 PM, Max Filippov <address@hidden> wrote:
> - mark privileged opcodes with ring check;
> - make debug exception on exception handler entry.
>
> Signed-off-by: Max Filippov <address@hidden>
> ---
> cpu-exec.c | 6 +++
> target-xtensa/cpu.h | 67 ++++++++++++++++++++++++++++
> target-xtensa/helper.c | 37 +++++++++++++++-
> target-xtensa/helpers.h | 2 +
> target-xtensa/op_helper.c | 29 ++++++++++++
> target-xtensa/translate.c | 107 ++++++++++++++++++++++++++++++++++++++++++--
> 6 files changed, 242 insertions(+), 6 deletions(-)
>
> diff --git a/cpu-exec.c b/cpu-exec.c
> index 3fce033..2fc37d8 100644
> --- a/cpu-exec.c
> +++ b/cpu-exec.c
> @@ -488,6 +488,12 @@ int cpu_exec(CPUState *env)
> do_interrupt(env);
> next_tb = 0;
> }
> +#elif defined(TARGET_XTENSA)
> + if (interrupt_request & CPU_INTERRUPT_HARD) {
> + env->exception_index = EXC_IRQ;
> + do_interrupt(env);
> + next_tb = 0;
> + }
> #endif
> /* Don't use the cached interrupt_request value,
> do_interrupt may have updated the EXITTB flag. */
> diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
> index 939222c..cae6637 100644
> --- a/target-xtensa/cpu.h
> +++ b/target-xtensa/cpu.h
> @@ -108,7 +108,12 @@ enum {
> enum {
> SAR = 3,
> SCOMPARE1 = 12,
> + EPC1 = 177,
> + DEPC = 192,
> + EXCSAVE1 = 209,
> PS = 230,
> + EXCCAUSE = 232,
> + EXCVADDR = 238,
> };
>
> #define PS_INTLEVEL 0xf
> @@ -129,9 +134,60 @@ enum {
>
> #define PS_WOE 0x40000
>
> +enum {
> + /* Static vectors */
> + EXC_RESET,
> + EXC_MEMORY_ERROR,
> +
> + /* Dynamic vectors */
> + EXC_WINDOW_OVERFLOW4,
> + EXC_WINDOW_UNDERFLOW4,
> + EXC_WINDOW_OVERFLOW8,
> + EXC_WINDOW_UNDERFLOW8,
> + EXC_WINDOW_OVERFLOW12,
> + EXC_WINDOW_UNDERFLOW12,
> + EXC_IRQ,
> + EXC_KERNEL,
> + EXC_USER,
> + EXC_DOUBLE,
> + EXC_MAX
> +};
> +
> +enum {
> + ILLEGAL_INSTRUCTION_CAUSE = 0,
> + SYSCALL_CAUSE,
> + INSTRUCTION_FETCH_ERROR_CAUSE,
> + LOAD_STORE_ERROR_CAUSE,
> + LEVEL1_INTERRUPT_CAUSE,
> + ALLOCA_CAUSE,
> + INTEGER_DIVIDE_BY_ZERO_CAUSE,
> + PRIVILEGED_CAUSE = 8,
> + LOAD_STORE_ALIGNMENT_CAUSE,
> +
> + INSTR_PIF_DATA_ERROR_CAUSE = 12,
> + LOAD_STORE_PIF_DATA_ERROR_CAUSE,
> + INSTR_PIF_ADDR_ERROR_CAUSE,
> + LOAD_STORE_PIF_ADDR_ERROR_CAUSE,
> +
> + INST_TLB_MISS_CAUSE,
> + INST_TLB_MULTI_HIT_CAUSE,
> + INST_FETCH_PRIVILEGE_CAUSE,
> + INST_FETCH_PROHIBITED_CAUSE = 20,
> + LOAD_STORE_TLB_MISS_CAUSE = 24,
> + LOAD_STORE_TLB_MULTI_HIT_CAUSE,
> + LOAD_STORE_PRIVILEGE_CAUSE,
> + LOAD_PROHIBITED_CAUSE = 28,
> + STORE_PROHIBITED_CAUSE,
> +
> + COPROCESSOR0_DISABLED = 32,
> +};
> +
> typedef struct XtensaConfig {
> const char *name;
> uint64_t options;
> + int excm_level;
> + int ndepc;
> + uint32_t exception_vector[EXC_MAX];
> } XtensaConfig;
>
> typedef struct CPUXtensaState {
> @@ -141,6 +197,8 @@ typedef struct CPUXtensaState {
> uint32_t sregs[256];
> uint32_t uregs[256];
>
> + int exception_taken;
> +
> CPU_COMMON
> } CPUXtensaState;
>
> @@ -164,6 +222,15 @@ static inline bool xtensa_option_enabled(const
> XtensaConfig *config, int opt)
> return (config->options & XTENSA_OPTION_BIT(opt)) != 0;
> }
>
> +static inline int xtensa_get_cintlevel(const CPUState *env)
> +{
> + int level = (env->sregs[PS] & PS_INTLEVEL) >> PS_INTLEVEL_SHIFT;
> + if ((env->sregs[PS] & PS_EXCM) && env->config->excm_level > level) {
> + level = env->config->excm_level;
> + }
> + return level;
> +}
> +
> static inline int xtensa_get_ring(const CPUState *env)
> {
> if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
> diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
> index 83b8a04..44ebb9f 100644
> --- a/target-xtensa/helper.c
> +++ b/target-xtensa/helper.c
> @@ -36,7 +36,8 @@
>
> void cpu_reset(CPUXtensaState *env)
> {
> - env->pc = 0;
> + env->exception_taken = 0;
> + env->pc = env->config->exception_vector[EXC_RESET];
> env->sregs[PS] = 0x1f;
> }
>
> @@ -44,6 +45,20 @@ static const XtensaConfig core_config[] = {
> {
> .name = "sample-xtensa-core",
> .options = -1,
> + .ndepc = 1,
> + .excm_level = 16,
> + .exception_vector = {
> + [EXC_RESET] = 0x5fff8000,
> + [EXC_WINDOW_OVERFLOW4] = 0x5fff8400,
> + [EXC_WINDOW_UNDERFLOW4] = 0x5fff8440,
> + [EXC_WINDOW_OVERFLOW8] = 0x5fff8480,
> + [EXC_WINDOW_UNDERFLOW8] = 0x5fff84c0,
> + [EXC_WINDOW_OVERFLOW12] = 0x5fff8500,
> + [EXC_WINDOW_UNDERFLOW12] = 0x5fff8540,
> + [EXC_KERNEL] = 0x5fff861c,
> + [EXC_USER] = 0x5fff863c,
> + [EXC_DOUBLE] = 0x5fff865c,
> + },
> },
> };
>
> @@ -94,4 +109,24 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env,
> target_ulong addr)
>
> void do_interrupt(CPUState *env)
> {
> + switch (env->exception_index) {
> + case EXC_WINDOW_OVERFLOW4:
> + case EXC_WINDOW_UNDERFLOW4:
> + case EXC_WINDOW_OVERFLOW8:
> + case EXC_WINDOW_UNDERFLOW8:
> + case EXC_WINDOW_OVERFLOW12:
> + case EXC_WINDOW_UNDERFLOW12:
> + case EXC_KERNEL:
> + case EXC_USER:
> + case EXC_DOUBLE:
> + if (env->config->exception_vector[env->exception_index]) {
> + env->pc = env->config->exception_vector[env->exception_index];
> + env->exception_taken = 1;
> + } else {
> + qemu_log("%s(pc = %08x) bad exception_index: %d\n",
> + __func__, env->pc, env->exception_index);
> + }
> + break;
> +
> + }
> }
> diff --git a/target-xtensa/helpers.h b/target-xtensa/helpers.h
> index 976c8d8..6329c43 100644
> --- a/target-xtensa/helpers.h
> +++ b/target-xtensa/helpers.h
> @@ -1,6 +1,8 @@
> #include "def-helper.h"
>
> DEF_HELPER_1(exception, void, i32)
> +DEF_HELPER_2(exception_cause, void, i32, i32)
> +DEF_HELPER_3(exception_cause_vaddr, void, i32, i32, i32)
> DEF_HELPER_1(nsa, i32, i32)
> DEF_HELPER_1(nsau, i32, i32)
>
> diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c
> index c1cfd2e..794a834 100644
> --- a/target-xtensa/op_helper.c
> +++ b/target-xtensa/op_helper.c
> @@ -59,6 +59,35 @@ void HELPER(exception)(uint32_t excp)
> cpu_loop_exit(env);
> }
>
> +void HELPER(exception_cause)(uint32_t pc, uint32_t cause)
> +{
> + uint32_t vector;
> +
> + env->pc = pc;
> + if (env->sregs[PS] & PS_EXCM) {
> + if (env->config->ndepc) {
> + env->sregs[DEPC] = pc;
> + } else {
> + env->sregs[EPC1] = pc;
> + }
> + vector = EXC_DOUBLE;
> + } else {
> + env->sregs[EPC1] = pc;
> + vector = (env->sregs[PS] & PS_UM) ? EXC_USER : EXC_KERNEL;
> + }
> +
> + env->sregs[EXCCAUSE] = cause;
> + env->sregs[PS] |= PS_EXCM;
> +
> + HELPER(exception)(vector);
> +}
> +
> +void HELPER(exception_cause_vaddr)(uint32_t pc, uint32_t cause, uint32_t
> vaddr)
> +{
> + env->sregs[EXCVADDR] = vaddr;
> + HELPER(exception_cause)(pc, cause);
> +}
> +
> uint32_t HELPER(nsa)(uint32_t v)
> {
> if (v & 0x80000000) {
> diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
> index b6d0210..4c9db9e 100644
> --- a/target-xtensa/translate.c
> +++ b/target-xtensa/translate.c
> @@ -67,7 +67,12 @@ static TCGv_i32 cpu_UR[256];
> static const char * const sregnames[256] = {
> [SAR] = "SAR",
> [SCOMPARE1] = "SCOMPARE1",
> + [EPC1] = "EPC1",
> + [DEPC] = "DEPC",
> + [EXCSAVE1] = "EXCSAVE1",
> [PS] = "PS",
> + [EXCCAUSE] = "EXCCAUSE",
> + [EXCVADDR] = "EXCVADDR",
> };
>
> static const char * const uregnames[256] = {
> @@ -165,6 +170,22 @@ static void gen_exception(int excp)
> tcg_temp_free(tmp);
> }
>
> +static void gen_exception_cause(DisasContext *dc, uint32_t cause)
> +{
> + TCGv_i32 _pc = tcg_const_i32(dc->pc);
> + TCGv_i32 _cause = tcg_const_i32(cause);
Please don't use identifiers starting with underscore.
> + gen_helper_exception_cause(_pc, _cause);
> + tcg_temp_free(_pc);
> + tcg_temp_free(_cause);
> +}
> +
> +static void gen_check_privilege(DisasContext *dc)
> +{
> + if (dc->cring) {
> + gen_exception_cause(dc, PRIVILEGED_CAUSE);
> + }
> +}
> +
> static void gen_jump_slot(DisasContext *dc, TCGv dest, int slot)
> {
> tcg_gen_mov_i32(cpu_pc, dest);
> @@ -392,7 +413,7 @@ static void disas_xtensa_insn(DisasContext *dc)
> case 0: /*SNM0*/
> switch (CALLX_M) {
> case 0: /*ILL*/
> - TBD();
> + gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE);
> break;
>
> case 1: /*reserved*/
> @@ -479,7 +500,52 @@ static void disas_xtensa_insn(DisasContext *dc)
> break;
>
> case 3: /*RFEIx*/
> - TBD();
> + switch (RRR_T) {
> + case 0: /*RFETx*/
> + HAS_OPTION(XTENSA_OPTION_EXCEPTION);
> + switch (RRR_S) {
> + case 0: /*RFEx*/
> + gen_check_privilege(dc);
> + tcg_gen_andi_i32(cpu_SR[PS], cpu_SR[PS],
> ~PS_EXCM);
> + gen_jump(dc, cpu_SR[EPC1]);
> + break;
> +
> + case 1: /*RFUEx*/
> + RESERVED();
> + break;
> +
> + case 2: /*RFDEx*/
> + gen_check_privilege(dc);
> + gen_jump(dc, cpu_SR[
> + dc->config->ndepc ? DEPC : EPC1]);
> + break;
> +
> + case 4: /*RFWOw*/
> + case 5: /*RFWUw*/
> + HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
> + TBD();
> + break;
> +
> + default: /*reserved*/
> + RESERVED();
> + break;
> + }
> + break;
> +
> + case 1: /*RFIx*/
> + HAS_OPTION(XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT);
> + TBD();
> + break;
> +
> + case 2: /*RFME*/
> + TBD();
> + break;
> +
> + default: /*reserved*/
> + RESERVED();
> + break;
> +
> + }
> break;
>
> case 4: /*BREAKx*/
> @@ -489,12 +555,28 @@ static void disas_xtensa_insn(DisasContext *dc)
>
> case 5: /*SYSCALLx*/
> HAS_OPTION(XTENSA_OPTION_EXCEPTION);
> - TBD();
> + switch (RRR_S) {
> + case 0: /*SYSCALLx*/
> + gen_exception_cause(dc, SYSCALL_CAUSE);
> + break;
> +
> + case 1: /*SIMCALL*/
> + TBD();
> + break;
> +
> + default:
> + RESERVED();
> + break;
> + }
> break;
>
> case 6: /*RSILx*/
> HAS_OPTION(XTENSA_OPTION_INTERRUPT);
> - TBD();
> + gen_check_privilege(dc);
> + tcg_gen_mov_i32(cpu_R[RRR_T], cpu_SR[PS]);
> + tcg_gen_ori_i32(cpu_SR[PS], cpu_SR[PS], RRR_S);
> + tcg_gen_andi_i32(cpu_SR[PS], cpu_SR[PS],
> + RRR_S | ~PS_INTLEVEL);
> break;
>
> case 7: /*WAITIx*/
> @@ -691,6 +773,9 @@ static void disas_xtensa_insn(DisasContext *dc)
> case 6: /*XSR*/
> {
> TCGv_i32 tmp = tcg_temp_new_i32();
> + if (RSR_SR >= 64) {
> + gen_check_privilege(dc);
> + }
> tcg_gen_mov_i32(tmp, cpu_R[RRR_T]);
> gen_rsr(dc, cpu_R[RRR_T], RSR_SR);
> gen_wsr(dc, RSR_SR, tmp);
> @@ -799,6 +884,9 @@ static void disas_xtensa_insn(DisasContext *dc)
> case 3: /*RST3*/
> switch (OP2) {
> case 0: /*RSR*/
> + if (RSR_SR >= 64) {
> + gen_check_privilege(dc);
> + }
> gen_rsr(dc, cpu_R[RRR_T], RSR_SR);
> if (!sregnames[RSR_SR]) {
> TBD();
> @@ -806,6 +894,9 @@ static void disas_xtensa_insn(DisasContext *dc)
> break;
>
> case 1: /*WSR*/
> + if (RSR_SR >= 64) {
> + gen_check_privilege(dc);
> + }
> gen_wsr(dc, RSR_SR, cpu_R[RRR_T]);
> if (!sregnames[RSR_SR]) {
> TBD();
> @@ -1421,7 +1512,7 @@ static void disas_xtensa_insn(DisasContext *dc)
> break;
>
> case 6: /*ILL.Nn*/
> - TBD();
> + gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE);
> break;
>
> default: /*reserved*/
> @@ -1493,6 +1584,12 @@ static void gen_intermediate_code_internal(
>
> gen_icount_start();
>
> + if (env->singlestep_enabled && env->exception_taken) {
> + env->exception_taken = 0;
> + tcg_gen_movi_i32(cpu_pc, dc.pc);
> + gen_exception(EXCP_DEBUG);
> + }
> +
> do {
> check_breakpoint(env, &dc);
>
> --
> 1.7.6
>
>
>
- [Qemu-devel] [PATCH v4 22/32] target-xtensa: implement unaligned exception option, (continued)
- [Qemu-devel] [PATCH v4 22/32] target-xtensa: implement unaligned exception option, Max Filippov, 2011/09/01
- [Qemu-devel] [PATCH v4 18/32] target-xtensa: implement RST2 group (32 bit mul/div/rem), Max Filippov, 2011/09/01
- [Qemu-devel] [PATCH v4 31/32] MAINTAINERS: add xtensa maintainer, Max Filippov, 2011/09/01
- [Qemu-devel] [PATCH v4 21/32] target-xtensa: implement extended L32R, Max Filippov, 2011/09/01
- [Qemu-devel] [PATCH v4 23/32] target-xtensa: implement SIMCALL, Max Filippov, 2011/09/01
- [Qemu-devel] [PATCH v4 19/32] target-xtensa: implement windowed registers, Max Filippov, 2011/09/01
- [Qemu-devel] [PATCH v4 27/32] target-xtensa: implement relocatable vectors, Max Filippov, 2011/09/01
- [Qemu-devel] [PATCH v4 17/32] target-xtensa: implement exceptions, Max Filippov, 2011/09/01
- Re: [Qemu-devel] [PATCH v4 17/32] target-xtensa: implement exceptions,
Blue Swirl <=
- [Qemu-devel] [PATCH v4 25/32] target-xtensa: implement accurate window check, Max Filippov, 2011/09/01
- [Qemu-devel] [PATCH v4 29/32] target-xtensa: implement memory protection options, Max Filippov, 2011/09/01
- [Qemu-devel] [PATCH v4 32/32] target-xtensa: add regression testsuite, Max Filippov, 2011/09/01
- [Qemu-devel] [PATCH v4 24/32] target-xtensa: implement interrupt option, Max Filippov, 2011/09/01
- [Qemu-devel] [PATCH v4 30/32] target-xtensa: add dc232b core and board, Max Filippov, 2011/09/01
- [Qemu-devel] [PATCH v4 28/32] target-xtensa: add gdb support, Max Filippov, 2011/09/01
- [Qemu-devel] [PATCH v4 20/32] target-xtensa: implement loop option, Max Filippov, 2011/09/01
- Re: [Qemu-devel] [PATCH v4 00/32] target-xtensa: new target architecture, Blue Swirl, 2011/09/04