]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
KVM: arm64: nv: Add handling of EL2-specific timer registers
authorMarc Zyngier <maz@kernel.org>
Tue, 17 Dec 2024 14:23:09 +0000 (14:23 +0000)
committerMarc Zyngier <maz@kernel.org>
Thu, 2 Jan 2025 19:19:09 +0000 (19:19 +0000)
Add the required handling for EL2 and EL02 registers, as
well as EL1 registers used in the E2H context. This includes
handling the virtual timer accesses when CNTHCTL_EL2.EL1TVT
or CNTHCTL_EL2.EL1TVCT are set.

Acked-by: Oliver Upton <oliver.upton@linux.dev>
Link: https://lore.kernel.org/r/20241217142321.763801-2-maz@kernel.org
Signed-off-by: Marc Zyngier <maz@kernel.org>
arch/arm64/include/asm/sysreg.h
arch/arm64/kvm/sys_regs.c
include/clocksource/arm_arch_timer.h

index b8303a83c0bff5fbac56f467a11ec4fc735fa8db..2ed33737c7a99f69492fa845879837cee515401c 100644 (file)
 #define SYS_CNTFRQ_EL0                 sys_reg(3, 3, 14, 0, 0)
 
 #define SYS_CNTPCT_EL0                 sys_reg(3, 3, 14, 0, 1)
+#define SYS_CNTVCT_EL0                 sys_reg(3, 3, 14, 0, 2)
 #define SYS_CNTPCTSS_EL0               sys_reg(3, 3, 14, 0, 5)
 #define SYS_CNTVCTSS_EL0               sys_reg(3, 3, 14, 0, 6)
 
 #define SYS_CNTP_CTL_EL0               sys_reg(3, 3, 14, 2, 1)
 #define SYS_CNTP_CVAL_EL0              sys_reg(3, 3, 14, 2, 2)
 
+#define SYS_CNTV_TVAL_EL0              sys_reg(3, 3, 14, 3, 0)
 #define SYS_CNTV_CTL_EL0               sys_reg(3, 3, 14, 3, 1)
 #define SYS_CNTV_CVAL_EL0              sys_reg(3, 3, 14, 3, 2)
 
 #define SYS_AARCH32_CNTP_TVAL          sys_reg(0, 0, 14, 2, 0)
 #define SYS_AARCH32_CNTP_CTL           sys_reg(0, 0, 14, 2, 1)
 #define SYS_AARCH32_CNTPCT             sys_reg(0, 0, 0, 14, 0)
+#define SYS_AARCH32_CNTVCT             sys_reg(0, 1, 0, 14, 0)
 #define SYS_AARCH32_CNTP_CVAL          sys_reg(0, 2, 0, 14, 0)
 #define SYS_AARCH32_CNTPCTSS           sys_reg(0, 8, 0, 14, 0)
+#define SYS_AARCH32_CNTVCTSS           sys_reg(0, 9, 0, 14, 0)
 
 #define __PMEV_op2(n)                  ((n) & 0x7)
 #define __CNTR_CRm(n)                  (0x8 | (((n) >> 3) & 0x3))
index 83c6b4a07ef56cf0ed9c8751ec80686f45dca6b2..986e63d4f9faa990024ea105e75c897bd0c19503 100644 (file)
@@ -1412,26 +1412,146 @@ static bool access_arch_timer(struct kvm_vcpu *vcpu,
 
        switch (reg) {
        case SYS_CNTP_TVAL_EL0:
+               if (is_hyp_ctxt(vcpu) && vcpu_el2_e2h_is_set(vcpu))
+                       tmr = TIMER_HPTIMER;
+               else
+                       tmr = TIMER_PTIMER;
+               treg = TIMER_REG_TVAL;
+               break;
+
+       case SYS_CNTV_TVAL_EL0:
+               if (is_hyp_ctxt(vcpu) && vcpu_el2_e2h_is_set(vcpu))
+                       tmr = TIMER_HVTIMER;
+               else
+                       tmr = TIMER_VTIMER;
+               treg = TIMER_REG_TVAL;
+               break;
+
        case SYS_AARCH32_CNTP_TVAL:
+       case SYS_CNTP_TVAL_EL02:
                tmr = TIMER_PTIMER;
                treg = TIMER_REG_TVAL;
                break;
+
+       case SYS_CNTV_TVAL_EL02:
+               tmr = TIMER_VTIMER;
+               treg = TIMER_REG_TVAL;
+               break;
+
+       case SYS_CNTHP_TVAL_EL2:
+               tmr = TIMER_HPTIMER;
+               treg = TIMER_REG_TVAL;
+               break;
+
+       case SYS_CNTHV_TVAL_EL2:
+               tmr = TIMER_HVTIMER;
+               treg = TIMER_REG_TVAL;
+               break;
+
        case SYS_CNTP_CTL_EL0:
+               if (is_hyp_ctxt(vcpu) && vcpu_el2_e2h_is_set(vcpu))
+                       tmr = TIMER_HPTIMER;
+               else
+                       tmr = TIMER_PTIMER;
+               treg = TIMER_REG_CTL;
+               break;
+
+       case SYS_CNTV_CTL_EL0:
+               if (is_hyp_ctxt(vcpu) && vcpu_el2_e2h_is_set(vcpu))
+                       tmr = TIMER_HVTIMER;
+               else
+                       tmr = TIMER_VTIMER;
+               treg = TIMER_REG_CTL;
+               break;
+
        case SYS_AARCH32_CNTP_CTL:
+       case SYS_CNTP_CTL_EL02:
                tmr = TIMER_PTIMER;
                treg = TIMER_REG_CTL;
                break;
+
+       case SYS_CNTV_CTL_EL02:
+               tmr = TIMER_VTIMER;
+               treg = TIMER_REG_CTL;
+               break;
+
+       case SYS_CNTHP_CTL_EL2:
+               tmr = TIMER_HPTIMER;
+               treg = TIMER_REG_CTL;
+               break;
+
+       case SYS_CNTHV_CTL_EL2:
+               tmr = TIMER_HVTIMER;
+               treg = TIMER_REG_CTL;
+               break;
+
        case SYS_CNTP_CVAL_EL0:
+               if (is_hyp_ctxt(vcpu) && vcpu_el2_e2h_is_set(vcpu))
+                       tmr = TIMER_HPTIMER;
+               else
+                       tmr = TIMER_PTIMER;
+               treg = TIMER_REG_CVAL;
+               break;
+
+       case SYS_CNTV_CVAL_EL0:
+               if (is_hyp_ctxt(vcpu) && vcpu_el2_e2h_is_set(vcpu))
+                       tmr = TIMER_HVTIMER;
+               else
+                       tmr = TIMER_VTIMER;
+               treg = TIMER_REG_CVAL;
+               break;
+
        case SYS_AARCH32_CNTP_CVAL:
+       case SYS_CNTP_CVAL_EL02:
                tmr = TIMER_PTIMER;
                treg = TIMER_REG_CVAL;
                break;
+
+       case SYS_CNTV_CVAL_EL02:
+               tmr = TIMER_VTIMER;
+               treg = TIMER_REG_CVAL;
+               break;
+
+       case SYS_CNTHP_CVAL_EL2:
+               tmr = TIMER_HPTIMER;
+               treg = TIMER_REG_CVAL;
+               break;
+
+       case SYS_CNTHV_CVAL_EL2:
+               tmr = TIMER_HVTIMER;
+               treg = TIMER_REG_CVAL;
+               break;
+
        case SYS_CNTPCT_EL0:
        case SYS_CNTPCTSS_EL0:
+               if (is_hyp_ctxt(vcpu))
+                       tmr = TIMER_HPTIMER;
+               else
+                       tmr = TIMER_PTIMER;
+               treg = TIMER_REG_CNT;
+               break;
+
        case SYS_AARCH32_CNTPCT:
+       case SYS_AARCH32_CNTPCTSS:
                tmr = TIMER_PTIMER;
                treg = TIMER_REG_CNT;
                break;
+
+       case SYS_CNTVCT_EL0:
+       case SYS_CNTVCTSS_EL0:
+               if (is_hyp_ctxt(vcpu))
+                       tmr = TIMER_HVTIMER;
+               else
+                       tmr = TIMER_VTIMER;
+               treg = TIMER_REG_CNT;
+               break;
+
+       case SYS_AARCH32_CNTVCT:
+       case SYS_AARCH32_CNTVCTSS:
+               tmr = TIMER_VTIMER;
+               treg = TIMER_REG_CNT;
+               break;
+
        default:
                print_sys_reg_msg(p, "%s", "Unhandled trapped timer register");
                return undef_access(vcpu, p, r);
@@ -2901,11 +3021,17 @@ static const struct sys_reg_desc sys_reg_descs[] = {
        AMU_AMEVTYPER1_EL0(15),
 
        { SYS_DESC(SYS_CNTPCT_EL0), access_arch_timer },
+       { SYS_DESC(SYS_CNTVCT_EL0), access_arch_timer },
        { SYS_DESC(SYS_CNTPCTSS_EL0), access_arch_timer },
+       { SYS_DESC(SYS_CNTVCTSS_EL0), access_arch_timer },
        { SYS_DESC(SYS_CNTP_TVAL_EL0), access_arch_timer },
        { SYS_DESC(SYS_CNTP_CTL_EL0), access_arch_timer },
        { SYS_DESC(SYS_CNTP_CVAL_EL0), access_arch_timer },
 
+       { SYS_DESC(SYS_CNTV_TVAL_EL0), access_arch_timer },
+       { SYS_DESC(SYS_CNTV_CTL_EL0), access_arch_timer },
+       { SYS_DESC(SYS_CNTV_CVAL_EL0), access_arch_timer },
+
        /* PMEVCNTRn_EL0 */
        PMU_PMEVCNTR_EL0(0),
        PMU_PMEVCNTR_EL0(1),
@@ -3057,9 +3183,24 @@ static const struct sys_reg_desc sys_reg_descs[] = {
 
        EL2_REG_VNCR(CNTVOFF_EL2, reset_val, 0),
        EL2_REG(CNTHCTL_EL2, access_rw, reset_val, 0),
+       { SYS_DESC(SYS_CNTHP_TVAL_EL2), access_arch_timer },
+       EL2_REG(CNTHP_CTL_EL2, access_arch_timer, reset_val, 0),
+       EL2_REG(CNTHP_CVAL_EL2, access_arch_timer, reset_val, 0),
+
+       { SYS_DESC(SYS_CNTHV_TVAL_EL2), access_arch_timer },
+       EL2_REG(CNTHV_CTL_EL2, access_arch_timer, reset_val, 0),
+       EL2_REG(CNTHV_CVAL_EL2, access_arch_timer, reset_val, 0),
 
        { SYS_DESC(SYS_CNTKCTL_EL12), access_cntkctl_el12 },
 
+       { SYS_DESC(SYS_CNTP_TVAL_EL02), access_arch_timer },
+       { SYS_DESC(SYS_CNTP_CTL_EL02), access_arch_timer },
+       { SYS_DESC(SYS_CNTP_CVAL_EL02), access_arch_timer },
+
+       { SYS_DESC(SYS_CNTV_TVAL_EL02), access_arch_timer },
+       { SYS_DESC(SYS_CNTV_CTL_EL02), access_arch_timer },
+       { SYS_DESC(SYS_CNTV_CVAL_EL02), access_arch_timer },
+
        EL2_REG(SP_EL2, NULL, reset_unknown, 0),
 };
 
@@ -3879,9 +4020,11 @@ static const struct sys_reg_desc cp15_64_regs[] = {
        { SYS_DESC(SYS_AARCH32_CNTPCT),       access_arch_timer },
        { Op1( 1), CRn( 0), CRm( 2), Op2( 0), access_vm_reg, NULL, TTBR1_EL1 },
        { Op1( 1), CRn( 0), CRm(12), Op2( 0), access_gic_sgi }, /* ICC_ASGI1R */
+       { SYS_DESC(SYS_AARCH32_CNTVCT),       access_arch_timer },
        { Op1( 2), CRn( 0), CRm(12), Op2( 0), access_gic_sgi }, /* ICC_SGI0R */
        { SYS_DESC(SYS_AARCH32_CNTP_CVAL),    access_arch_timer },
        { SYS_DESC(SYS_AARCH32_CNTPCTSS),     access_arch_timer },
+       { SYS_DESC(SYS_AARCH32_CNTVCTSS),     access_arch_timer },
 };
 
 static bool check_sysreg_table(const struct sys_reg_desc *table, unsigned int n,
index cbbc9a6dc571587db49b5e9b965f9e3610b83c55..877dcbb2601ae9edacbac09e15484db978c18f04 100644 (file)
@@ -22,6 +22,8 @@
 #define CNTHCTL_EVNTDIR                        (1 << 3)
 #define CNTHCTL_EVNTI                  (0xF << 4)
 #define CNTHCTL_ECV                    (1 << 12)
+#define CNTHCTL_EL1TVT                 (1 << 13)
+#define CNTHCTL_EL1TVCT                        (1 << 14)
 
 enum arch_timer_reg {
        ARCH_TIMER_REG_CTRL,