[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PULL 30/48] target/arm: Add VHE timer register redirection and aliasing
From: |
Peter Maydell |
Subject: |
[PULL 30/48] target/arm: Add VHE timer register redirection and aliasing |
Date: |
Fri, 7 Feb 2020 14:33:25 +0000 |
From: Richard Henderson <address@hidden>
Apart from the wholesale redirection that HCR_EL2.E2H performs
for EL2, there's a separate redirection specific to the timers
that happens for EL0 when running in the EL2&0 regime.
Tested-by: Alex Bennée <address@hidden>
Reviewed-by: Peter Maydell <address@hidden>
Signed-off-by: Richard Henderson <address@hidden>
Message-id: address@hidden
Signed-off-by: Peter Maydell <address@hidden>
---
target/arm/helper.c | 181 +++++++++++++++++++++++++++++++++++++++++---
1 file changed, 169 insertions(+), 12 deletions(-)
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 8f7620f2434..cfa6ce59dc8 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -2695,6 +2695,70 @@ static void gt_phys_ctl_write(CPUARMState *env, const
ARMCPRegInfo *ri,
gt_ctl_write(env, ri, GTIMER_PHYS, value);
}
+static int gt_phys_redir_timeridx(CPUARMState *env)
+{
+ switch (arm_mmu_idx(env)) {
+ case ARMMMUIdx_E20_0:
+ case ARMMMUIdx_E20_2:
+ return GTIMER_HYP;
+ default:
+ return GTIMER_PHYS;
+ }
+}
+
+static int gt_virt_redir_timeridx(CPUARMState *env)
+{
+ switch (arm_mmu_idx(env)) {
+ case ARMMMUIdx_E20_0:
+ case ARMMMUIdx_E20_2:
+ return GTIMER_HYPVIRT;
+ default:
+ return GTIMER_VIRT;
+ }
+}
+
+static uint64_t gt_phys_redir_cval_read(CPUARMState *env,
+ const ARMCPRegInfo *ri)
+{
+ int timeridx = gt_phys_redir_timeridx(env);
+ return env->cp15.c14_timer[timeridx].cval;
+}
+
+static void gt_phys_redir_cval_write(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t value)
+{
+ int timeridx = gt_phys_redir_timeridx(env);
+ gt_cval_write(env, ri, timeridx, value);
+}
+
+static uint64_t gt_phys_redir_tval_read(CPUARMState *env,
+ const ARMCPRegInfo *ri)
+{
+ int timeridx = gt_phys_redir_timeridx(env);
+ return gt_tval_read(env, ri, timeridx);
+}
+
+static void gt_phys_redir_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t value)
+{
+ int timeridx = gt_phys_redir_timeridx(env);
+ gt_tval_write(env, ri, timeridx, value);
+}
+
+static uint64_t gt_phys_redir_ctl_read(CPUARMState *env,
+ const ARMCPRegInfo *ri)
+{
+ int timeridx = gt_phys_redir_timeridx(env);
+ return env->cp15.c14_timer[timeridx].ctl;
+}
+
+static void gt_phys_redir_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t value)
+{
+ int timeridx = gt_phys_redir_timeridx(env);
+ gt_ctl_write(env, ri, timeridx, value);
+}
+
static void gt_virt_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri)
{
gt_timer_reset(env, ri, GTIMER_VIRT);
@@ -2733,6 +2797,48 @@ static void gt_cntvoff_write(CPUARMState *env, const
ARMCPRegInfo *ri,
gt_recalc_timer(cpu, GTIMER_VIRT);
}
+static uint64_t gt_virt_redir_cval_read(CPUARMState *env,
+ const ARMCPRegInfo *ri)
+{
+ int timeridx = gt_virt_redir_timeridx(env);
+ return env->cp15.c14_timer[timeridx].cval;
+}
+
+static void gt_virt_redir_cval_write(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t value)
+{
+ int timeridx = gt_virt_redir_timeridx(env);
+ gt_cval_write(env, ri, timeridx, value);
+}
+
+static uint64_t gt_virt_redir_tval_read(CPUARMState *env,
+ const ARMCPRegInfo *ri)
+{
+ int timeridx = gt_virt_redir_timeridx(env);
+ return gt_tval_read(env, ri, timeridx);
+}
+
+static void gt_virt_redir_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t value)
+{
+ int timeridx = gt_virt_redir_timeridx(env);
+ gt_tval_write(env, ri, timeridx, value);
+}
+
+static uint64_t gt_virt_redir_ctl_read(CPUARMState *env,
+ const ARMCPRegInfo *ri)
+{
+ int timeridx = gt_virt_redir_timeridx(env);
+ return env->cp15.c14_timer[timeridx].ctl;
+}
+
+static void gt_virt_redir_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t value)
+{
+ int timeridx = gt_virt_redir_timeridx(env);
+ gt_ctl_write(env, ri, timeridx, value);
+}
+
static void gt_hyp_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri)
{
gt_timer_reset(env, ri, GTIMER_HYP);
@@ -2889,7 +2995,8 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
.accessfn = gt_ptimer_access,
.fieldoffset = offsetoflow32(CPUARMState,
cp15.c14_timer[GTIMER_PHYS].ctl),
- .writefn = gt_phys_ctl_write, .raw_writefn = raw_write,
+ .readfn = gt_phys_redir_ctl_read, .raw_readfn = raw_read,
+ .writefn = gt_phys_redir_ctl_write, .raw_writefn = raw_write,
},
{ .name = "CNTP_CTL_S",
.cp = 15, .crn = 14, .crm = 2, .opc1 = 0, .opc2 = 1,
@@ -2906,14 +3013,16 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
.accessfn = gt_ptimer_access,
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].ctl),
.resetvalue = 0,
- .writefn = gt_phys_ctl_write, .raw_writefn = raw_write,
+ .readfn = gt_phys_redir_ctl_read, .raw_readfn = raw_read,
+ .writefn = gt_phys_redir_ctl_write, .raw_writefn = raw_write,
},
{ .name = "CNTV_CTL", .cp = 15, .crn = 14, .crm = 3, .opc1 = 0, .opc2 = 1,
.type = ARM_CP_IO | ARM_CP_ALIAS, .access = PL0_RW,
.accessfn = gt_vtimer_access,
.fieldoffset = offsetoflow32(CPUARMState,
cp15.c14_timer[GTIMER_VIRT].ctl),
- .writefn = gt_virt_ctl_write, .raw_writefn = raw_write,
+ .readfn = gt_virt_redir_ctl_read, .raw_readfn = raw_read,
+ .writefn = gt_virt_redir_ctl_write, .raw_writefn = raw_write,
},
{ .name = "CNTV_CTL_EL0", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 3, .crn = 14, .crm = 3, .opc2 = 1,
@@ -2921,14 +3030,15 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
.accessfn = gt_vtimer_access,
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].ctl),
.resetvalue = 0,
- .writefn = gt_virt_ctl_write, .raw_writefn = raw_write,
+ .readfn = gt_virt_redir_ctl_read, .raw_readfn = raw_read,
+ .writefn = gt_virt_redir_ctl_write, .raw_writefn = raw_write,
},
/* TimerValue views: a 32 bit downcounting view of the underlying state */
{ .name = "CNTP_TVAL", .cp = 15, .crn = 14, .crm = 2, .opc1 = 0, .opc2 = 0,
.secure = ARM_CP_SECSTATE_NS,
.type = ARM_CP_NO_RAW | ARM_CP_IO, .access = PL0_RW,
.accessfn = gt_ptimer_access,
- .readfn = gt_phys_tval_read, .writefn = gt_phys_tval_write,
+ .readfn = gt_phys_redir_tval_read, .writefn = gt_phys_redir_tval_write,
},
{ .name = "CNTP_TVAL_S",
.cp = 15, .crn = 14, .crm = 2, .opc1 = 0, .opc2 = 0,
@@ -2941,18 +3051,18 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
.opc0 = 3, .opc1 = 3, .crn = 14, .crm = 2, .opc2 = 0,
.type = ARM_CP_NO_RAW | ARM_CP_IO, .access = PL0_RW,
.accessfn = gt_ptimer_access, .resetfn = gt_phys_timer_reset,
- .readfn = gt_phys_tval_read, .writefn = gt_phys_tval_write,
+ .readfn = gt_phys_redir_tval_read, .writefn = gt_phys_redir_tval_write,
},
{ .name = "CNTV_TVAL", .cp = 15, .crn = 14, .crm = 3, .opc1 = 0, .opc2 = 0,
.type = ARM_CP_NO_RAW | ARM_CP_IO, .access = PL0_RW,
.accessfn = gt_vtimer_access,
- .readfn = gt_virt_tval_read, .writefn = gt_virt_tval_write,
+ .readfn = gt_virt_redir_tval_read, .writefn = gt_virt_redir_tval_write,
},
{ .name = "CNTV_TVAL_EL0", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 3, .crn = 14, .crm = 3, .opc2 = 0,
.type = ARM_CP_NO_RAW | ARM_CP_IO, .access = PL0_RW,
.accessfn = gt_vtimer_access, .resetfn = gt_virt_timer_reset,
- .readfn = gt_virt_tval_read, .writefn = gt_virt_tval_write,
+ .readfn = gt_virt_redir_tval_read, .writefn = gt_virt_redir_tval_write,
},
/* The counter itself */
{ .name = "CNTPCT", .cp = 15, .crm = 14, .opc1 = 0,
@@ -2982,7 +3092,8 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
.type = ARM_CP_64BIT | ARM_CP_IO | ARM_CP_ALIAS,
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].cval),
.accessfn = gt_ptimer_access,
- .writefn = gt_phys_cval_write, .raw_writefn = raw_write,
+ .readfn = gt_phys_redir_cval_read, .raw_readfn = raw_read,
+ .writefn = gt_phys_redir_cval_write, .raw_writefn = raw_write,
},
{ .name = "CNTP_CVAL_S", .cp = 15, .crm = 14, .opc1 = 2,
.secure = ARM_CP_SECSTATE_S,
@@ -2998,14 +3109,16 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
.type = ARM_CP_IO,
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].cval),
.resetvalue = 0, .accessfn = gt_ptimer_access,
- .writefn = gt_phys_cval_write, .raw_writefn = raw_write,
+ .readfn = gt_phys_redir_cval_read, .raw_readfn = raw_read,
+ .writefn = gt_phys_redir_cval_write, .raw_writefn = raw_write,
},
{ .name = "CNTV_CVAL", .cp = 15, .crm = 14, .opc1 = 3,
.access = PL0_RW,
.type = ARM_CP_64BIT | ARM_CP_IO | ARM_CP_ALIAS,
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].cval),
.accessfn = gt_vtimer_access,
- .writefn = gt_virt_cval_write, .raw_writefn = raw_write,
+ .readfn = gt_virt_redir_cval_read, .raw_readfn = raw_read,
+ .writefn = gt_virt_redir_cval_write, .raw_writefn = raw_write,
},
{ .name = "CNTV_CVAL_EL0", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 3, .crn = 14, .crm = 3, .opc2 = 2,
@@ -3013,7 +3126,8 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
.type = ARM_CP_IO,
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].cval),
.resetvalue = 0, .accessfn = gt_vtimer_access,
- .writefn = gt_virt_cval_write, .raw_writefn = raw_write,
+ .readfn = gt_virt_redir_cval_read, .raw_readfn = raw_read,
+ .writefn = gt_virt_redir_cval_write, .raw_writefn = raw_write,
},
/* Secure timer -- this is actually restricted to only EL3
* and configurably Secure-EL1 via the accessfn.
@@ -3044,6 +3158,15 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
REGINFO_SENTINEL
};
+static CPAccessResult e2h_access(CPUARMState *env, const ARMCPRegInfo *ri,
+ bool isread)
+{
+ if (!(arm_hcr_el2_eff(env) & HCR_E2H)) {
+ return CP_ACCESS_TRAP;
+ }
+ return CP_ACCESS_OK;
+}
+
#else
/* In user-mode most of the generic timer registers are inaccessible
@@ -6431,6 +6554,40 @@ static const ARMCPRegInfo vhe_reginfo[] = {
.access = PL2_RW,
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_HYPVIRT].ctl),
.writefn = gt_hv_ctl_write, .raw_writefn = raw_write },
+ { .name = "CNTP_CTL_EL02", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 5, .crn = 14, .crm = 2, .opc2 = 1,
+ .type = ARM_CP_IO | ARM_CP_ALIAS,
+ .access = PL2_RW, .accessfn = e2h_access,
+ .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].ctl),
+ .writefn = gt_phys_ctl_write, .raw_writefn = raw_write },
+ { .name = "CNTV_CTL_EL02", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 5, .crn = 14, .crm = 3, .opc2 = 1,
+ .type = ARM_CP_IO | ARM_CP_ALIAS,
+ .access = PL2_RW, .accessfn = e2h_access,
+ .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].ctl),
+ .writefn = gt_virt_ctl_write, .raw_writefn = raw_write },
+ { .name = "CNTP_TVAL_EL02", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 5, .crn = 14, .crm = 2, .opc2 = 0,
+ .type = ARM_CP_NO_RAW | ARM_CP_IO | ARM_CP_ALIAS,
+ .access = PL2_RW, .accessfn = e2h_access,
+ .readfn = gt_phys_tval_read, .writefn = gt_phys_tval_write },
+ { .name = "CNTV_TVAL_EL02", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 5, .crn = 14, .crm = 3, .opc2 = 0,
+ .type = ARM_CP_NO_RAW | ARM_CP_IO | ARM_CP_ALIAS,
+ .access = PL2_RW, .accessfn = e2h_access,
+ .readfn = gt_virt_tval_read, .writefn = gt_virt_tval_write },
+ { .name = "CNTP_CVAL_EL02", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 5, .crn = 14, .crm = 2, .opc2 = 2,
+ .type = ARM_CP_IO | ARM_CP_ALIAS,
+ .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].cval),
+ .access = PL2_RW, .accessfn = e2h_access,
+ .writefn = gt_phys_cval_write, .raw_writefn = raw_write },
+ { .name = "CNTV_CVAL_EL02", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 5, .crn = 14, .crm = 3, .opc2 = 2,
+ .type = ARM_CP_IO | ARM_CP_ALIAS,
+ .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].cval),
+ .access = PL2_RW, .accessfn = e2h_access,
+ .writefn = gt_virt_cval_write, .raw_writefn = raw_write },
#endif
REGINFO_SENTINEL
};
--
2.20.1
- [PULL 22/48] target/arm: Update arm_mmu_idx for VHE, (continued)
- [PULL 22/48] target/arm: Update arm_mmu_idx for VHE, Peter Maydell, 2020/02/07
- [PULL 20/48] target/arm: Reorganize ARMMMUIdx, Peter Maydell, 2020/02/07
- [PULL 23/48] target/arm: Update arm_sctlr for VHE, Peter Maydell, 2020/02/07
- [PULL 24/48] target/arm: Update aa64_zva_access for EL2, Peter Maydell, 2020/02/07
- [PULL 25/48] target/arm: Update ctr_el0_access for EL2, Peter Maydell, 2020/02/07
- [PULL 26/48] target/arm: Add the hypervisor virtual counter, Peter Maydell, 2020/02/07
- [PULL 27/48] target/arm: Update timer access for VHE, Peter Maydell, 2020/02/07
- [PULL 28/48] target/arm: Update define_one_arm_cp_reg_with_opaque for VHE, Peter Maydell, 2020/02/07
- [PULL 31/48] target/arm: Flush tlb for ASID changes in EL2&0 translation regime, Peter Maydell, 2020/02/07
- [PULL 29/48] target/arm: Add VHE system register redirection and aliasing, Peter Maydell, 2020/02/07
- [PULL 30/48] target/arm: Add VHE timer register redirection and aliasing,
Peter Maydell <=
- [PULL 32/48] target/arm: Flush tlbs for E2&0 translation regime, Peter Maydell, 2020/02/07
- [PULL 33/48] target/arm: Update arm_phys_excp_target_el for TGE, Peter Maydell, 2020/02/07
- [PULL 34/48] target/arm: Update {fp,sve}_exception_el for VHE, Peter Maydell, 2020/02/07
- [PULL 35/48] target/arm: check TGE and E2H flags for EL0 pauth traps, Peter Maydell, 2020/02/07
- [PULL 36/48] target/arm: Update get_a64_user_mem_index for VHE, Peter Maydell, 2020/02/07
- [PULL 38/48] target/arm: Enable ARMv8.1-VHE in -cpu max, Peter Maydell, 2020/02/07
- [PULL 37/48] target/arm: Update arm_cpu_do_interrupt_aarch64 for VHE, Peter Maydell, 2020/02/07
- [PULL 40/48] target/arm: Pass more cpu state to arm_excp_unmasked, Peter Maydell, 2020/02/07
- [PULL 41/48] target/arm: Use bool for unmasked in arm_excp_unmasked, Peter Maydell, 2020/02/07
- [PULL 43/48] bcm2835_dma: Fix the ylen loop in TD mode, Peter Maydell, 2020/02/07