Skip to content

Commit 19c515c

Browse files
Jinank Jainliuw
authored andcommitted
mshv: Allocate vp state page for HVCALL_MAP_VP_STATE_PAGE on L1VH
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@linux.microsoft.com> Signed-off-by: Nuno Das Neves <nunodasneves@linux.microsoft.com> Reviewed-by: Praveen K Paladugu <prapal@linux.microsoft.com> Reviewed-by: Easwar Hariharan <easwar.hariharan@linux.microsoft.com> Reviewed-by: Stanislav Kinsburskii <skinsburskii@linux.microsoft.com> Reviewed-by: Anirudh Rayabharam <anirudh@anirudhrb.com> Reviewed-by: Tianyu Lan <tiala@microsoft.com> Signed-off-by: Wei Liu <wei.liu@kernel.org>
1 parent fd612d9 commit 19c515c

3 files changed

Lines changed: 101 additions & 50 deletions

File tree

drivers/hv/mshv_root.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -279,11 +279,12 @@ int hv_call_set_vp_state(u32 vp_index, u64 partition_id,
279279
/* Choose between pages and bytes */
280280
struct hv_vp_state_data state_data, u64 page_count,
281281
struct page **pages, u32 num_bytes, u8 *bytes);
282-
int hv_call_map_vp_state_page(u64 partition_id, u32 vp_index, u32 type,
283-
union hv_input_vtl input_vtl,
284-
struct page **state_page);
285-
int hv_call_unmap_vp_state_page(u64 partition_id, u32 vp_index, u32 type,
286-
union hv_input_vtl input_vtl);
282+
int hv_map_vp_state_page(u64 partition_id, u32 vp_index, u32 type,
283+
union hv_input_vtl input_vtl,
284+
struct page **state_page);
285+
int hv_unmap_vp_state_page(u64 partition_id, u32 vp_index, u32 type,
286+
struct page *state_page,
287+
union hv_input_vtl input_vtl);
287288
int hv_call_create_port(u64 port_partition_id, union hv_port_id port_id,
288289
u64 connection_partition_id, struct hv_port_info *port_info,
289290
u8 port_vtl, u8 min_connection_vtl, int node);

drivers/hv/mshv_root_hv_call.c

Lines changed: 58 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -526,9 +526,9 @@ int hv_call_set_vp_state(u32 vp_index, u64 partition_id,
526526
return ret;
527527
}
528528

529-
int hv_call_map_vp_state_page(u64 partition_id, u32 vp_index, u32 type,
530-
union hv_input_vtl input_vtl,
531-
struct page **state_page)
529+
static int hv_call_map_vp_state_page(u64 partition_id, u32 vp_index, u32 type,
530+
union hv_input_vtl input_vtl,
531+
struct page **state_page)
532532
{
533533
struct hv_input_map_vp_state_page *input;
534534
struct hv_output_map_vp_state_page *output;
@@ -542,12 +542,20 @@ int hv_call_map_vp_state_page(u64 partition_id, u32 vp_index, u32 type,
542542
input = *this_cpu_ptr(hyperv_pcpu_input_arg);
543543
output = *this_cpu_ptr(hyperv_pcpu_output_arg);
544544

545+
memset(input, 0, sizeof(*input));
545546
input->partition_id = partition_id;
546547
input->vp_index = vp_index;
547548
input->type = type;
548549
input->input_vtl = input_vtl;
549550

550-
status = hv_do_hypercall(HVCALL_MAP_VP_STATE_PAGE, input, output);
551+
if (*state_page) {
552+
input->flags.map_location_provided = 1;
553+
input->requested_map_location =
554+
page_to_pfn(*state_page);
555+
}
556+
557+
status = hv_do_hypercall(HVCALL_MAP_VP_STATE_PAGE, input,
558+
output);
551559

552560
if (hv_result(status) != HV_STATUS_INSUFFICIENT_MEMORY) {
553561
if (hv_result_success(status))
@@ -565,8 +573,41 @@ int hv_call_map_vp_state_page(u64 partition_id, u32 vp_index, u32 type,
565573
return ret;
566574
}
567575

568-
int hv_call_unmap_vp_state_page(u64 partition_id, u32 vp_index, u32 type,
569-
union hv_input_vtl input_vtl)
576+
static bool mshv_use_overlay_gpfn(void)
577+
{
578+
return hv_l1vh_partition() &&
579+
mshv_root.vmm_caps.vmm_can_provide_overlay_gpfn;
580+
}
581+
582+
int hv_map_vp_state_page(u64 partition_id, u32 vp_index, u32 type,
583+
union hv_input_vtl input_vtl,
584+
struct page **state_page)
585+
{
586+
int ret = 0;
587+
struct page *allocated_page = NULL;
588+
589+
if (mshv_use_overlay_gpfn()) {
590+
allocated_page = alloc_page(GFP_KERNEL);
591+
if (!allocated_page)
592+
return -ENOMEM;
593+
*state_page = allocated_page;
594+
} else {
595+
*state_page = NULL;
596+
}
597+
598+
ret = hv_call_map_vp_state_page(partition_id, vp_index, type, input_vtl,
599+
state_page);
600+
601+
if (ret && allocated_page) {
602+
__free_page(allocated_page);
603+
*state_page = NULL;
604+
}
605+
606+
return ret;
607+
}
608+
609+
static int hv_call_unmap_vp_state_page(u64 partition_id, u32 vp_index, u32 type,
610+
union hv_input_vtl input_vtl)
570611
{
571612
unsigned long flags;
572613
u64 status;
@@ -590,6 +631,17 @@ int hv_call_unmap_vp_state_page(u64 partition_id, u32 vp_index, u32 type,
590631
return hv_result_to_errno(status);
591632
}
592633

634+
int hv_unmap_vp_state_page(u64 partition_id, u32 vp_index, u32 type,
635+
struct page *state_page, union hv_input_vtl input_vtl)
636+
{
637+
int ret = hv_call_unmap_vp_state_page(partition_id, vp_index, type, input_vtl);
638+
639+
if (mshv_use_overlay_gpfn() && state_page)
640+
__free_page(state_page);
641+
642+
return ret;
643+
}
644+
593645
int hv_call_get_partition_property_ex(u64 partition_id, u64 property_code,
594646
u64 arg, void *property_value,
595647
size_t property_value_sz)

drivers/hv/mshv_root_main.c

Lines changed: 37 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -892,7 +892,7 @@ mshv_partition_ioctl_create_vp(struct mshv_partition *partition,
892892
{
893893
struct mshv_create_vp args;
894894
struct mshv_vp *vp;
895-
struct page *intercept_message_page, *register_page, *ghcb_page;
895+
struct page *intercept_msg_page, *register_page, *ghcb_page;
896896
void *stats_pages[2];
897897
long ret;
898898

@@ -910,28 +910,25 @@ mshv_partition_ioctl_create_vp(struct mshv_partition *partition,
910910
if (ret)
911911
return ret;
912912

913-
ret = hv_call_map_vp_state_page(partition->pt_id, args.vp_index,
914-
HV_VP_STATE_PAGE_INTERCEPT_MESSAGE,
915-
input_vtl_zero,
916-
&intercept_message_page);
913+
ret = hv_map_vp_state_page(partition->pt_id, args.vp_index,
914+
HV_VP_STATE_PAGE_INTERCEPT_MESSAGE,
915+
input_vtl_zero, &intercept_msg_page);
917916
if (ret)
918917
goto destroy_vp;
919918

920919
if (!mshv_partition_encrypted(partition)) {
921-
ret = hv_call_map_vp_state_page(partition->pt_id, args.vp_index,
922-
HV_VP_STATE_PAGE_REGISTERS,
923-
input_vtl_zero,
924-
&register_page);
920+
ret = hv_map_vp_state_page(partition->pt_id, args.vp_index,
921+
HV_VP_STATE_PAGE_REGISTERS,
922+
input_vtl_zero, &register_page);
925923
if (ret)
926924
goto unmap_intercept_message_page;
927925
}
928926

929927
if (mshv_partition_encrypted(partition) &&
930928
is_ghcb_mapping_available()) {
931-
ret = hv_call_map_vp_state_page(partition->pt_id, args.vp_index,
932-
HV_VP_STATE_PAGE_GHCB,
933-
input_vtl_normal,
934-
&ghcb_page);
929+
ret = hv_map_vp_state_page(partition->pt_id, args.vp_index,
930+
HV_VP_STATE_PAGE_GHCB,
931+
input_vtl_normal, &ghcb_page);
935932
if (ret)
936933
goto unmap_register_page;
937934
}
@@ -962,7 +959,7 @@ mshv_partition_ioctl_create_vp(struct mshv_partition *partition,
962959
atomic64_set(&vp->run.vp_signaled_count, 0);
963960

964961
vp->vp_index = args.vp_index;
965-
vp->vp_intercept_msg_page = page_to_virt(intercept_message_page);
962+
vp->vp_intercept_msg_page = page_to_virt(intercept_msg_page);
966963
if (!mshv_partition_encrypted(partition))
967964
vp->vp_register_page = page_to_virt(register_page);
968965

@@ -995,21 +992,19 @@ mshv_partition_ioctl_create_vp(struct mshv_partition *partition,
995992
if (hv_scheduler_type == HV_SCHEDULER_TYPE_ROOT)
996993
mshv_vp_stats_unmap(partition->pt_id, args.vp_index);
997994
unmap_ghcb_page:
998-
if (mshv_partition_encrypted(partition) && is_ghcb_mapping_available()) {
999-
hv_call_unmap_vp_state_page(partition->pt_id, args.vp_index,
1000-
HV_VP_STATE_PAGE_GHCB,
1001-
input_vtl_normal);
1002-
}
995+
if (mshv_partition_encrypted(partition) && is_ghcb_mapping_available())
996+
hv_unmap_vp_state_page(partition->pt_id, args.vp_index,
997+
HV_VP_STATE_PAGE_GHCB, ghcb_page,
998+
input_vtl_normal);
1003999
unmap_register_page:
1004-
if (!mshv_partition_encrypted(partition)) {
1005-
hv_call_unmap_vp_state_page(partition->pt_id, args.vp_index,
1006-
HV_VP_STATE_PAGE_REGISTERS,
1007-
input_vtl_zero);
1008-
}
1000+
if (!mshv_partition_encrypted(partition))
1001+
hv_unmap_vp_state_page(partition->pt_id, args.vp_index,
1002+
HV_VP_STATE_PAGE_REGISTERS,
1003+
register_page, input_vtl_zero);
10091004
unmap_intercept_message_page:
1010-
hv_call_unmap_vp_state_page(partition->pt_id, args.vp_index,
1011-
HV_VP_STATE_PAGE_INTERCEPT_MESSAGE,
1012-
input_vtl_zero);
1005+
hv_unmap_vp_state_page(partition->pt_id, args.vp_index,
1006+
HV_VP_STATE_PAGE_INTERCEPT_MESSAGE,
1007+
intercept_msg_page, input_vtl_zero);
10131008
destroy_vp:
10141009
hv_call_delete_vp(partition->pt_id, args.vp_index);
10151010
return ret;
@@ -1750,24 +1745,27 @@ static void destroy_partition(struct mshv_partition *partition)
17501745
mshv_vp_stats_unmap(partition->pt_id, vp->vp_index);
17511746

17521747
if (vp->vp_register_page) {
1753-
(void)hv_call_unmap_vp_state_page(partition->pt_id,
1754-
vp->vp_index,
1755-
HV_VP_STATE_PAGE_REGISTERS,
1756-
input_vtl_zero);
1748+
(void)hv_unmap_vp_state_page(partition->pt_id,
1749+
vp->vp_index,
1750+
HV_VP_STATE_PAGE_REGISTERS,
1751+
virt_to_page(vp->vp_register_page),
1752+
input_vtl_zero);
17571753
vp->vp_register_page = NULL;
17581754
}
17591755

1760-
(void)hv_call_unmap_vp_state_page(partition->pt_id,
1761-
vp->vp_index,
1762-
HV_VP_STATE_PAGE_INTERCEPT_MESSAGE,
1763-
input_vtl_zero);
1756+
(void)hv_unmap_vp_state_page(partition->pt_id,
1757+
vp->vp_index,
1758+
HV_VP_STATE_PAGE_INTERCEPT_MESSAGE,
1759+
virt_to_page(vp->vp_intercept_msg_page),
1760+
input_vtl_zero);
17641761
vp->vp_intercept_msg_page = NULL;
17651762

17661763
if (vp->vp_ghcb_page) {
1767-
(void)hv_call_unmap_vp_state_page(partition->pt_id,
1768-
vp->vp_index,
1769-
HV_VP_STATE_PAGE_GHCB,
1770-
input_vtl_normal);
1764+
(void)hv_unmap_vp_state_page(partition->pt_id,
1765+
vp->vp_index,
1766+
HV_VP_STATE_PAGE_GHCB,
1767+
virt_to_page(vp->vp_ghcb_page),
1768+
input_vtl_normal);
17711769
vp->vp_ghcb_page = NULL;
17721770
}
17731771

0 commit comments

Comments
 (0)