arm64: KVM: Plug the arch timer
Add support for the in-kernel timer emulation. Reviewed-by: Christopher Covington <cov@codeaurora.org> Reviewed-by: Catalin Marinas <catalin.marinas@arm.com> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
This commit is contained in:
parent
f61701e0a2
commit
003300de6c
|
@ -390,6 +390,60 @@ __kvm_hyp_code_start:
|
||||||
2:
|
2:
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
|
.macro save_timer_state
|
||||||
|
// x0: vcpu pointer
|
||||||
|
ldr x2, [x0, #VCPU_KVM]
|
||||||
|
kern_hyp_va x2
|
||||||
|
ldr w3, [x2, #KVM_TIMER_ENABLED]
|
||||||
|
cbz w3, 1f
|
||||||
|
|
||||||
|
mrs x3, cntv_ctl_el0
|
||||||
|
and x3, x3, #3
|
||||||
|
str w3, [x0, #VCPU_TIMER_CNTV_CTL]
|
||||||
|
bic x3, x3, #1 // Clear Enable
|
||||||
|
msr cntv_ctl_el0, x3
|
||||||
|
|
||||||
|
isb
|
||||||
|
|
||||||
|
mrs x3, cntv_cval_el0
|
||||||
|
str x3, [x0, #VCPU_TIMER_CNTV_CVAL]
|
||||||
|
|
||||||
|
1:
|
||||||
|
// Allow physical timer/counter access for the host
|
||||||
|
mrs x2, cnthctl_el2
|
||||||
|
orr x2, x2, #3
|
||||||
|
msr cnthctl_el2, x2
|
||||||
|
|
||||||
|
// Clear cntvoff for the host
|
||||||
|
msr cntvoff_el2, xzr
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro restore_timer_state
|
||||||
|
// x0: vcpu pointer
|
||||||
|
// Disallow physical timer access for the guest
|
||||||
|
// Physical counter access is allowed
|
||||||
|
mrs x2, cnthctl_el2
|
||||||
|
orr x2, x2, #1
|
||||||
|
bic x2, x2, #2
|
||||||
|
msr cnthctl_el2, x2
|
||||||
|
|
||||||
|
ldr x2, [x0, #VCPU_KVM]
|
||||||
|
kern_hyp_va x2
|
||||||
|
ldr w3, [x2, #KVM_TIMER_ENABLED]
|
||||||
|
cbz w3, 1f
|
||||||
|
|
||||||
|
ldr x3, [x2, #KVM_TIMER_CNTVOFF]
|
||||||
|
msr cntvoff_el2, x3
|
||||||
|
ldr x2, [x0, #VCPU_TIMER_CNTV_CVAL]
|
||||||
|
msr cntv_cval_el0, x2
|
||||||
|
isb
|
||||||
|
|
||||||
|
ldr w2, [x0, #VCPU_TIMER_CNTV_CTL]
|
||||||
|
and x2, x2, #3
|
||||||
|
msr cntv_ctl_el0, x2
|
||||||
|
1:
|
||||||
|
.endm
|
||||||
|
|
||||||
__save_sysregs:
|
__save_sysregs:
|
||||||
save_sysregs
|
save_sysregs
|
||||||
ret
|
ret
|
||||||
|
@ -433,6 +487,7 @@ ENTRY(__kvm_vcpu_run)
|
||||||
activate_vm
|
activate_vm
|
||||||
|
|
||||||
restore_vgic_state
|
restore_vgic_state
|
||||||
|
restore_timer_state
|
||||||
|
|
||||||
// Guest context
|
// Guest context
|
||||||
add x2, x0, #VCPU_CONTEXT
|
add x2, x0, #VCPU_CONTEXT
|
||||||
|
@ -455,6 +510,7 @@ __kvm_vcpu_return:
|
||||||
bl __save_fpsimd
|
bl __save_fpsimd
|
||||||
bl __save_sysregs
|
bl __save_sysregs
|
||||||
|
|
||||||
|
save_timer_state
|
||||||
save_vgic_state
|
save_vgic_state
|
||||||
|
|
||||||
deactivate_traps
|
deactivate_traps
|
||||||
|
|
|
@ -23,6 +23,8 @@
|
||||||
#include <linux/kvm_host.h>
|
#include <linux/kvm_host.h>
|
||||||
#include <linux/kvm.h>
|
#include <linux/kvm.h>
|
||||||
|
|
||||||
|
#include <kvm/arm_arch_timer.h>
|
||||||
|
|
||||||
#include <asm/cputype.h>
|
#include <asm/cputype.h>
|
||||||
#include <asm/ptrace.h>
|
#include <asm/ptrace.h>
|
||||||
#include <asm/kvm_arm.h>
|
#include <asm/kvm_arm.h>
|
||||||
|
@ -36,6 +38,11 @@ static const struct kvm_regs default_regs_reset = {
|
||||||
PSR_F_BIT | PSR_D_BIT),
|
PSR_F_BIT | PSR_D_BIT),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct kvm_irq_level default_vtimer_irq = {
|
||||||
|
.irq = 27,
|
||||||
|
.level = 1,
|
||||||
|
};
|
||||||
|
|
||||||
int kvm_arch_dev_ioctl_check_extension(long ext)
|
int kvm_arch_dev_ioctl_check_extension(long ext)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
|
@ -58,11 +65,13 @@ int kvm_arch_dev_ioctl_check_extension(long ext)
|
||||||
*/
|
*/
|
||||||
int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
|
int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
|
||||||
{
|
{
|
||||||
|
const struct kvm_irq_level *cpu_vtimer_irq;
|
||||||
const struct kvm_regs *cpu_reset;
|
const struct kvm_regs *cpu_reset;
|
||||||
|
|
||||||
switch (vcpu->arch.target) {
|
switch (vcpu->arch.target) {
|
||||||
default:
|
default:
|
||||||
cpu_reset = &default_regs_reset;
|
cpu_reset = &default_regs_reset;
|
||||||
|
cpu_vtimer_irq = &default_vtimer_irq;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,5 +81,8 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
|
||||||
/* Reset system registers */
|
/* Reset system registers */
|
||||||
kvm_reset_sys_regs(vcpu);
|
kvm_reset_sys_regs(vcpu);
|
||||||
|
|
||||||
|
/* Reset timer */
|
||||||
|
kvm_timer_vcpu_reset(vcpu, cpu_vtimer_irq);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue