From: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
target/arm/cpregs.h | 6 ++++
target/arm/gdbstub.c | 5 ++++
target/arm/helper.c | 53 +---------------------------------
target/arm/tcg/translate-a64.c | 9 ++++++
4 files changed, 21 insertions(+), 52 deletions(-)
diff --git a/target/arm/cpregs.h b/target/arm/cpregs.h
index 08fc42ea571..eac0cb9ebf1 100644
--- a/target/arm/cpregs.h
+++ b/target/arm/cpregs.h
@@ -936,6 +936,12 @@ struct ARMCPRegInfo {
*/
uint32_t nv2_redirect_offset;
+ /*
+ * With VHE, with E2H, at EL2, access to this EL0/EL1 reg redirects
+ * to the EL2 reg with the specified key.
+ */
+ uint32_t vhe_redir_to_el2;
+
/* This is used only by VHE. */
void *opaque;
/*
diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c
index 4e2ac49b6a9..87d40d4366b 100644
--- a/target/arm/gdbstub.c
+++ b/target/arm/gdbstub.c
@@ -249,6 +249,11 @@ static int arm_gdb_get_sysreg(CPUState *cs, GByteArray *buf, int reg)
if (ri) {
switch (cpreg_field_type(ri)) {
case MO_64:
+ if (ri->vhe_redir_to_el2 &&
+ (arm_hcr_el2_eff(env) & HCR_E2H) &&
+ arm_current_el(env) == 2) {
+ ri = get_arm_cp_reginfo(cpu->cp_regs, ri->vhe_redir_to_el2);
+ }
return gdb_get_reg64(buf, (uint64_t)read_raw_cp_reg(env, ri));
case MO_32:
return gdb_get_reg32(buf, (uint32_t)read_raw_cp_reg(env, ri));
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 18066b0c5dc..87a32e363e9 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -4417,47 +4417,6 @@ static CPAccessResult access_el1nvvct(CPUARMState *env, const ARMCPRegInfo *ri,
return e2h_access(env, ri, isread);
}
-/* Test if system register redirection is to occur in the current state. */
-static bool redirect_for_e2h(CPUARMState *env)
-{
- return arm_current_el(env) == 2 && (arm_hcr_el2_eff(env) & HCR_E2H);
-}
-
-static uint64_t el2_e2h_read(CPUARMState *env, const ARMCPRegInfo *ri)
-{
- CPReadFn *readfn;
-
- if (redirect_for_e2h(env)) {
- /* Switch to the saved EL2 version of the register. */
- ri = ri->opaque;
- readfn = ri->readfn;
- } else {
- readfn = ri->orig_readfn;
- }
- if (readfn == NULL) {
- readfn = raw_read;
- }
- return readfn(env, ri);
-}
-
-static void el2_e2h_write(CPUARMState *env, const ARMCPRegInfo *ri,
- uint64_t value)
-{
- CPWriteFn *writefn;
-
- if (redirect_for_e2h(env)) {
- /* Switch to the saved EL2 version of the register. */
- ri = ri->opaque;
- writefn = ri->writefn;
- } else {
- writefn = ri->orig_writefn;
- }
- if (writefn == NULL) {
- writefn = raw_write;
- }
- 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 */
@@ -4632,17 +4591,7 @@ static void define_arm_vh_e2h_redirects_aliases(ARMCPU *cpu)
(gpointer)(uintptr_t)a->new_key, new_reg);
g_assert(ok);
- src_reg->opaque = dst_reg;
- src_reg->orig_readfn = src_reg->readfn ?: raw_read;
- src_reg->orig_writefn = src_reg->writefn ?: raw_write;
- if (!src_reg->raw_readfn) {
- src_reg->raw_readfn = raw_read;
- }
- if (!src_reg->raw_writefn) {
- src_reg->raw_writefn = raw_write;
- }
- src_reg->readfn = el2_e2h_read;
- src_reg->writefn = el2_e2h_write;
+ src_reg->vhe_redir_to_el2 = a->dst_key;
}
}
#endif
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index c0fa2137b63..3ef24fb0c3d 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -2573,6 +2573,15 @@ static void handle_sys(DisasContext *s, bool isread,
}
}
+ if (ri->vhe_redir_to_el2 && s->current_el == 2 && s->e2h) {
+ /*
+ * This one of the FOO_EL1 registers which redirect to FOO_EL2
+ * from EL2 when HCR_EL2.E2H is set.
+ */
+ key = ri->vhe_redir_to_el2;
+ ri = redirect_cpreg(s, key, isread);
+ }
+
if (ri->accessfn || (ri->fgt && s->fgt_active)) {
/* Emit code to perform further access permissions checks at
* runtime; this may result in an exception.
--
2.43.0