[PATCH v3 6/7] Drivers: hv: Use hv_hvcall_*() to set up hypercall arguments for mshv code

From: mhkelley58
Date: Tue Apr 15 2025 - 14:09:41 EST


From: Michael Kelley <mhklinux@xxxxxxxxxxx>

Update hypercall call sites to use the new hv_hvcall_*() functions
to set up hypercall arguments. Since these functions zero the
fixed portion of input memory, remove now redundant calls to memset()
and explicit zero'ing of input fields. Where feasible use batch size
returned by hv_hvcall_inout_array() instead of separate #define value.

Signed-off-by: Michael Kelley <mhklinux@xxxxxxxxxxx>
---

Notes:
Changes in v3:
* This patch is new in v3 due to rebasing on 6.15-rc1, which has new
mshv-related hypercalls.

drivers/hv/mshv_common.c | 31 +++------
drivers/hv/mshv_root_hv_call.c | 121 +++++++++++++--------------------
drivers/hv/mshv_root_main.c | 5 +-
3 files changed, 60 insertions(+), 97 deletions(-)

diff --git a/drivers/hv/mshv_common.c b/drivers/hv/mshv_common.c
index 2575e6d7a71f..2ad36cc7a329 100644
--- a/drivers/hv/mshv_common.c
+++ b/drivers/hv/mshv_common.c
@@ -16,12 +16,6 @@

#include "mshv.h"

-#define HV_GET_REGISTER_BATCH_SIZE \
- (HV_HYP_PAGE_SIZE / sizeof(union hv_register_value))
-#define HV_SET_REGISTER_BATCH_SIZE \
- ((HV_HYP_PAGE_SIZE - sizeof(struct hv_input_set_vp_registers)) \
- / sizeof(struct hv_register_assoc))
-
int hv_call_get_vp_registers(u32 vp_index, u64 partition_id, u16 count,
union hv_input_vtl input_vtl,
struct hv_register_assoc *registers)
@@ -29,24 +23,23 @@ int hv_call_get_vp_registers(u32 vp_index, u64 partition_id, u16 count,
struct hv_input_get_vp_registers *input_page;
union hv_register_value *output_page;
u16 completed = 0;
- unsigned long remaining = count;
+ unsigned long batch_size, remaining = count;
int rep_count, i;
u64 status = HV_STATUS_SUCCESS;
unsigned long flags;

local_irq_save(flags);

- input_page = *this_cpu_ptr(hyperv_pcpu_input_arg);
- output_page = *this_cpu_ptr(hyperv_pcpu_output_arg);
+ batch_size = hv_hvcall_inout_array(&input_page, sizeof(*input_page),
+ sizeof(input_page->names[0]),
+ &output_page, 0, sizeof(*output_page));

input_page->partition_id = partition_id;
input_page->vp_index = vp_index;
input_page->input_vtl.as_uint8 = input_vtl.as_uint8;
- input_page->rsvd_z8 = 0;
- input_page->rsvd_z16 = 0;

while (remaining) {
- rep_count = min(remaining, HV_GET_REGISTER_BATCH_SIZE);
+ rep_count = min(remaining, batch_size);
for (i = 0; i < rep_count; ++i)
input_page->names[i] = registers[i].name;

@@ -75,21 +68,19 @@ int hv_call_set_vp_registers(u32 vp_index, u64 partition_id, u16 count,
struct hv_input_set_vp_registers *input_page;
u16 completed = 0;
unsigned long remaining = count;
- int rep_count;
+ unsigned long rep_count, batch_size;
u64 status = HV_STATUS_SUCCESS;
unsigned long flags;

local_irq_save(flags);
- input_page = *this_cpu_ptr(hyperv_pcpu_input_arg);
-
+ batch_size = hv_hvcall_in_array(&input_page, sizeof(*input_page),
+ sizeof(input_page->elements[0]));
input_page->partition_id = partition_id;
input_page->vp_index = vp_index;
input_page->input_vtl.as_uint8 = input_vtl.as_uint8;
- input_page->rsvd_z8 = 0;
- input_page->rsvd_z16 = 0;

while (remaining) {
- rep_count = min(remaining, HV_SET_REGISTER_BATCH_SIZE);
+ rep_count = min(remaining, batch_size);
memcpy(input_page->elements, registers,
sizeof(struct hv_register_assoc) * rep_count);

@@ -119,9 +110,7 @@ int hv_call_get_partition_property(u64 partition_id,
struct hv_output_get_partition_property *output;

local_irq_save(flags);
- input = *this_cpu_ptr(hyperv_pcpu_input_arg);
- output = *this_cpu_ptr(hyperv_pcpu_output_arg);
- memset(input, 0, sizeof(*input));
+ hv_hvcall_inout(&input, sizeof(*input), &output, sizeof(*output));
input->partition_id = partition_id;
input->property_code = property_code;
status = hv_do_hypercall(HVCALL_GET_PARTITION_PROPERTY, input, output);
diff --git a/drivers/hv/mshv_root_hv_call.c b/drivers/hv/mshv_root_hv_call.c
index a222a16107f6..f14720de3248 100644
--- a/drivers/hv/mshv_root_hv_call.c
+++ b/drivers/hv/mshv_root_hv_call.c
@@ -21,22 +21,6 @@
#define HV_PAGE_COUNT_2M_ALIGNED(pg_count) (!((pg_count) & (0x200 - 1)))

#define HV_WITHDRAW_BATCH_SIZE (HV_HYP_PAGE_SIZE / sizeof(u64))
-#define HV_MAP_GPA_BATCH_SIZE \
- ((HV_HYP_PAGE_SIZE - sizeof(struct hv_input_map_gpa_pages)) \
- / sizeof(u64))
-#define HV_GET_VP_STATE_BATCH_SIZE \
- ((HV_HYP_PAGE_SIZE - sizeof(struct hv_input_get_vp_state)) \
- / sizeof(u64))
-#define HV_SET_VP_STATE_BATCH_SIZE \
- ((HV_HYP_PAGE_SIZE - sizeof(struct hv_input_set_vp_state)) \
- / sizeof(u64))
-#define HV_GET_GPA_ACCESS_STATES_BATCH_SIZE \
- ((HV_HYP_PAGE_SIZE - sizeof(union hv_gpa_page_access_state)) \
- / sizeof(union hv_gpa_page_access_state))
-#define HV_MODIFY_SPARSE_SPA_PAGE_HOST_ACCESS_MAX_PAGE_COUNT \
- ((HV_HYP_PAGE_SIZE - \
- sizeof(struct hv_input_modify_sparse_spa_page_host_access)) / \
- sizeof(u64))

int hv_call_withdraw_memory(u64 count, int node, u64 partition_id)
{
@@ -57,9 +41,7 @@ int hv_call_withdraw_memory(u64 count, int node, u64 partition_id)
while (remaining) {
local_irq_save(flags);

- input_page = *this_cpu_ptr(hyperv_pcpu_input_arg);
-
- memset(input_page, 0, sizeof(*input_page));
+ hv_hvcall_in(&input_page, sizeof(*input_page));
input_page->partition_id = partition_id;
status = hv_do_rep_hypercall(HVCALL_WITHDRAW_MEMORY,
min(remaining, HV_WITHDRAW_BATCH_SIZE),
@@ -98,10 +80,7 @@ int hv_call_create_partition(u64 flags,

do {
local_irq_save(irq_flags);
- input = *this_cpu_ptr(hyperv_pcpu_input_arg);
- output = *this_cpu_ptr(hyperv_pcpu_output_arg);
-
- memset(input, 0, sizeof(*input));
+ hv_hvcall_inout(&input, sizeof(*input), &output, sizeof(*output));
input->flags = flags;
input->compatibility_version = HV_COMPATIBILITY_21_H2;

@@ -205,11 +184,12 @@ static int hv_do_map_gpa_hcall(u64 partition_id, u64 gfn, u64 page_struct_count,

while (done < page_count) {
ulong i, completed, remain = page_count - done;
- int rep_count = min(remain, HV_MAP_GPA_BATCH_SIZE);
+ ulong rep_count, batch_size;

local_irq_save(irq_flags);
- input_page = *this_cpu_ptr(hyperv_pcpu_input_arg);
-
+ batch_size = hv_hvcall_in_array(&input_page, sizeof(*input_page),
+ sizeof(input_page->source_gpa_page_list[0]));
+ rep_count = min(remain, batch_size);
input_page->target_partition_id = partition_id;
input_page->target_gpa_base = gfn + (done << large_shift);
input_page->map_flags = flags;
@@ -310,7 +290,7 @@ int hv_call_unmap_gpa_pages(u64 partition_id, u64 gfn, u64 page_count_4k,
int rep_count = min(remain, HV_UMAP_GPA_PAGES);

local_irq_save(irq_flags);
- input_page = *this_cpu_ptr(hyperv_pcpu_input_arg);
+ hv_hvcall_in(&input_page, sizeof(*input_page));

input_page->target_partition_id = partition_id;
input_page->target_gpa_base = gfn + (done << large_shift);
@@ -339,7 +319,7 @@ int hv_call_get_gpa_access_states(u64 partition_id, u32 count, u64 gpa_base_pfn,
struct hv_input_get_gpa_pages_access_state *input_page;
union hv_gpa_page_access_state *output_page;
int completed = 0;
- unsigned long remaining = count;
+ unsigned long batch_size, remaining = count;
int rep_count, i;
u64 status = 0;
unsigned long flags;
@@ -347,13 +327,13 @@ int hv_call_get_gpa_access_states(u64 partition_id, u32 count, u64 gpa_base_pfn,
*written_total = 0;
while (remaining) {
local_irq_save(flags);
- input_page = *this_cpu_ptr(hyperv_pcpu_input_arg);
- output_page = *this_cpu_ptr(hyperv_pcpu_output_arg);
+ batch_size = hv_hvcall_inout_array(&input_page, sizeof(*input_page),
+ 0, &output_page, 0, sizeof(*output_page));

input_page->partition_id = partition_id;
input_page->hv_gpa_page_number = gpa_base_pfn + *written_total;
input_page->flags = state_flags;
- rep_count = min(remaining, HV_GET_GPA_ACCESS_STATES_BATCH_SIZE);
+ rep_count = min(remaining, batch_size);

status = hv_do_rep_hypercall(HVCALL_GET_GPA_PAGES_ACCESS_STATES, rep_count,
0, input_page, output_page);
@@ -383,8 +363,7 @@ int hv_call_assert_virtual_interrupt(u64 partition_id, u32 vector,
u64 status;

local_irq_save(flags);
- input = *this_cpu_ptr(hyperv_pcpu_input_arg);
- memset(input, 0, sizeof(*input));
+ hv_hvcall_in(&input, sizeof(*input));
input->partition_id = partition_id;
input->vector = vector;
input->dest_addr = dest_addr;
@@ -421,21 +400,21 @@ int hv_call_get_vp_state(u32 vp_index, u64 partition_id,
u64 status;
int i;
u64 control;
- unsigned long flags;
+ unsigned long flags, batch_size;
int ret = 0;

- if (page_count > HV_GET_VP_STATE_BATCH_SIZE)
- return -EINVAL;
-
if (!page_count && !ret_output)
return -EINVAL;

do {
local_irq_save(flags);
- input = *this_cpu_ptr(hyperv_pcpu_input_arg);
- output = *this_cpu_ptr(hyperv_pcpu_output_arg);
- memset(input, 0, sizeof(*input));
- memset(output, 0, sizeof(*output));
+ batch_size = hv_hvcall_inout_array(&input, sizeof(*input),
+ sizeof(input->output_data_pfns[0]),
+ &output, sizeof(*output), 0);
+ if (page_count > batch_size) {
+ local_irq_restore(flags);
+ return -EINVAL;
+ }

input->partition_id = partition_id;
input->vp_index = vp_index;
@@ -477,11 +456,7 @@ int hv_call_set_vp_state(u32 vp_index, u64 partition_id,
unsigned long flags;
int ret = 0;
u16 varhead_sz;
-
- if (page_count > HV_SET_VP_STATE_BATCH_SIZE)
- return -EINVAL;
- if (sizeof(*input) + num_bytes > HV_HYP_PAGE_SIZE)
- return -EINVAL;
+ u64 batch_size;

if (num_bytes)
/* round up to 8 and divide by 8 */
@@ -493,18 +468,26 @@ int hv_call_set_vp_state(u32 vp_index, u64 partition_id,

do {
local_irq_save(flags);
- input = *this_cpu_ptr(hyperv_pcpu_input_arg);
- memset(input, 0, sizeof(*input));

- input->partition_id = partition_id;
- input->vp_index = vp_index;
- input->state_data = state_data;
if (num_bytes) {
+ batch_size = hv_hvcall_in_array(&input, sizeof(*input),
+ sizeof(input->data[0].bytes));
+ if (num_bytes > batch_size)
+ goto size_error;
+
memcpy((u8 *)input->data, bytes, num_bytes);
} else {
+ batch_size = hv_hvcall_in_array(&input, sizeof(*input),
+ sizeof(input->data[0].pfns));
+ if (page_count > batch_size)
+ goto size_error;
+
for (i = 0; i < page_count; i++)
input->data[i].pfns = page_to_pfn(pages[i]);
}
+ input->partition_id = partition_id;
+ input->vp_index = vp_index;
+ input->state_data = state_data;

control = (HVCALL_SET_VP_STATE) |
(varhead_sz << HV_HYPERCALL_VARHEAD_OFFSET);
@@ -523,6 +506,10 @@ int hv_call_set_vp_state(u32 vp_index, u64 partition_id,
} while (!ret);

return ret;
+
+size_error:
+ local_irq_restore(flags);
+ return -EINVAL;
}

int hv_call_map_vp_state_page(u64 partition_id, u32 vp_index, u32 type,
@@ -538,8 +525,7 @@ int hv_call_map_vp_state_page(u64 partition_id, u32 vp_index, u32 type,
do {
local_irq_save(flags);

- input = *this_cpu_ptr(hyperv_pcpu_input_arg);
- output = *this_cpu_ptr(hyperv_pcpu_output_arg);
+ hv_hvcall_inout(&input, sizeof(*input), &output, sizeof(*output));

input->partition_id = partition_id;
input->vp_index = vp_index;
@@ -573,9 +559,7 @@ int hv_call_unmap_vp_state_page(u64 partition_id, u32 vp_index, u32 type,

local_irq_save(flags);

- input = *this_cpu_ptr(hyperv_pcpu_input_arg);
-
- memset(input, 0, sizeof(*input));
+ hv_hvcall_in(&input, sizeof(*input));

input->partition_id = partition_id;
input->vp_index = vp_index;
@@ -613,8 +597,7 @@ hv_call_create_port(u64 port_partition_id, union hv_port_id port_id,

do {
local_irq_save(flags);
- input = *this_cpu_ptr(hyperv_pcpu_input_arg);
- memset(input, 0, sizeof(*input));
+ hv_hvcall_in(&input, sizeof(*input));

input->port_partition_id = port_partition_id;
input->port_id = port_id;
@@ -667,8 +650,7 @@ hv_call_connect_port(u64 port_partition_id, union hv_port_id port_id,

do {
local_irq_save(flags);
- input = *this_cpu_ptr(hyperv_pcpu_input_arg);
- memset(input, 0, sizeof(*input));
+ hv_hvcall_in(&input, sizeof(*input));
input->port_partition_id = port_partition_id;
input->port_id = port_id;
input->connection_partition_id = connection_partition_id;
@@ -735,10 +717,7 @@ int hv_call_map_stat_page(enum hv_stats_object_type type,

do {
local_irq_save(flags);
- input = *this_cpu_ptr(hyperv_pcpu_input_arg);
- output = *this_cpu_ptr(hyperv_pcpu_output_arg);
-
- memset(input, 0, sizeof(*input));
+ hv_hvcall_inout(&input, sizeof(*input), &output, sizeof(*output));
input->type = type;
input->identity = *identity;

@@ -772,9 +751,7 @@ int hv_call_unmap_stat_page(enum hv_stats_object_type type,
u64 status;

local_irq_save(flags);
- input = *this_cpu_ptr(hyperv_pcpu_input_arg);
-
- memset(input, 0, sizeof(*input));
+ hv_hvcall_in(&input, sizeof(*input));
input->type = type;
input->identity = *identity;

@@ -807,14 +784,14 @@ int hv_call_modify_spa_host_access(u64 partition_id, struct page **pages,
}

while (done < page_count) {
- ulong i, completed, remain = page_count - done;
- int rep_count = min(remain,
- HV_MODIFY_SPARSE_SPA_PAGE_HOST_ACCESS_MAX_PAGE_COUNT);
+ ulong i, batch_size, completed, remain = page_count - done;
+ ulong rep_count;

local_irq_save(irq_flags);
- input_page = *this_cpu_ptr(hyperv_pcpu_input_arg);
+ batch_size = hv_hvcall_in_array(&input_page, sizeof(*input_page),
+ sizeof(input_page->spa_page_list[0]));
+ rep_count = min(remain, batch_size);

- memset(input_page, 0, sizeof(*input_page));
/* Only set the partition id if you are making the pages
* exclusive
*/
diff --git a/drivers/hv/mshv_root_main.c b/drivers/hv/mshv_root_main.c
index 72df774e410a..df6b0da4a9a8 100644
--- a/drivers/hv/mshv_root_main.c
+++ b/drivers/hv/mshv_root_main.c
@@ -2051,11 +2051,8 @@ static int __init hv_retrieve_scheduler_type(enum hv_scheduler_type *out)
u64 status;

local_irq_save(flags);
- input = *this_cpu_ptr(hyperv_pcpu_input_arg);
- output = *this_cpu_ptr(hyperv_pcpu_output_arg);

- memset(input, 0, sizeof(*input));
- memset(output, 0, sizeof(*output));
+ hv_hvcall_inout(&input, sizeof(*input), &output, sizeof(*output));
input->property_id = HV_SYSTEM_PROPERTY_SCHEDULER_TYPE;

status = hv_do_hypercall(HVCALL_GET_SYSTEM_PROPERTY, input, output);
--
2.25.1