Skip to content

Commit 5850e03

Browse files
rth7680pm215
authored andcommitted
target/arm: Redirect VHE FOO_EL12 to FOO_EL1 during translation
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> [PMM: expanded a comment slightly] Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
1 parent 34577fc commit 5850e03

File tree

4 files changed

+25
-68
lines changed

4 files changed

+25
-68
lines changed

target/arm/cpregs.h

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -942,8 +942,12 @@ struct ARMCPRegInfo {
942942
*/
943943
uint32_t vhe_redir_to_el2;
944944

945-
/* This is used only by VHE. */
946-
void *opaque;
945+
/*
946+
* With VHE, with E2H, at EL2+, access to this EL02/EL12 reg
947+
* redirects to the EL0/EL1 reg with the specified key.
948+
*/
949+
uint32_t vhe_redir_to_el01;
950+
947951
/*
948952
* Value of this register, if it is ARM_CP_CONST. Otherwise, if
949953
* fieldoffset is non-zero, the reset value of the register.
@@ -1011,20 +1015,6 @@ struct ARMCPRegInfo {
10111015
* fieldoffset is 0 then no reset will be done.
10121016
*/
10131017
CPResetFn *resetfn;
1014-
1015-
/*
1016-
* "Original" readfn, writefn, accessfn.
1017-
* For ARMv8.1-VHE register aliases, we overwrite the read/write
1018-
* accessor functions of various EL1/EL0 to perform the runtime
1019-
* check for which sysreg should actually be modified, and then
1020-
* forwards the operation. Before overwriting the accessors,
1021-
* the original function is copied here, so that accesses that
1022-
* really do go to the EL1/EL0 version proceed normally.
1023-
* (The corresponding EL2 register is linked via opaque.)
1024-
*/
1025-
CPReadFn *orig_readfn;
1026-
CPWriteFn *orig_writefn;
1027-
CPAccessFn *orig_accessfn;
10281018
};
10291019

10301020
void define_one_arm_cp_reg(ARMCPU *cpu, const ARMCPRegInfo *regs);

target/arm/gdbstub.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,8 @@ static int arm_gdb_get_sysreg(CPUState *cs, GByteArray *buf, int reg)
253253
(arm_hcr_el2_eff(env) & HCR_E2H) &&
254254
arm_current_el(env) == 2) {
255255
ri = get_arm_cp_reginfo(cpu->cp_regs, ri->vhe_redir_to_el2);
256+
} else if (ri->vhe_redir_to_el01) {
257+
ri = get_arm_cp_reginfo(cpu->cp_regs, ri->vhe_redir_to_el01);
256258
}
257259
return gdb_get_reg64(buf, (uint64_t)read_raw_cp_reg(env, ri));
258260
case MO_32:

target/arm/helper.c

Lines changed: 5 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -4417,42 +4417,6 @@ static CPAccessResult access_el1nvvct(CPUARMState *env, const ARMCPRegInfo *ri,
44174417
return e2h_access(env, ri, isread);
44184418
}
44194419

4420-
static uint64_t el2_e2h_e12_read(CPUARMState *env, const ARMCPRegInfo *ri)
4421-
{
4422-
/* Pass the EL1 register accessor its ri, not the EL12 alias ri */
4423-
return ri->orig_readfn(env, ri->opaque);
4424-
}
4425-
4426-
static void el2_e2h_e12_write(CPUARMState *env, const ARMCPRegInfo *ri,
4427-
uint64_t value)
4428-
{
4429-
/* Pass the EL1 register accessor its ri, not the EL12 alias ri */
4430-
return ri->orig_writefn(env, ri->opaque, value);
4431-
}
4432-
4433-
static CPAccessResult el2_e2h_e12_access(CPUARMState *env,
4434-
const ARMCPRegInfo *ri,
4435-
bool isread)
4436-
{
4437-
if (arm_current_el(env) == 1) {
4438-
/*
4439-
* This must be a FEAT_NV access (will either trap or redirect
4440-
* to memory). None of the registers with _EL12 aliases want to
4441-
* apply their trap controls for this kind of access, so don't
4442-
* call the orig_accessfn or do the "UNDEF when E2H is 0" check.
4443-
*/
4444-
return CP_ACCESS_OK;
4445-
}
4446-
/* FOO_EL12 aliases only exist when E2H is 1; otherwise they UNDEF */
4447-
if (!(arm_hcr_el2_eff(env) & HCR_E2H)) {
4448-
return CP_ACCESS_UNDEFINED;
4449-
}
4450-
if (ri->orig_accessfn) {
4451-
return ri->orig_accessfn(env, ri->opaque, isread);
4452-
}
4453-
return CP_ACCESS_OK;
4454-
}
4455-
44564420
static void define_arm_vh_e2h_redirects_aliases(ARMCPU *cpu)
44574421
{
44584422
struct E2HAlias {
@@ -4541,9 +4505,6 @@ static void define_arm_vh_e2h_redirects_aliases(ARMCPU *cpu)
45414505
g_assert(strcmp(src_reg->name, a->src_name) == 0);
45424506
g_assert(strcmp(dst_reg->name, a->dst_name) == 0);
45434507

4544-
/* None of the core system registers use opaque; we will. */
4545-
g_assert(src_reg->opaque == NULL);
4546-
45474508
/* Create alias before redirection so we dup the right data. */
45484509
new_reg = g_memdup(src_reg, sizeof(ARMCPRegInfo));
45494510

@@ -4562,19 +4523,11 @@ static void define_arm_vh_e2h_redirects_aliases(ARMCPU *cpu)
45624523
>> CP_REG_ARM64_SYSREG_OP1_SHIFT;
45634524
new_reg->opc2 = (a->new_key & CP_REG_ARM64_SYSREG_OP2_MASK)
45644525
>> CP_REG_ARM64_SYSREG_OP2_SHIFT;
4565-
new_reg->opaque = src_reg;
4566-
new_reg->orig_readfn = src_reg->readfn ?: raw_read;
4567-
new_reg->orig_writefn = src_reg->writefn ?: raw_write;
4568-
new_reg->orig_accessfn = src_reg->accessfn;
4569-
if (!new_reg->raw_readfn) {
4570-
new_reg->raw_readfn = raw_read;
4571-
}
4572-
if (!new_reg->raw_writefn) {
4573-
new_reg->raw_writefn = raw_write;
4574-
}
4575-
new_reg->readfn = el2_e2h_e12_read;
4576-
new_reg->writefn = el2_e2h_e12_write;
4577-
new_reg->accessfn = el2_e2h_e12_access;
4526+
new_reg->vhe_redir_to_el01 = a->src_key;
4527+
new_reg->readfn = NULL;
4528+
new_reg->writefn = NULL;
4529+
new_reg->accessfn = NULL;
4530+
new_reg->fieldoffset = 0;
45784531

45794532
/*
45804533
* If the _EL1 register is redirected to memory by FEAT_NV2,

target/arm/tcg/translate-a64.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2580,6 +2580,18 @@ static void handle_sys(DisasContext *s, bool isread,
25802580
*/
25812581
key = ri->vhe_redir_to_el2;
25822582
ri = redirect_cpreg(s, key, isread);
2583+
} else if (ri->vhe_redir_to_el01 && s->current_el >= 2) {
2584+
/*
2585+
* This is one of the FOO_EL12 or FOO_EL02 registers.
2586+
* With !E2H, they all UNDEF.
2587+
* With E2H, from EL2 or EL3, they redirect to FOO_EL1/FOO_EL0.
2588+
*/
2589+
if (!s->e2h) {
2590+
gen_sysreg_undef(s, isread, op0, op1, op2, crn, crm, rt);
2591+
return;
2592+
}
2593+
key = ri->vhe_redir_to_el01;
2594+
ri = redirect_cpreg(s, key, isread);
25832595
}
25842596

25852597
if (ri->accessfn || (ri->fgt && s->fgt_active)) {

0 commit comments

Comments
 (0)