[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PULL 15/41] target/arm: Record correct opcode fields in cpreg for E2H a
|
From: |
Peter Maydell |
|
Subject: |
[PULL 15/41] target/arm: Record correct opcode fields in cpreg for E2H aliases |
|
Date: |
Thu, 11 Jan 2024 11:04:39 +0000 |
For FEAT_VHE, we define a set of register aliases, so that for instance:
* the SCTLR_EL1 either accesses the real SCTLR_EL1, or (if E2H is 1)
SCTLR_EL2
* a new SCTLR_EL12 register accesses SCTLR_EL1 if E2H is 1
However when we create the 'new_reg' cpreg struct for the SCTLR_EL12
register, we duplicate the information in the SCTLR_EL1 cpreg, which
means the opcode fields are those of SCTLR_EL1, not SCTLR_EL12. This
is a problem for code which looks at the cpreg opcode fields to
determine behaviour (e.g. in access_check_cp_reg()). In practice
the current checks we do there don't intersect with the *_EL12
registers, but for FEAT_NV this will become a problem.
Write the correct values from the encoding into the new_reg struct.
This restores the invariant that the cpreg that you get back
from the hashtable has opcode fields that match the key you used
to retrieve it.
When we call the readfn or writefn for the target register, we
pass it the cpreg struct for that target register, not the one
for the alias, in case the readfn/writefn want to look at the
opcode fields to determine behaviour. This means we need to
interpose custom read/writefns for the e12 aliases.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Tested-by: Miguel Luis <miguel.luis@oracle.com>
---
target/arm/helper.c | 35 +++++++++++++++++++++++++++++++++++
1 file changed, 35 insertions(+)
diff --git a/target/arm/helper.c b/target/arm/helper.c
index dc4b4123e00..dc2471eda7e 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -6522,6 +6522,19 @@ static void el2_e2h_write(CPUARMState *env, const
ARMCPRegInfo *ri,
writefn(env, ri, value);
}
+static uint64_t el2_e2h_e12_read(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+ /* Pass the EL1 register accessor its ri, not the EL12 alias ri */
+ return ri->orig_readfn(env, ri->opaque);
+}
+
+static void el2_e2h_e12_write(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t value)
+{
+ /* Pass the EL1 register accessor its ri, not the EL12 alias ri */
+ return ri->orig_writefn(env, ri->opaque, value);
+}
+
static void define_arm_vh_e2h_redirects_aliases(ARMCPU *cpu)
{
struct E2HAlias {
@@ -6621,6 +6634,28 @@ static void define_arm_vh_e2h_redirects_aliases(ARMCPU
*cpu)
new_reg->type |= ARM_CP_ALIAS;
/* Remove PL1/PL0 access, leaving PL2/PL3 R/W in place. */
new_reg->access &= PL2_RW | PL3_RW;
+ /* The new_reg op fields are as per new_key, not the target reg */
+ new_reg->crn = (a->new_key & CP_REG_ARM64_SYSREG_CRN_MASK)
+ >> CP_REG_ARM64_SYSREG_CRN_SHIFT;
+ new_reg->crm = (a->new_key & CP_REG_ARM64_SYSREG_CRM_MASK)
+ >> CP_REG_ARM64_SYSREG_CRM_SHIFT;
+ new_reg->opc0 = (a->new_key & CP_REG_ARM64_SYSREG_OP0_MASK)
+ >> CP_REG_ARM64_SYSREG_OP0_SHIFT;
+ new_reg->opc1 = (a->new_key & CP_REG_ARM64_SYSREG_OP1_MASK)
+ >> CP_REG_ARM64_SYSREG_OP1_SHIFT;
+ new_reg->opc2 = (a->new_key & CP_REG_ARM64_SYSREG_OP2_MASK)
+ >> CP_REG_ARM64_SYSREG_OP2_SHIFT;
+ new_reg->opaque = src_reg;
+ new_reg->orig_readfn = src_reg->readfn ?: raw_read;
+ new_reg->orig_writefn = src_reg->writefn ?: raw_write;
+ if (!new_reg->raw_readfn) {
+ new_reg->raw_readfn = raw_read;
+ }
+ if (!new_reg->raw_writefn) {
+ new_reg->raw_writefn = raw_write;
+ }
+ new_reg->readfn = el2_e2h_e12_read;
+ new_reg->writefn = el2_e2h_e12_write;
ok = g_hash_table_insert(cpu->cp_regs,
(gpointer)(uintptr_t)a->new_key, new_reg);
--
2.34.1
- Re: [PULL 08/41] target/arm: Set CTR_EL0.{IDC,DIC} for the 'max' CPU, (continued)
[PULL 11/41] target/arm: Implement HCR_EL2.AT handling, Peter Maydell, 2024/01/11
[PULL 10/41] target/arm: Handle HCR_EL2 accesses for bits introduced with FEAT_NV, Peter Maydell, 2024/01/11
[PULL 13/41] target/arm: Always honour HCR_EL2.TSC when HCR_EL2.NV is set, Peter Maydell, 2024/01/11
[PULL 16/41] target/arm: *_EL12 registers should UNDEF when HCR_EL2.E2H is 0, Peter Maydell, 2024/01/11
[PULL 28/41] target/arm: Handle HCR_EL2 accesses for FEAT_NV2 bits, Peter Maydell, 2024/01/11
[PULL 25/41] target/arm: Treat LDTR* and STTR* as LDR/STR when NV, NV1 is 1, 1, Peter Maydell, 2024/01/11
[PULL 23/41] target/arm: Always use arm_pan_enabled() when checking if PAN is enabled, Peter Maydell, 2024/01/11
[PULL 15/41] target/arm: Record correct opcode fields in cpreg for E2H aliases,
Peter Maydell <=
[PULL 34/41] target/arm: Mark up VNCR offsets (offsets 0x0..0xff), Peter Maydell, 2024/01/11
[PULL 33/41] target/arm: Report VNCR_EL2 based faults correctly, Peter Maydell, 2024/01/11
[PULL 29/41] target/arm: Implement VNCR_EL2 register, Peter Maydell, 2024/01/11
[PULL 32/41] target/arm: Implement FEAT_NV2 redirection of sysregs to RAM, Peter Maydell, 2024/01/11
[PULL 37/41] target/arm: Mark up VNCR offsets (offsets >= 0x200, except GIC), Peter Maydell, 2024/01/11
[PULL 36/41] target/arm: Mark up VNCR offsets (offsets 0x168..0x1f8), Peter Maydell, 2024/01/11
[PULL 12/41] target/arm: Enable trapping of ERET for FEAT_NV, Peter Maydell, 2024/01/11
[PULL 19/41] target/arm: Trap sysreg accesses for FEAT_NV, Peter Maydell, 2024/01/11
[PULL 22/41] target/arm: Trap registers when HCR_EL2.{NV, NV1} == {1, 1}, Peter Maydell, 2024/01/11
[PULL 27/41] target/arm: Add FEAT_NV to max, neoverse-n2, neoverse-v1 CPUs, Peter Maydell, 2024/01/11