From nobody Wed Dec 17 19:36:25 2025 Received: from linux.microsoft.com (linux.microsoft.com [13.77.154.182]) by smtp.subspace.kernel.org (Postfix) with ESMTP id D605E22C6DC; Fri, 6 Dec 2024 22:22:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=13.77.154.182 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733523739; cv=none; b=gfQRMQYnyKCwDNV984lMMJ2Pwqn5gwv8vjeFo7OVAEW2T/JOOriJSEN6OjKgQndCVJeZDlVo+vthsTFjy7+IWzdQpm2EbHoe3+7yxZJQtxRQrv62O35EnP/G4dt6ElkzJhSRRO8lOVTA0+OM4u4BQD5WaZnGD8u8xIJVHzcQbG8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733523739; c=relaxed/simple; bh=xUmbyKLvkGB4VPSmMjoluR8Mm89ECKjpxvLaTWBfTcY=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References; b=d3aTLUtjHuRiRO5k3dQoZWI1tPjFHzCXJqzEgvIv1G8zecO8Bolusgcx5QK03k3q/UBnKp/9DlU4ZBoDIcVlSFxOL4yHMIJgxf0DKmp8Y4MVNszDTKcNDvbZ68rFqP7Q/zWuZ+xcOnwlW0fqn6IEeDCG0J3CHVHnptrKtkc3V5o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.microsoft.com; spf=pass smtp.mailfrom=linux.microsoft.com; dkim=pass (1024-bit key) header.d=linux.microsoft.com header.i=@linux.microsoft.com header.b=REA7xsYY; arc=none smtp.client-ip=13.77.154.182 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.microsoft.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.microsoft.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.microsoft.com header.i=@linux.microsoft.com header.b="REA7xsYY" Received: from linuxonhyperv3.guj3yctzbm1etfxqx2vob5hsef.xx.internal.cloudapp.net (linux.microsoft.com [13.77.154.182]) by linux.microsoft.com (Postfix) with ESMTPSA id 3B4EA20ACD99; Fri, 6 Dec 2024 14:22:17 -0800 (PST) DKIM-Filter: OpenDKIM Filter v2.11.0 linux.microsoft.com 3B4EA20ACD99 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.microsoft.com; s=default; t=1733523737; bh=zsSiUfsZewJqYJI/h0zpl0Mh++LhbcoDiROgPlX5NJA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=REA7xsYYwqr9vixfJU9WmxCH9z4BusWtpGeeRdy7mvsMagzauApyIP5p7RXzSr4Lo GpMr9/uuGKONGk+OhB0kIK4asAD5nQbKWHx6iMciJybaHapya1t4jNL/ns4uPhPlK7 UI3kTzx8xcuf4Nso/fmbVNchwbUwu1hxkqfW13T4= From: Nuno Das Neves To: linux-hyperv@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-arch@vger.kernel.org Cc: kys@microsoft.com, haiyangz@microsoft.com, wei.liu@kernel.org, mhklinux@outlook.com, decui@microsoft.com, catalin.marinas@arm.com, will@kernel.org, tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, dave.hansen@linux.intel.com, x86@kernel.org, hpa@zytor.com, arnd@arndb.de, jinankjain@linux.microsoft.com, muminulrussell@gmail.com, skinsburskii@linux.microsoft.com, mukeshrathor@microsoft.com Subject: [PATCH 1/2] hyperv: Move hv_current_partition_id to arch-generic code Date: Fri, 6 Dec 2024 14:21:46 -0800 Message-Id: <1733523707-15954-2-git-send-email-nunodasneves@linux.microsoft.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1733523707-15954-1-git-send-email-nunodasneves@linux.microsoft.com> References: <1733523707-15954-1-git-send-email-nunodasneves@linux.microsoft.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Nuno Das Neves Make hv_current_partition_id available in both x86_64 and arm64. This feature isn't specific to x86_64 and will be needed by common code. While at it, replace the BUG()s with WARN()s. Failing to get the id need not crash the machine (although it is a very bad sign). Signed-off-by: Nuno Das Neves --- arch/arm64/hyperv/mshyperv.c | 3 +++ arch/x86/hyperv/hv_init.c | 25 +------------------------ arch/x86/include/asm/mshyperv.h | 2 -- drivers/hv/hv_common.c | 23 +++++++++++++++++++++++ include/asm-generic/mshyperv.h | 2 ++ 5 files changed, 29 insertions(+), 26 deletions(-) diff --git a/arch/arm64/hyperv/mshyperv.c b/arch/arm64/hyperv/mshyperv.c index b1a4de4eee29..5050e748d266 100644 --- a/arch/arm64/hyperv/mshyperv.c +++ b/arch/arm64/hyperv/mshyperv.c @@ -19,6 +19,9 @@ =20 static bool hyperv_initialized; =20 +u64 hv_current_partition_id =3D HV_PARTITION_ID_SELF; +EXPORT_SYMBOL_GPL(hv_current_partition_id); + int hv_get_hypervisor_version(union hv_hypervisor_version_info *info) { hv_get_vpreg_128(HV_REGISTER_HYPERVISOR_VERSION, diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c index 95eada2994e1..950f5ccdb9d9 100644 --- a/arch/x86/hyperv/hv_init.c +++ b/arch/x86/hyperv/hv_init.c @@ -35,7 +35,7 @@ #include #include =20 -u64 hv_current_partition_id =3D ~0ull; +u64 hv_current_partition_id =3D HV_PARTITION_ID_SELF; EXPORT_SYMBOL_GPL(hv_current_partition_id); =20 void *hv_hypercall_pg; @@ -394,24 +394,6 @@ static void __init hv_stimer_setup_percpu_clockev(void) old_setup_percpu_clockev(); } =20 -static void __init hv_get_partition_id(void) -{ - struct hv_get_partition_id *output_page; - u64 status; - unsigned long flags; - - local_irq_save(flags); - output_page =3D *this_cpu_ptr(hyperv_pcpu_output_arg); - status =3D hv_do_hypercall(HVCALL_GET_PARTITION_ID, NULL, output_page); - if (!hv_result_success(status)) { - /* No point in proceeding if this failed */ - pr_err("Failed to get partition ID: %lld\n", status); - BUG(); - } - hv_current_partition_id =3D output_page->partition_id; - local_irq_restore(flags); -} - #if IS_ENABLED(CONFIG_HYPERV_VTL_MODE) static u8 __init get_vtl(void) { @@ -606,11 +588,6 @@ void __init hyperv_init(void) =20 register_syscore_ops(&hv_syscore_ops); =20 - if (cpuid_ebx(HYPERV_CPUID_FEATURES) & HV_ACCESS_PARTITION_ID) - hv_get_partition_id(); - - BUG_ON(hv_root_partition && hv_current_partition_id =3D=3D ~0ull); - #ifdef CONFIG_PCI_MSI /* * If we're running as root, we want to create our own PCI MSI domain. diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyper= v.h index 5f0bc6a6d025..9eeca2a6d047 100644 --- a/arch/x86/include/asm/mshyperv.h +++ b/arch/x86/include/asm/mshyperv.h @@ -44,8 +44,6 @@ extern bool hyperv_paravisor_present; =20 extern void *hv_hypercall_pg; =20 -extern u64 hv_current_partition_id; - extern union hv_ghcb * __percpu *hv_ghcb_pg; =20 bool hv_isolation_type_snp(void); diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c index 7a35c82976e0..819bcfd2b149 100644 --- a/drivers/hv/hv_common.c +++ b/drivers/hv/hv_common.c @@ -278,11 +278,34 @@ static void hv_kmsg_dump_register(void) } } =20 +static void __init hv_get_partition_id(void) +{ + struct hv_get_partition_id *output_page; + u64 status; + unsigned long flags; + + local_irq_save(flags); + output_page =3D *this_cpu_ptr(hyperv_pcpu_output_arg); + status =3D hv_do_hypercall(HVCALL_GET_PARTITION_ID, NULL, output_page); + if (!hv_result_success(status)) { + local_irq_restore(flags); + WARN(true, "Failed to get partition ID: %lld\n", status); + return; + } + hv_current_partition_id =3D output_page->partition_id; + local_irq_restore(flags); +} + int __init hv_common_init(void) { int i; union hv_hypervisor_version_info version; =20 + if (ms_hyperv.priv_high & HV_ACCESS_PARTITION_ID) + hv_get_partition_id(); + + WARN_ON(hv_root_partition && hv_current_partition_id =3D=3D HV_PARTITION_= ID_SELF); + /* Get information about the Hyper-V host version */ if (!hv_get_hypervisor_version(&version)) pr_info("Hyper-V: Host Build %d.%d.%d.%d-%d-%d\n", diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h index 8fe7aaab2599..8c4ff6e9aae7 100644 --- a/include/asm-generic/mshyperv.h +++ b/include/asm-generic/mshyperv.h @@ -60,6 +60,8 @@ struct ms_hyperv_info { extern struct ms_hyperv_info ms_hyperv; extern bool hv_nested; =20 +extern u64 hv_current_partition_id; + extern void * __percpu *hyperv_pcpu_input_arg; extern void * __percpu *hyperv_pcpu_output_arg; =20 --=20 2.34.1 From nobody Wed Dec 17 19:36:25 2025 Received: from linux.microsoft.com (linux.microsoft.com [13.77.154.182]) by smtp.subspace.kernel.org (Postfix) with ESMTP id B013422C6C1; Fri, 6 Dec 2024 22:22:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=13.77.154.182 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733523739; cv=none; b=JsF+u07dhXvhse/UUpybUialB7SkOGB1pyJ0hRdvBqUz3U+Y1ItUwtsH8s3vjPaa2kUhRSRvKPLxUu4Ik7ohquGwLZTeGzzAHWugJ82EEWCQnCEZYSRGGH4RIVrHOPiyfeiszQyDdFILPTkdp2kQAMCX7svovkfASlHe+fB9YXg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733523739; c=relaxed/simple; bh=ehV2KIoYo1qG3BcEdWXbUpZdwJhZlqDkPnxpl0xoZP8=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References; b=fxBNsx6FqphshvmVp9wsLwhX5qMiHxvPEhsRyZ13mwuzn1w9AJvC7g7p36iVTim50yT2KGxBzmZ5SvFQx66iwBHLDl54r6/GKhYm0rWjkGdlvNbsT1f42AARcvrVebSCnfzGU2dBboMzpZ7AO8ETCMrMu8Zgwarn0HKixcIfpeY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.microsoft.com; spf=pass smtp.mailfrom=linux.microsoft.com; dkim=pass (1024-bit key) header.d=linux.microsoft.com header.i=@linux.microsoft.com header.b=sWQ0SH08; arc=none smtp.client-ip=13.77.154.182 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.microsoft.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.microsoft.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.microsoft.com header.i=@linux.microsoft.com header.b="sWQ0SH08" Received: from linuxonhyperv3.guj3yctzbm1etfxqx2vob5hsef.xx.internal.cloudapp.net (linux.microsoft.com [13.77.154.182]) by linux.microsoft.com (Postfix) with ESMTPSA id 5583F20ACD9A; Fri, 6 Dec 2024 14:22:17 -0800 (PST) DKIM-Filter: OpenDKIM Filter v2.11.0 linux.microsoft.com 5583F20ACD9A DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.microsoft.com; s=default; t=1733523737; bh=qWhJO32QaX3zCsv7TE/p5YopM8ATfeZewveYiJmJv4o=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=sWQ0SH08qm9VeXGl27eQ7mStuAPq1heKmJyhk3J6cj9XUjc8DFgaG+08qqeATQszN En7kA8JL0Zkwh0/pBwysDXySLzYD7lw6gRiinipklXpaQypollKkxKcmKs4gTZ/eWg t9tL+IQodGWl8dNVT7ugatUSEdOW5unboz6+FCiQ= From: Nuno Das Neves To: linux-hyperv@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-arch@vger.kernel.org Cc: kys@microsoft.com, haiyangz@microsoft.com, wei.liu@kernel.org, mhklinux@outlook.com, decui@microsoft.com, catalin.marinas@arm.com, will@kernel.org, tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, dave.hansen@linux.intel.com, x86@kernel.org, hpa@zytor.com, arnd@arndb.de, jinankjain@linux.microsoft.com, muminulrussell@gmail.com, skinsburskii@linux.microsoft.com, mukeshrathor@microsoft.com Subject: [PATCH 2/2] hyperv: Move create_vp and deposit_pages hvcalls to hv_common.c Date: Fri, 6 Dec 2024 14:21:47 -0800 Message-Id: <1733523707-15954-3-git-send-email-nunodasneves@linux.microsoft.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1733523707-15954-1-git-send-email-nunodasneves@linux.microsoft.com> References: <1733523707-15954-1-git-send-email-nunodasneves@linux.microsoft.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Nuno Das Neves These are not specific to x86_64 and will be needed by common code. Signed-off-by: Nuno Das Neves Acked-by: Wei Liu --- arch/x86/hyperv/hv_proc.c | 144 ------------------------------- arch/x86/include/asm/mshyperv.h | 2 - drivers/hv/hv_common.c | 145 ++++++++++++++++++++++++++++++++ include/asm-generic/mshyperv.h | 2 + 4 files changed, 147 insertions(+), 146 deletions(-) diff --git a/arch/x86/hyperv/hv_proc.c b/arch/x86/hyperv/hv_proc.c index 3fa1f2ee7b0d..119354d00637 100644 --- a/arch/x86/hyperv/hv_proc.c +++ b/arch/x86/hyperv/hv_proc.c @@ -10,109 +10,8 @@ #include #include #include - #include =20 -/* - * See struct hv_deposit_memory. The first u64 is partition ID, the rest - * are GPAs. - */ -#define HV_DEPOSIT_MAX (HV_HYP_PAGE_SIZE / sizeof(u64) - 1) - -/* Deposits exact number of pages. Must be called with interrupts enabled.= */ -int hv_call_deposit_pages(int node, u64 partition_id, u32 num_pages) -{ - struct page **pages, *page; - int *counts; - int num_allocations; - int i, j, page_count; - int order; - u64 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 */ - page =3D alloc_page(GFP_KERNEL); - if (!page) - return -ENOMEM; - pages =3D page_address(page); - - counts =3D kcalloc(HV_DEPOSIT_MAX, sizeof(int), GFP_KERNEL); - if (!counts) { - free_page((unsigned long)pages); - return -ENOMEM; - } - - /* Allocate all the pages before disabling interrupts */ - i =3D 0; - - while (num_pages) { - /* Find highest order we can actually allocate */ - order =3D 31 - __builtin_clz(num_pages); - - while (1) { - pages[i] =3D alloc_pages_node(node, GFP_KERNEL, order); - if (pages[i]) - break; - if (!order) { - ret =3D -ENOMEM; - num_allocations =3D i; - goto err_free_allocations; - } - --order; - } - - split_page(pages[i], order); - counts[i] =3D 1 << order; - num_pages -=3D counts[i]; - i++; - } - num_allocations =3D i; - - local_irq_save(flags); - - input_page =3D *this_cpu_ptr(hyperv_pcpu_input_arg); - - input_page->partition_id =3D partition_id; - - /* Populate gpa_page_list - these will fit on the input page */ - for (i =3D 0, page_count =3D 0; i < num_allocations; ++i) { - base_pfn =3D page_to_pfn(pages[i]); - for (j =3D 0; j < counts[i]; ++j, ++page_count) - input_page->gpa_page_list[page_count] =3D base_pfn + j; - } - status =3D hv_do_rep_hypercall(HVCALL_DEPOSIT_MEMORY, - page_count, 0, input_page, NULL); - local_irq_restore(flags); - if (!hv_result_success(status)) { - pr_err("Failed to deposit pages: %lld\n", status); - ret =3D hv_result(status); - goto err_free_allocations; - } - - ret =3D 0; - goto free_buf; - -err_free_allocations: - for (i =3D 0; i < num_allocations; ++i) { - base_pfn =3D page_to_pfn(pages[i]); - for (j =3D 0; j < counts[i]; ++j) - __free_page(pfn_to_page(base_pfn + j)); - } - -free_buf: - free_page((unsigned long)pages); - kfree(counts); - return ret; -} - int hv_call_add_logical_proc(int node, u32 lp_index, u32 apic_id) { struct hv_input_add_logical_processor *input; @@ -154,46 +53,3 @@ int hv_call_add_logical_proc(int node, u32 lp_index, u3= 2 apic_id) return ret; } =20 -int hv_call_create_vp(int node, u64 partition_id, u32 vp_index, u32 flags) -{ - struct hv_create_vp *input; - u64 status; - unsigned long irq_flags; - int ret =3D HV_STATUS_SUCCESS; - - /* Root VPs don't seem to need pages deposited */ - if (partition_id !=3D hv_current_partition_id) { - /* The value 90 is empirically determined. It may change. */ - ret =3D hv_call_deposit_pages(node, partition_id, 90); - if (ret) - return ret; - } - - do { - local_irq_save(irq_flags); - - input =3D *this_cpu_ptr(hyperv_pcpu_input_arg); - - input->partition_id =3D partition_id; - input->vp_index =3D vp_index; - input->flags =3D flags; - input->subnode_type =3D HvSubnodeAny; - input->proximity_domain_info =3D hv_numa_node_to_pxm_info(node); - status =3D hv_do_hypercall(HVCALL_CREATE_VP, input, NULL); - local_irq_restore(irq_flags); - - if (hv_result(status) !=3D HV_STATUS_INSUFFICIENT_MEMORY) { - if (!hv_result_success(status)) { - pr_err("%s: vcpu %u, lp %u, %lld\n", __func__, - vp_index, flags, status); - ret =3D hv_result(status); - } - break; - } - ret =3D hv_call_deposit_pages(node, partition_id, 1); - - } while (!ret); - - return ret; -} - diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyper= v.h index 9eeca2a6d047..5bad88cfccba 100644 --- a/arch/x86/include/asm/mshyperv.h +++ b/arch/x86/include/asm/mshyperv.h @@ -57,9 +57,7 @@ u64 hv_tdx_hypercall(u64 control, u64 param1, u64 param2); #define HV_AP_INIT_GPAT_DEFAULT 0x0007040600070406ULL #define HV_AP_SEGMENT_LIMIT 0xffffffff =20 -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); =20 /* * If the hypercall involves no input or output parameters, the hypervisor diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c index 819bcfd2b149..591cc51e8817 100644 --- a/drivers/hv/hv_common.c +++ b/drivers/hv/hv_common.c @@ -679,3 +679,148 @@ u64 __weak hv_tdx_hypercall(u64 control, u64 param1, = u64 param2) return HV_STATUS_INVALID_PARAMETER; } EXPORT_SYMBOL_GPL(hv_tdx_hypercall); + +int hv_call_create_vp(int node, u64 partition_id, u32 vp_index, u32 flags) +{ + struct hv_create_vp *input; + u64 status; + unsigned long irq_flags; + int ret =3D HV_STATUS_SUCCESS; + + /* Root VPs don't seem to need pages deposited */ + if (partition_id !=3D hv_current_partition_id) { + /* The value 90 is empirically determined. It may change. */ + ret =3D hv_call_deposit_pages(node, partition_id, 90); + if (ret) + return ret; + } + + do { + local_irq_save(irq_flags); + + input =3D *this_cpu_ptr(hyperv_pcpu_input_arg); + + input->partition_id =3D partition_id; + input->vp_index =3D vp_index; + input->flags =3D flags; + input->subnode_type =3D HvSubnodeAny; + input->proximity_domain_info =3D hv_numa_node_to_pxm_info(node); + status =3D hv_do_hypercall(HVCALL_CREATE_VP, input, NULL); + local_irq_restore(irq_flags); + + if (hv_result(status) !=3D HV_STATUS_INSUFFICIENT_MEMORY) { + if (!hv_result_success(status)) { + pr_err("%s: vcpu %u, lp %u, %lld\n", __func__, + vp_index, flags, status); + ret =3D hv_result(status); + } + break; + } + ret =3D hv_call_deposit_pages(node, partition_id, 1); + + } while (!ret); + + return ret; +} +EXPORT_SYMBOL_GPL(hv_call_create_vp); + +/* + * See struct hv_deposit_memory. The first u64 is partition ID, the rest + * are GPAs. + */ +#define HV_DEPOSIT_MAX (HV_HYP_PAGE_SIZE / sizeof(u64) - 1) + +/* Deposits exact number of pages. Must be called with interrupts enabled.= */ +int hv_call_deposit_pages(int node, u64 partition_id, u32 num_pages) +{ + struct page **pages, *page; + int *counts; + int num_allocations; + int i, j, page_count; + int order; + u64 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 */ + page =3D alloc_page(GFP_KERNEL); + if (!page) + return -ENOMEM; + pages =3D page_address(page); + + counts =3D kcalloc(HV_DEPOSIT_MAX, sizeof(int), GFP_KERNEL); + if (!counts) { + free_page((unsigned long)pages); + return -ENOMEM; + } + + /* Allocate all the pages before disabling interrupts */ + i =3D 0; + + while (num_pages) { + /* Find highest order we can actually allocate */ + order =3D 31 - __builtin_clz(num_pages); + + while (1) { + pages[i] =3D alloc_pages_node(node, GFP_KERNEL, order); + if (pages[i]) + break; + if (!order) { + ret =3D -ENOMEM; + num_allocations =3D i; + goto err_free_allocations; + } + --order; + } + + split_page(pages[i], order); + counts[i] =3D 1 << order; + num_pages -=3D counts[i]; + i++; + } + num_allocations =3D i; + + local_irq_save(flags); + + input_page =3D *this_cpu_ptr(hyperv_pcpu_input_arg); + + input_page->partition_id =3D partition_id; + + /* Populate gpa_page_list - these will fit on the input page */ + for (i =3D 0, page_count =3D 0; i < num_allocations; ++i) { + base_pfn =3D page_to_pfn(pages[i]); + for (j =3D 0; j < counts[i]; ++j, ++page_count) + input_page->gpa_page_list[page_count] =3D base_pfn + j; + } + status =3D hv_do_rep_hypercall(HVCALL_DEPOSIT_MEMORY, + page_count, 0, input_page, NULL); + local_irq_restore(flags); + if (!hv_result_success(status)) { + pr_err("Failed to deposit pages: %lld\n", status); + ret =3D hv_result(status); + goto err_free_allocations; + } + + ret =3D 0; + goto free_buf; + +err_free_allocations: + for (i =3D 0; i < num_allocations; ++i) { + base_pfn =3D page_to_pfn(pages[i]); + for (j =3D 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); diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h index 8c4ff6e9aae7..46c0a6cae4e6 100644 --- a/include/asm-generic/mshyperv.h +++ b/include/asm-generic/mshyperv.h @@ -305,6 +305,8 @@ u64 hv_tdx_hypercall(u64 control, u64 param1, u64 param= 2); void hyperv_cleanup(void); bool hv_query_ext_cap(u64 cap_query); void hv_setup_dma_ops(struct device *dev, bool coherent); +int hv_call_deposit_pages(int node, u64 partition_id, u32 num_pages); +int hv_call_create_vp(int node, u64 partition_id, u32 vp_index, u32 flags); #else /* CONFIG_HYPERV */ static inline bool hv_is_hyperv_initialized(void) { return false; } static inline bool hv_is_hibernation_supported(void) { return false; } --=20 2.34.1