qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [RFC 0/9] target-xtensa: implement debug option
@ 2012-01-29  2:19 Max Filippov
  2012-01-29  2:19 ` [Qemu-devel] [RFC 1/9] target-xtensa: add DEBUGCAUSE SR and configuration Max Filippov
                   ` (8 more replies)
  0 siblings, 9 replies; 11+ messages in thread
From: Max Filippov @ 2012-01-29  2:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: jcmvbkbc

This patch series implements Xtensa debug option: debug interrupt, breakpoint
opcodes, instruction breakpoint SRs, instruction counting SR, data breakpoint
SRs.

This option enables native debugging, e.g. now guest linux GDB is functional.

Three exec.c patches fixe watchpoints bits that nobody seems to use currently.

There are still unresolved issue with data breakpoints on unmapped memory:
Xtensa ISA says that data breakpoint exception has higher priority than
TLB exception and thus accessing unmapped address that hits data breakpoint
will raise debug exception. Watchpoint mapping is performed in the tlb_set_page,
but it is not called in case of guest TLB miss. Any idea on how to resolve it
is welcome.

Max Filippov (9):
  target-xtensa: add DEBUGCAUSE SR and configuration
  target-xtensa: implement instruction breakpoints
  target-xtensa: add ICOUNT SR and debug exception
  exec: add missing breaks to the watch_mem_write
  exec: fix check_watchpoint exiting cpu_loop
  exec: let cpu_watchpoint_insert accept larger watchpoints
  target-xtensa: add DBREAK data breakpoints
  target-xtensa: add DEBUG_SECTION to overlay tool
  target-xtensa: add breakpoint tests

 exec.c                        |   18 +++-
 target-xtensa/core-dc232b.c   |    1 +
 target-xtensa/core-fsf.c      |    1 +
 target-xtensa/cpu.h           |   42 ++++++++
 target-xtensa/helper.c        |   43 ++++++++
 target-xtensa/helpers.h       |    7 ++
 target-xtensa/op_helper.c     |  100 ++++++++++++++++++
 target-xtensa/overlay_tool.h  |    5 +
 target-xtensa/translate.c     |  153 +++++++++++++++++++++++++++-
 tests/tcg/xtensa/Makefile     |    1 +
 tests/tcg/xtensa/test_break.S |  223 +++++++++++++++++++++++++++++++++++++++++
 11 files changed, 585 insertions(+), 9 deletions(-)
 create mode 100644 tests/tcg/xtensa/test_break.S

-- 
1.7.7.6

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [Qemu-devel] [RFC 1/9] target-xtensa: add DEBUGCAUSE SR and configuration
  2012-01-29  2:19 [Qemu-devel] [RFC 0/9] target-xtensa: implement debug option Max Filippov
@ 2012-01-29  2:19 ` Max Filippov
  2012-01-29  2:19 ` [Qemu-devel] [RFC 2/9] target-xtensa: implement instruction breakpoints Max Filippov
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Max Filippov @ 2012-01-29  2:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: jcmvbkbc

DEBUGCAUSE SR holds information about the most recent debug exception.
See ISA, 4.7.7 for more details.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 target-xtensa/cpu.h       |   15 +++++++++++++++
 target-xtensa/translate.c |    6 ++++++
 2 files changed, 21 insertions(+), 0 deletions(-)

diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index 0db83a6..25245d8 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -137,6 +137,7 @@ enum {
     PS = 230,
     VECBASE = 231,
     EXCCAUSE = 232,
+    DEBUGCAUSE = 233,
     CCOUNT = 234,
     PRID = 235,
     EXCVADDR = 238,
@@ -161,6 +162,15 @@ enum {
 
 #define PS_WOE 0x40000
 
+#define DEBUGCAUSE_IC 0x1
+#define DEBUGCAUSE_IB 0x2
+#define DEBUGCAUSE_DB 0x4
+#define DEBUGCAUSE_BI 0x8
+#define DEBUGCAUSE_BN 0x10
+#define DEBUGCAUSE_DI 0x20
+#define DEBUGCAUSE_DBNUM 0xf00
+#define DEBUGCAUSE_DBNUM_SHIFT 8
+
 #define MAX_NAREG 64
 #define MAX_NINTERRUPT 32
 #define MAX_NLEVEL 6
@@ -279,6 +289,11 @@ typedef struct XtensaConfig {
     uint32_t timerint[MAX_NCCOMPARE];
     unsigned nextint;
     unsigned extint[MAX_NINTERRUPT];
+
+    unsigned debug_level;
+    unsigned nibreak;
+    unsigned ndbreak;
+
     uint32_t clock_freq_khz;
 
     xtensa_tlb itlb;
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index c81450d..0786dd1 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -119,6 +119,7 @@ static const char * const sregnames[256] = {
     [PS] = "PS",
     [VECBASE] = "VECBASE",
     [EXCCAUSE] = "EXCCAUSE",
+    [DEBUGCAUSE] = "DEBUGCAUSE",
     [CCOUNT] = "CCOUNT",
     [PRID] = "PRID",
     [EXCVADDR] = "EXCVADDR",
@@ -535,6 +536,10 @@ static void gen_wsr_ps(DisasContext *dc, uint32_t sr, TCGv_i32 v)
     gen_jumpi_check_loop_end(dc, -1);
 }
 
+static void gen_wsr_debugcause(DisasContext *dc, uint32_t sr, TCGv_i32 v)
+{
+}
+
 static void gen_wsr_prid(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 {
 }
@@ -571,6 +576,7 @@ static void gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s)
         [INTCLEAR] = gen_wsr_intclear,
         [INTENABLE] = gen_wsr_intenable,
         [PS] = gen_wsr_ps,
+        [DEBUGCAUSE] = gen_wsr_debugcause,
         [PRID] = gen_wsr_prid,
         [CCOMPARE] = gen_wsr_ccompare,
         [CCOMPARE + 1] = gen_wsr_ccompare,
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [Qemu-devel] [RFC 2/9] target-xtensa: implement instruction breakpoints
  2012-01-29  2:19 [Qemu-devel] [RFC 0/9] target-xtensa: implement debug option Max Filippov
  2012-01-29  2:19 ` [Qemu-devel] [RFC 1/9] target-xtensa: add DEBUGCAUSE SR and configuration Max Filippov
@ 2012-01-29  2:19 ` Max Filippov
  2012-01-29  2:19 ` [Qemu-devel] [RFC 3/9] target-xtensa: add ICOUNT SR and debug exception Max Filippov
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Max Filippov @ 2012-01-29  2:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: jcmvbkbc

Add IBREAKA/IBREAKENABLE SRs and implement debug exception, BREAK and
BREAK.N instructions and IBREAK breakpoints.

IBREAK breakpoint address is considered constant for TB lifetime.
On IBREAKA/IBREAKENABLE change corresponding TBs are invalidated.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 target-xtensa/cpu.h       |    9 ++++++
 target-xtensa/helper.c    |    2 +
 target-xtensa/helpers.h   |    5 +++
 target-xtensa/op_helper.c |   38 +++++++++++++++++++++++++
 target-xtensa/translate.c |   68 +++++++++++++++++++++++++++++++++++++++++++--
 5 files changed, 119 insertions(+), 3 deletions(-)

diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index 25245d8..2875197 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -126,6 +126,8 @@ enum {
     RASID = 90,
     ITLBCFG = 91,
     DTLBCFG = 92,
+    IBREAKENABLE = 96,
+    IBREAKA = 128,
     EPC1 = 177,
     DEPC = 192,
     EPS2 = 194,
@@ -196,6 +198,7 @@ enum {
     EXC_KERNEL,
     EXC_USER,
     EXC_DOUBLE,
+    EXC_DEBUG,
     EXC_MAX
 };
 
@@ -424,6 +427,7 @@ static inline int cpu_mmu_index(CPUState *env)
 #define XTENSA_TBFLAG_RING_MASK 0x3
 #define XTENSA_TBFLAG_EXCM 0x4
 #define XTENSA_TBFLAG_LITBASE 0x8
+#define XTENSA_TBFLAG_DEBUG 0x10
 
 static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
         target_ulong *cs_base, int *flags)
@@ -439,6 +443,11 @@ static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
             (env->sregs[LITBASE] & 1)) {
         *flags |= XTENSA_TBFLAG_LITBASE;
     }
+    if (xtensa_option_enabled(env->config, XTENSA_OPTION_DEBUG)) {
+        if (xtensa_get_cintlevel(env) < env->config->debug_level) {
+            *flags |= XTENSA_TBFLAG_DEBUG;
+        }
+    }
 }
 
 #include "cpu-all.h"
diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
index 2a0cb1a..b7e67b7 100644
--- a/target-xtensa/helper.c
+++ b/target-xtensa/helper.c
@@ -44,6 +44,7 @@ void cpu_reset(CPUXtensaState *env)
     env->sregs[PS] = xtensa_option_enabled(env->config,
             XTENSA_OPTION_INTERRUPT) ? 0x1f : 0x10;
     env->sregs[VECBASE] = env->config->vecbase;
+    env->sregs[IBREAKENABLE] = 0;
 
     env->pending_irq_level = 0;
     reset_mmu(env);
@@ -193,6 +194,7 @@ void do_interrupt(CPUState *env)
     case EXC_KERNEL:
     case EXC_USER:
     case EXC_DOUBLE:
+    case EXC_DEBUG:
         qemu_log_mask(CPU_LOG_INT, "%s(%d) "
                 "pc = %08x, a0 = %08x, ps = %08x, ccount = %08x\n",
                 __func__, env->exception_index,
diff --git a/target-xtensa/helpers.h b/target-xtensa/helpers.h
index 09ab332..afe39d4 100644
--- a/target-xtensa/helpers.h
+++ b/target-xtensa/helpers.h
@@ -3,6 +3,8 @@
 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_2(debug_exception, void, i32, i32)
+
 DEF_HELPER_1(nsa, i32, i32)
 DEF_HELPER_1(nsau, i32, i32)
 DEF_HELPER_1(wsr_windowbase, void, i32)
@@ -29,4 +31,7 @@ DEF_HELPER_2(itlb, void, i32, i32)
 DEF_HELPER_2(ptlb, i32, i32, i32)
 DEF_HELPER_3(wtlb, void, i32, i32, i32)
 
+DEF_HELPER_1(wsr_ibreakenable, void, i32)
+DEF_HELPER_2(wsr_ibreaka, void, i32, i32)
+
 #include "def-helper.h"
diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c
index 0605611..1feaaee 100644
--- a/target-xtensa/op_helper.c
+++ b/target-xtensa/op_helper.c
@@ -134,6 +134,19 @@ void HELPER(exception_cause_vaddr)(uint32_t pc, uint32_t cause, uint32_t vaddr)
     HELPER(exception_cause)(pc, cause);
 }
 
+void HELPER(debug_exception)(uint32_t pc, uint32_t cause)
+{
+    unsigned level = env->config->debug_level;
+
+    env->pc = pc;
+    env->sregs[DEBUGCAUSE] = cause;
+    env->sregs[EPC1 + level - 1] = pc;
+    env->sregs[EPS2 + level - 2] = env->sregs[PS];
+    env->sregs[PS] = (env->sregs[PS] & ~PS_INTLEVEL) | PS_EXCM |
+        (level << PS_INTLEVEL_SHIFT);
+    HELPER(exception)(EXC_DEBUG);
+}
+
 uint32_t HELPER(nsa)(uint32_t v)
 {
     if (v & 0x80000000) {
@@ -662,3 +675,28 @@ void HELPER(wtlb)(uint32_t p, uint32_t v, uint32_t dtlb)
     split_tlb_entry_spec(v, dtlb, &vpn, &wi, &ei);
     xtensa_tlb_set_entry(env, dtlb, wi, ei, vpn, p);
 }
+
+
+void HELPER(wsr_ibreakenable)(uint32_t v)
+{
+    uint32_t change = v ^ env->sregs[IBREAKENABLE];
+    unsigned i;
+
+    for (i = 0; i < env->config->nibreak; ++i) {
+        if (change & (1 << i)) {
+            tb_invalidate_phys_page_range(
+                    env->sregs[IBREAKA + i], env->sregs[IBREAKA + i] + 1, 0);
+        }
+    }
+    env->sregs[IBREAKENABLE] = v & ((1 << env->config->nibreak) - 1);
+}
+
+void HELPER(wsr_ibreaka)(uint32_t i, uint32_t v)
+{
+    if (env->sregs[IBREAKENABLE] & (1 << i) && env->sregs[IBREAKA + i] != v) {
+        tb_invalidate_phys_page_range(
+                env->sregs[IBREAKA + i], env->sregs[IBREAKA + i] + 1, 0);
+        tb_invalidate_phys_page_range(v, v + 1, 0);
+    }
+    env->sregs[IBREAKA + i] = v;
+}
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index 0786dd1..71fbf34 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -61,6 +61,8 @@ typedef struct DisasContext {
 
     uint32_t ccount_delta;
     unsigned used_window;
+
+    bool debug;
 } DisasContext;
 
 static TCGv_ptr cpu_env;
@@ -91,6 +93,9 @@ static const char * const sregnames[256] = {
     [RASID] = "RASID",
     [ITLBCFG] = "ITLBCFG",
     [DTLBCFG] = "DTLBCFG",
+    [IBREAKENABLE] = "IBREAKENABLE",
+    [IBREAKA] = "IBREAKA0",
+    [IBREAKA + 1] = "IBREAKA1",
     [EPC1] = "EPC1",
     [EPC1 + 1] = "EPC2",
     [EPC1 + 2] = "EPC3",
@@ -284,6 +289,19 @@ static void gen_exception_cause_vaddr(DisasContext *dc, uint32_t cause,
     tcg_temp_free(tcause);
 }
 
+static void gen_debug_exception(DisasContext *dc, uint32_t cause)
+{
+    TCGv_i32 tpc = tcg_const_i32(dc->pc);
+    TCGv_i32 tcause = tcg_const_i32(cause);
+    gen_advance_ccount(dc);
+    gen_helper_debug_exception(tpc, tcause);
+    tcg_temp_free(tpc);
+    tcg_temp_free(tcause);
+    if (cause & (DEBUGCAUSE_IB | DEBUGCAUSE_BI | DEBUGCAUSE_BN)) {
+        dc->is_jmp = DISAS_UPDATE;
+    }
+}
+
 static void gen_check_privilege(DisasContext *dc)
 {
     if (dc->cring) {
@@ -493,6 +511,24 @@ static void gen_wsr_tlbcfg(DisasContext *dc, uint32_t sr, TCGv_i32 v)
     tcg_gen_andi_i32(cpu_SR[sr], v, 0x01130000);
 }
 
+static void gen_wsr_ibreakenable(DisasContext *dc, uint32_t sr, TCGv_i32 v)
+{
+    gen_helper_wsr_ibreakenable(v);
+    gen_jumpi_check_loop_end(dc, 0);
+}
+
+static void gen_wsr_ibreaka(DisasContext *dc, uint32_t sr, TCGv_i32 v)
+{
+    unsigned id = sr - IBREAKA;
+
+    if (id < dc->config->nibreak) {
+        TCGv_i32 tmp = tcg_const_i32(id);
+        gen_helper_wsr_ibreaka(tmp, v);
+        tcg_temp_free(tmp);
+        gen_jumpi_check_loop_end(dc, 0);
+    }
+}
+
 static void gen_wsr_intset(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 {
     tcg_gen_andi_i32(cpu_SR[sr], v,
@@ -572,6 +608,9 @@ static void gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s)
         [RASID] = gen_wsr_rasid,
         [ITLBCFG] = gen_wsr_tlbcfg,
         [DTLBCFG] = gen_wsr_tlbcfg,
+        [IBREAKENABLE] = gen_wsr_ibreakenable,
+        [IBREAKA] = gen_wsr_ibreaka,
+        [IBREAKA + 1] = gen_wsr_ibreaka,
         [INTSET] = gen_wsr_intset,
         [INTCLEAR] = gen_wsr_intclear,
         [INTENABLE] = gen_wsr_intenable,
@@ -974,8 +1013,10 @@ static void disas_xtensa_insn(DisasContext *dc)
                     break;
 
                 case 4: /*BREAKx*/
-                    HAS_OPTION(XTENSA_OPTION_EXCEPTION);
-                    TBD();
+                    HAS_OPTION(XTENSA_OPTION_DEBUG);
+                    if (dc->debug) {
+                        gen_debug_exception(dc, DEBUGCAUSE_BI);
+                    }
                     break;
 
                 case 5: /*SYSCALLx*/
@@ -2355,7 +2396,10 @@ static void disas_xtensa_insn(DisasContext *dc)
                 break;
 
             case 2: /*BREAK.Nn*/
-                TBD();
+                HAS_OPTION(XTENSA_OPTION_DEBUG);
+                if (dc->debug) {
+                    gen_debug_exception(dc, DEBUGCAUSE_BN);
+                }
                 break;
 
             case 3: /*NOP.Nn*/
@@ -2408,6 +2452,19 @@ static void check_breakpoint(CPUState *env, DisasContext *dc)
     }
 }
 
+static void gen_ibreak_check(CPUState *env, DisasContext *dc)
+{
+    unsigned i;
+
+    for (i = 0; i < dc->config->nibreak; ++i) {
+        if ((env->sregs[IBREAKENABLE] & (1 << i)) &&
+                env->sregs[IBREAKA + i] == dc->pc) {
+            gen_debug_exception(dc, DEBUGCAUSE_IB);
+            break;
+        }
+    }
+}
+
 static void gen_intermediate_code_internal(
         CPUState *env, TranslationBlock *tb, int search_pc)
 {
@@ -2434,6 +2491,7 @@ static void gen_intermediate_code_internal(
     dc.lend = env->sregs[LEND];
     dc.is_jmp = DISAS_NEXT;
     dc.ccount_delta = 0;
+    dc.debug = tb->flags & XTENSA_TBFLAG_DEBUG;
 
     init_litbase(&dc);
     init_sar_tracker(&dc);
@@ -2473,6 +2531,10 @@ static void gen_intermediate_code_internal(
             gen_io_start();
         }
 
+        if (dc.debug) {
+            gen_ibreak_check(env, &dc);
+        }
+
         disas_xtensa_insn(&dc);
         ++insn_count;
         if (env->singlestep_enabled) {
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [Qemu-devel] [RFC 3/9] target-xtensa: add ICOUNT SR and debug exception
  2012-01-29  2:19 [Qemu-devel] [RFC 0/9] target-xtensa: implement debug option Max Filippov
  2012-01-29  2:19 ` [Qemu-devel] [RFC 1/9] target-xtensa: add DEBUGCAUSE SR and configuration Max Filippov
  2012-01-29  2:19 ` [Qemu-devel] [RFC 2/9] target-xtensa: implement instruction breakpoints Max Filippov
@ 2012-01-29  2:19 ` Max Filippov
  2012-01-29  2:19 ` [Qemu-devel] [RFC 4/9] exec: add missing breaks to the watch_mem_write Max Filippov
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Max Filippov @ 2012-01-29  2:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: jcmvbkbc

ICOUNT SR gets incremented on every instruction completion provided that
CINTLEVEL at the beginning of the instruction execution is lower than
ICOUNTLEVEL.

When ICOUNT would increment to 0 a debug exception is raised if
CINTLEVEL is lower than DEBUGLEVEL.

See ISA, 4.7.7.5 for more details.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 target-xtensa/cpu.h       |    6 +++++
 target-xtensa/translate.c |   49 ++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 54 insertions(+), 1 deletions(-)

diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index 2875197..fbe5d15 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -142,6 +142,8 @@ enum {
     DEBUGCAUSE = 233,
     CCOUNT = 234,
     PRID = 235,
+    ICOUNT = 236,
+    ICOUNTLEVEL = 237,
     EXCVADDR = 238,
     CCOMPARE = 240,
 };
@@ -428,6 +430,7 @@ static inline int cpu_mmu_index(CPUState *env)
 #define XTENSA_TBFLAG_EXCM 0x4
 #define XTENSA_TBFLAG_LITBASE 0x8
 #define XTENSA_TBFLAG_DEBUG 0x10
+#define XTENSA_TBFLAG_ICOUNT 0x20
 
 static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
         target_ulong *cs_base, int *flags)
@@ -447,6 +450,9 @@ static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
         if (xtensa_get_cintlevel(env) < env->config->debug_level) {
             *flags |= XTENSA_TBFLAG_DEBUG;
         }
+        if (xtensa_get_cintlevel(env) < env->sregs[ICOUNTLEVEL]) {
+            *flags |= XTENSA_TBFLAG_ICOUNT;
+        }
     }
 }
 
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index 71fbf34..85f41a7 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -63,6 +63,8 @@ typedef struct DisasContext {
     unsigned used_window;
 
     bool debug;
+    bool icount;
+    TCGv_i32 next_icount;
 } DisasContext;
 
 static TCGv_ptr cpu_env;
@@ -127,6 +129,8 @@ static const char * const sregnames[256] = {
     [DEBUGCAUSE] = "DEBUGCAUSE",
     [CCOUNT] = "CCOUNT",
     [PRID] = "PRID",
+    [ICOUNT] = "ICOUNT",
+    [ICOUNTLEVEL] = "ICOUNTLEVEL",
     [EXCVADDR] = "EXCVADDR",
     [CCOMPARE] = "CCOMPARE0",
     [CCOMPARE + 1] = "CCOMPARE1",
@@ -313,10 +317,13 @@ static void gen_check_privilege(DisasContext *dc)
 static void gen_jump_slot(DisasContext *dc, TCGv dest, int slot)
 {
     tcg_gen_mov_i32(cpu_pc, dest);
+    gen_advance_ccount(dc);
+    if (dc->icount) {
+        tcg_gen_mov_i32(cpu_SR[ICOUNT], dc->next_icount);
+    }
     if (dc->singlestep_enabled) {
         gen_exception(dc, EXCP_DEBUG);
     } else {
-        gen_advance_ccount(dc);
         if (slot >= 0) {
             tcg_gen_goto_tb(slot);
             tcg_gen_exit_tb((tcg_target_long)dc->tb + slot);
@@ -580,6 +587,22 @@ static void gen_wsr_prid(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 {
 }
 
+static void gen_wsr_icount(DisasContext *dc, uint32_t sr, TCGv_i32 v)
+{
+    if (dc->icount) {
+        tcg_gen_mov_i32(dc->next_icount, v);
+    } else {
+        tcg_gen_mov_i32(cpu_SR[sr], v);
+    }
+}
+
+static void gen_wsr_icountlevel(DisasContext *dc, uint32_t sr, TCGv_i32 v)
+{
+    tcg_gen_andi_i32(cpu_SR[sr], v, 0xf);
+    /* This can change tb->flags, so exit tb */
+    gen_jumpi_check_loop_end(dc, -1);
+}
+
 static void gen_wsr_ccompare(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 {
     uint32_t id = sr - CCOMPARE;
@@ -617,6 +640,8 @@ static void gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s)
         [PS] = gen_wsr_ps,
         [DEBUGCAUSE] = gen_wsr_debugcause,
         [PRID] = gen_wsr_prid,
+        [ICOUNT] = gen_wsr_icount,
+        [ICOUNTLEVEL] = gen_wsr_icountlevel,
         [CCOMPARE] = gen_wsr_ccompare,
         [CCOMPARE + 1] = gen_wsr_ccompare,
         [CCOMPARE + 2] = gen_wsr_ccompare,
@@ -2492,10 +2517,14 @@ static void gen_intermediate_code_internal(
     dc.is_jmp = DISAS_NEXT;
     dc.ccount_delta = 0;
     dc.debug = tb->flags & XTENSA_TBFLAG_DEBUG;
+    dc.icount = tb->flags & XTENSA_TBFLAG_ICOUNT;
 
     init_litbase(&dc);
     init_sar_tracker(&dc);
     reset_used_window(&dc);
+    if (dc.icount) {
+        dc.next_icount = tcg_temp_local_new_i32();
+    }
 
     gen_icount_start();
 
@@ -2531,12 +2560,27 @@ static void gen_intermediate_code_internal(
             gen_io_start();
         }
 
+        if (dc.icount) {
+            int label = gen_new_label();
+
+            tcg_gen_addi_i32(dc.next_icount, cpu_SR[ICOUNT], 1);
+            tcg_gen_brcondi_i32(TCG_COND_NE, dc.next_icount, 0, label);
+            tcg_gen_mov_i32(dc.next_icount, cpu_SR[ICOUNT]);
+            if (dc.debug) {
+                gen_debug_exception(&dc, DEBUGCAUSE_IC);
+            }
+            gen_set_label(label);
+        }
+
         if (dc.debug) {
             gen_ibreak_check(env, &dc);
         }
 
         disas_xtensa_insn(&dc);
         ++insn_count;
+        if (dc.icount) {
+            tcg_gen_mov_i32(cpu_SR[ICOUNT], dc.next_icount);
+        }
         if (env->singlestep_enabled) {
             tcg_gen_movi_i32(cpu_pc, dc.pc);
             gen_exception(&dc, EXCP_DEBUG);
@@ -2549,6 +2593,9 @@ static void gen_intermediate_code_internal(
 
     reset_litbase(&dc);
     reset_sar_tracker(&dc);
+    if (dc.icount) {
+        tcg_temp_free(dc.next_icount);
+    }
 
     if (tb->cflags & CF_LAST_IO) {
         gen_io_end();
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [Qemu-devel] [RFC 4/9] exec: add missing breaks to the watch_mem_write
  2012-01-29  2:19 [Qemu-devel] [RFC 0/9] target-xtensa: implement debug option Max Filippov
                   ` (2 preceding siblings ...)
  2012-01-29  2:19 ` [Qemu-devel] [RFC 3/9] target-xtensa: add ICOUNT SR and debug exception Max Filippov
@ 2012-01-29  2:19 ` Max Filippov
  2012-01-29  9:49   ` Andreas Färber
  2012-01-29  2:19 ` [Qemu-devel] [RFC 5/9] exec: fix check_watchpoint exiting cpu_loop Max Filippov
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 11+ messages in thread
From: Max Filippov @ 2012-01-29  2:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: jcmvbkbc

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 exec.c |   12 +++++++++---
 1 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/exec.c b/exec.c
index 5b9eb9a..0e93e0e 100644
--- a/exec.c
+++ b/exec.c
@@ -3279,9 +3279,15 @@ static void watch_mem_write(void *opaque, target_phys_addr_t addr,
 {
     check_watchpoint(addr & ~TARGET_PAGE_MASK, ~(size - 1), BP_MEM_WRITE);
     switch (size) {
-    case 1: stb_phys(addr, val);
-    case 2: stw_phys(addr, val);
-    case 4: stl_phys(addr, val);
+    case 1:
+        stb_phys(addr, val);
+        break;
+    case 2:
+        stw_phys(addr, val);
+        break;
+    case 4:
+        stl_phys(addr, val);
+        break;
     default: abort();
     }
 }
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [Qemu-devel] [RFC 5/9] exec: fix check_watchpoint exiting cpu_loop
  2012-01-29  2:19 [Qemu-devel] [RFC 0/9] target-xtensa: implement debug option Max Filippov
                   ` (3 preceding siblings ...)
  2012-01-29  2:19 ` [Qemu-devel] [RFC 4/9] exec: add missing breaks to the watch_mem_write Max Filippov
@ 2012-01-29  2:19 ` Max Filippov
  2012-01-29  2:19 ` [Qemu-devel] [RFC 6/9] exec: let cpu_watchpoint_insert accept larger watchpoints Max Filippov
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Max Filippov @ 2012-01-29  2:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: jcmvbkbc

In case of BP_STOP_BEFORE_ACCESS watchpoint check_watchpoint intends to
signal EXCP_DEBUG exception on exit from cpu loop, but later overwrites
exception code by the cpu_resume_from_signal call.

Use cpu_loop_exit with BP_STOP_BEFORE_ACCESS watchpoints.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 exec.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/exec.c b/exec.c
index 0e93e0e..bc6c185 100644
--- a/exec.c
+++ b/exec.c
@@ -3247,11 +3247,12 @@ static void check_watchpoint(int offset, int len_mask, int flags)
                 tb_phys_invalidate(tb, -1);
                 if (wp->flags & BP_STOP_BEFORE_ACCESS) {
                     env->exception_index = EXCP_DEBUG;
+                    cpu_loop_exit(env);
                 } else {
                     cpu_get_tb_cpu_state(env, &pc, &cs_base, &cpu_flags);
                     tb_gen_code(env, pc, cs_base, cpu_flags, 1);
+                    cpu_resume_from_signal(env, NULL);
                 }
-                cpu_resume_from_signal(env, NULL);
             }
         } else {
             wp->flags &= ~BP_WATCHPOINT_HIT;
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [Qemu-devel] [RFC 6/9] exec: let cpu_watchpoint_insert accept larger watchpoints
  2012-01-29  2:19 [Qemu-devel] [RFC 0/9] target-xtensa: implement debug option Max Filippov
                   ` (4 preceding siblings ...)
  2012-01-29  2:19 ` [Qemu-devel] [RFC 5/9] exec: fix check_watchpoint exiting cpu_loop Max Filippov
@ 2012-01-29  2:19 ` Max Filippov
  2012-01-29  2:19 ` [Qemu-devel] [RFC 7/9] target-xtensa: add DBREAK data breakpoints Max Filippov
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Max Filippov @ 2012-01-29  2:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: jcmvbkbc

Make cpu_watchpoint_insert accept watchpoints of any power-of-two size
up to the target page size.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 exec.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/exec.c b/exec.c
index bc6c185..39a5497 100644
--- a/exec.c
+++ b/exec.c
@@ -1443,7 +1443,8 @@ int cpu_watchpoint_insert(CPUState *env, target_ulong addr, target_ulong len,
     CPUWatchpoint *wp;
 
     /* sanity checks: allow power-of-2 lengths, deny unaligned watchpoints */
-    if ((len != 1 && len != 2 && len != 4 && len != 8) || (addr & ~len_mask)) {
+    if ((len & (len - 1)) || (addr & ~len_mask) ||
+            len == 0 || len > TARGET_PAGE_SIZE) {
         fprintf(stderr, "qemu: tried to set invalid watchpoint at "
                 TARGET_FMT_lx ", len=" TARGET_FMT_lu "\n", addr, len);
         return -EINVAL;
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [Qemu-devel] [RFC 7/9] target-xtensa: add DBREAK data breakpoints
  2012-01-29  2:19 [Qemu-devel] [RFC 0/9] target-xtensa: implement debug option Max Filippov
                   ` (5 preceding siblings ...)
  2012-01-29  2:19 ` [Qemu-devel] [RFC 6/9] exec: let cpu_watchpoint_insert accept larger watchpoints Max Filippov
@ 2012-01-29  2:19 ` Max Filippov
  2012-01-29  2:19 ` [Qemu-devel] [RFC 8/9] target-xtensa: add DEBUG_SECTION to overlay tool Max Filippov
  2012-01-29  2:19 ` [Qemu-devel] [RFC 9/9] target-xtensa: add breakpoint tests Max Filippov
  8 siblings, 0 replies; 11+ messages in thread
From: Max Filippov @ 2012-01-29  2:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: jcmvbkbc

Add DBREAKA/DBREAKC SRs and implement DBREAK breakpoints as debug
watchpoints.

This implementation is not fully compliant to ISA: when a breakpoint is
set to an unmapped/inaccessible memory address it generates TLB/memory
protection exception instead of debug exception.

See ISA, 4.7.7.3, 4.7.7.6 for more details.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 target-xtensa/cpu.h       |   12 ++++++++
 target-xtensa/helper.c    |   41 +++++++++++++++++++++++++++++
 target-xtensa/helpers.h   |    2 +
 target-xtensa/op_helper.c |   62 +++++++++++++++++++++++++++++++++++++++++++++
 target-xtensa/translate.c |   30 +++++++++++++++++++++
 5 files changed, 147 insertions(+), 0 deletions(-)

diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index fbe5d15..4dbd7b7 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -128,6 +128,8 @@ enum {
     DTLBCFG = 92,
     IBREAKENABLE = 96,
     IBREAKA = 128,
+    DBREAKA = 144,
+    DBREAKC = 160,
     EPC1 = 177,
     DEPC = 192,
     EPS2 = 194,
@@ -175,12 +177,18 @@ enum {
 #define DEBUGCAUSE_DBNUM 0xf00
 #define DEBUGCAUSE_DBNUM_SHIFT 8
 
+#define DBREAKC_SB 0x80000000
+#define DBREAKC_LB 0x40000000
+#define DBREAKC_SB_LB (DBREAKC_SB | DBREAKC_LB)
+#define DBREAKC_MASK 0x3f
+
 #define MAX_NAREG 64
 #define MAX_NINTERRUPT 32
 #define MAX_NLEVEL 6
 #define MAX_NNMI 1
 #define MAX_NCCOMPARE 3
 #define MAX_TLB_WAY_SIZE 8
+#define MAX_NDBREAK 2
 
 #define REGION_PAGE_MASK 0xe0000000
 
@@ -330,6 +338,9 @@ typedef struct CPUXtensaState {
 
     int exception_taken;
 
+    /* Watchpoints for DBREAK registers */
+    CPUWatchpoint *cpu_watchpoint[MAX_NDBREAK];
+
     CPU_COMMON
 } CPUXtensaState;
 
@@ -364,6 +375,7 @@ void xtensa_tlb_set_entry(CPUState *env, bool dtlb,
 int xtensa_get_physical_addr(CPUState *env,
         uint32_t vaddr, int is_write, int mmu_idx,
         uint32_t *paddr, uint32_t *page_size, unsigned *access);
+void debug_exception_env(CPUState *new_env, uint32_t cause);
 
 
 #define XTENSA_OPTION_BIT(opt) (((uint64_t)1) << (opt))
diff --git a/target-xtensa/helper.c b/target-xtensa/helper.c
index b7e67b7..a0bf697 100644
--- a/target-xtensa/helper.c
+++ b/target-xtensa/helper.c
@@ -58,9 +58,44 @@ void xtensa_register_core(XtensaConfigList *node)
     xtensa_cores = node;
 }
 
+static uint32_t check_hw_breakpoints(CPUState *env)
+{
+    unsigned i;
+
+    for (i = 0; i < env->config->ndbreak; ++i) {
+        if (env->cpu_watchpoint[i] &&
+                env->cpu_watchpoint[i]->flags & BP_WATCHPOINT_HIT) {
+            return DEBUGCAUSE_DB | (i << DEBUGCAUSE_DBNUM_SHIFT);
+        }
+    }
+    return 0;
+}
+
+static CPUDebugExcpHandler *prev_debug_excp_handler;
+
+static void breakpoint_handler(CPUState *env)
+{
+    if (env->watchpoint_hit) {
+        if (env->watchpoint_hit->flags & BP_CPU) {
+            uint32_t cause;
+
+            env->watchpoint_hit = NULL;
+            cause = check_hw_breakpoints(env);
+            if (cause) {
+                debug_exception_env(env, cause);
+            }
+            cpu_resume_from_signal(env, NULL);
+        }
+    }
+    if (prev_debug_excp_handler) {
+        prev_debug_excp_handler(env);
+    }
+}
+
 CPUXtensaState *cpu_xtensa_init(const char *cpu_model)
 {
     static int tcg_inited;
+    static int debug_handler_inited;
     CPUXtensaState *env;
     const XtensaConfig *config = NULL;
     XtensaConfigList *core = xtensa_cores;
@@ -84,6 +119,12 @@ CPUXtensaState *cpu_xtensa_init(const char *cpu_model)
         xtensa_translate_init();
     }
 
+    if (!debug_handler_inited && tcg_enabled()) {
+        debug_handler_inited = 1;
+        prev_debug_excp_handler =
+            cpu_set_debug_excp_handler(breakpoint_handler);
+    }
+
     xtensa_irq_init(env);
     qemu_init_vcpu(env);
     return env;
diff --git a/target-xtensa/helpers.h b/target-xtensa/helpers.h
index afe39d4..48a741e 100644
--- a/target-xtensa/helpers.h
+++ b/target-xtensa/helpers.h
@@ -33,5 +33,7 @@ DEF_HELPER_3(wtlb, void, i32, i32, i32)
 
 DEF_HELPER_1(wsr_ibreakenable, void, i32)
 DEF_HELPER_2(wsr_ibreaka, void, i32, i32)
+DEF_HELPER_2(wsr_dbreaka, void, i32, i32)
+DEF_HELPER_2(wsr_dbreakc, void, i32, i32)
 
 #include "def-helper.h"
diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c
index 1feaaee..e184cf6 100644
--- a/target-xtensa/op_helper.c
+++ b/target-xtensa/op_helper.c
@@ -134,6 +134,14 @@ void HELPER(exception_cause_vaddr)(uint32_t pc, uint32_t cause, uint32_t vaddr)
     HELPER(exception_cause)(pc, cause);
 }
 
+void debug_exception_env(CPUState *new_env, uint32_t cause)
+{
+    if (xtensa_get_cintlevel(new_env) < new_env->config->debug_level) {
+        env = new_env;
+        HELPER(debug_exception)(env->pc, cause);
+    }
+}
+
 void HELPER(debug_exception)(uint32_t pc, uint32_t cause)
 {
     unsigned level = env->config->debug_level;
@@ -700,3 +708,57 @@ void HELPER(wsr_ibreaka)(uint32_t i, uint32_t v)
     }
     env->sregs[IBREAKA + i] = v;
 }
+
+static void set_dbreak(unsigned i, uint32_t dbreaka, uint32_t dbreakc)
+{
+    int flags = BP_CPU | BP_STOP_BEFORE_ACCESS;
+    uint32_t mask = dbreakc | ~DBREAKC_MASK;
+
+    if (env->cpu_watchpoint[i]) {
+        cpu_watchpoint_remove_by_ref(env, env->cpu_watchpoint[i]);
+    }
+    if (dbreakc & DBREAKC_SB) {
+        flags |= BP_MEM_WRITE;
+    }
+    if (dbreakc & DBREAKC_LB) {
+        flags |= BP_MEM_READ;
+    }
+    /* contiguous mask after inversion is one less than some power of 2 */
+    if ((~mask + 1) & ~mask) {
+        qemu_log("DBREAKC mask is not contiguous: 0x%08x\n", dbreakc);
+        /* cut mask after the first zero bit */
+        mask = 0xffffffff << (32 - clo32(mask));
+    }
+    if (cpu_watchpoint_insert(env, dbreaka & mask, ~mask + 1,
+            flags, &env->cpu_watchpoint[i])) {
+        env->cpu_watchpoint[i] = NULL;
+        qemu_log("Failed to set data breakpoint at 0x%08x/%d\n",
+                dbreaka & mask, ~mask + 1);
+    }
+}
+
+void HELPER(wsr_dbreaka)(uint32_t i, uint32_t v)
+{
+    uint32_t dbreakc = env->sregs[DBREAKC + i];
+
+    if ((dbreakc & DBREAKC_SB_LB) &&
+            env->sregs[DBREAKA + i] != v) {
+        set_dbreak(i, v, dbreakc);
+    }
+    env->sregs[DBREAKA + i] = v;
+}
+
+void HELPER(wsr_dbreakc)(uint32_t i, uint32_t v)
+{
+    if ((env->sregs[DBREAKC + i] ^ v) & (DBREAKC_SB_LB | DBREAKC_MASK)) {
+        if (v & DBREAKC_SB_LB) {
+            set_dbreak(i, env->sregs[DBREAKA + i], v);
+        } else {
+            if (env->cpu_watchpoint[i]) {
+                cpu_watchpoint_remove_by_ref(env, env->cpu_watchpoint[i]);
+                env->cpu_watchpoint[i] = NULL;
+            }
+        }
+    }
+    env->sregs[DBREAKC + i] = v;
+}
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index 85f41a7..0a68f54 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -98,6 +98,10 @@ static const char * const sregnames[256] = {
     [IBREAKENABLE] = "IBREAKENABLE",
     [IBREAKA] = "IBREAKA0",
     [IBREAKA + 1] = "IBREAKA1",
+    [DBREAKA] = "DBREAKA0",
+    [DBREAKA + 1] = "DBREAKA1",
+    [DBREAKC] = "DBREAKC0",
+    [DBREAKC + 1] = "DBREAKC1",
     [EPC1] = "EPC1",
     [EPC1 + 1] = "EPC2",
     [EPC1 + 2] = "EPC3",
@@ -536,6 +540,28 @@ static void gen_wsr_ibreaka(DisasContext *dc, uint32_t sr, TCGv_i32 v)
     }
 }
 
+static void gen_wsr_dbreaka(DisasContext *dc, uint32_t sr, TCGv_i32 v)
+{
+    unsigned id = sr - DBREAKA;
+
+    if (id < dc->config->ndbreak) {
+        TCGv_i32 tmp = tcg_const_i32(id);
+        gen_helper_wsr_dbreaka(tmp, v);
+        tcg_temp_free(tmp);
+    }
+}
+
+static void gen_wsr_dbreakc(DisasContext *dc, uint32_t sr, TCGv_i32 v)
+{
+    unsigned id = sr - DBREAKC;
+
+    if (id < dc->config->ndbreak) {
+        TCGv_i32 tmp = tcg_const_i32(id);
+        gen_helper_wsr_dbreakc(tmp, v);
+        tcg_temp_free(tmp);
+    }
+}
+
 static void gen_wsr_intset(DisasContext *dc, uint32_t sr, TCGv_i32 v)
 {
     tcg_gen_andi_i32(cpu_SR[sr], v,
@@ -634,6 +660,10 @@ static void gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s)
         [IBREAKENABLE] = gen_wsr_ibreakenable,
         [IBREAKA] = gen_wsr_ibreaka,
         [IBREAKA + 1] = gen_wsr_ibreaka,
+        [DBREAKA] = gen_wsr_dbreaka,
+        [DBREAKA + 1] = gen_wsr_dbreaka,
+        [DBREAKC] = gen_wsr_dbreakc,
+        [DBREAKC + 1] = gen_wsr_dbreakc,
         [INTSET] = gen_wsr_intset,
         [INTCLEAR] = gen_wsr_intclear,
         [INTENABLE] = gen_wsr_intenable,
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [Qemu-devel] [RFC 8/9] target-xtensa: add DEBUG_SECTION to overlay tool
  2012-01-29  2:19 [Qemu-devel] [RFC 0/9] target-xtensa: implement debug option Max Filippov
                   ` (6 preceding siblings ...)
  2012-01-29  2:19 ` [Qemu-devel] [RFC 7/9] target-xtensa: add DBREAK data breakpoints Max Filippov
@ 2012-01-29  2:19 ` Max Filippov
  2012-01-29  2:19 ` [Qemu-devel] [RFC 9/9] target-xtensa: add breakpoint tests Max Filippov
  8 siblings, 0 replies; 11+ messages in thread
From: Max Filippov @ 2012-01-29  2:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: jcmvbkbc

Fill debug configuration from overlay definitions in the DEBUG_SECTION.
Add DEBUG_SECTION to DC232B and FSF cores.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 target-xtensa/core-dc232b.c  |    1 +
 target-xtensa/core-fsf.c     |    1 +
 target-xtensa/overlay_tool.h |    5 +++++
 3 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/target-xtensa/core-dc232b.c b/target-xtensa/core-dc232b.c
index 4d9bd55..b723c4c 100644
--- a/target-xtensa/core-dc232b.c
+++ b/target-xtensa/core-dc232b.c
@@ -22,6 +22,7 @@ static const XtensaConfig dc232b = {
     EXCEPTIONS_SECTION,
     INTERRUPTS_SECTION,
     TLB_SECTION,
+    DEBUG_SECTION,
     .clock_freq_khz = 10000,
 };
 
diff --git a/target-xtensa/core-fsf.c b/target-xtensa/core-fsf.c
index 7650462..88de4dd 100644
--- a/target-xtensa/core-fsf.c
+++ b/target-xtensa/core-fsf.c
@@ -16,6 +16,7 @@ static const XtensaConfig fsf = {
     EXCEPTIONS_SECTION,
     INTERRUPTS_SECTION,
     TLB_SECTION,
+    DEBUG_SECTION,
     .clock_freq_khz = 10000,
 };
 
diff --git a/target-xtensa/overlay_tool.h b/target-xtensa/overlay_tool.h
index df19cc9..cbb4aa6 100644
--- a/target-xtensa/overlay_tool.h
+++ b/target-xtensa/overlay_tool.h
@@ -114,6 +114,7 @@
         [EXC_KERNEL] = XCHAL_KERNEL_VECTOR_VADDR, \
         [EXC_USER] = XCHAL_USER_VECTOR_VADDR, \
         [EXC_DOUBLE] = XCHAL_DOUBLEEXC_VECTOR_VADDR, \
+        [EXC_DEBUG] = XCHAL_DEBUG_VECTOR_VADDR, \
     }
 
 #define INTERRUPT_VECTORS { \
@@ -288,6 +289,10 @@
 #define REGISTER_CORE(core)
 #endif
 
+#define DEBUG_SECTION \
+    .debug_level = XCHAL_DEBUGLEVEL, \
+    .nibreak = XCHAL_NUM_IBREAK, \
+    .ndbreak = XCHAL_NUM_DBREAK
 
 #if XCHAL_NUM_INTLEVELS + XCHAL_HAVE_NMI + 1 <= 2
 #define XCHAL_INTLEVEL2_VECTOR_VADDR 0
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [Qemu-devel] [RFC 9/9] target-xtensa: add breakpoint tests
  2012-01-29  2:19 [Qemu-devel] [RFC 0/9] target-xtensa: implement debug option Max Filippov
                   ` (7 preceding siblings ...)
  2012-01-29  2:19 ` [Qemu-devel] [RFC 8/9] target-xtensa: add DEBUG_SECTION to overlay tool Max Filippov
@ 2012-01-29  2:19 ` Max Filippov
  8 siblings, 0 replies; 11+ messages in thread
From: Max Filippov @ 2012-01-29  2:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: jcmvbkbc

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 tests/tcg/xtensa/Makefile     |    1 +
 tests/tcg/xtensa/test_break.S |  223 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 224 insertions(+), 0 deletions(-)
 create mode 100644 tests/tcg/xtensa/test_break.S

diff --git a/tests/tcg/xtensa/Makefile b/tests/tcg/xtensa/Makefile
index 8713af1..7e1e619 100644
--- a/tests/tcg/xtensa/Makefile
+++ b/tests/tcg/xtensa/Makefile
@@ -23,6 +23,7 @@ CRT        = crt.o vectors.o
 TESTCASES += test_b.tst
 TESTCASES += test_bi.tst
 #TESTCASES += test_boolean.tst
+TESTCASES += test_break.tst
 TESTCASES += test_bz.tst
 TESTCASES += test_clamps.tst
 TESTCASES += test_fail.tst
diff --git a/tests/tcg/xtensa/test_break.S b/tests/tcg/xtensa/test_break.S
new file mode 100644
index 0000000..8a8db80
--- /dev/null
+++ b/tests/tcg/xtensa/test_break.S
@@ -0,0 +1,223 @@
+.include "macros.inc"
+
+#define debug_level 6
+#define debug_vector level6
+
+test_suite break
+
+test break
+    set_vector debug_vector, 0
+    rsil    a2, debug_level
+    _break  0, 0
+
+    set_vector debug_vector, 2f
+    rsil    a2, debug_level - 1
+1:
+    _break  0, 0
+    test_fail
+2:
+    rsr     a2, ps
+    movi    a3, 0x1f
+    and     a2, a2, a3
+    movi    a3, 0x10 | debug_level
+    assert  eq, a2, a3
+    rsr     a2, epc6
+    movi    a3, 1b
+    assert  eq, a2, a3
+    rsr     a2, debugcause
+    movi    a3, 0x8
+    assert  eq, a2, a3
+test_end
+
+test breakn
+    set_vector debug_vector, 0
+    rsil    a2, debug_level
+    _break.n  0
+
+    set_vector debug_vector, 2f
+    rsil    a2, debug_level - 1
+1:
+    _break.n  0
+    test_fail
+2:
+    rsr     a2, ps
+    movi    a3, 0x1f
+    and     a2, a2, a3
+    movi    a3, 0x10 | debug_level
+    assert  eq, a2, a3
+    rsr     a2, epc6
+    movi    a3, 1b
+    assert  eq, a2, a3
+    rsr     a2, debugcause
+    movi    a3, 0x10
+    assert  eq, a2, a3
+test_end
+
+test ibreak
+    set_vector debug_vector, 0
+    rsil    a2, debug_level
+    movi    a2, 1f
+    wsr     a2, ibreaka0
+    movi    a2, 1
+    wsr     a2, ibreakenable
+    isync
+1:
+    rsil    a2, debug_level - 1
+    movi    a2, 1f
+    wsr     a2, ibreaka0
+    movi    a2, 0
+    wsr     a2, ibreakenable
+    isync
+1:
+    set_vector debug_vector, 2f
+    movi    a2, 1f
+    wsr     a2, ibreaka0
+    movi    a2, 1
+    wsr     a2, ibreakenable
+    isync
+1:
+    test_fail
+2:
+    rsr     a2, ps
+    movi    a3, 0x1f
+    and     a2, a2, a3
+    movi    a3, 0x10 | debug_level
+    assert  eq, a2, a3
+    rsr     a2, epc6
+    movi    a3, 1b
+    assert  eq, a2, a3
+    rsr     a2, debugcause
+    movi    a3, 0x2
+    assert  eq, a2, a3
+test_end
+
+test ibreak_priority
+    set_vector debug_vector, 2f
+    rsil    a2, debug_level - 1
+    movi    a2, 1f
+    wsr     a2, ibreaka0
+    movi    a2, 1
+    wsr     a2, ibreakenable
+    isync
+1:
+    break   0, 0
+    test_fail
+2:
+    rsr     a2, debugcause
+    movi    a3, 0x2
+    assert  eq, a2, a3
+test_end
+
+test icount
+    set_vector debug_vector, 2f
+    rsil    a2, debug_level - 1
+    movi    a2, -2
+    wsr     a2, icount
+    movi    a2, 1
+    wsr     a2, icountlevel
+    isync
+    rsil    a2, 0
+    nop
+1:
+    break   0, 0
+    test_fail
+2:
+    movi    a2, 0
+    wsr     a2, icountlevel
+    rsr     a2, epc6
+    movi    a3, 1b
+    assert  eq, a2, a3
+    rsr     a2, debugcause
+    movi    a3, 0x1
+    assert  eq, a2, a3
+test_end
+
+.macro check_dbreak dr
+    rsr     a2, epc6
+    movi    a3, 1b
+    assert  eq, a2, a3
+    rsr     a2, debugcause
+    movi    a3, 0x4 | (\dr << 8)
+    assert  eq, a2, a3
+    movi    a2, 0
+    wsr     a2, dbreakc\dr
+.endm
+
+.macro dbreak_test dr, ctl, break, access, op
+    set_vector debug_vector, 2f
+    rsil    a2, debug_level - 1
+    movi    a2, \ctl
+    wsr     a2, dbreakc\dr
+    movi    a2, \break
+    wsr     a2, dbreaka\dr
+    movi    a2, \access
+    isync
+1:
+    \op     a3, a2, 0
+    test_fail
+2:
+    check_dbreak \dr
+    reset_ps
+.endm
+
+test dbreak_exact
+    dbreak_test 0, 0x4000003f, 0xd000007f, 0xd000007f, l8ui
+    dbreak_test 1, 0x4000003e, 0xd000007e, 0xd000007e, l16ui
+    dbreak_test 0, 0x4000003c, 0xd000007c, 0xd000007c, l32i
+
+    dbreak_test 1, 0x8000003f, 0xd000007f, 0xd000007f, s8i
+    dbreak_test 0, 0x8000003e, 0xd000007e, 0xd000007e, s16i
+    dbreak_test 1, 0x8000003c, 0xd000007c, 0xd000007c, s32i
+test_end
+
+test dbreak_overlap
+    dbreak_test 0, 0x4000003f, 0xd000007d, 0xd000007c, l16ui
+    dbreak_test 1, 0x4000003f, 0xd000007d, 0xd000007c, l32i
+
+    dbreak_test 0, 0x4000003e, 0xd000007e, 0xd000007f, l8ui
+    dbreak_test 1, 0x4000003e, 0xd000007e, 0xd000007c, l32i
+
+    dbreak_test 0, 0x4000003c, 0xd000007c, 0xd000007d, l8ui
+    dbreak_test 1, 0x4000003c, 0xd000007c, 0xd000007c, l16ui
+
+    dbreak_test 0, 0x40000038, 0xd0000078, 0xd000007b, l8ui
+    dbreak_test 1, 0x40000038, 0xd0000078, 0xd000007a, l16ui
+    dbreak_test 0, 0x40000038, 0xd0000078, 0xd000007c, l32i
+
+    dbreak_test 1, 0x40000030, 0xd0000070, 0xd0000075, l8ui
+    dbreak_test 0, 0x40000030, 0xd0000070, 0xd0000076, l16ui
+    dbreak_test 1, 0x40000030, 0xd0000070, 0xd0000078, l32i
+
+    dbreak_test 0, 0x40000020, 0xd0000060, 0xd000006f, l8ui
+    dbreak_test 1, 0x40000020, 0xd0000060, 0xd0000070, l16ui
+    dbreak_test 0, 0x40000020, 0xd0000060, 0xd0000074, l32i
+
+
+    dbreak_test 0, 0x8000003f, 0xd000007d, 0xd000007c, s16i
+    dbreak_test 1, 0x8000003f, 0xd000007d, 0xd000007c, s32i
+
+    dbreak_test 0, 0x8000003e, 0xd000007e, 0xd000007f, s8i
+    dbreak_test 1, 0x8000003e, 0xd000007e, 0xd000007c, s32i
+
+    dbreak_test 0, 0x8000003c, 0xd000007c, 0xd000007d, s8i
+    dbreak_test 1, 0x8000003c, 0xd000007c, 0xd000007c, s16i
+
+    dbreak_test 0, 0x80000038, 0xd0000078, 0xd000007b, s8i
+    dbreak_test 1, 0x80000038, 0xd0000078, 0xd000007a, s16i
+    dbreak_test 0, 0x80000038, 0xd0000078, 0xd000007c, s32i
+
+    dbreak_test 1, 0x80000030, 0xd0000070, 0xd0000075, s8i
+    dbreak_test 0, 0x80000030, 0xd0000070, 0xd0000076, s16i
+    dbreak_test 1, 0x80000030, 0xd0000070, 0xd0000078, s32i
+
+    dbreak_test 0, 0x80000020, 0xd0000060, 0xd000006f, s8i
+    dbreak_test 1, 0x80000020, 0xd0000060, 0xd0000070, s16i
+    dbreak_test 0, 0x80000020, 0xd0000060, 0xd0000074, s32i
+test_end
+
+test dbreak_invalid
+    dbreak_test 0, 0x40000030, 0xd0000071, 0xd0000070, l16ui
+    dbreak_test 1, 0x40000035, 0xd0000072, 0xd0000070, l32i
+test_end
+
+test_suite_end
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [Qemu-devel] [RFC 4/9] exec: add missing breaks to the watch_mem_write
  2012-01-29  2:19 ` [Qemu-devel] [RFC 4/9] exec: add missing breaks to the watch_mem_write Max Filippov
@ 2012-01-29  9:49   ` Andreas Färber
  0 siblings, 0 replies; 11+ messages in thread
From: Andreas Färber @ 2012-01-29  9:49 UTC (permalink / raw)
  To: Max Filippov; +Cc: qemu-devel

Am 29.01.2012 03:19, schrieb Max Filippov:
> Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>

Reviewed-by: Andreas Färber <afaerber@suse.de>

Good catch!

Andreas

> ---
>  exec.c |   12 +++++++++---
>  1 files changed, 9 insertions(+), 3 deletions(-)
> 
> diff --git a/exec.c b/exec.c
> index 5b9eb9a..0e93e0e 100644
> --- a/exec.c
> +++ b/exec.c
> @@ -3279,9 +3279,15 @@ static void watch_mem_write(void *opaque, target_phys_addr_t addr,
>  {
>      check_watchpoint(addr & ~TARGET_PAGE_MASK, ~(size - 1), BP_MEM_WRITE);
>      switch (size) {
> -    case 1: stb_phys(addr, val);
> -    case 2: stw_phys(addr, val);
> -    case 4: stl_phys(addr, val);
> +    case 1:
> +        stb_phys(addr, val);
> +        break;
> +    case 2:
> +        stw_phys(addr, val);
> +        break;
> +    case 4:
> +        stl_phys(addr, val);
> +        break;
>      default: abort();
>      }
>  }

-- 
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2012-01-29  9:51 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-01-29  2:19 [Qemu-devel] [RFC 0/9] target-xtensa: implement debug option Max Filippov
2012-01-29  2:19 ` [Qemu-devel] [RFC 1/9] target-xtensa: add DEBUGCAUSE SR and configuration Max Filippov
2012-01-29  2:19 ` [Qemu-devel] [RFC 2/9] target-xtensa: implement instruction breakpoints Max Filippov
2012-01-29  2:19 ` [Qemu-devel] [RFC 3/9] target-xtensa: add ICOUNT SR and debug exception Max Filippov
2012-01-29  2:19 ` [Qemu-devel] [RFC 4/9] exec: add missing breaks to the watch_mem_write Max Filippov
2012-01-29  9:49   ` Andreas Färber
2012-01-29  2:19 ` [Qemu-devel] [RFC 5/9] exec: fix check_watchpoint exiting cpu_loop Max Filippov
2012-01-29  2:19 ` [Qemu-devel] [RFC 6/9] exec: let cpu_watchpoint_insert accept larger watchpoints Max Filippov
2012-01-29  2:19 ` [Qemu-devel] [RFC 7/9] target-xtensa: add DBREAK data breakpoints Max Filippov
2012-01-29  2:19 ` [Qemu-devel] [RFC 8/9] target-xtensa: add DEBUG_SECTION to overlay tool Max Filippov
2012-01-29  2:19 ` [Qemu-devel] [RFC 9/9] target-xtensa: add breakpoint tests Max Filippov

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).