qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Max Filippov <jcmvbkbc@gmail.com>
To: qemu-devel@nongnu.org
Cc: blauwirbel@gmail.com, Max Filippov <jcmvbkbc@gmail.com>,
	aliguori@us.ibm.com, afaerber@suse.de
Subject: [Qemu-devel] [PATCH 05/12] target-xtensa: implement instruction breakpoints
Date: Sat, 18 Feb 2012 21:11:36 +0400	[thread overview]
Message-ID: <1329585103-31371-5-git-send-email-jcmvbkbc@gmail.com> (raw)
In-Reply-To: <1329585103-31371-1-git-send-email-jcmvbkbc@gmail.com>

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 c77fe13..a18072b 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
 };
 
@@ -425,6 +428,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)
@@ -440,6 +444,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 973c268..0a26f8d 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 da5fdb5..a438474 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,
@@ -975,8 +1014,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*/
@@ -2356,7 +2397,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*/
@@ -2409,6 +2453,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)
 {
@@ -2435,6 +2492,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);
@@ -2474,6 +2532,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

  parent reply	other threads:[~2012-02-18 17:12 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-02-18 11:30 [Qemu-devel] [PULL 00/12] target-xtensa queue Max Filippov
2012-02-18 16:36 ` Andreas Färber
2012-02-18 17:11 ` [Qemu-devel] [PATCH 01/12] target-xtensa: define TLB_TEMPLATE for MMU-less cores Max Filippov
2012-02-18 17:11   ` [Qemu-devel] [PATCH 02/12] target-xtensa: implement info tlb monitor command Max Filippov
2012-02-18 17:11   ` [Qemu-devel] [PATCH 03/12] target-xtensa: fetch 3rd opcode byte only when needed Max Filippov
2012-02-18 17:11   ` [Qemu-devel] [PATCH 04/12] target-xtensa: add DEBUGCAUSE SR and configuration Max Filippov
2012-02-18 17:11   ` Max Filippov [this message]
2012-02-18 17:11   ` [Qemu-devel] [PATCH 06/12] target-xtensa: add ICOUNT SR and debug exception Max Filippov
2012-02-18 17:11   ` [Qemu-devel] [PATCH 07/12] exec: add missing breaks to the watch_mem_write Max Filippov
2012-02-18 17:51     ` Andreas Färber
2012-02-18 18:13       ` Max Filippov
2012-02-20 14:12     ` Meador Inge
2012-02-18 17:11   ` [Qemu-devel] [PATCH 08/12] exec: fix check_watchpoint exiting cpu_loop Max Filippov
2012-02-18 17:11   ` [Qemu-devel] [PATCH 09/12] exec: let cpu_watchpoint_insert accept larger watchpoints Max Filippov
2012-02-18 17:11   ` [Qemu-devel] [PATCH 10/12] target-xtensa: add DBREAK data breakpoints Max Filippov
2012-02-18 17:11   ` [Qemu-devel] [PATCH 11/12] target-xtensa: add DEBUG_SECTION to overlay tool Max Filippov
2012-02-18 17:11   ` [Qemu-devel] [PATCH 12/12] target-xtensa: add breakpoint tests Max Filippov
2012-02-26 17:34 ` [Qemu-devel] [PULL 00/12] target-xtensa queue Max Filippov
2012-03-03 17:56   ` Blue Swirl

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=1329585103-31371-5-git-send-email-jcmvbkbc@gmail.com \
    --to=jcmvbkbc@gmail.com \
    --cc=afaerber@suse.de \
    --cc=aliguori@us.ibm.com \
    --cc=blauwirbel@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).