[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <07437725-60fc-4831-aa6a-d83470caaadc@gmail.com>
Date: Fri, 5 Sep 2025 11:18:52 -0500
From: Praveen K Paladugu <praveenkpaladugu@...il.com>
To: Nuno Das Neves <nunodasneves@...ux.microsoft.com>,
linux-hyperv@...r.kernel.org, linux-kernel@...r.kernel.org
Cc: kys@...rosoft.com, haiyangz@...rosoft.com, wei.liu@...nel.org,
mhklinux@...look.com, decui@...rosoft.com, paekkaladevi@...ux.microsoft.com,
Jinank Jain <jinankjain@...ux.microsoft.com>
Subject: Re: [PATCH 5/6] mshv: Allocate vp state page for
HVCALL_MAP_VP_STATE_PAGE on L1VH
On 8/28/2025 7:43 PM, Nuno Das Neves wrote:
> From: Jinank Jain <jinankjain@...ux.microsoft.com>
>
> Introduce mshv_use_overlay_gpfn() to check if a page needs to be
> allocated and passed to the hypervisor to map VP state pages. This is
> only needed on L1VH, and only on some (newer) versions of the
> hypervisor, hence the need to check vmm_capabilities.
>
> Introduce functions hv_map/unmap_vp_state_page() to handle the
> allocation and freeing.
>
> Signed-off-by: Jinank Jain <jinankjain@...ux.microsoft.com>
> Signed-off-by: Nuno Das Neves <nunodasneves@...ux.microsoft.com>
> ---
> drivers/hv/mshv_root.h | 11 +++---
> drivers/hv/mshv_root_hv_call.c | 61 +++++++++++++++++++++++++---
> drivers/hv/mshv_root_main.c | 72 +++++++++++++++++-----------------
> 3 files changed, 96 insertions(+), 48 deletions(-)
>
> diff --git a/drivers/hv/mshv_root.h b/drivers/hv/mshv_root.h
> index 0cb1e2589fe1..d7c9520ef788 100644
> --- a/drivers/hv/mshv_root.h
> +++ b/drivers/hv/mshv_root.h
> @@ -279,11 +279,12 @@ int hv_call_set_vp_state(u32 vp_index, u64 partition_id,
> /* Choose between pages and bytes */
> struct hv_vp_state_data state_data, u64 page_count,
> struct page **pages, u32 num_bytes, u8 *bytes);
> -int hv_call_map_vp_state_page(u64 partition_id, u32 vp_index, u32 type,
> - union hv_input_vtl input_vtl,
> - struct page **state_page);
> -int hv_call_unmap_vp_state_page(u64 partition_id, u32 vp_index, u32 type,
> - union hv_input_vtl input_vtl);
> +int hv_map_vp_state_page(u64 partition_id, u32 vp_index, u32 type,
> + union hv_input_vtl input_vtl,
> + struct page **state_page);
> +int hv_unmap_vp_state_page(u64 partition_id, u32 vp_index, u32 type,
> + void *page_addr,
> + union hv_input_vtl input_vtl);
> int hv_call_create_port(u64 port_partition_id, union hv_port_id port_id,
> u64 connection_partition_id, struct hv_port_info *port_info,
> u8 port_vtl, u8 min_connection_vtl, int node);
> diff --git a/drivers/hv/mshv_root_hv_call.c b/drivers/hv/mshv_root_hv_call.c
> index 7589b1ff3515..1882cc90f2f5 100644
> --- a/drivers/hv/mshv_root_hv_call.c
> +++ b/drivers/hv/mshv_root_hv_call.c
> @@ -526,9 +526,9 @@ int hv_call_set_vp_state(u32 vp_index, u64 partition_id,
> return ret;
> }
>
> -int hv_call_map_vp_state_page(u64 partition_id, u32 vp_index, u32 type,
> - union hv_input_vtl input_vtl,
> - struct page **state_page)
> +static int hv_call_map_vp_state_page(u64 partition_id, u32 vp_index, u32 type,
> + union hv_input_vtl input_vtl,
> + struct page **state_page)
> {
> struct hv_input_map_vp_state_page *input;
> struct hv_output_map_vp_state_page *output;
> @@ -547,7 +547,14 @@ int hv_call_map_vp_state_page(u64 partition_id, u32 vp_index, u32 type,
> input->type = type;
> input->input_vtl = input_vtl;
>
> - status = hv_do_hypercall(HVCALL_MAP_VP_STATE_PAGE, input, output);
> + if (*state_page) {
> + input->flags.map_location_provided = 1;
> + input->requested_map_location =
> + page_to_pfn(*state_page);
> + }
> +
> + status = hv_do_hypercall(HVCALL_MAP_VP_STATE_PAGE, input,
> + output);
>
> if (hv_result(status) != HV_STATUS_INSUFFICIENT_MEMORY) {
> if (hv_result_success(status))
> @@ -565,8 +572,39 @@ int hv_call_map_vp_state_page(u64 partition_id, u32 vp_index, u32 type,
> return ret;
> }
>
> -int hv_call_unmap_vp_state_page(u64 partition_id, u32 vp_index, u32 type,
> - union hv_input_vtl input_vtl)
> +static bool mshv_use_overlay_gpfn(void)
> +{
> + return hv_l1vh_partition() &&
> + mshv_root.vmm_caps.vmm_can_provide_overlay_gpfn;
> +}
> +
> +int hv_map_vp_state_page(u64 partition_id, u32 vp_index, u32 type,
> + union hv_input_vtl input_vtl,
> + struct page **state_page)
> +{
> + int ret = 0;
> + struct page *allocated_page = NULL;
> +
> + if (mshv_use_overlay_gpfn()) {
> + allocated_page = alloc_page(GFP_KERNEL);
> + if (!allocated_page)
> + return -ENOMEM;
> + *state_page = allocated_page;
> + } else {
> + *state_page = NULL;
> + }
> +
> + ret = hv_call_map_vp_state_page(partition_id, vp_index, type, input_vtl,
> + state_page);
> +
> + if (ret && allocated_page)
> + __free_page(allocated_page);
> +
> + return ret;
> +}
> +
> +static int hv_call_unmap_vp_state_page(u64 partition_id, u32 vp_index, u32 type,
> + union hv_input_vtl input_vtl)
> {
> unsigned long flags;
> u64 status;
> @@ -590,6 +628,17 @@ int hv_call_unmap_vp_state_page(u64 partition_id, u32 vp_index, u32 type,
> return hv_result_to_errno(status);
> }
>
> +int hv_unmap_vp_state_page(u64 partition_id, u32 vp_index, u32 type,
> + void *page_addr, union hv_input_vtl input_vtl)
> +{
> + int ret = hv_call_unmap_vp_state_page(partition_id, vp_index, type, input_vtl);
> +
> + if (mshv_use_overlay_gpfn() && page_addr)
> + __free_page(virt_to_page(page_addr));
> +
> + return ret;
> +}
> +
> int
> hv_call_get_partition_property_ex(u64 partition_id, u64 property_code, u64 arg,
> void *property_value, size_t property_value_sz)
> diff --git a/drivers/hv/mshv_root_main.c b/drivers/hv/mshv_root_main.c
> index 29f61ecc9771..f91880cc9e29 100644
> --- a/drivers/hv/mshv_root_main.c
> +++ b/drivers/hv/mshv_root_main.c
> @@ -964,28 +964,25 @@ mshv_partition_ioctl_create_vp(struct mshv_partition *partition,
> if (ret)
> return ret;
>
> - ret = hv_call_map_vp_state_page(partition->pt_id, args.vp_index,
> - HV_VP_STATE_PAGE_INTERCEPT_MESSAGE,
> - input_vtl_zero,
> - &intercept_message_page);
> + ret = hv_map_vp_state_page(partition->pt_id, args.vp_index,
> + HV_VP_STATE_PAGE_INTERCEPT_MESSAGE,
> + input_vtl_zero, &intercept_message_page);
> if (ret)
> goto destroy_vp;
>
> if (!mshv_partition_encrypted(partition)) {
> - ret = hv_call_map_vp_state_page(partition->pt_id, args.vp_index,
> - HV_VP_STATE_PAGE_REGISTERS,
> - input_vtl_zero,
> - ®ister_page);
> + ret = hv_map_vp_state_page(partition->pt_id, args.vp_index,
> + HV_VP_STATE_PAGE_REGISTERS,
> + input_vtl_zero, ®ister_page);
> if (ret)
> goto unmap_intercept_message_page;
> }
>
> if (mshv_partition_encrypted(partition) &&
> is_ghcb_mapping_available()) {
> - ret = hv_call_map_vp_state_page(partition->pt_id, args.vp_index,
> - HV_VP_STATE_PAGE_GHCB,
> - input_vtl_normal,
> - &ghcb_page);
> + ret = hv_map_vp_state_page(partition->pt_id, args.vp_index,
> + HV_VP_STATE_PAGE_GHCB,
> + input_vtl_normal, &ghcb_page);
> if (ret)
> goto unmap_register_page;
> }
> @@ -1049,21 +1046,19 @@ mshv_partition_ioctl_create_vp(struct mshv_partition *partition,
> if (hv_scheduler_type == HV_SCHEDULER_TYPE_ROOT)
> mshv_vp_stats_unmap(partition->pt_id, args.vp_index);
> unmap_ghcb_page:
> - if (mshv_partition_encrypted(partition) && is_ghcb_mapping_available()) {
> - hv_call_unmap_vp_state_page(partition->pt_id, args.vp_index,
> - HV_VP_STATE_PAGE_GHCB,
> - input_vtl_normal);
> - }
> + if (mshv_partition_encrypted(partition) && is_ghcb_mapping_available())
> + hv_unmap_vp_state_page(partition->pt_id, args.vp_index,
> + HV_VP_STATE_PAGE_GHCB, vp->vp_ghcb_page,
> + input_vtl_normal);
> unmap_register_page:
> - if (!mshv_partition_encrypted(partition)) {
> - hv_call_unmap_vp_state_page(partition->pt_id, args.vp_index,
> - HV_VP_STATE_PAGE_REGISTERS,
> - input_vtl_zero);
> - }
> + if (!mshv_partition_encrypted(partition))
> + hv_unmap_vp_state_page(partition->pt_id, args.vp_index,
> + HV_VP_STATE_PAGE_REGISTERS,
> + vp->vp_register_page, input_vtl_zero);
> unmap_intercept_message_page:
> - hv_call_unmap_vp_state_page(partition->pt_id, args.vp_index,
> - HV_VP_STATE_PAGE_INTERCEPT_MESSAGE,
> - input_vtl_zero);
> + hv_unmap_vp_state_page(partition->pt_id, args.vp_index,
> + HV_VP_STATE_PAGE_INTERCEPT_MESSAGE,
> + vp->vp_intercept_msg_page, input_vtl_zero);
> destroy_vp:
> hv_call_delete_vp(partition->pt_id, args.vp_index);
> return ret;
> @@ -1804,24 +1799,27 @@ static void destroy_partition(struct mshv_partition *partition)
> mshv_vp_stats_unmap(partition->pt_id, vp->vp_index);
>
> if (vp->vp_register_page) {
> - (void)hv_call_unmap_vp_state_page(partition->pt_id,
> - vp->vp_index,
> - HV_VP_STATE_PAGE_REGISTERS,
> - input_vtl_zero);
> + (void)hv_unmap_vp_state_page(partition->pt_id,
> + vp->vp_index,
> + HV_VP_STATE_PAGE_REGISTERS,
> + vp->vp_register_page,
> + input_vtl_zero);
> vp->vp_register_page = NULL;
> }
>
> - (void)hv_call_unmap_vp_state_page(partition->pt_id,
> - vp->vp_index,
> - HV_VP_STATE_PAGE_INTERCEPT_MESSAGE,
> - input_vtl_zero);
> + (void)hv_unmap_vp_state_page(partition->pt_id,
> + vp->vp_index,
> + HV_VP_STATE_PAGE_INTERCEPT_MESSAGE,
> + vp->vp_intercept_msg_page,
> + input_vtl_zero);
> vp->vp_intercept_msg_page = NULL;
>
> if (vp->vp_ghcb_page) {
> - (void)hv_call_unmap_vp_state_page(partition->pt_id,
> - vp->vp_index,
> - HV_VP_STATE_PAGE_GHCB,
> - input_vtl_normal);
> + (void)hv_unmap_vp_state_page(partition->pt_id,
> + vp->vp_index,
> + HV_VP_STATE_PAGE_GHCB,
> + vp->vp_ghcb_page,
> + input_vtl_normal);
> vp->vp_ghcb_page = NULL;
> }
>
Reviewed-by: Praveen K Paladugu <prapal@...ux.microsoft.com>
Powered by blists - more mailing lists