From: Vitaly Kuznetsov <vkuznets@redhat.com>
To: Wei Liu <wei.liu@kernel.org>,
Linux on Hyper-V List <linux-hyperv@vger.kernel.org>
Cc: virtualization@lists.linux-foundation.org,
Linux Kernel List <linux-kernel@vger.kernel.org>,
Michael Kelley <mikelley@microsoft.com>,
Vineeth Pillai <viremana@linux.microsoft.com>,
Sunil Muthuswamy <sunilmut@microsoft.com>,
Nuno Das Neves <nunodasneves@linux.microsoft.com>,
Wei Liu <wei.liu@kernel.org>,
Lillian Grassin-Drake <ligrassi@microsoft.com>,
"K. Y. Srinivasan" <kys@microsoft.com>,
Haiyang Zhang <haiyangz@microsoft.com>,
Stephen Hemminger <sthemmin@microsoft.com>,
Thomas Gleixner <tglx@linutronix.de>,
Ingo Molnar <mingo@redhat.com>, Borislav Petkov <bp@alien8.de>,
"maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT)"
<x86@kernel.org>, "H. Peter Anvin" <hpa@zytor.com>,
Arnd Bergmann <arnd@arndb.de>,
"open list:GENERIC INCLUDE/ASM HEADER FILES"
<linux-arch@vger.kernel.org>
Subject: Re: [PATCH v2 09/17] x86/hyperv: provide a bunch of helper functions
Date: Thu, 12 Nov 2020 16:57:46 +0100 [thread overview]
Message-ID: <871rgyy3d1.fsf@vitty.brq.redhat.com> (raw)
In-Reply-To: <20201105165814.29233-10-wei.liu@kernel.org>
Wei Liu <wei.liu@kernel.org> writes:
> They are used to deposit pages into Microsoft Hypervisor and bring up
> logical and virtual processors.
>
> Signed-off-by: Lillian Grassin-Drake <ligrassi@microsoft.com>
> Signed-off-by: Sunil Muthuswamy <sunilmut@microsoft.com>
> Signed-off-by: Nuno Das Neves <nunodasneves@linux.microsoft.com>
> Co-Developed-by: Lillian Grassin-Drake <ligrassi@microsoft.com>
> Co-Developed-by: Sunil Muthuswamy <sunilmut@microsoft.com>
> Co-Developed-by: Nuno Das Neves <nunodasneves@linux.microsoft.com>
> Signed-off-by: Wei Liu <wei.liu@kernel.org>
> ---
> v2:
> 1. Adapt to hypervisor side changes
> 2. Address Vitaly's comments
> ---
> arch/x86/hyperv/Makefile | 2 +-
> arch/x86/hyperv/hv_proc.c | 217 ++++++++++++++++++++++++++++++
> arch/x86/include/asm/mshyperv.h | 4 +
> include/asm-generic/hyperv-tlfs.h | 67 +++++++++
> 4 files changed, 289 insertions(+), 1 deletion(-)
> create mode 100644 arch/x86/hyperv/hv_proc.c
>
> diff --git a/arch/x86/hyperv/Makefile b/arch/x86/hyperv/Makefile
> index 89b1f74d3225..565358020921 100644
> --- a/arch/x86/hyperv/Makefile
> +++ b/arch/x86/hyperv/Makefile
> @@ -1,6 +1,6 @@
> # SPDX-License-Identifier: GPL-2.0-only
> obj-y := hv_init.o mmu.o nested.o
> -obj-$(CONFIG_X86_64) += hv_apic.o
> +obj-$(CONFIG_X86_64) += hv_apic.o hv_proc.o
>
> ifdef CONFIG_X86_64
> obj-$(CONFIG_PARAVIRT_SPINLOCKS) += hv_spinlock.o
> diff --git a/arch/x86/hyperv/hv_proc.c b/arch/x86/hyperv/hv_proc.c
> new file mode 100644
> index 000000000000..0fd972c9129a
> --- /dev/null
> +++ b/arch/x86/hyperv/hv_proc.c
> @@ -0,0 +1,217 @@
> +// SPDX-License-Identifier: GPL-2.0
> +#include <linux/types.h>
> +#include <linux/version.h>
> +#include <linux/vmalloc.h>
> +#include <linux/mm.h>
> +#include <linux/clockchips.h>
> +#include <linux/acpi.h>
> +#include <linux/hyperv.h>
> +#include <linux/slab.h>
> +#include <linux/cpuhotplug.h>
> +#include <linux/minmax.h>
> +#include <asm/hypervisor.h>
> +#include <asm/mshyperv.h>
> +#include <asm/apic.h>
> +
> +#include <asm/trace/hyperv.h>
> +
> +#define HV_DEPOSIT_MAX_ORDER (8)
> +#define HV_DEPOSIT_MAX (1 << HV_DEPOSIT_MAX_ORDER)
> +
> +/*
> + * Deposits exact number of pages
> + * Must be called with interrupts enabled
> + * Max 256 pages
> + */
> +int hv_call_deposit_pages(int node, u64 partition_id, u32 num_pages)
> +{
> + struct page **pages;
> + int *counts;
> + int num_allocations;
> + int i, j, page_count;
> + int order;
> + int desired_order;
> + u16 status;
> + int ret;
> + u64 base_pfn;
> + struct hv_deposit_memory *input_page;
> + unsigned long flags;
> +
> + if (num_pages > HV_DEPOSIT_MAX)
> + return -E2BIG;
> + if (!num_pages)
> + return 0;
> +
> + /* One buffer for page pointers and counts */
> + pages = page_address(alloc_page(GFP_KERNEL));
> + if (!pages)
> + return -ENOMEM;
> +
> + counts = kcalloc(HV_DEPOSIT_MAX, sizeof(int), GFP_KERNEL);
> + if (!counts) {
> + free_page((unsigned long)pages);
> + return -ENOMEM;
> + }
> +
> + /* Allocate all the pages before disabling interrupts */
> + num_allocations = 0;
> + i = 0;
> + order = HV_DEPOSIT_MAX_ORDER;
> +
> + while (num_pages) {
> + /* Find highest order we can actually allocate */
> + desired_order = 31 - __builtin_clz(num_pages);
> + order = min(desired_order, order);
> + do {
> + pages[i] = alloc_pages_node(node, GFP_KERNEL, order);
> + if (!pages[i]) {
> + if (!order) {
> + ret = -ENOMEM;
> + goto err_free_allocations;
> + }
> + --order;
> + }
> + } while (!pages[i]);
> +
> + split_page(pages[i], order);
> + counts[i] = 1 << order;
> + num_pages -= counts[i];
> + i++;
> + num_allocations++;
> + }
> +
> + local_irq_save(flags);
> +
> + input_page = *this_cpu_ptr(hyperv_pcpu_input_arg);
> +
> + input_page->partition_id = partition_id;
> +
> + /* Populate gpa_page_list - these will fit on the input page */
> + for (i = 0, page_count = 0; i < num_allocations; ++i) {
> + base_pfn = page_to_pfn(pages[i]);
> + for (j = 0; j < counts[i]; ++j, ++page_count)
> + input_page->gpa_page_list[page_count] = base_pfn + j;
> + }
> + status = hv_do_rep_hypercall(HVCALL_DEPOSIT_MEMORY,
> + page_count, 0, input_page,
> + NULL) & HV_HYPERCALL_RESULT_MASK;
> + local_irq_restore(flags);
> +
> + if (status != HV_STATUS_SUCCESS) {
> + pr_err("Failed to deposit pages: %d\n", status);
> + ret = status;
> + goto err_free_allocations;
> + }
> +
> + ret = 0;
> + goto free_buf;
> +
> +err_free_allocations:
> + for (i = 0; i < num_allocations; ++i) {
> + base_pfn = page_to_pfn(pages[i]);
> + for (j = 0; j < counts[i]; ++j)
> + __free_page(pfn_to_page(base_pfn + j));
> + }
> +
> +free_buf:
> + free_page((unsigned long)pages);
> + kfree(counts);
> + return ret;
> +}
> +EXPORT_SYMBOL_GPL(hv_call_deposit_pages);
> +
> +int hv_call_add_logical_proc(int node, u32 lp_index, u32 apic_id)
> +{
> + struct hv_add_logical_processor_in *input;
> + struct hv_add_logical_processor_out *output;
> + int status;
> + unsigned long flags;
> + int ret = 0;
> +
> + /*
> + * When adding a logical processor, the hypervisor may return
> + * HV_STATUS_INSUFFICIENT_MEMORY. When that happens, we deposit more
> + * pages and retry.
> + */
> + do {
> + local_irq_save(flags);
> +
> + input = *this_cpu_ptr(hyperv_pcpu_input_arg);
> + /* We don't do anything with the output right now */
> + output = *this_cpu_ptr(hyperv_pcpu_output_arg);
> +
> + input->lp_index = lp_index;
> + input->apic_id = apic_id;
> + input->flags = 0;
> + input->proximity_domain_info.domain_id = node_to_pxm(node);
> + input->proximity_domain_info.flags.reserved = 0;
> + input->proximity_domain_info.flags.proximity_info_valid = 1;
> + input->proximity_domain_info.flags.proximity_preferred = 1;
> + status = hv_do_hypercall(HVCALL_ADD_LOGICAL_PROCESSOR,
> + input, output);
> + local_irq_restore(flags);
> +
> + if (status != HV_STATUS_INSUFFICIENT_MEMORY) {
> + if (status != HV_STATUS_SUCCESS) {
> + pr_err("%s: cpu %u apic ID %u, %d\n", __func__,
> + lp_index, apic_id, status);
> + ret = status;
> + }
> + break;
> + }
> + ret = hv_call_deposit_pages(node, hv_current_partition_id, 1);
> + } while (!ret);
> +
> + return ret;
> +}
> +
> +int hv_call_create_vp(int node, u64 partition_id, u32 vp_index, u32 flags)
> +{
> + struct hv_create_vp *input;
> + u16 status;
> + unsigned long irq_flags;
> + int ret = 0;
> +
> + /* Root VPs don't seem to need pages deposited */
> + if (partition_id != hv_current_partition_id) {
> + ret = hv_call_deposit_pages(node, partition_id, 90);
> + if (ret)
> + return ret;
> + }
> +
> + do {
> + local_irq_save(irq_flags);
> +
> + input = *this_cpu_ptr(hyperv_pcpu_input_arg);
> +
> + input->partition_id = partition_id;
> + input->vp_index = vp_index;
> + input->flags = flags;
> + input->subnode_type = HvSubnodeAny;
> + if (node != NUMA_NO_NODE) {
> + input->proximity_domain_info.domain_id = node_to_pxm(node);
> + input->proximity_domain_info.flags.reserved = 0;
> + input->proximity_domain_info.flags.proximity_info_valid = 1;
> + input->proximity_domain_info.flags.proximity_preferred = 1;
> + } else {
> + input->proximity_domain_info.as_uint64 = 0;
> + }
> + status = hv_do_hypercall(HVCALL_CREATE_VP, input, NULL);
> + local_irq_restore(irq_flags);
> +
> + if (status != HV_STATUS_INSUFFICIENT_MEMORY) {
> + if (status != HV_STATUS_SUCCESS) {
> + pr_err("%s: vcpu %u, lp %u, %d\n", __func__,
> + vp_index, flags, status);
> + ret = status;
> + }
> + break;
> + }
> + ret = hv_call_deposit_pages(node, partition_id, 1);
> +
> + } while (!ret);
> +
> + return ret;
> +}
> +EXPORT_SYMBOL_GPL(hv_call_create_vp);
> +
> diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h
> index 67f5d35a73d3..4e590a167160 100644
> --- a/arch/x86/include/asm/mshyperv.h
> +++ b/arch/x86/include/asm/mshyperv.h
> @@ -80,6 +80,10 @@ extern void __percpu **hyperv_pcpu_output_arg;
>
> extern u64 hv_current_partition_id;
>
> +int hv_call_deposit_pages(int node, u64 partition_id, u32 num_pages);
> +int hv_call_add_logical_proc(int node, u32 lp_index, u32 acpi_id);
> +int hv_call_create_vp(int node, u64 partition_id, u32 vp_index, u32 flags);
You seem to be only doing EXPORT_SYMBOL_GPL() for
hv_call_deposit_pages() and hv_call_create_vp() but not for
hv_call_add_logical_proc() - is this intended? Also, I don't see
hv_call_create_vp()/hv_call_add_logical_proc() usage outside of
arch/x86/kernel/cpu/mshyperv.c so maybe we don't need to export them at all?
> +
> static inline u64 hv_do_hypercall(u64 control, void *input, void *output)
> {
> u64 input_address = input ? virt_to_phys(input) : 0;
> diff --git a/include/asm-generic/hyperv-tlfs.h b/include/asm-generic/hyperv-tlfs.h
> index 87b1a79b19eb..b6c74e1a5524 100644
> --- a/include/asm-generic/hyperv-tlfs.h
> +++ b/include/asm-generic/hyperv-tlfs.h
> @@ -142,6 +142,8 @@ struct ms_hyperv_tsc_page {
> #define HVCALL_FLUSH_VIRTUAL_ADDRESS_LIST_EX 0x0014
> #define HVCALL_SEND_IPI_EX 0x0015
> #define HVCALL_GET_PARTITION_ID 0x0046
> +#define HVCALL_DEPOSIT_MEMORY 0x0048
> +#define HVCALL_CREATE_VP 0x004e
> #define HVCALL_GET_VP_REGISTERS 0x0050
> #define HVCALL_SET_VP_REGISTERS 0x0051
> #define HVCALL_POST_MESSAGE 0x005c
> @@ -149,6 +151,7 @@ struct ms_hyperv_tsc_page {
> #define HVCALL_POST_DEBUG_DATA 0x0069
> #define HVCALL_RETRIEVE_DEBUG_DATA 0x006a
> #define HVCALL_RESET_DEBUG_SESSION 0x006b
> +#define HVCALL_ADD_LOGICAL_PROCESSOR 0x0076
> #define HVCALL_RETARGET_INTERRUPT 0x007e
> #define HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_SPACE 0x00af
> #define HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_LIST 0x00b0
> @@ -413,6 +416,70 @@ struct hv_get_partition_id {
> u64 partition_id;
> } __packed;
>
> +/* HvDepositMemory hypercall */
> +struct hv_deposit_memory {
> + u64 partition_id;
> + u64 gpa_page_list[];
> +} __packed;
> +
> +struct hv_proximity_domain_flags {
> + u32 proximity_preferred : 1;
> + u32 reserved : 30;
> + u32 proximity_info_valid : 1;
> +};
> +
> +/* Not a union in windows but useful for zeroing */
> +union hv_proximity_domain_info {
> + struct {
> + u32 domain_id;
> + struct hv_proximity_domain_flags flags;
> + };
> + u64 as_uint64;
> +};
> +
> +struct hv_lp_startup_status {
> + u64 hv_status;
> + u64 substatus1;
> + u64 substatus2;
> + u64 substatus3;
> + u64 substatus4;
> + u64 substatus5;
> + u64 substatus6;
> +};
> +
> +/* HvAddLogicalProcessor hypercall */
> +struct hv_add_logical_processor_in {
> + u32 lp_index;
> + u32 apic_id;
> + union hv_proximity_domain_info proximity_domain_info;
> + u64 flags;
> +};
> +
> +struct hv_add_logical_processor_out {
> + struct hv_lp_startup_status startup_status;
> +};
> +
> +enum HV_SUBNODE_TYPE
> +{
> + HvSubnodeAny = 0,
> + HvSubnodeSocket,
> + HvSubnodeAmdNode,
> + HvSubnodeL3,
> + HvSubnodeCount,
> + HvSubnodeInvalid = -1
> +};
> +
> +/* HvCreateVp hypercall */
> +struct hv_create_vp {
> + u64 partition_id;
> + u32 vp_index;
> + u8 padding[3];
> + u8 subnode_type;
> + u64 subnode_id;
> + union hv_proximity_domain_info proximity_domain_info;
> + u64 flags;
> +};
You add '__packed' to 'struct hv_deposit_memory' but not to 'struct
hv_create_vp'/'struct hv_add_logical_processor_in', this looks
inconsistent.
> +
> /* HvRetargetDeviceInterrupt hypercall */
> union hv_msi_entry {
> u64 as_uint64;
--
Vitaly
WARNING: multiple messages have this Message-ID (diff)
From: Vitaly Kuznetsov <vkuznets@redhat.com>
To: Wei Liu <wei.liu@kernel.org>,
Linux on Hyper-V List <linux-hyperv@vger.kernel.org>
Cc: "open list:GENERIC INCLUDE/ASM HEADER FILES"
<linux-arch@vger.kernel.org>, Wei Liu <wei.liu@kernel.org>,
Stephen Hemminger <sthemmin@microsoft.com>,
Arnd Bergmann <arnd@arndb.de>,
Haiyang Zhang <haiyangz@microsoft.com>,
"maintainer:X86 ARCHITECTURE \(32-BIT AND 64-BIT\)"
<x86@kernel.org>,
Linux Kernel List <linux-kernel@vger.kernel.org>,
Michael Kelley <mikelley@microsoft.com>,
Ingo Molnar <mingo@redhat.com>,
Thomas Gleixner <tglx@linutronix.de>,
"H. Peter Anvin" <hpa@zytor.com>,
Nuno Das Neves <nunodasneves@linux.microsoft.com>,
Borislav Petkov <bp@alien8.de>,
Sunil Muthuswamy <sunilmut@microsoft.com>,
virtualization@lists.linux-foundation.org,
Vineeth Pillai <viremana@linux.microsoft.com>,
Lillian Grassin-Drake <ligrassi@microsoft.com>
Subject: Re: [PATCH v2 09/17] x86/hyperv: provide a bunch of helper functions
Date: Thu, 12 Nov 2020 16:57:46 +0100 [thread overview]
Message-ID: <871rgyy3d1.fsf@vitty.brq.redhat.com> (raw)
In-Reply-To: <20201105165814.29233-10-wei.liu@kernel.org>
Wei Liu <wei.liu@kernel.org> writes:
> They are used to deposit pages into Microsoft Hypervisor and bring up
> logical and virtual processors.
>
> Signed-off-by: Lillian Grassin-Drake <ligrassi@microsoft.com>
> Signed-off-by: Sunil Muthuswamy <sunilmut@microsoft.com>
> Signed-off-by: Nuno Das Neves <nunodasneves@linux.microsoft.com>
> Co-Developed-by: Lillian Grassin-Drake <ligrassi@microsoft.com>
> Co-Developed-by: Sunil Muthuswamy <sunilmut@microsoft.com>
> Co-Developed-by: Nuno Das Neves <nunodasneves@linux.microsoft.com>
> Signed-off-by: Wei Liu <wei.liu@kernel.org>
> ---
> v2:
> 1. Adapt to hypervisor side changes
> 2. Address Vitaly's comments
> ---
> arch/x86/hyperv/Makefile | 2 +-
> arch/x86/hyperv/hv_proc.c | 217 ++++++++++++++++++++++++++++++
> arch/x86/include/asm/mshyperv.h | 4 +
> include/asm-generic/hyperv-tlfs.h | 67 +++++++++
> 4 files changed, 289 insertions(+), 1 deletion(-)
> create mode 100644 arch/x86/hyperv/hv_proc.c
>
> diff --git a/arch/x86/hyperv/Makefile b/arch/x86/hyperv/Makefile
> index 89b1f74d3225..565358020921 100644
> --- a/arch/x86/hyperv/Makefile
> +++ b/arch/x86/hyperv/Makefile
> @@ -1,6 +1,6 @@
> # SPDX-License-Identifier: GPL-2.0-only
> obj-y := hv_init.o mmu.o nested.o
> -obj-$(CONFIG_X86_64) += hv_apic.o
> +obj-$(CONFIG_X86_64) += hv_apic.o hv_proc.o
>
> ifdef CONFIG_X86_64
> obj-$(CONFIG_PARAVIRT_SPINLOCKS) += hv_spinlock.o
> diff --git a/arch/x86/hyperv/hv_proc.c b/arch/x86/hyperv/hv_proc.c
> new file mode 100644
> index 000000000000..0fd972c9129a
> --- /dev/null
> +++ b/arch/x86/hyperv/hv_proc.c
> @@ -0,0 +1,217 @@
> +// SPDX-License-Identifier: GPL-2.0
> +#include <linux/types.h>
> +#include <linux/version.h>
> +#include <linux/vmalloc.h>
> +#include <linux/mm.h>
> +#include <linux/clockchips.h>
> +#include <linux/acpi.h>
> +#include <linux/hyperv.h>
> +#include <linux/slab.h>
> +#include <linux/cpuhotplug.h>
> +#include <linux/minmax.h>
> +#include <asm/hypervisor.h>
> +#include <asm/mshyperv.h>
> +#include <asm/apic.h>
> +
> +#include <asm/trace/hyperv.h>
> +
> +#define HV_DEPOSIT_MAX_ORDER (8)
> +#define HV_DEPOSIT_MAX (1 << HV_DEPOSIT_MAX_ORDER)
> +
> +/*
> + * Deposits exact number of pages
> + * Must be called with interrupts enabled
> + * Max 256 pages
> + */
> +int hv_call_deposit_pages(int node, u64 partition_id, u32 num_pages)
> +{
> + struct page **pages;
> + int *counts;
> + int num_allocations;
> + int i, j, page_count;
> + int order;
> + int desired_order;
> + u16 status;
> + int ret;
> + u64 base_pfn;
> + struct hv_deposit_memory *input_page;
> + unsigned long flags;
> +
> + if (num_pages > HV_DEPOSIT_MAX)
> + return -E2BIG;
> + if (!num_pages)
> + return 0;
> +
> + /* One buffer for page pointers and counts */
> + pages = page_address(alloc_page(GFP_KERNEL));
> + if (!pages)
> + return -ENOMEM;
> +
> + counts = kcalloc(HV_DEPOSIT_MAX, sizeof(int), GFP_KERNEL);
> + if (!counts) {
> + free_page((unsigned long)pages);
> + return -ENOMEM;
> + }
> +
> + /* Allocate all the pages before disabling interrupts */
> + num_allocations = 0;
> + i = 0;
> + order = HV_DEPOSIT_MAX_ORDER;
> +
> + while (num_pages) {
> + /* Find highest order we can actually allocate */
> + desired_order = 31 - __builtin_clz(num_pages);
> + order = min(desired_order, order);
> + do {
> + pages[i] = alloc_pages_node(node, GFP_KERNEL, order);
> + if (!pages[i]) {
> + if (!order) {
> + ret = -ENOMEM;
> + goto err_free_allocations;
> + }
> + --order;
> + }
> + } while (!pages[i]);
> +
> + split_page(pages[i], order);
> + counts[i] = 1 << order;
> + num_pages -= counts[i];
> + i++;
> + num_allocations++;
> + }
> +
> + local_irq_save(flags);
> +
> + input_page = *this_cpu_ptr(hyperv_pcpu_input_arg);
> +
> + input_page->partition_id = partition_id;
> +
> + /* Populate gpa_page_list - these will fit on the input page */
> + for (i = 0, page_count = 0; i < num_allocations; ++i) {
> + base_pfn = page_to_pfn(pages[i]);
> + for (j = 0; j < counts[i]; ++j, ++page_count)
> + input_page->gpa_page_list[page_count] = base_pfn + j;
> + }
> + status = hv_do_rep_hypercall(HVCALL_DEPOSIT_MEMORY,
> + page_count, 0, input_page,
> + NULL) & HV_HYPERCALL_RESULT_MASK;
> + local_irq_restore(flags);
> +
> + if (status != HV_STATUS_SUCCESS) {
> + pr_err("Failed to deposit pages: %d\n", status);
> + ret = status;
> + goto err_free_allocations;
> + }
> +
> + ret = 0;
> + goto free_buf;
> +
> +err_free_allocations:
> + for (i = 0; i < num_allocations; ++i) {
> + base_pfn = page_to_pfn(pages[i]);
> + for (j = 0; j < counts[i]; ++j)
> + __free_page(pfn_to_page(base_pfn + j));
> + }
> +
> +free_buf:
> + free_page((unsigned long)pages);
> + kfree(counts);
> + return ret;
> +}
> +EXPORT_SYMBOL_GPL(hv_call_deposit_pages);
> +
> +int hv_call_add_logical_proc(int node, u32 lp_index, u32 apic_id)
> +{
> + struct hv_add_logical_processor_in *input;
> + struct hv_add_logical_processor_out *output;
> + int status;
> + unsigned long flags;
> + int ret = 0;
> +
> + /*
> + * When adding a logical processor, the hypervisor may return
> + * HV_STATUS_INSUFFICIENT_MEMORY. When that happens, we deposit more
> + * pages and retry.
> + */
> + do {
> + local_irq_save(flags);
> +
> + input = *this_cpu_ptr(hyperv_pcpu_input_arg);
> + /* We don't do anything with the output right now */
> + output = *this_cpu_ptr(hyperv_pcpu_output_arg);
> +
> + input->lp_index = lp_index;
> + input->apic_id = apic_id;
> + input->flags = 0;
> + input->proximity_domain_info.domain_id = node_to_pxm(node);
> + input->proximity_domain_info.flags.reserved = 0;
> + input->proximity_domain_info.flags.proximity_info_valid = 1;
> + input->proximity_domain_info.flags.proximity_preferred = 1;
> + status = hv_do_hypercall(HVCALL_ADD_LOGICAL_PROCESSOR,
> + input, output);
> + local_irq_restore(flags);
> +
> + if (status != HV_STATUS_INSUFFICIENT_MEMORY) {
> + if (status != HV_STATUS_SUCCESS) {
> + pr_err("%s: cpu %u apic ID %u, %d\n", __func__,
> + lp_index, apic_id, status);
> + ret = status;
> + }
> + break;
> + }
> + ret = hv_call_deposit_pages(node, hv_current_partition_id, 1);
> + } while (!ret);
> +
> + return ret;
> +}
> +
> +int hv_call_create_vp(int node, u64 partition_id, u32 vp_index, u32 flags)
> +{
> + struct hv_create_vp *input;
> + u16 status;
> + unsigned long irq_flags;
> + int ret = 0;
> +
> + /* Root VPs don't seem to need pages deposited */
> + if (partition_id != hv_current_partition_id) {
> + ret = hv_call_deposit_pages(node, partition_id, 90);
> + if (ret)
> + return ret;
> + }
> +
> + do {
> + local_irq_save(irq_flags);
> +
> + input = *this_cpu_ptr(hyperv_pcpu_input_arg);
> +
> + input->partition_id = partition_id;
> + input->vp_index = vp_index;
> + input->flags = flags;
> + input->subnode_type = HvSubnodeAny;
> + if (node != NUMA_NO_NODE) {
> + input->proximity_domain_info.domain_id = node_to_pxm(node);
> + input->proximity_domain_info.flags.reserved = 0;
> + input->proximity_domain_info.flags.proximity_info_valid = 1;
> + input->proximity_domain_info.flags.proximity_preferred = 1;
> + } else {
> + input->proximity_domain_info.as_uint64 = 0;
> + }
> + status = hv_do_hypercall(HVCALL_CREATE_VP, input, NULL);
> + local_irq_restore(irq_flags);
> +
> + if (status != HV_STATUS_INSUFFICIENT_MEMORY) {
> + if (status != HV_STATUS_SUCCESS) {
> + pr_err("%s: vcpu %u, lp %u, %d\n", __func__,
> + vp_index, flags, status);
> + ret = status;
> + }
> + break;
> + }
> + ret = hv_call_deposit_pages(node, partition_id, 1);
> +
> + } while (!ret);
> +
> + return ret;
> +}
> +EXPORT_SYMBOL_GPL(hv_call_create_vp);
> +
> diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h
> index 67f5d35a73d3..4e590a167160 100644
> --- a/arch/x86/include/asm/mshyperv.h
> +++ b/arch/x86/include/asm/mshyperv.h
> @@ -80,6 +80,10 @@ extern void __percpu **hyperv_pcpu_output_arg;
>
> extern u64 hv_current_partition_id;
>
> +int hv_call_deposit_pages(int node, u64 partition_id, u32 num_pages);
> +int hv_call_add_logical_proc(int node, u32 lp_index, u32 acpi_id);
> +int hv_call_create_vp(int node, u64 partition_id, u32 vp_index, u32 flags);
You seem to be only doing EXPORT_SYMBOL_GPL() for
hv_call_deposit_pages() and hv_call_create_vp() but not for
hv_call_add_logical_proc() - is this intended? Also, I don't see
hv_call_create_vp()/hv_call_add_logical_proc() usage outside of
arch/x86/kernel/cpu/mshyperv.c so maybe we don't need to export them at all?
> +
> static inline u64 hv_do_hypercall(u64 control, void *input, void *output)
> {
> u64 input_address = input ? virt_to_phys(input) : 0;
> diff --git a/include/asm-generic/hyperv-tlfs.h b/include/asm-generic/hyperv-tlfs.h
> index 87b1a79b19eb..b6c74e1a5524 100644
> --- a/include/asm-generic/hyperv-tlfs.h
> +++ b/include/asm-generic/hyperv-tlfs.h
> @@ -142,6 +142,8 @@ struct ms_hyperv_tsc_page {
> #define HVCALL_FLUSH_VIRTUAL_ADDRESS_LIST_EX 0x0014
> #define HVCALL_SEND_IPI_EX 0x0015
> #define HVCALL_GET_PARTITION_ID 0x0046
> +#define HVCALL_DEPOSIT_MEMORY 0x0048
> +#define HVCALL_CREATE_VP 0x004e
> #define HVCALL_GET_VP_REGISTERS 0x0050
> #define HVCALL_SET_VP_REGISTERS 0x0051
> #define HVCALL_POST_MESSAGE 0x005c
> @@ -149,6 +151,7 @@ struct ms_hyperv_tsc_page {
> #define HVCALL_POST_DEBUG_DATA 0x0069
> #define HVCALL_RETRIEVE_DEBUG_DATA 0x006a
> #define HVCALL_RESET_DEBUG_SESSION 0x006b
> +#define HVCALL_ADD_LOGICAL_PROCESSOR 0x0076
> #define HVCALL_RETARGET_INTERRUPT 0x007e
> #define HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_SPACE 0x00af
> #define HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_LIST 0x00b0
> @@ -413,6 +416,70 @@ struct hv_get_partition_id {
> u64 partition_id;
> } __packed;
>
> +/* HvDepositMemory hypercall */
> +struct hv_deposit_memory {
> + u64 partition_id;
> + u64 gpa_page_list[];
> +} __packed;
> +
> +struct hv_proximity_domain_flags {
> + u32 proximity_preferred : 1;
> + u32 reserved : 30;
> + u32 proximity_info_valid : 1;
> +};
> +
> +/* Not a union in windows but useful for zeroing */
> +union hv_proximity_domain_info {
> + struct {
> + u32 domain_id;
> + struct hv_proximity_domain_flags flags;
> + };
> + u64 as_uint64;
> +};
> +
> +struct hv_lp_startup_status {
> + u64 hv_status;
> + u64 substatus1;
> + u64 substatus2;
> + u64 substatus3;
> + u64 substatus4;
> + u64 substatus5;
> + u64 substatus6;
> +};
> +
> +/* HvAddLogicalProcessor hypercall */
> +struct hv_add_logical_processor_in {
> + u32 lp_index;
> + u32 apic_id;
> + union hv_proximity_domain_info proximity_domain_info;
> + u64 flags;
> +};
> +
> +struct hv_add_logical_processor_out {
> + struct hv_lp_startup_status startup_status;
> +};
> +
> +enum HV_SUBNODE_TYPE
> +{
> + HvSubnodeAny = 0,
> + HvSubnodeSocket,
> + HvSubnodeAmdNode,
> + HvSubnodeL3,
> + HvSubnodeCount,
> + HvSubnodeInvalid = -1
> +};
> +
> +/* HvCreateVp hypercall */
> +struct hv_create_vp {
> + u64 partition_id;
> + u32 vp_index;
> + u8 padding[3];
> + u8 subnode_type;
> + u64 subnode_id;
> + union hv_proximity_domain_info proximity_domain_info;
> + u64 flags;
> +};
You add '__packed' to 'struct hv_deposit_memory' but not to 'struct
hv_create_vp'/'struct hv_add_logical_processor_in', this looks
inconsistent.
> +
> /* HvRetargetDeviceInterrupt hypercall */
> union hv_msi_entry {
> u64 as_uint64;
--
Vitaly
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
next prev parent reply other threads:[~2020-11-12 15:57 UTC|newest]
Thread overview: 88+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-11-05 16:57 [PATCH v2 00/17] Introducing Linux root partition support for Microsoft Hypervisor Wei Liu
2020-11-05 16:57 ` [PATCH v2 01/17] asm-generic/hyperv: change HV_CPU_POWER_MANAGEMENT to HV_CPU_MANAGEMENT Wei Liu
2020-11-12 15:14 ` Vitaly Kuznetsov
2020-11-12 15:14 ` Vitaly Kuznetsov
2020-11-05 16:57 ` [PATCH v2 02/17] x86/hyperv: detect if Linux is the root partition Wei Liu
2020-11-05 19:16 ` kernel test robot
2020-11-05 19:16 ` kernel test robot
2020-11-05 19:16 ` kernel test robot
2020-11-12 11:42 ` Wei Liu
2020-11-12 11:42 ` Wei Liu
2020-11-12 11:46 ` Wei Liu
2020-11-12 11:46 ` Wei Liu
2020-11-12 12:22 ` Wei Liu
2020-11-12 12:22 ` Wei Liu
2020-11-05 20:23 ` kernel test robot
2020-11-05 20:23 ` kernel test robot
2020-11-05 20:23 ` kernel test robot
2020-11-12 15:16 ` Vitaly Kuznetsov
2020-11-12 15:16 ` Vitaly Kuznetsov
2020-11-12 15:51 ` Wei Liu
2020-11-05 16:58 ` [PATCH v2 03/17] Drivers: hv: vmbus: skip VMBus initialization if Linux is root Wei Liu
2020-11-12 15:24 ` Vitaly Kuznetsov
2020-11-12 15:24 ` Vitaly Kuznetsov
2020-11-13 14:51 ` Wei Liu
2020-11-05 16:58 ` [PATCH v2 04/17] iommu/hyperv: don't setup IRQ remapping when running as root Wei Liu
2020-11-05 16:58 ` Wei Liu
2020-11-12 15:27 ` Vitaly Kuznetsov
2020-11-12 15:27 ` Vitaly Kuznetsov
2020-11-12 15:27 ` Vitaly Kuznetsov
2020-11-13 14:53 ` Wei Liu
2020-11-13 14:53 ` Wei Liu
2020-11-05 16:58 ` [PATCH v2 05/17] clocksource/hyperv: use MSR-based access if " Wei Liu
2020-11-12 9:56 ` Daniel Lezcano
2020-11-12 9:56 ` Daniel Lezcano
2020-11-12 11:24 ` Wei Liu
2020-11-12 11:40 ` Daniel Lezcano
2020-11-12 11:40 ` Daniel Lezcano
2020-11-12 11:42 ` Wei Liu
2020-11-12 15:30 ` Vitaly Kuznetsov
2020-11-12 15:30 ` Vitaly Kuznetsov
2020-11-12 15:52 ` Wei Liu
2020-11-05 16:58 ` [PATCH v2 06/17] x86/hyperv: allocate output arg pages if required Wei Liu
2020-11-12 15:35 ` Vitaly Kuznetsov
2020-11-12 15:35 ` Vitaly Kuznetsov
2020-11-13 15:05 ` Wei Liu
2020-11-05 16:58 ` [PATCH v2 07/17] x86/hyperv: extract partition ID from Microsoft Hypervisor if necessary Wei Liu
2020-11-05 20:07 ` kernel test robot
2020-11-05 20:07 ` kernel test robot
2020-11-05 20:07 ` kernel test robot
2020-11-12 11:54 ` Wei Liu
2020-11-12 11:54 ` Wei Liu
2020-11-05 20:20 ` kernel test robot
2020-11-05 20:20 ` kernel test robot
2020-11-05 20:20 ` kernel test robot
2020-11-12 15:44 ` Vitaly Kuznetsov
2020-11-12 15:44 ` Vitaly Kuznetsov
2020-11-13 15:21 ` Wei Liu
2020-11-05 16:58 ` [PATCH v2 08/17] x86/hyperv: handling hypercall page setup for root Wei Liu
2020-11-12 15:51 ` Vitaly Kuznetsov
2020-11-12 15:51 ` Vitaly Kuznetsov
2020-11-13 15:33 ` Wei Liu
2020-11-13 16:09 ` Wei Liu
2020-11-13 16:16 ` Vitaly Kuznetsov
2020-11-13 16:16 ` Vitaly Kuznetsov
2020-11-05 16:58 ` [PATCH v2 09/17] x86/hyperv: provide a bunch of helper functions Wei Liu
2020-11-12 15:57 ` Vitaly Kuznetsov [this message]
2020-11-12 15:57 ` Vitaly Kuznetsov
2020-11-13 15:51 ` Wei Liu
2020-11-13 16:13 ` Vitaly Kuznetsov
2020-11-13 16:13 ` Vitaly Kuznetsov
2020-11-16 11:41 ` Wei Liu
2020-11-05 16:58 ` [PATCH v2 10/17] x86/hyperv: implement and use hv_smp_prepare_cpus Wei Liu
2020-11-12 16:44 ` Vitaly Kuznetsov
2020-11-12 16:44 ` Vitaly Kuznetsov
2020-11-13 15:56 ` Wei Liu
2020-11-05 16:58 ` [PATCH v2 11/17] asm-generic/hyperv: update hv_msi_entry Wei Liu
2020-11-05 16:58 ` [PATCH v2 12/17] asm-generic/hyperv: update hv_interrupt_entry Wei Liu
2020-11-05 16:58 ` [PATCH v2 13/17] asm-generic/hyperv: introduce hv_device_id and auxiliary structures Wei Liu
2020-11-05 16:58 ` [PATCH v2 14/17] asm-generic/hyperv: import data structures for mapping device interrupts Wei Liu
2020-11-05 16:58 ` [PATCH v2 15/17] x86/hyperv: implement an MSI domain for root partition Wei Liu
2020-11-12 13:50 ` Wei Liu
2020-11-05 16:58 ` [PATCH v2 16/17] x86/ioapic: export a few functions and data structures via io_apic.h Wei Liu
2020-11-12 11:39 ` Wei Liu
2020-11-05 16:58 ` [PATCH v2 17/17] x86/hyperv: handle IO-APIC when running as root Wei Liu
2020-11-12 16:56 ` Vitaly Kuznetsov
2020-11-12 16:56 ` Vitaly Kuznetsov
2020-11-13 16:01 ` Wei Liu
2020-11-13 16:04 ` Wei Liu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=871rgyy3d1.fsf@vitty.brq.redhat.com \
--to=vkuznets@redhat.com \
--cc=arnd@arndb.de \
--cc=bp@alien8.de \
--cc=haiyangz@microsoft.com \
--cc=hpa@zytor.com \
--cc=kys@microsoft.com \
--cc=ligrassi@microsoft.com \
--cc=linux-arch@vger.kernel.org \
--cc=linux-hyperv@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mikelley@microsoft.com \
--cc=mingo@redhat.com \
--cc=nunodasneves@linux.microsoft.com \
--cc=sthemmin@microsoft.com \
--cc=sunilmut@microsoft.com \
--cc=tglx@linutronix.de \
--cc=viremana@linux.microsoft.com \
--cc=virtualization@lists.linux-foundation.org \
--cc=wei.liu@kernel.org \
--cc=x86@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.