Commit cfef5af3 authored by Vitaly Kuznetsov's avatar Vitaly Kuznetsov Committed by Sean Christopherson
Browse files

KVM: x86: Move Hyper-V partition assist page out of Hyper-V emulation context



Hyper-V partition assist page is used when KVM runs on top of Hyper-V and
is not used for Windows/Hyper-V guests on KVM, this means that 'hv_pa_pg'
placement in 'struct kvm_hv' is unfortunate. As a preparation to making
Hyper-V emulation optional, move 'hv_pa_pg' to 'struct kvm_arch' and put it
under CONFIG_HYPERV.

While on it, introduce hv_get_partition_assist_page() helper to allocate
partition assist page. Move the comment explaining why we use a single page
for all vCPUs from VMX and expand it a bit.

No functional change intended.

Reviewed-by: default avatarMaxim Levitsky <mlevitsk@redhat.com>
Tested-by: default avatarJeremi Piotrowski <jpiotrowski@linux.microsoft.com>
Signed-off-by: default avatarVitaly Kuznetsov <vkuznets@redhat.com>
Link: https://lore.kernel.org/r/20231205103630.1391318-3-vkuznets@redhat.com


Signed-off-by: default avatarSean Christopherson <seanjc@google.com>
parent 87562052
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1125,7 +1125,6 @@ struct kvm_hv {
	 */
	unsigned int synic_auto_eoi_used;

	struct hv_partition_assist_pg *hv_pa_pg;
	struct kvm_hv_syndbg hv_syndbg;
};

@@ -1447,6 +1446,7 @@ struct kvm_arch {
#if IS_ENABLED(CONFIG_HYPERV)
	hpa_t	hv_root_tdp;
	spinlock_t hv_root_tdp_lock;
	struct hv_partition_assist_pg *hv_pa_pg;
#endif
	/*
	 * VM-scope maximum vCPU ID. Used to determine the size of structures
+20 −0
Original line number Diff line number Diff line
@@ -10,6 +10,26 @@
int hv_flush_remote_tlbs_range(struct kvm *kvm, gfn_t gfn, gfn_t nr_pages);
int hv_flush_remote_tlbs(struct kvm *kvm);
void hv_track_root_tdp(struct kvm_vcpu *vcpu, hpa_t root_tdp);
static inline hpa_t hv_get_partition_assist_page(struct kvm_vcpu *vcpu)
{
	/*
	 * Partition assist page is something which Hyper-V running in L0
	 * requires from KVM running in L1 before direct TLB flush for L2
	 * guests can be enabled. KVM doesn't currently use the page but to
	 * comply with TLFS it still needs to be allocated. For now, this
	 * is a single page shared among all vCPUs.
	 */
	struct hv_partition_assist_pg **p_hv_pa_pg =
		&vcpu->kvm->arch.hv_pa_pg;

	if (!*p_hv_pa_pg)
		*p_hv_pa_pg = kzalloc(PAGE_SIZE, GFP_KERNEL_ACCOUNT);

	if (!*p_hv_pa_pg)
		return INVALID_PAGE;

	return __pa(*p_hv_pa_pg);
}
#else /* !CONFIG_HYPERV */
static inline int hv_flush_remote_tlbs(struct kvm *kvm)
{
+3 −7
Original line number Diff line number Diff line
@@ -18,18 +18,14 @@
int svm_hv_enable_l2_tlb_flush(struct kvm_vcpu *vcpu)
{
	struct hv_vmcb_enlightenments *hve;
	struct hv_partition_assist_pg **p_hv_pa_pg =
			&to_kvm_hv(vcpu->kvm)->hv_pa_pg;
	hpa_t partition_assist_page = hv_get_partition_assist_page(vcpu);

	if (!*p_hv_pa_pg)
		*p_hv_pa_pg = kzalloc(PAGE_SIZE, GFP_KERNEL);

	if (!*p_hv_pa_pg)
	if (partition_assist_page == INVALID_PAGE)
		return -ENOMEM;

	hve = &to_svm(vcpu)->vmcb->control.hv_enlightenments;

	hve->partition_assist_page = __pa(*p_hv_pa_pg);
	hve->partition_assist_page = partition_assist_page;
	hve->hv_vm_id = (unsigned long)vcpu->kvm;
	if (!hve->hv_enlightenments_control.nested_flush_hypercall) {
		hve->hv_enlightenments_control.nested_flush_hypercall = 1;
+3 −11
Original line number Diff line number Diff line
@@ -523,22 +523,14 @@ module_param(enlightened_vmcs, bool, 0444);
static int hv_enable_l2_tlb_flush(struct kvm_vcpu *vcpu)
{
	struct hv_enlightened_vmcs *evmcs;
	struct hv_partition_assist_pg **p_hv_pa_pg =
			&to_kvm_hv(vcpu->kvm)->hv_pa_pg;
	/*
	 * Synthetic VM-Exit is not enabled in current code and so All
	 * evmcs in singe VM shares same assist page.
	 */
	if (!*p_hv_pa_pg)
		*p_hv_pa_pg = kzalloc(PAGE_SIZE, GFP_KERNEL_ACCOUNT);
	hpa_t partition_assist_page = hv_get_partition_assist_page(vcpu);

	if (!*p_hv_pa_pg)
	if (partition_assist_page == INVALID_PAGE)
		return -ENOMEM;

	evmcs = (struct hv_enlightened_vmcs *)to_vmx(vcpu)->loaded_vmcs->vmcs;

	evmcs->partition_assist_page =
		__pa(*p_hv_pa_pg);
	evmcs->partition_assist_page = partition_assist_page;
	evmcs->hv_vm_id = (unsigned long)vcpu->kvm;
	evmcs->hv_enlightenments_control.nested_flush_hypercall = 1;

+3 −1
Original line number Diff line number Diff line
@@ -12438,7 +12438,9 @@ void kvm_arch_sched_in(struct kvm_vcpu *vcpu, int cpu)

void kvm_arch_free_vm(struct kvm *kvm)
{
	kfree(to_kvm_hv(kvm)->hv_pa_pg);
#if IS_ENABLED(CONFIG_HYPERV)
	kfree(kvm->arch.hv_pa_pg);
#endif
	__kvm_arch_free_vm(kvm);
}