Skip to content

Commit b59dbb9

Browse files
author
Marc Zyngier
committed
KVM: arm64: nv: Add handling of EL2-specific timer registers
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 <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Marc Zyngier <[email protected]>
1 parent 40384c8 commit b59dbb9

File tree

3 files changed

+149
-0
lines changed

3 files changed

+149
-0
lines changed

arch/arm64/include/asm/sysreg.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,21 +477,25 @@
477477
#define SYS_CNTFRQ_EL0 sys_reg(3, 3, 14, 0, 0)
478478

479479
#define SYS_CNTPCT_EL0 sys_reg(3, 3, 14, 0, 1)
480+
#define SYS_CNTVCT_EL0 sys_reg(3, 3, 14, 0, 2)
480481
#define SYS_CNTPCTSS_EL0 sys_reg(3, 3, 14, 0, 5)
481482
#define SYS_CNTVCTSS_EL0 sys_reg(3, 3, 14, 0, 6)
482483

483484
#define SYS_CNTP_TVAL_EL0 sys_reg(3, 3, 14, 2, 0)
484485
#define SYS_CNTP_CTL_EL0 sys_reg(3, 3, 14, 2, 1)
485486
#define SYS_CNTP_CVAL_EL0 sys_reg(3, 3, 14, 2, 2)
486487

488+
#define SYS_CNTV_TVAL_EL0 sys_reg(3, 3, 14, 3, 0)
487489
#define SYS_CNTV_CTL_EL0 sys_reg(3, 3, 14, 3, 1)
488490
#define SYS_CNTV_CVAL_EL0 sys_reg(3, 3, 14, 3, 2)
489491

490492
#define SYS_AARCH32_CNTP_TVAL sys_reg(0, 0, 14, 2, 0)
491493
#define SYS_AARCH32_CNTP_CTL sys_reg(0, 0, 14, 2, 1)
492494
#define SYS_AARCH32_CNTPCT sys_reg(0, 0, 0, 14, 0)
495+
#define SYS_AARCH32_CNTVCT sys_reg(0, 1, 0, 14, 0)
493496
#define SYS_AARCH32_CNTP_CVAL sys_reg(0, 2, 0, 14, 0)
494497
#define SYS_AARCH32_CNTPCTSS sys_reg(0, 8, 0, 14, 0)
498+
#define SYS_AARCH32_CNTVCTSS sys_reg(0, 9, 0, 14, 0)
495499

496500
#define __PMEV_op2(n) ((n) & 0x7)
497501
#define __CNTR_CRm(n) (0x8 | (((n) >> 3) & 0x3))

arch/arm64/kvm/sys_regs.c

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1412,26 +1412,146 @@ static bool access_arch_timer(struct kvm_vcpu *vcpu,
14121412

14131413
switch (reg) {
14141414
case SYS_CNTP_TVAL_EL0:
1415+
if (is_hyp_ctxt(vcpu) && vcpu_el2_e2h_is_set(vcpu))
1416+
tmr = TIMER_HPTIMER;
1417+
else
1418+
tmr = TIMER_PTIMER;
1419+
treg = TIMER_REG_TVAL;
1420+
break;
1421+
1422+
case SYS_CNTV_TVAL_EL0:
1423+
if (is_hyp_ctxt(vcpu) && vcpu_el2_e2h_is_set(vcpu))
1424+
tmr = TIMER_HVTIMER;
1425+
else
1426+
tmr = TIMER_VTIMER;
1427+
treg = TIMER_REG_TVAL;
1428+
break;
1429+
14151430
case SYS_AARCH32_CNTP_TVAL:
1431+
case SYS_CNTP_TVAL_EL02:
14161432
tmr = TIMER_PTIMER;
14171433
treg = TIMER_REG_TVAL;
14181434
break;
1435+
1436+
case SYS_CNTV_TVAL_EL02:
1437+
tmr = TIMER_VTIMER;
1438+
treg = TIMER_REG_TVAL;
1439+
break;
1440+
1441+
case SYS_CNTHP_TVAL_EL2:
1442+
tmr = TIMER_HPTIMER;
1443+
treg = TIMER_REG_TVAL;
1444+
break;
1445+
1446+
case SYS_CNTHV_TVAL_EL2:
1447+
tmr = TIMER_HVTIMER;
1448+
treg = TIMER_REG_TVAL;
1449+
break;
1450+
14191451
case SYS_CNTP_CTL_EL0:
1452+
if (is_hyp_ctxt(vcpu) && vcpu_el2_e2h_is_set(vcpu))
1453+
tmr = TIMER_HPTIMER;
1454+
else
1455+
tmr = TIMER_PTIMER;
1456+
treg = TIMER_REG_CTL;
1457+
break;
1458+
1459+
case SYS_CNTV_CTL_EL0:
1460+
if (is_hyp_ctxt(vcpu) && vcpu_el2_e2h_is_set(vcpu))
1461+
tmr = TIMER_HVTIMER;
1462+
else
1463+
tmr = TIMER_VTIMER;
1464+
treg = TIMER_REG_CTL;
1465+
break;
1466+
14201467
case SYS_AARCH32_CNTP_CTL:
1468+
case SYS_CNTP_CTL_EL02:
14211469
tmr = TIMER_PTIMER;
14221470
treg = TIMER_REG_CTL;
14231471
break;
1472+
1473+
case SYS_CNTV_CTL_EL02:
1474+
tmr = TIMER_VTIMER;
1475+
treg = TIMER_REG_CTL;
1476+
break;
1477+
1478+
case SYS_CNTHP_CTL_EL2:
1479+
tmr = TIMER_HPTIMER;
1480+
treg = TIMER_REG_CTL;
1481+
break;
1482+
1483+
case SYS_CNTHV_CTL_EL2:
1484+
tmr = TIMER_HVTIMER;
1485+
treg = TIMER_REG_CTL;
1486+
break;
1487+
14241488
case SYS_CNTP_CVAL_EL0:
1489+
if (is_hyp_ctxt(vcpu) && vcpu_el2_e2h_is_set(vcpu))
1490+
tmr = TIMER_HPTIMER;
1491+
else
1492+
tmr = TIMER_PTIMER;
1493+
treg = TIMER_REG_CVAL;
1494+
break;
1495+
1496+
case SYS_CNTV_CVAL_EL0:
1497+
if (is_hyp_ctxt(vcpu) && vcpu_el2_e2h_is_set(vcpu))
1498+
tmr = TIMER_HVTIMER;
1499+
else
1500+
tmr = TIMER_VTIMER;
1501+
treg = TIMER_REG_CVAL;
1502+
break;
1503+
14251504
case SYS_AARCH32_CNTP_CVAL:
1505+
case SYS_CNTP_CVAL_EL02:
14261506
tmr = TIMER_PTIMER;
14271507
treg = TIMER_REG_CVAL;
14281508
break;
1509+
1510+
case SYS_CNTV_CVAL_EL02:
1511+
tmr = TIMER_VTIMER;
1512+
treg = TIMER_REG_CVAL;
1513+
break;
1514+
1515+
case SYS_CNTHP_CVAL_EL2:
1516+
tmr = TIMER_HPTIMER;
1517+
treg = TIMER_REG_CVAL;
1518+
break;
1519+
1520+
case SYS_CNTHV_CVAL_EL2:
1521+
tmr = TIMER_HVTIMER;
1522+
treg = TIMER_REG_CVAL;
1523+
break;
1524+
14291525
case SYS_CNTPCT_EL0:
14301526
case SYS_CNTPCTSS_EL0:
1527+
if (is_hyp_ctxt(vcpu))
1528+
tmr = TIMER_HPTIMER;
1529+
else
1530+
tmr = TIMER_PTIMER;
1531+
treg = TIMER_REG_CNT;
1532+
break;
1533+
14311534
case SYS_AARCH32_CNTPCT:
1535+
case SYS_AARCH32_CNTPCTSS:
14321536
tmr = TIMER_PTIMER;
14331537
treg = TIMER_REG_CNT;
14341538
break;
1539+
1540+
case SYS_CNTVCT_EL0:
1541+
case SYS_CNTVCTSS_EL0:
1542+
if (is_hyp_ctxt(vcpu))
1543+
tmr = TIMER_HVTIMER;
1544+
else
1545+
tmr = TIMER_VTIMER;
1546+
treg = TIMER_REG_CNT;
1547+
break;
1548+
1549+
case SYS_AARCH32_CNTVCT:
1550+
case SYS_AARCH32_CNTVCTSS:
1551+
tmr = TIMER_VTIMER;
1552+
treg = TIMER_REG_CNT;
1553+
break;
1554+
14351555
default:
14361556
print_sys_reg_msg(p, "%s", "Unhandled trapped timer register");
14371557
return undef_access(vcpu, p, r);
@@ -2901,11 +3021,17 @@ static const struct sys_reg_desc sys_reg_descs[] = {
29013021
AMU_AMEVTYPER1_EL0(15),
29023022

29033023
{ SYS_DESC(SYS_CNTPCT_EL0), access_arch_timer },
3024+
{ SYS_DESC(SYS_CNTVCT_EL0), access_arch_timer },
29043025
{ SYS_DESC(SYS_CNTPCTSS_EL0), access_arch_timer },
3026+
{ SYS_DESC(SYS_CNTVCTSS_EL0), access_arch_timer },
29053027
{ SYS_DESC(SYS_CNTP_TVAL_EL0), access_arch_timer },
29063028
{ SYS_DESC(SYS_CNTP_CTL_EL0), access_arch_timer },
29073029
{ SYS_DESC(SYS_CNTP_CVAL_EL0), access_arch_timer },
29083030

3031+
{ SYS_DESC(SYS_CNTV_TVAL_EL0), access_arch_timer },
3032+
{ SYS_DESC(SYS_CNTV_CTL_EL0), access_arch_timer },
3033+
{ SYS_DESC(SYS_CNTV_CVAL_EL0), access_arch_timer },
3034+
29093035
/* PMEVCNTRn_EL0 */
29103036
PMU_PMEVCNTR_EL0(0),
29113037
PMU_PMEVCNTR_EL0(1),
@@ -3057,9 +3183,24 @@ static const struct sys_reg_desc sys_reg_descs[] = {
30573183

30583184
EL2_REG_VNCR(CNTVOFF_EL2, reset_val, 0),
30593185
EL2_REG(CNTHCTL_EL2, access_rw, reset_val, 0),
3186+
{ SYS_DESC(SYS_CNTHP_TVAL_EL2), access_arch_timer },
3187+
EL2_REG(CNTHP_CTL_EL2, access_arch_timer, reset_val, 0),
3188+
EL2_REG(CNTHP_CVAL_EL2, access_arch_timer, reset_val, 0),
3189+
3190+
{ SYS_DESC(SYS_CNTHV_TVAL_EL2), access_arch_timer },
3191+
EL2_REG(CNTHV_CTL_EL2, access_arch_timer, reset_val, 0),
3192+
EL2_REG(CNTHV_CVAL_EL2, access_arch_timer, reset_val, 0),
30603193

30613194
{ SYS_DESC(SYS_CNTKCTL_EL12), access_cntkctl_el12 },
30623195

3196+
{ SYS_DESC(SYS_CNTP_TVAL_EL02), access_arch_timer },
3197+
{ SYS_DESC(SYS_CNTP_CTL_EL02), access_arch_timer },
3198+
{ SYS_DESC(SYS_CNTP_CVAL_EL02), access_arch_timer },
3199+
3200+
{ SYS_DESC(SYS_CNTV_TVAL_EL02), access_arch_timer },
3201+
{ SYS_DESC(SYS_CNTV_CTL_EL02), access_arch_timer },
3202+
{ SYS_DESC(SYS_CNTV_CVAL_EL02), access_arch_timer },
3203+
30633204
EL2_REG(SP_EL2, NULL, reset_unknown, 0),
30643205
};
30653206

@@ -3879,9 +4020,11 @@ static const struct sys_reg_desc cp15_64_regs[] = {
38794020
{ SYS_DESC(SYS_AARCH32_CNTPCT), access_arch_timer },
38804021
{ Op1( 1), CRn( 0), CRm( 2), Op2( 0), access_vm_reg, NULL, TTBR1_EL1 },
38814022
{ Op1( 1), CRn( 0), CRm(12), Op2( 0), access_gic_sgi }, /* ICC_ASGI1R */
4023+
{ SYS_DESC(SYS_AARCH32_CNTVCT), access_arch_timer },
38824024
{ Op1( 2), CRn( 0), CRm(12), Op2( 0), access_gic_sgi }, /* ICC_SGI0R */
38834025
{ SYS_DESC(SYS_AARCH32_CNTP_CVAL), access_arch_timer },
38844026
{ SYS_DESC(SYS_AARCH32_CNTPCTSS), access_arch_timer },
4027+
{ SYS_DESC(SYS_AARCH32_CNTVCTSS), access_arch_timer },
38854028
};
38864029

38874030
static bool check_sysreg_table(const struct sys_reg_desc *table, unsigned int n,

include/clocksource/arm_arch_timer.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
#define CNTHCTL_EVNTDIR (1 << 3)
2323
#define CNTHCTL_EVNTI (0xF << 4)
2424
#define CNTHCTL_ECV (1 << 12)
25+
#define CNTHCTL_EL1TVT (1 << 13)
26+
#define CNTHCTL_EL1TVCT (1 << 14)
2527

2628
enum arch_timer_reg {
2729
ARCH_TIMER_REG_CTRL,

0 commit comments

Comments
 (0)