Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 003300de authored by Marc Zyngier's avatar Marc Zyngier
Browse files

arm64: KVM: Plug the arch timer



Add support for the in-kernel timer emulation.

Reviewed-by: default avatarChristopher Covington <cov@codeaurora.org>
Reviewed-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
Signed-off-by: default avatarMarc Zyngier <marc.zyngier@arm.com>
parent f61701e0
Loading
Loading
Loading
Loading
+56 −0
Original line number Diff line number Diff line
@@ -390,6 +390,60 @@ __kvm_hyp_code_start:
2:
.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
	ret
@@ -433,6 +487,7 @@ ENTRY(__kvm_vcpu_run)
	activate_vm

	restore_vgic_state
	restore_timer_state

	// Guest context
	add	x2, x0, #VCPU_CONTEXT
@@ -455,6 +510,7 @@ __kvm_vcpu_return:
	bl __save_fpsimd
	bl __save_sysregs

	save_timer_state
	save_vgic_state

	deactivate_traps
+12 −0
Original line number Diff line number Diff line
@@ -23,6 +23,8 @@
#include <linux/kvm_host.h>
#include <linux/kvm.h>

#include <kvm/arm_arch_timer.h>

#include <asm/cputype.h>
#include <asm/ptrace.h>
#include <asm/kvm_arm.h>
@@ -36,6 +38,11 @@ static const struct kvm_regs default_regs_reset = {
			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 r;
@@ -58,11 +65,13 @@ int kvm_arch_dev_ioctl_check_extension(long ext)
 */
int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
{
	const struct kvm_irq_level *cpu_vtimer_irq;
	const struct kvm_regs *cpu_reset;

	switch (vcpu->arch.target) {
	default:
		cpu_reset = &default_regs_reset;
		cpu_vtimer_irq = &default_vtimer_irq;
		break;
	}

@@ -72,5 +81,8 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
	/* Reset system registers */
	kvm_reset_sys_regs(vcpu);

	/* Reset timer */
	kvm_timer_vcpu_reset(vcpu, cpu_vtimer_irq);

	return 0;
}