Commit df26b779 authored by Oliver Upton's avatar Oliver Upton
Browse files

Merge branch kvm-arm64/stage2-vhe-load into kvmarm/next



* kvm-arm64/stage2-vhe-load:
  : Setup stage-2 MMU from vcpu_load() for VHE
  :
  : Unlike nVHE, there is no need to switch the stage-2 MMU around on guest
  : entry/exit in VHE mode as the host is running at EL2. Despite this KVM
  : reloads the stage-2 on every guest entry, which is needless.
  :
  : This series moves the setup of the stage-2 MMU context to vcpu_load()
  : when running in VHE mode. This is likely to be a win across the board,
  : but also allows us to remove an ISB on the guest entry path for systems
  : with one of the speculative AT errata.
  KVM: arm64: Move VTCR_EL2 into struct s2_mmu
  KVM: arm64: Load the stage-2 MMU context in kvm_vcpu_load_vhe()
  KVM: arm64: Rename helpers for VHE vCPU load/put
  KVM: arm64: Reload stage-2 for VMID change on VHE
  KVM: arm64: Restore the stage-2 context in VHE's __tlb_switch_to_host()
  KVM: arm64: Don't zero VTTBR in __tlb_switch_to_host()

Signed-off-by: default avatarOliver Upton <oliver.upton@linux.dev>
parents 51e60796 fe49fd94
Loading
Loading
Loading
Loading
+13 −6
Original line number Diff line number Diff line
@@ -158,6 +158,16 @@ struct kvm_s2_mmu {
	phys_addr_t	pgd_phys;
	struct kvm_pgtable *pgt;

	/*
	 * VTCR value used on the host. For a non-NV guest (or a NV
	 * guest that runs in a context where its own S2 doesn't
	 * apply), its T0SZ value reflects that of the IPA size.
	 *
	 * For a shadow S2 MMU, T0SZ reflects the PARange exposed to
	 * the guest.
	 */
	u64	vtcr;

	/* The last vcpu id that ran on each physical CPU */
	int __percpu *last_vcpu_ran;

@@ -205,9 +215,6 @@ struct kvm_protected_vm {
struct kvm_arch {
	struct kvm_s2_mmu mmu;

	/* VTCR_EL2 value for this VM */
	u64    vtcr;

	/* Interrupt controller */
	struct vgic_dist	vgic;

@@ -1020,7 +1027,7 @@ int kvm_arm_pvtime_has_attr(struct kvm_vcpu *vcpu,
extern unsigned int __ro_after_init kvm_arm_vmid_bits;
int __init kvm_arm_vmid_alloc_init(void);
void __init kvm_arm_vmid_alloc_free(void);
void kvm_arm_vmid_update(struct kvm_vmid *kvm_vmid);
bool kvm_arm_vmid_update(struct kvm_vmid *kvm_vmid);
void kvm_arm_vmid_clear_active(void);

static inline void kvm_arm_pvtime_vcpu_init(struct kvm_vcpu_arch *vcpu_arch)
@@ -1104,8 +1111,8 @@ static inline bool kvm_set_pmuserenr(u64 val)
}
#endif

void kvm_vcpu_load_sysregs_vhe(struct kvm_vcpu *vcpu);
void kvm_vcpu_put_sysregs_vhe(struct kvm_vcpu *vcpu);
void kvm_vcpu_load_vhe(struct kvm_vcpu *vcpu);
void kvm_vcpu_put_vhe(struct kvm_vcpu *vcpu);

int __init kvm_set_ipa_limit(void);

+2 −5
Original line number Diff line number Diff line
@@ -93,6 +93,8 @@ void __timer_disable_traps(struct kvm_vcpu *vcpu);
void __sysreg_save_state_nvhe(struct kvm_cpu_context *ctxt);
void __sysreg_restore_state_nvhe(struct kvm_cpu_context *ctxt);
#else
void __vcpu_load_switch_sysregs(struct kvm_vcpu *vcpu);
void __vcpu_put_switch_sysregs(struct kvm_vcpu *vcpu);
void sysreg_save_host_state_vhe(struct kvm_cpu_context *ctxt);
void sysreg_restore_host_state_vhe(struct kvm_cpu_context *ctxt);
void sysreg_save_guest_state_vhe(struct kvm_cpu_context *ctxt);
@@ -111,11 +113,6 @@ void __fpsimd_save_state(struct user_fpsimd_state *fp_regs);
void __fpsimd_restore_state(struct user_fpsimd_state *fp_regs);
void __sve_restore_state(void *sve_pffr, u32 *fpsr);

#ifndef __KVM_NVHE_HYPERVISOR__
void activate_traps_vhe_load(struct kvm_vcpu *vcpu);
void deactivate_traps_vhe_put(struct kvm_vcpu *vcpu);
#endif

u64 __guest_enter(struct kvm_vcpu *vcpu);

bool kvm_host_psci_handler(struct kvm_cpu_context *host_ctxt, u32 func_id);
+4 −4
Original line number Diff line number Diff line
@@ -150,9 +150,9 @@ static __always_inline unsigned long __kern_hyp_va(unsigned long v)
 */
#define KVM_PHYS_SHIFT	(40)

#define kvm_phys_shift(kvm)		VTCR_EL2_IPA(kvm->arch.vtcr)
#define kvm_phys_size(kvm)		(_AC(1, ULL) << kvm_phys_shift(kvm))
#define kvm_phys_mask(kvm)		(kvm_phys_size(kvm) - _AC(1, ULL))
#define kvm_phys_shift(mmu)		VTCR_EL2_IPA((mmu)->vtcr)
#define kvm_phys_size(mmu)		(_AC(1, ULL) << kvm_phys_shift(mmu))
#define kvm_phys_mask(mmu)		(kvm_phys_size(mmu) - _AC(1, ULL))

#include <asm/kvm_pgtable.h>
#include <asm/stage2_pgtable.h>
@@ -324,7 +324,7 @@ static __always_inline u64 kvm_get_vttbr(struct kvm_s2_mmu *mmu)
static __always_inline void __load_stage2(struct kvm_s2_mmu *mmu,
					  struct kvm_arch *arch)
{
	write_sysreg(arch->vtcr, vtcr_el2);
	write_sysreg(mmu->vtcr, vtcr_el2);
	write_sysreg(kvm_get_vttbr(mmu), vttbr_el2);

	/*
+2 −2
Original line number Diff line number Diff line
@@ -21,13 +21,13 @@
 * (IPA_SHIFT - 4).
 */
#define stage2_pgtable_levels(ipa)	ARM64_HW_PGTABLE_LEVELS((ipa) - 4)
#define kvm_stage2_levels(kvm)		VTCR_EL2_LVLS(kvm->arch.vtcr)
#define kvm_stage2_levels(mmu)		VTCR_EL2_LVLS((mmu)->vtcr)

/*
 * kvm_mmmu_cache_min_pages() is the number of pages required to install
 * a stage-2 translation. We pre-allocate the entry level page table at
 * the VM creation.
 */
#define kvm_mmu_cache_min_pages(kvm)	(kvm_stage2_levels(kvm) - 1)
#define kvm_mmu_cache_min_pages(mmu)	(kvm_stage2_levels(mmu) - 1)

#endif	/* __ARM64_S2_PGTABLE_H_ */
+6 −3
Original line number Diff line number Diff line
@@ -447,7 +447,7 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
	kvm_vgic_load(vcpu);
	kvm_timer_vcpu_load(vcpu);
	if (has_vhe())
		kvm_vcpu_load_sysregs_vhe(vcpu);
		kvm_vcpu_load_vhe(vcpu);
	kvm_arch_vcpu_load_fp(vcpu);
	kvm_vcpu_pmu_restore_guest(vcpu);
	if (kvm_arm_is_pvtime_enabled(&vcpu->arch))
@@ -471,7 +471,7 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
	kvm_arch_vcpu_put_debug_state_flags(vcpu);
	kvm_arch_vcpu_put_fp(vcpu);
	if (has_vhe())
		kvm_vcpu_put_sysregs_vhe(vcpu);
		kvm_vcpu_put_vhe(vcpu);
	kvm_timer_vcpu_put(vcpu);
	kvm_vgic_put(vcpu);
	kvm_vcpu_pmu_restore_host(vcpu);
@@ -949,7 +949,10 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
		 * making a thread's VMID inactive. So we need to call
		 * kvm_arm_vmid_update() in non-premptible context.
		 */
		kvm_arm_vmid_update(&vcpu->arch.hw_mmu->vmid);
		if (kvm_arm_vmid_update(&vcpu->arch.hw_mmu->vmid) &&
		    has_vhe())
			__load_stage2(vcpu->arch.hw_mmu,
				      vcpu->arch.hw_mmu->arch);

		kvm_pmu_flush_hwstate(vcpu);

Loading