All of lore.kernel.org
 help / color / mirror / Atom feed
From: Richard Henderson <richard.henderson@linaro.org>
To: qemu-devel@nongnu.org
Cc: Peter Maydell <peter.maydell@linaro.org>
Subject: [PULL 57/68] target/nios2: Introduce shadow register sets
Date: Tue, 26 Apr 2022 11:18:56 -0700	[thread overview]
Message-ID: <20220426181907.103691-58-richard.henderson@linaro.org> (raw)
In-Reply-To: <20220426181907.103691-1-richard.henderson@linaro.org>

Do not actually enable them so far, in terms of being able
to change the current register set, but add all of the
plumbing to address them.  Do not enable them for user-only.

Add an env->regs pointer that handles the indirection to
the current register set.  The naming of the pointer hides
the difference between old and new, user-only and sysemu.

From the notes on wrprs, which states that r0 must be initialized
before use in shadow register sets, infer that R_ZERO is *not*
hardwired to zero in shadow register sets, but that it is still
read-only.  Introduce tbflags bit R0_0 to track that it has been
properly set to zero.  Adjust load_gpr to reflect this.

At the same time we might as well special case crs == 0 to avoid
the indirection through env->regs during translation as well; this
is intended to be the most common case for non-interrupt handlers.

Init env->regs at reset.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Message-Id: <20220421151735.31996-54-richard.henderson@linaro.org>
---
 target/nios2/cpu.h       | 29 ++++++++++++++++++-
 target/nios2/cpu.c       |  4 ++-
 target/nios2/translate.c | 61 ++++++++++++++++++++++++++++++++++------
 3 files changed, 83 insertions(+), 11 deletions(-)

diff --git a/target/nios2/cpu.h b/target/nios2/cpu.h
index 477a661f17..f6efaa79b3 100644
--- a/target/nios2/cpu.h
+++ b/target/nios2/cpu.h
@@ -60,6 +60,11 @@ struct Nios2CPUClass {
 #define NUM_GP_REGS 32
 #define NUM_CR_REGS 32
 
+#ifndef CONFIG_USER_ONLY
+/* 63 shadow register sets; index 0 is the primary register set. */
+#define NUM_REG_SETS 64
+#endif
+
 /* General purpose register aliases */
 enum {
     R_ZERO   = 0,
@@ -178,7 +183,13 @@ FIELD(CR_TLBMISC, EE, 24, 1)
 #define EXCP_MPUD     17
 
 struct CPUArchState {
+#ifdef CONFIG_USER_ONLY
     uint32_t regs[NUM_GP_REGS];
+#else
+    uint32_t shadow_regs[NUM_REG_SETS][NUM_GP_REGS];
+    /* Pointer into shadow_regs for the current register set. */
+    uint32_t *regs;
+#endif
     uint32_t ctrl[NUM_CR_REGS];
     uint32_t pc;
 
@@ -229,6 +240,14 @@ static inline bool nios2_cr_reserved(const ControlRegState *s)
     return (s->writable | s->readonly) == 0;
 }
 
+static inline void nios2_update_crs(CPUNios2State *env)
+{
+#ifndef CONFIG_USER_ONLY
+    unsigned crs = FIELD_EX32(env->ctrl[CR_STATUS], CR_STATUS, CRS);
+    env->regs = env->shadow_regs[crs];
+#endif
+}
+
 void nios2_tcg_init(void);
 void nios2_cpu_do_interrupt(CPUState *cs);
 void dump_mmu(CPUNios2State *env);
@@ -267,12 +286,20 @@ typedef Nios2CPU ArchCPU;
 
 #include "exec/cpu-all.h"
 
+FIELD(TBFLAGS, CRS0, 0, 1)  /* Set if CRS == 0. */
+FIELD(TBFLAGS, U, 1, 1)     /* Overlaps CR_STATUS_U */
+FIELD(TBFLAGS, R0_0, 2, 1)  /* Set if R0 == 0. */
+
 static inline void cpu_get_tb_cpu_state(CPUNios2State *env, target_ulong *pc,
                                         target_ulong *cs_base, uint32_t *flags)
 {
+    unsigned crs = FIELD_EX32(env->ctrl[CR_STATUS], CR_STATUS, CRS);
+
     *pc = env->pc;
     *cs_base = 0;
-    *flags = env->ctrl[CR_STATUS] & CR_STATUS_U;
+    *flags = (env->ctrl[CR_STATUS] & CR_STATUS_U)
+           | (crs ? 0 : R_TBFLAGS_CRS0_MASK)
+           | (env->regs[0] ? 0 : R_TBFLAGS_R0_0_MASK);
 }
 
 #endif /* NIOS2_CPU_H */
diff --git a/target/nios2/cpu.c b/target/nios2/cpu.c
index 54e7071907..d043c02fcd 100644
--- a/target/nios2/cpu.c
+++ b/target/nios2/cpu.c
@@ -48,15 +48,17 @@ static void nios2_cpu_reset(DeviceState *dev)
 
     ncc->parent_reset(dev);
 
-    memset(env->regs, 0, sizeof(env->regs));
     memset(env->ctrl, 0, sizeof(env->ctrl));
     env->pc = cpu->reset_addr;
 
 #if defined(CONFIG_USER_ONLY)
     /* Start in user mode with interrupts enabled. */
     env->ctrl[CR_STATUS] = CR_STATUS_RSIE | CR_STATUS_U | CR_STATUS_PIE;
+    memset(env->regs, 0, sizeof(env->regs));
 #else
     env->ctrl[CR_STATUS] = CR_STATUS_RSIE;
+    nios2_update_crs(env);
+    memset(env->shadow_regs, 0, sizeof(env->shadow_regs));
 #endif
 }
 
diff --git a/target/nios2/translate.c b/target/nios2/translate.c
index 794b763d8a..363f2ea3ca 100644
--- a/target/nios2/translate.c
+++ b/target/nios2/translate.c
@@ -127,12 +127,16 @@ typedef struct DisasContext {
     DisasContextBase  base;
     target_ulong      pc;
     int               mem_idx;
+    uint32_t          tb_flags;
     TCGv              sink;
     const ControlRegState *cr_state;
 } DisasContext;
 
 static TCGv cpu_R[NUM_GP_REGS];
 static TCGv cpu_pc;
+#ifndef CONFIG_USER_ONLY
+static TCGv cpu_crs_R[NUM_GP_REGS];
+#endif
 
 typedef struct Nios2Instruction {
     void     (*handler)(DisasContext *dc, uint32_t code, uint32_t flags);
@@ -154,22 +158,47 @@ static uint8_t get_opxcode(uint32_t code)
 static TCGv load_gpr(DisasContext *dc, unsigned reg)
 {
     assert(reg < NUM_GP_REGS);
-    if (unlikely(reg == R_ZERO)) {
+
+    /*
+     * With shadow register sets, register r0 does not necessarily contain 0,
+     * but it is overwhelmingly likely that it does -- software is supposed
+     * to have set r0 to 0 in every shadow register set before use.
+     */
+    if (unlikely(reg == R_ZERO) && FIELD_EX32(dc->tb_flags, TBFLAGS, R0_0)) {
         return tcg_constant_tl(0);
     }
-    return cpu_R[reg];
+    if (FIELD_EX32(dc->tb_flags, TBFLAGS, CRS0)) {
+        return cpu_R[reg];
+    }
+#ifdef CONFIG_USER_ONLY
+    g_assert_not_reached();
+#else
+    return cpu_crs_R[reg];
+#endif
 }
 
 static TCGv dest_gpr(DisasContext *dc, unsigned reg)
 {
     assert(reg < NUM_GP_REGS);
+
+    /*
+     * The spec for shadow register sets isn't clear, but we assume that
+     * writes to r0 are discarded regardless of CRS.
+     */
     if (unlikely(reg == R_ZERO)) {
         if (dc->sink == NULL) {
             dc->sink = tcg_temp_new();
         }
         return dc->sink;
     }
-    return cpu_R[reg];
+    if (FIELD_EX32(dc->tb_flags, TBFLAGS, CRS0)) {
+        return cpu_R[reg];
+    }
+#ifdef CONFIG_USER_ONLY
+    g_assert_not_reached();
+#else
+    return cpu_crs_R[reg];
+#endif
 }
 
 static void t_gen_helper_raise_exception(DisasContext *dc,
@@ -225,7 +254,7 @@ static void gen_excp(DisasContext *dc, uint32_t code, uint32_t flags)
 
 static bool gen_check_supervisor(DisasContext *dc)
 {
-    if (dc->base.tb->flags & CR_STATUS_U) {
+    if (FIELD_EX32(dc->tb_flags, TBFLAGS, U)) {
         /* CPU in user mode, privileged instruction called, stop. */
         t_gen_helper_raise_exception(dc, EXCP_SUPERI);
         return false;
@@ -335,7 +364,7 @@ static void do_i_math_logic(DisasContext *dc, uint32_t insn,
 
     val = imm(&instr);
 
-    if (instr.a == R_ZERO) {
+    if (instr.a == R_ZERO && FIELD_EX32(dc->tb_flags, TBFLAGS, R0_0)) {
         /* This catches the canonical expansions of movi and movhi. */
         tcg_gen_movi_tl(dest_gpr(dc, instr.b), x_op_0_eq_x ? val : 0);
     } else {
@@ -865,6 +894,7 @@ static void nios2_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
 
     dc->mem_idx = cpu_mmu_index(env, false);
     dc->cr_state = cpu->cr_state;
+    dc->tb_flags = dc->base.tb->flags;
 
     /* Bound the number of insns to execute to those left on the page.  */
     page_insns = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
@@ -999,13 +1029,26 @@ void nios2_cpu_dump_state(CPUState *cs, FILE *f, int flags)
 
 void nios2_tcg_init(void)
 {
-    int i;
+#ifndef CONFIG_USER_ONLY
+    TCGv_ptr crs = tcg_global_mem_new_ptr(cpu_env,
+                                          offsetof(CPUNios2State, regs), "crs");
 
-    for (i = 0; i < NUM_GP_REGS; i++) {
-        cpu_R[i] = tcg_global_mem_new(cpu_env,
-                                      offsetof(CPUNios2State, regs[i]),
+    for (int i = 0; i < NUM_GP_REGS; i++) {
+        cpu_crs_R[i] = tcg_global_mem_new(crs, 4 * i, gr_regnames[i]);
+    }
+
+#define offsetof_regs0(N)  offsetof(CPUNios2State, shadow_regs[0][N])
+#else
+#define offsetof_regs0(N)  offsetof(CPUNios2State, regs[N])
+#endif
+
+    for (int i = 0; i < NUM_GP_REGS; i++) {
+        cpu_R[i] = tcg_global_mem_new(cpu_env, offsetof_regs0(i),
                                       gr_regnames[i]);
     }
+
+#undef offsetof_regs0
+
     cpu_pc = tcg_global_mem_new(cpu_env,
                                 offsetof(CPUNios2State, pc), "pc");
 }
-- 
2.34.1



  parent reply	other threads:[~2022-04-26 19:16 UTC|newest]

Thread overview: 70+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-04-26 18:17 [PULL 00/68] nios2 patch queue Richard Henderson
2022-04-26 18:18 ` [PULL 01/68] linux-user/nios2: Hoist pc advance to the top of EXCP_TRAP Richard Henderson
2022-04-26 18:18 ` [PULL 02/68] linux-user/nios2: Fix clone child return Richard Henderson
2022-04-26 18:18 ` [PULL 03/68] linux-user/nios2: Drop syscall 0 "workaround" Richard Henderson
2022-04-26 18:18 ` [PULL 04/68] linux-user/nios2: Adjust error return Richard Henderson
2022-04-26 18:18 ` [PULL 05/68] linux-user/nios2: Handle special qemu syscall return values Richard Henderson
2022-04-26 18:18 ` [PULL 06/68] linux-user/nios2: Remove do_sigreturn Richard Henderson
2022-04-26 18:18 ` [PULL 07/68] linux-user/nios2: Use QEMU_ESIGRETURN from do_rt_sigreturn Richard Henderson
2022-04-26 18:18 ` [PULL 08/68] tests/tcg/nios2: Re-enable linux-user tests Richard Henderson
2022-04-26 18:18 ` [PULL 09/68] target/nios2: Remove user-only nios2_cpu_do_interrupt Richard Henderson
2022-04-26 18:18 ` [PULL 10/68] target/nios2: Remove nios2_cpu_record_sigsegv Richard Henderson
2022-04-26 18:18 ` [PULL 11/68] target/nios2: Build helper.c for system only Richard Henderson
2022-04-26 18:18 ` [PULL 12/68] linux-user/nios2: Use force_sig_fault for EXCP_DEBUG Richard Henderson
2022-04-26 18:18 ` [PULL 13/68] target/nios2: Check supervisor on eret Richard Henderson
2022-04-26 18:18 ` [PULL 14/68] target/nios2: Stop generating code if gen_check_supervisor fails Richard Henderson
2022-04-26 18:18 ` [PULL 15/68] target/nios2: Add NUM_GP_REGS and NUM_CP_REGS Richard Henderson
2022-04-26 18:18 ` [PULL 16/68] target/nios2: Split PC out of env->regs[] Richard Henderson
2022-04-26 18:18 ` [PULL 17/68] target/nios2: Split out helper for eret instruction Richard Henderson
2022-04-26 18:18 ` [PULL 18/68] target/nios2: Fix BRET instruction Richard Henderson
2022-04-26 18:18 ` [PULL 19/68] target/nios2: Do not create TCGv for control registers Richard Henderson
2022-04-26 18:18 ` [PULL 20/68] linux-user/nios2: Only initialize SP and PC in target_cpu_copy_regs Richard Henderson
2022-04-26 18:18 ` [PULL 21/68] target/nios2: Remove cpu_interrupts_enabled Richard Henderson
2022-04-26 18:18 ` [PULL 22/68] target/nios2: Split control registers away from general registers Richard Henderson
2022-04-26 18:18 ` [PULL 23/68] target/nios2: Clean up nios2_cpu_dump_state Richard Henderson
2022-04-26 18:18 ` [PULL 24/68] target/nios2: Use hw/registerfields.h for CR_STATUS fields Richard Henderson
2022-04-26 18:18 ` [PULL 25/68] target/nios2: Use hw/registerfields.h for CR_EXCEPTION fields Richard Henderson
2022-04-26 18:18 ` [PULL 26/68] target/nios2: Use hw/registerfields.h for CR_TLBADDR fields Richard Henderson
2022-04-26 18:18 ` [PULL 27/68] target/nios2: Use hw/registerfields.h for CR_TLBACC fields Richard Henderson
2022-04-26 18:18 ` [PULL 28/68] target/nios2: Rename CR_TLBMISC_WR to CR_TLBMISC_WE Richard Henderson
2022-04-26 18:18 ` [PULL 29/68] target/nios2: Use hw/registerfields.h for CR_TLBMISC fields Richard Henderson
2022-04-26 18:18 ` [PULL 30/68] target/nios2: Move R_FOO and CR_BAR into enumerations Richard Henderson
2022-04-26 18:18 ` [PULL 31/68] target/nios2: Create EXCP_SEMIHOST for semi-hosting Richard Henderson
2022-04-26 18:18 ` [PULL 32/68] target/nios2: Clean up nios2_cpu_do_interrupt Richard Henderson
2022-04-26 18:18 ` [PULL 33/68] target/nios2: Hoist CPU_LOG_INT logging Richard Henderson
2022-04-26 18:18 ` [PULL 34/68] target/nios2: Handle EXCP_UNALIGN and EXCP_UNALIGND Richard Henderson
2022-04-26 18:18 ` [PULL 35/68] target/nios2: Cleanup set of CR_EXCEPTION for do_interrupt Richard Henderson
2022-04-26 18:18 ` [PULL 36/68] target/nios2: Clean up handling of tlbmisc in do_exception Richard Henderson
2022-04-26 18:18 ` [PULL 37/68] target/nios2: Prevent writes to read-only or reserved control fields Richard Henderson
2022-04-26 18:18 ` [PULL 38/68] target/nios2: Implement cpuid Richard Henderson
2022-04-26 18:18 ` [PULL 39/68] target/nios2: Implement CR_STATUS.RSIE Richard Henderson
2022-04-26 18:18 ` [PULL 40/68] target/nios2: Remove CPU_INTERRUPT_NMI Richard Henderson
2022-04-26 18:18 ` [PULL 41/68] target/nios2: Support division error exception Richard Henderson
2022-04-26 18:18 ` [PULL 42/68] target/nios2: Use tcg_constant_tl Richard Henderson
2022-04-26 18:18 ` [PULL 43/68] target/nios2: Split out named structs for [IRJ]_TYPE Richard Henderson
2022-04-26 18:18 ` [PULL 44/68] target/nios2: Split out helpers for gen_i_cmpxx Richard Henderson
2022-04-26 18:18 ` [PULL 45/68] target/nios2: Split out helpers for gen_i_math_logic Richard Henderson
2022-04-26 18:18 ` [PULL 46/68] target/nios2: Split out helpers for gen_r_math_logic Richard Henderson
2022-04-26 18:18 ` [PULL 47/68] target/nios2: Split out helpers for gen_rr_mul_high Richard Henderson
2022-04-26 18:18 ` [PULL 48/68] target/nios2: Split out helpers for gen_rr_shift Richard Henderson
2022-04-26 18:18 ` [PULL 49/68] target/nios2: Introduce dest_gpr Richard Henderson
2022-04-26 18:18 ` [PULL 50/68] target/nios2: Drop CR_STATUS_EH from tb->flags Richard Henderson
2022-04-26 18:18 ` [PULL 51/68] target/nios2: Enable unaligned traps for system mode Richard Henderson
2022-04-26 18:18 ` [PULL 52/68] target/nios2: Create gen_jumpr Richard Henderson
2022-04-26 18:18 ` [PULL 53/68] target/nios2: Hoist set of is_jmp into gen_goto_tb Richard Henderson
2022-04-26 18:18 ` [PULL 54/68] target/nios2: Use gen_goto_tb for DISAS_TOO_MANY Richard Henderson
2022-04-26 18:18 ` [PULL 55/68] target/nios2: Use tcg_gen_lookup_and_goto_ptr Richard Henderson
2022-04-26 18:18 ` [PULL 56/68] target/nios2: Implement Misaligned destination exception Richard Henderson
2022-04-26 18:18 ` Richard Henderson [this message]
2022-04-26 18:18 ` [PULL 58/68] target/nios2: Implement rdprs, wrprs Richard Henderson
2022-04-26 18:18 ` [PULL 59/68] target/nios2: Update helper_eret for shadow registers Richard Henderson
2022-04-26 18:18 ` [PULL 60/68] target/nios2: Implement EIC interrupt processing Richard Henderson
2022-04-26 18:19 ` [PULL 61/68] target/nios2: Advance pc when raising exceptions Richard Henderson
2022-04-26 18:19 ` [PULL 62/68] linux-user/nios2: Handle various SIGILL exceptions Richard Henderson
2022-04-26 18:19 ` [PULL 63/68] hw/intc: Vectored Interrupt Controller (VIC) Richard Henderson
2022-04-26 18:19 ` [PULL 64/68] hw/nios2: Introduce Nios2MachineState Richard Henderson
2022-04-26 18:19 ` [PULL 65/68] hw/nios2: Move memory regions into Nios2Machine Richard Henderson
2022-04-26 18:19 ` [PULL 66/68] hw/nios2: Machine with a Vectored Interrupt Controller Richard Henderson
2022-04-26 18:19 ` [PULL 67/68] tests/tcg/nios2: Add semihosting multiarch tests Richard Henderson
2022-04-26 18:19 ` [PULL 68/68] tests/tcg/nios2: Add test-shadow-1 Richard Henderson
2022-04-26 21:38 ` [PULL 00/68] nios2 patch queue Richard Henderson

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=20220426181907.103691-58-richard.henderson@linaro.org \
    --to=richard.henderson@linaro.org \
    --cc=peter.maydell@linaro.org \
    --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.