* [PATCH v6 00/10] Introduce /dev/mshv root partition driver
@ 2025-03-14 19:28 Nuno Das Neves
2025-03-14 19:28 ` [PATCH v6 01/10] hyperv: Log hypercall status codes as strings Nuno Das Neves
` (10 more replies)
0 siblings, 11 replies; 20+ messages in thread
From: Nuno Das Neves @ 2025-03-14 19:28 UTC (permalink / raw)
To: linux-hyperv, x86, linux-arm-kernel, linux-kernel, linux-arch,
mhklinux, ltykernel, stanislav.kinsburskiy, linux-acpi, eahariha,
jeff.johnson
Cc: kys, haiyangz, wei.liu, decui, catalin.marinas, will, tglx, mingo,
bp, dave.hansen, hpa, daniel.lezcano, joro, robin.murphy, arnd,
jinankjain, muminulrussell, skinsburskii, mrathor, ssengar, apais,
gregkh, vkuznets, prapal, anrayabh, rafael, lenb, corbet
This series introduces support for creating and running guest virtual
machines while running on the Microsoft Hypervisor[0] as root partition.
This is done via an IOCTL interface accessed through /dev/mshv, similar to
/dev/kvm. Another series introducing this support was previously posted in
2021[1], and versions 1-4 of this series were posted in 2023[2].
Patches 1-4 are small refactors and additions to Hyper-V code.
Patches 5-6 just export some definitions needed by /dev/mshv.
Patches 7-9 introduce some functionality and definitions in common code, that
are specific to the driver.
Patch 10 contains the driver code.
-----------------
[0] "Hyper-V" is more well-known, but it really refers to the whole stack
including the hypervisor and other components that run in Windows
kernel and userspace.
[1] Previous /dev/mshv patch series (2021) and discussion:
https://lore.kernel.org/linux-hyperv/1632853875-20261-1-git-send-email-nunodasneves@linux.microsoft.com/
[2] v4 (2023):
https://lore.kernel.org/linux-hyperv/1696010501-24584-1-git-send-email-nunodasneves@linux.microsoft.com/
-----------------
Changes since v5:
* Rework patch 1:
1. Introduce hv_status_printk() logging macros which print the raw HV_STATUS_
code along with string [Roman Kisel]
2. Iterate over an array of data items to get the string and errno for the
hv_result_to_*() functions. [Michael Kelley]
3. Use hv_status_printk() to log errors in hyperv/irqdomain.c and
hyperv-iommu.c [Easwar Hariharan]
* Minor cleanup, improvements, and commit wording changes in patches 2, 3, 4, 6
[Roman Kisel, Easwar Hariharan, Michael Kelley]
* Fix issues with declaration and lifecycle of hv_synic_eventring_tail in patch
7 [Michael Kelley]
* Improve detail and clarity of commit message in patch 8 [Michael Kelley]
* Minor cleanups in patch 9 - uapi types -> kernel types, #ifdef CONFIG_X86_64
-> CONFIG_X86 for consistency, fix HVCALL_* ordering, remove redundant
__packed, use explicit enum value [Stanislav Kinsburskii, Easwar Hariharan,
Michael Kelley, Tianyu Lan]
* Minor fixes and cleanup in patch 10 [Michael Kelley]
* Add MODULE_DESCRIPTION() to patch 10 [Jeff Johnson]
Changes since v4:
* Slim down the IOCTL interface significantly, via several means:
1. Use generic "passthrough" call MSHV_ROOT_HVCALL to replace many ioctls.
2. Use MSHV_* versions of some of the HV_* definitions.
3. Move hv headers out of uapi altogether, into include/hyperv/, see:
https://lore.kernel.org/linux-hyperv/1732577084-2122-1-git-send-email-nunodasneves@linux.microsoft.com/
* Remove mshv_vtl module altogther, it will be posted in followup series
* Also remove the parent "mshv" module which didn't serve much purpose
* Update and refactor parts of the driver code for clarity, extensibility
Changes since v3 (summarized):
* Clean up the error and debug logging:
1. Add a set of macros vp_*() and partition_*() which call the equivalent
dev_*(), passing the device from the partition struct
* The new macros also print the partition and vp ids to aid debugging
and reduce repeated code
2. Use dev_*() (mostly via the new macros) instead of pr_*() *almost*
everywhere - in interrupt context we can't always get the device struct
3. Remove pr_*() logging from hv_call.c and mshv_root_hv_call.c
Changes since v2 (summarized):
* Fix many checkpatch.pl --strict style issues
* Initialize status in get/set registers hypercall helpers
* Add missing return on error in get_vp_signaled_count
Changes since v1 (summarized):
* Clean up formatting, commit messages
Nuno Das Neves (9):
hyperv: Log hypercall status codes as strings
arm64/hyperv: Add some missing functions to arm64
hyperv: Introduce hv_recommend_using_aeoi()
acpi: numa: Export node_to_pxm()
Drivers: hv: Export some functions for use by root partition module
Drivers: hv: Introduce per-cpu event ring tail
x86: hyperv: Add mshv_handler() irq handler and setup function
hyperv: Add definitions for root partition driver to hv headers
Drivers: hv: Introduce mshv_root module to expose /dev/mshv to VMMs
Stanislav Kinsburskii (1):
x86/mshyperv: Add support for extended Hyper-V features
.../userspace-api/ioctl/ioctl-number.rst | 2 +
arch/arm64/hyperv/hv_core.c | 17 +
arch/arm64/hyperv/mshyperv.c | 1 +
arch/arm64/include/asm/mshyperv.h | 13 +
arch/x86/hyperv/irqdomain.c | 6 +-
arch/x86/kernel/cpu/mshyperv.c | 16 +-
drivers/acpi/numa/srat.c | 1 +
drivers/hv/Makefile | 5 +-
drivers/hv/hv.c | 12 +-
drivers/hv/hv_common.c | 175 +-
drivers/hv/hv_proc.c | 13 +-
drivers/hv/mshv.h | 30 +
drivers/hv/mshv_common.c | 161 ++
drivers/hv/mshv_eventfd.c | 833 ++++++
drivers/hv/mshv_eventfd.h | 71 +
drivers/hv/mshv_irq.c | 124 +
drivers/hv/mshv_portid_table.c | 84 +
drivers/hv/mshv_root.h | 308 +++
drivers/hv/mshv_root_hv_call.c | 852 ++++++
drivers/hv/mshv_root_main.c | 2333 +++++++++++++++++
drivers/hv/mshv_synic.c | 665 +++++
drivers/iommu/hyperv-iommu.c | 4 +-
include/asm-generic/mshyperv.h | 34 +-
include/hyperv/hvgdk_mini.h | 72 +-
include/hyperv/hvhdk.h | 132 +-
include/hyperv/hvhdk_mini.h | 91 +
include/uapi/linux/mshv.h | 287 ++
27 files changed, 6266 insertions(+), 76 deletions(-)
create mode 100644 drivers/hv/mshv.h
create mode 100644 drivers/hv/mshv_common.c
create mode 100644 drivers/hv/mshv_eventfd.c
create mode 100644 drivers/hv/mshv_eventfd.h
create mode 100644 drivers/hv/mshv_irq.c
create mode 100644 drivers/hv/mshv_portid_table.c
create mode 100644 drivers/hv/mshv_root.h
create mode 100644 drivers/hv/mshv_root_hv_call.c
create mode 100644 drivers/hv/mshv_root_main.c
create mode 100644 drivers/hv/mshv_synic.c
create mode 100644 include/uapi/linux/mshv.h
--
2.34.1
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v6 01/10] hyperv: Log hypercall status codes as strings
2025-03-14 19:28 [PATCH v6 00/10] Introduce /dev/mshv root partition driver Nuno Das Neves
@ 2025-03-14 19:28 ` Nuno Das Neves
2025-03-18 18:01 ` Michael Kelley
2025-03-19 4:17 ` Easwar Hariharan
2025-03-14 19:28 ` [PATCH v6 02/10] x86/mshyperv: Add support for extended Hyper-V features Nuno Das Neves
` (9 subsequent siblings)
10 siblings, 2 replies; 20+ messages in thread
From: Nuno Das Neves @ 2025-03-14 19:28 UTC (permalink / raw)
To: linux-hyperv, x86, linux-arm-kernel, linux-kernel, linux-arch,
mhklinux, ltykernel, stanislav.kinsburskiy, linux-acpi, eahariha,
jeff.johnson
Cc: kys, haiyangz, wei.liu, decui, catalin.marinas, will, tglx, mingo,
bp, dave.hansen, hpa, daniel.lezcano, joro, robin.murphy, arnd,
jinankjain, muminulrussell, skinsburskii, mrathor, ssengar, apais,
gregkh, vkuznets, prapal, anrayabh, rafael, lenb, corbet
Introduce hv_status_printk() macros as a convenience to log hypercall
errors, formatting them with the status code (HV_STATUS_*) as a raw hex
value and also as a string, which saves some time while debugging.
Create a table of HV_STATUS_ codes with strings and mapped errnos, and
use it for hv_result_to_string() and hv_result_to_errno().
Use the new hv_status_printk()s in hv_proc.c, hyperv-iommu.c, and
irqdomain.c hypercalls to aid debugging in the root partition.
Signed-off-by: Nuno Das Neves <nunodasneves@linux.microsoft.com>
Reviewed-by: Stanislav Kinsburskii <skinsburskii@linux.microsoft.com>
---
arch/x86/hyperv/irqdomain.c | 6 +-
drivers/hv/hv_common.c | 129 ++++++++++++++++++++++++---------
drivers/hv/hv_proc.c | 10 +--
drivers/iommu/hyperv-iommu.c | 4 +-
include/asm-generic/mshyperv.h | 13 ++++
5 files changed, 118 insertions(+), 44 deletions(-)
diff --git a/arch/x86/hyperv/irqdomain.c b/arch/x86/hyperv/irqdomain.c
index 64b921360b0f..31f0d29cbc5e 100644
--- a/arch/x86/hyperv/irqdomain.c
+++ b/arch/x86/hyperv/irqdomain.c
@@ -64,7 +64,7 @@ static int hv_map_interrupt(union hv_device_id device_id, bool level,
local_irq_restore(flags);
if (!hv_result_success(status))
- pr_err("%s: hypercall failed, status %lld\n", __func__, status);
+ hv_status_err(status, "\n");
return hv_result(status);
}
@@ -224,7 +224,7 @@ static void hv_irq_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
kfree(stored_entry);
if (status != HV_STATUS_SUCCESS) {
- pr_debug("%s: failed to unmap, status %lld", __func__, status);
+ hv_status_debug(status, "failed to unmap\n");
return;
}
}
@@ -273,7 +273,7 @@ static void hv_teardown_msi_irq(struct pci_dev *dev, struct irq_data *irqd)
status = hv_unmap_msi_interrupt(dev, &old_entry);
if (status != HV_STATUS_SUCCESS)
- pr_err("%s: hypercall failed, status %lld\n", __func__, status);
+ hv_status_err(status, "\n");
}
static void hv_msi_free_irq(struct irq_domain *domain,
diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c
index 9804adb4cc56..885bbc3d86d8 100644
--- a/drivers/hv/hv_common.c
+++ b/drivers/hv/hv_common.c
@@ -684,40 +684,6 @@ u64 __weak hv_tdx_hypercall(u64 control, u64 param1, u64 param2)
}
EXPORT_SYMBOL_GPL(hv_tdx_hypercall);
-/* Convert a hypercall result into a linux-friendly error code. */
-int hv_result_to_errno(u64 status)
-{
- /* hv_do_hypercall() may return U64_MAX, hypercalls aren't possible */
- if (unlikely(status == U64_MAX))
- return -EOPNOTSUPP;
- /*
- * A failed hypercall is usually only recoverable (or loggable) near
- * the call site where the HV_STATUS_* code is known. So the errno
- * it gets converted to is not too useful further up the stack.
- * Provide a few mappings that could be useful, and revert to -EIO
- * as a fallback.
- */
- switch (hv_result(status)) {
- case HV_STATUS_SUCCESS:
- return 0;
- case HV_STATUS_INVALID_HYPERCALL_CODE:
- case HV_STATUS_INVALID_HYPERCALL_INPUT:
- case HV_STATUS_INVALID_PARAMETER:
- case HV_STATUS_INVALID_PARTITION_ID:
- case HV_STATUS_INVALID_VP_INDEX:
- case HV_STATUS_INVALID_PORT_ID:
- case HV_STATUS_INVALID_CONNECTION_ID:
- case HV_STATUS_INVALID_LP_INDEX:
- case HV_STATUS_INVALID_REGISTER_VALUE:
- return -EINVAL;
- case HV_STATUS_INSUFFICIENT_MEMORY:
- return -ENOMEM;
- default:
- break;
- }
- return -EIO;
-}
-
void hv_identify_partition_type(void)
{
/* Assume guest role */
@@ -740,3 +706,98 @@ void hv_identify_partition_type(void)
pr_crit("Hyper-V: CONFIG_MSHV_ROOT not enabled!\n");
}
}
+
+struct hv_status_info {
+ char *string;
+ int errno;
+ u16 code;
+};
+
+/*
+ * Note on the errno mappings:
+ * A failed hypercall is usually only recoverable (or loggable) near
+ * the call site where the HV_STATUS_* code is known. So the errno
+ * it gets converted to is not too useful further up the stack.
+ * Provide a few mappings that could be useful, and revert to -EIO
+ * as a fallback.
+ */
+static const struct hv_status_info hv_status_infos[] = {
+#define _STATUS_INFO(status, errno) { #status, (errno), (status) }
+ _STATUS_INFO(HV_STATUS_SUCCESS, 0),
+ _STATUS_INFO(HV_STATUS_INVALID_HYPERCALL_CODE, -EINVAL),
+ _STATUS_INFO(HV_STATUS_INVALID_HYPERCALL_INPUT, -EINVAL),
+ _STATUS_INFO(HV_STATUS_INVALID_ALIGNMENT, -EIO),
+ _STATUS_INFO(HV_STATUS_INVALID_PARAMETER, -EINVAL),
+ _STATUS_INFO(HV_STATUS_ACCESS_DENIED, -EIO),
+ _STATUS_INFO(HV_STATUS_INVALID_PARTITION_STATE, -EIO),
+ _STATUS_INFO(HV_STATUS_OPERATION_DENIED, -EIO),
+ _STATUS_INFO(HV_STATUS_UNKNOWN_PROPERTY, -EIO),
+ _STATUS_INFO(HV_STATUS_PROPERTY_VALUE_OUT_OF_RANGE, -EIO),
+ _STATUS_INFO(HV_STATUS_INSUFFICIENT_MEMORY, -ENOMEM),
+ _STATUS_INFO(HV_STATUS_INVALID_PARTITION_ID, -EINVAL),
+ _STATUS_INFO(HV_STATUS_INVALID_VP_INDEX, -EINVAL),
+ _STATUS_INFO(HV_STATUS_NOT_FOUND, -EIO),
+ _STATUS_INFO(HV_STATUS_INVALID_PORT_ID, -EINVAL),
+ _STATUS_INFO(HV_STATUS_INVALID_CONNECTION_ID, -EINVAL),
+ _STATUS_INFO(HV_STATUS_INSUFFICIENT_BUFFERS, -EIO),
+ _STATUS_INFO(HV_STATUS_NOT_ACKNOWLEDGED, -EIO),
+ _STATUS_INFO(HV_STATUS_INVALID_VP_STATE, -EIO),
+ _STATUS_INFO(HV_STATUS_NO_RESOURCES, -EIO),
+ _STATUS_INFO(HV_STATUS_PROCESSOR_FEATURE_NOT_SUPPORTED, -EIO),
+ _STATUS_INFO(HV_STATUS_INVALID_LP_INDEX, -EINVAL),
+ _STATUS_INFO(HV_STATUS_INVALID_REGISTER_VALUE, -EINVAL),
+ _STATUS_INFO(HV_STATUS_INVALID_LP_INDEX, -EIO),
+ _STATUS_INFO(HV_STATUS_INVALID_REGISTER_VALUE, -EIO),
+ _STATUS_INFO(HV_STATUS_OPERATION_FAILED, -EIO),
+ _STATUS_INFO(HV_STATUS_TIME_OUT, -EIO),
+ _STATUS_INFO(HV_STATUS_CALL_PENDING, -EIO),
+ _STATUS_INFO(HV_STATUS_VTL_ALREADY_ENABLED, -EIO),
+#undef _STATUS_INFO
+};
+
+static inline const struct hv_status_info *find_hv_status_info(u64 hv_status)
+{
+ int i;
+ u16 code = hv_result(hv_status);
+
+ for (i = 0; i < ARRAY_SIZE(hv_status_infos); ++i) {
+ const struct hv_status_info *info = &hv_status_infos[i];
+
+ if (info->code == code)
+ return info;
+ }
+
+ return NULL;
+}
+
+/* Convert a hypercall result into a linux-friendly error code. */
+int hv_result_to_errno(u64 status)
+{
+ const struct hv_status_info *info;
+
+ /* hv_do_hypercall() may return U64_MAX, hypercalls aren't possible */
+ if (unlikely(status == U64_MAX))
+ return -EOPNOTSUPP;
+
+ info = find_hv_status_info(status);
+ if (info)
+ return info->errno;
+
+ return -EIO;
+}
+EXPORT_SYMBOL_GPL(hv_result_to_errno);
+
+const char *hv_result_to_string(u64 status)
+{
+ const struct hv_status_info *info;
+
+ if (unlikely(status == U64_MAX))
+ return "Hypercall page missing!";
+
+ info = find_hv_status_info(status);
+ if (info)
+ return info->string;
+
+ return "Unknown";
+}
+EXPORT_SYMBOL_GPL(hv_result_to_string);
diff --git a/drivers/hv/hv_proc.c b/drivers/hv/hv_proc.c
index 2fae18e4f7d2..605999f10e17 100644
--- a/drivers/hv/hv_proc.c
+++ b/drivers/hv/hv_proc.c
@@ -87,7 +87,7 @@ int hv_call_deposit_pages(int node, u64 partition_id, u32 num_pages)
page_count, 0, input_page, NULL);
local_irq_restore(flags);
if (!hv_result_success(status)) {
- pr_err("Failed to deposit pages: %lld\n", status);
+ hv_status_err(status, "\n");
ret = hv_result_to_errno(status);
goto err_free_allocations;
}
@@ -137,8 +137,8 @@ int hv_call_add_logical_proc(int node, u32 lp_index, u32 apic_id)
if (hv_result(status) != HV_STATUS_INSUFFICIENT_MEMORY) {
if (!hv_result_success(status)) {
- pr_err("%s: cpu %u apic ID %u, %lld\n", __func__,
- lp_index, apic_id, status);
+ hv_status_err(status, "cpu %u apic ID: %u\n",
+ lp_index, apic_id);
ret = hv_result_to_errno(status);
}
break;
@@ -179,8 +179,8 @@ int hv_call_create_vp(int node, u64 partition_id, u32 vp_index, u32 flags)
if (hv_result(status) != HV_STATUS_INSUFFICIENT_MEMORY) {
if (!hv_result_success(status)) {
- pr_err("%s: vcpu %u, lp %u, %lld\n", __func__,
- vp_index, flags, status);
+ hv_status_err(status, "vcpu: %u, lp: %u\n",
+ vp_index, flags);
ret = hv_result_to_errno(status);
}
break;
diff --git a/drivers/iommu/hyperv-iommu.c b/drivers/iommu/hyperv-iommu.c
index 53e4b37716af..761ab647f372 100644
--- a/drivers/iommu/hyperv-iommu.c
+++ b/drivers/iommu/hyperv-iommu.c
@@ -217,7 +217,7 @@ hyperv_root_ir_compose_msi_msg(struct irq_data *irq_data, struct msi_msg *msg)
status = hv_unmap_ioapic_interrupt(ioapic_id, &entry);
if (status != HV_STATUS_SUCCESS)
- pr_debug("%s: unexpected unmap status %lld\n", __func__, status);
+ hv_status_debug(status, "failed to unmap\n");
data->entry.ioapic_rte.as_uint64 = 0;
data->entry.source = 0; /* Invalid source */
@@ -228,7 +228,7 @@ hyperv_root_ir_compose_msi_msg(struct irq_data *irq_data, struct msi_msg *msg)
vector, &entry);
if (status != HV_STATUS_SUCCESS) {
- pr_err("%s: map hypercall failed, status %lld\n", __func__, status);
+ hv_status_err(status, "map failed\n");
return;
}
diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h
index b13b0cda4ac8..250c65236919 100644
--- a/include/asm-generic/mshyperv.h
+++ b/include/asm-generic/mshyperv.h
@@ -298,6 +298,19 @@ static inline int cpumask_to_vpset_skip(struct hv_vpset *vpset,
return __cpumask_to_vpset(vpset, cpus, func);
}
+#define _hv_status_fmt(fmt) "%s: Hyper-V status: %#x = %s: " fmt
+#define hv_status_printk(level, status, fmt, ...) \
+do { \
+ u64 __status = (status); \
+ pr_##level(_hv_status_fmt(fmt), __func__, hv_result(__status), \
+ hv_result_to_string(__status), ##__VA_ARGS__); \
+} while (0)
+#define hv_status_err(status, fmt, ...) \
+ hv_status_printk(err, status, fmt, ##__VA_ARGS__)
+#define hv_status_debug(status, fmt, ...) \
+ hv_status_printk(debug, status, fmt, ##__VA_ARGS__)
+
+const char *hv_result_to_string(u64 hv_status);
int hv_result_to_errno(u64 status);
void hyperv_report_panic(struct pt_regs *regs, long err, bool in_die);
bool hv_is_hyperv_initialized(void);
--
2.34.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v6 02/10] x86/mshyperv: Add support for extended Hyper-V features
2025-03-14 19:28 [PATCH v6 00/10] Introduce /dev/mshv root partition driver Nuno Das Neves
2025-03-14 19:28 ` [PATCH v6 01/10] hyperv: Log hypercall status codes as strings Nuno Das Neves
@ 2025-03-14 19:28 ` Nuno Das Neves
2025-03-14 19:28 ` [PATCH v6 03/10] arm64/hyperv: Add some missing functions to arm64 Nuno Das Neves
` (8 subsequent siblings)
10 siblings, 0 replies; 20+ messages in thread
From: Nuno Das Neves @ 2025-03-14 19:28 UTC (permalink / raw)
To: linux-hyperv, x86, linux-arm-kernel, linux-kernel, linux-arch,
mhklinux, ltykernel, stanislav.kinsburskiy, linux-acpi, eahariha,
jeff.johnson
Cc: kys, haiyangz, wei.liu, decui, catalin.marinas, will, tglx, mingo,
bp, dave.hansen, hpa, daniel.lezcano, joro, robin.murphy, arnd,
jinankjain, muminulrussell, skinsburskii, mrathor, ssengar, apais,
gregkh, vkuznets, prapal, anrayabh, rafael, lenb, corbet
From: Stanislav Kinsburskii <skinsburskii@linux.microsoft.com>
Extend the "ms_hyperv_info" structure to include a new field,
"ext_features", for capturing extended Hyper-V features.
Update the "ms_hyperv_init_platform" function to retrieve these features
using the cpuid instruction and include them in the informational output.
Signed-off-by: Stanislav Kinsburskii <skinsburskii@linux.microsoft.com>
Signed-off-by: Nuno Das Neves <nunodasneves@linux.microsoft.com>
Reviewed-by: Easwar Hariharan <eahariha@linux.microsoft.com>
Reviewed-by: Roman Kisel <romank@linux.microsoft.com>
Reviewed-by: Tianyu Lan <tiala@microsoft.com>
Reviewed-by: Michael Kelley <mhklinux@outlook.com>
---
arch/x86/kernel/cpu/mshyperv.c | 6 ++++--
include/asm-generic/mshyperv.h | 1 +
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
index 4f01f424ea5b..fd285b18d6b4 100644
--- a/arch/x86/kernel/cpu/mshyperv.c
+++ b/arch/x86/kernel/cpu/mshyperv.c
@@ -434,13 +434,15 @@ static void __init ms_hyperv_init_platform(void)
*/
ms_hyperv.features = cpuid_eax(HYPERV_CPUID_FEATURES);
ms_hyperv.priv_high = cpuid_ebx(HYPERV_CPUID_FEATURES);
+ ms_hyperv.ext_features = cpuid_ecx(HYPERV_CPUID_FEATURES);
ms_hyperv.misc_features = cpuid_edx(HYPERV_CPUID_FEATURES);
ms_hyperv.hints = cpuid_eax(HYPERV_CPUID_ENLIGHTMENT_INFO);
hv_max_functions_eax = cpuid_eax(HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS);
- pr_info("Hyper-V: privilege flags low 0x%x, high 0x%x, hints 0x%x, misc 0x%x\n",
- ms_hyperv.features, ms_hyperv.priv_high, ms_hyperv.hints,
+ pr_info("Hyper-V: privilege flags low %#x, high %#x, ext %#x, hints %#x, misc %#x\n",
+ ms_hyperv.features, ms_hyperv.priv_high,
+ ms_hyperv.ext_features, ms_hyperv.hints,
ms_hyperv.misc_features);
ms_hyperv.max_vp_index = cpuid_eax(HYPERV_CPUID_IMPLEMENT_LIMITS);
diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h
index 250c65236919..c8043efabf5a 100644
--- a/include/asm-generic/mshyperv.h
+++ b/include/asm-generic/mshyperv.h
@@ -36,6 +36,7 @@ enum hv_partition_type {
struct ms_hyperv_info {
u32 features;
u32 priv_high;
+ u32 ext_features;
u32 misc_features;
u32 hints;
u32 nested_features;
--
2.34.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v6 03/10] arm64/hyperv: Add some missing functions to arm64
2025-03-14 19:28 [PATCH v6 00/10] Introduce /dev/mshv root partition driver Nuno Das Neves
2025-03-14 19:28 ` [PATCH v6 01/10] hyperv: Log hypercall status codes as strings Nuno Das Neves
2025-03-14 19:28 ` [PATCH v6 02/10] x86/mshyperv: Add support for extended Hyper-V features Nuno Das Neves
@ 2025-03-14 19:28 ` Nuno Das Neves
2025-03-19 4:08 ` Easwar Hariharan
2025-03-14 19:28 ` [PATCH v6 04/10] hyperv: Introduce hv_recommend_using_aeoi() Nuno Das Neves
` (7 subsequent siblings)
10 siblings, 1 reply; 20+ messages in thread
From: Nuno Das Neves @ 2025-03-14 19:28 UTC (permalink / raw)
To: linux-hyperv, x86, linux-arm-kernel, linux-kernel, linux-arch,
mhklinux, ltykernel, stanislav.kinsburskiy, linux-acpi, eahariha,
jeff.johnson
Cc: kys, haiyangz, wei.liu, decui, catalin.marinas, will, tglx, mingo,
bp, dave.hansen, hpa, daniel.lezcano, joro, robin.murphy, arnd,
jinankjain, muminulrussell, skinsburskii, mrathor, ssengar, apais,
gregkh, vkuznets, prapal, anrayabh, rafael, lenb, corbet
These non-nested msr and fast hypercall functions are present in x86,
but they must be available in both architectures for the root partition
driver code.
While at it, remove the redundant 'extern' keywords from the
hv_do_hypercall() variants in asm-generic/mshyperv.h.
Signed-off-by: Nuno Das Neves <nunodasneves@linux.microsoft.com>
Reviewed-by: Stanislav Kinsburskii <skinsburskii@linux.microsoft.com>
Reviewed-by: Roman Kisel <romank@linux.microsoft.com>
---
arch/arm64/hyperv/hv_core.c | 17 +++++++++++++++++
arch/arm64/include/asm/mshyperv.h | 13 +++++++++++++
include/asm-generic/mshyperv.h | 6 ++++--
3 files changed, 34 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/hyperv/hv_core.c b/arch/arm64/hyperv/hv_core.c
index 69004f619c57..e33a9e3c366a 100644
--- a/arch/arm64/hyperv/hv_core.c
+++ b/arch/arm64/hyperv/hv_core.c
@@ -53,6 +53,23 @@ u64 hv_do_fast_hypercall8(u16 code, u64 input)
}
EXPORT_SYMBOL_GPL(hv_do_fast_hypercall8);
+/*
+ * hv_do_fast_hypercall16 -- Invoke the specified hypercall
+ * with arguments in registers instead of physical memory.
+ * Avoids the overhead of virt_to_phys for simple hypercalls.
+ */
+u64 hv_do_fast_hypercall16(u16 code, u64 input1, u64 input2)
+{
+ struct arm_smccc_res res;
+ u64 control;
+
+ control = (u64)code | HV_HYPERCALL_FAST_BIT;
+
+ arm_smccc_1_1_hvc(HV_FUNC_ID, control, input1, input2, &res);
+ return res.a0;
+}
+EXPORT_SYMBOL_GPL(hv_do_fast_hypercall16);
+
/*
* Set a single VP register to a 64-bit value.
*/
diff --git a/arch/arm64/include/asm/mshyperv.h b/arch/arm64/include/asm/mshyperv.h
index 2e2f83bafcfb..b721d3134ab6 100644
--- a/arch/arm64/include/asm/mshyperv.h
+++ b/arch/arm64/include/asm/mshyperv.h
@@ -40,6 +40,19 @@ static inline u64 hv_get_msr(unsigned int reg)
return hv_get_vpreg(reg);
}
+/*
+ * Nested is not supported on arm64
+ */
+static inline void hv_set_non_nested_msr(unsigned int reg, u64 value)
+{
+ hv_set_msr(reg, value);
+}
+
+static inline u64 hv_get_non_nested_msr(unsigned int reg)
+{
+ return hv_get_msr(reg);
+}
+
/* SMCCC hypercall parameters */
#define HV_SMCCC_FUNC_NUMBER 1
#define HV_FUNC_ID ARM_SMCCC_CALL_VAL( \
diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h
index c8043efabf5a..c3697bc0598d 100644
--- a/include/asm-generic/mshyperv.h
+++ b/include/asm-generic/mshyperv.h
@@ -70,8 +70,10 @@ extern enum hv_partition_type hv_curr_partition_type;
extern void * __percpu *hyperv_pcpu_input_arg;
extern void * __percpu *hyperv_pcpu_output_arg;
-extern u64 hv_do_hypercall(u64 control, void *inputaddr, void *outputaddr);
-extern u64 hv_do_fast_hypercall8(u16 control, u64 input8);
+u64 hv_do_hypercall(u64 control, void *inputaddr, void *outputaddr);
+u64 hv_do_fast_hypercall8(u16 control, u64 input8);
+u64 hv_do_fast_hypercall16(u16 control, u64 input1, u64 input2);
+
bool hv_isolation_type_snp(void);
bool hv_isolation_type_tdx(void);
--
2.34.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v6 04/10] hyperv: Introduce hv_recommend_using_aeoi()
2025-03-14 19:28 [PATCH v6 00/10] Introduce /dev/mshv root partition driver Nuno Das Neves
` (2 preceding siblings ...)
2025-03-14 19:28 ` [PATCH v6 03/10] arm64/hyperv: Add some missing functions to arm64 Nuno Das Neves
@ 2025-03-14 19:28 ` Nuno Das Neves
2025-03-14 19:28 ` [PATCH v6 05/10] acpi: numa: Export node_to_pxm() Nuno Das Neves
` (6 subsequent siblings)
10 siblings, 0 replies; 20+ messages in thread
From: Nuno Das Neves @ 2025-03-14 19:28 UTC (permalink / raw)
To: linux-hyperv, x86, linux-arm-kernel, linux-kernel, linux-arch,
mhklinux, ltykernel, stanislav.kinsburskiy, linux-acpi, eahariha,
jeff.johnson
Cc: kys, haiyangz, wei.liu, decui, catalin.marinas, will, tglx, mingo,
bp, dave.hansen, hpa, daniel.lezcano, joro, robin.murphy, arnd,
jinankjain, muminulrussell, skinsburskii, mrathor, ssengar, apais,
gregkh, vkuznets, prapal, anrayabh, rafael, lenb, corbet
Factor out the check for enabling auto eoi, to be reused in root
partition code.
No functional changes.
Signed-off-by: Nuno Das Neves <nunodasneves@linux.microsoft.com>
Reviewed-by: Stanislav Kinsburskii <skinsburskii@linux.microsoft.com>
Reviewed-by: Easwar Hariharan <eahariha@linux.microsoft.com>
Reviewed-by: Michael Kelley <mhklinux@outlook.com>
Reviewed-by: Tianyu Lan <tiala@microsoft.com>
---
drivers/hv/hv.c | 12 +-----------
include/asm-generic/mshyperv.h | 13 +++++++++++++
2 files changed, 14 insertions(+), 11 deletions(-)
diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c
index a38f84548bc2..308c8f279df8 100644
--- a/drivers/hv/hv.c
+++ b/drivers/hv/hv.c
@@ -313,17 +313,7 @@ void hv_synic_enable_regs(unsigned int cpu)
shared_sint.vector = vmbus_interrupt;
shared_sint.masked = false;
-
- /*
- * On architectures where Hyper-V doesn't support AEOI (e.g., ARM64),
- * it doesn't provide a recommendation flag and AEOI must be disabled.
- */
-#ifdef HV_DEPRECATING_AEOI_RECOMMENDED
- shared_sint.auto_eoi =
- !(ms_hyperv.hints & HV_DEPRECATING_AEOI_RECOMMENDED);
-#else
- shared_sint.auto_eoi = 0;
-#endif
+ shared_sint.auto_eoi = hv_recommend_using_aeoi();
hv_set_msr(HV_MSR_SINT0 + VMBUS_MESSAGE_SINT, shared_sint.as_uint64);
/* Enable the global synic bit */
diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h
index c3697bc0598d..8519b8ec8e9d 100644
--- a/include/asm-generic/mshyperv.h
+++ b/include/asm-generic/mshyperv.h
@@ -77,6 +77,19 @@ u64 hv_do_fast_hypercall16(u16 control, u64 input1, u64 input2);
bool hv_isolation_type_snp(void);
bool hv_isolation_type_tdx(void);
+/*
+ * On architectures where Hyper-V doesn't support AEOI (e.g., ARM64),
+ * it doesn't provide a recommendation flag and AEOI must be disabled.
+ */
+static inline bool hv_recommend_using_aeoi(void)
+{
+#ifdef HV_DEPRECATING_AEOI_RECOMMENDED
+ return !(ms_hyperv.hints & HV_DEPRECATING_AEOI_RECOMMENDED);
+#else
+ return false;
+#endif
+}
+
static inline struct hv_proximity_domain_info hv_numa_node_to_pxm_info(int node)
{
struct hv_proximity_domain_info pxm_info = {};
--
2.34.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v6 05/10] acpi: numa: Export node_to_pxm()
2025-03-14 19:28 [PATCH v6 00/10] Introduce /dev/mshv root partition driver Nuno Das Neves
` (3 preceding siblings ...)
2025-03-14 19:28 ` [PATCH v6 04/10] hyperv: Introduce hv_recommend_using_aeoi() Nuno Das Neves
@ 2025-03-14 19:28 ` Nuno Das Neves
2025-03-14 19:28 ` [PATCH v6 06/10] Drivers: hv: Export some functions for use by root partition module Nuno Das Neves
` (5 subsequent siblings)
10 siblings, 0 replies; 20+ messages in thread
From: Nuno Das Neves @ 2025-03-14 19:28 UTC (permalink / raw)
To: linux-hyperv, x86, linux-arm-kernel, linux-kernel, linux-arch,
mhklinux, ltykernel, stanislav.kinsburskiy, linux-acpi, eahariha,
jeff.johnson
Cc: kys, haiyangz, wei.liu, decui, catalin.marinas, will, tglx, mingo,
bp, dave.hansen, hpa, daniel.lezcano, joro, robin.murphy, arnd,
jinankjain, muminulrussell, skinsburskii, mrathor, ssengar, apais,
gregkh, vkuznets, prapal, anrayabh, rafael, lenb, corbet
node_to_pxm() is used by hv_numa_node_to_pxm_info().
That helper will be used by Hyper-V root partition module code
when CONFIG_MSHV_ROOT=m.
Signed-off-by: Nuno Das Neves <nunodasneves@linux.microsoft.com>
Reviewed-by: Stanislav Kinsburskii <skinsburskii@linux.microsoft.com>
Reviewed-by: Easwar Hariharan <eahariha@linux.microsoft.com>
Reviewed-by: Michael Kelley <mhklinux@outlook.com>
Reviewed-by: Tianyu Lan <tiala@microsoft.com>
---
drivers/acpi/numa/srat.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/acpi/numa/srat.c b/drivers/acpi/numa/srat.c
index 00ac0d7bb8c9..ce815d7cb8f6 100644
--- a/drivers/acpi/numa/srat.c
+++ b/drivers/acpi/numa/srat.c
@@ -51,6 +51,7 @@ int node_to_pxm(int node)
return PXM_INVAL;
return node_to_pxm_map[node];
}
+EXPORT_SYMBOL_GPL(node_to_pxm);
static void __acpi_map_pxm_to_node(int pxm, int node)
{
--
2.34.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v6 06/10] Drivers: hv: Export some functions for use by root partition module
2025-03-14 19:28 [PATCH v6 00/10] Introduce /dev/mshv root partition driver Nuno Das Neves
` (4 preceding siblings ...)
2025-03-14 19:28 ` [PATCH v6 05/10] acpi: numa: Export node_to_pxm() Nuno Das Neves
@ 2025-03-14 19:28 ` Nuno Das Neves
2025-03-14 19:28 ` [PATCH v6 07/10] Drivers: hv: Introduce per-cpu event ring tail Nuno Das Neves
` (4 subsequent siblings)
10 siblings, 0 replies; 20+ messages in thread
From: Nuno Das Neves @ 2025-03-14 19:28 UTC (permalink / raw)
To: linux-hyperv, x86, linux-arm-kernel, linux-kernel, linux-arch,
mhklinux, ltykernel, stanislav.kinsburskiy, linux-acpi, eahariha,
jeff.johnson
Cc: kys, haiyangz, wei.liu, decui, catalin.marinas, will, tglx, mingo,
bp, dave.hansen, hpa, daniel.lezcano, joro, robin.murphy, arnd,
jinankjain, muminulrussell, skinsburskii, mrathor, ssengar, apais,
gregkh, vkuznets, prapal, anrayabh, rafael, lenb, corbet
hv_get_hypervisor_version(), hv_call_deposit_pages(), and
hv_call_create_vp(), are all needed in-module with CONFIG_MSHV_ROOT=m.
Signed-off-by: Nuno Das Neves <nunodasneves@linux.microsoft.com>
Reviewed-by: Stanislav Kinsburskii <skinsburskii@microsoft.linux.com>
Reviewed-by: Roman Kisel <romank@linux.microsoft.com>
Reviewed-by: Easwar Hariharan <eahariha@linux.microsoft.com>
Reviewed-by: Tianyu Lan <tiala@microsoft.com>
---
arch/arm64/hyperv/mshyperv.c | 1 +
arch/x86/kernel/cpu/mshyperv.c | 1 +
drivers/hv/hv_proc.c | 3 ++-
3 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/hyperv/mshyperv.c b/arch/arm64/hyperv/mshyperv.c
index 2265ea5ce5ad..4e27cc29c79e 100644
--- a/arch/arm64/hyperv/mshyperv.c
+++ b/arch/arm64/hyperv/mshyperv.c
@@ -26,6 +26,7 @@ int hv_get_hypervisor_version(union hv_hypervisor_version_info *info)
return 0;
}
+EXPORT_SYMBOL_GPL(hv_get_hypervisor_version);
static int __init hyperv_init(void)
{
diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
index fd285b18d6b4..fcd0e066d9bd 100644
--- a/arch/x86/kernel/cpu/mshyperv.c
+++ b/arch/x86/kernel/cpu/mshyperv.c
@@ -420,6 +420,7 @@ int hv_get_hypervisor_version(union hv_hypervisor_version_info *info)
return 0;
}
+EXPORT_SYMBOL_GPL(hv_get_hypervisor_version);
static void __init ms_hyperv_init_platform(void)
{
diff --git a/drivers/hv/hv_proc.c b/drivers/hv/hv_proc.c
index 605999f10e17..7d7ecb6f6137 100644
--- a/drivers/hv/hv_proc.c
+++ b/drivers/hv/hv_proc.c
@@ -107,6 +107,7 @@ int hv_call_deposit_pages(int node, u64 partition_id, u32 num_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)
{
@@ -191,4 +192,4 @@ int hv_call_create_vp(int node, u64 partition_id, u32 vp_index, u32 flags)
return ret;
}
-
+EXPORT_SYMBOL_GPL(hv_call_create_vp);
--
2.34.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v6 07/10] Drivers: hv: Introduce per-cpu event ring tail
2025-03-14 19:28 [PATCH v6 00/10] Introduce /dev/mshv root partition driver Nuno Das Neves
` (5 preceding siblings ...)
2025-03-14 19:28 ` [PATCH v6 06/10] Drivers: hv: Export some functions for use by root partition module Nuno Das Neves
@ 2025-03-14 19:28 ` Nuno Das Neves
2025-03-14 19:28 ` [PATCH v6 08/10] x86: hyperv: Add mshv_handler() irq handler and setup function Nuno Das Neves
` (3 subsequent siblings)
10 siblings, 0 replies; 20+ messages in thread
From: Nuno Das Neves @ 2025-03-14 19:28 UTC (permalink / raw)
To: linux-hyperv, x86, linux-arm-kernel, linux-kernel, linux-arch,
mhklinux, ltykernel, stanislav.kinsburskiy, linux-acpi, eahariha,
jeff.johnson
Cc: kys, haiyangz, wei.liu, decui, catalin.marinas, will, tglx, mingo,
bp, dave.hansen, hpa, daniel.lezcano, joro, robin.murphy, arnd,
jinankjain, muminulrussell, skinsburskii, mrathor, ssengar, apais,
gregkh, vkuznets, prapal, anrayabh, rafael, lenb, corbet
Add a pointer hv_synic_eventring_tail to track the tail pointer for the
SynIC event ring buffer for each SINT.
This will be used by the mshv driver, but must be tracked independently
since the driver module could be removed and re-inserted.
Signed-off-by: Nuno Das Neves <nunodasneves@linux.microsoft.com>
Reviewed-by: Wei Liu <wei.liu@kernel.org>
Reviewed-by: Stanislav Kinsburskii <skinsburskii@linux.microsoft.com>
---
drivers/hv/hv_common.c | 41 +++++++++++++++++++++++++++++++++++++----
1 file changed, 37 insertions(+), 4 deletions(-)
diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c
index 885bbc3d86d8..3cd9b96ffc67 100644
--- a/drivers/hv/hv_common.c
+++ b/drivers/hv/hv_common.c
@@ -68,6 +68,16 @@ static void hv_kmsg_dump_unregister(void);
static struct ctl_table_header *hv_ctl_table_hdr;
+/*
+ * Per-cpu array holding the tail pointer for the SynIC event ring buffer
+ * for each SINT.
+ *
+ * We cannot maintain this in mshv driver because the tail pointer should
+ * persist even if the mshv driver is unloaded.
+ */
+u8 * __percpu *hv_synic_eventring_tail;
+EXPORT_SYMBOL_GPL(hv_synic_eventring_tail);
+
/*
* Hyper-V specific initialization and shutdown code that is
* common across all architectures. Called from architecture
@@ -90,6 +100,9 @@ void __init hv_common_free(void)
free_percpu(hyperv_pcpu_input_arg);
hyperv_pcpu_input_arg = NULL;
+
+ free_percpu(hv_synic_eventring_tail);
+ hv_synic_eventring_tail = NULL;
}
/*
@@ -372,6 +385,11 @@ int __init hv_common_init(void)
BUG_ON(!hyperv_pcpu_output_arg);
}
+ if (hv_root_partition()) {
+ hv_synic_eventring_tail = alloc_percpu(u8 *);
+ BUG_ON(!hv_synic_eventring_tail);
+ }
+
hv_vp_index = kmalloc_array(nr_cpu_ids, sizeof(*hv_vp_index),
GFP_KERNEL);
if (!hv_vp_index) {
@@ -460,11 +478,12 @@ void __init ms_hyperv_late_init(void)
int hv_common_cpu_init(unsigned int cpu)
{
void **inputarg, **outputarg;
+ u8 **synic_eventring_tail;
u64 msr_vp_index;
gfp_t flags;
const int pgcount = hv_output_page_exists() ? 2 : 1;
void *mem;
- int ret;
+ int ret = 0;
/* hv_cpu_init() can be called with IRQs disabled from hv_resume() */
flags = irqs_disabled() ? GFP_ATOMIC : GFP_KERNEL;
@@ -472,8 +491,8 @@ int hv_common_cpu_init(unsigned int cpu)
inputarg = (void **)this_cpu_ptr(hyperv_pcpu_input_arg);
/*
- * hyperv_pcpu_input_arg and hyperv_pcpu_output_arg memory is already
- * allocated if this CPU was previously online and then taken offline
+ * The per-cpu memory is already allocated if this CPU was previously
+ * online and then taken offline
*/
if (!*inputarg) {
mem = kmalloc(pgcount * HV_HYP_PAGE_SIZE, flags);
@@ -520,11 +539,21 @@ int hv_common_cpu_init(unsigned int cpu)
if (msr_vp_index > hv_max_vp_index)
hv_max_vp_index = msr_vp_index;
- return 0;
+ if (hv_root_partition()) {
+ synic_eventring_tail = (u8 **)this_cpu_ptr(hv_synic_eventring_tail);
+ *synic_eventring_tail = kcalloc(HV_SYNIC_SINT_COUNT,
+ sizeof(u8), flags);
+ /* No need to unwind any of the above on failure here */
+ if (unlikely(!*synic_eventring_tail))
+ ret = -ENOMEM;
+ }
+
+ return ret;
}
int hv_common_cpu_die(unsigned int cpu)
{
+ u8 **synic_eventring_tail;
/*
* The hyperv_pcpu_input_arg and hyperv_pcpu_output_arg memory
* is not freed when the CPU goes offline as the hyperv_pcpu_input_arg
@@ -537,6 +566,10 @@ int hv_common_cpu_die(unsigned int cpu)
* originally allocated memory is reused in hv_common_cpu_init().
*/
+ synic_eventring_tail = this_cpu_ptr(hv_synic_eventring_tail);
+ kfree(*synic_eventring_tail);
+ *synic_eventring_tail = NULL;
+
return 0;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v6 08/10] x86: hyperv: Add mshv_handler() irq handler and setup function
2025-03-14 19:28 [PATCH v6 00/10] Introduce /dev/mshv root partition driver Nuno Das Neves
` (6 preceding siblings ...)
2025-03-14 19:28 ` [PATCH v6 07/10] Drivers: hv: Introduce per-cpu event ring tail Nuno Das Neves
@ 2025-03-14 19:28 ` Nuno Das Neves
2025-03-14 19:28 ` [PATCH v6 09/10] hyperv: Add definitions for root partition driver to hv headers Nuno Das Neves
` (2 subsequent siblings)
10 siblings, 0 replies; 20+ messages in thread
From: Nuno Das Neves @ 2025-03-14 19:28 UTC (permalink / raw)
To: linux-hyperv, x86, linux-arm-kernel, linux-kernel, linux-arch,
mhklinux, ltykernel, stanislav.kinsburskiy, linux-acpi, eahariha,
jeff.johnson
Cc: kys, haiyangz, wei.liu, decui, catalin.marinas, will, tglx, mingo,
bp, dave.hansen, hpa, daniel.lezcano, joro, robin.murphy, arnd,
jinankjain, muminulrussell, skinsburskii, mrathor, ssengar, apais,
gregkh, vkuznets, prapal, anrayabh, rafael, lenb, corbet
Add mshv_handler() to process messages related to managing guest
partitions such as intercepts, doorbells, and scheduling messages.
In a (non-nested) root partition, the same interrupt vector is shared
between the vmbus and mshv_root drivers.
Introduce a stub for mshv_handler() and call it in
sysvec_hyperv_callback alongside vmbus_handler().
Even though both handlers will be called for every Hyper-V interrupt,
the messages for each driver are delivered to different offsets
within the SYNIC message page, so they won't step on each other.
Signed-off-by: Nuno Das Neves <nunodasneves@linux.microsoft.com>
Reviewed-by: Wei Liu <wei.liu@kernel.org>
Reviewed-by: Tianyu Lan <tiala@microsoft.com>
---
arch/x86/kernel/cpu/mshyperv.c | 9 +++++++++
drivers/hv/hv_common.c | 5 +++++
include/asm-generic/mshyperv.h | 1 +
3 files changed, 15 insertions(+)
diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
index fcd0e066d9bd..3e2533954675 100644
--- a/arch/x86/kernel/cpu/mshyperv.c
+++ b/arch/x86/kernel/cpu/mshyperv.c
@@ -107,6 +107,7 @@ void hv_set_msr(unsigned int reg, u64 value)
}
EXPORT_SYMBOL_GPL(hv_set_msr);
+static void (*mshv_handler)(void);
static void (*vmbus_handler)(void);
static void (*hv_stimer0_handler)(void);
static void (*hv_kexec_handler)(void);
@@ -117,6 +118,9 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_hyperv_callback)
struct pt_regs *old_regs = set_irq_regs(regs);
inc_irq_stat(irq_hv_callback_count);
+ if (mshv_handler)
+ mshv_handler();
+
if (vmbus_handler)
vmbus_handler();
@@ -126,6 +130,11 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_hyperv_callback)
set_irq_regs(old_regs);
}
+void hv_setup_mshv_handler(void (*handler)(void))
+{
+ mshv_handler = handler;
+}
+
void hv_setup_vmbus_handler(void (*handler)(void))
{
vmbus_handler = handler;
diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c
index 3cd9b96ffc67..b3b11be11650 100644
--- a/drivers/hv/hv_common.c
+++ b/drivers/hv/hv_common.c
@@ -680,6 +680,11 @@ void __weak hv_remove_vmbus_handler(void)
}
EXPORT_SYMBOL_GPL(hv_remove_vmbus_handler);
+void __weak hv_setup_mshv_handler(void (*handler)(void))
+{
+}
+EXPORT_SYMBOL_GPL(hv_setup_mshv_handler);
+
void __weak hv_setup_kexec_handler(void (*handler)(void))
{
}
diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h
index 8519b8ec8e9d..ccccb1cbf7df 100644
--- a/include/asm-generic/mshyperv.h
+++ b/include/asm-generic/mshyperv.h
@@ -208,6 +208,7 @@ void hv_setup_kexec_handler(void (*handler)(void));
void hv_remove_kexec_handler(void);
void hv_setup_crash_handler(void (*handler)(struct pt_regs *regs));
void hv_remove_crash_handler(void);
+void hv_setup_mshv_handler(void (*handler)(void));
extern int vmbus_interrupt;
extern int vmbus_irq;
--
2.34.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v6 09/10] hyperv: Add definitions for root partition driver to hv headers
2025-03-14 19:28 [PATCH v6 00/10] Introduce /dev/mshv root partition driver Nuno Das Neves
` (7 preceding siblings ...)
2025-03-14 19:28 ` [PATCH v6 08/10] x86: hyperv: Add mshv_handler() irq handler and setup function Nuno Das Neves
@ 2025-03-14 19:28 ` Nuno Das Neves
2025-03-19 4:04 ` Easwar Hariharan
2025-03-17 21:27 ` [PATCH v6 00/10] Introduce /dev/mshv root partition driver Wei Liu
[not found] ` <1741980536-3865-11-git-send-email-nunodasneves@linux.microsoft.com>
10 siblings, 1 reply; 20+ messages in thread
From: Nuno Das Neves @ 2025-03-14 19:28 UTC (permalink / raw)
To: linux-hyperv, x86, linux-arm-kernel, linux-kernel, linux-arch,
mhklinux, ltykernel, stanislav.kinsburskiy, linux-acpi, eahariha,
jeff.johnson
Cc: kys, haiyangz, wei.liu, decui, catalin.marinas, will, tglx, mingo,
bp, dave.hansen, hpa, daniel.lezcano, joro, robin.murphy, arnd,
jinankjain, muminulrussell, skinsburskii, mrathor, ssengar, apais,
gregkh, vkuznets, prapal, anrayabh, rafael, lenb, corbet
A few additional definitions are required for the mshv driver code
(to follow). Introduce those here and clean up a little bit while
at it.
Signed-off-by: Nuno Das Neves <nunodasneves@linux.microsoft.com>
Reviewed-by: Roman Kisel <romank@linux.microsoft.com>
Reviewed-by: Stanislav Kinsburskii <skinsburskii@linux.microsoft.com>
Reviewed-by: Tianyu Lan <tiala@microsoft.com>
---
include/hyperv/hvgdk_mini.h | 72 ++++++++++++++++++--
include/hyperv/hvhdk.h | 132 ++++++++++++++++++++++++++++++++++--
include/hyperv/hvhdk_mini.h | 91 +++++++++++++++++++++++++
3 files changed, 284 insertions(+), 11 deletions(-)
diff --git a/include/hyperv/hvgdk_mini.h b/include/hyperv/hvgdk_mini.h
index 58895883f636..735329859f21 100644
--- a/include/hyperv/hvgdk_mini.h
+++ b/include/hyperv/hvgdk_mini.h
@@ -13,7 +13,7 @@ struct hv_u128 {
u64 high_part;
} __packed;
-/* NOTE: when adding below, update hv_status_to_string() */
+/* NOTE: when adding below, update hv_result_to_string() */
#define HV_STATUS_SUCCESS 0x0
#define HV_STATUS_INVALID_HYPERCALL_CODE 0x2
#define HV_STATUS_INVALID_HYPERCALL_INPUT 0x3
@@ -51,6 +51,7 @@ struct hv_u128 {
#define HV_HYP_PAGE_SHIFT 12
#define HV_HYP_PAGE_SIZE BIT(HV_HYP_PAGE_SHIFT)
#define HV_HYP_PAGE_MASK (~(HV_HYP_PAGE_SIZE - 1))
+#define HV_HYP_LARGE_PAGE_SHIFT 21
#define HV_PARTITION_ID_INVALID ((u64)0)
#define HV_PARTITION_ID_SELF ((u64)-1)
@@ -374,6 +375,10 @@ union hv_hypervisor_version_info {
#define HV_SHARED_GPA_BOUNDARY_ACTIVE BIT(5)
#define HV_SHARED_GPA_BOUNDARY_BITS GENMASK(11, 6)
+/* HYPERV_CPUID_FEATURES.ECX bits. */
+#define HV_VP_DISPATCH_INTERRUPT_INJECTION_AVAILABLE BIT(9)
+#define HV_VP_GHCB_ROOT_MAPPING_AVAILABLE BIT(10)
+
enum hv_isolation_type {
HV_ISOLATION_TYPE_NONE = 0, /* HV_PARTITION_ISOLATION_TYPE_NONE */
HV_ISOLATION_TYPE_VBS = 1,
@@ -436,10 +441,13 @@ union hv_vp_assist_msr_contents { /* HV_REGISTER_VP_ASSIST_PAGE */
#define HVCALL_WITHDRAW_MEMORY 0x0049
#define HVCALL_MAP_GPA_PAGES 0x004b
#define HVCALL_UNMAP_GPA_PAGES 0x004c
+#define HVCALL_INSTALL_INTERCEPT 0x004d
#define HVCALL_CREATE_VP 0x004e
#define HVCALL_DELETE_VP 0x004f
#define HVCALL_GET_VP_REGISTERS 0x0050
#define HVCALL_SET_VP_REGISTERS 0x0051
+#define HVCALL_TRANSLATE_VIRTUAL_ADDRESS 0x0052
+#define HVCALL_CLEAR_VIRTUAL_INTERRUPT 0x0056
#define HVCALL_DELETE_PORT 0x0058
#define HVCALL_DISCONNECT_PORT 0x005b
#define HVCALL_POST_MESSAGE 0x005c
@@ -447,12 +455,15 @@ union hv_vp_assist_msr_contents { /* HV_REGISTER_VP_ASSIST_PAGE */
#define HVCALL_POST_DEBUG_DATA 0x0069
#define HVCALL_RETRIEVE_DEBUG_DATA 0x006a
#define HVCALL_RESET_DEBUG_SESSION 0x006b
+#define HVCALL_MAP_STATS_PAGE 0x006c
+#define HVCALL_UNMAP_STATS_PAGE 0x006d
#define HVCALL_ADD_LOGICAL_PROCESSOR 0x0076
#define HVCALL_GET_SYSTEM_PROPERTY 0x007b
#define HVCALL_MAP_DEVICE_INTERRUPT 0x007c
#define HVCALL_UNMAP_DEVICE_INTERRUPT 0x007d
#define HVCALL_RETARGET_INTERRUPT 0x007e
#define HVCALL_NOTIFY_PORT_RING_EMPTY 0x008b
+#define HVCALL_REGISTER_INTERCEPT_RESULT 0x0091
#define HVCALL_ASSERT_VIRTUAL_INTERRUPT 0x0094
#define HVCALL_CREATE_PORT 0x0095
#define HVCALL_CONNECT_PORT 0x0096
@@ -460,12 +471,18 @@ union hv_vp_assist_msr_contents { /* HV_REGISTER_VP_ASSIST_PAGE */
#define HVCALL_GET_VP_ID_FROM_APIC_ID 0x009a
#define HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_SPACE 0x00af
#define HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_LIST 0x00b0
+#define HVCALL_SIGNAL_EVENT_DIRECT 0x00c0
+#define HVCALL_POST_MESSAGE_DIRECT 0x00c1
#define HVCALL_DISPATCH_VP 0x00c2
+#define HVCALL_GET_GPA_PAGES_ACCESS_STATES 0x00c9
+#define HVCALL_ACQUIRE_SPARSE_SPA_PAGE_HOST_ACCESS 0x00d7
+#define HVCALL_RELEASE_SPARSE_SPA_PAGE_HOST_ACCESS 0x00d8
#define HVCALL_MODIFY_SPARSE_GPA_PAGE_HOST_VISIBILITY 0x00db
#define HVCALL_MAP_VP_STATE_PAGE 0x00e1
#define HVCALL_UNMAP_VP_STATE_PAGE 0x00e2
#define HVCALL_GET_VP_STATE 0x00e3
#define HVCALL_SET_VP_STATE 0x00e4
+#define HVCALL_GET_VP_CPUID_VALUES 0x00f4
#define HVCALL_MMIO_READ 0x0106
#define HVCALL_MMIO_WRITE 0x0107
@@ -775,10 +792,10 @@ struct hv_message_page {
/* Define timer message payload structure. */
struct hv_timer_message_payload {
- __u32 timer_index;
- __u32 reserved;
- __u64 expiration_time; /* When the timer expired */
- __u64 delivery_time; /* When the message was delivered */
+ u32 timer_index;
+ u32 reserved;
+ u64 expiration_time; /* When the timer expired */
+ u64 delivery_time; /* When the message was delivered */
} __packed;
struct hv_x64_segment_register {
@@ -807,6 +824,8 @@ struct hv_x64_table_register {
u64 base;
} __packed;
+#define HV_NORMAL_VTL 0
+
union hv_input_vtl {
u8 as_uint8;
struct {
@@ -1325,6 +1344,49 @@ struct hv_retarget_device_interrupt { /* HV_INPUT_RETARGET_DEVICE_INTERRUPT */
struct hv_device_interrupt_target int_target;
} __packed __aligned(8);
+enum hv_intercept_type {
+#if defined(CONFIG_X86)
+ HV_INTERCEPT_TYPE_X64_IO_PORT = 0x00000000,
+ HV_INTERCEPT_TYPE_X64_MSR = 0x00000001,
+ HV_INTERCEPT_TYPE_X64_CPUID = 0x00000002,
+#endif
+ HV_INTERCEPT_TYPE_EXCEPTION = 0x00000003,
+ /* Used to be HV_INTERCEPT_TYPE_REGISTER */
+ HV_INTERCEPT_TYPE_RESERVED0 = 0x00000004,
+ HV_INTERCEPT_TYPE_MMIO = 0x00000005,
+#if defined(CONFIG_X86)
+ HV_INTERCEPT_TYPE_X64_GLOBAL_CPUID = 0x00000006,
+ HV_INTERCEPT_TYPE_X64_APIC_SMI = 0x00000007,
+#endif
+ HV_INTERCEPT_TYPE_HYPERCALL = 0x00000008,
+#if defined(CONFIG_X86)
+ HV_INTERCEPT_TYPE_X64_APIC_INIT_SIPI = 0x00000009,
+ HV_INTERCEPT_MC_UPDATE_PATCH_LEVEL_MSR_READ = 0x0000000A,
+ HV_INTERCEPT_TYPE_X64_APIC_WRITE = 0x0000000B,
+ HV_INTERCEPT_TYPE_X64_MSR_INDEX = 0x0000000C,
+#endif
+ HV_INTERCEPT_TYPE_MAX,
+ HV_INTERCEPT_TYPE_INVALID = 0xFFFFFFFF,
+};
+
+union hv_intercept_parameters {
+ /* HV_INTERCEPT_PARAMETERS is defined to be an 8-byte field. */
+ u64 as_uint64;
+#if defined(CONFIG_X86)
+ /* HV_INTERCEPT_TYPE_X64_IO_PORT */
+ u16 io_port;
+ /* HV_INTERCEPT_TYPE_X64_CPUID */
+ u32 cpuid_index;
+ /* HV_INTERCEPT_TYPE_X64_APIC_WRITE */
+ u32 apic_write_mask;
+ /* HV_INTERCEPT_TYPE_EXCEPTION */
+ u16 exception_vector;
+ /* HV_INTERCEPT_TYPE_X64_MSR_INDEX */
+ u32 msr_index;
+#endif
+ /* N.B. Other intercept types do not have any parameters. */
+};
+
/* Data structures for HVCALL_MMIO_READ and HVCALL_MMIO_WRITE */
#define HV_HYPERCALL_MMIO_MAX_DATA_LENGTH 64
diff --git a/include/hyperv/hvhdk.h b/include/hyperv/hvhdk.h
index 64407c2a3809..b4067ada02cf 100644
--- a/include/hyperv/hvhdk.h
+++ b/include/hyperv/hvhdk.h
@@ -19,11 +19,24 @@
#define HV_VP_REGISTER_PAGE_VERSION_1 1u
+#define HV_VP_REGISTER_PAGE_MAX_VECTOR_COUNT 7
+
+union hv_vp_register_page_interrupt_vectors {
+ u64 as_uint64;
+ struct {
+ u8 vector_count;
+ u8 vector[HV_VP_REGISTER_PAGE_MAX_VECTOR_COUNT];
+ } __packed;
+};
+
struct hv_vp_register_page {
u16 version;
u8 isvalid;
u8 rsvdz;
u32 dirty;
+
+#if IS_ENABLED(CONFIG_X86)
+
union {
struct {
/* General purpose registers
@@ -95,6 +108,22 @@ struct hv_vp_register_page {
union hv_x64_pending_interruption_register pending_interruption;
union hv_x64_interrupt_state_register interrupt_state;
u64 instruction_emulation_hints;
+ u64 xfem;
+
+ /*
+ * Fields from this point are not included in the register page save chunk.
+ * The reserved field is intended to maintain alignment for unsaved fields.
+ */
+ u8 reserved1[0x100];
+
+ /*
+ * Interrupts injected as part of HvCallDispatchVp.
+ */
+ union hv_vp_register_page_interrupt_vectors interrupt_vectors;
+
+#elif IS_ENABLED(CONFIG_ARM64)
+ /* Not yet supported in ARM */
+#endif
} __packed;
#define HV_PARTITION_PROCESSOR_FEATURES_BANKS 2
@@ -299,10 +328,11 @@ union hv_partition_isolation_properties {
#define HV_PARTITION_ISOLATION_HOST_TYPE_RESERVED 0x2
/* Note: Exo partition is enabled by default */
-#define HV_PARTITION_CREATION_FLAG_EXO_PARTITION BIT(8)
-#define HV_PARTITION_CREATION_FLAG_LAPIC_ENABLED BIT(13)
-#define HV_PARTITION_CREATION_FLAG_INTERCEPT_MESSAGE_PAGE_ENABLED BIT(19)
-#define HV_PARTITION_CREATION_FLAG_X2APIC_CAPABLE BIT(22)
+#define HV_PARTITION_CREATION_FLAG_GPA_SUPER_PAGES_ENABLED BIT(4)
+#define HV_PARTITION_CREATION_FLAG_EXO_PARTITION BIT(8)
+#define HV_PARTITION_CREATION_FLAG_LAPIC_ENABLED BIT(13)
+#define HV_PARTITION_CREATION_FLAG_INTERCEPT_MESSAGE_PAGE_ENABLED BIT(19)
+#define HV_PARTITION_CREATION_FLAG_X2APIC_CAPABLE BIT(22)
struct hv_input_create_partition {
u64 flags;
@@ -349,13 +379,23 @@ struct hv_input_set_partition_property {
enum hv_vp_state_page_type {
HV_VP_STATE_PAGE_REGISTERS = 0,
HV_VP_STATE_PAGE_INTERCEPT_MESSAGE = 1,
+ HV_VP_STATE_PAGE_GHCB = 2,
HV_VP_STATE_PAGE_COUNT
};
struct hv_input_map_vp_state_page {
u64 partition_id;
u32 vp_index;
- u32 type; /* enum hv_vp_state_page_type */
+ u16 type; /* enum hv_vp_state_page_type */
+ union hv_input_vtl input_vtl;
+ union {
+ u8 as_uint8;
+ struct {
+ u8 map_location_provided : 1;
+ u8 reserved : 7;
+ };
+ } flags;
+ u64 requested_map_location;
} __packed;
struct hv_output_map_vp_state_page {
@@ -365,7 +405,14 @@ struct hv_output_map_vp_state_page {
struct hv_input_unmap_vp_state_page {
u64 partition_id;
u32 vp_index;
- u32 type; /* enum hv_vp_state_page_type */
+ u16 type; /* enum hv_vp_state_page_type */
+ union hv_input_vtl input_vtl;
+ u8 reserved0;
+} __packed;
+
+struct hv_x64_apic_eoi_message {
+ u32 vp_index;
+ u32 interrupt_vector;
} __packed;
struct hv_opaque_intercept_message {
@@ -515,6 +562,13 @@ struct hv_synthetic_timers_state {
u64 reserved[5];
} __packed;
+struct hv_async_completion_message_payload {
+ u64 partition_id;
+ u32 status;
+ u32 completion_count;
+ u64 sub_status;
+} __packed;
+
union hv_input_delete_vp {
u64 as_uint64[2];
struct {
@@ -649,6 +703,57 @@ struct hv_input_set_vp_state {
union hv_input_set_vp_state_data data[];
} __packed;
+union hv_x64_vp_execution_state {
+ u16 as_uint16;
+ struct {
+ u16 cpl:2;
+ u16 cr0_pe:1;
+ u16 cr0_am:1;
+ u16 efer_lma:1;
+ u16 debug_active:1;
+ u16 interruption_pending:1;
+ u16 vtl:4;
+ u16 enclave_mode:1;
+ u16 interrupt_shadow:1;
+ u16 virtualization_fault_active:1;
+ u16 reserved:2;
+ } __packed;
+};
+
+struct hv_x64_intercept_message_header {
+ u32 vp_index;
+ u8 instruction_length:4;
+ u8 cr8:4; /* Only set for exo partitions */
+ u8 intercept_access_type;
+ union hv_x64_vp_execution_state execution_state;
+ struct hv_x64_segment_register cs_segment;
+ u64 rip;
+ u64 rflags;
+} __packed;
+
+union hv_x64_memory_access_info {
+ u8 as_uint8;
+ struct {
+ u8 gva_valid:1;
+ u8 gva_gpa_valid:1;
+ u8 hypercall_output_pending:1;
+ u8 tlb_locked_no_overlay:1;
+ u8 reserved:4;
+ } __packed;
+};
+
+struct hv_x64_memory_intercept_message {
+ struct hv_x64_intercept_message_header header;
+ u32 cache_type; /* enum hv_cache_type */
+ u8 instruction_byte_count;
+ union hv_x64_memory_access_info memory_access_info;
+ u8 tpr_priority;
+ u8 reserved1;
+ u64 guest_virtual_address;
+ u64 guest_physical_address;
+ u8 instruction_bytes[16];
+} __packed;
+
/*
* Dispatch state for the VP communicated by the hypervisor to the
* VP-dispatching thread in the root on return from HVCALL_DISPATCH_VP.
@@ -716,6 +821,7 @@ static_assert(sizeof(struct hv_vp_signal_pair_scheduler_message) ==
#define HV_DISPATCH_VP_FLAG_SKIP_VP_SPEC_FLUSH 0x8
#define HV_DISPATCH_VP_FLAG_SKIP_CALLER_SPEC_FLUSH 0x10
#define HV_DISPATCH_VP_FLAG_SKIP_CALLER_USER_SPEC_FLUSH 0x20
+#define HV_DISPATCH_VP_FLAG_SCAN_INTERRUPT_INJECTION 0x40
struct hv_input_dispatch_vp {
u64 partition_id;
@@ -730,4 +836,18 @@ struct hv_output_dispatch_vp {
u32 dispatch_event; /* enum hv_vp_dispatch_event */
} __packed;
+struct hv_input_modify_sparse_spa_page_host_access {
+ u32 host_access : 2;
+ u32 reserved : 30;
+ u32 flags;
+ u64 partition_id;
+ u64 spa_page_list[];
+} __packed;
+
+/* hv_input_modify_sparse_spa_page_host_access flags */
+#define HV_MODIFY_SPA_PAGE_HOST_ACCESS_MAKE_EXCLUSIVE 0x1
+#define HV_MODIFY_SPA_PAGE_HOST_ACCESS_MAKE_SHARED 0x2
+#define HV_MODIFY_SPA_PAGE_HOST_ACCESS_LARGE_PAGE 0x4
+#define HV_MODIFY_SPA_PAGE_HOST_ACCESS_HUGE_PAGE 0x8
+
#endif /* _HV_HVHDK_H */
diff --git a/include/hyperv/hvhdk_mini.h b/include/hyperv/hvhdk_mini.h
index f8a39d3e9ce6..42e7876455b5 100644
--- a/include/hyperv/hvhdk_mini.h
+++ b/include/hyperv/hvhdk_mini.h
@@ -36,6 +36,52 @@ enum hv_scheduler_type {
HV_SCHEDULER_TYPE_MAX
};
+/* HV_STATS_AREA_TYPE */
+enum hv_stats_area_type {
+ HV_STATS_AREA_SELF = 0,
+ HV_STATS_AREA_PARENT = 1,
+ HV_STATS_AREA_INTERNAL = 2,
+ HV_STATS_AREA_COUNT
+};
+
+enum hv_stats_object_type {
+ HV_STATS_OBJECT_HYPERVISOR = 0x00000001,
+ HV_STATS_OBJECT_LOGICAL_PROCESSOR = 0x00000002,
+ HV_STATS_OBJECT_PARTITION = 0x00010001,
+ HV_STATS_OBJECT_VP = 0x00010002
+};
+
+union hv_stats_object_identity {
+ /* hv_stats_hypervisor */
+ struct {
+ u8 reserved[15];
+ u8 stats_area_type;
+ } __packed hv;
+
+ /* hv_stats_logical_processor */
+ struct {
+ u32 lp_index;
+ u8 reserved[11];
+ u8 stats_area_type;
+ } __packed lp;
+
+ /* hv_stats_partition */
+ struct {
+ u64 partition_id;
+ u8 reserved[7];
+ u8 stats_area_type;
+ } __packed partition;
+
+ /* hv_stats_vp */
+ struct {
+ u64 partition_id;
+ u32 vp_index;
+ u16 flags;
+ u8 reserved;
+ u8 stats_area_type;
+ } __packed vp;
+};
+
enum hv_partition_property_code {
/* Privilege properties */
HV_PARTITION_PROPERTY_PRIVILEGE_FLAGS = 0x00010000,
@@ -47,19 +93,45 @@ enum hv_partition_property_code {
/* Compatibility properties */
HV_PARTITION_PROPERTY_PROCESSOR_XSAVE_FEATURES = 0x00060002,
+ HV_PARTITION_PROPERTY_XSAVE_STATES = 0x00060007,
HV_PARTITION_PROPERTY_MAX_XSAVE_DATA_SIZE = 0x00060008,
HV_PARTITION_PROPERTY_PROCESSOR_CLOCK_FREQUENCY = 0x00060009,
};
+enum hv_snp_status {
+ HV_SNP_STATUS_NONE = 0,
+ HV_SNP_STATUS_AVAILABLE = 1,
+ HV_SNP_STATUS_INCOMPATIBLE = 2,
+ HV_SNP_STATUS_PSP_UNAVAILABLE = 3,
+ HV_SNP_STATUS_PSP_INIT_FAILED = 4,
+ HV_SNP_STATUS_PSP_BAD_FW_VERSION = 5,
+ HV_SNP_STATUS_BAD_CONFIGURATION = 6,
+ HV_SNP_STATUS_PSP_FW_UPDATE_IN_PROGRESS = 7,
+ HV_SNP_STATUS_PSP_RB_INIT_FAILED = 8,
+ HV_SNP_STATUS_PSP_PLATFORM_STATUS_FAILED = 9,
+ HV_SNP_STATUS_PSP_INIT_LATE_FAILED = 10,
+};
+
enum hv_system_property {
/* Add more values when needed */
HV_SYSTEM_PROPERTY_SCHEDULER_TYPE = 15,
+ HV_DYNAMIC_PROCESSOR_FEATURE_PROPERTY = 21,
+};
+
+enum hv_dynamic_processor_feature_property {
+ /* Add more values when needed */
+ HV_X64_DYNAMIC_PROCESSOR_FEATURE_MAX_ENCRYPTED_PARTITIONS = 13,
+ HV_X64_DYNAMIC_PROCESSOR_FEATURE_SNP_STATUS = 16,
};
struct hv_input_get_system_property {
u32 property_id; /* enum hv_system_property */
union {
u32 as_uint32;
+#if IS_ENABLED(CONFIG_X86)
+ /* enum hv_dynamic_processor_feature_property */
+ u32 hv_processor_feature;
+#endif
/* More fields to be filled in when needed */
};
} __packed;
@@ -67,9 +139,28 @@ struct hv_input_get_system_property {
struct hv_output_get_system_property {
union {
u32 scheduler_type; /* enum hv_scheduler_type */
+#if IS_ENABLED(CONFIG_X86)
+ u64 hv_processor_feature_value;
+#endif
};
} __packed;
+struct hv_input_map_stats_page {
+ u32 type; /* enum hv_stats_object_type */
+ u32 padding;
+ union hv_stats_object_identity identity;
+} __packed;
+
+struct hv_output_map_stats_page {
+ u64 map_location;
+} __packed;
+
+struct hv_input_unmap_stats_page {
+ u32 type; /* enum hv_stats_object_type */
+ u32 padding;
+ union hv_stats_object_identity identity;
+} __packed;
+
struct hv_proximity_domain_flags {
u32 proximity_preferred : 1;
u32 reserved : 30;
--
2.34.1
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH v6 00/10] Introduce /dev/mshv root partition driver
2025-03-14 19:28 [PATCH v6 00/10] Introduce /dev/mshv root partition driver Nuno Das Neves
` (8 preceding siblings ...)
2025-03-14 19:28 ` [PATCH v6 09/10] hyperv: Add definitions for root partition driver to hv headers Nuno Das Neves
@ 2025-03-17 21:27 ` Wei Liu
[not found] ` <1741980536-3865-11-git-send-email-nunodasneves@linux.microsoft.com>
10 siblings, 0 replies; 20+ messages in thread
From: Wei Liu @ 2025-03-17 21:27 UTC (permalink / raw)
To: Nuno Das Neves
Cc: linux-hyperv, x86, linux-arm-kernel, linux-kernel, linux-arch,
mhklinux, ltykernel, stanislav.kinsburskiy, linux-acpi, eahariha,
jeff.johnson, kys, haiyangz, wei.liu, decui, catalin.marinas,
will, tglx, mingo, bp, dave.hansen, hpa, daniel.lezcano, joro,
robin.murphy, arnd, jinankjain, muminulrussell, skinsburskii,
mrathor, ssengar, apais, gregkh, vkuznets, prapal, anrayabh,
rafael, lenb, corbet
On Fri, Mar 14, 2025 at 12:28:46PM -0700, Nuno Das Neves wrote:
> This series introduces support for creating and running guest virtual
> machines while running on the Microsoft Hypervisor[0] as root partition.
> This is done via an IOCTL interface accessed through /dev/mshv, similar to
> /dev/kvm. Another series introducing this support was previously posted in
> 2021[1], and versions 1-4 of this series were posted in 2023[2].
>
> Patches 1-4 are small refactors and additions to Hyper-V code.
> Patches 5-6 just export some definitions needed by /dev/mshv.
> Patches 7-9 introduce some functionality and definitions in common code, that
> are specific to the driver.
> Patch 10 contains the driver code.
>
> -----------------
> [0] "Hyper-V" is more well-known, but it really refers to the whole stack
> including the hypervisor and other components that run in Windows
> kernel and userspace.
> [1] Previous /dev/mshv patch series (2021) and discussion:
> https://lore.kernel.org/linux-hyperv/1632853875-20261-1-git-send-email-nunodasneves@linux.microsoft.com/
> [2] v4 (2023):
> https://lore.kernel.org/linux-hyperv/1696010501-24584-1-git-send-email-nunodasneves@linux.microsoft.com/
>
> -----------------
> Changes since v5:
> * Rework patch 1:
> 1. Introduce hv_status_printk() logging macros which print the raw HV_STATUS_
> code along with string [Roman Kisel]
> 2. Iterate over an array of data items to get the string and errno for the
> hv_result_to_*() functions. [Michael Kelley]
> 3. Use hv_status_printk() to log errors in hyperv/irqdomain.c and
> hyperv-iommu.c [Easwar Hariharan]
> * Minor cleanup, improvements, and commit wording changes in patches 2, 3, 4, 6
> [Roman Kisel, Easwar Hariharan, Michael Kelley]
> * Fix issues with declaration and lifecycle of hv_synic_eventring_tail in patch
> 7 [Michael Kelley]
> * Improve detail and clarity of commit message in patch 8 [Michael Kelley]
> * Minor cleanups in patch 9 - uapi types -> kernel types, #ifdef CONFIG_X86_64
> -> CONFIG_X86 for consistency, fix HVCALL_* ordering, remove redundant
> __packed, use explicit enum value [Stanislav Kinsburskii, Easwar Hariharan,
> Michael Kelley, Tianyu Lan]
> * Minor fixes and cleanup in patch 10 [Michael Kelley]
> * Add MODULE_DESCRIPTION() to patch 10 [Jeff Johnson]
>
> Changes since v4:
> * Slim down the IOCTL interface significantly, via several means:
> 1. Use generic "passthrough" call MSHV_ROOT_HVCALL to replace many ioctls.
> 2. Use MSHV_* versions of some of the HV_* definitions.
> 3. Move hv headers out of uapi altogether, into include/hyperv/, see:
> https://lore.kernel.org/linux-hyperv/1732577084-2122-1-git-send-email-nunodasneves@linux.microsoft.com/
> * Remove mshv_vtl module altogther, it will be posted in followup series
> * Also remove the parent "mshv" module which didn't serve much purpose
> * Update and refactor parts of the driver code for clarity, extensibility
>
> Changes since v3 (summarized):
> * Clean up the error and debug logging:
> 1. Add a set of macros vp_*() and partition_*() which call the equivalent
> dev_*(), passing the device from the partition struct
> * The new macros also print the partition and vp ids to aid debugging
> and reduce repeated code
> 2. Use dev_*() (mostly via the new macros) instead of pr_*() *almost*
> everywhere - in interrupt context we can't always get the device struct
> 3. Remove pr_*() logging from hv_call.c and mshv_root_hv_call.c
>
> Changes since v2 (summarized):
> * Fix many checkpatch.pl --strict style issues
> * Initialize status in get/set registers hypercall helpers
> * Add missing return on error in get_vp_signaled_count
>
> Changes since v1 (summarized):
> * Clean up formatting, commit messages
>
> Nuno Das Neves (9):
> hyperv: Log hypercall status codes as strings
> arm64/hyperv: Add some missing functions to arm64
> hyperv: Introduce hv_recommend_using_aeoi()
> acpi: numa: Export node_to_pxm()
> Drivers: hv: Export some functions for use by root partition module
> Drivers: hv: Introduce per-cpu event ring tail
> x86: hyperv: Add mshv_handler() irq handler and setup function
> hyperv: Add definitions for root partition driver to hv headers
> Drivers: hv: Introduce mshv_root module to expose /dev/mshv to VMMs
>
> Stanislav Kinsburskii (1):
> x86/mshyperv: Add support for extended Hyper-V features
Series applied to hyperv-next. Thanks.
I had to fix one minor compilation issue in patch 10, but nothing major.
I also folded the following patch to a previous patch that introduced
MSHV_ROOT (not in this series).
diff --git a/drivers/hv/Kconfig b/drivers/hv/Kconfig
index 794e88e9dc6b..3118d5472fab 100644
--- a/drivers/hv/Kconfig
+++ b/drivers/hv/Kconfig
@@ -57,7 +57,7 @@ config HYPERV_BALLOON
config MSHV_ROOT
tristate "Microsoft Hyper-V root partition support"
- depends on HYPERV
+ depends on HYPERV && (X86_64 || ARM64)
depends on !HYPERV_VTL_MODE
# The hypervisor interface operates on 4k pages. Enforcing it here
# simplifies many assumptions in the root partition code.
Wei.
^ permalink raw reply related [flat|nested] 20+ messages in thread
* RE: [PATCH v6 01/10] hyperv: Log hypercall status codes as strings
2025-03-14 19:28 ` [PATCH v6 01/10] hyperv: Log hypercall status codes as strings Nuno Das Neves
@ 2025-03-18 18:01 ` Michael Kelley
2025-03-21 19:12 ` Nuno Das Neves
2025-03-19 4:17 ` Easwar Hariharan
1 sibling, 1 reply; 20+ messages in thread
From: Michael Kelley @ 2025-03-18 18:01 UTC (permalink / raw)
To: Nuno Das Neves, linux-hyperv@vger.kernel.org, x86@kernel.org,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, linux-arch@vger.kernel.org,
ltykernel@gmail.com, stanislav.kinsburskiy@gmail.com,
linux-acpi@vger.kernel.org, eahariha@linux.microsoft.com,
jeff.johnson@oss.qualcomm.com
Cc: kys@microsoft.com, haiyangz@microsoft.com, wei.liu@kernel.org,
decui@microsoft.com, catalin.marinas@arm.com, will@kernel.org,
tglx@linutronix.de, mingo@redhat.com, bp@alien8.de,
dave.hansen@linux.intel.com, hpa@zytor.com,
daniel.lezcano@linaro.org, joro@8bytes.org, robin.murphy@arm.com,
arnd@arndb.de, jinankjain@linux.microsoft.com,
muminulrussell@gmail.com, skinsburskii@linux.microsoft.com,
mrathor@linux.microsoft.com, ssengar@linux.microsoft.com,
apais@linux.microsoft.com, gregkh@linuxfoundation.org,
vkuznets@redhat.com, prapal@linux.microsoft.com,
anrayabh@linux.microsoft.com, rafael@kernel.org, lenb@kernel.org,
corbet@lwn.net
From: Nuno Das Neves <nunodasneves@linux.microsoft.com> Sent: Friday, March 14, 2025 12:29 PM
>
> Introduce hv_status_printk() macros as a convenience to log hypercall
> errors, formatting them with the status code (HV_STATUS_*) as a raw hex
> value and also as a string, which saves some time while debugging.
>
> Create a table of HV_STATUS_ codes with strings and mapped errnos, and
> use it for hv_result_to_string() and hv_result_to_errno().
>
> Use the new hv_status_printk()s in hv_proc.c, hyperv-iommu.c, and
> irqdomain.c hypercalls to aid debugging in the root partition.
>
> Signed-off-by: Nuno Das Neves <nunodasneves@linux.microsoft.com>
> Reviewed-by: Stanislav Kinsburskii <skinsburskii@linux.microsoft.com>
> ---
> arch/x86/hyperv/irqdomain.c | 6 +-
> drivers/hv/hv_common.c | 129 ++++++++++++++++++++++++---------
> drivers/hv/hv_proc.c | 10 +--
> drivers/iommu/hyperv-iommu.c | 4 +-
> include/asm-generic/mshyperv.h | 13 ++++
> 5 files changed, 118 insertions(+), 44 deletions(-)
>
[snip]
> +
> +struct hv_status_info {
> + char *string;
> + int errno;
> + u16 code;
> +};
> +
> +/*
> + * Note on the errno mappings:
> + * A failed hypercall is usually only recoverable (or loggable) near
> + * the call site where the HV_STATUS_* code is known. So the errno
> + * it gets converted to is not too useful further up the stack.
> + * Provide a few mappings that could be useful, and revert to -EIO
> + * as a fallback.
> + */
> +static const struct hv_status_info hv_status_infos[] = {
> +#define _STATUS_INFO(status, errno) { #status, (errno), (status) }
> + _STATUS_INFO(HV_STATUS_SUCCESS, 0),
> + _STATUS_INFO(HV_STATUS_INVALID_HYPERCALL_CODE, -EINVAL),
> + _STATUS_INFO(HV_STATUS_INVALID_HYPERCALL_INPUT, -EINVAL),
> + _STATUS_INFO(HV_STATUS_INVALID_ALIGNMENT, -EIO),
> + _STATUS_INFO(HV_STATUS_INVALID_PARAMETER, -EINVAL),
> + _STATUS_INFO(HV_STATUS_ACCESS_DENIED, -EIO),
> + _STATUS_INFO(HV_STATUS_INVALID_PARTITION_STATE, -EIO),
> + _STATUS_INFO(HV_STATUS_OPERATION_DENIED, -EIO),
> + _STATUS_INFO(HV_STATUS_UNKNOWN_PROPERTY, -EIO),
> + _STATUS_INFO(HV_STATUS_PROPERTY_VALUE_OUT_OF_RANGE, -EIO),
> + _STATUS_INFO(HV_STATUS_INSUFFICIENT_MEMORY, -ENOMEM),
> + _STATUS_INFO(HV_STATUS_INVALID_PARTITION_ID, -EINVAL),
> + _STATUS_INFO(HV_STATUS_INVALID_VP_INDEX, -EINVAL),
> + _STATUS_INFO(HV_STATUS_NOT_FOUND, -EIO),
> + _STATUS_INFO(HV_STATUS_INVALID_PORT_ID, -EINVAL),
> + _STATUS_INFO(HV_STATUS_INVALID_CONNECTION_ID, -EINVAL),
> + _STATUS_INFO(HV_STATUS_INSUFFICIENT_BUFFERS, -EIO),
> + _STATUS_INFO(HV_STATUS_NOT_ACKNOWLEDGED, -EIO),
> + _STATUS_INFO(HV_STATUS_INVALID_VP_STATE, -EIO),
> + _STATUS_INFO(HV_STATUS_NO_RESOURCES, -EIO),
> + _STATUS_INFO(HV_STATUS_PROCESSOR_FEATURE_NOT_SUPPORTED, -EIO),
> + _STATUS_INFO(HV_STATUS_INVALID_LP_INDEX, -EINVAL),
> + _STATUS_INFO(HV_STATUS_INVALID_REGISTER_VALUE, -EINVAL),
> + _STATUS_INFO(HV_STATUS_INVALID_LP_INDEX, -EIO),
> + _STATUS_INFO(HV_STATUS_INVALID_REGISTER_VALUE, -EIO),
> + _STATUS_INFO(HV_STATUS_OPERATION_FAILED, -EIO),
> + _STATUS_INFO(HV_STATUS_TIME_OUT, -EIO),
> + _STATUS_INFO(HV_STATUS_CALL_PENDING, -EIO),
> + _STATUS_INFO(HV_STATUS_VTL_ALREADY_ENABLED, -EIO),
> +#undef _STATUS_INFO
> +};
> +
> +static inline const struct hv_status_info *find_hv_status_info(u64 hv_status)
> +{
> + int i;
> + u16 code = hv_result(hv_status);
> +
> + for (i = 0; i < ARRAY_SIZE(hv_status_infos); ++i) {
> + const struct hv_status_info *info = &hv_status_infos[i];
> +
> + if (info->code == code)
> + return info;
> + }
> +
> + return NULL;
> +}
> +
> +/* Convert a hypercall result into a linux-friendly error code. */
> +int hv_result_to_errno(u64 status)
> +{
> + const struct hv_status_info *info;
> +
> + /* hv_do_hypercall() may return U64_MAX, hypercalls aren't possible */
> + if (unlikely(status == U64_MAX))
> + return -EOPNOTSUPP;
> +
> + info = find_hv_status_info(status);
> + if (info)
> + return info->errno;
> +
> + return -EIO;
> +}
> +EXPORT_SYMBOL_GPL(hv_result_to_errno);
> +
> +const char *hv_result_to_string(u64 status)
> +{
> + const struct hv_status_info *info;
> +
> + if (unlikely(status == U64_MAX))
> + return "Hypercall page missing!";
> +
> + info = find_hv_status_info(status);
> + if (info)
> + return info->string;
> +
> + return "Unknown";
> +}
> +EXPORT_SYMBOL_GPL(hv_result_to_string);
I think the table-driven approach worked out pretty well. But here's a version that
is even more compact, and avoids the duplicate testing for U64_MAX and having
to special case both U64_MAX and not finding a match:
+
+struct hv_status_info {
+ char *string;
+ int errno;
+ int code;
+};
+
+/*
+ * Note on the errno mappings:
+ * A failed hypercall is usually only recoverable (or loggable) near
+ * the call site where the HV_STATUS_* code is known. So the errno
+ * it gets converted to is not too useful further up the stack.
+ * Provide a few mappings that could be useful, and revert to -EIO
+ * as a fallback.
+ */
+static const struct hv_status_info hv_status_infos[] = {
+#define _STATUS_INFO(status, errno) { #status, (errno), (status) }
+ _STATUS_INFO(HV_STATUS_SUCCESS, 0),
+ _STATUS_INFO(HV_STATUS_INVALID_HYPERCALL_CODE, -EINVAL),
+ _STATUS_INFO(HV_STATUS_INVALID_HYPERCALL_INPUT, -EINVAL),
+ _STATUS_INFO(HV_STATUS_INVALID_ALIGNMENT, -EIO),
+ _STATUS_INFO(HV_STATUS_INVALID_PARAMETER, -EINVAL),
+ _STATUS_INFO(HV_STATUS_ACCESS_DENIED, -EIO),
+ _STATUS_INFO(HV_STATUS_INVALID_PARTITION_STATE, -EIO),
+ _STATUS_INFO(HV_STATUS_OPERATION_DENIED, -EIO),
+ _STATUS_INFO(HV_STATUS_UNKNOWN_PROPERTY, -EIO),
+ _STATUS_INFO(HV_STATUS_PROPERTY_VALUE_OUT_OF_RANGE, -EIO),
+ _STATUS_INFO(HV_STATUS_INSUFFICIENT_MEMORY, -ENOMEM),
+ _STATUS_INFO(HV_STATUS_INVALID_PARTITION_ID, -EINVAL),
+ _STATUS_INFO(HV_STATUS_INVALID_VP_INDEX, -EINVAL),
+ _STATUS_INFO(HV_STATUS_NOT_FOUND, -EIO),
+ _STATUS_INFO(HV_STATUS_INVALID_PORT_ID, -EINVAL),
+ _STATUS_INFO(HV_STATUS_INVALID_CONNECTION_ID, -EINVAL),
+ _STATUS_INFO(HV_STATUS_INSUFFICIENT_BUFFERS, -EIO),
+ _STATUS_INFO(HV_STATUS_NOT_ACKNOWLEDGED, -EIO),
+ _STATUS_INFO(HV_STATUS_INVALID_VP_STATE, -EIO),
+ _STATUS_INFO(HV_STATUS_NO_RESOURCES, -EIO),
+ _STATUS_INFO(HV_STATUS_PROCESSOR_FEATURE_NOT_SUPPORTED, -EIO),
+ _STATUS_INFO(HV_STATUS_INVALID_LP_INDEX, -EINVAL),
+ _STATUS_INFO(HV_STATUS_INVALID_REGISTER_VALUE, -EINVAL),
+ _STATUS_INFO(HV_STATUS_INVALID_LP_INDEX, -EIO),
+ _STATUS_INFO(HV_STATUS_INVALID_REGISTER_VALUE, -EIO),
+ _STATUS_INFO(HV_STATUS_OPERATION_FAILED, -EIO),
+ _STATUS_INFO(HV_STATUS_TIME_OUT, -EIO),
+ _STATUS_INFO(HV_STATUS_CALL_PENDING, -EIO),
+ _STATUS_INFO(HV_STATUS_VTL_ALREADY_ENABLED, -EIO),
+ {"Hypercall page missing!", -EOPNOTSUPP, -1}, /* code -1 is "no hypercall page" */
+ {"Unknown", -EIO, -2}, /* code -2 is "Not found" entry; must be last */
+#undef _STATUS_INFO
+};
+
+static inline const struct hv_status_info *find_hv_status_info(u64 hv_status)
+{
+ int i, code;
+ const struct hv_status_info *info;
+
+ /* hv_do_hypercall() may return U64_MAX, hypercalls aren't possible */
+ if (unlikely(hv_status == U64_MAX))
+ code = -1;
+ else
+ code = hv_result(hv_status);
+
+ for (i = 0; i < ARRAY_SIZE(hv_status_infos); ++i) {
+ info = &hv_status_infos[i];
+ if (info->code == code || info->code == -2)
+ break;
+ }
+
+ return info;
+}
+
+/* Convert a hypercall result into a linux-friendly error code. */
+int hv_result_to_errno(u64 status)
+{
+ return find_hv_status_info(status)->errno;
+}
+EXPORT_SYMBOL_GPL(hv_result_to_errno);
+
+const char *hv_result_to_string(u64 status)
+{
+ return find_hv_status_info(status)->string;
+}
+EXPORT_SYMBOL_GPL(hv_result_to_string);
It could be even more compact by exporting find_hv_status_info() and
letting hv_result_to_errno() and hv_result_to_string() be #defines to
find_hv_status_info()->errno and find_hv_status_info()->string,
respectively.
Note that in struct hv_status_info, the "code" field is defined as "int"
instead of "u16" so that it can contain sentinel values -1 and -2 that
won't overlap with HV_STATUS_* values.
Anyway, just a suggestion. The current code works from what I can
see.
Michael
^ permalink raw reply [flat|nested] 20+ messages in thread
* RE: [PATCH v6 10/10] Drivers: hv: Introduce mshv_root module to expose /dev/mshv to VMMs
[not found] ` <1741980536-3865-11-git-send-email-nunodasneves@linux.microsoft.com>
@ 2025-03-18 19:54 ` Michael Kelley
2025-03-18 20:00 ` Wei Liu
0 siblings, 1 reply; 20+ messages in thread
From: Michael Kelley @ 2025-03-18 19:54 UTC (permalink / raw)
To: Nuno Das Neves, linux-hyperv@vger.kernel.org, x86@kernel.org,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, linux-arch@vger.kernel.org,
ltykernel@gmail.com, stanislav.kinsburskiy@gmail.com,
linux-acpi@vger.kernel.org, eahariha@linux.microsoft.com,
jeff.johnson@oss.qualcomm.com
Cc: kys@microsoft.com, haiyangz@microsoft.com, wei.liu@kernel.org,
decui@microsoft.com, catalin.marinas@arm.com, will@kernel.org,
tglx@linutronix.de, mingo@redhat.com, bp@alien8.de,
dave.hansen@linux.intel.com, hpa@zytor.com,
daniel.lezcano@linaro.org, joro@8bytes.org, robin.murphy@arm.com,
arnd@arndb.de, jinankjain@linux.microsoft.com,
muminulrussell@gmail.com, skinsburskii@linux.microsoft.com,
mrathor@linux.microsoft.com, ssengar@linux.microsoft.com,
apais@linux.microsoft.com, gregkh@linuxfoundation.org,
vkuznets@redhat.com, prapal@linux.microsoft.com,
anrayabh@linux.microsoft.com, rafael@kernel.org, lenb@kernel.org,
corbet@lwn.net
From: Nuno Das Neves <nunodasneves@linux.microsoft.com> Sent: Friday, March 14, 2025 12:29 PM
>
> Provide a set of IOCTLs for creating and managing child partitions when
> running as root partition on Hyper-V. The new driver is enabled via
> CONFIG_MSHV_ROOT.
>
[snip]
> +
> +int
> +hv_call_clear_virtual_interrupt(u64 partition_id)
> +{
> + unsigned long flags;
This local variable is now unused and will generate a compile warning.
> + int status;
> +
> + status = hv_do_fast_hypercall8(HVCALL_CLEAR_VIRTUAL_INTERRUPT,
> + partition_id);
> +
> + return hv_result_to_errno(status);
> +}
> +
> +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)
> +{
> + struct hv_input_create_port *input;
> + unsigned long flags;
> + int ret = 0;
> + int status;
> +
> + do {
> + local_irq_save(flags);
> + input = *this_cpu_ptr(hyperv_pcpu_input_arg);
> + memset(input, 0, sizeof(*input));
> +
> + input->port_partition_id = port_partition_id;
> + input->port_id = port_id;
> + input->connection_partition_id = connection_partition_id;
> + input->port_info = *port_info;
> + input->port_vtl = port_vtl;
> + input->min_connection_vtl = min_connection_vtl;
> + input->proximity_domain_info = hv_numa_node_to_pxm_info(node);
> + status = hv_do_hypercall(HVCALL_CREATE_PORT, input, NULL);
> + local_irq_restore(flags);
> + if (hv_result_success(status))
> + break;
> +
> + if (hv_result(status) != HV_STATUS_INSUFFICIENT_MEMORY) {
> + ret = hv_result_to_errno(status);
> + break;
> + }
> + ret = hv_call_deposit_pages(NUMA_NO_NODE, port_partition_id, 1);
> +
> + } while (!ret);
> +
> + return ret;
> +}
> +
> +int
> +hv_call_delete_port(u64 port_partition_id, union hv_port_id port_id)
> +{
> + union hv_input_delete_port input = { 0 };
> + unsigned long flags;
Unused local variable.
> + int status;
> +
> + input.port_partition_id = port_partition_id;
> + input.port_id = port_id;
> + status = hv_do_fast_hypercall16(HVCALL_DELETE_PORT,
> + input.as_uint64[0],
> + input.as_uint64[1]);
> +
> + return hv_result_to_errno(status);
> +}
> +
> +int
> +hv_call_connect_port(u64 port_partition_id, union hv_port_id port_id,
> + u64 connection_partition_id,
> + union hv_connection_id connection_id,
> + struct hv_connection_info *connection_info,
> + u8 connection_vtl, int node)
> +{
> + struct hv_input_connect_port *input;
> + unsigned long flags;
> + int ret = 0, status;
> +
> + do {
> + local_irq_save(flags);
> + input = *this_cpu_ptr(hyperv_pcpu_input_arg);
> + memset(input, 0, sizeof(*input));
> + input->port_partition_id = port_partition_id;
> + input->port_id = port_id;
> + input->connection_partition_id = connection_partition_id;
> + input->connection_id = connection_id;
> + input->connection_info = *connection_info;
> + input->connection_vtl = connection_vtl;
> + input->proximity_domain_info = hv_numa_node_to_pxm_info(node);
> + status = hv_do_hypercall(HVCALL_CONNECT_PORT, input, NULL);
> +
> + local_irq_restore(flags);
> + if (hv_result_success(status))
> + break;
> +
> + if (hv_result(status) != HV_STATUS_INSUFFICIENT_MEMORY) {
> + ret = hv_result_to_errno(status);
> + break;
> + }
> + ret = hv_call_deposit_pages(NUMA_NO_NODE,
> + connection_partition_id, 1);
> + } while (!ret);
> +
> + return ret;
> +}
> +
> +int
> +hv_call_disconnect_port(u64 connection_partition_id,
> + union hv_connection_id connection_id)
> +{
> + union hv_input_disconnect_port input = { 0 };
> + unsigned long flags;
Unused local variable.
> + int status;
> +
> + input.connection_partition_id = connection_partition_id;
> + input.connection_id = connection_id;
> + input.is_doorbell = 1;
> + status = hv_do_fast_hypercall16(HVCALL_DISCONNECT_PORT,
> + input.as_uint64[0],
> + input.as_uint64[1]);
> +
> + return hv_result_to_errno(status);
> +}
> +
> +int
> +hv_call_notify_port_ring_empty(u32 sint_index)
> +{
> + union hv_input_notify_port_ring_empty input = { 0 };
> + unsigned long flags;
Unused.
> + int status;
> +
> + input.sint_index = sint_index;
> + status = hv_do_fast_hypercall8(HVCALL_NOTIFY_PORT_RING_EMPTY,
> + input.as_uint64);
> +
> + return hv_result_to_errno(status);
> +}
> +
> +int hv_call_map_stat_page(enum hv_stats_object_type type,
> + const union hv_stats_object_identity *identity,
> + void **addr)
> +{
> + unsigned long flags;
> + struct hv_input_map_stats_page *input;
> + struct hv_output_map_stats_page *output;
> + u64 status, pfn;
> + int ret;
> +
> + 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));
> + input->type = type;
> + input->identity = *identity;
> +
> + status = hv_do_hypercall(HVCALL_MAP_STATS_PAGE, input, output);
> + pfn = output->map_location;
> +
> + local_irq_restore(flags);
> + if (hv_result(status) != HV_STATUS_INSUFFICIENT_MEMORY) {
> + if (hv_result_success(status))
> + break;
If this "break" is taken, "ret" may be uninitialized and the return value is
stack garbage. This bug was also in v5 and I didn't notice it in my
previous review.
> + return hv_result_to_errno(status);
> + }
> +
> + ret = hv_call_deposit_pages(NUMA_NO_NODE,
> + hv_current_partition_id, 1);
> + if (ret)
> + return ret;
> + } while (!ret);
> +
> + *addr = page_address(pfn_to_page(pfn));
> +
> + return ret;
> +}
> +
> +int hv_call_unmap_stat_page(enum hv_stats_object_type type,
> + const union hv_stats_object_identity *identity)
> +{
> + unsigned long flags;
> + struct hv_input_unmap_stats_page *input;
> + u64 status;
> +
> + local_irq_save(flags);
> + input = *this_cpu_ptr(hyperv_pcpu_input_arg);
> +
> + memset(input, 0, sizeof(*input));
> + input->type = type;
> + input->identity = *identity;
> +
> + status = hv_do_hypercall(HVCALL_UNMAP_STATS_PAGE, input, NULL);
> + local_irq_restore(flags);
> +
> + return hv_result_to_errno(status);
> +}
> +
> +int hv_call_modify_spa_host_access(u64 partition_id, struct page **pages,
> + u64 page_struct_count, u32 host_access,
> + u32 flags, u8 acquire)
> +{
> + struct hv_input_modify_sparse_spa_page_host_access *input_page;
> + u64 status;
> + int done = 0;
> + unsigned long irq_flags, large_shift = 0;
> + u64 page_count = page_struct_count;
> + u16 code = acquire ? HVCALL_ACQUIRE_SPARSE_SPA_PAGE_HOST_ACCESS :
> + HVCALL_RELEASE_SPARSE_SPA_PAGE_HOST_ACCESS;
> +
> + if (page_count == 0)
> + return -EINVAL;
> +
> + if (flags & HV_MODIFY_SPA_PAGE_HOST_ACCESS_LARGE_PAGE) {
> + if (!HV_PAGE_COUNT_2M_ALIGNED(page_count))
> + return -EINVAL;
> + large_shift = HV_HYP_LARGE_PAGE_SHIFT - HV_HYP_PAGE_SHIFT;
> + page_count >>= large_shift;
> + }
> +
> + 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);
> +
> + local_irq_save(irq_flags);
> + input_page = *this_cpu_ptr(hyperv_pcpu_input_arg);
> +
> + memset(input_page, 0, sizeof(*input_page));
> + /* Only set the partition id if you are making the pages
> + * exclusive
> + */
> + if (flags & HV_MODIFY_SPA_PAGE_HOST_ACCESS_MAKE_EXCLUSIVE)
> + input_page->partition_id = partition_id;
> + input_page->flags = flags;
> + input_page->host_access = host_access;
> +
> + for (i = 0; i < rep_count; i++) {
> + u64 index = (done + i) << large_shift;
> +
> + if (index >= page_struct_count)
> + return -EINVAL;
> +
> + input_page->spa_page_list[i] =
> + page_to_pfn(pages[index]);
> + }
> +
> + status = hv_do_rep_hypercall(code, rep_count, 0, input_page,
> + NULL);
> + local_irq_restore(irq_flags);
> +
> + completed = hv_repcomp(status);
> +
> + if (!hv_result_success(status))
> + return hv_result_to_errno(status);
> +
> + done += completed;
> + }
> +
> + return 0;
> +}
Stopping here because that's where I stopped in Part 1 of my v5 review
of this patch.
Michael
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v6 10/10] Drivers: hv: Introduce mshv_root module to expose /dev/mshv to VMMs
2025-03-18 19:54 ` [PATCH v6 10/10] Drivers: hv: Introduce mshv_root module to expose /dev/mshv to VMMs Michael Kelley
@ 2025-03-18 20:00 ` Wei Liu
2025-03-18 20:23 ` Michael Kelley
0 siblings, 1 reply; 20+ messages in thread
From: Wei Liu @ 2025-03-18 20:00 UTC (permalink / raw)
To: Michael Kelley
Cc: Nuno Das Neves, linux-hyperv@vger.kernel.org, x86@kernel.org,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, linux-arch@vger.kernel.org,
ltykernel@gmail.com, stanislav.kinsburskiy@gmail.com,
linux-acpi@vger.kernel.org, eahariha@linux.microsoft.com,
jeff.johnson@oss.qualcomm.com, kys@microsoft.com,
haiyangz@microsoft.com, wei.liu@kernel.org, decui@microsoft.com,
catalin.marinas@arm.com, will@kernel.org, tglx@linutronix.de,
mingo@redhat.com, bp@alien8.de, dave.hansen@linux.intel.com,
hpa@zytor.com, daniel.lezcano@linaro.org, joro@8bytes.org,
robin.murphy@arm.com, arnd@arndb.de,
jinankjain@linux.microsoft.com, muminulrussell@gmail.com,
skinsburskii@linux.microsoft.com, mrathor@linux.microsoft.com,
ssengar@linux.microsoft.com, apais@linux.microsoft.com,
gregkh@linuxfoundation.org, vkuznets@redhat.com,
prapal@linux.microsoft.com, anrayabh@linux.microsoft.com,
rafael@kernel.org, lenb@kernel.org, corbet@lwn.net
On Tue, Mar 18, 2025 at 07:54:49PM +0000, Michael Kelley wrote:
> From: Nuno Das Neves <nunodasneves@linux.microsoft.com> Sent: Friday, March 14, 2025 12:29 PM
> >
> > Provide a set of IOCTLs for creating and managing child partitions when
> > running as root partition on Hyper-V. The new driver is enabled via
> > CONFIG_MSHV_ROOT.
> >
>
> [snip]
>
> > +
> > +int
> > +hv_call_clear_virtual_interrupt(u64 partition_id)
> > +{
> > + unsigned long flags;
>
> This local variable is now unused and will generate a compile warning.
FWIW I noticed the same thing too and fixed them all while I committed
the patch.
Thanks,
Wei.
^ permalink raw reply [flat|nested] 20+ messages in thread
* RE: [PATCH v6 10/10] Drivers: hv: Introduce mshv_root module to expose /dev/mshv to VMMs
2025-03-18 20:00 ` Wei Liu
@ 2025-03-18 20:23 ` Michael Kelley
0 siblings, 0 replies; 20+ messages in thread
From: Michael Kelley @ 2025-03-18 20:23 UTC (permalink / raw)
To: Wei Liu
Cc: Nuno Das Neves, linux-hyperv@vger.kernel.org, x86@kernel.org,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, linux-arch@vger.kernel.org,
ltykernel@gmail.com, stanislav.kinsburskiy@gmail.com,
linux-acpi@vger.kernel.org, eahariha@linux.microsoft.com,
jeff.johnson@oss.qualcomm.com, kys@microsoft.com,
haiyangz@microsoft.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,
hpa@zytor.com, daniel.lezcano@linaro.org, joro@8bytes.org,
robin.murphy@arm.com, arnd@arndb.de,
jinankjain@linux.microsoft.com, muminulrussell@gmail.com,
skinsburskii@linux.microsoft.com, mrathor@linux.microsoft.com,
ssengar@linux.microsoft.com, apais@linux.microsoft.com,
gregkh@linuxfoundation.org, vkuznets@redhat.com,
prapal@linux.microsoft.com, anrayabh@linux.microsoft.com,
rafael@kernel.org, lenb@kernel.org, corbet@lwn.net
From: Wei Liu <wei.liu@kernel.org> Sent: Tuesday, March 18, 2025 1:00 PM
>
> On Tue, Mar 18, 2025 at 07:54:49PM +0000, Michael Kelley wrote:
> > From: Nuno Das Neves <nunodasneves@linux.microsoft.com> Sent: Friday, March 14,
> 2025 12:29 PM
> > >
> > > Provide a set of IOCTLs for creating and managing child partitions when
> > > running as root partition on Hyper-V. The new driver is enabled via
> > > CONFIG_MSHV_ROOT.
> > >
> >
> > [snip]
> >
> > > +
> > > +int
> > > +hv_call_clear_virtual_interrupt(u64 partition_id)
> > > +{
> > > + unsigned long flags;
> >
> > This local variable is now unused and will generate a compile warning.
>
> FWIW I noticed the same thing too and fixed them all while I committed
> the patch.
>
Ah, good. That just leaves the uninitialized "ret" in hv_call_map_stat_page().
Michael
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v6 09/10] hyperv: Add definitions for root partition driver to hv headers
2025-03-14 19:28 ` [PATCH v6 09/10] hyperv: Add definitions for root partition driver to hv headers Nuno Das Neves
@ 2025-03-19 4:04 ` Easwar Hariharan
0 siblings, 0 replies; 20+ messages in thread
From: Easwar Hariharan @ 2025-03-19 4:04 UTC (permalink / raw)
To: Nuno Das Neves
Cc: linux-hyperv, x86, linux-arm-kernel, linux-kernel, linux-arch,
mhklinux, ltykernel, stanislav.kinsburskiy, linux-acpi,
jeff.johnson, eahariha, kys, haiyangz, wei.liu, decui,
catalin.marinas, will, tglx, mingo, bp, dave.hansen, hpa,
daniel.lezcano, joro, robin.murphy, arnd, jinankjain,
muminulrussell, skinsburskii, mrathor, ssengar, apais, gregkh,
vkuznets, prapal, anrayabh, rafael, lenb, corbet
On 3/14/2025 12:28 PM, Nuno Das Neves wrote:
> A few additional definitions are required for the mshv driver code
> (to follow). Introduce those here and clean up a little bit while
> at it.
>
> Signed-off-by: Nuno Das Neves <nunodasneves@linux.microsoft.com>
> Reviewed-by: Roman Kisel <romank@linux.microsoft.com>
> Reviewed-by: Stanislav Kinsburskii <skinsburskii@linux.microsoft.com>
> Reviewed-by: Tianyu Lan <tiala@microsoft.com>
> ---
> include/hyperv/hvgdk_mini.h | 72 ++++++++++++++++++--
> include/hyperv/hvhdk.h | 132 ++++++++++++++++++++++++++++++++++--
> include/hyperv/hvhdk_mini.h | 91 +++++++++++++++++++++++++
> 3 files changed, 284 insertions(+), 11 deletions(-)
Looks good to me.
Reviewed-by: Easwar Hariharan <eahariha@linux.microsoft.com>
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v6 03/10] arm64/hyperv: Add some missing functions to arm64
2025-03-14 19:28 ` [PATCH v6 03/10] arm64/hyperv: Add some missing functions to arm64 Nuno Das Neves
@ 2025-03-19 4:08 ` Easwar Hariharan
0 siblings, 0 replies; 20+ messages in thread
From: Easwar Hariharan @ 2025-03-19 4:08 UTC (permalink / raw)
To: Nuno Das Neves
Cc: linux-hyperv, x86, linux-arm-kernel, linux-kernel, linux-arch,
mhklinux, ltykernel, stanislav.kinsburskiy, linux-acpi,
jeff.johnson, eahariha, kys, haiyangz, wei.liu, decui,
catalin.marinas, will, tglx, mingo, bp, dave.hansen, hpa,
daniel.lezcano, joro, robin.murphy, arnd, jinankjain,
muminulrussell, skinsburskii, mrathor, ssengar, apais, gregkh,
vkuznets, prapal, anrayabh, rafael, lenb, corbet
On 3/14/2025 12:28 PM, Nuno Das Neves wrote:
> These non-nested msr and fast hypercall functions are present in x86,
> but they must be available in both architectures for the root partition
> driver code.
>
> While at it, remove the redundant 'extern' keywords from the
> hv_do_hypercall() variants in asm-generic/mshyperv.h.
>
> Signed-off-by: Nuno Das Neves <nunodasneves@linux.microsoft.com>
> Reviewed-by: Stanislav Kinsburskii <skinsburskii@linux.microsoft.com>
> Reviewed-by: Roman Kisel <romank@linux.microsoft.com>
> ---
> arch/arm64/hyperv/hv_core.c | 17 +++++++++++++++++
> arch/arm64/include/asm/mshyperv.h | 13 +++++++++++++
> include/asm-generic/mshyperv.h | 6 ++++--
> 3 files changed, 34 insertions(+), 2 deletions(-)
>
Looks good to me.
Reviewed-by: Easwar Hariharan <eahariha@linux.microsoft.com>
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v6 01/10] hyperv: Log hypercall status codes as strings
2025-03-14 19:28 ` [PATCH v6 01/10] hyperv: Log hypercall status codes as strings Nuno Das Neves
2025-03-18 18:01 ` Michael Kelley
@ 2025-03-19 4:17 ` Easwar Hariharan
1 sibling, 0 replies; 20+ messages in thread
From: Easwar Hariharan @ 2025-03-19 4:17 UTC (permalink / raw)
To: Nuno Das Neves
Cc: linux-hyperv, x86, linux-arm-kernel, linux-kernel, linux-arch,
mhklinux, ltykernel, stanislav.kinsburskiy, linux-acpi,
jeff.johnson, eahariha, kys, haiyangz, wei.liu, decui,
catalin.marinas, will, tglx, mingo, bp, dave.hansen, hpa,
daniel.lezcano, joro, robin.murphy, arnd, jinankjain,
muminulrussell, skinsburskii, mrathor, ssengar, apais, gregkh,
vkuznets, prapal, anrayabh, rafael, lenb, corbet
On 3/14/2025 12:28 PM, Nuno Das Neves wrote:
> Introduce hv_status_printk() macros as a convenience to log hypercall
> errors, formatting them with the status code (HV_STATUS_*) as a raw hex
> value and also as a string, which saves some time while debugging.
>
> Create a table of HV_STATUS_ codes with strings and mapped errnos, and
> use it for hv_result_to_string() and hv_result_to_errno().
>
> Use the new hv_status_printk()s in hv_proc.c, hyperv-iommu.c, and
> irqdomain.c hypercalls to aid debugging in the root partition.
>
> Signed-off-by: Nuno Das Neves <nunodasneves@linux.microsoft.com>
> Reviewed-by: Stanislav Kinsburskii <skinsburskii@linux.microsoft.com>
> ---
> arch/x86/hyperv/irqdomain.c | 6 +-
> drivers/hv/hv_common.c | 129 ++++++++++++++++++++++++---------
> drivers/hv/hv_proc.c | 10 +--
> drivers/iommu/hyperv-iommu.c | 4 +-
> include/asm-generic/mshyperv.h | 13 ++++
> 5 files changed, 118 insertions(+), 44 deletions(-)
>
Looks good to me.
Reviewed-by: Easwar Hariharan <eahariha@linux.microsoft.com>
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v6 01/10] hyperv: Log hypercall status codes as strings
2025-03-18 18:01 ` Michael Kelley
@ 2025-03-21 19:12 ` Nuno Das Neves
2025-03-25 18:02 ` Michael Kelley
0 siblings, 1 reply; 20+ messages in thread
From: Nuno Das Neves @ 2025-03-21 19:12 UTC (permalink / raw)
To: Michael Kelley, linux-hyperv@vger.kernel.org, x86@kernel.org,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, linux-arch@vger.kernel.org,
ltykernel@gmail.com, stanislav.kinsburskiy@gmail.com,
linux-acpi@vger.kernel.org, eahariha@linux.microsoft.com,
jeff.johnson@oss.qualcomm.com
Cc: kys@microsoft.com, haiyangz@microsoft.com, wei.liu@kernel.org,
decui@microsoft.com, catalin.marinas@arm.com, will@kernel.org,
tglx@linutronix.de, mingo@redhat.com, bp@alien8.de,
dave.hansen@linux.intel.com, hpa@zytor.com,
daniel.lezcano@linaro.org, joro@8bytes.org, robin.murphy@arm.com,
arnd@arndb.de, jinankjain@linux.microsoft.com,
muminulrussell@gmail.com, skinsburskii@linux.microsoft.com,
mrathor@linux.microsoft.com, ssengar@linux.microsoft.com,
apais@linux.microsoft.com, gregkh@linuxfoundation.org,
vkuznets@redhat.com, prapal@linux.microsoft.com,
anrayabh@linux.microsoft.com, rafael@kernel.org, lenb@kernel.org,
corbet@lwn.net
On 3/18/2025 11:01 AM, Michael Kelley wrote:
> From: Nuno Das Neves <nunodasneves@linux.microsoft.com> Sent: Friday, March 14, 2025 12:29 PM
>>
>> Introduce hv_status_printk() macros as a convenience to log hypercall
>> errors, formatting them with the status code (HV_STATUS_*) as a raw hex
>> value and also as a string, which saves some time while debugging.
>>
>> Create a table of HV_STATUS_ codes with strings and mapped errnos, and
>> use it for hv_result_to_string() and hv_result_to_errno().
>>
>> Use the new hv_status_printk()s in hv_proc.c, hyperv-iommu.c, and
>> irqdomain.c hypercalls to aid debugging in the root partition.
>>
>> Signed-off-by: Nuno Das Neves <nunodasneves@linux.microsoft.com>
>> Reviewed-by: Stanislav Kinsburskii <skinsburskii@linux.microsoft.com>
>> ---
>> arch/x86/hyperv/irqdomain.c | 6 +-
>> drivers/hv/hv_common.c | 129 ++++++++++++++++++++++++---------
>> drivers/hv/hv_proc.c | 10 +--
>> drivers/iommu/hyperv-iommu.c | 4 +-
>> include/asm-generic/mshyperv.h | 13 ++++
>> 5 files changed, 118 insertions(+), 44 deletions(-)
>>
>
> [snip]
>
>> +
>> +struct hv_status_info {
>> + char *string;
>> + int errno;
>> + u16 code;
>> +};
>> +
>> +/*
>> + * Note on the errno mappings:
>> + * A failed hypercall is usually only recoverable (or loggable) near
>> + * the call site where the HV_STATUS_* code is known. So the errno
>> + * it gets converted to is not too useful further up the stack.
>> + * Provide a few mappings that could be useful, and revert to -EIO
>> + * as a fallback.
>> + */
>> +static const struct hv_status_info hv_status_infos[] = {
>> +#define _STATUS_INFO(status, errno) { #status, (errno), (status) }
>> + _STATUS_INFO(HV_STATUS_SUCCESS, 0),
>> + _STATUS_INFO(HV_STATUS_INVALID_HYPERCALL_CODE, -EINVAL),
>> + _STATUS_INFO(HV_STATUS_INVALID_HYPERCALL_INPUT, -EINVAL),
>> + _STATUS_INFO(HV_STATUS_INVALID_ALIGNMENT, -EIO),
>> + _STATUS_INFO(HV_STATUS_INVALID_PARAMETER, -EINVAL),
>> + _STATUS_INFO(HV_STATUS_ACCESS_DENIED, -EIO),
>> + _STATUS_INFO(HV_STATUS_INVALID_PARTITION_STATE, -EIO),
>> + _STATUS_INFO(HV_STATUS_OPERATION_DENIED, -EIO),
>> + _STATUS_INFO(HV_STATUS_UNKNOWN_PROPERTY, -EIO),
>> + _STATUS_INFO(HV_STATUS_PROPERTY_VALUE_OUT_OF_RANGE, -EIO),
>> + _STATUS_INFO(HV_STATUS_INSUFFICIENT_MEMORY, -ENOMEM),
>> + _STATUS_INFO(HV_STATUS_INVALID_PARTITION_ID, -EINVAL),
>> + _STATUS_INFO(HV_STATUS_INVALID_VP_INDEX, -EINVAL),
>> + _STATUS_INFO(HV_STATUS_NOT_FOUND, -EIO),
>> + _STATUS_INFO(HV_STATUS_INVALID_PORT_ID, -EINVAL),
>> + _STATUS_INFO(HV_STATUS_INVALID_CONNECTION_ID, -EINVAL),
>> + _STATUS_INFO(HV_STATUS_INSUFFICIENT_BUFFERS, -EIO),
>> + _STATUS_INFO(HV_STATUS_NOT_ACKNOWLEDGED, -EIO),
>> + _STATUS_INFO(HV_STATUS_INVALID_VP_STATE, -EIO),
>> + _STATUS_INFO(HV_STATUS_NO_RESOURCES, -EIO),
>> + _STATUS_INFO(HV_STATUS_PROCESSOR_FEATURE_NOT_SUPPORTED, -EIO),
>> + _STATUS_INFO(HV_STATUS_INVALID_LP_INDEX, -EINVAL),
>> + _STATUS_INFO(HV_STATUS_INVALID_REGISTER_VALUE, -EINVAL),
>> + _STATUS_INFO(HV_STATUS_INVALID_LP_INDEX, -EIO),
>> + _STATUS_INFO(HV_STATUS_INVALID_REGISTER_VALUE, -EIO),
>> + _STATUS_INFO(HV_STATUS_OPERATION_FAILED, -EIO),
>> + _STATUS_INFO(HV_STATUS_TIME_OUT, -EIO),
>> + _STATUS_INFO(HV_STATUS_CALL_PENDING, -EIO),
>> + _STATUS_INFO(HV_STATUS_VTL_ALREADY_ENABLED, -EIO),
>> +#undef _STATUS_INFO
>> +};
>> +
>> +static inline const struct hv_status_info *find_hv_status_info(u64 hv_status)
>> +{
>> + int i;
>> + u16 code = hv_result(hv_status);
>> +
>> + for (i = 0; i < ARRAY_SIZE(hv_status_infos); ++i) {
>> + const struct hv_status_info *info = &hv_status_infos[i];
>> +
>> + if (info->code == code)
>> + return info;
>> + }
>> +
>> + return NULL;
>> +}
>> +
>> +/* Convert a hypercall result into a linux-friendly error code. */
>> +int hv_result_to_errno(u64 status)
>> +{
>> + const struct hv_status_info *info;
>> +
>> + /* hv_do_hypercall() may return U64_MAX, hypercalls aren't possible */
>> + if (unlikely(status == U64_MAX))
>> + return -EOPNOTSUPP;
>> +
>> + info = find_hv_status_info(status);
>> + if (info)
>> + return info->errno;
>> +
>> + return -EIO;
>> +}
>> +EXPORT_SYMBOL_GPL(hv_result_to_errno);
>> +
>> +const char *hv_result_to_string(u64 status)
>> +{
>> + const struct hv_status_info *info;
>> +
>> + if (unlikely(status == U64_MAX))
>> + return "Hypercall page missing!";
>> +
>> + info = find_hv_status_info(status);
>> + if (info)
>> + return info->string;
>> +
>> + return "Unknown";
>> +}
>> +EXPORT_SYMBOL_GPL(hv_result_to_string);
>
> I think the table-driven approach worked out pretty well. But here's a version that
> is even more compact, and avoids the duplicate testing for U64_MAX and having
> to special case both U64_MAX and not finding a match:
>
> +
> +struct hv_status_info {
> + char *string;
> + int errno;
> + int code;
> +};
> +
> +/*
> + * Note on the errno mappings:
> + * A failed hypercall is usually only recoverable (or loggable) near
> + * the call site where the HV_STATUS_* code is known. So the errno
> + * it gets converted to is not too useful further up the stack.
> + * Provide a few mappings that could be useful, and revert to -EIO
> + * as a fallback.
> + */
> +static const struct hv_status_info hv_status_infos[] = {
> +#define _STATUS_INFO(status, errno) { #status, (errno), (status) }
> + _STATUS_INFO(HV_STATUS_SUCCESS, 0),
> + _STATUS_INFO(HV_STATUS_INVALID_HYPERCALL_CODE, -EINVAL),
> + _STATUS_INFO(HV_STATUS_INVALID_HYPERCALL_INPUT, -EINVAL),
> + _STATUS_INFO(HV_STATUS_INVALID_ALIGNMENT, -EIO),
> + _STATUS_INFO(HV_STATUS_INVALID_PARAMETER, -EINVAL),
> + _STATUS_INFO(HV_STATUS_ACCESS_DENIED, -EIO),
> + _STATUS_INFO(HV_STATUS_INVALID_PARTITION_STATE, -EIO),
> + _STATUS_INFO(HV_STATUS_OPERATION_DENIED, -EIO),
> + _STATUS_INFO(HV_STATUS_UNKNOWN_PROPERTY, -EIO),
> + _STATUS_INFO(HV_STATUS_PROPERTY_VALUE_OUT_OF_RANGE, -EIO),
> + _STATUS_INFO(HV_STATUS_INSUFFICIENT_MEMORY, -ENOMEM),
> + _STATUS_INFO(HV_STATUS_INVALID_PARTITION_ID, -EINVAL),
> + _STATUS_INFO(HV_STATUS_INVALID_VP_INDEX, -EINVAL),
> + _STATUS_INFO(HV_STATUS_NOT_FOUND, -EIO),
> + _STATUS_INFO(HV_STATUS_INVALID_PORT_ID, -EINVAL),
> + _STATUS_INFO(HV_STATUS_INVALID_CONNECTION_ID, -EINVAL),
> + _STATUS_INFO(HV_STATUS_INSUFFICIENT_BUFFERS, -EIO),
> + _STATUS_INFO(HV_STATUS_NOT_ACKNOWLEDGED, -EIO),
> + _STATUS_INFO(HV_STATUS_INVALID_VP_STATE, -EIO),
> + _STATUS_INFO(HV_STATUS_NO_RESOURCES, -EIO),
> + _STATUS_INFO(HV_STATUS_PROCESSOR_FEATURE_NOT_SUPPORTED, -EIO),
> + _STATUS_INFO(HV_STATUS_INVALID_LP_INDEX, -EINVAL),
> + _STATUS_INFO(HV_STATUS_INVALID_REGISTER_VALUE, -EINVAL),
> + _STATUS_INFO(HV_STATUS_INVALID_LP_INDEX, -EIO),
> + _STATUS_INFO(HV_STATUS_INVALID_REGISTER_VALUE, -EIO),
> + _STATUS_INFO(HV_STATUS_OPERATION_FAILED, -EIO),
> + _STATUS_INFO(HV_STATUS_TIME_OUT, -EIO),
> + _STATUS_INFO(HV_STATUS_CALL_PENDING, -EIO),
> + _STATUS_INFO(HV_STATUS_VTL_ALREADY_ENABLED, -EIO),
> + {"Hypercall page missing!", -EOPNOTSUPP, -1}, /* code -1 is "no hypercall page" */
> + {"Unknown", -EIO, -2}, /* code -2 is "Not found" entry; must be last */
> +#undef _STATUS_INFO
> +};
> +
> +static inline const struct hv_status_info *find_hv_status_info(u64 hv_status)
> +{
> + int i, code;
> + const struct hv_status_info *info;
> +
> + /* hv_do_hypercall() may return U64_MAX, hypercalls aren't possible */
> + if (unlikely(hv_status == U64_MAX))
> + code = -1;
> + else
> + code = hv_result(hv_status);
> +
> + for (i = 0; i < ARRAY_SIZE(hv_status_infos); ++i) {
> + info = &hv_status_infos[i];
> + if (info->code == code || info->code == -2)
> + break;
> + }
> +
> + return info;
> +}
> +
> +/* Convert a hypercall result into a linux-friendly error code. */
> +int hv_result_to_errno(u64 status)
> +{
> + return find_hv_status_info(status)->errno;
> +}
> +EXPORT_SYMBOL_GPL(hv_result_to_errno);
> +
> +const char *hv_result_to_string(u64 status)
> +{
> + return find_hv_status_info(status)->string;
> +}
> +EXPORT_SYMBOL_GPL(hv_result_to_string);
>
> It could be even more compact by exporting find_hv_status_info() and
> letting hv_result_to_errno() and hv_result_to_string() be #defines to
> find_hv_status_info()->errno and find_hv_status_info()->string,
> respectively.
>
> Note that in struct hv_status_info, the "code" field is defined as "int"
> instead of "u16" so that it can contain sentinel values -1 and -2 that
> won't overlap with HV_STATUS_* values.
>
Played around with this some more.
I like your idea of making it more compact by dealing with U64_MAX and
unknown in find_hv_status_info(), however I'm not as keen on putting
these cases in the array and iterating over the whole array when they
could just be static constants or inline struct initializers. See below.
I also like the idea of making hv_result_to_*() functions into simple
macros and exporting find_hv_status_info(). However, if it gets used
elsewhere it makes more sense if the returned hv_status_info for the
"Unknown" case contains the actual status code instead of replacing
that information with -2, so then I'd want to return it by value
instead of pointer:
+static const struct hv_status_info hv_status_infos[] = {
+#define _STATUS_INFO(status, errno) { #status, (status), (errno) }
+ _STATUS_INFO(HV_STATUS_SUCCESS, 0),
<snip>
+ _STATUS_INFO(HV_STATUS_VTL_ALREADY_ENABLED, -EIO),
+#undef _STATUS_INFO
+};
+
+struct hv_status_info hv_get_status_info(u64 hv_status)
+{
+ int i;
+ const struct hv_status_info *info;
+ u16 code = hv_result(hv_status);
+ struct hv_status_info ret = {"Unknown", code, -EIO};
+
+ if (hv_status == U64_MAX)
+ ret = (struct hv_status_info){"Hypercall page missing!", -1,
+ -EOPNOTSUPP};
+ else
+ for (i = 0; i < ARRAY_SIZE(hv_status_infos); ++i) {
+ info = &hv_status_infos[i];
+ if (info->code == code) {
+ ret = *info;
+ break;
+ }
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(hv_get_status_info);
and in mshyperv.h:
+#define hv_result_to_string(hv_status) hv_get_status_info(hv_status).string
+#define hv_result_to_errno(hv_status) hv_get_status_info(hv_status).errno
+
+struct hv_status_info {
+ char *string;
+ int code;
+ int errno;
+};
+
+struct hv_status_info hv_get_status_info(u64 hv_status);
Note also I switched the order of code and errno in hv_status_info,
mainly because I think the struct initializers for "Unknown" and
"Hypercall page missing!" are more readable with that order:
{string, code, errno}
Do you see any problems with the above?
> Anyway, just a suggestion. The current code works from what I can
> see.
Thanks, it's not a bad idea at all to make it as compact and readable
as possible on the first try, but not a big loss either way.
Thanks
Nuno
>
> Michael
^ permalink raw reply [flat|nested] 20+ messages in thread
* RE: [PATCH v6 01/10] hyperv: Log hypercall status codes as strings
2025-03-21 19:12 ` Nuno Das Neves
@ 2025-03-25 18:02 ` Michael Kelley
0 siblings, 0 replies; 20+ messages in thread
From: Michael Kelley @ 2025-03-25 18:02 UTC (permalink / raw)
To: Nuno Das Neves, linux-hyperv@vger.kernel.org, x86@kernel.org,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, linux-arch@vger.kernel.org,
ltykernel@gmail.com, stanislav.kinsburskiy@gmail.com,
linux-acpi@vger.kernel.org, eahariha@linux.microsoft.com,
jeff.johnson@oss.qualcomm.com
Cc: kys@microsoft.com, haiyangz@microsoft.com, wei.liu@kernel.org,
decui@microsoft.com, catalin.marinas@arm.com, will@kernel.org,
tglx@linutronix.de, mingo@redhat.com, bp@alien8.de,
dave.hansen@linux.intel.com, hpa@zytor.com,
daniel.lezcano@linaro.org, joro@8bytes.org, robin.murphy@arm.com,
arnd@arndb.de, jinankjain@linux.microsoft.com,
muminulrussell@gmail.com, skinsburskii@linux.microsoft.com,
mrathor@linux.microsoft.com, ssengar@linux.microsoft.com,
apais@linux.microsoft.com, gregkh@linuxfoundation.org,
vkuznets@redhat.com, prapal@linux.microsoft.com,
anrayabh@linux.microsoft.com, rafael@kernel.org, lenb@kernel.org,
corbet@lwn.net
From: Nuno Das Neves <nunodasneves@linux.microsoft.com> Sent: Friday, March 21, 2025 12:13 PM
>
> On 3/18/2025 11:01 AM, Michael Kelley wrote:
> > From: Nuno Das Neves <nunodasneves@linux.microsoft.com> Sent: Friday, March 14, 2025 12:29 PM
> >>
> >> Introduce hv_status_printk() macros as a convenience to log hypercall
> >> errors, formatting them with the status code (HV_STATUS_*) as a raw hex
> >> value and also as a string, which saves some time while debugging.
> >>
> >> Create a table of HV_STATUS_ codes with strings and mapped errnos, and
> >> use it for hv_result_to_string() and hv_result_to_errno().
> >>
> >> Use the new hv_status_printk()s in hv_proc.c, hyperv-iommu.c, and
> >> irqdomain.c hypercalls to aid debugging in the root partition.
> >>
> >> Signed-off-by: Nuno Das Neves <nunodasneves@linux.microsoft.com>
> >> Reviewed-by: Stanislav Kinsburskii <skinsburskii@linux.microsoft.com>
> >> ---
> >> arch/x86/hyperv/irqdomain.c | 6 +-
> >> drivers/hv/hv_common.c | 129 ++++++++++++++++++++++++---------
> >> drivers/hv/hv_proc.c | 10 +--
> >> drivers/iommu/hyperv-iommu.c | 4 +-
> >> include/asm-generic/mshyperv.h | 13 ++++
> >> 5 files changed, 118 insertions(+), 44 deletions(-)
> >>
> >
> > [snip]
> >
> >> +
> >> +struct hv_status_info {
> >> + char *string;
> >> + int errno;
> >> + u16 code;
> >> +};
> >> +
> >> +/*
> >> + * Note on the errno mappings:
> >> + * A failed hypercall is usually only recoverable (or loggable) near
> >> + * the call site where the HV_STATUS_* code is known. So the errno
> >> + * it gets converted to is not too useful further up the stack.
> >> + * Provide a few mappings that could be useful, and revert to -EIO
> >> + * as a fallback.
> >> + */
> >> +static const struct hv_status_info hv_status_infos[] = {
> >> +#define _STATUS_INFO(status, errno) { #status, (errno), (status) }
> >> + _STATUS_INFO(HV_STATUS_SUCCESS, 0),
> >> + _STATUS_INFO(HV_STATUS_INVALID_HYPERCALL_CODE, -EINVAL),
> >> + _STATUS_INFO(HV_STATUS_INVALID_HYPERCALL_INPUT, -EINVAL),
> >> + _STATUS_INFO(HV_STATUS_INVALID_ALIGNMENT, -EIO),
> >> + _STATUS_INFO(HV_STATUS_INVALID_PARAMETER, -EINVAL),
> >> + _STATUS_INFO(HV_STATUS_ACCESS_DENIED, -EIO),
> >> + _STATUS_INFO(HV_STATUS_INVALID_PARTITION_STATE, -EIO),
> >> + _STATUS_INFO(HV_STATUS_OPERATION_DENIED, -EIO),
> >> + _STATUS_INFO(HV_STATUS_UNKNOWN_PROPERTY, -EIO),
> >> + _STATUS_INFO(HV_STATUS_PROPERTY_VALUE_OUT_OF_RANGE, -EIO),
> >> + _STATUS_INFO(HV_STATUS_INSUFFICIENT_MEMORY, -ENOMEM),
> >> + _STATUS_INFO(HV_STATUS_INVALID_PARTITION_ID, -EINVAL),
> >> + _STATUS_INFO(HV_STATUS_INVALID_VP_INDEX, -EINVAL),
> >> + _STATUS_INFO(HV_STATUS_NOT_FOUND, -EIO),
> >> + _STATUS_INFO(HV_STATUS_INVALID_PORT_ID, -EINVAL),
> >> + _STATUS_INFO(HV_STATUS_INVALID_CONNECTION_ID, -EINVAL),
> >> + _STATUS_INFO(HV_STATUS_INSUFFICIENT_BUFFERS, -EIO),
> >> + _STATUS_INFO(HV_STATUS_NOT_ACKNOWLEDGED, -EIO),
> >> + _STATUS_INFO(HV_STATUS_INVALID_VP_STATE, -EIO),
> >> + _STATUS_INFO(HV_STATUS_NO_RESOURCES, -EIO),
> >> + _STATUS_INFO(HV_STATUS_PROCESSOR_FEATURE_NOT_SUPPORTED, -EIO),
> >> + _STATUS_INFO(HV_STATUS_INVALID_LP_INDEX, -EINVAL),
> >> + _STATUS_INFO(HV_STATUS_INVALID_REGISTER_VALUE, -EINVAL),
> >> + _STATUS_INFO(HV_STATUS_INVALID_LP_INDEX, -EIO),
> >> + _STATUS_INFO(HV_STATUS_INVALID_REGISTER_VALUE, -EIO),
> >> + _STATUS_INFO(HV_STATUS_OPERATION_FAILED, -EIO),
> >> + _STATUS_INFO(HV_STATUS_TIME_OUT, -EIO),
> >> + _STATUS_INFO(HV_STATUS_CALL_PENDING, -EIO),
> >> + _STATUS_INFO(HV_STATUS_VTL_ALREADY_ENABLED, -EIO),
> >> +#undef _STATUS_INFO
> >> +};
> >> +
> >> +static inline const struct hv_status_info *find_hv_status_info(u64 hv_status)
> >> +{
> >> + int i;
> >> + u16 code = hv_result(hv_status);
> >> +
> >> + for (i = 0; i < ARRAY_SIZE(hv_status_infos); ++i) {
> >> + const struct hv_status_info *info = &hv_status_infos[i];
> >> +
> >> + if (info->code == code)
> >> + return info;
> >> + }
> >> +
> >> + return NULL;
> >> +}
> >> +
> >> +/* Convert a hypercall result into a linux-friendly error code. */
> >> +int hv_result_to_errno(u64 status)
> >> +{
> >> + const struct hv_status_info *info;
> >> +
> >> + /* hv_do_hypercall() may return U64_MAX, hypercalls aren't possible */
> >> + if (unlikely(status == U64_MAX))
> >> + return -EOPNOTSUPP;
> >> +
> >> + info = find_hv_status_info(status);
> >> + if (info)
> >> + return info->errno;
> >> +
> >> + return -EIO;
> >> +}
> >> +EXPORT_SYMBOL_GPL(hv_result_to_errno);
> >> +
> >> +const char *hv_result_to_string(u64 status)
> >> +{
> >> + const struct hv_status_info *info;
> >> +
> >> + if (unlikely(status == U64_MAX))
> >> + return "Hypercall page missing!";
> >> +
> >> + info = find_hv_status_info(status);
> >> + if (info)
> >> + return info->string;
> >> +
> >> + return "Unknown";
> >> +}
> >> +EXPORT_SYMBOL_GPL(hv_result_to_string);
> >
> > I think the table-driven approach worked out pretty well. But here's a version that
> > is even more compact, and avoids the duplicate testing for U64_MAX and having
> > to special case both U64_MAX and not finding a match:
> >
> > +
> > +struct hv_status_info {
> > + char *string;
> > + int errno;
> > + int code;
> > +};
> > +
> > +/*
> > + * Note on the errno mappings:
> > + * A failed hypercall is usually only recoverable (or loggable) near
> > + * the call site where the HV_STATUS_* code is known. So the errno
> > + * it gets converted to is not too useful further up the stack.
> > + * Provide a few mappings that could be useful, and revert to -EIO
> > + * as a fallback.
> > + */
> > +static const struct hv_status_info hv_status_infos[] = {
> > +#define _STATUS_INFO(status, errno) { #status, (errno), (status) }
> > + _STATUS_INFO(HV_STATUS_SUCCESS, 0),
> > + _STATUS_INFO(HV_STATUS_INVALID_HYPERCALL_CODE, -EINVAL),
> > + _STATUS_INFO(HV_STATUS_INVALID_HYPERCALL_INPUT, -EINVAL),
> > + _STATUS_INFO(HV_STATUS_INVALID_ALIGNMENT, -EIO),
> > + _STATUS_INFO(HV_STATUS_INVALID_PARAMETER, -EINVAL),
> > + _STATUS_INFO(HV_STATUS_ACCESS_DENIED, -EIO),
> > + _STATUS_INFO(HV_STATUS_INVALID_PARTITION_STATE, -EIO),
> > + _STATUS_INFO(HV_STATUS_OPERATION_DENIED, -EIO),
> > + _STATUS_INFO(HV_STATUS_UNKNOWN_PROPERTY, -EIO),
> > + _STATUS_INFO(HV_STATUS_PROPERTY_VALUE_OUT_OF_RANGE, -EIO),
> > + _STATUS_INFO(HV_STATUS_INSUFFICIENT_MEMORY, -ENOMEM),
> > + _STATUS_INFO(HV_STATUS_INVALID_PARTITION_ID, -EINVAL),
> > + _STATUS_INFO(HV_STATUS_INVALID_VP_INDEX, -EINVAL),
> > + _STATUS_INFO(HV_STATUS_NOT_FOUND, -EIO),
> > + _STATUS_INFO(HV_STATUS_INVALID_PORT_ID, -EINVAL),
> > + _STATUS_INFO(HV_STATUS_INVALID_CONNECTION_ID, -EINVAL),
> > + _STATUS_INFO(HV_STATUS_INSUFFICIENT_BUFFERS, -EIO),
> > + _STATUS_INFO(HV_STATUS_NOT_ACKNOWLEDGED, -EIO),
> > + _STATUS_INFO(HV_STATUS_INVALID_VP_STATE, -EIO),
> > + _STATUS_INFO(HV_STATUS_NO_RESOURCES, -EIO),
> > + _STATUS_INFO(HV_STATUS_PROCESSOR_FEATURE_NOT_SUPPORTED, -EIO),
> > + _STATUS_INFO(HV_STATUS_INVALID_LP_INDEX, -EINVAL),
> > + _STATUS_INFO(HV_STATUS_INVALID_REGISTER_VALUE, -EINVAL),
> > + _STATUS_INFO(HV_STATUS_INVALID_LP_INDEX, -EIO),
> > + _STATUS_INFO(HV_STATUS_INVALID_REGISTER_VALUE, -EIO),
> > + _STATUS_INFO(HV_STATUS_OPERATION_FAILED, -EIO),
> > + _STATUS_INFO(HV_STATUS_TIME_OUT, -EIO),
> > + _STATUS_INFO(HV_STATUS_CALL_PENDING, -EIO),
> > + _STATUS_INFO(HV_STATUS_VTL_ALREADY_ENABLED, -EIO),
> > + {"Hypercall page missing!", -EOPNOTSUPP, -1}, /* code -1 is "no hypercall page" */
> > + {"Unknown", -EIO, -2}, /* code -2 is "Not found" entry; must be last */
> > +#undef _STATUS_INFO
> > +};
> > +
> > +static inline const struct hv_status_info *find_hv_status_info(u64 hv_status)
> > +{
> > + int i, code;
> > + const struct hv_status_info *info;
> > +
> > + /* hv_do_hypercall() may return U64_MAX, hypercalls aren't possible */
> > + if (unlikely(hv_status == U64_MAX))
> > + code = -1;
> > + else
> > + code = hv_result(hv_status);
> > +
> > + for (i = 0; i < ARRAY_SIZE(hv_status_infos); ++i) {
> > + info = &hv_status_infos[i];
> > + if (info->code == code || info->code == -2)
> > + break;
> > + }
> > +
> > + return info;
> > +}
> > +
> > +/* Convert a hypercall result into a linux-friendly error code. */
> > +int hv_result_to_errno(u64 status)
> > +{
> > + return find_hv_status_info(status)->errno;
> > +}
> > +EXPORT_SYMBOL_GPL(hv_result_to_errno);
> > +
> > +const char *hv_result_to_string(u64 status)
> > +{
> > + return find_hv_status_info(status)->string;
> > +}
> > +EXPORT_SYMBOL_GPL(hv_result_to_string);
> >
> > It could be even more compact by exporting find_hv_status_info() and
> > letting hv_result_to_errno() and hv_result_to_string() be #defines to
> > find_hv_status_info()->errno and find_hv_status_info()->string,
> > respectively.
> >
> > Note that in struct hv_status_info, the "code" field is defined as "int"
> > instead of "u16" so that it can contain sentinel values -1 and -2 that
> > won't overlap with HV_STATUS_* values.
> >
> Played around with this some more.
>
> I like your idea of making it more compact by dealing with U64_MAX and
> unknown in find_hv_status_info(), however I'm not as keen on putting
> these cases in the array and iterating over the whole array when they
> could just be static constants or inline struct initializers. See below.
>
> I also like the idea of making hv_result_to_*() functions into simple
> macros and exporting find_hv_status_info(). However, if it gets used
> elsewhere it makes more sense if the returned hv_status_info for the
> "Unknown" case contains the actual status code instead of replacing
> that information with -2, so then I'd want to return it by value
> instead of pointer:
OK, yes I agree that having the -2 in the status code field could
be a little weird.
>
> +static const struct hv_status_info hv_status_infos[] = {
> +#define _STATUS_INFO(status, errno) { #status, (status), (errno) }
> + _STATUS_INFO(HV_STATUS_SUCCESS, 0),
> <snip>
> + _STATUS_INFO(HV_STATUS_VTL_ALREADY_ENABLED, -EIO),
> +#undef _STATUS_INFO
> +};
> +
> +struct hv_status_info hv_get_status_info(u64 hv_status)
> +{
> + int i;
> + const struct hv_status_info *info;
> + u16 code = hv_result(hv_status);
> + struct hv_status_info ret = {"Unknown", code, -EIO};
> +
> + if (hv_status == U64_MAX)
> + ret = (struct hv_status_info){"Hypercall page missing!", -1,
> + -EOPNOTSUPP};
> + else
> + for (i = 0; i < ARRAY_SIZE(hv_status_infos); ++i) {
> + info = &hv_status_infos[i];
> + if (info->code == code) {
> + ret = *info;
> + break;
> + }
> + }
> +
> + return ret;
> +}
> +EXPORT_SYMBOL_GPL(hv_get_status_info);
>
> and in mshyperv.h:
>
> +#define hv_result_to_string(hv_status) hv_get_status_info(hv_status).string
> +#define hv_result_to_errno(hv_status) hv_get_status_info(hv_status).errno
> +
> +struct hv_status_info {
> + char *string;
> + int code;
> + int errno;
> +};
> +
> +struct hv_status_info hv_get_status_info(u64 hv_status);
>
> Note also I switched the order of code and errno in hv_status_info,
> mainly because I think the struct initializers for "Unknown" and
> "Hypercall page missing!" are more readable with that order:
> {string, code, errno}
>
> Do you see any problems with the above?
I don't see any problems. Having struct hv_status_info assigned
and returned by value is a little out-of-the-ordinary since it is
bigger than 64 bits. But it is only 128 bits so should be OK.
If you want to adopt your new version as a replacement for the
original version, I'm good with that.
Michael
^ permalink raw reply [flat|nested] 20+ messages in thread
end of thread, other threads:[~2025-03-25 18:04 UTC | newest]
Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-03-14 19:28 [PATCH v6 00/10] Introduce /dev/mshv root partition driver Nuno Das Neves
2025-03-14 19:28 ` [PATCH v6 01/10] hyperv: Log hypercall status codes as strings Nuno Das Neves
2025-03-18 18:01 ` Michael Kelley
2025-03-21 19:12 ` Nuno Das Neves
2025-03-25 18:02 ` Michael Kelley
2025-03-19 4:17 ` Easwar Hariharan
2025-03-14 19:28 ` [PATCH v6 02/10] x86/mshyperv: Add support for extended Hyper-V features Nuno Das Neves
2025-03-14 19:28 ` [PATCH v6 03/10] arm64/hyperv: Add some missing functions to arm64 Nuno Das Neves
2025-03-19 4:08 ` Easwar Hariharan
2025-03-14 19:28 ` [PATCH v6 04/10] hyperv: Introduce hv_recommend_using_aeoi() Nuno Das Neves
2025-03-14 19:28 ` [PATCH v6 05/10] acpi: numa: Export node_to_pxm() Nuno Das Neves
2025-03-14 19:28 ` [PATCH v6 06/10] Drivers: hv: Export some functions for use by root partition module Nuno Das Neves
2025-03-14 19:28 ` [PATCH v6 07/10] Drivers: hv: Introduce per-cpu event ring tail Nuno Das Neves
2025-03-14 19:28 ` [PATCH v6 08/10] x86: hyperv: Add mshv_handler() irq handler and setup function Nuno Das Neves
2025-03-14 19:28 ` [PATCH v6 09/10] hyperv: Add definitions for root partition driver to hv headers Nuno Das Neves
2025-03-19 4:04 ` Easwar Hariharan
2025-03-17 21:27 ` [PATCH v6 00/10] Introduce /dev/mshv root partition driver Wei Liu
[not found] ` <1741980536-3865-11-git-send-email-nunodasneves@linux.microsoft.com>
2025-03-18 19:54 ` [PATCH v6 10/10] Drivers: hv: Introduce mshv_root module to expose /dev/mshv to VMMs Michael Kelley
2025-03-18 20:00 ` Wei Liu
2025-03-18 20:23 ` Michael Kelley
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).