x86/hyper-v: allocate and use Virtual Processor Assist Pages
Virtual Processor Assist Pages usage allows us to do optimized EOI processing for APIC, enable Enlightened VMCS support in KVM and more. struct hv_vp_assist_page is defined according to the Hyper-V TLFS v5.0b. Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com> Reviewed-by: Thomas Gleixner <tglx@linutronix.de> Acked-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Radim Krčmář <rkrcmar@redhat.com>
This commit is contained in:

committed by
Radim Krčmář

parent
d4abc577bb
commit
a46d15cc1a
@@ -88,11 +88,15 @@ EXPORT_SYMBOL_GPL(hyperv_cs);
|
||||
u32 *hv_vp_index;
|
||||
EXPORT_SYMBOL_GPL(hv_vp_index);
|
||||
|
||||
struct hv_vp_assist_page **hv_vp_assist_page;
|
||||
EXPORT_SYMBOL_GPL(hv_vp_assist_page);
|
||||
|
||||
u32 hv_max_vp_index;
|
||||
|
||||
static int hv_cpu_init(unsigned int cpu)
|
||||
{
|
||||
u64 msr_vp_index;
|
||||
struct hv_vp_assist_page **hvp = &hv_vp_assist_page[smp_processor_id()];
|
||||
|
||||
hv_get_vp_index(msr_vp_index);
|
||||
|
||||
@@ -101,6 +105,22 @@ static int hv_cpu_init(unsigned int cpu)
|
||||
if (msr_vp_index > hv_max_vp_index)
|
||||
hv_max_vp_index = msr_vp_index;
|
||||
|
||||
if (!hv_vp_assist_page)
|
||||
return 0;
|
||||
|
||||
if (!*hvp)
|
||||
*hvp = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL);
|
||||
|
||||
if (*hvp) {
|
||||
u64 val;
|
||||
|
||||
val = vmalloc_to_pfn(*hvp);
|
||||
val = (val << HV_X64_MSR_VP_ASSIST_PAGE_ADDRESS_SHIFT) |
|
||||
HV_X64_MSR_VP_ASSIST_PAGE_ENABLE;
|
||||
|
||||
wrmsrl(HV_X64_MSR_VP_ASSIST_PAGE, val);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -198,6 +218,9 @@ static int hv_cpu_die(unsigned int cpu)
|
||||
struct hv_reenlightenment_control re_ctrl;
|
||||
unsigned int new_cpu;
|
||||
|
||||
if (hv_vp_assist_page && hv_vp_assist_page[cpu])
|
||||
wrmsrl(HV_X64_MSR_VP_ASSIST_PAGE, 0);
|
||||
|
||||
if (hv_reenlightenment_cb == NULL)
|
||||
return 0;
|
||||
|
||||
@@ -224,6 +247,7 @@ void hyperv_init(void)
|
||||
{
|
||||
u64 guest_id, required_msrs;
|
||||
union hv_x64_msr_hypercall_contents hypercall_msr;
|
||||
int cpuhp;
|
||||
|
||||
if (x86_hyper_type != X86_HYPER_MS_HYPERV)
|
||||
return;
|
||||
@@ -241,9 +265,17 @@ void hyperv_init(void)
|
||||
if (!hv_vp_index)
|
||||
return;
|
||||
|
||||
if (cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "x86/hyperv_init:online",
|
||||
hv_cpu_init, hv_cpu_die) < 0)
|
||||
hv_vp_assist_page = kcalloc(num_possible_cpus(),
|
||||
sizeof(*hv_vp_assist_page), GFP_KERNEL);
|
||||
if (!hv_vp_assist_page) {
|
||||
ms_hyperv.hints &= ~HV_X64_ENLIGHTENED_VMCS_RECOMMENDED;
|
||||
goto free_vp_index;
|
||||
}
|
||||
|
||||
cpuhp = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "x86/hyperv_init:online",
|
||||
hv_cpu_init, hv_cpu_die);
|
||||
if (cpuhp < 0)
|
||||
goto free_vp_assist_page;
|
||||
|
||||
/*
|
||||
* Setup the hypercall page and enable hypercalls.
|
||||
@@ -256,7 +288,7 @@ void hyperv_init(void)
|
||||
hv_hypercall_pg = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL_RX);
|
||||
if (hv_hypercall_pg == NULL) {
|
||||
wrmsrl(HV_X64_MSR_GUEST_OS_ID, 0);
|
||||
goto free_vp_index;
|
||||
goto remove_cpuhp_state;
|
||||
}
|
||||
|
||||
rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
|
||||
@@ -304,6 +336,11 @@ register_msr_cs:
|
||||
|
||||
return;
|
||||
|
||||
remove_cpuhp_state:
|
||||
cpuhp_remove_state(cpuhp);
|
||||
free_vp_assist_page:
|
||||
kfree(hv_vp_assist_page);
|
||||
hv_vp_assist_page = NULL;
|
||||
free_vp_index:
|
||||
kfree(hv_vp_index);
|
||||
hv_vp_index = NULL;
|
||||
|
Reference in New Issue
Block a user