From: Max Filippov <jcmvbkbc@gmail.com>
To: qemu-devel@nongnu.org
Cc: jcmvbkbc@gmail.com
Subject: [Qemu-devel] [PATCH v4 17/32] target-xtensa: implement exceptions
Date: Fri, 2 Sep 2011 00:45:45 +0400 [thread overview]
Message-ID: <1314909960-31738-18-git-send-email-jcmvbkbc@gmail.com> (raw)
In-Reply-To: <1314909960-31738-1-git-send-email-jcmvbkbc@gmail.com>
- mark privileged opcodes with ring check;
- make debug exception on exception handler entry.
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
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);
+ 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
next prev parent reply other threads:[~2011-09-01 20:46 UTC|newest]
Thread overview: 47+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-09-01 20:45 [Qemu-devel] [PATCH v4 00/32] target-xtensa: new target architecture Max Filippov
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 01/32] target-xtensa: add target stubs Max Filippov
2011-09-04 18:14 ` Blue Swirl
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 02/32] target-xtensa: add target to the configure script Max Filippov
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 03/32] target-xtensa: implement disas_xtensa_insn Max Filippov
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 04/32] target-xtensa: implement narrow instructions Max Filippov
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 05/32] target-xtensa: implement RT0 group Max Filippov
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 06/32] target-xtensa: add sample board Max Filippov
2011-09-04 18:17 ` Blue Swirl
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 07/32] target-xtensa: implement conditional jumps Max Filippov
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 08/32] target-xtensa: implement JX/RET0/CALLX Max Filippov
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 09/32] target-xtensa: add special and user registers Max Filippov
2011-09-04 18:18 ` Blue Swirl
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 10/32] target-xtensa: implement RST3 group Max Filippov
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 11/32] target-xtensa: implement shifts (ST1 and RST1 groups) Max Filippov
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 12/32] target-xtensa: implement LSAI group Max Filippov
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 13/32] target-xtensa: mark reserved and TBD opcodes Max Filippov
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 14/32] target-xtensa: implement SYNC group Max Filippov
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 15/32] target-xtensa: implement CACHE group Max Filippov
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 16/32] target-xtensa: add PS register and access control Max Filippov
2011-09-01 20:45 ` Max Filippov [this message]
2011-09-04 18:22 ` [Qemu-devel] [PATCH v4 17/32] target-xtensa: implement exceptions Blue Swirl
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 18/32] target-xtensa: implement RST2 group (32 bit mul/div/rem) Max Filippov
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 19/32] target-xtensa: implement windowed registers Max Filippov
2011-09-04 18:27 ` Blue Swirl
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 20/32] target-xtensa: implement loop option Max Filippov
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 21/32] target-xtensa: implement extended L32R Max Filippov
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 22/32] target-xtensa: implement unaligned exception option Max Filippov
2011-09-04 18:28 ` Blue Swirl
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 23/32] target-xtensa: implement SIMCALL Max Filippov
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 24/32] target-xtensa: implement interrupt option Max Filippov
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 25/32] target-xtensa: implement accurate window check Max Filippov
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 26/32] target-xtensa: implement CPENABLE and PRID SRs Max Filippov
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 27/32] target-xtensa: implement relocatable vectors Max Filippov
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 28/32] target-xtensa: add gdb support Max Filippov
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 29/32] target-xtensa: implement memory protection options Max Filippov
2011-09-04 18:32 ` Blue Swirl
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 30/32] target-xtensa: add dc232b core and board Max Filippov
2011-09-04 18:33 ` Blue Swirl
2011-09-01 20:45 ` [Qemu-devel] [PATCH v4 31/32] MAINTAINERS: add xtensa maintainer Max Filippov
2011-09-01 20:46 ` [Qemu-devel] [PATCH v4 32/32] target-xtensa: add regression testsuite Max Filippov
2011-09-04 18:35 ` [Qemu-devel] [PATCH v4 00/32] target-xtensa: new target architecture Blue Swirl
2011-09-05 10:55 ` Edgar E. Iglesias
2011-09-05 12:35 ` Max Filippov
2011-09-14 21:18 ` Edgar E. Iglesias
2011-09-14 22:24 ` Max Filippov
2011-09-14 22:28 ` Edgar E. Iglesias
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1314909960-31738-18-git-send-email-jcmvbkbc@gmail.com \
--to=jcmvbkbc@gmail.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).