Skip to content

Commit

Permalink
x86/hyperv: allocate output arg pages if required
Browse files Browse the repository at this point in the history
When Linux runs as the root partition, it will need to make hypercalls
which return data from the hypervisor.

Allocate pages for storing results when Linux runs as the root
partition.

Signed-off-by: Lillian Grassin-Drake <ligrassi@microsoft.com>
Co-Developed-by: Lillian Grassin-Drake <ligrassi@microsoft.com>
Signed-off-by: Wei Liu <wei.liu@kernel.org>
Reviewed-by: Michael Kelley <mikelley@microsoft.com>
Link: https://lore.kernel.org/r/20210203150435.27941-6-wei.liu@kernel.org
  • Loading branch information
Wei Liu committed Feb 11, 2021
1 parent 7d4163c commit 5d0f077
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 5 deletions.
35 changes: 30 additions & 5 deletions arch/x86/hyperv/hv_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ EXPORT_SYMBOL_GPL(hv_vp_assist_page);
void __percpu **hyperv_pcpu_input_arg;
EXPORT_SYMBOL_GPL(hyperv_pcpu_input_arg);

void __percpu **hyperv_pcpu_output_arg;
EXPORT_SYMBOL_GPL(hyperv_pcpu_output_arg);

u32 hv_max_vp_index;
EXPORT_SYMBOL_GPL(hv_max_vp_index);

Expand Down Expand Up @@ -77,12 +80,19 @@ static int hv_cpu_init(unsigned int cpu)
void **input_arg;
struct page *pg;

input_arg = (void **)this_cpu_ptr(hyperv_pcpu_input_arg);
/* hv_cpu_init() can be called with IRQs disabled from hv_resume() */
pg = alloc_page(irqs_disabled() ? GFP_ATOMIC : GFP_KERNEL);
pg = alloc_pages(irqs_disabled() ? GFP_ATOMIC : GFP_KERNEL, hv_root_partition ? 1 : 0);
if (unlikely(!pg))
return -ENOMEM;

input_arg = (void **)this_cpu_ptr(hyperv_pcpu_input_arg);
*input_arg = page_address(pg);
if (hv_root_partition) {
void **output_arg;

output_arg = (void **)this_cpu_ptr(hyperv_pcpu_output_arg);
*output_arg = page_address(pg + 1);
}

hv_get_vp_index(msr_vp_index);

Expand Down Expand Up @@ -209,14 +219,23 @@ static int hv_cpu_die(unsigned int cpu)
unsigned int new_cpu;
unsigned long flags;
void **input_arg;
void *input_pg = NULL;
void *pg;

local_irq_save(flags);
input_arg = (void **)this_cpu_ptr(hyperv_pcpu_input_arg);
input_pg = *input_arg;
pg = *input_arg;
*input_arg = NULL;

if (hv_root_partition) {
void **output_arg;

output_arg = (void **)this_cpu_ptr(hyperv_pcpu_output_arg);
*output_arg = NULL;
}

local_irq_restore(flags);
free_page((unsigned long)input_pg);

free_pages((unsigned long)pg, hv_root_partition ? 1 : 0);

if (hv_vp_assist_page && hv_vp_assist_page[cpu])
wrmsrl(HV_X64_MSR_VP_ASSIST_PAGE, 0);
Expand Down Expand Up @@ -369,6 +388,12 @@ void __init hyperv_init(void)

BUG_ON(hyperv_pcpu_input_arg == NULL);

/* Allocate the per-CPU state for output arg for root */
if (hv_root_partition) {
hyperv_pcpu_output_arg = alloc_percpu(void *);
BUG_ON(hyperv_pcpu_output_arg == NULL);
}

/* Allocate percpu VP index */
hv_vp_index = kmalloc_array(num_possible_cpus(), sizeof(*hv_vp_index),
GFP_KERNEL);
Expand Down
1 change: 1 addition & 0 deletions arch/x86/include/asm/mshyperv.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ extern int hyperv_init_cpuhp;

extern void *hv_hypercall_pg;
extern void __percpu **hyperv_pcpu_input_arg;
extern void __percpu **hyperv_pcpu_output_arg;

static inline u64 hv_do_hypercall(u64 control, void *input, void *output)
{
Expand Down

0 comments on commit 5d0f077

Please sign in to comment.