Loading arch/arm/include/asm/virt.h +5 −0 Original line number Diff line number Diff line Loading @@ -80,6 +80,11 @@ static inline bool is_kernel_in_hyp_mode(void) return false; } static inline bool has_vhe(void) { return false; } /* The section containing the hypervisor idmap text */ extern char __hyp_idmap_text_start[]; extern char __hyp_idmap_text_end[]; Loading arch/arm/kvm/arm.c +3 −0 Original line number Diff line number Diff line Loading @@ -1099,6 +1099,9 @@ static void cpu_init_hyp_mode(void *dummy) __cpu_init_hyp_mode(pgd_ptr, hyp_stack_ptr, vector_ptr); __cpu_init_stage2(); if (is_kernel_in_hyp_mode()) kvm_timer_init_vhe(); kvm_arm_init_debug(); } Loading arch/arm64/include/asm/virt.h +9 −0 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ #include <asm/ptrace.h> #include <asm/sections.h> #include <asm/sysreg.h> #include <asm/cpufeature.h> /* * __boot_cpu_mode records what mode CPUs were booted in. Loading Loading @@ -80,6 +81,14 @@ static inline bool is_kernel_in_hyp_mode(void) return read_sysreg(CurrentEL) == CurrentEL_EL2; } static inline bool has_vhe(void) { if (cpus_have_const_cap(ARM64_HAS_VIRT_HOST_EXTN)) return true; return false; } #ifdef CONFIG_ARM64_VHE extern void verify_cpu_run_el(void); #else Loading include/kvm/arm_arch_timer.h +1 −0 Original line number Diff line number Diff line Loading @@ -76,4 +76,5 @@ void kvm_timer_unschedule(struct kvm_vcpu *vcpu); void kvm_timer_vcpu_put(struct kvm_vcpu *vcpu); void kvm_timer_init_vhe(void); #endif virt/kvm/arm/arch_timer.c +23 −3 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ #include <clocksource/arm_arch_timer.h> #include <asm/arch_timer.h> #include <asm/kvm_hyp.h> #include <kvm/arm_vgic.h> #include <kvm/arm_arch_timer.h> Loading Loading @@ -89,9 +90,6 @@ static void kvm_timer_inject_irq_work(struct work_struct *work) struct kvm_vcpu *vcpu; vcpu = container_of(work, struct kvm_vcpu, arch.timer_cpu.expired); vcpu->arch.timer_cpu.armed = false; WARN_ON(!kvm_timer_should_fire(vcpu)); /* * If the vcpu is blocked we want to wake it up so that it will see Loading Loading @@ -512,3 +510,25 @@ void kvm_timer_init(struct kvm *kvm) { kvm->arch.timer.cntvoff = kvm_phys_timer_read(); } /* * On VHE system, we only need to configure trap on physical timer and counter * accesses in EL0 and EL1 once, not for every world switch. * The host kernel runs at EL2 with HCR_EL2.TGE == 1, * and this makes those bits have no effect for the host kernel execution. */ void kvm_timer_init_vhe(void) { /* When HCR_EL2.E2H ==1, EL1PCEN and EL1PCTEN are shifted by 10 */ u32 cnthctl_shift = 10; u64 val; /* * Disallow physical timer access for the guest. * Physical counter access is allowed. */ val = read_sysreg(cnthctl_el2); val &= ~(CNTHCTL_EL1PCEN << cnthctl_shift); val |= (CNTHCTL_EL1PCTEN << cnthctl_shift); write_sysreg(val, cnthctl_el2); } Loading
arch/arm/include/asm/virt.h +5 −0 Original line number Diff line number Diff line Loading @@ -80,6 +80,11 @@ static inline bool is_kernel_in_hyp_mode(void) return false; } static inline bool has_vhe(void) { return false; } /* The section containing the hypervisor idmap text */ extern char __hyp_idmap_text_start[]; extern char __hyp_idmap_text_end[]; Loading
arch/arm/kvm/arm.c +3 −0 Original line number Diff line number Diff line Loading @@ -1099,6 +1099,9 @@ static void cpu_init_hyp_mode(void *dummy) __cpu_init_hyp_mode(pgd_ptr, hyp_stack_ptr, vector_ptr); __cpu_init_stage2(); if (is_kernel_in_hyp_mode()) kvm_timer_init_vhe(); kvm_arm_init_debug(); } Loading
arch/arm64/include/asm/virt.h +9 −0 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ #include <asm/ptrace.h> #include <asm/sections.h> #include <asm/sysreg.h> #include <asm/cpufeature.h> /* * __boot_cpu_mode records what mode CPUs were booted in. Loading Loading @@ -80,6 +81,14 @@ static inline bool is_kernel_in_hyp_mode(void) return read_sysreg(CurrentEL) == CurrentEL_EL2; } static inline bool has_vhe(void) { if (cpus_have_const_cap(ARM64_HAS_VIRT_HOST_EXTN)) return true; return false; } #ifdef CONFIG_ARM64_VHE extern void verify_cpu_run_el(void); #else Loading
include/kvm/arm_arch_timer.h +1 −0 Original line number Diff line number Diff line Loading @@ -76,4 +76,5 @@ void kvm_timer_unschedule(struct kvm_vcpu *vcpu); void kvm_timer_vcpu_put(struct kvm_vcpu *vcpu); void kvm_timer_init_vhe(void); #endif
virt/kvm/arm/arch_timer.c +23 −3 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ #include <clocksource/arm_arch_timer.h> #include <asm/arch_timer.h> #include <asm/kvm_hyp.h> #include <kvm/arm_vgic.h> #include <kvm/arm_arch_timer.h> Loading Loading @@ -89,9 +90,6 @@ static void kvm_timer_inject_irq_work(struct work_struct *work) struct kvm_vcpu *vcpu; vcpu = container_of(work, struct kvm_vcpu, arch.timer_cpu.expired); vcpu->arch.timer_cpu.armed = false; WARN_ON(!kvm_timer_should_fire(vcpu)); /* * If the vcpu is blocked we want to wake it up so that it will see Loading Loading @@ -512,3 +510,25 @@ void kvm_timer_init(struct kvm *kvm) { kvm->arch.timer.cntvoff = kvm_phys_timer_read(); } /* * On VHE system, we only need to configure trap on physical timer and counter * accesses in EL0 and EL1 once, not for every world switch. * The host kernel runs at EL2 with HCR_EL2.TGE == 1, * and this makes those bits have no effect for the host kernel execution. */ void kvm_timer_init_vhe(void) { /* When HCR_EL2.E2H ==1, EL1PCEN and EL1PCTEN are shifted by 10 */ u32 cnthctl_shift = 10; u64 val; /* * Disallow physical timer access for the guest. * Physical counter access is allowed. */ val = read_sysreg(cnthctl_el2); val &= ~(CNTHCTL_EL1PCEN << cnthctl_shift); val |= (CNTHCTL_EL1PCTEN << cnthctl_shift); write_sysreg(val, cnthctl_el2); }