Skip to content

Commit 5c5196d

Browse files
Christoffer Dallchazy
authored andcommitted
KVM: arm/arm64: Support EL1 phys timer register access in set/get reg
Add suport for the physical timer registers in kvm_arm_timer_set_reg and kvm_arm_timer_get_reg so that these functions can be reused to interact with the rest of the system. Note that this paves part of the way for the physical timer state save/restore, but we still need to add those registers to KVM_GET_REG_LIST before we support migrating the physical timer state. Acked-by: Marc Zyngier <marc.zyngier@arm.com> Signed-off-by: Christoffer Dall <cdall@linaro.org>
1 parent b103cc3 commit 5c5196d

File tree

3 files changed

+43
-2
lines changed

3 files changed

+43
-2
lines changed

arch/arm/include/uapi/asm/kvm.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,12 @@ struct kvm_arch_memory_slot {
151151
(__ARM_CP15_REG(op1, 0, crm, 0) | KVM_REG_SIZE_U64)
152152
#define ARM_CP15_REG64(...) __ARM_CP15_REG64(__VA_ARGS__)
153153

154+
/* PL1 Physical Timer Registers */
155+
#define KVM_REG_ARM_PTIMER_CTL ARM_CP15_REG32(0, 14, 2, 1)
156+
#define KVM_REG_ARM_PTIMER_CNT ARM_CP15_REG64(0, 14)
157+
#define KVM_REG_ARM_PTIMER_CVAL ARM_CP15_REG64(2, 14)
158+
159+
/* Virtual Timer Registers */
154160
#define KVM_REG_ARM_TIMER_CTL ARM_CP15_REG32(0, 14, 3, 1)
155161
#define KVM_REG_ARM_TIMER_CNT ARM_CP15_REG64(1, 14)
156162
#define KVM_REG_ARM_TIMER_CVAL ARM_CP15_REG64(3, 14)

arch/arm64/include/uapi/asm/kvm.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,12 @@ struct kvm_arch_memory_slot {
195195

196196
#define ARM64_SYS_REG(...) (__ARM64_SYS_REG(__VA_ARGS__) | KVM_REG_SIZE_U64)
197197

198+
/* Physical Timer EL0 Registers */
199+
#define KVM_REG_ARM_PTIMER_CTL ARM64_SYS_REG(3, 3, 14, 2, 1)
200+
#define KVM_REG_ARM_PTIMER_CVAL ARM64_SYS_REG(3, 3, 14, 2, 2)
201+
#define KVM_REG_ARM_PTIMER_CNT ARM64_SYS_REG(3, 3, 14, 0, 1)
202+
203+
/* EL0 Virtual Timer Registers */
198204
#define KVM_REG_ARM_TIMER_CTL ARM64_SYS_REG(3, 3, 14, 3, 1)
199205
#define KVM_REG_ARM_TIMER_CNT ARM64_SYS_REG(3, 3, 14, 3, 2)
200206
#define KVM_REG_ARM_TIMER_CVAL ARM64_SYS_REG(3, 3, 14, 0, 2)

virt/kvm/arm/arch_timer.c

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -628,17 +628,25 @@ static void kvm_timer_init_interrupt(void *info)
628628
int kvm_arm_timer_set_reg(struct kvm_vcpu *vcpu, u64 regid, u64 value)
629629
{
630630
struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
631+
struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
631632

632633
switch (regid) {
633634
case KVM_REG_ARM_TIMER_CTL:
634-
vtimer->cnt_ctl = value;
635+
vtimer->cnt_ctl = value & ~ARCH_TIMER_CTRL_IT_STAT;
635636
break;
636637
case KVM_REG_ARM_TIMER_CNT:
637638
update_vtimer_cntvoff(vcpu, kvm_phys_timer_read() - value);
638639
break;
639640
case KVM_REG_ARM_TIMER_CVAL:
640641
vtimer->cnt_cval = value;
641642
break;
643+
case KVM_REG_ARM_PTIMER_CTL:
644+
ptimer->cnt_ctl = value & ~ARCH_TIMER_CTRL_IT_STAT;
645+
break;
646+
case KVM_REG_ARM_PTIMER_CVAL:
647+
ptimer->cnt_cval = value;
648+
break;
649+
642650
default:
643651
return -1;
644652
}
@@ -647,17 +655,38 @@ int kvm_arm_timer_set_reg(struct kvm_vcpu *vcpu, u64 regid, u64 value)
647655
return 0;
648656
}
649657

658+
static u64 read_timer_ctl(struct arch_timer_context *timer)
659+
{
660+
/*
661+
* Set ISTATUS bit if it's expired.
662+
* Note that according to ARMv8 ARM Issue A.k, ISTATUS bit is
663+
* UNKNOWN when ENABLE bit is 0, so we chose to set ISTATUS bit
664+
* regardless of ENABLE bit for our implementation convenience.
665+
*/
666+
if (!kvm_timer_compute_delta(timer))
667+
return timer->cnt_ctl | ARCH_TIMER_CTRL_IT_STAT;
668+
else
669+
return timer->cnt_ctl;
670+
}
671+
650672
u64 kvm_arm_timer_get_reg(struct kvm_vcpu *vcpu, u64 regid)
651673
{
674+
struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
652675
struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
653676

654677
switch (regid) {
655678
case KVM_REG_ARM_TIMER_CTL:
656-
return vtimer->cnt_ctl;
679+
return read_timer_ctl(vtimer);
657680
case KVM_REG_ARM_TIMER_CNT:
658681
return kvm_phys_timer_read() - vtimer->cntvoff;
659682
case KVM_REG_ARM_TIMER_CVAL:
660683
return vtimer->cnt_cval;
684+
case KVM_REG_ARM_PTIMER_CTL:
685+
return read_timer_ctl(ptimer);
686+
case KVM_REG_ARM_PTIMER_CVAL:
687+
return ptimer->cnt_cval;
688+
case KVM_REG_ARM_PTIMER_CNT:
689+
return kvm_phys_timer_read();
661690
}
662691
return (u64)-1;
663692
}

0 commit comments

Comments
 (0)