[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH 1/2] target/ppc: Implement the DEXCR and HDEXCR

From: Daniel Henrique Barboza
Subject: Re: [PATCH 1/2] target/ppc: Implement the DEXCR and HDEXCR
Date: Mon, 28 Nov 2022 17:33:22 -0300
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.4.1

On 11/24/22 02:51, Nicholas Miehlbradt wrote:
Define the DEXCR and HDEXCR as special purpose registers.

Each register occupies two SPR indicies, one which can be read in an
unprivileged state and one which can be modified in the appropriate
priviliged state, however both indicies refer to the same underlying

Note that the ISA uses the abbreviation UDEXCR in two different
contexts: the userspace DEXCR, the SPR index which can be read from
userspace (implemented in this patch), and the ultravisor DEXCR, the
equivalent register for the ultravisor state (not implemented).

Signed-off-by: Nicholas Miehlbradt <nicholas@linux.ibm.com>
  target/ppc/cpu.h        | 19 +++++++++++++++++++
  target/ppc/cpu_init.c   | 25 +++++++++++++++++++++++++
  target/ppc/spr_common.h |  1 +
  target/ppc/translate.c  |  9 +++++++++
  4 files changed, 54 insertions(+)

diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 81d4263a07..0ed9f2ae35 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -1068,6 +1068,21 @@ struct ppc_radix_page_info {
      uint32_t entries[PPC_PAGE_SIZES_MAX_SZ];
+/* Dynamic Execution Control Register */
+#define DEXCR_ASPECT(name, num)                    \
+FIELD(DEXCR, PNH_##name, PPC_BIT_NR(num), 1)       \
+FIELD(DEXCR, PRO_##name, PPC_BIT_NR(num + 32), 1)  \
+FIELD(HDEXCR, HNU_##name, PPC_BIT_NR(num), 1)      \
+FIELD(HDEXCR, ENF_##name, PPC_BIT_NR(num + 32), 1) \
  /* The whole PowerPC CPU context */
@@ -1674,9 +1689,11 @@ void ppc_compat_add_property(Object *obj, const char *name,
  #define SPR_BOOKE_GIVOR13     (0x1BC)
  #define SPR_BOOKE_GIVOR14     (0x1BD)
  #define SPR_TIR               (0x1BE)
+#define SPR_UHDEXCR           (0x1C7)
  #define SPR_PTCR              (0x1D0)
  #define SPR_HASHKEYR          (0x1D4)
  #define SPR_HASHPKEYR         (0x1D5)
+#define SPR_HDEXCR            (0x1D7)
  #define SPR_BOOKE_SPEFSCR     (0x200)
  #define SPR_Exxx_BBEAR        (0x201)
  #define SPR_Exxx_BBTAR        (0x202)
@@ -1865,8 +1882,10 @@ void ppc_compat_add_property(Object *obj, const char 
  #define SPR_RCPU_L2U_RA2      (0x32A)
  #define SPR_MPC_MD_DBRAM1     (0x32A)
  #define SPR_RCPU_L2U_RA3      (0x32B)
+#define SPR_UDEXCR            (0x32C)
  #define SPR_TAR               (0x32F)
  #define SPR_ASDR              (0x330)
+#define SPR_DEXCR             (0x33C)
  #define SPR_IC                (0x350)
  #define SPR_VTB               (0x351)
  #define SPR_MMCRC             (0x353)
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index cbf0081374..d6b950feb6 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -5727,6 +5727,30 @@ static void register_power10_hash_sprs(CPUPPCState *env)
+static void register_power10_dexcr_sprs(CPUPPCState *env)
+    spr_register(env, SPR_DEXCR, "DEXCR",
+            &spr_read_generic, &spr_write_dexcr,
+            0);
+    spr_register(env, SPR_UDEXCR, "DEXCR",
+            &spr_read_generic, SPR_NOACCESS,
+            &spr_read_generic, SPR_NOACCESS,
+            0);
+    spr_register_hv(env, SPR_HDEXCR, "HDEXCR",
+            &spr_read_generic, &spr_write_dexcr,
+            0);
+    spr_register(env, SPR_UHDEXCR, "HDEXCR",
+            &spr_read_generic, SPR_NOACCESS,
+            &spr_read_generic, SPR_NOACCESS,
+            0);
   * Initialize PMU counter overflow timers for Power8 and
   * newer Power chips when using TCG.
@@ -6402,6 +6426,7 @@ static void init_proc_POWER10(CPUPPCState *env)
+    register_power10_dexcr_sprs(env);
/* FIXME: Filter fields properly based on privilege level */
      spr_register_kvm_hv(env, SPR_PSSCR, "PSSCR", NULL, NULL, NULL, NULL,
diff --git a/target/ppc/spr_common.h b/target/ppc/spr_common.h
index b5a5bc6895..3cfa500250 100644
--- a/target/ppc/spr_common.h
+++ b/target/ppc/spr_common.h
@@ -195,6 +195,7 @@ void spr_read_ebb_upper32(DisasContext *ctx, int gprn, int 
  void spr_write_ebb_upper32(DisasContext *ctx, int sprn, int gprn);
  void spr_write_hmer(DisasContext *ctx, int sprn, int gprn);
  void spr_write_lpcr(DisasContext *ctx, int sprn, int gprn);
+void spr_write_dexcr(DisasContext *ctx, int sprn, int gprn);
void register_low_BATs(CPUPPCState *env);
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 19c1d17cb0..24e9e2fece 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -1249,6 +1249,15 @@ void spr_write_ebb_upper32(DisasContext *ctx, int sprn, 
int gprn)
      gen_fscr_facility_check(ctx, SPR_FSCR, FSCR_EBB, sprn, FSCR_IC_EBB);
      spr_write_prev_upper32(ctx, sprn, gprn);
+void spr_write_dexcr(DisasContext *ctx, int sprn, int gprn)
+    TCGv t0 = tcg_temp_new();
+    spr_write_generic(ctx, sprn, gprn);
+    tcg_gen_ext32u_tl(t0, cpu_gpr[gprn]);
+    gen_store_spr(sprn - 16, t0);
+    tcg_temp_free(t0);

IIUC you're writing sprn as is, then zeroing bits 0-31 and writing it to
sprn - 16, because of this comment in PowerISA:

This register can be read and written in privileged state
using SPR 828. Bits 32:63 of the register can only be
read in problem state using SPR 812; mfspr 812
returns 0s for bits 0:31.

I am no longer familiar with Power10 internals and can't say whether
sprn 812/455 is writable in problem state. You didn't create a write
function for it, so I'll assume that problem state can't write sprn
812/455 and can read only the higher bits.

I'll note that there's another way of doing it: instead of doing two
writes and clearing 32 bits every time sprn 828/471 is written, you can
also just do a regular write and, instead, implement spr_read_dexcr_ureg
that would clear bits 0-31 when problem state reads it. Depending on
how frequent problem state reads the reg versus priv state writes it,
we'll spare a few cycles in the emulation. I did something similar in
spr_read_MMCR0_ureg if you want to take a look.

All that said, what is being done here also works. I'll just ask you to
put a comment in spr_write_dexcr() explaining why you're clearing bits
and writing another sprn-16 in it.



#define GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \

reply via email to

[Prev in Thread] Current Thread [Next in Thread]