All of lore.kernel.org
 help / color / mirror / Atom feed
From: Brian Cain <brian.cain@oss.qualcomm.com>
To: qemu-devel@nongnu.org
Cc: Pierrick Bouvier <pierrick.bouvier@oss.qualcomm.com>,
	Brian Cain <brian.cain@oss.qualcomm.com>,
	Laurent Vivier <laurent@vivier.eu>, Helge Deller <deller@gmx.de>
Subject: [PATCH v2 08/11] target/hexagon: raise imprecise exception on multi-TLB match
Date: Tue,  1 Sep 2026 10:33:50 -0700	[thread overview]
Message-ID: <20260901173353.200474-9-brian.cain@oss.qualcomm.com> (raw)
In-Reply-To: <20260901173353.200474-1-brian.cain@oss.qualcomm.com>

tlbp now records a pending imprecise exception (via env->imprecise_exception)
when the lookup matches multiple entries, and the translator raises it after
the tlbp packet.  Implement the HEX_EVENT_IMPRECISE delivery path so the
guest sees HEX_CAUSE_IMPRECISE_MULTI_TLB_MATCH instead of the exception
being silently dropped.

Reviewed-by: Pierrick Bouvier <pierrick.bouvier@oss.qualcomm.com>
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
 include/hw/hexagon/hexagon_tlb.h |  3 ++-
 target/hexagon/cpu.h             |  1 +
 hw/hexagon/hexagon_tlb.c         |  5 ++++-
 target/hexagon/hex_mmu.c         |  5 ++++-
 target/hexagon/hexswi.c          | 37 +++++++++++++++++++++++++++++---
 target/hexagon/machine.c         |  5 +++--
 target/hexagon/translate.c       | 29 +++++++++++++++++++++++++
 7 files changed, 77 insertions(+), 8 deletions(-)

diff --git a/include/hw/hexagon/hexagon_tlb.h b/include/hw/hexagon/hexagon_tlb.h
index 760dc1ea811..67c0a56b79e 100644
--- a/include/hw/hexagon/hexagon_tlb.h
+++ b/include/hw/hexagon/hexagon_tlb.h
@@ -32,7 +32,8 @@ bool hexagon_tlb_find_match(HexagonTLBState *tlb, uint32_t asid,
                             int32_t *excp, int *cause_code, int mmu_idx);
 
 uint32_t hexagon_tlb_lookup(HexagonTLBState *tlb, uint32_t asid,
-                            uint32_t VA, int *cause_code);
+                            uint32_t VA, uint32_t *imprecise_exception,
+                            int *cause_code);
 
 int hexagon_tlb_check_overlap(HexagonTLBState *tlb, uint64_t entry,
                               uint64_t index);
diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h
index c50fbb3f72a..ed5671abe5c 100644
--- a/target/hexagon/cpu.h
+++ b/target/hexagon/cpu.h
@@ -147,6 +147,7 @@ typedef struct CPUArchState {
     uint64_t t_cycle_count;
 #endif
     uint32_t next_PC;
+    uint32_t imprecise_exception;
     target_ulong new_value_usr;
 
     MemLog mem_log_stores[STORES_MAX];
diff --git a/hw/hexagon/hexagon_tlb.c b/hw/hexagon/hexagon_tlb.c
index b6d4aff389e..6539458f25f 100644
--- a/hw/hexagon/hexagon_tlb.c
+++ b/hw/hexagon/hexagon_tlb.c
@@ -319,15 +319,18 @@ bool hexagon_tlb_find_match(HexagonTLBState *tlb, uint32_t asid,
 }
 
 uint32_t hexagon_tlb_lookup(HexagonTLBState *tlb, uint32_t asid,
-                            uint32_t VA, int *cause_code)
+                            uint32_t VA, uint32_t *imprecise_exception,
+                            int *cause_code)
 {
     uint32_t not_found = 0x80000000;
     uint32_t idx = not_found;
 
+    *imprecise_exception = 0;
     for (uint32_t i = 0; i < tlb->num_entries; i++) {
         uint64_t entry = tlb->entries[i];
         if (hex_tlb_entry_match_noperm(entry, asid, VA)) {
             if (idx != not_found) {
+                *imprecise_exception = HEX_EVENT_IMPRECISE;
                 *cause_code = HEX_CAUSE_IMPRECISE_MULTI_TLB_MATCH;
                 break;
             }
diff --git a/target/hexagon/hex_mmu.c b/target/hexagon/hex_mmu.c
index 81d64a6146c..de108f709c0 100644
--- a/target/hexagon/hex_mmu.c
+++ b/target/hexagon/hex_mmu.c
@@ -86,9 +86,12 @@ uint32_t hex_tlb_lookup(CPUHexagonState *env, uint32_t ssr, uint32_t VA)
 {
     HexagonCPU *cpu = env_archcpu(env);
     uint8_t asid = GET_SSR_FIELD(SSR_ASID, ssr);
+    uint32_t imprecise_exception = 0;
     int cause_code = 0;
 
-    uint32_t result = hexagon_tlb_lookup(cpu->tlb, asid, VA, &cause_code);
+    uint32_t result = hexagon_tlb_lookup(cpu->tlb, asid, VA,
+                                         &imprecise_exception, &cause_code);
+    env->imprecise_exception = imprecise_exception;
     if (cause_code) {
         env->cause_code = cause_code;
     }
diff --git a/target/hexagon/hexswi.c b/target/hexagon/hexswi.c
index 43c373ea2ee..d29c12e6481 100644
--- a/target/hexagon/hexswi.c
+++ b/target/hexagon/hexswi.c
@@ -69,6 +69,7 @@ void hexagon_cpu_do_interrupt(CPUState *cs)
 
 {
     CPUHexagonState *env = cpu_env(cs);
+    HexagonCPU *cpu = HEXAGON_CPU(cs);
     uint32_t ssr;
 
     BQL_LOCK_GUARD();
@@ -83,7 +84,6 @@ void hexagon_cpu_do_interrupt(CPUState *cs)
 
     ssr = env->t_sreg[HEX_SREG_SSR];
     if (GET_SSR_FIELD(SSR_EX, ssr) == 1) {
-        HexagonCPU *cpu = env_archcpu(env);
         if (cpu->globalregs) {
             hexagon_globalreg_write(cpu->globalregs, HEX_SREG_DIAG,
                                     env->cause_code, env->threadId);
@@ -243,8 +243,39 @@ void hexagon_cpu_do_interrupt(CPUState *cs)
         break;
 
     case HEX_EVENT_IMPRECISE:
-        qemu_log_mask(LOG_UNIMP,
-                "Imprecise exception: this case is not yet handled");
+        if (get_exe_mode(env) == HEX_EXE_MODE_WAIT) {
+            env->gpr[HEX_REG_PC] = env->wait_next_pc - 4;
+            clear_wait_mode(env);
+        }
+        switch (env->cause_code) {
+        case HEX_CAUSE_IMPRECISE_MULTI_TLB_MATCH:
+            hexagon_ssr_set_cause(env, env->cause_code);
+            set_addresses(env, 4, cs->exception_index);
+            if (cpu->globalregs) {
+                hexagon_globalreg_write(cpu->globalregs, HEX_SREG_DIAG,
+                    (0x4 << 4) | (env->t_sreg[HEX_SREG_HTID] & 0xF),
+                    env->threadId);
+            }
+            break;
+
+        case HEX_CAUSE_IMPRECISE_NMI:
+            hexagon_ssr_set_cause(env, env->cause_code);
+            set_addresses(env, 4, cs->exception_index);
+            if (cpu->globalregs) {
+                hexagon_globalreg_write(cpu->globalregs, HEX_SREG_DIAG,
+                    (0x3 << 4) | (env->t_sreg[HEX_SREG_HTID] & 0xF),
+                    env->threadId);
+            }
+            break;
+
+        default:
+            qemu_log_mask(LOG_GUEST_ERROR,
+                    "Imprecise exception with unhandled cause 0x%x\n",
+                    env->cause_code);
+            hexagon_ssr_set_cause(env, env->cause_code);
+            set_addresses(env, 4, cs->exception_index);
+            break;
+        }
         break;
 
     default:
diff --git a/target/hexagon/machine.c b/target/hexagon/machine.c
index 2dd95466e7d..bf4646f4a8b 100644
--- a/target/hexagon/machine.c
+++ b/target/hexagon/machine.c
@@ -10,8 +10,8 @@
 
 const VMStateDescription vmstate_hexagon_cpu = {
     .name = "cpu",
-    .version_id = 1,
-    .minimum_version_id = 1,
+    .version_id = 2,
+    .minimum_version_id = 2,
     .fields = (const VMStateField[]) {
         VMSTATE_UINT32_ARRAY(env.gpr, HexagonCPU, TOTAL_PER_THREAD_REGS),
         VMSTATE_UINT32_ARRAY(env.pred, HexagonCPU, NUM_PREGS),
@@ -26,6 +26,7 @@ const VMStateDescription vmstate_hexagon_cpu = {
         VMSTATE_UINT32(env.cause_code, HexagonCPU),
         VMSTATE_UINT32(env.wait_next_pc, HexagonCPU),
         VMSTATE_UINT64(env.t_cycle_count, HexagonCPU),
+        VMSTATE_UINT32(env.imprecise_exception, HexagonCPU),
 
         VMSTATE_END_OF_LIST()
     },
diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c
index 5cfa60ca302..1d28f2db0fc 100644
--- a/target/hexagon/translate.c
+++ b/target/hexagon/translate.c
@@ -65,6 +65,7 @@ TCGv hex_llsc_val;
 TCGv_i64 hex_llsc_val_i64;
 #ifndef CONFIG_USER_ONLY
 TCGv_i64 hex_cycle_count;
+TCGv hex_imprecise_exception;
 #endif
 TCGv hex_vstore_addr[VSTORES_MAX];
 TCGv hex_vstore_size[VSTORES_MAX];
@@ -1051,6 +1052,28 @@ static void update_exec_counters(DisasContext *ctx)
     ctx->num_cycles += PCYCLES_PER_PACKET;
 }
 
+#ifndef CONFIG_USER_ONLY
+/*
+ * A tlbp instruction may detect multiple TLB matches and set a pending
+ * imprecise exception.  Raise it after the packet that ran the tlbp.
+ */
+static void check_imprecise_exception(Packet *pkt)
+{
+    for (int i = 0; i < pkt->num_insns; i++) {
+        if (pkt->insn[i].opcode == Y2_tlbp) {
+            TCGv PC = tcg_constant_tl(pkt->pc);
+            TCGLabel *label = gen_new_label();
+            tcg_gen_brcondi_tl(TCG_COND_EQ, hex_imprecise_exception,
+                               0, label);
+            gen_helper_raise_exception(tcg_env,
+                                       hex_imprecise_exception, PC);
+            gen_set_label(label);
+            return;
+        }
+    }
+}
+#endif
+
 static void gen_commit_packet(DisasContext *ctx)
 {
     /*
@@ -1150,6 +1173,10 @@ static void gen_commit_packet(DisasContext *ctx)
         ctx->pkt.vhist_insn->generate(ctx);
     }
 
+#ifndef CONFIG_USER_ONLY
+    check_imprecise_exception(&ctx->pkt);
+#endif
+
     if (ctx->pkt_ends_tb || ctx->base.is_jmp == DISAS_NORETURN) {
         gen_end_tb(ctx);
     }
@@ -1357,6 +1384,8 @@ void hexagon_translate_init(void)
 #ifndef CONFIG_USER_ONLY
     hex_cycle_count = tcg_global_mem_new_i64(tcg_env,
         offsetof(CPUHexagonState, t_cycle_count), "t_cycle_count");
+    hex_imprecise_exception = tcg_global_mem_new(tcg_env,
+        offsetof(CPUHexagonState, imprecise_exception), "imprecise_exception");
 #endif
     for (i = 0; i < STORES_MAX; i++) {
         snprintf(store_addr_names[i], NAME_LEN, "store_addr_%d", i);
-- 
2.34.1


  parent reply	other threads:[~2026-09-01 17:35 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-01 17:33 [PATCH v2 00/11] Hexagon: exception, interrupt, system reg fixes Brian Cain
2026-09-01 17:33 ` [PATCH v2 01/11] target/hexagon: align exceptions for user/sysemu Brian Cain
2026-09-01 17:33 ` [PATCH v2 02/11] tests/tcg/hexagon: check priv instructions raise SIGILL Brian Cain
2026-09-01 17:33 ` [PATCH v2 03/11] hw/intc: clear pending bit on l2vic de-assertion Brian Cain
2026-09-02 21:30   ` Philippe Mathieu-Daudé
2026-09-03 19:33     ` Brian Cain
2026-09-01 17:33 ` [PATCH v2 04/11] target/hexagon: guard writes to unimplemented guest registers Brian Cain
2026-09-01 18:25   ` Pierrick Bouvier
2026-09-01 17:33 ` [PATCH v2 05/11] target/hexagon: take BQL when reading the system pcycle count Brian Cain
2026-09-01 17:33 ` [PATCH v2 06/11] target/hexagon: gate GPCYCLE guest register reads on SSR:CE Brian Cain
2026-09-02 21:16   ` Philippe Mathieu-Daudé
2026-09-03 19:36     ` Brian Cain
2026-09-04 13:19       ` Philippe Mathieu-Daudé
2026-09-01 17:33 ` [PATCH v2 07/11] target/hexagon: read UTIMERLO/UTIMERHI from the global timer Brian Cain
2026-09-02 21:21   ` Philippe Mathieu-Daudé
2026-09-01 17:33 ` Brian Cain [this message]
2026-09-01 17:33 ` [PATCH v2 09/11] target/hexagon: implement direct-to-guest interrupt delivery Brian Cain
2026-09-01 18:26   ` Pierrick Bouvier
2026-09-01 17:33 ` [PATCH v2 10/11] target/hexagon: fix iassign{r, w} to cover all threads Brian Cain via qemu development
2026-09-01 17:33 ` [PATCH v2 11/11] tests/functional/hexagon: update to v0.2.12, +test_{interrupts, sys_regs} Brian Cain via qemu development

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=20260901173353.200474-9-brian.cain@oss.qualcomm.com \
    --to=brian.cain@oss.qualcomm.com \
    --cc=deller@gmx.de \
    --cc=laurent@vivier.eu \
    --cc=pierrick.bouvier@oss.qualcomm.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.