[PATCH v3 00/15] Introduce /dev/mshv drivers
This series introduces support for creating and running guest machines while running on the Microsoft Hypervisor. [0] This is done via an IOCTL interface accessed through /dev/mshv, similar to /dev/kvm. Another series introducing this support was previously posted. [1] These interfaces support VMMs running in: 1. The root patition - provided in the mshv_root module, and 2. VTL 2 - provided in the mshv_vtl module [2] Patches breakdown - The first 7 patches are refactoring and adding some helper functions. They provide some benefit on their own and could be applied independently as cleanup patches. Patches 8-12 just set things up for the driver code to come. These are very small. They come first so that the remaining patches are more self-contained. The final 3 patches are the meat of the series: - Patch 13 contains new header files used by the driver. These are designed to mirror the ABI headers exported by Hyper-V. This is done to avoid polluting hyperv-tlfs.h and help track changes to the ABIs that are still unstable. (See FAQ below). - Patch 14 conditionally includes these new header files into mshyperv.h and linux/hyperv.h, in order to be able to use these files in the new drivers while remaining independent from hyperv-tlfs.h. - Patch 15 contains the new driver code located in drivers/hv. This is a large amount of code and new files, but it is mostly self-contained and all within drivers/hv - apart from the IOCTL interface itself in uapi. Patch 15 is rather big and has bounced back from some mailing lists. If you did not get a copy in your inbox, you can view it here instead: https://github.com/NunoDasNeves/linux/commit/2ae1cabd82257cb303296ab6af707d1bac867e42 FAQ on include/uapi/hyperv/*.h -- Q: Why not just add these definitions to hyperv-tlfs.h? A: The intention of hyperv-tlfs.h is to contain stable definitions documented in the public TLFS document. These new definitions don't fit that criteria, so they should be separate. Q: The new headers redefine many things that are already in hyperv-tlfs.h - why? A: Some definitions are extended compared to what is documented in the TLFS. In order to avoid adding undocumented or unstable definitions to hyperv-tlfs.h, the new headers must compile independently. Therefore, the new headers must redefine many things in hyperv-tlfs.h in order to compile. Q: Why are these files named hvgdk.h, hvgdk_mini.h, hvhdk.h and hvhdk_mini.h? A: The precise meaning of the names reflects conventions used internally at Microsoft. Naming them this way makes it easy to find where particular Hyper-V definitions come from, and check their correctness. It also facilitates the future work of automatically generating these files. Q: Why are they in uapi? A: In short, to keep things simple. There are many definitions needed in both the kernel and the VMM in userspace. Separating them doesn't serve much purpose, and makes it more laborious to import definitions from Hyper-V 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 and discussion: https://lore.kernel.org/linux-hyperv/1632853875-20261-1-git-send-email-nunodasne...@linux.microsoft.com/ [2] Virtual Secure Mode (VSM) and Virtual Trust Levels (VTL): https://learn.microsoft.com/en-us/virtualization/hyper-v-on-windows/tlfs/vsm -- Changes since v2: * Fix some commit message wrapping * Fix many checkpatch.pl --strict style issues * Replace uapi ints with __s32 * Replace uapi enums with __u32 * Replace uapi pointers with __u64 * Add explicit padding to uapi structures * Initialize status in get/set registers hypercall helpers * Add missing return on error in get_vp_signaled_count * Remove select TRANSPARENT_HUGEPAGES for mshv_vtl * Use __func__ prefix consistently in printks * Use single generic cpuid() to get all 4 registers instead of 4 calls * Change hv_proximity_domain_info from union to struct for clarity Changes since v1: * Clean up formatting, capitalization in commit messages * Add detail to commit message for patch 15 * Remove errant lines in Makefile and Kconfig in patch 15 * Move a reference to CONFIG_MSHV_VTL from patch 9 to 15 Nuno Das Neves (15): hyperv-tlfs: Change shared HV_REGISTER_* defines to HV_MSR_* mshyperv: Introduce hv_get_hypervisor_version function mshyperv: Introduce numa_node_to_proximity_domain_info asm-generic/mshyperv: Introduce hv_recommend_using_aeoi() hyperv: Move hv_connection_id to hyperv-tlfs hyperv-tlfs: Introduce hv_status_to_string and hv_status_to_errno Drivers: hv: Move hv_call_deposit_pages and hv_call_create_vp to common code Drivers: hv: Introduce per-cpu event ring tail Drivers: hv: Introduce hv_
[PATCH v3 02/15] mshyperv: Introduce hv_get_hypervisor_version function
x86_64 and arm64 implementations to get the hypervisor version information. Store these in hv_hypervisor_version_info structure to simplify parsing the fields. Replace the existing parsing when printing the version numbers at boot. Signed-off-by: Nuno Das Neves --- arch/arm64/hyperv/mshyperv.c | 23 +--- arch/x86/kernel/cpu/mshyperv.c| 36 +++ include/asm-generic/hyperv-tlfs.h | 23 include/asm-generic/mshyperv.h| 2 ++ 4 files changed, 62 insertions(+), 22 deletions(-) diff --git a/arch/arm64/hyperv/mshyperv.c b/arch/arm64/hyperv/mshyperv.c index f1b8a04ee9f2..53bdd3bc81ac 100644 --- a/arch/arm64/hyperv/mshyperv.c +++ b/arch/arm64/hyperv/mshyperv.c @@ -19,10 +19,19 @@ static bool hyperv_initialized; +int hv_get_hypervisor_version(union hv_hypervisor_version_info *info) +{ + hv_get_vpreg_128(HV_REGISTER_HYPERVISOR_VERSION, +(struct hv_get_vp_registers_output *)info); + + return 0; +} +EXPORT_SYMBOL_GPL(hv_get_hypervisor_version); + static int __init hyperv_init(void) { - struct hv_get_vp_registers_output result; - u32 a, b, c, d; + struct hv_get_vp_registers_output result; + union hv_hypervisor_version_info version; u64 guest_id; int ret; @@ -55,13 +64,11 @@ static int __init hyperv_init(void) ms_hyperv.misc_features); /* Get information about the Hyper-V host version */ - hv_get_vpreg_128(HV_REGISTER_HYPERVISOR_VERSION, &result); - a = result.as32.a; - b = result.as32.b; - c = result.as32.c; - d = result.as32.d; + hv_get_hypervisor_version(&version); pr_info("Hyper-V: Host Build %d.%d.%d.%d-%d-%d\n", - b >> 16, b & 0x, a, d & 0xFF, c, d >> 24); + version.major_version, version.minor_version, + version.build_number, version.service_number, + version.service_pack, version.service_branch); ret = hv_common_init(); if (ret) diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c index 7c82b96da11f..73fbcc003d68 100644 --- a/arch/x86/kernel/cpu/mshyperv.c +++ b/arch/x86/kernel/cpu/mshyperv.c @@ -347,13 +347,26 @@ static void __init reduced_hw_init(void) x86_init.irqs.pre_vector_init = x86_init_noop; } +int hv_get_hypervisor_version(union hv_hypervisor_version_info *info) +{ + unsigned int hv_max_functions; + + hv_max_functions = cpuid_eax(HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS); + if (hv_max_functions < HYPERV_CPUID_VERSION) { + pr_err("%s: Could not detect Hyper-V version\n", __func__); + return -ENODEV; + } + + cpuid(HYPERV_CPUID_VERSION, &info->eax, &info->ebx, &info->ecx, &info->edx); + + return 0; +} +EXPORT_SYMBOL_GPL(hv_get_hypervisor_version); + static void __init ms_hyperv_init_platform(void) { int hv_max_functions_eax; - int hv_host_info_eax; - int hv_host_info_ebx; - int hv_host_info_ecx; - int hv_host_info_edx; + union hv_hypervisor_version_info version; #ifdef CONFIG_PARAVIRT pv_info.name = "Hyper-V"; @@ -407,16 +420,11 @@ static void __init ms_hyperv_init_platform(void) /* * Extract host information. */ - if (hv_max_functions_eax >= HYPERV_CPUID_VERSION) { - hv_host_info_eax = cpuid_eax(HYPERV_CPUID_VERSION); - hv_host_info_ebx = cpuid_ebx(HYPERV_CPUID_VERSION); - hv_host_info_ecx = cpuid_ecx(HYPERV_CPUID_VERSION); - hv_host_info_edx = cpuid_edx(HYPERV_CPUID_VERSION); - - pr_info("Hyper-V: Host Build %d.%d.%d.%d-%d-%d\n", - hv_host_info_ebx >> 16, hv_host_info_ebx & 0x, - hv_host_info_eax, hv_host_info_edx & 0xFF, - hv_host_info_ecx, hv_host_info_edx >> 24); + if (hv_get_hypervisor_version(&version) == 0) { + pr_info("Hyper-V Host Build:%d-%d.%d-%d-%d.%d\n", + version.build_number, version.major_version, + version.minor_version, version.service_pack, + version.service_branch, version.service_number); } if (ms_hyperv.features & HV_ACCESS_FREQUENCY_MSRS && diff --git a/include/asm-generic/hyperv-tlfs.h b/include/asm-generic/hyperv-tlfs.h index fdac4a1714ec..f63b3704d89e 100644 --- a/include/asm-generic/hyperv-tlfs.h +++ b/include/asm-generic/hyperv-tlfs.h @@ -787,6 +787,29 @@ struct hv_input_unmap_device_interrupt { #define HV_SOURCE_SHADOW_NONE 0x0 #define HV_SOURCE_SHADOW_BRIDGE_BUS_RANGE 0x1 +/* + * Version info reported by hypervisor + */ +union hv_hyperviso
[PATCH v3 04/15] asm-generic/mshyperv: Introduce hv_recommend_using_aeoi()
Factor out logic for determining if we should set the auto eoi flag in SINT register. Signed-off-by: Nuno Das Neves Reviewed-by: Wei Liu --- 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 5ea104c61fa7..d7869205dcbe 100644 --- a/drivers/hv/hv.c +++ b/drivers/hv/hv.c @@ -315,17 +315,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_register(HV_MSR_SINT0 + VMBUS_MESSAGE_SINT, shared_sint.as_uint64); diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h index e16557523b6e..c9e166d73fca 100644 --- a/include/asm-generic/mshyperv.h +++ b/include/asm-generic/mshyperv.h @@ -82,6 +82,19 @@ extern u64 hv_do_fast_hypercall8(u16 control, u64 input8); 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 +} + /* Helper functions that provide a consistent pattern for checking Hyper-V hypercall status. */ static inline int hv_result(u64 status) { -- 2.25.1
[PATCH v3 01/15] hyperv-tlfs: Change shared HV_REGISTER_* defines to HV_MSR_*
In x86 hyperv-tlfs, HV_REGISTER_ prefix is used to indicate MSRs accessed via rdmsrl/wrmsrl. But in ARM64, HV_REGISTER_ instead indicates VP registers accessed via get/set vp registers hypercall. This is due to HV_REGISTER_* names being used by hv_set/get_register, with the arch-specific version delegating to the appropriate mechanism. The problem is, using prefix HV_REGISTER_ for MSRs will conflict with VP registers when they are introduced for x86 in future. This patch solves the issue by: 1. Defining all the x86 MSRs with a consistent prefix: HV_X64_MSR_. This is so HV_REGISTER_ can be reserved for VP registers. 2. Change the non-arch-specific alias used by hv_set/get_register to HV_MSR_. This is also happens to be the same name HyperV uses for this purpose. Signed-off-by: Nuno Das Neves --- arch/arm64/include/asm/hyperv-tlfs.h | 25 + arch/x86/include/asm/hyperv-tlfs.h | 137 +-- arch/x86/include/asm/mshyperv.h | 8 +- arch/x86/kernel/cpu/mshyperv.c | 22 ++--- drivers/clocksource/hyperv_timer.c | 24 ++--- drivers/hv/hv.c | 36 +++ drivers/hv/hv_common.c | 18 ++-- include/asm-generic/mshyperv.h | 2 +- 8 files changed, 148 insertions(+), 124 deletions(-) diff --git a/arch/arm64/include/asm/hyperv-tlfs.h b/arch/arm64/include/asm/hyperv-tlfs.h index bc6c7ac934a1..a6e852c2fc3a 100644 --- a/arch/arm64/include/asm/hyperv-tlfs.h +++ b/arch/arm64/include/asm/hyperv-tlfs.h @@ -64,6 +64,31 @@ #define HV_REGISTER_STIMER0_CONFIG 0x000B #define HV_REGISTER_STIMER0_COUNT 0x000B0001 +/* + * To support non-arch-specific code calling hv_set/get_register: + * - On x86, HV_MSR_ indicates an MSR accessed via rdmsrl/wrmsrl + * - On ARM, HV_MSR_ indicates a VP register accessed via hypercall + */ +#define HV_MSR_VP_INDEX(HV_REGISTER_VP_INDEX) +#define HV_MSR_TIME_REF_COUNT (HV_REGISTER_TIME_REF_COUNT) +#define HV_MSR_REFERENCE_TS(HV_REGISTER_REFERENCE_TSC) + +#define HV_MSR_STIMER0_CONFIG (HV_REGISTER_STIMER0_CONFIG) +#define HV_MSR_STIMER0_COUNT (HV_REGISTER_STIMER0_COUNT) + +#define HV_MSR_SCONTROL(HV_REGISTER_SCONTROL) +#define HV_MSR_SIEFP (HV_REGISTER_SIEFP) +#define HV_MSR_SIMP(HV_REGISTER_SIMP) +#define HV_MSR_EOM (HV_REGISTER_EOM) +#define HV_MSR_SINT0 (HV_REGISTER_SINT0) + +#define HV_MSR_CRASH_P0(HV_REGISTER_CRASH_P0) +#define HV_MSR_CRASH_P1(HV_REGISTER_CRASH_P1) +#define HV_MSR_CRASH_P2(HV_REGISTER_CRASH_P2) +#define HV_MSR_CRASH_P3(HV_REGISTER_CRASH_P3) +#define HV_MSR_CRASH_P4(HV_REGISTER_CRASH_P4) +#define HV_MSR_CRASH_CTL (HV_REGISTER_CRASH_CTL) + union hv_msi_entry { u64 as_uint64[2]; struct { diff --git a/arch/x86/include/asm/hyperv-tlfs.h b/arch/x86/include/asm/hyperv-tlfs.h index 2ff26f53cd62..058c5c8dc382 100644 --- a/arch/x86/include/asm/hyperv-tlfs.h +++ b/arch/x86/include/asm/hyperv-tlfs.h @@ -182,7 +182,7 @@ enum hv_isolation_type { #define HV_X64_MSR_HYPERCALL 0x4001 /* MSR used to provide vcpu index */ -#define HV_REGISTER_VP_INDEX 0x4002 +#define HV_X64_MSR_VP_INDEX0x4002 /* MSR used to reset the guest OS. */ #define HV_X64_MSR_RESET 0x4003 @@ -191,10 +191,10 @@ enum hv_isolation_type { #define HV_X64_MSR_VP_RUNTIME 0x4010 /* MSR used to read the per-partition time reference counter */ -#define HV_REGISTER_TIME_REF_COUNT 0x4020 +#define HV_X64_MSR_TIME_REF_COUNT 0x4020 /* A partition's reference time stamp counter (TSC) page */ -#define HV_REGISTER_REFERENCE_TSC 0x4021 +#define HV_X64_MSR_REFERENCE_TSC 0x4021 /* MSR used to retrieve the TSC frequency */ #define HV_X64_MSR_TSC_FREQUENCY 0x4022 @@ -209,61 +209,61 @@ enum hv_isolation_type { #define HV_X64_MSR_VP_ASSIST_PAGE 0x4073 /* Define synthetic interrupt controller model specific registers. */ -#define HV_REGISTER_SCONTROL 0x4080 -#define HV_REGISTER_SVERSION 0x4081 -#define HV_REGISTER_SIEFP 0x4082 -#define HV_REGISTER_SIMP 0x4083 -#define HV_REGISTER_EOM0x4084 -#define HV_REGISTER_SINT0 0x4090 -#define HV_REGISTER_SINT1 0x4091 -#define HV_REGISTER_SINT2 0x4092 -#define HV_REGISTER_SINT3 0x4093 -#define HV_REGISTER_SINT4 0x4094 -#define HV_REGISTER_SINT5 0x4095 -#define HV_REGISTER_SINT6 0x4096 -#define HV_REGISTER_SINT7 0x4097 -#define HV_REGISTER_
[PATCH v3 14/15] asm-generic: hyperv: Use new Hyper-V headers conditionally.
Add asm-generic/hyperv-defs.h. It includes hyperv-tlfs.h or hvhdk.h depending on compile-time constant HV_HYPERV_DEFS which will be defined in the mshv driver. This is needed to keep unstable Hyper-V interfaces independent of hyperv-tlfs.h. This ensures hvhdk.h replaces hyperv-tlfs.h in the mshv driver, even via indirect includes. Signed-off-by: Nuno Das Neves Acked-by: Wei Liu --- arch/arm64/include/asm/mshyperv.h | 2 +- arch/x86/include/asm/mshyperv.h | 3 +-- drivers/hv/hyperv_vmbus.h | 1 - include/asm-generic/hyperv-defs.h | 26 ++ include/asm-generic/mshyperv.h| 2 +- include/linux/hyperv.h| 2 +- 6 files changed, 30 insertions(+), 6 deletions(-) create mode 100644 include/asm-generic/hyperv-defs.h diff --git a/arch/arm64/include/asm/mshyperv.h b/arch/arm64/include/asm/mshyperv.h index 20070a847304..8ec14caf3d4f 100644 --- a/arch/arm64/include/asm/mshyperv.h +++ b/arch/arm64/include/asm/mshyperv.h @@ -20,7 +20,7 @@ #include #include -#include +#include /* * Declare calls to get and set Hyper-V VP register values on ARM64, which diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h index 6e96d3420a9d..e19fc6140a31 100644 --- a/arch/x86/include/asm/mshyperv.h +++ b/arch/x86/include/asm/mshyperv.h @@ -6,10 +6,9 @@ #include #include #include -#include #include #include -#include +#include /* * Hyper-V always provides a single IO-APIC at this MMIO address. diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h index 09792eb4ffed..0e4bc18a13fa 100644 --- a/drivers/hv/hyperv_vmbus.h +++ b/drivers/hv/hyperv_vmbus.h @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include diff --git a/include/asm-generic/hyperv-defs.h b/include/asm-generic/hyperv-defs.h new file mode 100644 index ..ac6fcba35c8c --- /dev/null +++ b/include/asm-generic/hyperv-defs.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_GENERIC_HYPERV_DEFS_H +#define _ASM_GENERIC_HYPERV_DEFS_H + +/* + * There are cases where Microsoft Hypervisor ABIs are needed which may not be + * stable or present in the Hyper-V TLFS document. E.g. the mshv_root driver. + * + * As these interfaces are unstable and may differ from hyperv-tlfs.h, they + * must be kept separate and independent. + * + * However, code from files that depend on hyperv-tlfs.h (such as mshyperv.h) + * is still needed, so work around the issue by conditionally including the + * correct definitions. + * + * Note: Since they are independent of each other, there are many definitions + * duplicated in both hyperv-tlfs.h and uapi/hyperv/hv*.h files. + */ +#ifdef HV_HYPERV_DEFS +#include +#else +#include +#endif + +#endif /* _ASM_GENERIC_HYPERV_DEFS_H */ + diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h index 0a9e8ff31b73..d3864ba64e47 100644 --- a/include/asm-generic/mshyperv.h +++ b/include/asm-generic/mshyperv.h @@ -25,7 +25,7 @@ #include #include #include -#include +#include #define VTPM_BASE_ADDRESS 0xfed4 diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index 2d8568708d90..d0bc3d34241c 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -24,7 +24,7 @@ #include #include #include -#include +#include #define MAX_PAGE_BUFFER_COUNT 32 #define MAX_MULTIPAGE_BUFFER_COUNT 32 /* 128K */ -- 2.25.1
[PATCH v3 06/15] hyperv-tlfs: Introduce hv_status_to_string and hv_status_to_errno
hv_status_to_errno translates hyperv statuses to linux error codes. This is useful for returning something linux-friendly from a hypercall helper function. hv_status_to_string improves clarity of error messages. Signed-off-by: Nuno Das Neves Acked-by: Wei Liu --- arch/x86/hyperv/hv_init.c | 2 +- arch/x86/hyperv/hv_proc.c | 6 ++-- include/asm-generic/hyperv-tlfs.h | 47 ++- include/asm-generic/mshyperv.h| 33 ++ 4 files changed, 71 insertions(+), 17 deletions(-) diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c index 2b0124394e24..5b679bfbc7f7 100644 --- a/arch/x86/hyperv/hv_init.c +++ b/arch/x86/hyperv/hv_init.c @@ -386,7 +386,7 @@ static void __init hv_get_partition_id(void) status = hv_do_hypercall(HVCALL_GET_PARTITION_ID, NULL, output_page); if (!hv_result_success(status)) { /* No point in proceeding if this failed */ - pr_err("Failed to get partition ID: %lld\n", status); + pr_err("Failed to get partition ID: %s\n", hv_status_to_string(status)); BUG(); } hv_current_partition_id = output_page->partition_id; diff --git a/arch/x86/hyperv/hv_proc.c b/arch/x86/hyperv/hv_proc.c index 5ba5ca1b2089..ed80da64649e 100644 --- a/arch/x86/hyperv/hv_proc.c +++ b/arch/x86/hyperv/hv_proc.c @@ -144,9 +144,9 @@ 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); - ret = hv_result(status); + pr_err("%s: cpu %u apic ID %u, %s\n", __func__, + lp_index, apic_id, hv_status_to_string(status)); + ret = hv_status_to_errno(status); } break; } diff --git a/include/asm-generic/hyperv-tlfs.h b/include/asm-generic/hyperv-tlfs.h index 1316584983c1..8d76661a8c9f 100644 --- a/include/asm-generic/hyperv-tlfs.h +++ b/include/asm-generic/hyperv-tlfs.h @@ -212,19 +212,40 @@ enum HV_GENERIC_SET_FORMAT { HV_HYPERCALL_RSVD2_MASK) /* hypercall status code */ -#define HV_STATUS_SUCCESS 0 -#define HV_STATUS_INVALID_HYPERCALL_CODE 2 -#define HV_STATUS_INVALID_HYPERCALL_INPUT 3 -#define HV_STATUS_INVALID_ALIGNMENT4 -#define HV_STATUS_INVALID_PARAMETER5 -#define HV_STATUS_ACCESS_DENIED6 -#define HV_STATUS_OPERATION_DENIED 8 -#define HV_STATUS_INSUFFICIENT_MEMORY 11 -#define HV_STATUS_INVALID_PORT_ID 17 -#define HV_STATUS_INVALID_CONNECTION_ID18 -#define HV_STATUS_INSUFFICIENT_BUFFERS 19 -#define HV_STATUS_TIME_OUT 120 -#define HV_STATUS_VTL_ALREADY_ENABLED 134 +#define __HV_STATUS_DEF(OP) \ + OP(HV_STATUS_SUCCESS, 0x0) \ + OP(HV_STATUS_INVALID_HYPERCALL_CODE,0x2) \ + OP(HV_STATUS_INVALID_HYPERCALL_INPUT, 0x3) \ + OP(HV_STATUS_INVALID_ALIGNMENT, 0x4) \ + OP(HV_STATUS_INVALID_PARAMETER, 0x5) \ + OP(HV_STATUS_ACCESS_DENIED, 0x6) \ + OP(HV_STATUS_INVALID_PARTITION_STATE, 0x7) \ + OP(HV_STATUS_OPERATION_DENIED, 0x8) \ + OP(HV_STATUS_UNKNOWN_PROPERTY, 0x9) \ + OP(HV_STATUS_PROPERTY_VALUE_OUT_OF_RANGE, 0xA) \ + OP(HV_STATUS_INSUFFICIENT_MEMORY, 0xB) \ + OP(HV_STATUS_INVALID_PARTITION_ID, 0xD) \ + OP(HV_STATUS_INVALID_VP_INDEX, 0xE) \ + OP(HV_STATUS_NOT_FOUND, 0x10) \ + OP(HV_STATUS_INVALID_PORT_ID, 0x11) \ + OP(HV_STATUS_INVALID_CONNECTION_ID, 0x12) \ + OP(HV_STATUS_INSUFFICIENT_BUFFERS, 0x13) \ + OP(HV_STATUS_NOT_ACKNOWLEDGED, 0x14) \ + OP(HV_STATUS_INVALID_VP_STATE, 0x15) \ + OP(HV_STATUS_NO_RESOURCES, 0x1D) \ + OP(HV_STATUS_PROCESSOR_FEATURE_NOT_SUPPORTED, 0x20) \ + OP(HV_STATUS_INVALID_LP_INDEX, 0x41) \ + OP(HV_STATUS_INVALID_REGISTER_VALUE,0x50) \ + OP(HV_STATUS_TIME_OUT, 0x78) \ + OP(HV_STATUS_CALL_PENDING, 0x79) \ + OP(HV_STATUS_VTL_ALREADY_ENABLED, 0x86) + +#define __HV_MAKE_HV_STATUS_ENUM(NAME, VAL) NAME = (VAL), +#define __HV_MAKE_HV_STATUS_CASE(NAME, VAL) cas
[PATCH v3 10/15] x86: hyperv: Add mshv_handler irq handler and setup function
This will handle SYNIC interrupts such as intercepts, doorbells, and scheduling messages intended for the mshv driver. Signed-off-by: Nuno Das Neves Reviewed-by: Wei Liu Reviewed-by: Tianyu Lan --- arch/x86/kernel/cpu/mshyperv.c | 9 + drivers/hv/hv_common.c | 5 + include/asm-generic/mshyperv.h | 2 ++ 3 files changed, 16 insertions(+) diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c index 73fbcc003d68..b8c3177d6389 100644 --- a/arch/x86/kernel/cpu/mshyperv.c +++ b/arch/x86/kernel/cpu/mshyperv.c @@ -110,6 +110,7 @@ void hv_set_register(unsigned int reg, u64 value) } EXPORT_SYMBOL_GPL(hv_set_register); +static void (*mshv_handler)(void); static void (*vmbus_handler)(void); static void (*hv_stimer0_handler)(void); static void (*hv_kexec_handler)(void); @@ -120,6 +121,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(); @@ -129,6 +133,11 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_hyperv_callback) set_irq_regs(old_regs); } +void hv_setup_mshv_irq(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 89f5c1fb2a35..092b0c727db9 100644 --- a/drivers/hv/hv_common.c +++ b/drivers/hv/hv_common.c @@ -585,6 +585,11 @@ void __weak hv_remove_vmbus_handler(void) } EXPORT_SYMBOL_GPL(hv_remove_vmbus_handler); +void __weak hv_setup_mshv_irq(void (*handler)(void)) +{ +} +EXPORT_SYMBOL_GPL(hv_setup_mshv_irq); + void __weak hv_setup_kexec_handler(void (*handler)(void)) { } diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h index 5a12e5754e97..0a9e8ff31b73 100644 --- a/include/asm-generic/mshyperv.h +++ b/include/asm-generic/mshyperv.h @@ -198,6 +198,8 @@ void hv_remove_vmbus_handler(void); void hv_setup_stimer0_handler(void (*handler)(void)); void hv_remove_stimer0_handler(void); +void hv_setup_mshv_irq(void (*handler)(void)); + 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)); -- 2.25.1
[PATCH v3 08/15] Drivers: hv: Introduce per-cpu event ring tail
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 Reviewed-by: Wei Liu --- drivers/hv/hv_common.c | 28 ++-- include/asm-generic/mshyperv.h | 2 ++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c index 8c6ab60d5387..d346ce6adf00 100644 --- a/drivers/hv/hv_common.c +++ b/drivers/hv/hv_common.c @@ -62,6 +62,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 @@ -84,6 +94,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; } /* @@ -333,6 +346,8 @@ int __init hv_common_init(void) if (hv_root_partition) { hyperv_pcpu_output_arg = alloc_percpu(void *); BUG_ON(!hyperv_pcpu_output_arg); + hv_synic_eventring_tail = alloc_percpu(u8 *); + BUG_ON(hv_synic_eventring_tail == NULL); } hv_vp_index = kmalloc_array(num_possible_cpus(), sizeof(*hv_vp_index), @@ -357,6 +372,7 @@ int __init hv_common_init(void) int hv_common_cpu_init(unsigned int cpu) { void **inputarg, **outputarg; + u8 **synic_eventring_tail; u64 msr_vp_index; gfp_t flags; int pgcount = hv_root_partition ? 2 : 1; @@ -369,8 +385,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); @@ -380,6 +396,14 @@ int hv_common_cpu_init(unsigned int cpu) if (hv_root_partition) { outputarg = (void **)this_cpu_ptr(hyperv_pcpu_output_arg); *outputarg = (char *)mem + HV_HYP_PAGE_SIZE; + synic_eventring_tail = (u8 **)this_cpu_ptr(hv_synic_eventring_tail); + *synic_eventring_tail = kcalloc(HV_SYNIC_SINT_COUNT, sizeof(u8), + flags); + + if (unlikely(!*synic_eventring_tail)) { + kfree(mem); + return -ENOMEM; + } } if (!ms_hyperv.paravisor_present && diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h index 5be3e3402e37..5a12e5754e97 100644 --- a/include/asm-generic/mshyperv.h +++ b/include/asm-generic/mshyperv.h @@ -77,6 +77,8 @@ extern bool hv_nested; extern void * __percpu *hyperv_pcpu_input_arg; extern void * __percpu *hyperv_pcpu_output_arg; +extern u8 __percpu **hv_synic_eventring_tail; + extern u64 hv_do_hypercall(u64 control, void *inputaddr, void *outputaddr); extern u64 hv_do_fast_hypercall8(u16 control, u64 input8); bool hv_isolation_type_snp(void); -- 2.25.1
[PATCH v3 11/15] Drivers: hv: export vmbus_isr, hv_context and hv_post_message
These will be used by the mshv_vtl driver. Signed-off-by: Nuno Das Neves Acked-by: Wei Liu --- drivers/hv/hv.c | 2 ++ drivers/hv/hyperv_vmbus.h | 1 + drivers/hv/vmbus_drv.c| 3 ++- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c index d7869205dcbe..c60a4fb55f3c 100644 --- a/drivers/hv/hv.c +++ b/drivers/hv/hv.c @@ -25,6 +25,7 @@ /* The one and only */ struct hv_context hv_context; +EXPORT_SYMBOL_GPL(hv_context); /* * hv_init - Main initialization routine. @@ -93,6 +94,7 @@ int hv_post_message(union hv_connection_id connection_id, return hv_result(status); } +EXPORT_SYMBOL_GPL(hv_post_message); int hv_synic_alloc(void) { diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h index f6b1e710f805..09792eb4ffed 100644 --- a/drivers/hv/hyperv_vmbus.h +++ b/drivers/hv/hyperv_vmbus.h @@ -32,6 +32,7 @@ */ #define HV_UTIL_NEGO_TIMEOUT 55 +void vmbus_isr(void); /* Definitions for the monitored notification facility */ union hv_monitor_trigger_group { diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index edbb38f6956b..6d27597af8bf 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -1286,7 +1286,7 @@ static void vmbus_chan_sched(struct hv_per_cpu_context *hv_cpu) } } -static void vmbus_isr(void) +void vmbus_isr(void) { struct hv_per_cpu_context *hv_cpu = this_cpu_ptr(hv_context.cpu_context); @@ -1309,6 +1309,7 @@ static void vmbus_isr(void) add_interrupt_randomness(vmbus_interrupt); } +EXPORT_SYMBOL_GPL(vmbus_isr); static irqreturn_t vmbus_percpu_isr(int irq, void *dev_id) { -- 2.25.1
[PATCH v3 07/15] Drivers: hv: Move hv_call_deposit_pages and hv_call_create_vp to common code
These hypercalls are not arch-specific. Move them to common code. Signed-off-by: Nuno Das Neves Acked-by: Wei Liu --- arch/x86/hyperv/hv_proc.c | 152 arch/x86/include/asm/mshyperv.h | 1 - drivers/hv/hv_common.c | 147 ++ include/asm-generic/mshyperv.h | 2 + 4 files changed, 149 insertions(+), 153 deletions(-) diff --git a/arch/x86/hyperv/hv_proc.c b/arch/x86/hyperv/hv_proc.c index ed80da64649e..0a35cb865427 100644 --- a/arch/x86/hyperv/hv_proc.c +++ b/arch/x86/hyperv/hv_proc.c @@ -3,7 +3,6 @@ #include #include #include -#include #include #include #include @@ -14,106 +13,6 @@ #include -/* - * See struct hv_deposit_memory. The first u64 is partition ID, the rest - * are GPAs. - */ -#define HV_DEPOSIT_MAX (HV_HYP_PAGE_SIZE / sizeof(u64) - 1) - -/* Deposits exact number of pages. Must be called with interrupts enabled. */ -int hv_call_deposit_pages(int node, u64 partition_id, u32 num_pages) -{ - struct page **pages, *page; - int *counts; - int num_allocations; - int i, j, page_count; - int order; - u64 status; - int ret; - u64 base_pfn; - struct hv_deposit_memory *input_page; - unsigned long flags; - - if (num_pages > HV_DEPOSIT_MAX) - return -E2BIG; - if (!num_pages) - return 0; - - /* One buffer for page pointers and counts */ - page = alloc_page(GFP_KERNEL); - if (!page) - return -ENOMEM; - pages = page_address(page); - - counts = kcalloc(HV_DEPOSIT_MAX, sizeof(int), GFP_KERNEL); - if (!counts) { - free_page((unsigned long)pages); - return -ENOMEM; - } - - /* Allocate all the pages before disabling interrupts */ - i = 0; - - while (num_pages) { - /* Find highest order we can actually allocate */ - order = 31 - __builtin_clz(num_pages); - - while (1) { - pages[i] = alloc_pages_node(node, GFP_KERNEL, order); - if (pages[i]) - break; - if (!order) { - ret = -ENOMEM; - num_allocations = i; - goto err_free_allocations; - } - --order; - } - - split_page(pages[i], order); - counts[i] = 1 << order; - num_pages -= counts[i]; - i++; - } - num_allocations = i; - - local_irq_save(flags); - - input_page = *this_cpu_ptr(hyperv_pcpu_input_arg); - - input_page->partition_id = partition_id; - - /* Populate gpa_page_list - these will fit on the input page */ - for (i = 0, page_count = 0; i < num_allocations; ++i) { - base_pfn = page_to_pfn(pages[i]); - for (j = 0; j < counts[i]; ++j, ++page_count) - input_page->gpa_page_list[page_count] = base_pfn + j; - } - status = hv_do_rep_hypercall(HVCALL_DEPOSIT_MEMORY, -page_count, 0, input_page, NULL); - local_irq_restore(flags); - if (!hv_result_success(status)) { - pr_err("Failed to deposit pages: %lld\n", status); - ret = hv_result(status); - goto err_free_allocations; - } - - ret = 0; - goto free_buf; - -err_free_allocations: - for (i = 0; i < num_allocations; ++i) { - base_pfn = page_to_pfn(pages[i]); - for (j = 0; j < counts[i]; ++j) - __free_page(pfn_to_page(base_pfn + j)); - } - -free_buf: - free_page((unsigned long)pages); - kfree(counts); - return ret; -} - int hv_call_add_logical_proc(int node, u32 lp_index, u32 apic_id) { struct hv_add_logical_processor_in *input; @@ -156,54 +55,3 @@ int hv_call_add_logical_proc(int node, u32 lp_index, u32 apic_id) return ret; } -int hv_call_create_vp(int node, u64 partition_id, u32 vp_index, u32 flags) -{ - struct hv_create_vp *input; - u64 status; - unsigned long irq_flags; - int ret = HV_STATUS_SUCCESS; - int pxm = node_to_pxm(node); - - /* Root VPs don't seem to need pages deposited */ - if (partition_id != hv_current_partition_id) { - /* The value 90 is empirically determined. It may change. */ - ret = hv_call_deposit_pages(node, partition_id, 90); - if (ret) - return ret; - } - - do { - local_irq_save(irq_flags); - - input = *this_cpu_ptr(hyperv_pcpu_input_arg); - - input->partition_id = partition_id; - input->vp_index = vp_index; - input->
[PATCH v3 09/15] Drivers: hv: Introduce hv_output_arg_exists in hv_common.c
This is a more flexible approach for determining whether to allocate the output page. Signed-off-by: Nuno Das Neves Acked-by: Wei Liu --- drivers/hv/hv_common.c | 21 + 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c index d346ce6adf00..89f5c1fb2a35 100644 --- a/drivers/hv/hv_common.c +++ b/drivers/hv/hv_common.c @@ -58,6 +58,14 @@ EXPORT_SYMBOL_GPL(hyperv_pcpu_input_arg); void * __percpu *hyperv_pcpu_output_arg; EXPORT_SYMBOL_GPL(hyperv_pcpu_output_arg); +/* + * Determine whether output arg is needed + */ +static inline bool hv_output_arg_exists(void) +{ + return hv_root_partition ? true : false; +} + static void hv_kmsg_dump_unregister(void); static struct ctl_table_header *hv_ctl_table_hdr; @@ -342,10 +350,12 @@ int __init hv_common_init(void) hyperv_pcpu_input_arg = alloc_percpu(void *); BUG_ON(!hyperv_pcpu_input_arg); - /* Allocate the per-CPU state for output arg for root */ - if (hv_root_partition) { + if (hv_output_arg_exists()) { hyperv_pcpu_output_arg = alloc_percpu(void *); BUG_ON(!hyperv_pcpu_output_arg); + } + + if (hv_root_partition) { hv_synic_eventring_tail = alloc_percpu(u8 *); BUG_ON(hv_synic_eventring_tail == NULL); } @@ -375,7 +385,7 @@ int hv_common_cpu_init(unsigned int cpu) u8 **synic_eventring_tail; u64 msr_vp_index; gfp_t flags; - int pgcount = hv_root_partition ? 2 : 1; + int pgcount = hv_output_arg_exists() ? 2 : 1; void *mem; int ret; @@ -393,9 +403,12 @@ int hv_common_cpu_init(unsigned int cpu) if (!mem) return -ENOMEM; - if (hv_root_partition) { + if (hv_output_arg_exists()) { outputarg = (void **)this_cpu_ptr(hyperv_pcpu_output_arg); *outputarg = (char *)mem + HV_HYP_PAGE_SIZE; + } + + 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); -- 2.25.1
[PATCH v3 12/15] Documentation: Reserve ioctl number for mshv driver
Signed-off-by: Nuno Das Neves Acked-by: Jonathan Corbet --- Documentation/userspace-api/ioctl/ioctl-number.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/userspace-api/ioctl/ioctl-number.rst b/Documentation/userspace-api/ioctl/ioctl-number.rst index 4ea5b837399a..71e6d23070ca 100644 --- a/Documentation/userspace-api/ioctl/ioctl-number.rst +++ b/Documentation/userspace-api/ioctl/ioctl-number.rst @@ -355,6 +355,8 @@ Code Seq#Include File Comments 0xB6 alllinux/fpga-dfl.h 0xB7 alluapi/linux/remoteproc_cdev.h <mailto:linux-remotep...@vger.kernel.org> 0xB7 alluapi/linux/nsfs.h <mailto:Andrei Vagin > +0xB8 alluapi/linux/mshv.h Microsoft Hypervisor VM management APIs + <mailto:linux-hyperv@vger.kernel.org> 0xC0 00-0F linux/usb/iowarrior.h 0xCA 00-0F uapi/misc/cxl.h 0xCA 10-2F uapi/misc/ocxl.h -- 2.25.1
[PATCH v3 05/15] hyperv: Move hv_connection_id to hyperv-tlfs
The definition conflicts with one added in hvgdk.h as part of the mshv driver so must be moved to hyperv-tlfs.h. This structure should be in hyperv-tlfs.h anyway, since it is part of the TLFS document. Signed-off-by: Nuno Das Neves Acked-by: Wei Liu --- include/asm-generic/hyperv-tlfs.h | 9 + include/linux/hyperv.h| 9 - 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/include/asm-generic/hyperv-tlfs.h b/include/asm-generic/hyperv-tlfs.h index a6dffb346bf2..1316584983c1 100644 --- a/include/asm-generic/hyperv-tlfs.h +++ b/include/asm-generic/hyperv-tlfs.h @@ -842,4 +842,13 @@ struct hv_mmio_write_input { u8 data[HV_HYPERCALL_MMIO_MAX_DATA_LENGTH]; } __packed; +/* Define connection identifier type. */ +union hv_connection_id { + u32 asu32; + struct { + u32 id:24; + u32 reserved:8; + } u; +}; + #endif diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index a922d4526de4..2d8568708d90 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -748,15 +748,6 @@ struct vmbus_close_msg { struct vmbus_channel_close_channel msg; }; -/* Define connection identifier type. */ -union hv_connection_id { - u32 asu32; - struct { - u32 id:24; - u32 reserved:8; - } u; -}; - enum vmbus_device_type { HV_IDE = 0, HV_SCSI, -- 2.25.1
[PATCH v3 03/15] mshyperv: Introduce numa_node_to_proximity_domain_info
Factor out logic for converting numa node to proximity domain info into a helper function, and export it. Change hv_proximity_domain_info to a struct to simplify the code. Signed-off-by: Nuno Das Neves Reviewed-by: Wei Liu --- arch/x86/hyperv/hv_proc.c | 8 ++-- drivers/acpi/numa/srat.c | 1 + include/asm-generic/hyperv-tlfs.h | 14 +- include/asm-generic/mshyperv.h| 15 +++ 4 files changed, 23 insertions(+), 15 deletions(-) diff --git a/arch/x86/hyperv/hv_proc.c b/arch/x86/hyperv/hv_proc.c index 68a0843d4750..5ba5ca1b2089 100644 --- a/arch/x86/hyperv/hv_proc.c +++ b/arch/x86/hyperv/hv_proc.c @@ -121,7 +121,6 @@ int hv_call_add_logical_proc(int node, u32 lp_index, u32 apic_id) u64 status; unsigned long flags; int ret = HV_STATUS_SUCCESS; - int pxm = node_to_pxm(node); /* * When adding a logical processor, the hypervisor may return @@ -137,11 +136,8 @@ int hv_call_add_logical_proc(int node, u32 lp_index, u32 apic_id) input->lp_index = lp_index; input->apic_id = apic_id; - input->flags = 0; - input->proximity_domain_info.domain_id = pxm; - input->proximity_domain_info.flags.reserved = 0; - input->proximity_domain_info.flags.proximity_info_valid = 1; - input->proximity_domain_info.flags.proximity_preferred = 1; + input->proximity_domain_info = + numa_node_to_proximity_domain_info(node); status = hv_do_hypercall(HVCALL_ADD_LOGICAL_PROCESSOR, input, output); local_irq_restore(flags); diff --git a/drivers/acpi/numa/srat.c b/drivers/acpi/numa/srat.c index 1f4fc5f8a819..0cf9f0574495 100644 --- a/drivers/acpi/numa/srat.c +++ b/drivers/acpi/numa/srat.c @@ -48,6 +48,7 @@ int node_to_pxm(int node) return PXM_INVAL; return node_to_pxm_map[node]; } +EXPORT_SYMBOL(node_to_pxm); static void __acpi_map_pxm_to_node(int pxm, int node) { diff --git a/include/asm-generic/hyperv-tlfs.h b/include/asm-generic/hyperv-tlfs.h index f63b3704d89e..a6dffb346bf2 100644 --- a/include/asm-generic/hyperv-tlfs.h +++ b/include/asm-generic/hyperv-tlfs.h @@ -512,13 +512,9 @@ struct hv_proximity_domain_flags { u32 proximity_info_valid : 1; } __packed; -/* Not a union in windows but useful for zeroing */ -union hv_proximity_domain_info { - struct { - u32 domain_id; - struct hv_proximity_domain_flags flags; - }; - u64 as_uint64; +struct hv_proximity_domain_info { + u32 domain_id; + struct hv_proximity_domain_flags flags; } __packed; struct hv_lp_startup_status { @@ -535,7 +531,7 @@ struct hv_lp_startup_status { struct hv_add_logical_processor_in { u32 lp_index; u32 apic_id; - union hv_proximity_domain_info proximity_domain_info; + struct hv_proximity_domain_info proximity_domain_info; u64 flags; } __packed; @@ -560,7 +556,7 @@ struct hv_create_vp { u8 padding[3]; u8 subnode_type; u64 subnode_id; - union hv_proximity_domain_info proximity_domain_info; + struct hv_proximity_domain_info proximity_domain_info; u64 flags; } __packed; diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h index 5b3512e5a72e..e16557523b6e 100644 --- a/include/asm-generic/mshyperv.h +++ b/include/asm-generic/mshyperv.h @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -28,6 +29,20 @@ #define VTPM_BASE_ADDRESS 0xfed4 +static inline struct hv_proximity_domain_info +numa_node_to_proximity_domain_info(int node) +{ + struct hv_proximity_domain_info proximity_domain_info = {}; + + if (node != NUMA_NO_NODE) { + proximity_domain_info.domain_id = node_to_pxm(node); + proximity_domain_info.flags.proximity_info_valid = 1; + proximity_domain_info.flags.proximity_preferred = 1; + } + + return proximity_domain_info; +} + struct ms_hyperv_info { u32 features; u32 priv_high; -- 2.25.1
[PATCH v3 13/15] uapi: hyperv: Add mshv driver headers defining hypervisor ABIs
These must be in uapi because they will be used in the mshv ioctl API. Version numbers for each file: hvhdk.h 25212 hvhdk_mini.h25294 hvgdk.h 25125 hvgdk_mini.h25294 These are unstable interfaces and as such must be compiled independently from published interfaces found in hyperv-tlfs.h. Signed-off-by: Nuno Das Neves Acked-by: Wei Liu --- include/uapi/hyperv/hvgdk.h | 41 + include/uapi/hyperv/hvgdk_mini.h | 1076 include/uapi/hyperv/hvhdk.h | 1342 ++ include/uapi/hyperv/hvhdk_mini.h | 160 4 files changed, 2619 insertions(+) create mode 100644 include/uapi/hyperv/hvgdk.h create mode 100644 include/uapi/hyperv/hvgdk_mini.h create mode 100644 include/uapi/hyperv/hvhdk.h create mode 100644 include/uapi/hyperv/hvhdk_mini.h diff --git a/include/uapi/hyperv/hvgdk.h b/include/uapi/hyperv/hvgdk.h new file mode 100644 index ..9bcbb7d902b2 --- /dev/null +++ b/include/uapi/hyperv/hvgdk.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright (c) 2023, Microsoft Corporation. + * + * These files (hvhdk.h, hvhdk_mini.h, hvgdk.h, hvgdk_mini.h) define APIs for + * communicating with the Microsoft Hypervisor. + * + * These definitions are subject to change across hypervisor versions, and as + * such are separate and independent from hyperv-tlfs.h. + * + * The naming of these headers reflects conventions used in the Microsoft + * Hypervisor. + */ +#ifndef _UAPI_HV_HVGDK_H +#define _UAPI_HV_HVGDK_H + +#include "hvgdk_mini.h" + +enum hv_unimplemented_msr_action { + HV_UNIMPLEMENTED_MSR_ACTION_FAULT = 0, + HV_UNIMPLEMENTED_MSR_ACTION_IGNORE_WRITE_READ_ZERO = 1, + HV_UNIMPLEMENTED_MSR_ACTION_COUNT = 2, +}; + +/* Define connection identifier type. */ +union hv_connection_id { + __u32 asu32; + struct { + __u32 id:24; + __u32 reserved:8; + } __packed u; +}; + +struct hv_input_unmap_gpa_pages { + __u64 target_partition_id; + __u64 target_gpa_base; + __u32 unmap_flags; + __u32 padding; +} __packed; + +#endif /* #ifndef _UAPI_HV_HVGDK_H */ diff --git a/include/uapi/hyperv/hvgdk_mini.h b/include/uapi/hyperv/hvgdk_mini.h new file mode 100644 index ..f894327206c8 --- /dev/null +++ b/include/uapi/hyperv/hvgdk_mini.h @@ -0,0 +1,1076 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright (c) 2023, Microsoft Corporation. + * + * These files (hvhdk.h, hvhdk_mini.h, hvgdk.h, hvgdk_mini.h) define APIs for + * communicating with the Microsoft Hypervisor. + * + * These definitions are subject to change across hypervisor versions, and as + * such are separate and independent from hyperv-tlfs.h. + * + * The naming of these headers reflects conventions used in the Microsoft + * Hypervisor. + */ +#ifndef _UAPI_HV_HVGDK_MINI_H +#define _UAPI_HV_HVGDK_MINI_H + +struct hv_u128 { + __u64 low_part; + __u64 high_part; +} __packed; + +/* hypercall status code */ +#define __HV_STATUS_DEF(OP) \ + OP(HV_STATUS_SUCCESS, 0x0) \ + OP(HV_STATUS_INVALID_HYPERCALL_CODE,0x2) \ + OP(HV_STATUS_INVALID_HYPERCALL_INPUT, 0x3) \ + OP(HV_STATUS_INVALID_ALIGNMENT, 0x4) \ + OP(HV_STATUS_INVALID_PARAMETER, 0x5) \ + OP(HV_STATUS_ACCESS_DENIED, 0x6) \ + OP(HV_STATUS_INVALID_PARTITION_STATE, 0x7) \ + OP(HV_STATUS_OPERATION_DENIED, 0x8) \ + OP(HV_STATUS_UNKNOWN_PROPERTY, 0x9) \ + OP(HV_STATUS_PROPERTY_VALUE_OUT_OF_RANGE, 0xA) \ + OP(HV_STATUS_INSUFFICIENT_MEMORY, 0xB) \ + OP(HV_STATUS_INVALID_PARTITION_ID, 0xD) \ + OP(HV_STATUS_INVALID_VP_INDEX, 0xE) \ + OP(HV_STATUS_NOT_FOUND, 0x10) \ + OP(HV_STATUS_INVALID_PORT_ID, 0x11) \ + OP(HV_STATUS_INVALID_CONNECTION_ID, 0x12) \ + OP(HV_STATUS_INSUFFICIENT_BUFFERS, 0x13) \ + OP(HV_STATUS_NOT_ACKNOWLEDGED, 0x14) \ + OP(HV_STATUS_INVALID_VP_STATE, 0x15) \ + OP(HV_STATUS_NO_RESOURCES, 0x1D) \ + OP(HV_STATUS_PROCESSOR_FEATURE_NOT_SUPPORTED, 0x20) \ + OP(HV_STATUS_INVALID_LP_INDEX, 0x41) \ + OP(HV_STATUS_INVALID_REGISTER_VALUE,0x50) \ + OP(HV_STATUS_CALL_PENDING, 0x79) + +#define __HV_MAKE_HV_STATUS_ENUM(NAME, VAL) NAME = (VAL), +#define __HV_MAKE_HV_STATUS_CASE(NAME, VAL) case (NAME): return (#NAME); + +enum hv_status { + __HV_STATUS_DEF(__HV_MAKE_HV_STATUS_ENUM) +}; + +/* TODO not in hv headers */ +#define HV_LINUX_VENDOR_ID 0x8100 +#define HV_HYP_PAGE_SHIFT 12 +#define HV_HYP_PAGE_SIZE BIT(HV_HYP_PAGE_SHIFT) +#define HV_HYP
Re: [PATCH v3 15/15] Drivers: hv: Add modules to expose /dev/mshv to VMMs running on Hyper-V
Resend in plain text instead of HTML - oops! On 9/23/2023 12:58 AM, Greg KH wrote: On Fri, Sep 22, 2023 at 11:38:35AM -0700, Nuno Das Neves wrote: +static int mshv_vtl_get_vsm_regs(void) +{ + struct hv_register_assoc registers[2]; + union hv_input_vtl input_vtl; + int ret, count = 2; + + input_vtl.as_uint8 = 0; + registers[0].name = HV_REGISTER_VSM_CODE_PAGE_OFFSETS; + registers[1].name = HV_REGISTER_VSM_CAPABILITIES; + + ret = hv_call_get_vp_registers(HV_VP_INDEX_SELF, HV_PARTITION_ID_SELF, + count, input_vtl, registers); + if (ret) + return ret; + + mshv_vsm_page_offsets.as_uint64 = registers[0].value.reg64; + mshv_vsm_capabilities.as_uint64 = registers[1].value.reg64; + + pr_debug("%s: VSM code page offsets: %#016llx\n", __func__, +mshv_vsm_page_offsets.as_uint64); + pr_info("%s: VSM capabilities: %#016llx\n", __func__, + mshv_vsm_capabilities.as_uint64); When drivers are working properly, they are quiet. This is very noisy and probably is leaking memory addresses to userspace? I will remove these, thanks. Also, there is NEVER a need for __func__ in a pr_debug() line, it has that for you automatically. Thank you, I didn't know this. Also, drivers should never call pr_*() calls, always use the proper dev_*() calls instead. We only use struct device in one place in this driver, I think that is the only place it makes sense to use dev_*() over pr_*() calls. + + return ret; +} + +static int mshv_vtl_configure_vsm_partition(void) +{ + union hv_register_vsm_partition_config config; + struct hv_register_assoc reg_assoc; + union hv_input_vtl input_vtl; + + config.as_u64 = 0; + config.default_vtl_protection_mask = HV_MAP_GPA_PERMISSIONS_MASK; + config.enable_vtl_protection = 1; + config.zero_memory_on_reset = 1; + config.intercept_vp_startup = 1; + config.intercept_cpuid_unimplemented = 1; + + if (mshv_vsm_capabilities.intercept_page_available) { + pr_debug("%s: using intercept page", __func__); Again, __func__ is not needed, you are providing it twice here for no real reason except to waste storage space :) Thanks, I will review all the uses of pr_debug(). + config.intercept_page = 1; + } + + reg_assoc.name = HV_REGISTER_VSM_PARTITION_CONFIG; + reg_assoc.value.reg64 = config.as_u64; + input_vtl.as_uint8 = 0; + + return hv_call_set_vp_registers(HV_VP_INDEX_SELF, HV_PARTITION_ID_SELF, + 1, input_vtl, ®_assoc); None of this needs to be unwound if initialization fails later on? I think unwinding this is not needed, not 100% sure. Saurabh, can you comment? Thanks, Nuno thanks, greg k-h
Re: [PATCH v3 15/15] Drivers: hv: Add modules to expose /dev/mshv to VMMs running on Hyper-V
On 9/26/2023 1:03 AM, Greg KH wrote: On Tue, Sep 26, 2023 at 07:00:51AM +, Wei Liu wrote: On Tue, Sep 26, 2023 at 08:31:03AM +0200, Greg KH wrote: On Tue, Sep 26, 2023 at 05:54:34AM +, Wei Liu wrote: On Tue, Sep 26, 2023 at 06:52:46AM +0200, Greg KH wrote: On Mon, Sep 25, 2023 at 05:07:24PM -0700, Nuno Das Neves wrote: On 9/23/2023 12:58 AM, Greg KH wrote: Also, drivers should never call pr_*() calls, always use the proper dev_*() calls instead. We only use struct device in one place in this driver, I think that is the only place it makes sense to use dev_*() over pr_*() calls. Then the driver needs to be fixed to use struct device properly so that you do have access to it when you want to print messages. That's a valid reason to pass around your device structure when needed. What is the tangible benefit of using dev_*() over pr_*()? As I said, our use of struct device is very limited compared to all the places we may need to log errors. pr_*() is used by many, many drivers; it seems to be the norm. We can certainly add a pr_fmt to improve the logging. Greg, ACRN and Nitro drivers do not pass around the device structure. Instead, they rely on a global struct device. We can follow the same. A single global struct device is wrong, please don't do that. Don't copy bad design patterns from other drivers, be better :) What makes it a bad pattern? It seems to be well-established, and is also used by KVM which this driver is loosely modeled after: https://elixir.bootlin.com/linux/v6.5.5/source/virt/kvm/kvm_main.c#L5128 If we're working with real devices like network cards or graphics cards I would agree -- it is easy to imagine that we have several cards of the same model in the system -- but in real world there won't be two hypervisor instances running on the same hardware. We can stash the struct device inside some private data fields, but that doesn't change the fact that we're still having one instance of the structure. Is this what you want? Or do you have something else in mind? You have a real device, it's how userspace interacts with your subsystem. Please use that, it is dynamically created and handled and is the correct representation here. Are you referring to the struct device we get from calling misc_register? If not, please be more specific. How would you suggest we get a reference to that device via e.g. open() or ioctl() without keeping a global reference to it? Thanks, Nuno
Re: [PATCH v3 15/15] Drivers: hv: Add modules to expose /dev/mshv to VMMs running on Hyper-V
On 9/27/2023 1:33 AM, Greg KH wrote: On Wed, Sep 27, 2023 at 08:04:42AM +, Wei Liu wrote: So, the driver is supposed to stash a pointer to struct device in private_data. That's what I alluded to in my previous reply. The core driver framework or the VFS doesn't give us a reference to struct device. We have to do it ourselves. Please read Linux Device Drivers, 3rd edition, chapter 3, for how to do this properly. The book is free online. Thanks, the issue that confused us was how to get the miscdevice. I eventually found the answer in the misc_register() documentation: "By default, an open() syscall to the device sets file->private_data to point to the structure." That's good - when we create a guest, we will have the miscdevice in private_data already. Then we can just put it in our per-guest data structure. That will let us retrieve the device in the other ioctls so we can call dev_*(). Thanks, Nuno
[PATCH v4 00/15] Introduce /dev/mshv drivers
cpuid() to get all 4 registers instead of 4 calls * Change hv_proximity_domain_info from union to struct for clarity Changes since v1: * Clean up formatting, capitalization in commit messages * Add detail to commit message for patch 15 * Remove errant lines in Makefile and Kconfig in patch 15 * Move a reference to CONFIG_MSHV_VTL from patch 9 to 15 Nuno Das Neves (15): hyperv-tlfs: Change shared HV_REGISTER_* defines to HV_MSR_* mshyperv: Introduce hv_get_hypervisor_version function mshyperv: Introduce numa_node_to_proximity_domain_info asm-generic/mshyperv: Introduce hv_recommend_using_aeoi() hyperv: Move hv_connection_id to hyperv-tlfs hyperv-tlfs: Introduce hv_status_to_string and hv_status_to_errno Drivers: hv: Move hv_call_deposit_pages and hv_call_create_vp to common code Drivers: hv: Introduce per-cpu event ring tail Drivers: hv: Introduce hv_output_arg_exists in hv_common.c x86: hyperv: Add mshv_handler irq handler and setup function Drivers: hv: export vmbus_isr, hv_context and hv_post_message Documentation: Reserve ioctl number for mshv driver uapi: hyperv: Add mshv driver headers defining hypervisor ABIs asm-generic: hyperv: Use new Hyper-V headers conditionally. Drivers: hv: Add modules to expose /dev/mshv to VMMs running on Hyper-V .../userspace-api/ioctl/ioctl-number.rst |2 + arch/arm64/hyperv/mshyperv.c | 23 +- arch/arm64/include/asm/hyperv-tlfs.h | 25 + arch/arm64/include/asm/mshyperv.h |2 +- arch/x86/hyperv/hv_init.c |2 +- arch/x86/hyperv/hv_proc.c | 166 +- arch/x86/include/asm/hyperv-tlfs.h| 137 +- arch/x86/include/asm/mshyperv.h | 12 +- arch/x86/kernel/cpu/mshyperv.c| 67 +- drivers/acpi/numa/srat.c |1 + drivers/clocksource/hyperv_timer.c| 24 +- drivers/hv/Kconfig| 49 + drivers/hv/Makefile | 20 + drivers/hv/hv.c | 50 +- drivers/hv/hv_call.c | 103 + drivers/hv/hv_common.c| 223 +- drivers/hv/hyperv_vmbus.h |2 +- drivers/hv/mshv.h | 125 ++ drivers/hv/mshv_eventfd.c | 761 +++ drivers/hv/mshv_eventfd.h | 80 + drivers/hv/mshv_main.c| 196 ++ drivers/hv/mshv_msi.c | 129 ++ drivers/hv/mshv_portid_table.c| 84 + drivers/hv/mshv_root.h| 232 ++ drivers/hv/mshv_root_hv_call.c| 911 drivers/hv/mshv_root_main.c | 1911 + drivers/hv/mshv_synic.c | 688 ++ drivers/hv/mshv_vtl.h | 52 + drivers/hv/mshv_vtl_main.c| 1522 + drivers/hv/vmbus_drv.c|3 +- drivers/hv/xfer_to_guest.c| 28 + include/asm-generic/hyperv-defs.h | 26 + include/asm-generic/hyperv-tlfs.h | 93 +- include/asm-generic/mshyperv.h| 73 +- include/linux/hyperv.h| 11 +- include/uapi/hyperv/hvgdk.h | 41 + include/uapi/hyperv/hvgdk_mini.h | 1076 ++ include/uapi/hyperv/hvhdk.h | 1342 include/uapi/hyperv/hvhdk_mini.h | 160 ++ include/uapi/linux/mshv.h | 306 +++ 40 files changed, 10394 insertions(+), 364 deletions(-) create mode 100644 drivers/hv/hv_call.c create mode 100644 drivers/hv/mshv.h create mode 100644 drivers/hv/mshv_eventfd.c create mode 100644 drivers/hv/mshv_eventfd.h create mode 100644 drivers/hv/mshv_main.c create mode 100644 drivers/hv/mshv_msi.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 drivers/hv/mshv_vtl.h create mode 100644 drivers/hv/mshv_vtl_main.c create mode 100644 drivers/hv/xfer_to_guest.c create mode 100644 include/asm-generic/hyperv-defs.h create mode 100644 include/uapi/hyperv/hvgdk.h create mode 100644 include/uapi/hyperv/hvgdk_mini.h create mode 100644 include/uapi/hyperv/hvhdk.h create mode 100644 include/uapi/hyperv/hvhdk_mini.h create mode 100644 include/uapi/linux/mshv.h -- 2.25.1
[PATCH v4 05/15] hyperv: Move hv_connection_id to hyperv-tlfs
The definition conflicts with one added in hvgdk.h as part of the mshv driver so must be moved to hyperv-tlfs.h. This structure should be in hyperv-tlfs.h anyway, since it is part of the TLFS document. Signed-off-by: Nuno Das Neves Acked-by: Wei Liu --- include/asm-generic/hyperv-tlfs.h | 9 + include/linux/hyperv.h| 9 - 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/include/asm-generic/hyperv-tlfs.h b/include/asm-generic/hyperv-tlfs.h index a6dffb346bf2..1316584983c1 100644 --- a/include/asm-generic/hyperv-tlfs.h +++ b/include/asm-generic/hyperv-tlfs.h @@ -842,4 +842,13 @@ struct hv_mmio_write_input { u8 data[HV_HYPERCALL_MMIO_MAX_DATA_LENGTH]; } __packed; +/* Define connection identifier type. */ +union hv_connection_id { + u32 asu32; + struct { + u32 id:24; + u32 reserved:8; + } u; +}; + #endif diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index 2b00faf98017..4d5a5e39d76c 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -748,15 +748,6 @@ struct vmbus_close_msg { struct vmbus_channel_close_channel msg; }; -/* Define connection identifier type. */ -union hv_connection_id { - u32 asu32; - struct { - u32 id:24; - u32 reserved:8; - } u; -}; - enum vmbus_device_type { HV_IDE = 0, HV_SCSI, -- 2.25.1
[PATCH v4 03/15] mshyperv: Introduce numa_node_to_proximity_domain_info
Factor out logic for converting numa node to proximity domain info into a helper function, and export it. Change hv_proximity_domain_info to a struct to simplify the code. Signed-off-by: Nuno Das Neves Reviewed-by: Wei Liu --- arch/x86/hyperv/hv_proc.c | 8 ++-- drivers/acpi/numa/srat.c | 1 + include/asm-generic/hyperv-tlfs.h | 14 +- include/asm-generic/mshyperv.h| 15 +++ 4 files changed, 23 insertions(+), 15 deletions(-) diff --git a/arch/x86/hyperv/hv_proc.c b/arch/x86/hyperv/hv_proc.c index 68a0843d4750..5ba5ca1b2089 100644 --- a/arch/x86/hyperv/hv_proc.c +++ b/arch/x86/hyperv/hv_proc.c @@ -121,7 +121,6 @@ int hv_call_add_logical_proc(int node, u32 lp_index, u32 apic_id) u64 status; unsigned long flags; int ret = HV_STATUS_SUCCESS; - int pxm = node_to_pxm(node); /* * When adding a logical processor, the hypervisor may return @@ -137,11 +136,8 @@ int hv_call_add_logical_proc(int node, u32 lp_index, u32 apic_id) input->lp_index = lp_index; input->apic_id = apic_id; - input->flags = 0; - input->proximity_domain_info.domain_id = pxm; - input->proximity_domain_info.flags.reserved = 0; - input->proximity_domain_info.flags.proximity_info_valid = 1; - input->proximity_domain_info.flags.proximity_preferred = 1; + input->proximity_domain_info = + numa_node_to_proximity_domain_info(node); status = hv_do_hypercall(HVCALL_ADD_LOGICAL_PROCESSOR, input, output); local_irq_restore(flags); diff --git a/drivers/acpi/numa/srat.c b/drivers/acpi/numa/srat.c index 1f4fc5f8a819..0cf9f0574495 100644 --- a/drivers/acpi/numa/srat.c +++ b/drivers/acpi/numa/srat.c @@ -48,6 +48,7 @@ int node_to_pxm(int node) return PXM_INVAL; return node_to_pxm_map[node]; } +EXPORT_SYMBOL(node_to_pxm); static void __acpi_map_pxm_to_node(int pxm, int node) { diff --git a/include/asm-generic/hyperv-tlfs.h b/include/asm-generic/hyperv-tlfs.h index f63b3704d89e..a6dffb346bf2 100644 --- a/include/asm-generic/hyperv-tlfs.h +++ b/include/asm-generic/hyperv-tlfs.h @@ -512,13 +512,9 @@ struct hv_proximity_domain_flags { u32 proximity_info_valid : 1; } __packed; -/* Not a union in windows but useful for zeroing */ -union hv_proximity_domain_info { - struct { - u32 domain_id; - struct hv_proximity_domain_flags flags; - }; - u64 as_uint64; +struct hv_proximity_domain_info { + u32 domain_id; + struct hv_proximity_domain_flags flags; } __packed; struct hv_lp_startup_status { @@ -535,7 +531,7 @@ struct hv_lp_startup_status { struct hv_add_logical_processor_in { u32 lp_index; u32 apic_id; - union hv_proximity_domain_info proximity_domain_info; + struct hv_proximity_domain_info proximity_domain_info; u64 flags; } __packed; @@ -560,7 +556,7 @@ struct hv_create_vp { u8 padding[3]; u8 subnode_type; u64 subnode_id; - union hv_proximity_domain_info proximity_domain_info; + struct hv_proximity_domain_info proximity_domain_info; u64 flags; } __packed; diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h index 9f2c06c9d5d1..8cc7b0e316d7 100644 --- a/include/asm-generic/mshyperv.h +++ b/include/asm-generic/mshyperv.h @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -28,6 +29,20 @@ #define VTPM_BASE_ADDRESS 0xfed4 +static inline struct hv_proximity_domain_info +numa_node_to_proximity_domain_info(int node) +{ + struct hv_proximity_domain_info proximity_domain_info = {}; + + if (node != NUMA_NO_NODE) { + proximity_domain_info.domain_id = node_to_pxm(node); + proximity_domain_info.flags.proximity_info_valid = 1; + proximity_domain_info.flags.proximity_preferred = 1; + } + + return proximity_domain_info; +} + struct ms_hyperv_info { u32 features; u32 priv_high; -- 2.25.1
[PATCH v4 08/15] Drivers: hv: Introduce per-cpu event ring tail
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 Reviewed-by: Wei Liu --- drivers/hv/hv_common.c | 28 ++-- include/asm-generic/mshyperv.h | 2 ++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c index 9d9f6f90f99e..39077841d518 100644 --- a/drivers/hv/hv_common.c +++ b/drivers/hv/hv_common.c @@ -62,6 +62,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 @@ -84,6 +94,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; } /* @@ -333,6 +346,8 @@ int __init hv_common_init(void) if (hv_root_partition) { hyperv_pcpu_output_arg = alloc_percpu(void *); BUG_ON(!hyperv_pcpu_output_arg); + hv_synic_eventring_tail = alloc_percpu(u8 *); + BUG_ON(hv_synic_eventring_tail == NULL); } hv_vp_index = kmalloc_array(num_possible_cpus(), sizeof(*hv_vp_index), @@ -357,6 +372,7 @@ int __init hv_common_init(void) int hv_common_cpu_init(unsigned int cpu) { void **inputarg, **outputarg; + u8 **synic_eventring_tail; u64 msr_vp_index; gfp_t flags; int pgcount = hv_root_partition ? 2 : 1; @@ -369,8 +385,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); @@ -380,6 +396,14 @@ int hv_common_cpu_init(unsigned int cpu) if (hv_root_partition) { outputarg = (void **)this_cpu_ptr(hyperv_pcpu_output_arg); *outputarg = (char *)mem + HV_HYP_PAGE_SIZE; + synic_eventring_tail = (u8 **)this_cpu_ptr(hv_synic_eventring_tail); + *synic_eventring_tail = kcalloc(HV_SYNIC_SINT_COUNT, sizeof(u8), + flags); + + if (unlikely(!*synic_eventring_tail)) { + kfree(mem); + return -ENOMEM; + } } if (!ms_hyperv.paravisor_present && diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h index 4f2bb6099063..4e49fd662b2b 100644 --- a/include/asm-generic/mshyperv.h +++ b/include/asm-generic/mshyperv.h @@ -77,6 +77,8 @@ extern bool hv_nested; extern void * __percpu *hyperv_pcpu_input_arg; extern void * __percpu *hyperv_pcpu_output_arg; +extern u8 __percpu **hv_synic_eventring_tail; + extern u64 hv_do_hypercall(u64 control, void *inputaddr, void *outputaddr); extern u64 hv_do_fast_hypercall8(u16 control, u64 input8); bool hv_isolation_type_snp(void); -- 2.25.1
[PATCH v4 11/15] Drivers: hv: export vmbus_isr, hv_context and hv_post_message
These will be used by the mshv_vtl driver. Signed-off-by: Nuno Das Neves Acked-by: Wei Liu --- drivers/hv/hv.c | 2 ++ drivers/hv/hyperv_vmbus.h | 1 + drivers/hv/vmbus_drv.c| 3 ++- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c index d7869205dcbe..c60a4fb55f3c 100644 --- a/drivers/hv/hv.c +++ b/drivers/hv/hv.c @@ -25,6 +25,7 @@ /* The one and only */ struct hv_context hv_context; +EXPORT_SYMBOL_GPL(hv_context); /* * hv_init - Main initialization routine. @@ -93,6 +94,7 @@ int hv_post_message(union hv_connection_id connection_id, return hv_result(status); } +EXPORT_SYMBOL_GPL(hv_post_message); int hv_synic_alloc(void) { diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h index f6b1e710f805..09792eb4ffed 100644 --- a/drivers/hv/hyperv_vmbus.h +++ b/drivers/hv/hyperv_vmbus.h @@ -32,6 +32,7 @@ */ #define HV_UTIL_NEGO_TIMEOUT 55 +void vmbus_isr(void); /* Definitions for the monitored notification facility */ union hv_monitor_trigger_group { diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index edbb38f6956b..6d27597af8bf 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -1286,7 +1286,7 @@ static void vmbus_chan_sched(struct hv_per_cpu_context *hv_cpu) } } -static void vmbus_isr(void) +void vmbus_isr(void) { struct hv_per_cpu_context *hv_cpu = this_cpu_ptr(hv_context.cpu_context); @@ -1309,6 +1309,7 @@ static void vmbus_isr(void) add_interrupt_randomness(vmbus_interrupt); } +EXPORT_SYMBOL_GPL(vmbus_isr); static irqreturn_t vmbus_percpu_isr(int irq, void *dev_id) { -- 2.25.1
[PATCH v4 04/15] asm-generic/mshyperv: Introduce hv_recommend_using_aeoi()
Factor out logic for determining if we should set the auto eoi flag in SINT register. Signed-off-by: Nuno Das Neves Reviewed-by: Wei Liu --- 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 5ea104c61fa7..d7869205dcbe 100644 --- a/drivers/hv/hv.c +++ b/drivers/hv/hv.c @@ -315,17 +315,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_register(HV_MSR_SINT0 + VMBUS_MESSAGE_SINT, shared_sint.as_uint64); diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h index 8cc7b0e316d7..3e715aa114da 100644 --- a/include/asm-generic/mshyperv.h +++ b/include/asm-generic/mshyperv.h @@ -82,6 +82,19 @@ extern u64 hv_do_fast_hypercall8(u16 control, u64 input8); 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 +} + /* Helper functions that provide a consistent pattern for checking Hyper-V hypercall status. */ static inline int hv_result(u64 status) { -- 2.25.1
[PATCH v4 07/15] Drivers: hv: Move hv_call_deposit_pages and hv_call_create_vp to common code
These hypercalls are not arch-specific. Move them to common code. Signed-off-by: Nuno Das Neves Acked-by: Wei Liu --- arch/x86/hyperv/hv_proc.c | 152 arch/x86/include/asm/mshyperv.h | 1 - drivers/hv/hv_common.c | 147 ++ include/asm-generic/mshyperv.h | 2 + 4 files changed, 149 insertions(+), 153 deletions(-) diff --git a/arch/x86/hyperv/hv_proc.c b/arch/x86/hyperv/hv_proc.c index ed80da64649e..0a35cb865427 100644 --- a/arch/x86/hyperv/hv_proc.c +++ b/arch/x86/hyperv/hv_proc.c @@ -3,7 +3,6 @@ #include #include #include -#include #include #include #include @@ -14,106 +13,6 @@ #include -/* - * See struct hv_deposit_memory. The first u64 is partition ID, the rest - * are GPAs. - */ -#define HV_DEPOSIT_MAX (HV_HYP_PAGE_SIZE / sizeof(u64) - 1) - -/* Deposits exact number of pages. Must be called with interrupts enabled. */ -int hv_call_deposit_pages(int node, u64 partition_id, u32 num_pages) -{ - struct page **pages, *page; - int *counts; - int num_allocations; - int i, j, page_count; - int order; - u64 status; - int ret; - u64 base_pfn; - struct hv_deposit_memory *input_page; - unsigned long flags; - - if (num_pages > HV_DEPOSIT_MAX) - return -E2BIG; - if (!num_pages) - return 0; - - /* One buffer for page pointers and counts */ - page = alloc_page(GFP_KERNEL); - if (!page) - return -ENOMEM; - pages = page_address(page); - - counts = kcalloc(HV_DEPOSIT_MAX, sizeof(int), GFP_KERNEL); - if (!counts) { - free_page((unsigned long)pages); - return -ENOMEM; - } - - /* Allocate all the pages before disabling interrupts */ - i = 0; - - while (num_pages) { - /* Find highest order we can actually allocate */ - order = 31 - __builtin_clz(num_pages); - - while (1) { - pages[i] = alloc_pages_node(node, GFP_KERNEL, order); - if (pages[i]) - break; - if (!order) { - ret = -ENOMEM; - num_allocations = i; - goto err_free_allocations; - } - --order; - } - - split_page(pages[i], order); - counts[i] = 1 << order; - num_pages -= counts[i]; - i++; - } - num_allocations = i; - - local_irq_save(flags); - - input_page = *this_cpu_ptr(hyperv_pcpu_input_arg); - - input_page->partition_id = partition_id; - - /* Populate gpa_page_list - these will fit on the input page */ - for (i = 0, page_count = 0; i < num_allocations; ++i) { - base_pfn = page_to_pfn(pages[i]); - for (j = 0; j < counts[i]; ++j, ++page_count) - input_page->gpa_page_list[page_count] = base_pfn + j; - } - status = hv_do_rep_hypercall(HVCALL_DEPOSIT_MEMORY, -page_count, 0, input_page, NULL); - local_irq_restore(flags); - if (!hv_result_success(status)) { - pr_err("Failed to deposit pages: %lld\n", status); - ret = hv_result(status); - goto err_free_allocations; - } - - ret = 0; - goto free_buf; - -err_free_allocations: - for (i = 0; i < num_allocations; ++i) { - base_pfn = page_to_pfn(pages[i]); - for (j = 0; j < counts[i]; ++j) - __free_page(pfn_to_page(base_pfn + j)); - } - -free_buf: - free_page((unsigned long)pages); - kfree(counts); - return ret; -} - int hv_call_add_logical_proc(int node, u32 lp_index, u32 apic_id) { struct hv_add_logical_processor_in *input; @@ -156,54 +55,3 @@ int hv_call_add_logical_proc(int node, u32 lp_index, u32 apic_id) return ret; } -int hv_call_create_vp(int node, u64 partition_id, u32 vp_index, u32 flags) -{ - struct hv_create_vp *input; - u64 status; - unsigned long irq_flags; - int ret = HV_STATUS_SUCCESS; - int pxm = node_to_pxm(node); - - /* Root VPs don't seem to need pages deposited */ - if (partition_id != hv_current_partition_id) { - /* The value 90 is empirically determined. It may change. */ - ret = hv_call_deposit_pages(node, partition_id, 90); - if (ret) - return ret; - } - - do { - local_irq_save(irq_flags); - - input = *this_cpu_ptr(hyperv_pcpu_input_arg); - - input->partition_id = partition_id; - input->vp_index = vp_index; - input->
[PATCH v4 01/15] hyperv-tlfs: Change shared HV_REGISTER_* defines to HV_MSR_*
In x86 hyperv-tlfs, HV_REGISTER_ prefix is used to indicate MSRs accessed via rdmsrl/wrmsrl. But in ARM64, HV_REGISTER_ instead indicates VP registers accessed via get/set vp registers hypercall. This is due to HV_REGISTER_* names being used by hv_set/get_register, with the arch-specific version delegating to the appropriate mechanism. The problem is, using prefix HV_REGISTER_ for MSRs will conflict with VP registers when they are introduced for x86 in future. This patch solves the issue by: 1. Defining all the x86 MSRs with a consistent prefix: HV_X64_MSR_. This is so HV_REGISTER_ can be reserved for VP registers. 2. Change the non-arch-specific alias used by hv_set/get_register to HV_MSR_. This is also happens to be the same name Hyper-V uses for this purpose. Signed-off-by: Nuno Das Neves Reviewed-by: Wei Liu --- arch/arm64/include/asm/hyperv-tlfs.h | 25 + arch/x86/include/asm/hyperv-tlfs.h | 137 +-- arch/x86/include/asm/mshyperv.h | 8 +- arch/x86/kernel/cpu/mshyperv.c | 22 ++--- drivers/clocksource/hyperv_timer.c | 24 ++--- drivers/hv/hv.c | 36 +++ drivers/hv/hv_common.c | 18 ++-- include/asm-generic/mshyperv.h | 2 +- 8 files changed, 148 insertions(+), 124 deletions(-) diff --git a/arch/arm64/include/asm/hyperv-tlfs.h b/arch/arm64/include/asm/hyperv-tlfs.h index bc6c7ac934a1..a6e852c2fc3a 100644 --- a/arch/arm64/include/asm/hyperv-tlfs.h +++ b/arch/arm64/include/asm/hyperv-tlfs.h @@ -64,6 +64,31 @@ #define HV_REGISTER_STIMER0_CONFIG 0x000B #define HV_REGISTER_STIMER0_COUNT 0x000B0001 +/* + * To support non-arch-specific code calling hv_set/get_register: + * - On x86, HV_MSR_ indicates an MSR accessed via rdmsrl/wrmsrl + * - On ARM, HV_MSR_ indicates a VP register accessed via hypercall + */ +#define HV_MSR_VP_INDEX(HV_REGISTER_VP_INDEX) +#define HV_MSR_TIME_REF_COUNT (HV_REGISTER_TIME_REF_COUNT) +#define HV_MSR_REFERENCE_TS(HV_REGISTER_REFERENCE_TSC) + +#define HV_MSR_STIMER0_CONFIG (HV_REGISTER_STIMER0_CONFIG) +#define HV_MSR_STIMER0_COUNT (HV_REGISTER_STIMER0_COUNT) + +#define HV_MSR_SCONTROL(HV_REGISTER_SCONTROL) +#define HV_MSR_SIEFP (HV_REGISTER_SIEFP) +#define HV_MSR_SIMP(HV_REGISTER_SIMP) +#define HV_MSR_EOM (HV_REGISTER_EOM) +#define HV_MSR_SINT0 (HV_REGISTER_SINT0) + +#define HV_MSR_CRASH_P0(HV_REGISTER_CRASH_P0) +#define HV_MSR_CRASH_P1(HV_REGISTER_CRASH_P1) +#define HV_MSR_CRASH_P2(HV_REGISTER_CRASH_P2) +#define HV_MSR_CRASH_P3(HV_REGISTER_CRASH_P3) +#define HV_MSR_CRASH_P4(HV_REGISTER_CRASH_P4) +#define HV_MSR_CRASH_CTL (HV_REGISTER_CRASH_CTL) + union hv_msi_entry { u64 as_uint64[2]; struct { diff --git a/arch/x86/include/asm/hyperv-tlfs.h b/arch/x86/include/asm/hyperv-tlfs.h index 2ff26f53cd62..058c5c8dc382 100644 --- a/arch/x86/include/asm/hyperv-tlfs.h +++ b/arch/x86/include/asm/hyperv-tlfs.h @@ -182,7 +182,7 @@ enum hv_isolation_type { #define HV_X64_MSR_HYPERCALL 0x4001 /* MSR used to provide vcpu index */ -#define HV_REGISTER_VP_INDEX 0x4002 +#define HV_X64_MSR_VP_INDEX0x4002 /* MSR used to reset the guest OS. */ #define HV_X64_MSR_RESET 0x4003 @@ -191,10 +191,10 @@ enum hv_isolation_type { #define HV_X64_MSR_VP_RUNTIME 0x4010 /* MSR used to read the per-partition time reference counter */ -#define HV_REGISTER_TIME_REF_COUNT 0x4020 +#define HV_X64_MSR_TIME_REF_COUNT 0x4020 /* A partition's reference time stamp counter (TSC) page */ -#define HV_REGISTER_REFERENCE_TSC 0x4021 +#define HV_X64_MSR_REFERENCE_TSC 0x4021 /* MSR used to retrieve the TSC frequency */ #define HV_X64_MSR_TSC_FREQUENCY 0x4022 @@ -209,61 +209,61 @@ enum hv_isolation_type { #define HV_X64_MSR_VP_ASSIST_PAGE 0x4073 /* Define synthetic interrupt controller model specific registers. */ -#define HV_REGISTER_SCONTROL 0x4080 -#define HV_REGISTER_SVERSION 0x4081 -#define HV_REGISTER_SIEFP 0x4082 -#define HV_REGISTER_SIMP 0x4083 -#define HV_REGISTER_EOM0x4084 -#define HV_REGISTER_SINT0 0x4090 -#define HV_REGISTER_SINT1 0x4091 -#define HV_REGISTER_SINT2 0x4092 -#define HV_REGISTER_SINT3 0x4093 -#define HV_REGISTER_SINT4 0x4094 -#define HV_REGISTER_SINT5 0x4095 -#define HV_REGISTER_SINT6 0x4096 -#define HV_REGISTER_SINT7 0x4097 -#d
[PATCH v4 10/15] x86: hyperv: Add mshv_handler irq handler and setup function
This will handle SYNIC interrupts such as intercepts, doorbells, and scheduling messages intended for the mshv driver. Signed-off-by: Nuno Das Neves Reviewed-by: Wei Liu Reviewed-by: Tianyu Lan --- arch/x86/kernel/cpu/mshyperv.c | 9 + drivers/hv/hv_common.c | 5 + include/asm-generic/mshyperv.h | 2 ++ 3 files changed, 16 insertions(+) diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c index 9b898b65a013..06f79963add5 100644 --- a/arch/x86/kernel/cpu/mshyperv.c +++ b/arch/x86/kernel/cpu/mshyperv.c @@ -110,6 +110,7 @@ void hv_set_register(unsigned int reg, u64 value) } EXPORT_SYMBOL_GPL(hv_set_register); +static void (*mshv_handler)(void); static void (*vmbus_handler)(void); static void (*hv_stimer0_handler)(void); static void (*hv_kexec_handler)(void); @@ -120,6 +121,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(); @@ -129,6 +133,11 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_hyperv_callback) set_irq_regs(old_regs); } +void hv_setup_mshv_irq(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 3f6f23e4c579..6ec63502d83d 100644 --- a/drivers/hv/hv_common.c +++ b/drivers/hv/hv_common.c @@ -585,6 +585,11 @@ void __weak hv_remove_vmbus_handler(void) } EXPORT_SYMBOL_GPL(hv_remove_vmbus_handler); +void __weak hv_setup_mshv_irq(void (*handler)(void)) +{ +} +EXPORT_SYMBOL_GPL(hv_setup_mshv_irq); + void __weak hv_setup_kexec_handler(void (*handler)(void)) { } diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h index 4e49fd662b2b..d832852d0ee7 100644 --- a/include/asm-generic/mshyperv.h +++ b/include/asm-generic/mshyperv.h @@ -198,6 +198,8 @@ void hv_remove_vmbus_handler(void); void hv_setup_stimer0_handler(void (*handler)(void)); void hv_remove_stimer0_handler(void); +void hv_setup_mshv_irq(void (*handler)(void)); + 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)); -- 2.25.1
[PATCH v4 14/15] asm-generic: hyperv: Use new Hyper-V headers conditionally.
Add asm-generic/hyperv-defs.h. It includes hyperv-tlfs.h or hvhdk.h depending on compile-time constant HV_HYPERV_DEFS which will be defined in the mshv driver. This is needed to keep unstable Hyper-V interfaces independent of hyperv-tlfs.h. This ensures hvhdk.h replaces hyperv-tlfs.h in the mshv driver, even via indirect includes. Signed-off-by: Nuno Das Neves Acked-by: Wei Liu --- arch/arm64/include/asm/mshyperv.h | 2 +- arch/x86/include/asm/mshyperv.h | 3 +-- drivers/hv/hyperv_vmbus.h | 1 - include/asm-generic/hyperv-defs.h | 26 ++ include/asm-generic/mshyperv.h| 2 +- include/linux/hyperv.h| 2 +- 6 files changed, 30 insertions(+), 6 deletions(-) create mode 100644 include/asm-generic/hyperv-defs.h diff --git a/arch/arm64/include/asm/mshyperv.h b/arch/arm64/include/asm/mshyperv.h index 20070a847304..8ec14caf3d4f 100644 --- a/arch/arm64/include/asm/mshyperv.h +++ b/arch/arm64/include/asm/mshyperv.h @@ -20,7 +20,7 @@ #include #include -#include +#include /* * Declare calls to get and set Hyper-V VP register values on ARM64, which diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h index e3768d787065..bb1b97106cd3 100644 --- a/arch/x86/include/asm/mshyperv.h +++ b/arch/x86/include/asm/mshyperv.h @@ -6,10 +6,9 @@ #include #include #include -#include #include #include -#include +#include /* * Hyper-V always provides a single IO-APIC at this MMIO address. diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h index 09792eb4ffed..0e4bc18a13fa 100644 --- a/drivers/hv/hyperv_vmbus.h +++ b/drivers/hv/hyperv_vmbus.h @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include diff --git a/include/asm-generic/hyperv-defs.h b/include/asm-generic/hyperv-defs.h new file mode 100644 index ..ac6fcba35c8c --- /dev/null +++ b/include/asm-generic/hyperv-defs.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_GENERIC_HYPERV_DEFS_H +#define _ASM_GENERIC_HYPERV_DEFS_H + +/* + * There are cases where Microsoft Hypervisor ABIs are needed which may not be + * stable or present in the Hyper-V TLFS document. E.g. the mshv_root driver. + * + * As these interfaces are unstable and may differ from hyperv-tlfs.h, they + * must be kept separate and independent. + * + * However, code from files that depend on hyperv-tlfs.h (such as mshyperv.h) + * is still needed, so work around the issue by conditionally including the + * correct definitions. + * + * Note: Since they are independent of each other, there are many definitions + * duplicated in both hyperv-tlfs.h and uapi/hyperv/hv*.h files. + */ +#ifdef HV_HYPERV_DEFS +#include +#else +#include +#endif + +#endif /* _ASM_GENERIC_HYPERV_DEFS_H */ + diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h index d832852d0ee7..6bef0d59d1b7 100644 --- a/include/asm-generic/mshyperv.h +++ b/include/asm-generic/mshyperv.h @@ -25,7 +25,7 @@ #include #include #include -#include +#include #define VTPM_BASE_ADDRESS 0xfed4 diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index 4d5a5e39d76c..722a8cf23d87 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -24,7 +24,7 @@ #include #include #include -#include +#include #define MAX_PAGE_BUFFER_COUNT 32 #define MAX_MULTIPAGE_BUFFER_COUNT 32 /* 128K */ -- 2.25.1
[PATCH v4 02/15] mshyperv: Introduce hv_get_hypervisor_version function
x86_64 and arm64 implementations to get the hypervisor version information. Store these in hv_hypervisor_version_info structure to simplify parsing the fields. Replace the existing parsing when printing the version numbers at boot. Signed-off-by: Nuno Das Neves Acked-by: Wei Liu --- arch/arm64/hyperv/mshyperv.c | 23 +--- arch/x86/kernel/cpu/mshyperv.c| 36 +++ include/asm-generic/hyperv-tlfs.h | 23 include/asm-generic/mshyperv.h| 2 ++ 4 files changed, 62 insertions(+), 22 deletions(-) diff --git a/arch/arm64/hyperv/mshyperv.c b/arch/arm64/hyperv/mshyperv.c index f1b8a04ee9f2..53bdd3bc81ac 100644 --- a/arch/arm64/hyperv/mshyperv.c +++ b/arch/arm64/hyperv/mshyperv.c @@ -19,10 +19,19 @@ static bool hyperv_initialized; +int hv_get_hypervisor_version(union hv_hypervisor_version_info *info) +{ + hv_get_vpreg_128(HV_REGISTER_HYPERVISOR_VERSION, +(struct hv_get_vp_registers_output *)info); + + return 0; +} +EXPORT_SYMBOL_GPL(hv_get_hypervisor_version); + static int __init hyperv_init(void) { - struct hv_get_vp_registers_output result; - u32 a, b, c, d; + struct hv_get_vp_registers_output result; + union hv_hypervisor_version_info version; u64 guest_id; int ret; @@ -55,13 +64,11 @@ static int __init hyperv_init(void) ms_hyperv.misc_features); /* Get information about the Hyper-V host version */ - hv_get_vpreg_128(HV_REGISTER_HYPERVISOR_VERSION, &result); - a = result.as32.a; - b = result.as32.b; - c = result.as32.c; - d = result.as32.d; + hv_get_hypervisor_version(&version); pr_info("Hyper-V: Host Build %d.%d.%d.%d-%d-%d\n", - b >> 16, b & 0x, a, d & 0xFF, c, d >> 24); + version.major_version, version.minor_version, + version.build_number, version.service_number, + version.service_pack, version.service_branch); ret = hv_common_init(); if (ret) diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c index d85a8e2a10c9..9b898b65a013 100644 --- a/arch/x86/kernel/cpu/mshyperv.c +++ b/arch/x86/kernel/cpu/mshyperv.c @@ -347,13 +347,26 @@ static void __init reduced_hw_init(void) x86_init.irqs.pre_vector_init = x86_init_noop; } +int hv_get_hypervisor_version(union hv_hypervisor_version_info *info) +{ + unsigned int hv_max_functions; + + hv_max_functions = cpuid_eax(HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS); + if (hv_max_functions < HYPERV_CPUID_VERSION) { + pr_err("%s: Could not detect Hyper-V version\n", __func__); + return -ENODEV; + } + + cpuid(HYPERV_CPUID_VERSION, &info->eax, &info->ebx, &info->ecx, &info->edx); + + return 0; +} +EXPORT_SYMBOL_GPL(hv_get_hypervisor_version); + static void __init ms_hyperv_init_platform(void) { int hv_max_functions_eax; - int hv_host_info_eax; - int hv_host_info_ebx; - int hv_host_info_ecx; - int hv_host_info_edx; + union hv_hypervisor_version_info version; #ifdef CONFIG_PARAVIRT pv_info.name = "Hyper-V"; @@ -407,16 +420,11 @@ static void __init ms_hyperv_init_platform(void) /* * Extract host information. */ - if (hv_max_functions_eax >= HYPERV_CPUID_VERSION) { - hv_host_info_eax = cpuid_eax(HYPERV_CPUID_VERSION); - hv_host_info_ebx = cpuid_ebx(HYPERV_CPUID_VERSION); - hv_host_info_ecx = cpuid_ecx(HYPERV_CPUID_VERSION); - hv_host_info_edx = cpuid_edx(HYPERV_CPUID_VERSION); - - pr_info("Hyper-V: Host Build %d.%d.%d.%d-%d-%d\n", - hv_host_info_ebx >> 16, hv_host_info_ebx & 0x, - hv_host_info_eax, hv_host_info_edx & 0xFF, - hv_host_info_ecx, hv_host_info_edx >> 24); + if (hv_get_hypervisor_version(&version) == 0) { + pr_info("Hyper-V Host Build:%d-%d.%d-%d-%d.%d\n", + version.build_number, version.major_version, + version.minor_version, version.service_pack, + version.service_branch, version.service_number); } if (ms_hyperv.features & HV_ACCESS_FREQUENCY_MSRS && diff --git a/include/asm-generic/hyperv-tlfs.h b/include/asm-generic/hyperv-tlfs.h index fdac4a1714ec..f63b3704d89e 100644 --- a/include/asm-generic/hyperv-tlfs.h +++ b/include/asm-generic/hyperv-tlfs.h @@ -787,6 +787,29 @@ struct hv_input_unmap_device_interrupt { #define HV_SOURCE_SHADOW_NONE 0x0 #define HV_SOURCE_SHADOW_BRIDGE_BUS_RANGE 0x1 +/* + * Version info reported by hypervisor + */ +union hv_hype
[PATCH v4 12/15] Documentation: Reserve ioctl number for mshv driver
Signed-off-by: Nuno Das Neves Acked-by: Jonathan Corbet Acked-by: Wei Liu --- Documentation/userspace-api/ioctl/ioctl-number.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/userspace-api/ioctl/ioctl-number.rst b/Documentation/userspace-api/ioctl/ioctl-number.rst index 4ea5b837399a..71e6d23070ca 100644 --- a/Documentation/userspace-api/ioctl/ioctl-number.rst +++ b/Documentation/userspace-api/ioctl/ioctl-number.rst @@ -355,6 +355,8 @@ Code Seq#Include File Comments 0xB6 alllinux/fpga-dfl.h 0xB7 alluapi/linux/remoteproc_cdev.h <mailto:linux-remotep...@vger.kernel.org> 0xB7 alluapi/linux/nsfs.h <mailto:Andrei Vagin > +0xB8 alluapi/linux/mshv.h Microsoft Hypervisor VM management APIs + <mailto:linux-hyperv@vger.kernel.org> 0xC0 00-0F linux/usb/iowarrior.h 0xCA 00-0F uapi/misc/cxl.h 0xCA 10-2F uapi/misc/ocxl.h -- 2.25.1
[PATCH v4 09/15] Drivers: hv: Introduce hv_output_arg_exists in hv_common.c
This is a more flexible approach for determining whether to allocate the output page. Signed-off-by: Nuno Das Neves Acked-by: Wei Liu --- drivers/hv/hv_common.c | 21 + 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c index 39077841d518..3f6f23e4c579 100644 --- a/drivers/hv/hv_common.c +++ b/drivers/hv/hv_common.c @@ -58,6 +58,14 @@ EXPORT_SYMBOL_GPL(hyperv_pcpu_input_arg); void * __percpu *hyperv_pcpu_output_arg; EXPORT_SYMBOL_GPL(hyperv_pcpu_output_arg); +/* + * Determine whether output arg is needed + */ +static inline bool hv_output_arg_exists(void) +{ + return hv_root_partition ? true : false; +} + static void hv_kmsg_dump_unregister(void); static struct ctl_table_header *hv_ctl_table_hdr; @@ -342,10 +350,12 @@ int __init hv_common_init(void) hyperv_pcpu_input_arg = alloc_percpu(void *); BUG_ON(!hyperv_pcpu_input_arg); - /* Allocate the per-CPU state for output arg for root */ - if (hv_root_partition) { + if (hv_output_arg_exists()) { hyperv_pcpu_output_arg = alloc_percpu(void *); BUG_ON(!hyperv_pcpu_output_arg); + } + + if (hv_root_partition) { hv_synic_eventring_tail = alloc_percpu(u8 *); BUG_ON(hv_synic_eventring_tail == NULL); } @@ -375,7 +385,7 @@ int hv_common_cpu_init(unsigned int cpu) u8 **synic_eventring_tail; u64 msr_vp_index; gfp_t flags; - int pgcount = hv_root_partition ? 2 : 1; + int pgcount = hv_output_arg_exists() ? 2 : 1; void *mem; int ret; @@ -393,9 +403,12 @@ int hv_common_cpu_init(unsigned int cpu) if (!mem) return -ENOMEM; - if (hv_root_partition) { + if (hv_output_arg_exists()) { outputarg = (void **)this_cpu_ptr(hyperv_pcpu_output_arg); *outputarg = (char *)mem + HV_HYP_PAGE_SIZE; + } + + 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); -- 2.25.1
[PATCH v4 06/15] hyperv-tlfs: Introduce hv_status_to_string and hv_status_to_errno
hv_status_to_errno translates hyperv statuses to linux error codes. This is useful for returning something linux-friendly from a hypercall helper function. hv_status_to_string improves clarity of error messages. Signed-off-by: Nuno Das Neves Acked-by: Wei Liu --- arch/x86/hyperv/hv_init.c | 2 +- arch/x86/hyperv/hv_proc.c | 6 ++-- include/asm-generic/hyperv-tlfs.h | 47 ++- include/asm-generic/mshyperv.h| 33 ++ 4 files changed, 71 insertions(+), 17 deletions(-) diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c index 783ed339f341..515ca168748d 100644 --- a/arch/x86/hyperv/hv_init.c +++ b/arch/x86/hyperv/hv_init.c @@ -387,7 +387,7 @@ static void __init hv_get_partition_id(void) status = hv_do_hypercall(HVCALL_GET_PARTITION_ID, NULL, output_page); if (!hv_result_success(status)) { /* No point in proceeding if this failed */ - pr_err("Failed to get partition ID: %lld\n", status); + pr_err("Failed to get partition ID: %s\n", hv_status_to_string(status)); BUG(); } hv_current_partition_id = output_page->partition_id; diff --git a/arch/x86/hyperv/hv_proc.c b/arch/x86/hyperv/hv_proc.c index 5ba5ca1b2089..ed80da64649e 100644 --- a/arch/x86/hyperv/hv_proc.c +++ b/arch/x86/hyperv/hv_proc.c @@ -144,9 +144,9 @@ 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); - ret = hv_result(status); + pr_err("%s: cpu %u apic ID %u, %s\n", __func__, + lp_index, apic_id, hv_status_to_string(status)); + ret = hv_status_to_errno(status); } break; } diff --git a/include/asm-generic/hyperv-tlfs.h b/include/asm-generic/hyperv-tlfs.h index 1316584983c1..8d76661a8c9f 100644 --- a/include/asm-generic/hyperv-tlfs.h +++ b/include/asm-generic/hyperv-tlfs.h @@ -212,19 +212,40 @@ enum HV_GENERIC_SET_FORMAT { HV_HYPERCALL_RSVD2_MASK) /* hypercall status code */ -#define HV_STATUS_SUCCESS 0 -#define HV_STATUS_INVALID_HYPERCALL_CODE 2 -#define HV_STATUS_INVALID_HYPERCALL_INPUT 3 -#define HV_STATUS_INVALID_ALIGNMENT4 -#define HV_STATUS_INVALID_PARAMETER5 -#define HV_STATUS_ACCESS_DENIED6 -#define HV_STATUS_OPERATION_DENIED 8 -#define HV_STATUS_INSUFFICIENT_MEMORY 11 -#define HV_STATUS_INVALID_PORT_ID 17 -#define HV_STATUS_INVALID_CONNECTION_ID18 -#define HV_STATUS_INSUFFICIENT_BUFFERS 19 -#define HV_STATUS_TIME_OUT 120 -#define HV_STATUS_VTL_ALREADY_ENABLED 134 +#define __HV_STATUS_DEF(OP) \ + OP(HV_STATUS_SUCCESS, 0x0) \ + OP(HV_STATUS_INVALID_HYPERCALL_CODE,0x2) \ + OP(HV_STATUS_INVALID_HYPERCALL_INPUT, 0x3) \ + OP(HV_STATUS_INVALID_ALIGNMENT, 0x4) \ + OP(HV_STATUS_INVALID_PARAMETER, 0x5) \ + OP(HV_STATUS_ACCESS_DENIED, 0x6) \ + OP(HV_STATUS_INVALID_PARTITION_STATE, 0x7) \ + OP(HV_STATUS_OPERATION_DENIED, 0x8) \ + OP(HV_STATUS_UNKNOWN_PROPERTY, 0x9) \ + OP(HV_STATUS_PROPERTY_VALUE_OUT_OF_RANGE, 0xA) \ + OP(HV_STATUS_INSUFFICIENT_MEMORY, 0xB) \ + OP(HV_STATUS_INVALID_PARTITION_ID, 0xD) \ + OP(HV_STATUS_INVALID_VP_INDEX, 0xE) \ + OP(HV_STATUS_NOT_FOUND, 0x10) \ + OP(HV_STATUS_INVALID_PORT_ID, 0x11) \ + OP(HV_STATUS_INVALID_CONNECTION_ID, 0x12) \ + OP(HV_STATUS_INSUFFICIENT_BUFFERS, 0x13) \ + OP(HV_STATUS_NOT_ACKNOWLEDGED, 0x14) \ + OP(HV_STATUS_INVALID_VP_STATE, 0x15) \ + OP(HV_STATUS_NO_RESOURCES, 0x1D) \ + OP(HV_STATUS_PROCESSOR_FEATURE_NOT_SUPPORTED, 0x20) \ + OP(HV_STATUS_INVALID_LP_INDEX, 0x41) \ + OP(HV_STATUS_INVALID_REGISTER_VALUE,0x50) \ + OP(HV_STATUS_TIME_OUT, 0x78) \ + OP(HV_STATUS_CALL_PENDING, 0x79) \ + OP(HV_STATUS_VTL_ALREADY_ENABLED, 0x86) + +#define __HV_MAKE_HV_STATUS_ENUM(NAME, VAL) NAME = (VAL), +#define __HV_MAKE_HV_STATUS_CASE(NAME, VAL) cas
[PATCH v4 13/15] uapi: hyperv: Add mshv driver headers defining hypervisor ABIs
These must be in uapi because they will be used in the mshv ioctl API. Version numbers for each file: hvhdk.h 25212 hvhdk_mini.h25294 hvgdk.h 25125 hvgdk_mini.h25294 These are unstable interfaces and as such must be compiled independently from published interfaces found in hyperv-tlfs.h. Signed-off-by: Nuno Das Neves Acked-by: Wei Liu --- include/uapi/hyperv/hvgdk.h | 41 + include/uapi/hyperv/hvgdk_mini.h | 1076 include/uapi/hyperv/hvhdk.h | 1342 ++ include/uapi/hyperv/hvhdk_mini.h | 160 4 files changed, 2619 insertions(+) create mode 100644 include/uapi/hyperv/hvgdk.h create mode 100644 include/uapi/hyperv/hvgdk_mini.h create mode 100644 include/uapi/hyperv/hvhdk.h create mode 100644 include/uapi/hyperv/hvhdk_mini.h diff --git a/include/uapi/hyperv/hvgdk.h b/include/uapi/hyperv/hvgdk.h new file mode 100644 index ..9bcbb7d902b2 --- /dev/null +++ b/include/uapi/hyperv/hvgdk.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright (c) 2023, Microsoft Corporation. + * + * These files (hvhdk.h, hvhdk_mini.h, hvgdk.h, hvgdk_mini.h) define APIs for + * communicating with the Microsoft Hypervisor. + * + * These definitions are subject to change across hypervisor versions, and as + * such are separate and independent from hyperv-tlfs.h. + * + * The naming of these headers reflects conventions used in the Microsoft + * Hypervisor. + */ +#ifndef _UAPI_HV_HVGDK_H +#define _UAPI_HV_HVGDK_H + +#include "hvgdk_mini.h" + +enum hv_unimplemented_msr_action { + HV_UNIMPLEMENTED_MSR_ACTION_FAULT = 0, + HV_UNIMPLEMENTED_MSR_ACTION_IGNORE_WRITE_READ_ZERO = 1, + HV_UNIMPLEMENTED_MSR_ACTION_COUNT = 2, +}; + +/* Define connection identifier type. */ +union hv_connection_id { + __u32 asu32; + struct { + __u32 id:24; + __u32 reserved:8; + } __packed u; +}; + +struct hv_input_unmap_gpa_pages { + __u64 target_partition_id; + __u64 target_gpa_base; + __u32 unmap_flags; + __u32 padding; +} __packed; + +#endif /* #ifndef _UAPI_HV_HVGDK_H */ diff --git a/include/uapi/hyperv/hvgdk_mini.h b/include/uapi/hyperv/hvgdk_mini.h new file mode 100644 index ..f894327206c8 --- /dev/null +++ b/include/uapi/hyperv/hvgdk_mini.h @@ -0,0 +1,1076 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright (c) 2023, Microsoft Corporation. + * + * These files (hvhdk.h, hvhdk_mini.h, hvgdk.h, hvgdk_mini.h) define APIs for + * communicating with the Microsoft Hypervisor. + * + * These definitions are subject to change across hypervisor versions, and as + * such are separate and independent from hyperv-tlfs.h. + * + * The naming of these headers reflects conventions used in the Microsoft + * Hypervisor. + */ +#ifndef _UAPI_HV_HVGDK_MINI_H +#define _UAPI_HV_HVGDK_MINI_H + +struct hv_u128 { + __u64 low_part; + __u64 high_part; +} __packed; + +/* hypercall status code */ +#define __HV_STATUS_DEF(OP) \ + OP(HV_STATUS_SUCCESS, 0x0) \ + OP(HV_STATUS_INVALID_HYPERCALL_CODE,0x2) \ + OP(HV_STATUS_INVALID_HYPERCALL_INPUT, 0x3) \ + OP(HV_STATUS_INVALID_ALIGNMENT, 0x4) \ + OP(HV_STATUS_INVALID_PARAMETER, 0x5) \ + OP(HV_STATUS_ACCESS_DENIED, 0x6) \ + OP(HV_STATUS_INVALID_PARTITION_STATE, 0x7) \ + OP(HV_STATUS_OPERATION_DENIED, 0x8) \ + OP(HV_STATUS_UNKNOWN_PROPERTY, 0x9) \ + OP(HV_STATUS_PROPERTY_VALUE_OUT_OF_RANGE, 0xA) \ + OP(HV_STATUS_INSUFFICIENT_MEMORY, 0xB) \ + OP(HV_STATUS_INVALID_PARTITION_ID, 0xD) \ + OP(HV_STATUS_INVALID_VP_INDEX, 0xE) \ + OP(HV_STATUS_NOT_FOUND, 0x10) \ + OP(HV_STATUS_INVALID_PORT_ID, 0x11) \ + OP(HV_STATUS_INVALID_CONNECTION_ID, 0x12) \ + OP(HV_STATUS_INSUFFICIENT_BUFFERS, 0x13) \ + OP(HV_STATUS_NOT_ACKNOWLEDGED, 0x14) \ + OP(HV_STATUS_INVALID_VP_STATE, 0x15) \ + OP(HV_STATUS_NO_RESOURCES, 0x1D) \ + OP(HV_STATUS_PROCESSOR_FEATURE_NOT_SUPPORTED, 0x20) \ + OP(HV_STATUS_INVALID_LP_INDEX, 0x41) \ + OP(HV_STATUS_INVALID_REGISTER_VALUE,0x50) \ + OP(HV_STATUS_CALL_PENDING, 0x79) + +#define __HV_MAKE_HV_STATUS_ENUM(NAME, VAL) NAME = (VAL), +#define __HV_MAKE_HV_STATUS_CASE(NAME, VAL) case (NAME): return (#NAME); + +enum hv_status { + __HV_STATUS_DEF(__HV_MAKE_HV_STATUS_ENUM) +}; + +/* TODO not in hv headers */ +#define HV_LINUX_VENDOR_ID 0x8100 +#define HV_HYP_PAGE_SHIFT 12 +#define HV_HYP_PAGE_SIZE BIT(HV_HYP_PAGE_SHIFT) +#define HV_HYP
Re: [PATCH v4 14/15] asm-generic: hyperv: Use new Hyper-V headers conditionally.
Hi Alex, On 10/2/2023 12:35 PM, Alex Ionescu wrote: Hi Nuno, I understand the requirement to have undocumented/non-standard/non-TLFS-published information in the HDK headers, however, the current state of this patch is that for any other code that's not in the kernel today, or in this upcoming driver, the hyperv-tlfs definitions are incomplete, because some *documented* TLFS fields are only in HDK headers. Similarly, it is also impossible If I understand correctly, you are saying there are documented definitions (in the TLFS document), which are NOT in hyperv-tlfs.h, but ARE in these new HDK headers, correct? If these are needed elsewhere in the kernel, they can just be added to hyperv-tlfs.h. to only use the HDK headers for other use cases, because some basic documented, standard defines only exist in hyperv-tlfs. So there is no "logical" relationship between the two -- HDK headers are not _just_ undocumented information, but also documented information, but also not complete documented information. That is correct - they are meant to be independently compileable. The new HDK headers only serve as a replacement *in our driver* when we need some definitions like do_hypercall() etc in mshyperv.h. Would you consider: 1) Updating hyperv-tlfs with all newly documented TLFS fields that are in the HDK headers? I think this can be done on an as-needed basis, as I outlined above. OR 2) Updating the new HDK headers you're adding here to also include previously-documented information from hyperv-tlfs? This way, someone can include the HDK headers and get everything they need The new HDK headers are only intended for the new mshv driver. OR 3) Truly making hypertv-tlfs the "documented" header, and then > removing any duplication from HDK so that it remains the "undocumented" header file. In this manner, one would include hyperv-tlfs to use the stable ABI, and they would include HDK (which would include hyperv-tlfs) to use the unstable+stable ABI. hyperv-tlfs.h is remaining the "documented" header. But, we can't make the HDK header depend on hyperv-tlfs.h, for 2 primary reasons: 1. We need to put the new HDK headers in uapi so that we can use them in our IOCTL interface. As a result, we can't include hyperv-tlfs.h (unless we put it in uapi as well). 2. The HDK headers not only duplicate, but also MODIFY some structures in hyperv-tlfs.h. e.g., The struct is in hyperv-tlfs.h, but a particular field or bitfield is not. Thanks, Nuno Thank you for your consideration. Best regards, Alex Ionescu On Fri, Sep 29, 2023 at 2:02 PM Nuno Das Neves wrote: Add asm-generic/hyperv-defs.h. It includes hyperv-tlfs.h or hvhdk.h depending on compile-time constant HV_HYPERV_DEFS which will be defined in the mshv driver. This is needed to keep unstable Hyper-V interfaces independent of hyperv-tlfs.h. This ensures hvhdk.h replaces hyperv-tlfs.h in the mshv driver, even via indirect includes. Signed-off-by: Nuno Das Neves Acked-by: Wei Liu --- arch/arm64/include/asm/mshyperv.h | 2 +- arch/x86/include/asm/mshyperv.h | 3 +-- drivers/hv/hyperv_vmbus.h | 1 - include/asm-generic/hyperv-defs.h | 26 ++ include/asm-generic/mshyperv.h| 2 +- include/linux/hyperv.h| 2 +- 6 files changed, 30 insertions(+), 6 deletions(-) create mode 100644 include/asm-generic/hyperv-defs.h diff --git a/arch/arm64/include/asm/mshyperv.h b/arch/arm64/include/asm/mshyperv.h index 20070a847304..8ec14caf3d4f 100644 --- a/arch/arm64/include/asm/mshyperv.h +++ b/arch/arm64/include/asm/mshyperv.h @@ -20,7 +20,7 @@ #include #include -#include +#include /* * Declare calls to get and set Hyper-V VP register values on ARM64, which diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h index e3768d787065..bb1b97106cd3 100644 --- a/arch/x86/include/asm/mshyperv.h +++ b/arch/x86/include/asm/mshyperv.h @@ -6,10 +6,9 @@ #include #include #include -#include #include #include -#include +#include /* * Hyper-V always provides a single IO-APIC at this MMIO address. diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h index 09792eb4ffed..0e4bc18a13fa 100644 --- a/drivers/hv/hyperv_vmbus.h +++ b/drivers/hv/hyperv_vmbus.h @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include diff --git a/include/asm-generic/hyperv-defs.h b/include/asm-generic/hyperv-defs.h new file mode 100644 index ..ac6fcba35c8c --- /dev/null +++ b/include/asm-generic/hyperv-defs.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_GENERIC_HYPERV_DEFS_H +#define _ASM_GENERIC_HYPERV_DEFS_H + +/* + * There are cases where Microsoft Hypervisor ABIs are needed which may not be + * stable or present in the Hyper-V TLFS document. E.g. the mshv_root driver. + * + * As these interfaces are unstable an
Re: [PATCH v4 13/15] uapi: hyperv: Add mshv driver headers defining hypervisor ABIs
On 9/30/2023 11:19 PM, Greg KH wrote: On Sat, Sep 30, 2023 at 10:01:58PM +, Wei Liu wrote: On Sat, Sep 30, 2023 at 08:09:19AM +0200, Greg KH wrote: On Fri, Sep 29, 2023 at 11:01:39AM -0700, Nuno Das Neves wrote: +/* Define connection identifier type. */ +union hv_connection_id { + __u32 asu32; + struct { + __u32 id:24; + __u32 reserved:8; + } __packed u; bitfields will not work properly in uapi .h files, please never do that. Can you clarify a bit more why it wouldn't work? Endianess? Alignment? Yes to both. Did you all read the documentation for how to write a kernel api? If not, please do so. I think it mentions bitfields, but it not, it really should as of course, this will not work properly with different endian systems or many compilers. Yes, in https://docs.kernel.org/driver-api/ioctl.html it says that it is "better to avoid" bitfields. Unfortunately bitfields are used in the definition of the hypervisor ABI. We import these definitions directly from the hypervisor code. In practice the hypervisor, linux, and VMM compilers all produce the same layout for bitfields on the architectures we support. Thanks, Nuno thanks, greg k-h
Re: [PATCH v4 13/15] uapi: hyperv: Add mshv driver headers defining hypervisor ABIs
On 10/4/2023 10:50 AM, Greg KH wrote: On Wed, Oct 04, 2023 at 05:36:32PM +, Dexuan Cui wrote: From: Greg KH Sent: Tuesday, October 3, 2023 11:10 PM [...] On Tue, Oct 03, 2023 at 04:37:01PM -0700, Nuno Das Neves wrote: On 9/30/2023 11:19 PM, Greg KH wrote: On Sat, Sep 30, 2023 at 10:01:58PM +, Wei Liu wrote: On Sat, Sep 30, 2023 at 08:09:19AM +0200, Greg KH wrote: On Fri, Sep 29, 2023 at 11:01:39AM -0700, Nuno Das Neves wrote: +/* Define connection identifier type. */ +union hv_connection_id { + __u32 asu32; + struct { + __u32 id:24; + __u32 reserved:8; + } __packed u; IMO the "__packed" is unnecessary. bitfields will not work properly in uapi .h files, please never do that. Can you clarify a bit more why it wouldn't work? Endianess? Alignment? Yes to both. Did you all read the documentation for how to write a kernel api? If not, please do so. I think it mentions bitfields, but it not, it really should as of course, this will not work properly with different endian systems or many compilers. Yes, in https://docs.k/ ernel.org%2Fdriver- api%2Fioctl.html&data=05%7C01%7Cdecui%40microsoft.com%7Ce404769e0f 85493f0aa108dbc4a08a27%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C 0%7C638319966071263290%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLj AwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C% 7C%7C&sdata=RiLNA5DRviWBQK6XXhxC4m77raSDBb%2F0BB6BDpFPUJY%3D &reserved=0 it says that it is "better to avoid" bitfields. Unfortunately bitfields are used in the definition of the hypervisor ABI. We import these definitions directly from the hypervisor code. So why do you feel you have to use this specific format for your user/kernel api? That is not what is going to the hypervisor. These *are* going to the hypervisor - we use these same definitions in our driver for the kernel/hypervisor API. This is so we don't have to maintain two separate definitions for user/kernel and kernel/hypervisor APIs. If it's hard to avoid bitfield here, maybe we can refer to the definition of struct iphdr in include/uapi/linux/ip.h It is not hard to avoid using bitfields, just use the proper definitions to make this portable for all compilers. And ick, ip.h is not a good thing to follow :) Greg, there is nothing making us use bitfields. It just makes the work of porting the hypervisor definitions to Linux easier - aided by the fact that in practice, all the compilers in our stack produce the same code for these. If that stops being true, or we need to support some other scenario, then I can see the value in changing it. Right now it just feels like pointless work. Just a reminder - we are the only consumers of this code right now; no one else can meaningfully use this interface yet. That all said, if you really insist on changing it, then please say so. And please point to an example of how it should be done so there is no confusion on the best path forward. Thanks, Nuno thanks, greg k-h
Re: [PATCH v4 09/15] Drivers: hv: Introduce hv_output_arg_exists in hv_common.c
On 10/2/2023 12:29 PM, Alex Ionescu wrote: Hi Nuno, Is it possible to simply change to always allocating the output page? For example, the output page could be needed in scenarios where Linux is not running as the root partition, since certain hypercalls that a guest can make will still require one (I realize that's not the case _today_, but I don't believe this optimization buys much). I agree - it would indeed simplify the code, and guests will probably make use of it sooner or later. Happy to make that change if Hyper-V guest maintainers agree. Long, Dexuan, Michael, what do you think? Thanks, Nuno Best regards, Alex Ionescu On Fri, Sep 29, 2023 at 2:02 PM Nuno Das Neves wrote: This is a more flexible approach for determining whether to allocate the output page. Signed-off-by: Nuno Das Neves Acked-by: Wei Liu --- drivers/hv/hv_common.c | 21 + 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c index 39077841d518..3f6f23e4c579 100644 --- a/drivers/hv/hv_common.c +++ b/drivers/hv/hv_common.c @@ -58,6 +58,14 @@ EXPORT_SYMBOL_GPL(hyperv_pcpu_input_arg); void * __percpu *hyperv_pcpu_output_arg; EXPORT_SYMBOL_GPL(hyperv_pcpu_output_arg); +/* + * Determine whether output arg is needed + */ +static inline bool hv_output_arg_exists(void) +{ + return hv_root_partition ? true : false; +} + static void hv_kmsg_dump_unregister(void); static struct ctl_table_header *hv_ctl_table_hdr; @@ -342,10 +350,12 @@ int __init hv_common_init(void) hyperv_pcpu_input_arg = alloc_percpu(void *); BUG_ON(!hyperv_pcpu_input_arg); - /* Allocate the per-CPU state for output arg for root */ - if (hv_root_partition) { + if (hv_output_arg_exists()) { hyperv_pcpu_output_arg = alloc_percpu(void *); BUG_ON(!hyperv_pcpu_output_arg); + } + + if (hv_root_partition) { hv_synic_eventring_tail = alloc_percpu(u8 *); BUG_ON(hv_synic_eventring_tail == NULL); } @@ -375,7 +385,7 @@ int hv_common_cpu_init(unsigned int cpu) u8 **synic_eventring_tail; u64 msr_vp_index; gfp_t flags; - int pgcount = hv_root_partition ? 2 : 1; + int pgcount = hv_output_arg_exists() ? 2 : 1; void *mem; int ret; @@ -393,9 +403,12 @@ int hv_common_cpu_init(unsigned int cpu) if (!mem) return -ENOMEM; - if (hv_root_partition) { + if (hv_output_arg_exists()) { outputarg = (void **)this_cpu_ptr(hyperv_pcpu_output_arg); *outputarg = (char *)mem + HV_HYP_PAGE_SIZE; + } + + 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); -- 2.25.1
Re: [PATCH v2 13/15] uapi: hyperv: Add mshv driver headers hvhdk.h, hvhdk_mini.h, hvgdk.h, hvgdk_mini.h
On 8/25/2023 11:24 AM, Nuno Das Neves wrote: On 8/19/2023 3:26 AM, Greg KH wrote: My "strong" opinion is the one kernel development rule that we have, "you can not break userspace". So, if you change these values/structures/whatever in the future, and userspace tools break, that's not ok and the changes have to be reverted. If you can control both sides of the API here (with open tools that you can guarantee everyone will always update to), then yes, you can change the api in the future. This is true for us - we contribute and maintain support for this driver in Cloud Hypervisor[1], an open source VMM. Hi Greg, Bringing up this discussion again so we can clear up any confusion on the uapi headers in this patch set. The headers consist of the ioctls in mshv.h, and the hypervisor ABIs in the *hdk.h files. The ioctls depend on the hypervisor ABIs. We will add (to the next version), an ioctl like KVM_GET_API_VERSION [1]. This will return a version number for the ioctl interface that increments any time there is a breaking change. Userspace would be required to check this before calling any other ioctl, and it can exit gracefully if there is a mismatch. That's how KVM evolved its userspace ABI. We want to use the same approach. I also wanted to reiterate that we are the only maintainers and users of the userspace code for this driver via Cloud Hypervisor [2]. We generate rust bindings from these headers using bindgen [3]. Taking this into account, is the above a viable path for this patch set? Thanks, Nuno [1] https://docs.kernel.org/virt/kvm/api.html#kvm-get-api-version [2] https://github.com/cloud-hypervisor/cloud-hypervisor [3] https://github.com/rust-lang/rust-bindgen
Re: [PATCH v4 14/15] asm-generic: hyperv: Use new Hyper-V headers conditionally.
On 10/5/2023 12:52 PM, Alex Ionescu wrote: 3) Truly making hypertv-tlfs the "documented" header, and then > removing any duplication from HDK so that it remains the "undocumented" header file. In this manner, one would include hyperv-tlfs to use the stable ABI, and they would include HDK (which would include hyperv-tlfs) to use the unstable+stable ABI. hyperv-tlfs.h is remaining the "documented" header. But, we can't make the HDK header depend on hyperv-tlfs.h, for 2 primary reasons: 1. We need to put the new HDK headers in uapi so that we can use them in our IOCTL interface. As a result, we can't include hyperv-tlfs.h (unless we put it in uapi as well). 2. The HDK headers not only duplicate, but also MODIFY some structures in hyperv-tlfs.h. e.g., The struct is in hyperv-tlfs.h, but a particular field or bitfield is not. #2 was something I was worried about. Do you know if the standards/docs team is planning on updating the TLFS at some point with updates on their end? At which point I'd assume you'd be OK with patches to add them to hyperv-tlfs.h I don't know the current plans for updating the TLFS. But yes, assuming a new TLFS doc has something that is needed in the kernel, hyperv-tlfs.h would be updated to support that. Thanks, Nuno
Re: [PATCH v2 13/15] uapi: hyperv: Add mshv driver headers hvhdk.h, hvhdk_mini.h, hvgdk.h, hvgdk_mini.h
On 10/10/2023 11:42 PM, Greg KH wrote: On Tue, Oct 10, 2023 at 03:49:48PM -0700, Nuno Das Neves wrote: On 8/25/2023 11:24 AM, Nuno Das Neves wrote: On 8/19/2023 3:26 AM, Greg KH wrote: My "strong" opinion is the one kernel development rule that we have, "you can not break userspace". So, if you change these values/structures/whatever in the future, and userspace tools break, that's not ok and the changes have to be reverted. If you can control both sides of the API here (with open tools that you can guarantee everyone will always update to), then yes, you can change the api in the future. We control both sides of the API. The code is open. No one else can use it today, therefore we can guarantee all the users will stay updated. Just submit your fixed up patch series based on the previous review comments and it will be reviewed again, just like all kernel patches are. I will do that. Perhaps you all should take the time to do some kernel patch reviews of other stuff sent to the mailing lists to get an idea of how this whole process works, and to get better integrated into the kernel development community, That is a good suggestion, I will do that. before dumping a huge patchset on us with lots of process questions like this? Why are you asking the community to do a lot of work and hand-holding when you aren't helping others out as well? I take your point, sorry my questions came off that way. I will work to improve on that :) Thanks, Nuno
Re: Incorrect definition of hv_enable_vp_vtl in hyperv-tlfs.h
On 10/16/2023 4:49 AM, Alex Ionescu wrote: Hi, In arch/x86/include/asm/hyperv-tlfs.h, the following definition at line 786 (in Linus' tree), I believe to be incorrect. struct hv_enable_vp_vtl { u64partition_id; u32vp_index; union hv_input_vtltarget_vtl; < Here For this hypercall, the TLFS and MSDN documentation states this field is HV_VTL (u8) and not HV_INPUT_VTL (the bit-field used for targeting hypercalls to specific target VTLs, which is not the case here). I realize this is essentially a no-op in code at the moment, but for correctness should be addressed? I'm happy to make a patch, but wanted to make sure this isn't a mistake in TLFS/MSDN to begin with (although, my copy of GDK headers would corroborate it's indeed HV_VTL as well). Best regards, Alex Ionescu Hi Alex, I checked the code to make sure - seems like the TLFS doc is correct. It should indeed be HV_VTL (u8). Feel free to submit a patch. Thanks Nuno
[PATCH] hyperv-tlfs: Change prefix of generic HV_REGISTER_* MSRs to HV_MSR_*
The HV_REGISTER_ are used as arguments to hv_set/get_register(), which delegate to arch-specific mechanisms for getting/setting synthetic Hyper-V MSRs. On arm64, HV_REGISTER_ defines are synthetic VP registers accessed via the get/set vp registers hypercalls. The naming matches the TLFS document, although these register names are not specific to arm64. However, on x86 the prefix HV_REGISTER_ indicates Hyper-V MSRs accessed via rdmsrl()/wrmsrl(). This is not consistent with the TLFS doc, where HV_REGISTER_ is *only* used for used for VP register names used by the get/set register hypercalls. To fix this inconsistency and prevent future confusion, change the arch-generic aliases used by callers of hv_set/get_register() to have the prefix HV_MSR_ instead of HV_REGISTER_. Use the prefix HV_X64_MSR_ for the x86-only Hyper-V MSRs. On x86, the generic HV_MSR_'s point to the corresponding HV_X64_MSR_. Move the arm64 HV_REGISTER_* defines to the asm-generic hyperv-tlfs.h, since these are not specific to arm64. On arm64, the generic HV_MSR_'s point to the corresponding HV_REGISTER_. While at it, rename hv_get/set_registers() and related functions to hv_get/set_msr(), hv_get/set_nested_msr(), etc. These are only used for Hyper-V MSRs and this naming makes that clear. Signed-off-by: Nuno Das Neves Reviewed-by: Wei Liu --- arch/arm64/include/asm/hyperv-tlfs.h | 45 - arch/arm64/include/asm/mshyperv.h| 4 +- arch/x86/hyperv/hv_init.c| 8 +- arch/x86/include/asm/hyperv-tlfs.h | 145 ++- arch/x86/include/asm/mshyperv.h | 30 +++--- arch/x86/kernel/cpu/mshyperv.c | 56 +-- drivers/clocksource/hyperv_timer.c | 26 ++--- drivers/hv/hv.c | 36 +++ drivers/hv/hv_common.c | 22 ++-- include/asm-generic/hyperv-tlfs.h| 32 +- include/asm-generic/mshyperv.h | 2 +- 11 files changed, 216 insertions(+), 190 deletions(-) diff --git a/arch/arm64/include/asm/hyperv-tlfs.h b/arch/arm64/include/asm/hyperv-tlfs.h index bc6c7ac934a1..54846d1d29c3 100644 --- a/arch/arm64/include/asm/hyperv-tlfs.h +++ b/arch/arm64/include/asm/hyperv-tlfs.h @@ -21,14 +21,6 @@ * byte ordering of Linux running on ARM64, so no special handling is required. */ -/* - * These Hyper-V registers provide information equivalent to the CPUID - * instruction on x86/x64. - */ -#define HV_REGISTER_HYPERVISOR_VERSION 0x0100 /*CPUID 0x4002 */ -#define HV_REGISTER_FEATURES 0x0200 /*CPUID 0x4003 */ -#define HV_REGISTER_ENLIGHTENMENTS 0x0201 /*CPUID 0x4004 */ - /* * Group C Features. See the asm-generic version of hyperv-tlfs.h * for a description of Feature Groups. @@ -41,28 +33,29 @@ #define HV_STIMER_DIRECT_MODE_AVAILABLEBIT(13) /* - * Synthetic register definitions equivalent to MSRs on x86/x64 + * To support arch-generic code calling hv_set/get_register: + * - On x86, HV_MSR_ indicates an MSR accessed via rdmsrl/wrmsrl + * - On ARM, HV_MSR_ indicates a VP register accessed via hypercall */ -#define HV_REGISTER_CRASH_P0 0x0210 -#define HV_REGISTER_CRASH_P1 0x0211 -#define HV_REGISTER_CRASH_P2 0x0212 -#define HV_REGISTER_CRASH_P3 0x0213 -#define HV_REGISTER_CRASH_P4 0x0214 -#define HV_REGISTER_CRASH_CTL 0x0215 +#define HV_MSR_CRASH_P0(HV_REGISTER_CRASH_P0) +#define HV_MSR_CRASH_P1(HV_REGISTER_CRASH_P1) +#define HV_MSR_CRASH_P2(HV_REGISTER_CRASH_P2) +#define HV_MSR_CRASH_P3(HV_REGISTER_CRASH_P3) +#define HV_MSR_CRASH_P4(HV_REGISTER_CRASH_P4) +#define HV_MSR_CRASH_CTL (HV_REGISTER_CRASH_CTL) -#define HV_REGISTER_GUEST_OSID 0x00090002 -#define HV_REGISTER_VP_INDEX 0x00090003 -#define HV_REGISTER_TIME_REF_COUNT 0x00090004 -#define HV_REGISTER_REFERENCE_TSC 0x00090017 +#define HV_MSR_VP_INDEX(HV_REGISTER_VP_INDEX) +#define HV_MSR_TIME_REF_COUNT (HV_REGISTER_TIME_REF_COUNT) +#define HV_MSR_REFERENCE_TSC (HV_REGISTER_REFERENCE_TSC) -#define HV_REGISTER_SINT0 0x000A -#define HV_REGISTER_SCONTROL 0x000A0010 -#define HV_REGISTER_SIEFP 0x000A0012 -#define HV_REGISTER_SIMP 0x000A0013 -#define HV_REGISTER_EOM0x000A0014 +#define HV_MSR_SINT0 (HV_REGISTER_SINT0) +#define HV_MSR_SCONTROL(HV_REGISTER_SCONTROL) +#define HV_MSR_SIEFP (HV_REGISTER_SIEFP) +#define HV_MSR_SIMP(HV_REGISTER_SIMP) +#define HV_MSR_EOM (HV_REGISTER_EOM) -#define HV_REGISTER_STIMER0_CONFIG 0x000B -#define HV_REGISTER_STIMER0_COUNT 0x000B0001 +#define HV_MSR_STIMER0_CONFIG (HV_REGISTER_STIMER0_CONFIG) +#define HV_MSR_STIMER0_COUNT (HV_REGISTER_STIMER0_COUNT) union hv_msi_entry { u64 as_uint6
Re: [PATCH] hyperv-tlfs: Change prefix of generic HV_REGISTER_* MSRs to HV_MSR_*
On 2/10/2024 2:37 AM, Michael Kelley wrote: > > Overall, this looks good to me. It cleans up the mess I made five > years ago when first separating x86 from ARM64. :-( > > See one comment below, but otherwise, > > Reviewed-by: Michael Kelley > Thanks! Responded to your comment below. >> #if IS_ENABLED(CONFIG_HYPERV) >> -static inline unsigned int hv_get_nested_reg(unsigned int reg) >> +static inline unsigned int hv_get_nested_msr(unsigned int reg) >> { >> -if (hv_is_sint_reg(reg)) >> -return reg - HV_REGISTER_SINT0 + HV_REGISTER_NESTED_SINT0; >> +if (hv_is_sint_msr(reg)) >> +return reg - HV_MSR_SINT0 + HV_MSR_NESTED_SINT0; >> >> switch (reg) { >> -case HV_REGISTER_SIMP: >> -return HV_REGISTER_NESTED_SIMP; >> -case HV_REGISTER_SIEFP: >> -return HV_REGISTER_NESTED_SIEFP; >> -case HV_REGISTER_SVERSION: >> -return HV_REGISTER_NESTED_SVERSION; >> -case HV_REGISTER_SCONTROL: >> -return HV_REGISTER_NESTED_SCONTROL; >> -case HV_REGISTER_EOM: >> -return HV_REGISTER_NESTED_EOM; >> +case HV_MSR_SIMP: >> +return HV_MSR_NESTED_SIMP; >> +case HV_MSR_SIEFP: >> +return HV_MSR_NESTED_SIEFP; >> +case HV_MSR_SVERSION: >> +return HV_MSR_NESTED_SVERSION; >> +case HV_MSR_SCONTROL: >> +return HV_MSR_NESTED_SCONTROL; >> +case HV_MSR_EOM: >> +return HV_MSR_NESTED_EOM; >> default: >> return reg; >> } >> } > > This function is x86 specific, but you are using the generic HV_MSR_* flavor > instead of the x86 specific HV_X64_MSR_* flavor like in other x86 specific > code. > Both flavors work, but I wondered if there is any reason for using the > generic flavor. >> I remember debating myself the merits of one approach vs. the other, but I > don't think there was a solid argument either way. Given that you are > doing the work to get this all fixed like it should have been originally, I > would > argue for being consistently one way or the other. ARM64 specific code is > *not* using the generic HV_MSR_* flavor, so I suspect x86 code should not > either. > > Michael > I see your point about keeping it consistent within the file. My thinking was that hv_get_nested_msr is not inherently x86-specific, even though it lives in arch/x86 today. However, I realize that even if this function *is* moved to generic code in the future, at that time it could be changed to the generic prefix. Doing so in this patch could be confusing since it introduces an inconsistency. So, I will take your advice and keep it HV_X64_MSR_* for everything in this file. Thanks again! Nuno
[PATCH v2] hyperv-tlfs: Change prefix of generic HV_REGISTER_* MSRs to HV_MSR_*
The HV_REGISTER_ are used as arguments to hv_set/get_register(), which delegate to arch-specific mechanisms for getting/setting synthetic Hyper-V MSRs. On arm64, HV_REGISTER_ defines are synthetic VP registers accessed via the get/set vp registers hypercalls. The naming matches the TLFS document, although these register names are not specific to arm64. However, on x86 the prefix HV_REGISTER_ indicates Hyper-V MSRs accessed via rdmsrl()/wrmsrl(). This is not consistent with the TLFS doc, where HV_REGISTER_ is *only* used for used for VP register names used by the get/set register hypercalls. To fix this inconsistency and prevent future confusion, change the arch-generic aliases used by callers of hv_set/get_register() to have the prefix HV_MSR_ instead of HV_REGISTER_. Use the prefix HV_X64_MSR_ for the x86-only Hyper-V MSRs. On x86, the generic HV_MSR_'s point to the corresponding HV_X64_MSR_. Move the arm64 HV_REGISTER_* defines to the asm-generic hyperv-tlfs.h, since these are not specific to arm64. On arm64, the generic HV_MSR_'s point to the corresponding HV_REGISTER_. While at it, rename hv_get/set_registers() and related functions to hv_get/set_msr(), hv_get/set_nested_msr(), etc. These are only used for Hyper-V MSRs and this naming makes that clear. Signed-off-by: Nuno Das Neves Reviewed-by: Wei Liu Reviewed-by: Michael Kelley --- Changes in v2: * Use HV_X64_MSR_ instead of HV_MSR_ in arch/x86/kernel/cpu/mshyperv.c --- arch/arm64/include/asm/hyperv-tlfs.h | 45 - arch/arm64/include/asm/mshyperv.h| 4 +- arch/x86/hyperv/hv_init.c| 8 +- arch/x86/include/asm/hyperv-tlfs.h | 145 ++- arch/x86/include/asm/mshyperv.h | 30 +++--- arch/x86/kernel/cpu/mshyperv.c | 56 +-- drivers/clocksource/hyperv_timer.c | 26 ++--- drivers/hv/hv.c | 36 +++ drivers/hv/hv_common.c | 22 ++-- include/asm-generic/hyperv-tlfs.h| 32 +- include/asm-generic/mshyperv.h | 2 +- 11 files changed, 216 insertions(+), 190 deletions(-) diff --git a/arch/arm64/include/asm/hyperv-tlfs.h b/arch/arm64/include/asm/hyperv-tlfs.h index bc6c7ac934a1..54846d1d29c3 100644 --- a/arch/arm64/include/asm/hyperv-tlfs.h +++ b/arch/arm64/include/asm/hyperv-tlfs.h @@ -21,14 +21,6 @@ * byte ordering of Linux running on ARM64, so no special handling is required. */ -/* - * These Hyper-V registers provide information equivalent to the CPUID - * instruction on x86/x64. - */ -#define HV_REGISTER_HYPERVISOR_VERSION 0x0100 /*CPUID 0x4002 */ -#define HV_REGISTER_FEATURES 0x0200 /*CPUID 0x4003 */ -#define HV_REGISTER_ENLIGHTENMENTS 0x0201 /*CPUID 0x4004 */ - /* * Group C Features. See the asm-generic version of hyperv-tlfs.h * for a description of Feature Groups. @@ -41,28 +33,29 @@ #define HV_STIMER_DIRECT_MODE_AVAILABLEBIT(13) /* - * Synthetic register definitions equivalent to MSRs on x86/x64 + * To support arch-generic code calling hv_set/get_register: + * - On x86, HV_MSR_ indicates an MSR accessed via rdmsrl/wrmsrl + * - On ARM, HV_MSR_ indicates a VP register accessed via hypercall */ -#define HV_REGISTER_CRASH_P0 0x0210 -#define HV_REGISTER_CRASH_P1 0x0211 -#define HV_REGISTER_CRASH_P2 0x0212 -#define HV_REGISTER_CRASH_P3 0x0213 -#define HV_REGISTER_CRASH_P4 0x0214 -#define HV_REGISTER_CRASH_CTL 0x0215 +#define HV_MSR_CRASH_P0(HV_REGISTER_CRASH_P0) +#define HV_MSR_CRASH_P1(HV_REGISTER_CRASH_P1) +#define HV_MSR_CRASH_P2(HV_REGISTER_CRASH_P2) +#define HV_MSR_CRASH_P3(HV_REGISTER_CRASH_P3) +#define HV_MSR_CRASH_P4(HV_REGISTER_CRASH_P4) +#define HV_MSR_CRASH_CTL (HV_REGISTER_CRASH_CTL) -#define HV_REGISTER_GUEST_OSID 0x00090002 -#define HV_REGISTER_VP_INDEX 0x00090003 -#define HV_REGISTER_TIME_REF_COUNT 0x00090004 -#define HV_REGISTER_REFERENCE_TSC 0x00090017 +#define HV_MSR_VP_INDEX(HV_REGISTER_VP_INDEX) +#define HV_MSR_TIME_REF_COUNT (HV_REGISTER_TIME_REF_COUNT) +#define HV_MSR_REFERENCE_TSC (HV_REGISTER_REFERENCE_TSC) -#define HV_REGISTER_SINT0 0x000A -#define HV_REGISTER_SCONTROL 0x000A0010 -#define HV_REGISTER_SIEFP 0x000A0012 -#define HV_REGISTER_SIMP 0x000A0013 -#define HV_REGISTER_EOM0x000A0014 +#define HV_MSR_SINT0 (HV_REGISTER_SINT0) +#define HV_MSR_SCONTROL(HV_REGISTER_SCONTROL) +#define HV_MSR_SIEFP (HV_REGISTER_SIEFP) +#define HV_MSR_SIMP(HV_REGISTER_SIMP) +#define HV_MSR_EOM (HV_REGISTER_EOM) -#define HV_REGISTER_STIMER0_CONFIG 0x000B -#define HV_REGISTER_STIMER0_COUNT 0x000B0001 +#define HV_MSR_STIM
[PATCH] mshyperv: Introduce hv_get_hypervisor_version function
Introduce x86_64 and arm64 functions for getting the hypervisor version information and storing it in a structure for simpler parsing. Use the new function to get and parse the version at boot time. While at it, print the version in the same format for each architecture, and move the printing code to hv_common_init() so it is not duplicated. Signed-off-by: Nuno Das Neves Acked-by: Wei Liu --- arch/arm64/hyperv/mshyperv.c | 19 - arch/x86/kernel/cpu/mshyperv.c| 35 ++- drivers/hv/hv_common.c| 9 include/asm-generic/hyperv-tlfs.h | 23 include/asm-generic/mshyperv.h| 2 ++ 5 files changed, 59 insertions(+), 29 deletions(-) diff --git a/arch/arm64/hyperv/mshyperv.c b/arch/arm64/hyperv/mshyperv.c index f1b8a04ee9f2..55dc224d466d 100644 --- a/arch/arm64/hyperv/mshyperv.c +++ b/arch/arm64/hyperv/mshyperv.c @@ -19,10 +19,18 @@ static bool hyperv_initialized; +int hv_get_hypervisor_version(union hv_hypervisor_version_info *info) +{ + hv_get_vpreg_128(HV_REGISTER_HYPERVISOR_VERSION, +(struct hv_get_vp_registers_output *)info); + + return 0; +} +EXPORT_SYMBOL_GPL(hv_get_hypervisor_version); + static int __init hyperv_init(void) { struct hv_get_vp_registers_output result; - u32 a, b, c, d; u64 guest_id; int ret; @@ -54,15 +62,6 @@ static int __init hyperv_init(void) ms_hyperv.features, ms_hyperv.priv_high, ms_hyperv.hints, ms_hyperv.misc_features); - /* Get information about the Hyper-V host version */ - hv_get_vpreg_128(HV_REGISTER_HYPERVISOR_VERSION, &result); - a = result.as32.a; - b = result.as32.b; - c = result.as32.c; - d = result.as32.d; - pr_info("Hyper-V: Host Build %d.%d.%d.%d-%d-%d\n", - b >> 16, b & 0x, a, d & 0xFF, c, d >> 24); - ret = hv_common_init(); if (ret) return ret; diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c index d306f6184cee..03a3445faf7a 100644 --- a/arch/x86/kernel/cpu/mshyperv.c +++ b/arch/x86/kernel/cpu/mshyperv.c @@ -350,13 +350,25 @@ static void __init reduced_hw_init(void) x86_init.irqs.pre_vector_init = x86_init_noop; } +int hv_get_hypervisor_version(union hv_hypervisor_version_info *info) +{ + unsigned int hv_max_functions; + + hv_max_functions = cpuid_eax(HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS); + if (hv_max_functions < HYPERV_CPUID_VERSION) { + pr_err("%s: Could not detect Hyper-V version\n", __func__); + return -ENODEV; + } + + cpuid(HYPERV_CPUID_VERSION, &info->eax, &info->ebx, &info->ecx, &info->edx); + + return 0; +} +EXPORT_SYMBOL_GPL(hv_get_hypervisor_version); + static void __init ms_hyperv_init_platform(void) { int hv_max_functions_eax; - int hv_host_info_eax; - int hv_host_info_ebx; - int hv_host_info_ecx; - int hv_host_info_edx; #ifdef CONFIG_PARAVIRT pv_info.name = "Hyper-V"; @@ -407,21 +419,6 @@ static void __init ms_hyperv_init_platform(void) pr_info("Hyper-V: running on a nested hypervisor\n"); } - /* -* Extract host information. -*/ - if (hv_max_functions_eax >= HYPERV_CPUID_VERSION) { - hv_host_info_eax = cpuid_eax(HYPERV_CPUID_VERSION); - hv_host_info_ebx = cpuid_ebx(HYPERV_CPUID_VERSION); - hv_host_info_ecx = cpuid_ecx(HYPERV_CPUID_VERSION); - hv_host_info_edx = cpuid_edx(HYPERV_CPUID_VERSION); - - pr_info("Hyper-V: Host Build %d.%d.%d.%d-%d-%d\n", - hv_host_info_ebx >> 16, hv_host_info_ebx & 0x, - hv_host_info_eax, hv_host_info_edx & 0xFF, - hv_host_info_ecx, hv_host_info_edx >> 24); - } - if (ms_hyperv.features & HV_ACCESS_FREQUENCY_MSRS && ms_hyperv.misc_features & HV_FEATURE_FREQUENCY_MSRS_AVAILABLE) { x86_platform.calibrate_tsc = hv_get_tsc_khz; diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c index 2f1dd4b07f9a..4d72c528af68 100644 --- a/drivers/hv/hv_common.c +++ b/drivers/hv/hv_common.c @@ -278,6 +278,15 @@ static void hv_kmsg_dump_register(void) int __init hv_common_init(void) { int i; + union hv_hypervisor_version_info version; + + /* Get information about the Hyper-V host version */ + if (hv_get_hypervisor_version(&version) == 0) { + pr_info("Hyper-V: Host Build %d.%d.%d.%d-%d-%d\n", + version.major_version, version.minor_version, + version.build_number, version.service_number, +
Re: [PATCH] mshyperv: Introduce hv_get_hypervisor_version function
On 3/7/2024 11:22 AM, Michael Kelley wrote: > From: Nuno Das Neves Sent: Wednesday, > March 6, 2024 4:48 PM >> >> Introduce x86_64 and arm64 functions for getting the hypervisor version >> information and storing it in a structure for simpler parsing. >> >> Use the new function to get and parse the version at boot time. While at >> it, print the version in the same format for each architecture, and move >> the printing code to hv_common_init() so it is not duplicated. > > Isn't the format already the same for x86 and ARM64? A couple of > years ago they didn't match. But that was fixed in commit eeda29db98f4. > You're correct - I will amend the commit message. Thanks! >> >> Signed-off-by: Nuno Das Neves >> Acked-by: Wei Liu >> --- >> arch/arm64/hyperv/mshyperv.c | 19 - >> arch/x86/kernel/cpu/mshyperv.c| 35 ++- >> drivers/hv/hv_common.c| 9 >> include/asm-generic/hyperv-tlfs.h | 23 >> include/asm-generic/mshyperv.h| 2 ++ >> 5 files changed, 59 insertions(+), 29 deletions(-) >> >> diff --git a/arch/arm64/hyperv/mshyperv.c >> b/arch/arm64/hyperv/mshyperv.c >> index f1b8a04ee9f2..55dc224d466d 100644 >> --- a/arch/arm64/hyperv/mshyperv.c >> +++ b/arch/arm64/hyperv/mshyperv.c >> @@ -19,10 +19,18 @@ >> >> static bool hyperv_initialized; >> >> +int hv_get_hypervisor_version(union hv_hypervisor_version_info *info) >> +{ >> +hv_get_vpreg_128(HV_REGISTER_HYPERVISOR_VERSION, >> + (struct hv_get_vp_registers_output *)info); >> + >> +return 0; >> +} >> +EXPORT_SYMBOL_GPL(hv_get_hypervisor_version); > > I don't think this need to be exported, at least not for the usage in > this patch. The caller in hv_common.c is never part of a module -- it's > always built-in. But maybe you are anticipating future use cases > from a module? > Yes, it will be used in a module eventually. Do you think I should remove this and the below export until they are actually needed? >> + >> static int __init hyperv_init(void) >> { >> struct hv_get_vp_registers_output result; >> -u32 a, b, c, d; >> u64 guest_id; >> int ret; >> >> @@ -54,15 +62,6 @@ static int __init hyperv_init(void) >> ms_hyperv.features, ms_hyperv.priv_high, ms_hyperv.hints, >> ms_hyperv.misc_features); >> >> -/* Get information about the Hyper-V host version */ >> -hv_get_vpreg_128(HV_REGISTER_HYPERVISOR_VERSION, &result); >> -a = result.as32.a; >> -b = result.as32.b; >> -c = result.as32.c; >> -d = result.as32.d; >> -pr_info("Hyper-V: Host Build %d.%d.%d.%d-%d-%d\n", >> -b >> 16, b & 0x, a, d & 0xFF, c, d >> 24); >> - >> ret = hv_common_init(); >> if (ret) >> return ret; >> diff --git a/arch/x86/kernel/cpu/mshyperv.c >> b/arch/x86/kernel/cpu/mshyperv.c >> index d306f6184cee..03a3445faf7a 100644 >> --- a/arch/x86/kernel/cpu/mshyperv.c >> +++ b/arch/x86/kernel/cpu/mshyperv.c >> @@ -350,13 +350,25 @@ static void __init reduced_hw_init(void) >> x86_init.irqs.pre_vector_init = x86_init_noop; >> } >> >> +int hv_get_hypervisor_version(union hv_hypervisor_version_info *info) >> +{ >> +unsigned int hv_max_functions; >> + >> +hv_max_functions = cpuid_eax(HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS); >> +if (hv_max_functions < HYPERV_CPUID_VERSION) { >> +pr_err("%s: Could not detect Hyper-V version\n", __func__); >> +return -ENODEV; >> +} >> + >> +cpuid(HYPERV_CPUID_VERSION, &info->eax, &info->ebx, &info->ecx, >> &info->edx); >> + >> +return 0; >> +} >> +EXPORT_SYMBOL_GPL(hv_get_hypervisor_version); > > Same for this EXPORT. >>> + >> static void __init ms_hyperv_init_platform(void) >> { >> int hv_max_functions_eax; >> -int hv_host_info_eax; >> -int hv_host_info_ebx; >> -int hv_host_info_ecx; >> -int hv_host_info_edx; >> >> #ifdef CONFIG_PARAVIRT >> pv_info.name = "Hyper-V"; >> @@ -407,21 +419,6 @@ static void __init ms_hyperv_init_platform(void) >> pr_info("Hyper-V: running on a nested hypervisor\n"); >> } >> >> -/* >> -
[PATCH v2] mshyperv: Introduce hv_get_hypervisor_version function
Introduce x86_64 and arm64 functions to get the hypervisor version information and store it in a structure for simpler parsing. Use the new function to get and parse the version at boot time. While at it, move the printing code to hv_common_init() so it is not duplicated. Signed-off-by: Nuno Das Neves Acked-by: Wei Liu --- Changes since v1: - Amend commit message - Address minor style issues - Remove unneeded EXPORT_SYMBOL_GPL(hv_get_hypervisor_version) --- arch/arm64/hyperv/mshyperv.c | 18 arch/x86/kernel/cpu/mshyperv.c| 34 ++- drivers/hv/hv_common.c| 8 include/asm-generic/hyperv-tlfs.h | 23 + include/asm-generic/mshyperv.h| 1 + 5 files changed, 55 insertions(+), 29 deletions(-) diff --git a/arch/arm64/hyperv/mshyperv.c b/arch/arm64/hyperv/mshyperv.c index f1b8a04ee9f2..99362716ac87 100644 --- a/arch/arm64/hyperv/mshyperv.c +++ b/arch/arm64/hyperv/mshyperv.c @@ -19,10 +19,17 @@ static bool hyperv_initialized; +int hv_get_hypervisor_version(union hv_hypervisor_version_info *info) +{ + hv_get_vpreg_128(HV_REGISTER_HYPERVISOR_VERSION, +(struct hv_get_vp_registers_output *)info); + + return 0; +} + static int __init hyperv_init(void) { struct hv_get_vp_registers_output result; - u32 a, b, c, d; u64 guest_id; int ret; @@ -54,15 +61,6 @@ static int __init hyperv_init(void) ms_hyperv.features, ms_hyperv.priv_high, ms_hyperv.hints, ms_hyperv.misc_features); - /* Get information about the Hyper-V host version */ - hv_get_vpreg_128(HV_REGISTER_HYPERVISOR_VERSION, &result); - a = result.as32.a; - b = result.as32.b; - c = result.as32.c; - d = result.as32.d; - pr_info("Hyper-V: Host Build %d.%d.%d.%d-%d-%d\n", - b >> 16, b & 0x, a, d & 0xFF, c, d >> 24); - ret = hv_common_init(); if (ret) return ret; diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c index d306f6184cee..56e731d8f513 100644 --- a/arch/x86/kernel/cpu/mshyperv.c +++ b/arch/x86/kernel/cpu/mshyperv.c @@ -350,13 +350,24 @@ static void __init reduced_hw_init(void) x86_init.irqs.pre_vector_init = x86_init_noop; } +int hv_get_hypervisor_version(union hv_hypervisor_version_info *info) +{ + unsigned int hv_max_functions; + + hv_max_functions = cpuid_eax(HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS); + if (hv_max_functions < HYPERV_CPUID_VERSION) { + pr_err("%s: Could not detect Hyper-V version\n", __func__); + return -ENODEV; + } + + cpuid(HYPERV_CPUID_VERSION, &info->eax, &info->ebx, &info->ecx, &info->edx); + + return 0; +} + static void __init ms_hyperv_init_platform(void) { int hv_max_functions_eax; - int hv_host_info_eax; - int hv_host_info_ebx; - int hv_host_info_ecx; - int hv_host_info_edx; #ifdef CONFIG_PARAVIRT pv_info.name = "Hyper-V"; @@ -407,21 +418,6 @@ static void __init ms_hyperv_init_platform(void) pr_info("Hyper-V: running on a nested hypervisor\n"); } - /* -* Extract host information. -*/ - if (hv_max_functions_eax >= HYPERV_CPUID_VERSION) { - hv_host_info_eax = cpuid_eax(HYPERV_CPUID_VERSION); - hv_host_info_ebx = cpuid_ebx(HYPERV_CPUID_VERSION); - hv_host_info_ecx = cpuid_ecx(HYPERV_CPUID_VERSION); - hv_host_info_edx = cpuid_edx(HYPERV_CPUID_VERSION); - - pr_info("Hyper-V: Host Build %d.%d.%d.%d-%d-%d\n", - hv_host_info_ebx >> 16, hv_host_info_ebx & 0x, - hv_host_info_eax, hv_host_info_edx & 0xFF, - hv_host_info_ecx, hv_host_info_edx >> 24); - } - if (ms_hyperv.features & HV_ACCESS_FREQUENCY_MSRS && ms_hyperv.misc_features & HV_FEATURE_FREQUENCY_MSRS_AVAILABLE) { x86_platform.calibrate_tsc = hv_get_tsc_khz; diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c index 2f1dd4b07f9a..5d64cb0a709d 100644 --- a/drivers/hv/hv_common.c +++ b/drivers/hv/hv_common.c @@ -278,6 +278,14 @@ static void hv_kmsg_dump_register(void) int __init hv_common_init(void) { int i; + union hv_hypervisor_version_info version; + + /* Get information about the Hyper-V host version */ + if (!hv_get_hypervisor_version(&version)) + pr_info("Hyper-V: Host Build %d.%d.%d.%d-%d-%d\n", + version.major_version, version.minor_version, + version.build_number, version.service_number, + version.service_pack, v
Re: [PATCH v2] mshyperv: Introduce hv_get_hypervisor_version function
On 3/7/2024 3:03 PM, Nuno Das Neves wrote: > Introduce x86_64 and arm64 functions to get the hypervisor version > information and store it in a structure for simpler parsing. > > Use the new function to get and parse the version at boot time. While at > it, move the printing code to hv_common_init() so it is not duplicated. > > Signed-off-by: Nuno Das Neves > Acked-by: Wei Liu > --- > Changes since v1: > - Amend commit message > - Address minor style issues > - Remove unneeded EXPORT_SYMBOL_GPL(hv_get_hypervisor_version) > --- > arch/arm64/hyperv/mshyperv.c | 18 > arch/x86/kernel/cpu/mshyperv.c| 34 ++- > drivers/hv/hv_common.c| 8 > include/asm-generic/hyperv-tlfs.h | 23 + > include/asm-generic/mshyperv.h| 1 + > 5 files changed, 55 insertions(+), 29 deletions(-) > > diff --git a/arch/arm64/hyperv/mshyperv.c b/arch/arm64/hyperv/mshyperv.c > index f1b8a04ee9f2..99362716ac87 100644 > --- a/arch/arm64/hyperv/mshyperv.c > +++ b/arch/arm64/hyperv/mshyperv.c > @@ -19,10 +19,17 @@ > > static bool hyperv_initialized; > > +int hv_get_hypervisor_version(union hv_hypervisor_version_info *info) > +{ > + hv_get_vpreg_128(HV_REGISTER_HYPERVISOR_VERSION, > + (struct hv_get_vp_registers_output *)info); > + > + return 0; > +} > + > static int __init hyperv_init(void) > { > struct hv_get_vp_registers_output result; > - u32 a, b, c, d; > u64 guest_id; > int ret; > > @@ -54,15 +61,6 @@ static int __init hyperv_init(void) > ms_hyperv.features, ms_hyperv.priv_high, ms_hyperv.hints, > ms_hyperv.misc_features); > > - /* Get information about the Hyper-V host version */ > - hv_get_vpreg_128(HV_REGISTER_HYPERVISOR_VERSION, &result); > - a = result.as32.a; > - b = result.as32.b; > - c = result.as32.c; > - d = result.as32.d; > - pr_info("Hyper-V: Host Build %d.%d.%d.%d-%d-%d\n", > - b >> 16, b & 0x, a, d & 0xFF, c, d >> 24); > - > ret = hv_common_init(); > if (ret) > return ret; > diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c > index d306f6184cee..56e731d8f513 100644 > --- a/arch/x86/kernel/cpu/mshyperv.c > +++ b/arch/x86/kernel/cpu/mshyperv.c > @@ -350,13 +350,24 @@ static void __init reduced_hw_init(void) > x86_init.irqs.pre_vector_init = x86_init_noop; > } > > +int hv_get_hypervisor_version(union hv_hypervisor_version_info *info) > +{ > + unsigned int hv_max_functions; > + > + hv_max_functions = cpuid_eax(HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS); > + if (hv_max_functions < HYPERV_CPUID_VERSION) { > + pr_err("%s: Could not detect Hyper-V version\n", __func__); > + return -ENODEV; > + } > + > + cpuid(HYPERV_CPUID_VERSION, &info->eax, &info->ebx, &info->ecx, > &info->edx); > + > + return 0; > +} > + > static void __init ms_hyperv_init_platform(void) > { > int hv_max_functions_eax; > - int hv_host_info_eax; > - int hv_host_info_ebx; > - int hv_host_info_ecx; > - int hv_host_info_edx; > > #ifdef CONFIG_PARAVIRT > pv_info.name = "Hyper-V"; > @@ -407,21 +418,6 @@ static void __init ms_hyperv_init_platform(void) > pr_info("Hyper-V: running on a nested hypervisor\n"); > } > > - /* > - * Extract host information. > - */ > - if (hv_max_functions_eax >= HYPERV_CPUID_VERSION) { > - hv_host_info_eax = cpuid_eax(HYPERV_CPUID_VERSION); > - hv_host_info_ebx = cpuid_ebx(HYPERV_CPUID_VERSION); > - hv_host_info_ecx = cpuid_ecx(HYPERV_CPUID_VERSION); > - hv_host_info_edx = cpuid_edx(HYPERV_CPUID_VERSION); > - > - pr_info("Hyper-V: Host Build %d.%d.%d.%d-%d-%d\n", > - hv_host_info_ebx >> 16, hv_host_info_ebx & 0x, > - hv_host_info_eax, hv_host_info_edx & 0xFF, > - hv_host_info_ecx, hv_host_info_edx >> 24); > - } > - > if (ms_hyperv.features & HV_ACCESS_FREQUENCY_MSRS && > ms_hyperv.misc_features & HV_FEATURE_FREQUENCY_MSRS_AVAILABLE) { > x86_platform.calibrate_tsc = hv_get_tsc_khz; > diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c > index 2f1dd4b07f9a..5d64cb0a709d 100644 > --- a/drivers/hv/hv_common.c > +++ b/drivers
[PATCH] hyperv-tlfs: Rename some HV_REGISTER_* defines for consistency
Rename HV_REGISTER_GUEST_OSID to HV_REGISTER_GUEST_OS_ID. This matches the existing HV_X64_MSR_GUEST_OS_ID. Rename HV_REGISTER_CRASH_* to HV_REGISTER_GUEST_CRASH_*. Including GUEST_ is consistent with other #defines such as HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE. The new names also match the TLFS document more accurately, i.e. HvRegisterGuestCrash*. Signed-off-by: Nuno Das Neves --- arch/arm64/hyperv/hv_core.c | 14 +++--- arch/arm64/hyperv/mshyperv.c | 2 +- arch/arm64/include/asm/hyperv-tlfs.h | 12 ++-- arch/x86/kernel/cpu/mshyperv.c | 2 +- include/asm-generic/hyperv-tlfs.h| 16 5 files changed, 23 insertions(+), 23 deletions(-) diff --git a/arch/arm64/hyperv/hv_core.c b/arch/arm64/hyperv/hv_core.c index b54c34793701..f1ebc025e1df 100644 --- a/arch/arm64/hyperv/hv_core.c +++ b/arch/arm64/hyperv/hv_core.c @@ -160,22 +160,22 @@ void hyperv_report_panic(struct pt_regs *regs, long err, bool in_die) return; panic_reported = true; - guest_id = hv_get_vpreg(HV_REGISTER_GUEST_OSID); + guest_id = hv_get_vpreg(HV_REGISTER_GUEST_OS_ID); /* * Hyper-V provides the ability to store only 5 values. * Pick the passed in error value, the guest_id, the PC, * and the SP. */ - hv_set_vpreg(HV_REGISTER_CRASH_P0, err); - hv_set_vpreg(HV_REGISTER_CRASH_P1, guest_id); - hv_set_vpreg(HV_REGISTER_CRASH_P2, regs->pc); - hv_set_vpreg(HV_REGISTER_CRASH_P3, regs->sp); - hv_set_vpreg(HV_REGISTER_CRASH_P4, 0); + hv_set_vpreg(HV_REGISTER_GUEST_CRASH_P0, err); + hv_set_vpreg(HV_REGISTER_GUEST_CRASH_P1, guest_id); + hv_set_vpreg(HV_REGISTER_GUEST_CRASH_P2, regs->pc); + hv_set_vpreg(HV_REGISTER_GUEST_CRASH_P3, regs->sp); + hv_set_vpreg(HV_REGISTER_GUEST_CRASH_P4, 0); /* * Let Hyper-V know there is crash data available */ - hv_set_vpreg(HV_REGISTER_CRASH_CTL, HV_CRASH_CTL_CRASH_NOTIFY); + hv_set_vpreg(HV_REGISTER_GUEST_CRASH_CTL, HV_CRASH_CTL_CRASH_NOTIFY); } EXPORT_SYMBOL_GPL(hyperv_report_panic); diff --git a/arch/arm64/hyperv/mshyperv.c b/arch/arm64/hyperv/mshyperv.c index 99362716ac87..03ac88bb9d10 100644 --- a/arch/arm64/hyperv/mshyperv.c +++ b/arch/arm64/hyperv/mshyperv.c @@ -46,7 +46,7 @@ static int __init hyperv_init(void) /* Setup the guest ID */ guest_id = hv_generate_guest_id(LINUX_VERSION_CODE); - hv_set_vpreg(HV_REGISTER_GUEST_OSID, guest_id); + hv_set_vpreg(HV_REGISTER_GUEST_OS_ID, guest_id); /* Get the features and hints from Hyper-V */ hv_get_vpreg_128(HV_REGISTER_FEATURES, &result); diff --git a/arch/arm64/include/asm/hyperv-tlfs.h b/arch/arm64/include/asm/hyperv-tlfs.h index 54846d1d29c3..bc30aadedfe9 100644 --- a/arch/arm64/include/asm/hyperv-tlfs.h +++ b/arch/arm64/include/asm/hyperv-tlfs.h @@ -37,12 +37,12 @@ * - On x86, HV_MSR_ indicates an MSR accessed via rdmsrl/wrmsrl * - On ARM, HV_MSR_ indicates a VP register accessed via hypercall */ -#define HV_MSR_CRASH_P0(HV_REGISTER_CRASH_P0) -#define HV_MSR_CRASH_P1(HV_REGISTER_CRASH_P1) -#define HV_MSR_CRASH_P2(HV_REGISTER_CRASH_P2) -#define HV_MSR_CRASH_P3(HV_REGISTER_CRASH_P3) -#define HV_MSR_CRASH_P4(HV_REGISTER_CRASH_P4) -#define HV_MSR_CRASH_CTL (HV_REGISTER_CRASH_CTL) +#define HV_MSR_CRASH_P0(HV_REGISTER_GUEST_CRASH_P0) +#define HV_MSR_CRASH_P1(HV_REGISTER_GUEST_CRASH_P1) +#define HV_MSR_CRASH_P2(HV_REGISTER_GUEST_CRASH_P2) +#define HV_MSR_CRASH_P3(HV_REGISTER_GUEST_CRASH_P3) +#define HV_MSR_CRASH_P4(HV_REGISTER_GUEST_CRASH_P4) +#define HV_MSR_CRASH_CTL (HV_REGISTER_GUEST_CRASH_CTL) #define HV_MSR_VP_INDEX(HV_REGISTER_VP_INDEX) #define HV_MSR_TIME_REF_COUNT (HV_REGISTER_TIME_REF_COUNT) diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c index 56e731d8f513..909a6236a4c0 100644 --- a/arch/x86/kernel/cpu/mshyperv.c +++ b/arch/x86/kernel/cpu/mshyperv.c @@ -450,7 +450,7 @@ static void __init ms_hyperv_init_platform(void) /* To be supported: more work is required. */ ms_hyperv.features &= ~HV_MSR_REFERENCE_TSC_AVAILABLE; - /* HV_REGISTER_CRASH_CTL is unsupported. */ + /* HV_MSR_CRASH_CTL is unsupported. */ ms_hyperv.misc_features &= ~HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE; /* Don't trust Hyper-V's TLB-flushing hypercalls. */ diff --git a/include/asm-generic/hyperv-tlfs.h b/include/asm-generic/hyperv-tlfs.h index 32514a870b98..87e3d49a4e29 100644 --- a/include/asm-generic/hyperv-tlfs.h +++ b/include/asm-generic/hyperv-t
Re: [PATCH v3 1/1] x86/hyperv: Use Hyper-V entropy to seed guest random number generator
On 3/18/2024 8:54 AM, mhkelle...@gmail.com wrote: > From: Michael Kelley > > A Hyper-V host provides its guest VMs with entropy in a custom ACPI > table named "OEM0". The entropy bits are updated each time Hyper-V > boots the VM, and are suitable for seeding the Linux guest random > number generator (rng). See a brief description of OEM0 in [1]. > > Generation 2 VMs on Hyper-V use UEFI to boot. Existing EFI code in > Linux seeds the rng with entropy bits from the EFI_RNG_PROTOCOL. > Via this path, the rng is seeded very early during boot with good > entropy. The ACPI OEM0 table provided in such VMs is an additional > source of entropy. > > Generation 1 VMs on Hyper-V boot from BIOS. For these VMs, Linux > doesn't currently get any entropy from the Hyper-V host. While this > is not fundamentally broken because Linux can generate its own entropy, > using the Hyper-V host provided entropy would get the rng off to a > better start and would do so earlier in the boot process. > > Improve the rng seeding for Generation 1 VMs by having Hyper-V specific > code in Linux take advantage of the OEM0 table to seed the rng. For > Generation 2 VMs, use the OEM0 table to provide additional entropy > beyond the EFI_RNG_PROTOCOL. Because the OEM0 table is custom to > Hyper-V, parse it directly in the Hyper-V code in the Linux kernel > and use add_bootloader_randomness() to add it to the rng. Once the > entropy bits are read from OEM0, zero them out in the table so > they don't appear in /sys/firmware/acpi/tables/OEM0 in the running > VM. The zero'ing is done out of an abundance of caution to avoid > potential security risks to the rng. Also set the OEM0 data length > to zero so a kexec or other subsequent use of the table won't try > to use the zero'ed bits. > > [1] > https://download.microsoft.com/download/1/c/9/1c9813b8-089c-4fef-b2ad-ad80e79403ba/Whitepaper%20-%20The%20Windows%2010%20random%20number%20generation%20infrastructure.pdf > > Signed-off-by: Michael Kelley > --- > Changes in v3: > * Removed restriction to just Generation 1 VMs. Generation 2 VMs > now also use the additional entropy even though they also get > initial entropy via EFI_RNG_PROTOCOL [Jason Donenfeld] > * Process the OEM0 table on ARM64 systems in addition to x86/x64, > as a result of no longer excluding Generation 2 VM. > * Enlarge the range of entropy byte counts that are considered valid > in the OEM0 table. New range is 8 to 4K; previously the range was > 32 to 256. [Jason Donenfeld] > * After processing the entropy bits in OEM0, also set the OEM0 > table length to indicate that the entropy byte count is zero, > to prevent a subsequent kexec or other use of the table from > trying to use the zero'ed bits. [Jason Donenfeld] > > Changes in v2: > * Tweaked commit message [Wei Liu] > * Removed message when OEM0 table isn't found. Added debug-level > message when OEM0 is successfully used to add randomness. [Wei Liu] > > arch/arm64/hyperv/mshyperv.c | 2 + > arch/x86/kernel/cpu/mshyperv.c | 1 + > drivers/hv/hv_common.c | 69 ++ > include/asm-generic/mshyperv.h | 2 + > 4 files changed, 74 insertions(+) > > diff --git a/arch/arm64/hyperv/mshyperv.c b/arch/arm64/hyperv/mshyperv.c > index f1b8a04ee9f2..c8193cec1b90 100644 > --- a/arch/arm64/hyperv/mshyperv.c > +++ b/arch/arm64/hyperv/mshyperv.c > @@ -74,6 +74,8 @@ static int __init hyperv_init(void) > return ret; > } > > + ms_hyperv_late_init(); > + > hyperv_initialized = true; > return 0; > } > diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c > index 303fef824167..65c9cbdd2282 100644 > --- a/arch/x86/kernel/cpu/mshyperv.c > +++ b/arch/x86/kernel/cpu/mshyperv.c > @@ -648,6 +648,7 @@ const __initconst struct hypervisor_x86 > x86_hyper_ms_hyperv = { > .init.x2apic_available = ms_hyperv_x2apic_available, > .init.msi_ext_dest_id = ms_hyperv_msi_ext_dest_id, > .init.init_platform = ms_hyperv_init_platform, > + .init.guest_late_init = ms_hyperv_late_init, > #ifdef CONFIG_AMD_MEM_ENCRYPT > .runtime.sev_es_hcall_prepare = hv_sev_es_hcall_prepare, > .runtime.sev_es_hcall_finish = hv_sev_es_hcall_finish, > diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c > index 0285a74363b3..724de94d885f 100644 > --- a/drivers/hv/hv_common.c > +++ b/drivers/hv/hv_common.c > @@ -20,8 +20,11 @@ > #include > #include > #include > +#include > +#include > #include > #include > +#include > #include > #include > #include > @@ -347,6 +350,72 @@ int __init hv_common_init(void) > return 0; > } > > +void __init ms_hyperv_late_init(void) > +{ > + struct acpi_table_header *header; > + acpi_status status; > + u8 *randomdata; > + u32 length, i; > + > + /* > + * Seed the Linux random number generator with entropy provided by > + * the Hyper-V host in ACPI table OEM0. > + */ > + if
[PATCH v3] mshyperv: Introduce hv_numa_node_to_pxm_info()
Factor out logic for converting numa node to hv_proximity_domain_info into a helper function. Change hv_proximity_domain_info to a struct to improve readability. While at it, rename hv_add_logical_processor_* structs to the correct hv_input_/hv_output_ prefix, and remove the flags field which is not present in the ABI. Signed-off-by: Nuno Das Neves Reviewed-by: Wei Liu --- Changes in v3: * Shorten function name to hv_numa_node_to_pxm_info() * Correct hv_add_logical_processor_* naming, and remove flags Changes in v2: * Change hv_proximity_domain_info from union to struct to improve readability [Dave Hanson] --- arch/x86/hyperv/hv_proc.c | 22 -- include/asm-generic/hyperv-tlfs.h | 19 +++ include/asm-generic/mshyperv.h| 14 ++ 3 files changed, 25 insertions(+), 30 deletions(-) diff --git a/arch/x86/hyperv/hv_proc.c b/arch/x86/hyperv/hv_proc.c index 68a0843d4750..3fa1f2ee7b0d 100644 --- a/arch/x86/hyperv/hv_proc.c +++ b/arch/x86/hyperv/hv_proc.c @@ -3,7 +3,6 @@ #include #include #include -#include #include #include #include @@ -116,12 +115,11 @@ int hv_call_deposit_pages(int node, u64 partition_id, u32 num_pages) int hv_call_add_logical_proc(int node, u32 lp_index, u32 apic_id) { - struct hv_add_logical_processor_in *input; - struct hv_add_logical_processor_out *output; + struct hv_input_add_logical_processor *input; + struct hv_output_add_logical_processor *output; u64 status; unsigned long flags; int ret = HV_STATUS_SUCCESS; - int pxm = node_to_pxm(node); /* * When adding a logical processor, the hypervisor may return @@ -137,11 +135,7 @@ int hv_call_add_logical_proc(int node, u32 lp_index, u32 apic_id) input->lp_index = lp_index; input->apic_id = apic_id; - input->flags = 0; - input->proximity_domain_info.domain_id = pxm; - input->proximity_domain_info.flags.reserved = 0; - input->proximity_domain_info.flags.proximity_info_valid = 1; - input->proximity_domain_info.flags.proximity_preferred = 1; + input->proximity_domain_info = hv_numa_node_to_pxm_info(node); status = hv_do_hypercall(HVCALL_ADD_LOGICAL_PROCESSOR, input, output); local_irq_restore(flags); @@ -166,7 +160,6 @@ int hv_call_create_vp(int node, u64 partition_id, u32 vp_index, u32 flags) u64 status; unsigned long irq_flags; int ret = HV_STATUS_SUCCESS; - int pxm = node_to_pxm(node); /* Root VPs don't seem to need pages deposited */ if (partition_id != hv_current_partition_id) { @@ -185,14 +178,7 @@ int hv_call_create_vp(int node, u64 partition_id, u32 vp_index, u32 flags) input->vp_index = vp_index; input->flags = flags; input->subnode_type = HvSubnodeAny; - if (node != NUMA_NO_NODE) { - input->proximity_domain_info.domain_id = pxm; - input->proximity_domain_info.flags.reserved = 0; - input->proximity_domain_info.flags.proximity_info_valid = 1; - input->proximity_domain_info.flags.proximity_preferred = 1; - } else { - input->proximity_domain_info.as_uint64 = 0; - } + input->proximity_domain_info = hv_numa_node_to_pxm_info(node); status = hv_do_hypercall(HVCALL_CREATE_VP, input, NULL); local_irq_restore(irq_flags); diff --git a/include/asm-generic/hyperv-tlfs.h b/include/asm-generic/hyperv-tlfs.h index 87e3d49a4e29..814207e7c37f 100644 --- a/include/asm-generic/hyperv-tlfs.h +++ b/include/asm-generic/hyperv-tlfs.h @@ -512,13 +512,9 @@ struct hv_proximity_domain_flags { u32 proximity_info_valid : 1; } __packed; -/* Not a union in windows but useful for zeroing */ -union hv_proximity_domain_info { - struct { - u32 domain_id; - struct hv_proximity_domain_flags flags; - }; - u64 as_uint64; +struct hv_proximity_domain_info { + u32 domain_id; + struct hv_proximity_domain_flags flags; } __packed; struct hv_lp_startup_status { @@ -532,14 +528,13 @@ struct hv_lp_startup_status { } __packed; /* HvAddLogicalProcessor hypercall */ -struct hv_add_logical_processor_in { +struct hv_input_add_logical_processor { u32 lp_index; u32 apic_id; - union hv_proximity_domain_info proximity_domain_info; - u64 flags; + struct hv_proximity_domain_info proximity_domain_info; } __packed; -struct hv_add_logical_processor_out { +struct hv_output_add_logical_processor { struct hv_lp_startup_status startup_status; } __packed; @@ -560,7 +555,7 @@ struct hv_cr
Re: [PATCH] Drivers: hv: vmbus: Deferring per cpu tasks
On 7/24/2024 10:26 PM, Saurabh Sengar wrote: > Currently on a very large system with 1780 CPUs, hv_acpi_init takes > around 3 seconds to complete for all the CPUs. This is because of > sequential synic initialization for each CPU. > > Defer these tasks so that each CPU executes hv_acpi_init in parallel > to take full advantage of multiple CPUs. I think you mean hv_synic_init() here, not hv_acpi_init()? > > This solution saves around 2 seconds of boot time on a 1780 CPU system, > that around 66% improvement in the existing logic. > > Signed-off-by: Saurabh Sengar > --- > drivers/hv/vmbus_drv.c | 33 ++--- > 1 file changed, 30 insertions(+), 3 deletions(-) > LGTM otherwise. Reviewed-by: Nuno Das Neves
Re: [PATCH 5/5] hyperv: Use hvhdk.h instead of hyperv-tlfs.h in Hyper-V code
On 10/4/2024 8:58 AM, Stanislav Kinsburskii wrote: > Hi Nuno, > > On Thu, Oct 03, 2024 at 12:51:04PM -0700, Nuno Das Neves wrote: >> diff --git a/arch/arm64/hyperv/hv_core.c b/arch/arm64/hyperv/hv_core.c >> index 9d1969b875e9..bb7f28f74bf4 100644 >> --- a/arch/arm64/hyperv/hv_core.c >> +++ b/arch/arm64/hyperv/hv_core.c >> @@ -14,6 +14,7 @@ >> #include >> #include >> #include >> +#define HYPERV_NONTLFS_HEADERS >> #include >> > > Perhaps it would be cleaner to introduce a new header file to be > included, containing the new define and including instead. > > Stas If I understand correctly, you're suggesting adding another stub named e.g. "hv_mshyperv.h", containing: #define HYPERV_NONTLFS_HEADERS #include Then in the roughly 24 places in this patch where we have: +#define HYPERV_NONTLFS_HEADERS Instead, we'd have: -#include +#include I suppose the current version is a bit opaque - it's not immediately clear why HYPERV_NONTLFs_HEADERS is defined, and that it must be defined before including asm/mshyperv.h - someone reading the code would have to go find hv_defs.h to puzzle that out. This improves the situation slightly by associating the #define with asm/mshyperv.h. I'll consider it for v2, thanks! Nuno
Re: [PATCH 5/5] hyperv: Use hvhdk.h instead of hyperv-tlfs.h in Hyper-V code
On 10/4/2024 12:11 PM, Simon Horman wrote: > Hi, > > With this change in place I see allmodconfig x86_64 builds reporting that > HV_REGISTER_FEATURES is undeclared. > > arch/arm64/hyperv/mshyperv.c: In function 'hyperv_init': > arch/arm64/hyperv/mshyperv.c:53:26: error: 'HV_REGISTER_FEATURES' undeclared > (first use in this function); did you mean 'HV_REGISTER_FEATURES_INFO'? >53 | hv_get_vpreg_128(HV_REGISTER_FEATURES, &result); > | ^~~~ > | HV_REGISTER_FEATURES_INFO > arch/arm64/hyperv/mshyperv.c:53:26: note: each undeclared identifier is > reported only once for each function it appears in > arch/arm64/hyperv/mshyperv.c:58:26: error: 'HV_REGISTER_ENLIGHTENMENTS' > undeclared (first use in this function); did you mean > 'HV_ACCESS_REENLIGHTENMENT'? >58 | hv_get_vpreg_128(HV_REGISTER_ENLIGHTENMENTS, &result); > | ^~ > | HV_ACCESS_REENLIGHTENMENT > Ah, I did forgot to check arm64. Thanks for the catch, I'll be sure to fix it for v2. > > And here too, with x86_64 allmodconfig. > > In file included from ./include/linux/string.h:390, > from ./include/linux/efi.h:16, > from arch/x86/hyperv/hv_init.c:12: > arch/x86/hyperv/hv_init.c: In function 'get_vtl': > ./include/linux/overflow.h:372:23: error: invalid application of 'sizeof' to > incomplete type 'struct hv_get_vp_registers_input' > 372 | sizeof(*(p)) + flex_array_size(p, member, count), > \ > | ^ > ./include/linux/fortify-string.h:502:42: note: in definition of macro > '__fortify_memset_chk' > 502 | size_t __fortify_size = (size_t)(size); > \ > | ^~~~ > arch/x86/hyperv/hv_init.c:427:9: note: in expansion of macro 'memset' > 427 | memset(input, 0, struct_size(input, element, 1)); > | ^~ > arch/x86/hyperv/hv_init.c:427:26: note: in expansion of macro 'struct_size' > 427 | memset(input, 0, struct_size(input, element, 1)); > | ^~~ > > [errors trimmed for the sake of brevity] > > ... > Thanks > > And, likewise, with this patch applied I see a number of errors when > compiling this file. This is with allmodconfig on x86_64 with: > > Modified: CONFIG_HYPERV=y (instead of m) > Added: CONFIG_HYPERV_VTL_MODE=y > Thanks again, Ah, I wish there was a way to check these different combinations of y/m more easily. > arch/x86/hyperv/hv_vtl.c: In function 'hv_vtl_bringup_vcpu': > arch/x86/hyperv/hv_vtl.c:154:34: error: 'HVCALL_ENABLE_VP_VTL' undeclared > (first use in this function) > 154 | status = hv_do_hypercall(HVCALL_ENABLE_VP_VTL, input, NULL); > | ^~~~ > arch/x86/hyperv/hv_vtl.c:154:34: note: each undeclared identifier is reported > only once for each function it appears in > In file included from ./include/linux/string.h:390, > from ./include/linux/bitmap.h:13, > from ./include/linux/cpumask.h:12, > from ./arch/x86/include/asm/apic.h:5, > from arch/x86/hyperv/hv_vtl.c:9: > arch/x86/hyperv/hv_vtl.c: In function 'hv_vtl_apicid_to_vp_id': > arch/x86/hyperv/hv_vtl.c:189:32: error: invalid application of 'sizeof' to > incomplete type 'struct hv_get_vp_from_apic_id_in' > 189 | memset(input, 0, sizeof(*input)); > |^ > ./include/linux/fortify-string.h:502:42: note: in definition of macro > '__fortify_memset_chk' > 502 | size_t __fortify_size = (size_t)(size); > \ > | ^~~~ > arch/x86/hyperv/hv_vtl.c:189:9: note: in expansion of macro 'memset' > 189 | memset(input, 0, sizeof(*input)); > | ^~ > arch/x86/hyperv/hv_vtl.c:190:14: error: invalid use of undefined type 'struct > hv_get_vp_from_apic_id_in' > 190 | input->partition_id = HV_PARTITION_ID_SELF; > | ^~ > arch/x86/hyperv/hv_vtl.c:191:14: error: invalid use of undefined type 'struct > hv_get_vp_from_apic_id_in' > 191 | input->apic_ids[0] = apic_id; > | ^~ > arch/x86/hyperv/hv_vtl.c:195:45: error: 'HVCALL_GET_VP_ID_FROM_APIC_ID' > undeclared (first use in this function) > 195 | control = HV_HYPERCALL_REP_COMP_1 | > HVCALL_GET_VP_ID_FROM_APIC_ID; > | > ^ > > ... Looks like I'm missing a one or two definitions in the new headers, and the names have changed slightly in couple of cases. I'll do some more thorough checking and have it all fixed for v2. I didn't know about this allmodconfig target, that will make it a bit easier! Nuno
[PATCH 4/5] hyperv: Add hv_defs.h to conditionally include hyperv-tlfs.h or hvhdk.h
Include one or the other depending on whether HYPERV_NONTLFS_HEADERS is defined. This will allow Hyper-V code to use the new headers while other code can continue using hyperv-tlfs.h which is only for Hyper-V guests. Replace hyperv-tlfs.h in shared headers with hv_defs.h These headers are shared between Hyper-V code and non-Hyper-V code (KVM for example). This will allow switching to the new headers in Hyper-V code only. Signed-off-by: Nuno Das Neves --- arch/arm64/include/asm/mshyperv.h | 2 +- arch/x86/include/asm/mshyperv.h| 2 +- arch/x86/include/asm/svm.h | 2 +- include/asm-generic/mshyperv.h | 2 +- include/clocksource/hyperv_timer.h | 2 +- include/hyperv/hv_defs.h | 29 + 6 files changed, 34 insertions(+), 5 deletions(-) create mode 100644 include/hyperv/hv_defs.h diff --git a/arch/arm64/include/asm/mshyperv.h b/arch/arm64/include/asm/mshyperv.h index a975e1a689dd..13b2b2218d85 100644 --- a/arch/arm64/include/asm/mshyperv.h +++ b/arch/arm64/include/asm/mshyperv.h @@ -20,7 +20,7 @@ #include #include -#include +#include /* * Declare calls to get and set Hyper-V VP register values on ARM64, which diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h index 47ca48062547..dc8587f02850 100644 --- a/arch/x86/include/asm/mshyperv.h +++ b/arch/x86/include/asm/mshyperv.h @@ -6,9 +6,9 @@ #include #include #include -#include #include #include +#include /* * Hyper-V always provides a single IO-APIC at this MMIO address. diff --git a/arch/x86/include/asm/svm.h b/arch/x86/include/asm/svm.h index f0dea3750ca9..c682fc080310 100644 --- a/arch/x86/include/asm/svm.h +++ b/arch/x86/include/asm/svm.h @@ -5,7 +5,7 @@ #include #include -#include +#include /* * 32-bit intercept words in the VMCB Control Area, starting diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h index 8fe7aaab2599..8bd308ae1056 100644 --- a/include/asm-generic/mshyperv.h +++ b/include/asm-generic/mshyperv.h @@ -25,7 +25,7 @@ #include #include #include -#include +#include #define VTPM_BASE_ADDRESS 0xfed4 diff --git a/include/clocksource/hyperv_timer.h b/include/clocksource/hyperv_timer.h index 6cdc873ac907..068ca1934c23 100644 --- a/include/clocksource/hyperv_timer.h +++ b/include/clocksource/hyperv_timer.h @@ -15,7 +15,7 @@ #include #include -#include +#include #define HV_MAX_MAX_DELTA_TICKS 0x #define HV_MIN_DELTA_TICKS 1 diff --git a/include/hyperv/hv_defs.h b/include/hyperv/hv_defs.h new file mode 100644 index ..eed500288499 --- /dev/null +++ b/include/hyperv/hv_defs.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * This file includes Microsoft Hypervisor definitions from hyperv-tlfs.h, or + * hvhdk.h when HYPERV_NONTLFS_HEADERS is defined. + */ +/* + * NOTE: + * The typical #ifdef guard to prevent redefinition errors is intentionally + * omitted. This makes compiler error (either via #error or redefinition) in + * the case where hyperv-tlfs.h is accidentally included, followed by + * definition of HYPERV_NON_TLFS_HEADERS and inclusion of this file. + * If this file could only be included once, the compiler would ignore the + * attempt to use HYPERV_NONTLFS_HEADERS to include hvhdk.h. + */ + +#ifdef HYPERV_NONTLFS_HEADERS + +#ifdef HYPERV_TLFS_HEADERS_INCLUDED +#error "hyperv-tlfs.h was already included before HYPERV_NONTLFS_HEADERS was defined" +#else +#include +#endif + +#else /* HYPERV_NONTLFS_HEADERS */ + +#include +#define HYPERV_TLFS_HEADERS_INCLUDED + +#endif /* !HYPERV_NONTLFS_HEADERS */ -- 2.34.1
[PATCH 1/5] hyperv: Move hv_connection_id to hyperv-tlfs.h
This definition is in the wrong file; it is part of the TLFS doc. Signed-off-by: Nuno Das Neves --- include/asm-generic/hyperv-tlfs.h | 9 + include/linux/hyperv.h| 9 - 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/include/asm-generic/hyperv-tlfs.h b/include/asm-generic/hyperv-tlfs.h index 814207e7c37f..52274c9aefef 100644 --- a/include/asm-generic/hyperv-tlfs.h +++ b/include/asm-generic/hyperv-tlfs.h @@ -871,4 +871,13 @@ struct hv_mmio_write_input { u8 data[HV_HYPERCALL_MMIO_MAX_DATA_LENGTH]; } __packed; +/* Define connection identifier type. */ +union hv_connection_id { + u32 asu32; + struct { + u32 id:24; + u32 reserved:8; + } u; +}; + #endif diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index 22c22fb91042..d0893ec488ae 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -768,15 +768,6 @@ struct vmbus_close_msg { struct vmbus_channel_close_channel msg; }; -/* Define connection identifier type. */ -union hv_connection_id { - u32 asu32; - struct { - u32 id:24; - u32 reserved:8; - } u; -}; - enum vmbus_device_type { HV_IDE = 0, HV_SCSI, -- 2.34.1
[PATCH 0/5] Add new headers for Hyper-V Dom0
To support Hyper-V Dom0 (aka Linux as root partition), many new definitions are required. The plan going forward is to directly import headers from Hyper-V. This is a more maintainable way to import definitions rather than via the TLFS doc. This patch series introduces new headers (hvhdk.h, hvgdk.h, etc, see patch #3) directly derived from Hyper-V code. This patch series replaces hyperv-tlfs.h with hvhdk.h, but only in Microsoft-maintained Hyper-V code where they are needed. This leaves the existing hyperv-tlfs.h in use elsewhere - notably for Hyper-V enlightenments on KVM guests. An intermediary header "hv_defs.h" is introduced to conditionally include either hyperv-tlfs.h or hvhdk.h. This is required because several headers which today include hyperv-tlfs.h, are shared between Hyper-V and KVM code (e.g. mshyperv.h). Summary: Patch 1-2: Cleanup patches Patch 3: Add the new headers (hvhdk.h, etc..) in include/hyperv/ Patch 4: Add hv_defs.h and use it in mshyperv.h, svm.h, hyperv_timer.h Patch 5: Switch to the new headers, only in Hyper-V code Nuno Das Neves (5): hyperv: Move hv_connection_id to hyperv-tlfs.h hyperv: Remove unnecessary #includes hyperv: Add new Hyper-V headers hyperv: Add hv_defs.h to conditionally include hyperv-tlfs.h or hvhdk.h hyperv: Use hvhdk.h instead of hyperv-tlfs.h in Hyper-V code arch/arm64/hyperv/hv_core.c |3 +- arch/arm64/hyperv/mshyperv.c |1 + arch/arm64/include/asm/mshyperv.h|2 +- arch/x86/entry/vdso/vma.c|1 + arch/x86/hyperv/hv_apic.c|2 +- arch/x86/hyperv/hv_init.c|3 +- arch/x86/hyperv/hv_proc.c|4 +- arch/x86/hyperv/hv_spinlock.c|1 + arch/x86/hyperv/hv_vtl.c |1 + arch/x86/hyperv/irqdomain.c |1 + arch/x86/hyperv/ivm.c|2 +- arch/x86/hyperv/mmu.c|2 +- arch/x86/hyperv/nested.c |2 +- arch/x86/include/asm/kvm_host.h |1 - arch/x86/include/asm/mshyperv.h |3 +- arch/x86/include/asm/svm.h |2 +- arch/x86/include/asm/vdso/gettimeofday.h |1 + arch/x86/kernel/cpu/mshyperv.c |2 +- arch/x86/kernel/cpu/mtrr/generic.c |1 + arch/x86/kvm/vmx/vmx_onhyperv.h |1 - arch/x86/mm/pat/set_memory.c |2 - drivers/clocksource/hyperv_timer.c |2 +- drivers/hv/channel.c |1 + drivers/hv/channel_mgmt.c|1 + drivers/hv/connection.c |1 + drivers/hv/hv.c |1 + drivers/hv/hv_balloon.c |5 +- drivers/hv/hv_common.c |2 +- drivers/hv/hv_kvp.c |1 - drivers/hv/hv_snapshot.c |1 - drivers/hv/hv_util.c |1 + drivers/hv/hyperv_vmbus.h|1 - drivers/hv/ring_buffer.c |1 + drivers/hv/vmbus_drv.c |1 + drivers/iommu/hyperv-iommu.c |1 + drivers/net/hyperv/netvsc.c |1 + drivers/pci/controller/pci-hyperv.c |1 + include/asm-generic/hyperv-tlfs.h|9 + include/asm-generic/mshyperv.h |2 +- include/clocksource/hyperv_timer.h |2 +- include/hyperv/hv_defs.h | 29 + include/hyperv/hvgdk.h | 66 ++ include/hyperv/hvgdk_ext.h | 46 + include/hyperv/hvgdk_mini.h | 1212 ++ include/hyperv/hvhdk.h | 733 + include/hyperv/hvhdk_mini.h | 310 ++ include/linux/hyperv.h | 12 +- net/vmw_vsock/hyperv_transport.c |1 - 48 files changed, 2442 insertions(+), 40 deletions(-) create mode 100644 include/hyperv/hv_defs.h create mode 100644 include/hyperv/hvgdk.h create mode 100644 include/hyperv/hvgdk_ext.h create mode 100644 include/hyperv/hvgdk_mini.h create mode 100644 include/hyperv/hvhdk.h create mode 100644 include/hyperv/hvhdk_mini.h -- 2.34.1
[PATCH 2/5] hyperv: Remove unnecessary #includes
asm/hyperv-tlfs.h is already included implicitly wherever mshyperv.h or linux/hyperv.h is included. Remove those redundancies. Remove includes of linux/hyperv.h and mshyperv.h where they are not needed. Signed-off-by: Nuno Das Neves --- arch/arm64/hyperv/hv_core.c| 2 -- arch/x86/hyperv/hv_apic.c | 1 - arch/x86/hyperv/hv_init.c | 2 -- arch/x86/hyperv/hv_proc.c | 1 - arch/x86/hyperv/ivm.c | 1 - arch/x86/hyperv/mmu.c | 1 - arch/x86/hyperv/nested.c | 1 - arch/x86/include/asm/kvm_host.h| 1 - arch/x86/include/asm/mshyperv.h| 1 - arch/x86/kernel/cpu/mshyperv.c | 1 - arch/x86/kvm/vmx/vmx_onhyperv.h| 1 - arch/x86/mm/pat/set_memory.c | 2 -- drivers/clocksource/hyperv_timer.c | 1 - drivers/hv/hv_balloon.c| 2 -- drivers/hv/hv_common.c | 1 - drivers/hv/hv_kvp.c| 1 - drivers/hv/hv_snapshot.c | 1 - drivers/hv/hyperv_vmbus.h | 1 - net/vmw_vsock/hyperv_transport.c | 1 - 19 files changed, 23 deletions(-) diff --git a/arch/arm64/hyperv/hv_core.c b/arch/arm64/hyperv/hv_core.c index f1ebc025e1df..9d1969b875e9 100644 --- a/arch/arm64/hyperv/hv_core.c +++ b/arch/arm64/hyperv/hv_core.c @@ -11,11 +11,9 @@ #include #include #include -#include #include #include #include -#include #include /* diff --git a/arch/x86/hyperv/hv_apic.c b/arch/x86/hyperv/hv_apic.c index 0569f579338b..f022d5f64fb6 100644 --- a/arch/x86/hyperv/hv_apic.c +++ b/arch/x86/hyperv/hv_apic.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c index 17a71e92a343..fc3c3d76c181 100644 --- a/arch/x86/hyperv/hv_init.c +++ b/arch/x86/hyperv/hv_init.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include @@ -27,7 +26,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/x86/hyperv/hv_proc.c b/arch/x86/hyperv/hv_proc.c index 3fa1f2ee7b0d..b74c06c04ff1 100644 --- a/arch/x86/hyperv/hv_proc.c +++ b/arch/x86/hyperv/hv_proc.c @@ -3,7 +3,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/x86/hyperv/ivm.c b/arch/x86/hyperv/ivm.c index 60fc3ed72830..b56d70612734 100644 --- a/arch/x86/hyperv/ivm.c +++ b/arch/x86/hyperv/ivm.c @@ -7,7 +7,6 @@ */ #include -#include #include #include #include diff --git a/arch/x86/hyperv/mmu.c b/arch/x86/hyperv/mmu.c index 1cc113200ff5..cc8c3bd0e7c2 100644 --- a/arch/x86/hyperv/mmu.c +++ b/arch/x86/hyperv/mmu.c @@ -1,6 +1,5 @@ #define pr_fmt(fmt) "Hyper-V: " fmt -#include #include #include #include diff --git a/arch/x86/hyperv/nested.c b/arch/x86/hyperv/nested.c index 9dc259fa322e..ee06d0315c24 100644 --- a/arch/x86/hyperv/nested.c +++ b/arch/x86/hyperv/nested.c @@ -11,7 +11,6 @@ #include -#include #include #include diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 4a68cb3eba78..3627eab994a3 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -24,7 +24,6 @@ #include #include #include -#include #include #include diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h index 390c4d13956d..47ca48062547 100644 --- a/arch/x86/include/asm/mshyperv.h +++ b/arch/x86/include/asm/mshyperv.h @@ -9,7 +9,6 @@ #include #include #include -#include /* * Hyper-V always provides a single IO-APIC at this MMIO address. diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c index e0fd57a8ba84..8e8fd23b1439 100644 --- a/arch/x86/kernel/cpu/mshyperv.c +++ b/arch/x86/kernel/cpu/mshyperv.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/x86/kvm/vmx/vmx_onhyperv.h b/arch/x86/kvm/vmx/vmx_onhyperv.h index eb48153bfd73..f4b081eb6521 100644 --- a/arch/x86/kvm/vmx/vmx_onhyperv.h +++ b/arch/x86/kvm/vmx/vmx_onhyperv.h @@ -3,7 +3,6 @@ #ifndef __ARCH_X86_KVM_VMX_ONHYPERV_H__ #define __ARCH_X86_KVM_VMX_ONHYPERV_H__ -#include #include #include diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c index 44f7b2ea6a07..85fa0d4509f0 100644 --- a/arch/x86/mm/pat/set_memory.c +++ b/arch/x86/mm/pat/set_memory.c @@ -32,8 +32,6 @@ #include #include #include -#include -#include #include "../mm_internal.h" diff --git a/drivers/clocksource/hyperv_timer.c b/drivers/clocksource/hyperv_timer.c index b2a080647e41..1b7de45a7185 100644 --- a/drivers/clocksource/hyperv_timer.c +++ b/drivers/clocksource/hyperv_timer.c @@ -23,7 +23,6 @@ #include #include #include -#include #include static struct clock_event_device __percpu *hv_clock_event; diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c index c38dcdfcb914..a120e9b80ded 100644 --- a/drivers/hv/hv_bal
[PATCH 3/5] hyperv: Add new Hyper-V headers
Add definitions needed for privileged Hyper-V partitions. These files are derived from headers exported from the hypervisor code. This is a step toward importing headers directly, similar to Xen public files in include/xen/interface/. Signed-off-by: Nuno Das Neves --- include/hyperv/hvgdk.h | 66 ++ include/hyperv/hvgdk_ext.h | 46 ++ include/hyperv/hvgdk_mini.h | 1212 +++ include/hyperv/hvhdk.h | 733 + include/hyperv/hvhdk_mini.h | 310 + 5 files changed, 2367 insertions(+) create mode 100644 include/hyperv/hvgdk.h create mode 100644 include/hyperv/hvgdk_ext.h create mode 100644 include/hyperv/hvgdk_mini.h create mode 100644 include/hyperv/hvhdk.h create mode 100644 include/hyperv/hvhdk_mini.h diff --git a/include/hyperv/hvgdk.h b/include/hyperv/hvgdk.h new file mode 100644 index ..af44e8034090 --- /dev/null +++ b/include/hyperv/hvgdk.h @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Type definitions for the Microsoft Hypervisor. + */ +#ifndef _HV_HVGDK_H +#define _HV_HVGDK_H + +#include "hvgdk_mini.h" +#include "hvgdk_ext.h" + +/* + * The guest OS needs to register the guest ID with the hypervisor. + * The guest ID is a 64 bit entity and the structure of this ID is + * specified in the Hyper-V TLFS specification. + * + * While the current guideline does not specify how Linux guest ID(s) + * need to be generated, our plan is to publish the guidelines for + * Linux and other guest operating systems that currently are hosted + * on Hyper-V. The implementation here conforms to this yet + * unpublished guidelines. + * + * Bit(s) + * 63 - Indicates if the OS is Open Source or not; 1 is Open Source + * 62:56 - Os Type; Linux is 0x100 + * 55:48 - Distro specific identification + * 47:16 - Linux kernel version number + * 15:0 - Distro specific identification + */ + +#define HV_LINUX_VENDOR_ID 0x8100 + +/* + * Hyper-V uses the software reserved 32 bytes in VMCB control area to expose + * SVM enlightenments to guests. This is documented in the TLFS doc. + * HV_VMX_ENLIGHTENED_VMCS or SVM_NESTED_ENLIGHTENED_VMCB_FIELDS + */ +struct hv_vmcb_enlightenments { + struct __packed hv_enlightenments_control { + u32 nested_flush_hypercall : 1; + u32 msr_bitmap : 1; + u32 enlightened_npt_tlb: 1; + u32 reserved : 29; + } __packed hv_enlightenments_control; + u32 hv_vp_id; + u64 hv_vm_id; + u64 partition_assist_page; + u64 reserved; +} __packed; + +/* Define connection identifier type. */ +union hv_connection_id { + u32 asu32; + struct { + u32 id : 24; + u32 reserved : 8; + } __packed u; +}; + +struct hv_input_unmap_gpa_pages { + u64 target_partition_id; + u64 target_gpa_base; + u32 unmap_flags; + u32 padding; +} __packed; + +#endif /* #ifndef _HV_HVGDK_H */ diff --git a/include/hyperv/hvgdk_ext.h b/include/hyperv/hvgdk_ext.h new file mode 100644 index ..641b591ee61f --- /dev/null +++ b/include/hyperv/hvgdk_ext.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Type definitions for the Microsoft Hypervisor. + */ +#ifndef _HV_HVGDK_EXT_H +#define _HV_HVGDK_EXT_H + +#include "hvgdk_mini.h" + +/* Extended hypercalls */ +#define HV_EXT_CALL_QUERY_CAPABILITIES 0x8001 +#define HV_EXT_CALL_MEMORY_HEAT_HINT 0x8003 + +/* Extended hypercalls */ +enum { /* HV_EXT_CALL */ + HV_EXTCALL_QUERY_CAPABILITIES = 0x8001, + HV_EXTCALL_MEMORY_HEAT_HINT = 0x8003, +}; + +/* HV_EXT_OUTPUT_QUERY_CAPABILITIES */ +#define HV_EXT_CAPABILITY_MEMORY_COLD_DISCARD_HINT BIT(8) + +enum { /* HV_EXT_MEMORY_HEAT_HINT_TYPE */ + HV_EXTMEM_HEAT_HINT_COLD = 0, + HV_EXTMEM_HEAT_HINT_HOT = 1, + HV_EXTMEM_HEAT_HINT_COLD_DISCARD = 2, + HV_EXTMEM_HEAT_HINT_MAX +}; + +/* + * The whole argument should fit in a page to be able to pass to the hypervisor + * in one hypercall. + */ +#define HV_MEMORY_HINT_MAX_GPA_PAGE_RANGES \ + ((HV_HYP_PAGE_SIZE - sizeof(struct hv_memory_hint)) / \ + sizeof(union hv_gpa_page_range)) + +/* HvExtCallMemoryHeatHint hypercall */ +#define HV_EXT_MEMORY_HEAT_HINT_TYPE_COLD_DISCARD 2 +struct hv_memory_hint {/* HV_EXT_INPUT_MEMORY_HEAT_HINT */ + u64 heat_type : 2; /* HV_EXTMEM_HEAT_HINT_* */ + u64 reserved : 62; + union hv_gpa_page_range ranges[]; +} __packed; + +#endif /* _HV_HVGDK_EXT_H */ diff --git a/include/hyperv/hvgdk_mini.h b/include/hyperv/hvgdk_mini.h new file mode 100644 index ..b7dd22784c96 --- /dev/null +++ b/include/hyperv/hvgdk_mini.h @@ -0,0 +1,1212 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Type definitions for the Microsoft hypervisor. + */ +#ifndef _HV_HVGDK_MINI_H +#define _HV_HVGDK_MINI_H + +#include +#include + +struct
[PATCH 5/5] hyperv: Use hvhdk.h instead of hyperv-tlfs.h in Hyper-V code
To move toward importing headers from Hyper-V directly, switch to using hvhdk.h in all Hyper-V code. KVM code that uses Hyper-V definitions from hyperv-tlfs.h remains untouched. Add HYPERV_NONTLFS_HEADERS everywhere mshyperv.h, asm/svm.h, clocksource/hyperv_timer.h is included in Hyper-V code. Replace hyperv-tlfs.h with hvhdk.h directly in linux/hyperv.h, and define HYPERV_NONTLFS_HEADERS there, since it is only used in Hyper-V device code. Update a couple of definitions to updated names found in the new headers: HV_EXT_MEM_HEAT_HINT, HV_SUBNODE_TYPE_ANY. Signed-off-by: Nuno Das Neves --- arch/arm64/hyperv/hv_core.c | 1 + arch/arm64/hyperv/mshyperv.c | 1 + arch/x86/entry/vdso/vma.c| 1 + arch/x86/hyperv/hv_apic.c| 1 + arch/x86/hyperv/hv_init.c| 1 + arch/x86/hyperv/hv_proc.c| 3 ++- arch/x86/hyperv/hv_spinlock.c| 1 + arch/x86/hyperv/hv_vtl.c | 1 + arch/x86/hyperv/irqdomain.c | 1 + arch/x86/hyperv/ivm.c| 1 + arch/x86/hyperv/mmu.c| 1 + arch/x86/hyperv/nested.c | 1 + arch/x86/include/asm/vdso/gettimeofday.h | 1 + arch/x86/kernel/cpu/mshyperv.c | 1 + arch/x86/kernel/cpu/mtrr/generic.c | 1 + drivers/clocksource/hyperv_timer.c | 1 + drivers/hv/channel.c | 1 + drivers/hv/channel_mgmt.c| 1 + drivers/hv/connection.c | 1 + drivers/hv/hv.c | 1 + drivers/hv/hv_balloon.c | 3 ++- drivers/hv/hv_common.c | 1 + drivers/hv/hv_util.c | 1 + drivers/hv/ring_buffer.c | 1 + drivers/hv/vmbus_drv.c | 1 + drivers/iommu/hyperv-iommu.c | 1 + drivers/net/hyperv/netvsc.c | 1 + drivers/pci/controller/pci-hyperv.c | 1 + include/linux/hyperv.h | 3 ++- 29 files changed, 32 insertions(+), 3 deletions(-) diff --git a/arch/arm64/hyperv/hv_core.c b/arch/arm64/hyperv/hv_core.c index 9d1969b875e9..bb7f28f74bf4 100644 --- a/arch/arm64/hyperv/hv_core.c +++ b/arch/arm64/hyperv/hv_core.c @@ -14,6 +14,7 @@ #include #include #include +#define HYPERV_NONTLFS_HEADERS #include /* diff --git a/arch/arm64/hyperv/mshyperv.c b/arch/arm64/hyperv/mshyperv.c index b1a4de4eee29..62b2a270ae65 100644 --- a/arch/arm64/hyperv/mshyperv.c +++ b/arch/arm64/hyperv/mshyperv.c @@ -15,6 +15,7 @@ #include #include #include +#define HYPERV_NONTLFS_HEADERS #include static bool hyperv_initialized; diff --git a/arch/x86/entry/vdso/vma.c b/arch/x86/entry/vdso/vma.c index 6d83ceb7f1ba..5f4053c49658 100644 --- a/arch/x86/entry/vdso/vma.c +++ b/arch/x86/entry/vdso/vma.c @@ -25,6 +25,7 @@ #include #include #include +#define HYPERV_NONTLFS_HEADERS #include #undef _ASM_X86_VVAR_H diff --git a/arch/x86/hyperv/hv_apic.c b/arch/x86/hyperv/hv_apic.c index f022d5f64fb6..4fe3b3b13256 100644 --- a/arch/x86/hyperv/hv_apic.c +++ b/arch/x86/hyperv/hv_apic.c @@ -26,6 +26,7 @@ #include #include #include +#define HYPERV_NONTLFS_HEADERS #include #include diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c index fc3c3d76c181..680c4abc456e 100644 --- a/arch/x86/hyperv/hv_init.c +++ b/arch/x86/hyperv/hv_init.c @@ -19,6 +19,7 @@ #include #include #include +#define HYPERV_NONTLFS_HEADERS #include #include #include diff --git a/arch/x86/hyperv/hv_proc.c b/arch/x86/hyperv/hv_proc.c index b74c06c04ff1..428542134b84 100644 --- a/arch/x86/hyperv/hv_proc.c +++ b/arch/x86/hyperv/hv_proc.c @@ -7,6 +7,7 @@ #include #include #include +#define HYPERV_NONTLFS_HEADERS #include #include @@ -176,7 +177,7 @@ int hv_call_create_vp(int node, u64 partition_id, u32 vp_index, u32 flags) input->partition_id = partition_id; input->vp_index = vp_index; input->flags = flags; - input->subnode_type = HvSubnodeAny; + input->subnode_type = HV_SUBNODE_ANY; input->proximity_domain_info = hv_numa_node_to_pxm_info(node); status = hv_do_hypercall(HVCALL_CREATE_VP, input, NULL); local_irq_restore(irq_flags); diff --git a/arch/x86/hyperv/hv_spinlock.c b/arch/x86/hyperv/hv_spinlock.c index 151e851bef09..7e8e2c03f669 100644 --- a/arch/x86/hyperv/hv_spinlock.c +++ b/arch/x86/hyperv/hv_spinlock.c @@ -12,6 +12,7 @@ #include +#define HYPERV_NONTLFS_HEADERS #include #include #include diff --git a/arch/x86/hyperv/hv_vtl.c b/arch/x86/hyperv/hv_vtl.c index 04775346369c..a8bb6ad7efb6 100644 --- a/arch/x86/hyperv/hv_vtl.c +++ b/arch/x86/hyperv/hv_vtl.c @@ -10,6 +10,7 @@ #include #include #include +#define HYPERV_NONTLFS_HEADERS #include #include #include <../kernel/smpboot.h> diff --git a/arch/x86/hyperv/irqdomain.c b/arch/x86/hyperv/irqdom
Re: [EXTERNAL] RE: [PATCH 0/5] Add new headers for Hyper-V Dom0
Michael - sorry for the delay, I just got back from vacation. On 10/10/2024 6:34 PM, MUKESH RATHOR wrote: > > > On 10/10/24 11:21, Michael Kelley wrote: > > From: Nuno Das Neves Sent: > Thursday, October 3, 2024 12:51 PM > >> > >> To support Hyper-V Dom0 (aka Linux as root partition), many new > >> definitions are required. > >> > >> The plan going forward is to directly import headers from > >> Hyper-V. This is a more maintainable way to import definitions > >> rather than via the TLFS doc. This patch series introduces > >> new headers (hvhdk.h, hvgdk.h, etc, see patch #3) directly > >> derived from Hyper-V code. > >> > >> This patch series replaces hyperv-tlfs.h with hvhdk.h, but only > >> in Microsoft-maintained Hyper-V code where they are needed. This > >> leaves the existing hyperv-tlfs.h in use elsewhere - notably for > >> Hyper-V enlightenments on KVM guests. > > > > Could you elaborate on why the bifurcation is necessary? Is it an > > interim step until the KVM code can use the new scheme as well? It's not strictly necessary. We chose this approach in order to minimize any potential impact on KVM and other non-Microsoft- maintained code that uses hyperv-tlfs.h. As Mukesh mentioned below, eventually it will be better if everyone uses the new headers. > > Also, does "Hyper-V enlightenments on KVM guests" refer to > > nested KVM running at L1 on an L0 Hyper-V, and supporting L2 guests? > > Or is it the more general KVM support for mimicking Hyper-V for > > the purposes of running Windows guests? From these patches, it > > looks like your intention is for all KVM support for Hyper-V > > functionality to continue to use the existing hyperv-tlfs.h file. You're correct - "all KVM support for Hyper-V" is really what I meant. > > Like it says above, we are creating new dom0 (root/host) support > that requires many new defs only available to dom0 and not any > guest. Hypervisor makes them publicly available via hv*dk files. > > Ideally, someday everybody will use those, I hope we can move in > that direction, but I guess one step at a time. For now, KVM can > continue to use the tlfs file, and if there is no resistance, we > can move them to hv*dk files also as next step and obsolete the > single tlfs file. > > Since headers are the ultimate source of truth, this will allow > better maintenance, better debug/support experience, and a more > stable stack. It also enforces non-leaking of data structs from > private header files (unfortunately has happened). > > Thanks > -Mukesh > Thanks for providing the additional context, Mukesh. Nuno
Re: [PATCH 0/5] Add new headers for Hyper-V Dom0
On 10/10/2024 11:21 AM, Michael Kelley wrote: > From: Nuno Das Neves Sent: Thursday, > October 3, 2024 12:51 PM >>>> An intermediary header "hv_defs.h" is introduced to conditionally >> include either hyperv-tlfs.h or hvhdk.h. This is required because >> several headers which today include hyperv-tlfs.h, are shared >> between Hyper-V and KVM code (e.g. mshyperv.h). > > Have you considered user space code that uses > include/linux/hyperv.h? Which of the two schemes will it use? That code > needs to compile correctly on x86 and ARM64 after your changes. > User space code includes the separate DPDK project, and some of the > tools in the kernel tree under tools/hv. Anything that uses the > uio_hv_generic.c driver falls into this category. > Unless I misunderstand something, the uapi code isn't affected at all by this patch set. e.g. the code in tools/hv uses include/uapi/linux/hyperv.h, which doesn't include any other Hyper-V headers. I'm not aware of how the DPDK project uses the Hyper-V definitions, but if it is getting headers from uapi it should also be unaffected. > I think there's also user space code that is built for vDSO that might pull > in the .h files you are modifying. There are in-progress patches dealing > with vDSO include files, such as [1]. My general comment on vDSO > is to be careful in making #include file changes that it uses, but I'm > not knowledgeable enough on how vDSO is built to give specific > guidance. :-( > Hmm, interesting, looks like it does get used by userspace. The tsc page is mapped into userspace in vdso.vma.c, and read in vdso/gettimeofday.h. That is unexpected for me, since these things aren't in uapi. However I don't anticipate a problem. The definitions used haven't changed, just the headers they are included from. Thanks Nuno > Michael > > [1] > https://lore.kernel.org/lkml/20241010135146.181175-1-vincenzo.frasc...@arm.com/ > >> >> Summary: >> Patch 1-2: Cleanup patches >> Patch 3: Add the new headers (hvhdk.h, etc..) in include/hyperv/ >> Patch 4: Add hv_defs.h and use it in mshyperv.h, svm.h, >> hyperv_timer.h >> Patch 5: Switch to the new headers, only in Hyper-V code >> >> Nuno Das Neves (5): >> hyperv: Move hv_connection_id to hyperv-tlfs.h >> hyperv: Remove unnecessary #includes >> hyperv: Add new Hyper-V headers >> hyperv: Add hv_defs.h to conditionally include hyperv-tlfs.h or >> hvhdk.h >> hyperv: Use hvhdk.h instead of hyperv-tlfs.h in Hyper-V code >> >> arch/arm64/hyperv/hv_core.c |3 +- >> arch/arm64/hyperv/mshyperv.c |1 + >> arch/arm64/include/asm/mshyperv.h|2 +- >> arch/x86/entry/vdso/vma.c|1 + >> arch/x86/hyperv/hv_apic.c|2 +- >> arch/x86/hyperv/hv_init.c|3 +- >> arch/x86/hyperv/hv_proc.c|4 +- >> arch/x86/hyperv/hv_spinlock.c|1 + >> arch/x86/hyperv/hv_vtl.c |1 + >> arch/x86/hyperv/irqdomain.c |1 + >> arch/x86/hyperv/ivm.c|2 +- >> arch/x86/hyperv/mmu.c|2 +- >> arch/x86/hyperv/nested.c |2 +- >> arch/x86/include/asm/kvm_host.h |1 - >> arch/x86/include/asm/mshyperv.h |3 +- >> arch/x86/include/asm/svm.h |2 +- >> arch/x86/include/asm/vdso/gettimeofday.h |1 + >> arch/x86/kernel/cpu/mshyperv.c |2 +- >> arch/x86/kernel/cpu/mtrr/generic.c |1 + >> arch/x86/kvm/vmx/vmx_onhyperv.h |1 - >> arch/x86/mm/pat/set_memory.c |2 - >> drivers/clocksource/hyperv_timer.c |2 +- >> drivers/hv/channel.c |1 + >> drivers/hv/channel_mgmt.c|1 + >> drivers/hv/connection.c |1 + >> drivers/hv/hv.c |1 + >> drivers/hv/hv_balloon.c |5 +- >> drivers/hv/hv_common.c |2 +- >> drivers/hv/hv_kvp.c |1 - >> drivers/hv/hv_snapshot.c |1 - >> drivers/hv/hv_util.c |1 + >> drivers/hv/hyperv_vmbus.h|1 - >> drivers/hv/ring_buffer.c |1 + >> drivers/hv/vmbus_drv.c |1 + >> drivers/iommu/hyperv-iommu.c |1 + >> drivers/net/hyperv/netvsc.c |1 + >> drivers/pci/controller/pci-hyperv.c |1 + >> include/asm-generic/hyper
Re: [PATCH 2/5] hyperv: Remove unnecessary #includes
On 10/10/2024 11:21 AM, Michael Kelley wrote: > From: Nuno Das Neves Sent: Thursday, > October 3, 2024 12:51 PM >> >> asm/hyperv-tlfs.h is already included implicitly wherever mshyperv.h >> or linux/hyperv.h is included. Remove those redundancies. > > I've been under the impression that it is preferable to directly include > .h files for all definitions that a source code file uses, even if the > needed .h file is indirectly included by some other .h file. I looked through I've also heard this idea, and generally try to stick to it. I myself haven't yet encountered a situation where doing this or not has greatly impacted the readability of the code. > the coding style documentation, and didn't find anything addressing > this topic, so maybe I'm wrong. But I know I've seen patches to other > parts of the kernel that were changes to follow the direct inclusion > approach. Direct inclusion is less fragile if the #include file nesting > structure changes (and perhaps removes the indirect inclusion). > > The mshyperv.h and linux/hyperv.h dependency on hyperv-tlfs.h is > highly unlikely to change, so the chance of breakage is minimal. But You probably already understood this after seeing the later patches, but it's worth pointing out that the goal of this series is to change that dependency (situationally), which is exactly why I created this precursor patch. > I wonder if your approach is going the wrong direction vs. preferred > kernel practices. > I could replace with in most of these cases (in v2), to preserve the explicit include of the definitions before mshyperv.h or linux/hyperv.h. I will give it a try in v2. Thanks, Nuno > Michael > >> >> Remove includes of linux/hyperv.h and mshyperv.h where they are not >> needed. >> >> Signed-off-by: Nuno Das Neves >> --- >> arch/arm64/hyperv/hv_core.c| 2 -- >> arch/x86/hyperv/hv_apic.c | 1 - >> arch/x86/hyperv/hv_init.c | 2 -- >> arch/x86/hyperv/hv_proc.c | 1 - >> arch/x86/hyperv/ivm.c | 1 - >> arch/x86/hyperv/mmu.c | 1 - >> arch/x86/hyperv/nested.c | 1 - >> arch/x86/include/asm/kvm_host.h| 1 - >> arch/x86/include/asm/mshyperv.h| 1 - >> arch/x86/kernel/cpu/mshyperv.c | 1 - >> arch/x86/kvm/vmx/vmx_onhyperv.h| 1 - >> arch/x86/mm/pat/set_memory.c | 2 -- >> drivers/clocksource/hyperv_timer.c | 1 - >> drivers/hv/hv_balloon.c| 2 -- >> drivers/hv/hv_common.c | 1 - >> drivers/hv/hv_kvp.c| 1 - >> drivers/hv/hv_snapshot.c | 1 - >> drivers/hv/hyperv_vmbus.h | 1 - >> net/vmw_vsock/hyperv_transport.c | 1 - >> 19 files changed, 23 deletions(-) >> >> diff --git a/arch/arm64/hyperv/hv_core.c b/arch/arm64/hyperv/hv_core.c >> index f1ebc025e1df..9d1969b875e9 100644 >> --- a/arch/arm64/hyperv/hv_core.c >> +++ b/arch/arm64/hyperv/hv_core.c >> @@ -11,11 +11,9 @@ >> #include >> #include >> #include >> -#include >> #include >> #include >> #include >> -#include >> #include >> >> /* >> diff --git a/arch/x86/hyperv/hv_apic.c b/arch/x86/hyperv/hv_apic.c >> index 0569f579338b..f022d5f64fb6 100644 >> --- a/arch/x86/hyperv/hv_apic.c >> +++ b/arch/x86/hyperv/hv_apic.c >> @@ -23,7 +23,6 @@ >> #include >> #include >> #include >> -#include >> #include >> #include >> #include >> diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c >> index 17a71e92a343..fc3c3d76c181 100644 >> --- a/arch/x86/hyperv/hv_init.c >> +++ b/arch/x86/hyperv/hv_init.c >> @@ -19,7 +19,6 @@ >> #include >> #include >> #include >> -#include >> #include >> #include >> #include >> @@ -27,7 +26,6 @@ >> #include >> #include >> #include >> -#include >> #include >> #include >> #include >> diff --git a/arch/x86/hyperv/hv_proc.c b/arch/x86/hyperv/hv_proc.c >> index 3fa1f2ee7b0d..b74c06c04ff1 100644 >> --- a/arch/x86/hyperv/hv_proc.c >> +++ b/arch/x86/hyperv/hv_proc.c >> @@ -3,7 +3,6 @@ >> #include >> #include >> #include >> -#include >> #include >> #include >> #include >> diff --git a/arch/x86/hyperv/ivm.c b/arch/x86/hyperv/ivm.c >> index 60fc3ed72830..b56d70612734 100644 >> --- a/arch/x86/hyperv/ivm.c >> +++ b/arch/x86/hyperv/ivm.c >> @@ -7,7 +7,6 @@ >> */ >> >> #include >> -#include &
Re: [PATCH v2 3/4] hyperv: Add new Hyper-V headers in include/hyperv
On 11/10/2024 8:13 PM, Michael Kelley wrote: > From: Nuno Das Neves Sent: Thursday, > November 7, 2024 2:32 PM >> >> These headers contain definitions for regular Hyper-V guests (as in >> hyperv-tlfs.h), as well as interfaces for more privileged guests like >> Dom0. > > See my comment on Patch 0/4 about use of "dom0" terminology. > Thanks, noted. >> >> These files are derived from headers exported from Hyper-V, rather than >> being derived from the TLFS document. (Although, to preserve >> compatibility with existing Linux code, some definitions are copied >> directly from hyperv-tlfs.h too). >> >> The new files follow a naming convention according to their original >> use: >> - hdk "host development kit" >> - gdk "guest development kit" >> With postfix "_mini" implying userspace-only headers, and "_ext" for >> extended hypercalls. >> >> These names should be considered a rough guide only - since there are >> many places already where both host and guest code are in the same >> place, hvhdk.h (which includes everything) can be used most of the time. > > Just curious -- are there really cases where hvhdk.h can't be used? > If so, could you summarize why? > No, there aren't cases where it "can't" be used. I suppose if someone doesn't want to include everything, perhaps they could just include hvgdk.h, for example. It doesn't really matter though. > I ask because it would be nice to expand slightly on your paragraph > below, as follows: (if indeed what I've added is correct) > > The use of multiple files and their original names is primarily to > keep the provenance of exactly where they came from in Hyper-V > code, which is helpful for manual maintenance and extension > of these definitions. Microsoft maintainers importing new definitions > should take care to put them in the right file. However, Linux kernel code > that uses any of the definitions need not be aware of the multiple files > or assign any meaning to the new names. Linux kernel uses should > always just include hvhdk.h > Thanks, I think that additional sentence helps clarify things. I'll include it in the next version, and I think I can probably omit the prior paragraph: "These names should be considered a rough guide only...". >> >> The original names are kept intact primarily to keep the provenance of >> exactly where they came from in Hyper-V code, which is helpful for >> manual maintenance and extension of these definitions. Microsoft >> maintainers importing new definitions should take care to put them in >> the right file. >> >> Note also that the files contain both arm64 and x86_64 code guarded by >> \#ifdefs, which is how the definitions originally appear in Hyper-V. > > Spurious backslash? > Indeed, thanks. > I would suggest some additional clarification: The #ifdef guards are > employed minimally where necessary to prevent conflicts due to > different definitions for the same thing on x86_64 and arm64. Where > there are no conflicts, the union of x86_64 definitions and arm64 > definitions is visible when building for either architecture. In other > words, not all definitions specific to x86_64 are protected by #ifdef > x86_64. Such unprotected definitions may be visible when building > for arm64. And vice versa. > Is there a reason you specifically want to point out that "Such unprotected definitions may be visible when building for arm64. And vice versa."? I think, in all the cases where #ifdefs are not used, an arch-specific prefix is used - hv_x64_ or hv_arm64_. The main thing I wanted to call out here was the reasoning for not splitting arch-specific definitions into separate files in arch/x86/ and arch/arm64/ as is typical in Linux. Maybe this is a bit clearer: " Note the new headers contain both arm64 and x86_64 definitions. Some are guarded by #ifdefs, and some are instead prefixed with the architecture, e.g. hv_x64_*. These conventions are kept from Hyper-V code as another tactic to simplify the process of importing and maintaining the definitions, rather than splitting them up into their own files in arch/x86/ and arch/arm64/. " I hope it's reasonably clear that it's a good tradeoff to go against Linux convention in this case, to make it easy to import and maintain Hyper-V definitions. Thanks Nuno > Michael > >> Keeping this convention from Hyper-V code is another tactic for >> simplying the process of importing new definitions. >> >> These headers are a step toward importing headers directly from Hyper-V >> in the future, similar to Xen public files in includ
Re: [PATCH v2 3/4] hyperv: Add new Hyper-V headers in include/hyperv
On 11/7/2024 9:59 PM, Naman Jain wrote: > > > On 11/8/2024 4:02 AM, Nuno Das Neves wrote: >> These headers contain definitions for regular Hyper-V guests (as in >> hyperv-tlfs.h), as well as interfaces for more privileged guests like >> Dom0. >> >> These files are derived from headers exported from Hyper-V, rather than >> being derived from the TLFS document. (Although, to preserve >> compatibility with existing Linux code, some definitions are copied >> directly from hyperv-tlfs.h too). >> >> The new files follow a naming convention according to their original >> use: >> - hdk "host development kit" >> - gdk "guest development kit" >> With postfix "_mini" implying userspace-only headers, and "_ext" for >> extended hypercalls. > > Naming convention for mini (which may have come from HyperV code) is a bit > odd TBH. May be it has more to it than what is mentioned here or what I know. > If more information helps, or this can be changed, please see. > The naming is originally from the Hyper-V code. See below: "The original names are kept intact primarily to keep the provenance of exactly where they came from in Hyper-V code, which is helpful for manual maintenance and extension of these definitions." >> >> These names should be considered a rough guide only - since there are >> many places already where both host and guest code are in the same >> place, hvhdk.h (which includes everything) can be used most of the time. >> >> The original names are kept intact primarily to keep the provenance of >> exactly where they came from in Hyper-V code, which is helpful for >> manual maintenance and extension of these definitions. Microsoft >> maintainers importing new definitions should take care to put them in >> the right file. >> >> Note also that the files contain both arm64 and x86_64 code guarded by >> \#ifdefs, which is how the definitions originally appear in Hyper-V. >> Keeping this convention from Hyper-V code is another tactic for >> simplying the process of importing new definitions. >> >> These headers are a step toward importing headers directly from Hyper-V >> in the future, similar to Xen public files in include/xen/interface/. >> >> Signed-off-by: Nuno Das Neves > > While I understand the motivation behind this series that this is going to > ease out the process of updating the header files with respect to HyperV, I > think, we will need to pay attention to what we are bringing in with these > headers, whether there are any users of it or not, and make sure that TLFS > document is updated regularly, to avoid having bunch of code with no > information of it. > The code comments in these files are one step forward towards that. > And from your cover letter it seems that some changes which actually make use > of these additional interfaces are underway, so things will make more sense > later. For now, this looks good to me. > Yes, we do need to be careful about what interfaces we add here. Not just anything can be copied from Hyper-V code into these files. The exact process is a matter we can discuss internally. But, as you say, there are upcoming patches (previous versions can be found in the mailing list) which use the new root partition interfaces. Updating the TLFS and documenting the interfaces is a different matter. I can't speak to the best way forward for documenting these, but in many cases the use of the new interfaces will be self-evident from the code that uses them, and/or comments as you mentioned. Over the years many Hyper-V definitions have already been added and used in Linux which have not been documented in the TLFS or elsewhere. This patch series makes that fact more obvious and sets us on a path towards a more maintainable method (i.e., publishing headers directly from the Hyper-V code, hopefully). Thanks Nuno > > Regards, > Naman > >
Re: [PATCH v2 0/4] Add new headers for Hyper-V Dom0
On 11/10/2024 8:12 PM, Michael Kelley wrote: > From: Nuno Das Neves Sent: Thursday, > November 7, 2024 2:32 PM >> >> To support Hyper-V Dom0 (aka Linux as root partition), many new >> definitions are required. > > Using "dom0" terminology here and in the Subject: line is likely to > be confusing to folks who aren't intimately involved in Hyper-V work. > Previous Linux kernel commit messages and code for running in the > Hyper-V root partition use "root partition" terminology, and I couldn't > find "dom0" having been used before. "root partition" would be more > consistent, and it also matches the public documentation for Hyper-V. > "dom0" is Xen specific terminology, and having it show up in Hyper-V > patches would be confusing for the casual reader. I know "dom0" has > been used internally at Microsoft as shorthand for "Hyper-V root > partition", but it's probably best to completely avoid such shorthand > in public Linux kernel patches and code. > > Just my $.02 > Noted - I will update the terminology in v3 and generally avoid "Dom0", except possibly by way of explanation (i.e. to compare it to Xen Dom0). Thanks Nuno >> >> The plan going forward is to directly import definitions from >> Hyper-V code without waiting for them to land in the TLFS document. >> This is a quicker and more maintainable way to import definitions, >> and is a step toward the eventual goal of exporting headers directly >> from Hyper-V for use in Linux. >> >> This patch series introduces new headers (hvhdk.h, hvgdk.h, etc, >> see patch #3) derived directly from Hyper-V code. hyperv-tlfs.h is >> replaced with hvhdk.h (which includes the other new headers) >> everywhere. >> >> No functional change is expected. >> >> Summary: >> Patch 1-2: Minor cleanup patches >> Patch 3: Add the new headers (hvhdk.h, etc..) in include/hyperv/ >> Patch 4: Switch to the new headers >> >> Signed-off-by: Nuno Das Neves >> --- >> Changelog: >> v2: >> - Rework the series to simply use the new headers everywhere >> instead of fiddling around to keep hyperv-tlfs.h used in some >> places, suggested by Michael Kelley and Easwar Hariharan > > Thanks! That should be simpler all around. > > Michael > >> - Fix compilation errors with some configs by adding missing >> definitions and changing some names, thanks to Simon Horman for >> catching those >> - Add additional definitions to the new headers to support them now >> replacing hyperv-tlfs.h everywhere >> - Add additional context in the commit messages for patches #3 and #4 >> - In patch #2, don't remove indirect includes. Only remove includes >> which truly aren't used, suggested by Michael Kelley >> >> --- >> Nuno Das Neves (4): >> hyperv: Move hv_connection_id to hyperv-tlfs.h >> hyperv: Clean up unnecessary #includes >> hyperv: Add new Hyper-V headers in include/hyperv >> hyperv: Switch from hyperv-tlfs.h to hyperv/hvhdk.h >> >> arch/arm64/hyperv/hv_core.c|3 +- >> arch/arm64/hyperv/mshyperv.c |4 +- >> arch/arm64/include/asm/mshyperv.h |2 +- >> arch/x86/hyperv/hv_apic.c |1 - >> arch/x86/hyperv/hv_init.c | 21 +- >> arch/x86/hyperv/hv_proc.c |3 +- >> arch/x86/hyperv/ivm.c |1 - >> arch/x86/hyperv/mmu.c |1 - >> arch/x86/hyperv/nested.c |2 +- >> arch/x86/include/asm/kvm_host.h|3 +- >> arch/x86/include/asm/mshyperv.h|3 +- >> arch/x86/include/asm/svm.h |2 +- >> arch/x86/kernel/cpu/mshyperv.c |2 +- >> arch/x86/kvm/vmx/hyperv_evmcs.h|2 +- >> arch/x86/kvm/vmx/vmx_onhyperv.h|2 +- >> arch/x86/mm/pat/set_memory.c |2 - >> drivers/clocksource/hyperv_timer.c |2 +- >> drivers/hv/hv_balloon.c|4 +- >> drivers/hv/hv_common.c |2 +- >> drivers/hv/hv_kvp.c|2 +- >> drivers/hv/hv_snapshot.c |2 +- >> drivers/hv/hyperv_vmbus.h |2 +- >> include/asm-generic/hyperv-tlfs.h |9 + >> include/asm-generic/mshyperv.h |2 +- >> include/clocksource/hyperv_timer.h |2 +- >> include/hyperv/hvgdk.h | 303 +++ >> include/hyperv/hvgdk_ext.h | 46 + >> include/hyperv/hvgdk_mini.h| 1295 >> include/hyperv/hvhdk.h | 733 >> include/hyperv/hvhdk_mini.h| 310 +++ >> include/linux/hyperv.h | 11 +- >> net/vmw_vsock/hyperv_transport.c |2 +- >> 32 files changed, 2729 insertions(+), 52 deletions(-) >> create mode 100644 include/hyperv/hvgdk.h >> create mode 100644 include/hyperv/hvgdk_ext.h >> create mode 100644 include/hyperv/hvgdk_mini.h >> create mode 100644 include/hyperv/hvhdk.h >> create mode 100644 include/hyperv/hvhdk_mini.h >> >> -- >> 2.34.1
Re: [PATCH 0/5] Add new headers for Hyper-V Dom0
On 10/31/2024 12:05 PM, Easwar Hariharan wrote: > On 10/3/2024 12:50 PM, Nuno Das Neves wrote: >> To support Hyper-V Dom0 (aka Linux as root partition), many new >> definitions are required. >> >> The plan going forward is to directly import headers from >> Hyper-V. This is a more maintainable way to import definitions >> rather than via the TLFS doc. This patch series introduces >> new headers (hvhdk.h, hvgdk.h, etc, see patch #3) directly >> derived from Hyper-V code. >> >> This patch series replaces hyperv-tlfs.h with hvhdk.h, but only >> in Microsoft-maintained Hyper-V code where they are needed. This >> leaves the existing hyperv-tlfs.h in use elsewhere - notably for >> Hyper-V enlightenments on KVM guests. >> >> An intermediary header "hv_defs.h" is introduced to conditionally >> include either hyperv-tlfs.h or hvhdk.h. This is required because >> several headers which today include hyperv-tlfs.h, are shared >> between Hyper-V and KVM code (e.g. mshyperv.h). >> >> Summary: >> Patch 1-2: Cleanup patches >> Patch 3: Add the new headers (hvhdk.h, etc..) in include/hyperv/ >> Patch 4: Add hv_defs.h and use it in mshyperv.h, svm.h, >> hyperv_timer.h >> Patch 5: Switch to the new headers, only in Hyper-V code >> >> Nuno Das Neves (5): >> hyperv: Move hv_connection_id to hyperv-tlfs.h >> hyperv: Remove unnecessary #includes >> hyperv: Add new Hyper-V headers >> hyperv: Add hv_defs.h to conditionally include hyperv-tlfs.h or >> hvhdk.h >> hyperv: Use hvhdk.h instead of hyperv-tlfs.h in Hyper-V code >> Hi Easwar, thanks for the questions. I will attempt to clarify. > > What is the model for Hyper-V code that has both guest and host roles > where the corresponding hypercalls are available for both? As I > understand it, those are supposed to be in hvgdk*.h. > It's true that the naming of the files implies hvgdk*.h is for guests, and hvhdk*.h (which includes hvgdk*.h), is for hosts/dom0. But I would only take that as a rough guide. The real reason for keeping these names is to make it a easier to copy and maintain the definitions from the Windows code into Linux, by keeping the provenance of exactly where they came from. > For a specific example, IOMMU hypercalls can operate on stage 2 or stage > 1 translations depending on the role of the (hyper) caller and the input > values provided. Should a driver using these hypercalls import both > hvhdk* and hvgdk*? What about hyperv-tlfs? > I'd recommend importing hvhdk.h since it contains everything you need (including hvgdk*.h). The goal of this patchset is to move away from hyperv-tlfs.h, because by definition it should only contain definitions from the TLFS document. > Patches 4 and 5 seem to draw a bright line between host and guest roles > while the reality is more gray. Please do correct me if I'm wrong here, > perhaps the picture would be clearer if Stas' suggestion of a new header > file is implemented. > Patches 4 and 5 introduce the new headers in a way that avoids any potential impact on KVM and other non-Microsoft-maintained code. The 'line' is not between guest and host, but between Microsoft-maintained and non-Microsoft-maintained code. Thanks, Nuno > Thanks, > Easwar
[PATCH v2 3/4] hyperv: Add new Hyper-V headers in include/hyperv
These headers contain definitions for regular Hyper-V guests (as in hyperv-tlfs.h), as well as interfaces for more privileged guests like Dom0. These files are derived from headers exported from Hyper-V, rather than being derived from the TLFS document. (Although, to preserve compatibility with existing Linux code, some definitions are copied directly from hyperv-tlfs.h too). The new files follow a naming convention according to their original use: - hdk "host development kit" - gdk "guest development kit" With postfix "_mini" implying userspace-only headers, and "_ext" for extended hypercalls. These names should be considered a rough guide only - since there are many places already where both host and guest code are in the same place, hvhdk.h (which includes everything) can be used most of the time. The original names are kept intact primarily to keep the provenance of exactly where they came from in Hyper-V code, which is helpful for manual maintenance and extension of these definitions. Microsoft maintainers importing new definitions should take care to put them in the right file. Note also that the files contain both arm64 and x86_64 code guarded by \#ifdefs, which is how the definitions originally appear in Hyper-V. Keeping this convention from Hyper-V code is another tactic for simplying the process of importing new definitions. These headers are a step toward importing headers directly from Hyper-V in the future, similar to Xen public files in include/xen/interface/. Signed-off-by: Nuno Das Neves --- include/hyperv/hvgdk.h | 303 include/hyperv/hvgdk_ext.h | 46 ++ include/hyperv/hvgdk_mini.h | 1295 +++ include/hyperv/hvhdk.h | 733 include/hyperv/hvhdk_mini.h | 310 + 5 files changed, 2687 insertions(+) create mode 100644 include/hyperv/hvgdk.h create mode 100644 include/hyperv/hvgdk_ext.h create mode 100644 include/hyperv/hvgdk_mini.h create mode 100644 include/hyperv/hvhdk.h create mode 100644 include/hyperv/hvhdk_mini.h diff --git a/include/hyperv/hvgdk.h b/include/hyperv/hvgdk.h new file mode 100644 index ..9687c6570dfb --- /dev/null +++ b/include/hyperv/hvgdk.h @@ -0,0 +1,303 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Type definitions for the Microsoft Hypervisor. + */ +#ifndef _HV_HVGDK_H +#define _HV_HVGDK_H + +#include "hvgdk_mini.h" +#include "hvgdk_ext.h" + +/* + * The guest OS needs to register the guest ID with the hypervisor. + * The guest ID is a 64 bit entity and the structure of this ID is + * specified in the Hyper-V TLFS specification. + * + * While the current guideline does not specify how Linux guest ID(s) + * need to be generated, our plan is to publish the guidelines for + * Linux and other guest operating systems that currently are hosted + * on Hyper-V. The implementation here conforms to this yet + * unpublished guidelines. + * + * Bit(s) + * 63 - Indicates if the OS is Open Source or not; 1 is Open Source + * 62:56 - Os Type; Linux is 0x100 + * 55:48 - Distro specific identification + * 47:16 - Linux kernel version number + * 15:0 - Distro specific identification + */ + +#define HV_LINUX_VENDOR_ID 0x8100 + +/* HV_VMX_ENLIGHTENED_VMCS */ +struct hv_enlightened_vmcs { + u32 revision_id; + u32 abort; + + u16 host_es_selector; + u16 host_cs_selector; + u16 host_ss_selector; + u16 host_ds_selector; + u16 host_fs_selector; + u16 host_gs_selector; + u16 host_tr_selector; + + u16 padding16_1; + + u64 host_ia32_pat; + u64 host_ia32_efer; + + u64 host_cr0; + u64 host_cr3; + u64 host_cr4; + + u64 host_ia32_sysenter_esp; + u64 host_ia32_sysenter_eip; + u64 host_rip; + u32 host_ia32_sysenter_cs; + + u32 pin_based_vm_exec_control; + u32 vm_exit_controls; + u32 secondary_vm_exec_control; + + u64 io_bitmap_a; + u64 io_bitmap_b; + u64 msr_bitmap; + + u16 guest_es_selector; + u16 guest_cs_selector; + u16 guest_ss_selector; + u16 guest_ds_selector; + u16 guest_fs_selector; + u16 guest_gs_selector; + u16 guest_ldtr_selector; + u16 guest_tr_selector; + + u32 guest_es_limit; + u32 guest_cs_limit; + u32 guest_ss_limit; + u32 guest_ds_limit; + u32 guest_fs_limit; + u32 guest_gs_limit; + u32 guest_ldtr_limit; + u32 guest_tr_limit; + u32 guest_gdtr_limit; + u32 guest_idtr_limit; + + u32 guest_es_ar_bytes; + u32 guest_cs_ar_bytes; + u32 guest_ss_ar_bytes; + u32 guest_ds_ar_bytes; + u32 guest_fs_ar_bytes; + u32 guest_gs_ar_bytes; + u32 guest_ldtr_ar_bytes; + u32 guest_tr_ar_bytes; + + u64 guest_es_base; + u64 guest_cs_base; + u64 guest_ss_base; + u64 guest_ds_base; +
[PATCH v2 0/4] Add new headers for Hyper-V Dom0
To support Hyper-V Dom0 (aka Linux as root partition), many new definitions are required. The plan going forward is to directly import definitions from Hyper-V code without waiting for them to land in the TLFS document. This is a quicker and more maintainable way to import definitions, and is a step toward the eventual goal of exporting headers directly from Hyper-V for use in Linux. This patch series introduces new headers (hvhdk.h, hvgdk.h, etc, see patch #3) derived directly from Hyper-V code. hyperv-tlfs.h is replaced with hvhdk.h (which includes the other new headers) everywhere. No functional change is expected. Summary: Patch 1-2: Minor cleanup patches Patch 3: Add the new headers (hvhdk.h, etc..) in include/hyperv/ Patch 4: Switch to the new headers Signed-off-by: Nuno Das Neves --- Changelog: v2: - Rework the series to simply use the new headers everywhere instead of fiddling around to keep hyperv-tlfs.h used in some places, suggested by Michael Kelley and Easwar Hariharan - Fix compilation errors with some configs by adding missing definitions and changing some names, thanks to Simon Horman for catching those - Add additional definitions to the new headers to support them now replacing hyperv-tlfs.h everywhere - Add additional context in the commit messages for patches #3 and #4 - In patch #2, don't remove indirect includes. Only remove includes which truly aren't used, suggested by Michael Kelley --- Nuno Das Neves (4): hyperv: Move hv_connection_id to hyperv-tlfs.h hyperv: Clean up unnecessary #includes hyperv: Add new Hyper-V headers in include/hyperv hyperv: Switch from hyperv-tlfs.h to hyperv/hvhdk.h arch/arm64/hyperv/hv_core.c|3 +- arch/arm64/hyperv/mshyperv.c |4 +- arch/arm64/include/asm/mshyperv.h |2 +- arch/x86/hyperv/hv_apic.c |1 - arch/x86/hyperv/hv_init.c | 21 +- arch/x86/hyperv/hv_proc.c |3 +- arch/x86/hyperv/ivm.c |1 - arch/x86/hyperv/mmu.c |1 - arch/x86/hyperv/nested.c |2 +- arch/x86/include/asm/kvm_host.h|3 +- arch/x86/include/asm/mshyperv.h|3 +- arch/x86/include/asm/svm.h |2 +- arch/x86/kernel/cpu/mshyperv.c |2 +- arch/x86/kvm/vmx/hyperv_evmcs.h|2 +- arch/x86/kvm/vmx/vmx_onhyperv.h|2 +- arch/x86/mm/pat/set_memory.c |2 - drivers/clocksource/hyperv_timer.c |2 +- drivers/hv/hv_balloon.c|4 +- drivers/hv/hv_common.c |2 +- drivers/hv/hv_kvp.c|2 +- drivers/hv/hv_snapshot.c |2 +- drivers/hv/hyperv_vmbus.h |2 +- include/asm-generic/hyperv-tlfs.h |9 + include/asm-generic/mshyperv.h |2 +- include/clocksource/hyperv_timer.h |2 +- include/hyperv/hvgdk.h | 303 +++ include/hyperv/hvgdk_ext.h | 46 + include/hyperv/hvgdk_mini.h| 1295 include/hyperv/hvhdk.h | 733 include/hyperv/hvhdk_mini.h| 310 +++ include/linux/hyperv.h | 11 +- net/vmw_vsock/hyperv_transport.c |2 +- 32 files changed, 2729 insertions(+), 52 deletions(-) create mode 100644 include/hyperv/hvgdk.h create mode 100644 include/hyperv/hvgdk_ext.h create mode 100644 include/hyperv/hvgdk_mini.h create mode 100644 include/hyperv/hvhdk.h create mode 100644 include/hyperv/hvhdk_mini.h -- 2.34.1
[PATCH v2 4/4] hyperv: Switch from hyperv-tlfs.h to hyperv/hvhdk.h
Switch to using hvhdk.h everywhere in the kernel. This header includes all the new Hyper-V headers in include/hyperv, which form a superset of the definitions found in hyperv-tlfs.h. This makes it easier to add new Hyper-V interfaces without being restricted to those in the TLFS doc (reflected in hyperv-tlfs.h). To be more consistent with the original Hyper-V code, the names of some definitions are changed slightly. Update those where needed. hyperv-tlfs.h is no longer included anywhere - hvhdk.h can serve the same role, but with an easier path for adding new definitions. Signed-off-by: Nuno Das Neves --- arch/arm64/hyperv/hv_core.c| 2 +- arch/arm64/hyperv/mshyperv.c | 4 ++-- arch/arm64/include/asm/mshyperv.h | 2 +- arch/x86/hyperv/hv_init.c | 20 ++-- arch/x86/hyperv/hv_proc.c | 2 +- arch/x86/hyperv/nested.c | 2 +- arch/x86/include/asm/kvm_host.h| 2 +- arch/x86/include/asm/mshyperv.h| 2 +- arch/x86/include/asm/svm.h | 2 +- arch/x86/kernel/cpu/mshyperv.c | 2 +- arch/x86/kvm/vmx/hyperv_evmcs.h| 2 +- arch/x86/kvm/vmx/vmx_onhyperv.h| 2 +- drivers/clocksource/hyperv_timer.c | 2 +- drivers/hv/hv_balloon.c| 4 ++-- drivers/hv/hv_common.c | 2 +- drivers/hv/hv_kvp.c| 2 +- drivers/hv/hv_snapshot.c | 2 +- drivers/hv/hyperv_vmbus.h | 2 +- include/asm-generic/mshyperv.h | 2 +- include/clocksource/hyperv_timer.h | 2 +- include/linux/hyperv.h | 2 +- net/vmw_vsock/hyperv_transport.c | 2 +- 22 files changed, 33 insertions(+), 33 deletions(-) diff --git a/arch/arm64/hyperv/hv_core.c b/arch/arm64/hyperv/hv_core.c index 7a746a5a6b42..69004f619c57 100644 --- a/arch/arm64/hyperv/hv_core.c +++ b/arch/arm64/hyperv/hv_core.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include /* diff --git a/arch/arm64/hyperv/mshyperv.c b/arch/arm64/hyperv/mshyperv.c index b1a4de4eee29..fc49949b7df6 100644 --- a/arch/arm64/hyperv/mshyperv.c +++ b/arch/arm64/hyperv/mshyperv.c @@ -49,12 +49,12 @@ static int __init hyperv_init(void) hv_set_vpreg(HV_REGISTER_GUEST_OS_ID, guest_id); /* Get the features and hints from Hyper-V */ - hv_get_vpreg_128(HV_REGISTER_FEATURES, &result); + hv_get_vpreg_128(HV_REGISTER_PRIVILEGES_AND_FEATURES_INFO, &result); ms_hyperv.features = result.as32.a; ms_hyperv.priv_high = result.as32.b; ms_hyperv.misc_features = result.as32.c; - hv_get_vpreg_128(HV_REGISTER_ENLIGHTENMENTS, &result); + hv_get_vpreg_128(HV_REGISTER_FEATURES_INFO, &result); ms_hyperv.hints = result.as32.a; pr_info("Hyper-V: privilege flags low 0x%x, high 0x%x, hints 0x%x, misc 0x%x\n", diff --git a/arch/arm64/include/asm/mshyperv.h b/arch/arm64/include/asm/mshyperv.h index a975e1a689dd..7595fb35fae6 100644 --- a/arch/arm64/include/asm/mshyperv.h +++ b/arch/arm64/include/asm/mshyperv.h @@ -20,7 +20,7 @@ #include #include -#include +#include /* * Declare calls to get and set Hyper-V VP register values on ARM64, which diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c index 1a6354b3e582..3f9aef157c88 100644 --- a/arch/x86/hyperv/hv_init.c +++ b/arch/x86/hyperv/hv_init.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include @@ -416,24 +416,24 @@ static void __init hv_get_partition_id(void) static u8 __init get_vtl(void) { u64 control = HV_HYPERCALL_REP_COMP_1 | HVCALL_GET_VP_REGISTERS; - struct hv_get_vp_registers_input *input; - struct hv_get_vp_registers_output *output; + struct hv_input_get_vp_registers *input; + struct hv_register_assoc *output; unsigned long flags; u64 ret; local_irq_save(flags); input = *this_cpu_ptr(hyperv_pcpu_input_arg); - output = (struct hv_get_vp_registers_output *)input; + output = (struct hv_register_assoc *)input; - memset(input, 0, struct_size(input, element, 1)); - input->header.partitionid = HV_PARTITION_ID_SELF; - input->header.vpindex = HV_VP_INDEX_SELF; - input->header.inputvtl = 0; - input->element[0].name0 = HV_X64_REGISTER_VSM_VP_STATUS; + memset(input, 0, struct_size(input, names, 1)); + input->partition_id = HV_PARTITION_ID_SELF; + input->vp_index = HV_VP_INDEX_SELF; + input->input_vtl.as_uint8 = 0; + input->names[0] = HV_X64_REGISTER_VSM_VP_STATUS; ret = hv_do_hypercall(control, input, output); if (hv_result_success(ret)) { - ret = output->as64.low & HV_X64_VTL_MASK; + ret = output->value.reg8 & HV_X64_VTL_MASK; } else { pr_err("Failed to get VTL(error: %lld) exiting...\n", ret); BUG(); diff --git
[PATCH v2 1/4] hyperv: Move hv_connection_id to hyperv-tlfs.h
This definition is in the wrong file; it is part of the TLFS doc. Acked-by: Wei Liu Signed-off-by: Nuno Das Neves --- include/asm-generic/hyperv-tlfs.h | 9 + include/linux/hyperv.h| 9 - 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/include/asm-generic/hyperv-tlfs.h b/include/asm-generic/hyperv-tlfs.h index 814207e7c37f..52274c9aefef 100644 --- a/include/asm-generic/hyperv-tlfs.h +++ b/include/asm-generic/hyperv-tlfs.h @@ -871,4 +871,13 @@ struct hv_mmio_write_input { u8 data[HV_HYPERCALL_MMIO_MAX_DATA_LENGTH]; } __packed; +/* Define connection identifier type. */ +union hv_connection_id { + u32 asu32; + struct { + u32 id:24; + u32 reserved:8; + } u; +}; + #endif diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index 22c22fb91042..d0893ec488ae 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -768,15 +768,6 @@ struct vmbus_close_msg { struct vmbus_channel_close_channel msg; }; -/* Define connection identifier type. */ -union hv_connection_id { - u32 asu32; - struct { - u32 id:24; - u32 reserved:8; - } u; -}; - enum vmbus_device_type { HV_IDE = 0, HV_SCSI, -- 2.34.1
[PATCH v2 2/4] hyperv: Clean up unnecessary #includes
Remove includes of linux/hyperv.h, mshyperv.h, and hyperv-tlfs.h where they are not used. Acked-by: Wei Liu Signed-off-by: Nuno Das Neves --- arch/arm64/hyperv/hv_core.c | 1 - arch/x86/hyperv/hv_apic.c | 1 - arch/x86/hyperv/hv_init.c | 1 - arch/x86/hyperv/hv_proc.c | 1 - arch/x86/hyperv/ivm.c | 1 - arch/x86/hyperv/mmu.c | 1 - arch/x86/include/asm/kvm_host.h | 1 - arch/x86/include/asm/mshyperv.h | 1 - arch/x86/mm/pat/set_memory.c| 2 -- 9 files changed, 10 deletions(-) diff --git a/arch/arm64/hyperv/hv_core.c b/arch/arm64/hyperv/hv_core.c index f1ebc025e1df..7a746a5a6b42 100644 --- a/arch/arm64/hyperv/hv_core.c +++ b/arch/arm64/hyperv/hv_core.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/x86/hyperv/hv_apic.c b/arch/x86/hyperv/hv_apic.c index 0569f579338b..f022d5f64fb6 100644 --- a/arch/x86/hyperv/hv_apic.c +++ b/arch/x86/hyperv/hv_apic.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c index 17a71e92a343..1a6354b3e582 100644 --- a/arch/x86/hyperv/hv_init.c +++ b/arch/x86/hyperv/hv_init.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/x86/hyperv/hv_proc.c b/arch/x86/hyperv/hv_proc.c index 3fa1f2ee7b0d..b74c06c04ff1 100644 --- a/arch/x86/hyperv/hv_proc.c +++ b/arch/x86/hyperv/hv_proc.c @@ -3,7 +3,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/x86/hyperv/ivm.c b/arch/x86/hyperv/ivm.c index 60fc3ed72830..b56d70612734 100644 --- a/arch/x86/hyperv/ivm.c +++ b/arch/x86/hyperv/ivm.c @@ -7,7 +7,6 @@ */ #include -#include #include #include #include diff --git a/arch/x86/hyperv/mmu.c b/arch/x86/hyperv/mmu.c index 1cc113200ff5..cc8c3bd0e7c2 100644 --- a/arch/x86/hyperv/mmu.c +++ b/arch/x86/hyperv/mmu.c @@ -1,6 +1,5 @@ #define pr_fmt(fmt) "Hyper-V: " fmt -#include #include #include #include diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 4a68cb3eba78..3627eab994a3 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -24,7 +24,6 @@ #include #include #include -#include #include #include diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h index 390c4d13956d..47ca48062547 100644 --- a/arch/x86/include/asm/mshyperv.h +++ b/arch/x86/include/asm/mshyperv.h @@ -9,7 +9,6 @@ #include #include #include -#include /* * Hyper-V always provides a single IO-APIC at this MMIO address. diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c index 44f7b2ea6a07..85fa0d4509f0 100644 --- a/arch/x86/mm/pat/set_memory.c +++ b/arch/x86/mm/pat/set_memory.c @@ -32,8 +32,6 @@ #include #include #include -#include -#include #include "../mm_internal.h" -- 2.34.1
Re: [PATCH v2 4/4] hyperv: Switch from hyperv-tlfs.h to hyperv/hvhdk.h
On 11/10/2024 8:13 PM, Michael Kelley wrote: > From: Nuno Das Neves Sent: Thursday, > November 7, 2024 2:32 PM >> >> Switch to using hvhdk.h everywhere in the kernel. This header includes >> all the new Hyper-V headers in include/hyperv, which form a superset of >> the definitions found in hyperv-tlfs.h. >> >> This makes it easier to add new Hyper-V interfaces without being >> restricted to those in the TLFS doc (reflected in hyperv-tlfs.h). >> >> To be more consistent with the original Hyper-V code, the names of some >> definitions are changed slightly. Update those where needed. >> >> hyperv-tlfs.h is no longer included anywhere - hvhdk.h can serve >> the same role, but with an easier path for adding new definitions. > > Is hyperv-tlfs.h and friends being deleted? If not, the risk is that > someone adds a new #include of it without realizing that it has been > superseded by hvhdk.h. > I was hesitant to delete it because I thought someone may still have a use for a header file that (mostly) reflects the TLFS document and nothing more. But in practical terms, this patchset makes it much more difficult to use because all the helper code (i.e. mshyperv.h) now uses hvhdk.h. So, maybe there is no point keeping it. > Note also that this patch does not apply cleanly to 6.12 rc's, or to > current linux-next trees. There's an unrelated #include added to > arch/x86/include/asm/kvm_host.h that causes a merge failure > in that file. > I've been developing this series based on hyperv-next. Should I be basing it on linux-next? > Michael > >> >> Signed-off-by: Nuno Das Neves >> --- >> arch/arm64/hyperv/hv_core.c| 2 +- >> arch/arm64/hyperv/mshyperv.c | 4 ++-- >> arch/arm64/include/asm/mshyperv.h | 2 +- >> arch/x86/hyperv/hv_init.c | 20 ++-- >> arch/x86/hyperv/hv_proc.c | 2 +- >> arch/x86/hyperv/nested.c | 2 +- >> arch/x86/include/asm/kvm_host.h| 2 +- >> arch/x86/include/asm/mshyperv.h| 2 +- >> arch/x86/include/asm/svm.h | 2 +- >> arch/x86/kernel/cpu/mshyperv.c | 2 +- >> arch/x86/kvm/vmx/hyperv_evmcs.h| 2 +- >> arch/x86/kvm/vmx/vmx_onhyperv.h| 2 +- >> drivers/clocksource/hyperv_timer.c | 2 +- >> drivers/hv/hv_balloon.c| 4 ++-- >> drivers/hv/hv_common.c | 2 +- >> drivers/hv/hv_kvp.c| 2 +- >> drivers/hv/hv_snapshot.c | 2 +- >> drivers/hv/hyperv_vmbus.h | 2 +- >> include/asm-generic/mshyperv.h | 2 +- >> include/clocksource/hyperv_timer.h | 2 +- >> include/linux/hyperv.h | 2 +- >> net/vmw_vsock/hyperv_transport.c | 2 +- >> 22 files changed, 33 insertions(+), 33 deletions(-) >> >> diff --git a/arch/arm64/hyperv/hv_core.c b/arch/arm64/hyperv/hv_core.c >> index 7a746a5a6b42..69004f619c57 100644 >> --- a/arch/arm64/hyperv/hv_core.c >> +++ b/arch/arm64/hyperv/hv_core.c >> @@ -14,7 +14,7 @@ >> #include >> #include >> #include >> -#include >> +#include >> #include >> >> /* >> diff --git a/arch/arm64/hyperv/mshyperv.c b/arch/arm64/hyperv/mshyperv.c >> index b1a4de4eee29..fc49949b7df6 100644 >> --- a/arch/arm64/hyperv/mshyperv.c >> +++ b/arch/arm64/hyperv/mshyperv.c >> @@ -49,12 +49,12 @@ static int __init hyperv_init(void) >> hv_set_vpreg(HV_REGISTER_GUEST_OS_ID, guest_id); >> >> /* Get the features and hints from Hyper-V */ >> -hv_get_vpreg_128(HV_REGISTER_FEATURES, &result); >> +hv_get_vpreg_128(HV_REGISTER_PRIVILEGES_AND_FEATURES_INFO, &result); >> ms_hyperv.features = result.as32.a; >> ms_hyperv.priv_high = result.as32.b; >> ms_hyperv.misc_features = result.as32.c; >> >> -hv_get_vpreg_128(HV_REGISTER_ENLIGHTENMENTS, &result); >> +hv_get_vpreg_128(HV_REGISTER_FEATURES_INFO, &result); >> ms_hyperv.hints = result.as32.a; >> >> pr_info("Hyper-V: privilege flags low 0x%x, high 0x%x, hints 0x%x, misc >> 0x%x\n", >> diff --git a/arch/arm64/include/asm/mshyperv.h >> b/arch/arm64/include/asm/mshyperv.h >> index a975e1a689dd..7595fb35fae6 100644 >> --- a/arch/arm64/include/asm/mshyperv.h >> +++ b/arch/arm64/include/asm/mshyperv.h >> @@ -20,7 +20,7 @@ >> >> #include >> #include >> -#include >> +#include >> >> /* >> * Declare calls to get and set Hyper-V VP register values on ARM64, which >> diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86
Re: [PATCH v2 3/4] hyperv: Add new Hyper-V headers in include/hyperv
On 11/11/2024 11:31 AM, Michael Kelley wrote: > From: Nuno Das Neves Sent: Monday, > November 11, 2024 10:45 AM >> >> On 11/10/2024 8:13 PM, Michael Kelley wrote: >>> From: Nuno Das Neves Sent: Thursday, >> November 7, 2024 2:32 PM >>>> >>>> These headers contain definitions for regular Hyper-V guests (as in >>>> hyperv-tlfs.h), as well as interfaces for more privileged guests like >>>> Dom0. >>> >>> See my comment on Patch 0/4 about use of "dom0" terminology. >>> >> >> Thanks, noted. >> >>>> >>>> These files are derived from headers exported from Hyper-V, rather than >>>> being derived from the TLFS document. (Although, to preserve >>>> compatibility with existing Linux code, some definitions are copied >>>> directly from hyperv-tlfs.h too). >>>> >>>> The new files follow a naming convention according to their original >>>> use: >>>> - hdk "host development kit" >>>> - gdk "guest development kit" >>>> With postfix "_mini" implying userspace-only headers, and "_ext" for >>>> extended hypercalls. >>>> >>>> These names should be considered a rough guide only - since there are >>>> many places already where both host and guest code are in the same >>>> place, hvhdk.h (which includes everything) can be used most of the time. >>> >>> Just curious -- are there really cases where hvhdk.h can't be used? >>> If so, could you summarize why? >>> >> >> No, there aren't cases where it "can't" be used. I suppose if someone >> doesn't want to include everything, perhaps they could just include >> hvgdk.h, for example. It doesn't really matter though. >> >>> I ask because it would be nice to expand slightly on your paragraph >>> below, as follows: (if indeed what I've added is correct) >>> >>> The use of multiple files and their original names is primarily to >>> keep the provenance of exactly where they came from in Hyper-V >>> code, which is helpful for manual maintenance and extension >>> of these definitions. Microsoft maintainers importing new definitions >>> should take care to put them in the right file. However, Linux kernel code >>> that uses any of the definitions need not be aware of the multiple files >>> or assign any meaning to the new names. Linux kernel uses should >>> always just include hvhdk.h >>> >> >> Thanks, I think that additional sentence helps clarify things. I'll >> include it in the next version, and I think I can probably omit the prior >> paragraph: "These names should be considered a rough guide only...". >> > > Omitting that prior paragraph is OK with me. The key thoughts from my > standpoint are: > * The separation into multiple files and the file names come from >the Windows Hyper-V world and are maintained to ease bringing >the definitions over from that world > > * Linux code can ignore the multiple files and their names. Just >#include hvhdk.h. > Agreed, thanks for helping clarify the points. >>>> >>>> The original names are kept intact primarily to keep the provenance of >>>> exactly where they came from in Hyper-V code, which is helpful for >>>> manual maintenance and extension of these definitions. Microsoft >>>> maintainers importing new definitions should take care to put them in >>>> the right file. >>>> >>>> Note also that the files contain both arm64 and x86_64 code guarded by >>>> \#ifdefs, which is how the definitions originally appear in Hyper-V. >>> >>> Spurious backslash? >>> >> >> Indeed, thanks. >> >>> I would suggest some additional clarification: The #ifdef guards are >>> employed minimally where necessary to prevent conflicts due to >>> different definitions for the same thing on x86_64 and arm64. Where >>> there are no conflicts, the union of x86_64 definitions and arm64 >>> definitions is visible when building for either architecture. In other >>> words, not all definitions specific to x86_64 are protected by #ifdef >>> x86_64. Such unprotected definitions may be visible when building >>> for arm64. And vice versa. >>> >> >> Is there a reason you specifically want to point out that "Such >> unprotected definitions may be visible when bui
Re: [PATCH v3 5/5] hyperv: Remove the now unused hyperv-tlfs.h files
On 11/25/2024 9:59 PM, Michael Kelley wrote: > From: Nuno Das Neves Sent: Monday, > November 25, 2024 3:25 PM >> >> Remove all hyperv-tlfs.h files. These are no longer included >> anywhere. hyperv/hvhdk.h serves the same role, but with an easier >> path for adding new definitions. >> >> Remove the relevant lines in MAINTAINERS. >> >> Signed-off-by: Nuno Das Neves > > Reviewed-by: Michael Kelley Thanks for the reviews on this series Michael!
[PATCH v3 2/5] hyperv: Clean up unnecessary #includes
Remove includes of linux/hyperv.h, mshyperv.h, and hyperv-tlfs.h where they are not used. Acked-by: Wei Liu Reviewed-by: Michael Kelley Reviewed-by: Easwar Hariharan Signed-off-by: Nuno Das Neves --- arch/arm64/hyperv/hv_core.c | 1 - arch/x86/hyperv/hv_apic.c | 1 - arch/x86/hyperv/hv_init.c | 1 - arch/x86/hyperv/hv_proc.c | 1 - arch/x86/hyperv/ivm.c | 1 - arch/x86/hyperv/mmu.c | 1 - arch/x86/include/asm/kvm_host.h | 1 - arch/x86/include/asm/mshyperv.h | 1 - arch/x86/mm/pat/set_memory.c| 2 -- 9 files changed, 10 deletions(-) diff --git a/arch/arm64/hyperv/hv_core.c b/arch/arm64/hyperv/hv_core.c index f1ebc025e1df..7a746a5a6b42 100644 --- a/arch/arm64/hyperv/hv_core.c +++ b/arch/arm64/hyperv/hv_core.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/x86/hyperv/hv_apic.c b/arch/x86/hyperv/hv_apic.c index 0569f579338b..f022d5f64fb6 100644 --- a/arch/x86/hyperv/hv_apic.c +++ b/arch/x86/hyperv/hv_apic.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c index 95eada2994e1..3562826915f9 100644 --- a/arch/x86/hyperv/hv_init.c +++ b/arch/x86/hyperv/hv_init.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/x86/hyperv/hv_proc.c b/arch/x86/hyperv/hv_proc.c index 3fa1f2ee7b0d..b74c06c04ff1 100644 --- a/arch/x86/hyperv/hv_proc.c +++ b/arch/x86/hyperv/hv_proc.c @@ -3,7 +3,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/x86/hyperv/ivm.c b/arch/x86/hyperv/ivm.c index 60fc3ed72830..b56d70612734 100644 --- a/arch/x86/hyperv/ivm.c +++ b/arch/x86/hyperv/ivm.c @@ -7,7 +7,6 @@ */ #include -#include #include #include #include diff --git a/arch/x86/hyperv/mmu.c b/arch/x86/hyperv/mmu.c index 1cc113200ff5..cc8c3bd0e7c2 100644 --- a/arch/x86/hyperv/mmu.c +++ b/arch/x86/hyperv/mmu.c @@ -1,6 +1,5 @@ #define pr_fmt(fmt) "Hyper-V: " fmt -#include #include #include #include diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index e159e44a6a1b..46f354b12488 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -24,7 +24,6 @@ #include #include #include -#include #include #include diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h index 5f0bc6a6d025..6f866fb9ffee 100644 --- a/arch/x86/include/asm/mshyperv.h +++ b/arch/x86/include/asm/mshyperv.h @@ -9,7 +9,6 @@ #include #include #include -#include /* * Hyper-V always provides a single IO-APIC at this MMIO address. diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c index 069e421c2247..128e3448ae4f 100644 --- a/arch/x86/mm/pat/set_memory.c +++ b/arch/x86/mm/pat/set_memory.c @@ -32,8 +32,6 @@ #include #include #include -#include -#include #include "../mm_internal.h" -- 2.34.1
[PATCH v3 1/5] hyperv: Move hv_connection_id to hyperv-tlfs.h
This definition is in the wrong file; it is part of the TLFS doc. Acked-by: Wei Liu Reviewed-by: Easwar Hariharan Reviewed-by: Michael Kelley Signed-off-by: Nuno Das Neves --- include/asm-generic/hyperv-tlfs.h | 9 + include/linux/hyperv.h| 9 - 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/include/asm-generic/hyperv-tlfs.h b/include/asm-generic/hyperv-tlfs.h index 814207e7c37f..52274c9aefef 100644 --- a/include/asm-generic/hyperv-tlfs.h +++ b/include/asm-generic/hyperv-tlfs.h @@ -871,4 +871,13 @@ struct hv_mmio_write_input { u8 data[HV_HYPERCALL_MMIO_MAX_DATA_LENGTH]; } __packed; +/* Define connection identifier type. */ +union hv_connection_id { + u32 asu32; + struct { + u32 id:24; + u32 reserved:8; + } u; +}; + #endif diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index 22c22fb91042..d0893ec488ae 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -768,15 +768,6 @@ struct vmbus_close_msg { struct vmbus_channel_close_channel msg; }; -/* Define connection identifier type. */ -union hv_connection_id { - u32 asu32; - struct { - u32 id:24; - u32 reserved:8; - } u; -}; - enum vmbus_device_type { HV_IDE = 0, HV_SCSI, -- 2.34.1
[PATCH v3 0/5] Introduce new headers for Hyper-V
To support Linux as root partition[1] on Hyper-V many new definitions are required. The plan going forward is to directly import definitions from Hyper-V code without waiting for them to land in the TLFS document. This is a quicker and more maintainable way to import definitions, and is a step toward the eventual goal of exporting the headers directly from Hyper-V for use in Linux. This patch series introduces new headers (hvhdk.h, hvgdk.h, etc, see patch #3) derived directly from Hyper-V code. hyperv-tlfs.h is replaced with hvhdk.h (which includes the other new headers) everywhere. No functional change is expected. Summary: Patch 1-2: Minor cleanup patches Patch 3: Add the new headers (hvhdk.h, etc..) in include/hyperv/ Patch 4: Switch to the new headers Patch 5: Delete hyperv-tlfs.h files Signed-off-by: Nuno Das Neves --- Changelog: v3: - Add patch (#5) to delete the hyperv-tlfs.h files, suggested by Michael Kelley and Easwar Hariharan - Reword commit message on patch #3 to improve clarity, suggested by Michael Kelley - Clarify "Dom0" terminology, suggested by Michael Kelley v2: - Rework the series to simply use the new headers everywhere, instead of fiddling around to keep hyperv-tlfs.h in some areas, suggested by Michael Kelley and Easwar Hariharan - Fix compilation issues with some configs by adding missing definitions and changing some names, thanks to Simon Horman for catching those - Add additional definitions to the new headers due to them now being used everywhere - Don't remove indirect includes in patch #2, only remove those which truly aren't used, suggested by Michael Kelley --- Footnotes: [1] Linux as root partition on Hyper-V is sometimes referred to as "Dom0", borrowing the terminology from Xen. Although they are conceptually similar, note that "Hyper-V Dom0" has nothing to do with Xen. Nuno Das Neves (5): hyperv: Move hv_connection_id to hyperv-tlfs.h hyperv: Clean up unnecessary #includes hyperv: Add new Hyper-V headers in include/hyperv hyperv: Switch from hyperv-tlfs.h to hyperv/hvhdk.h hyperv: Remove the now unused hyperv-tlfs.h files MAINTAINERS |8 +- arch/arm64/hyperv/hv_core.c |3 +- arch/arm64/hyperv/mshyperv.c |4 +- arch/arm64/include/asm/hyperv-tlfs.h | 71 -- arch/arm64/include/asm/mshyperv.h|7 +- arch/x86/hyperv/hv_apic.c|1 - arch/x86/hyperv/hv_init.c| 21 +- arch/x86/hyperv/hv_proc.c|3 +- arch/x86/hyperv/ivm.c|1 - arch/x86/hyperv/mmu.c|1 - arch/x86/hyperv/nested.c |2 +- arch/x86/include/asm/hyperv-tlfs.h | 811 arch/x86/include/asm/kvm_host.h |3 +- arch/x86/include/asm/mshyperv.h |3 +- arch/x86/include/asm/svm.h |2 +- arch/x86/kernel/cpu/mshyperv.c |2 +- arch/x86/kvm/vmx/hyperv_evmcs.h |2 +- arch/x86/kvm/vmx/vmx_onhyperv.h |2 +- arch/x86/mm/pat/set_memory.c |2 - drivers/clocksource/hyperv_timer.c |2 +- drivers/hv/hv_balloon.c |4 +- drivers/hv/hv_common.c |2 +- drivers/hv/hv_kvp.c |2 +- drivers/hv/hv_snapshot.c |2 +- drivers/hv/hyperv_vmbus.h|2 +- include/asm-generic/hyperv-tlfs.h| 874 - include/asm-generic/mshyperv.h |7 +- include/clocksource/hyperv_timer.h |2 +- include/hyperv/hvgdk.h | 308 ++ include/hyperv/hvgdk_ext.h | 46 + include/hyperv/hvgdk_mini.h | 1306 ++ include/hyperv/hvhdk.h | 733 +++ include/hyperv/hvhdk_mini.h | 311 ++ include/linux/hyperv.h | 11 +- net/vmw_vsock/hyperv_transport.c |6 +- 35 files changed, 2748 insertions(+), 1819 deletions(-) delete mode 100644 arch/arm64/include/asm/hyperv-tlfs.h delete mode 100644 arch/x86/include/asm/hyperv-tlfs.h delete mode 100644 include/asm-generic/hyperv-tlfs.h create mode 100644 include/hyperv/hvgdk.h create mode 100644 include/hyperv/hvgdk_ext.h create mode 100644 include/hyperv/hvgdk_mini.h create mode 100644 include/hyperv/hvhdk.h create mode 100644 include/hyperv/hvhdk_mini.h -- 2.34.1
[PATCH v3 3/5] hyperv: Add new Hyper-V headers in include/hyperv
These headers contain definitions for regular Hyper-V guests (as in hyperv-tlfs.h), as well as interfaces for more privileged guests like the root partition (aka Dom0). These files are derived from headers exported from Hyper-V, rather than being derived from the TLFS document. (Although, to preserve compatibility with existing Linux code, some definitions are copied directly from hyperv-tlfs.h too). The new files follow a naming convention according to their original use: - hdk "host development kit" - gdk "guest development kit" With postfix "_mini" implying userspace-only headers, and "_ext" for extended hypercalls. The use of multiple files and their original names is primarily to keep the provenance of exactly where they came from in Hyper-V code, which is helpful for manual maintenance and extension of these definitions. Microsoft maintainers importing new definitions should take care to put them in the right file. However, Linux kernel code that uses any of the definitions need not be aware of the multiple files or assign any meaning to the new names. Linux kernel code should always just include hvhdk.h Note the new headers contain both arm64 and x86_64 definitions. Some are guarded by #ifdefs, and some are instead prefixed with the architecture, e.g. hv_x64_*. These conventions are kept from Hyper-V code as another tactic to simplify the process of importing and maintaining the definitions, rather than splitting them up into their own files in arch/x86/ and arch/arm64/. These headers are a step toward importing headers directly from Hyper-V in the future, similar to Xen public files in include/xen/interface/. Signed-off-by: Nuno Das Neves --- MAINTAINERS |5 + include/hyperv/hvgdk.h | 308 + include/hyperv/hvgdk_ext.h | 46 ++ include/hyperv/hvgdk_mini.h | 1306 +++ include/hyperv/hvhdk.h | 733 include/hyperv/hvhdk_mini.h | 311 + 6 files changed, 2709 insertions(+) create mode 100644 include/hyperv/hvgdk.h create mode 100644 include/hyperv/hvgdk_ext.h create mode 100644 include/hyperv/hvgdk_mini.h create mode 100644 include/hyperv/hvhdk.h create mode 100644 include/hyperv/hvhdk_mini.h diff --git a/MAINTAINERS b/MAINTAINERS index cf1d81bd04a7..6ffa65b5a160 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10694,6 +10694,11 @@ F: drivers/video/fbdev/hyperv_fb.c F: include/asm-generic/hyperv-tlfs.h F: include/asm-generic/mshyperv.h F: include/clocksource/hyperv_timer.h +F: include/hyperv/hvgdk.h +F: include/hyperv/hvgdk_ext.h +F: include/hyperv/hvgdk_mini.h +F: include/hyperv/hvhdk.h +F: include/hyperv/hvhdk_mini.h F: include/linux/hyperv.h F: include/net/mana F: include/uapi/linux/hyperv.h diff --git a/include/hyperv/hvgdk.h b/include/hyperv/hvgdk.h new file mode 100644 index ..dd6d4939ea29 --- /dev/null +++ b/include/hyperv/hvgdk.h @@ -0,0 +1,308 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Type definitions for the Microsoft Hypervisor. + */ +#ifndef _HV_HVGDK_H +#define _HV_HVGDK_H + +#include "hvgdk_mini.h" +#include "hvgdk_ext.h" + +/* + * The guest OS needs to register the guest ID with the hypervisor. + * The guest ID is a 64 bit entity and the structure of this ID is + * specified in the Hyper-V TLFS specification. + * + * While the current guideline does not specify how Linux guest ID(s) + * need to be generated, our plan is to publish the guidelines for + * Linux and other guest operating systems that currently are hosted + * on Hyper-V. The implementation here conforms to this yet + * unpublished guidelines. + * + * Bit(s) + * 63 - Indicates if the OS is Open Source or not; 1 is Open Source + * 62:56 - Os Type; Linux is 0x100 + * 55:48 - Distro specific identification + * 47:16 - Linux kernel version number + * 15:0 - Distro specific identification + */ + +#define HV_LINUX_VENDOR_ID 0x8100 + +/* HV_VMX_ENLIGHTENED_VMCS */ +struct hv_enlightened_vmcs { + u32 revision_id; + u32 abort; + + u16 host_es_selector; + u16 host_cs_selector; + u16 host_ss_selector; + u16 host_ds_selector; + u16 host_fs_selector; + u16 host_gs_selector; + u16 host_tr_selector; + + u16 padding16_1; + + u64 host_ia32_pat; + u64 host_ia32_efer; + + u64 host_cr0; + u64 host_cr3; + u64 host_cr4; + + u64 host_ia32_sysenter_esp; + u64 host_ia32_sysenter_eip; + u64 host_rip; + u32 host_ia32_sysenter_cs; + + u32 pin_based_vm_exec_control; + u32 vm_exit_controls; + u32 secondary_vm_exec_control; + + u64 io_bitmap_a; + u64 io_bitmap_b; + u64 msr_bitmap; + + u16 guest_es_selector; + u16 guest_cs_selector; + u16 guest_ss_selector; + u16 guest_ds_selector; + u16 guest_fs_selector; +
[PATCH v3 5/5] hyperv: Remove the now unused hyperv-tlfs.h files
Remove all hyperv-tlfs.h files. These are no longer included anywhere. hyperv/hvhdk.h serves the same role, but with an easier path for adding new definitions. Remove the relevant lines in MAINTAINERS. Signed-off-by: Nuno Das Neves --- MAINTAINERS | 3 - arch/arm64/include/asm/hyperv-tlfs.h | 71 --- arch/x86/include/asm/hyperv-tlfs.h | 811 include/asm-generic/hyperv-tlfs.h| 883 --- 4 files changed, 1768 deletions(-) delete mode 100644 arch/arm64/include/asm/hyperv-tlfs.h delete mode 100644 arch/x86/include/asm/hyperv-tlfs.h delete mode 100644 include/asm-generic/hyperv-tlfs.h diff --git a/MAINTAINERS b/MAINTAINERS index 6ffa65b5a160..b1fb2a008982 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10672,10 +10672,8 @@ F: Documentation/devicetree/bindings/bus/microsoft,vmbus.yaml F: Documentation/networking/device_drivers/ethernet/microsoft/netvsc.rst F: Documentation/virt/hyperv F: arch/arm64/hyperv -F: arch/arm64/include/asm/hyperv-tlfs.h F: arch/arm64/include/asm/mshyperv.h F: arch/x86/hyperv -F: arch/x86/include/asm/hyperv-tlfs.h F: arch/x86/include/asm/mshyperv.h F: arch/x86/include/asm/trace/hyperv.h F: arch/x86/kernel/cpu/mshyperv.c @@ -10691,7 +10689,6 @@ F: drivers/pci/controller/pci-hyperv.c F: drivers/scsi/storvsc_drv.c F: drivers/uio/uio_hv_generic.c F: drivers/video/fbdev/hyperv_fb.c -F: include/asm-generic/hyperv-tlfs.h F: include/asm-generic/mshyperv.h F: include/clocksource/hyperv_timer.h F: include/hyperv/hvgdk.h diff --git a/arch/arm64/include/asm/hyperv-tlfs.h b/arch/arm64/include/asm/hyperv-tlfs.h deleted file mode 100644 index bc30aadedfe9.. --- a/arch/arm64/include/asm/hyperv-tlfs.h +++ /dev/null @@ -1,71 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ - -/* - * This file contains definitions from the Hyper-V Hypervisor Top-Level - * Functional Specification (TLFS): - * https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/reference/tlfs - * - * Copyright (C) 2021, Microsoft, Inc. - * - * Author : Michael Kelley - */ - -#ifndef _ASM_HYPERV_TLFS_H -#define _ASM_HYPERV_TLFS_H - -#include - -/* - * All data structures defined in the TLFS that are shared between Hyper-V - * and a guest VM use Little Endian byte ordering. This matches the default - * byte ordering of Linux running on ARM64, so no special handling is required. - */ - -/* - * Group C Features. See the asm-generic version of hyperv-tlfs.h - * for a description of Feature Groups. - */ - -/* Crash MSRs available */ -#define HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE BIT(8) - -/* STIMER direct mode is available */ -#define HV_STIMER_DIRECT_MODE_AVAILABLEBIT(13) - -/* - * To support arch-generic code calling hv_set/get_register: - * - On x86, HV_MSR_ indicates an MSR accessed via rdmsrl/wrmsrl - * - On ARM, HV_MSR_ indicates a VP register accessed via hypercall - */ -#define HV_MSR_CRASH_P0(HV_REGISTER_GUEST_CRASH_P0) -#define HV_MSR_CRASH_P1(HV_REGISTER_GUEST_CRASH_P1) -#define HV_MSR_CRASH_P2(HV_REGISTER_GUEST_CRASH_P2) -#define HV_MSR_CRASH_P3(HV_REGISTER_GUEST_CRASH_P3) -#define HV_MSR_CRASH_P4(HV_REGISTER_GUEST_CRASH_P4) -#define HV_MSR_CRASH_CTL (HV_REGISTER_GUEST_CRASH_CTL) - -#define HV_MSR_VP_INDEX(HV_REGISTER_VP_INDEX) -#define HV_MSR_TIME_REF_COUNT (HV_REGISTER_TIME_REF_COUNT) -#define HV_MSR_REFERENCE_TSC (HV_REGISTER_REFERENCE_TSC) - -#define HV_MSR_SINT0 (HV_REGISTER_SINT0) -#define HV_MSR_SCONTROL(HV_REGISTER_SCONTROL) -#define HV_MSR_SIEFP (HV_REGISTER_SIEFP) -#define HV_MSR_SIMP(HV_REGISTER_SIMP) -#define HV_MSR_EOM (HV_REGISTER_EOM) - -#define HV_MSR_STIMER0_CONFIG (HV_REGISTER_STIMER0_CONFIG) -#define HV_MSR_STIMER0_COUNT (HV_REGISTER_STIMER0_COUNT) - -union hv_msi_entry { - u64 as_uint64[2]; - struct { - u64 address; - u32 data; - u32 reserved; - } __packed; -}; - -#include - -#endif diff --git a/arch/x86/include/asm/hyperv-tlfs.h b/arch/x86/include/asm/hyperv-tlfs.h deleted file mode 100644 index 3787d26810c1.. --- a/arch/x86/include/asm/hyperv-tlfs.h +++ /dev/null @@ -1,811 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ - -/* - * This file contains definitions from Hyper-V Hypervisor Top-Level Functional - * Specification (TLFS): - * https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/reference/tlfs - */ - -#ifndef _ASM_X86_HYPERV_TLFS_H -#define _ASM_X86_HYPERV_TLFS_H - -#include -#include -/* - * The below CPUID leaves are present if VersionAndFeatures.HypervisorPresent - * is set by CPUID(HvCpuIdFunctionVersionAndFeatures). - */ -#define HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS 0x4000 -#define HYPERV_CPUID_INTERFACE
[PATCH v3 4/5] hyperv: Switch from hyperv-tlfs.h to hyperv/hvhdk.h
Switch to using hvhdk.h everywhere in the kernel. This header includes all the new Hyper-V headers in include/hyperv, which form a superset of the definitions found in hyperv-tlfs.h. This makes it easier to add new Hyper-V interfaces without being restricted to those in the TLFS doc (reflected in hyperv-tlfs.h). To be more consistent with the original Hyper-V code, the names of some definitions are changed slightly. Update those where needed. Update comments in mshyperv.h files to point to include/hyperv for adding new definitions. Signed-off-by: Nuno Das Neves --- arch/arm64/hyperv/hv_core.c| 2 +- arch/arm64/hyperv/mshyperv.c | 4 ++-- arch/arm64/include/asm/mshyperv.h | 7 +++ arch/x86/hyperv/hv_init.c | 20 ++-- arch/x86/hyperv/hv_proc.c | 2 +- arch/x86/hyperv/nested.c | 2 +- arch/x86/include/asm/kvm_host.h| 2 +- arch/x86/include/asm/mshyperv.h| 2 +- arch/x86/include/asm/svm.h | 2 +- arch/x86/kernel/cpu/mshyperv.c | 2 +- arch/x86/kvm/vmx/hyperv_evmcs.h| 2 +- arch/x86/kvm/vmx/vmx_onhyperv.h| 2 +- drivers/clocksource/hyperv_timer.c | 2 +- drivers/hv/hv_balloon.c| 4 ++-- drivers/hv/hv_common.c | 2 +- drivers/hv/hv_kvp.c| 2 +- drivers/hv/hv_snapshot.c | 2 +- drivers/hv/hyperv_vmbus.h | 2 +- include/asm-generic/mshyperv.h | 7 +++ include/clocksource/hyperv_timer.h | 2 +- include/linux/hyperv.h | 2 +- net/vmw_vsock/hyperv_transport.c | 6 +++--- 22 files changed, 39 insertions(+), 41 deletions(-) diff --git a/arch/arm64/hyperv/hv_core.c b/arch/arm64/hyperv/hv_core.c index 7a746a5a6b42..69004f619c57 100644 --- a/arch/arm64/hyperv/hv_core.c +++ b/arch/arm64/hyperv/hv_core.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include /* diff --git a/arch/arm64/hyperv/mshyperv.c b/arch/arm64/hyperv/mshyperv.c index b1a4de4eee29..fc49949b7df6 100644 --- a/arch/arm64/hyperv/mshyperv.c +++ b/arch/arm64/hyperv/mshyperv.c @@ -49,12 +49,12 @@ static int __init hyperv_init(void) hv_set_vpreg(HV_REGISTER_GUEST_OS_ID, guest_id); /* Get the features and hints from Hyper-V */ - hv_get_vpreg_128(HV_REGISTER_FEATURES, &result); + hv_get_vpreg_128(HV_REGISTER_PRIVILEGES_AND_FEATURES_INFO, &result); ms_hyperv.features = result.as32.a; ms_hyperv.priv_high = result.as32.b; ms_hyperv.misc_features = result.as32.c; - hv_get_vpreg_128(HV_REGISTER_ENLIGHTENMENTS, &result); + hv_get_vpreg_128(HV_REGISTER_FEATURES_INFO, &result); ms_hyperv.hints = result.as32.a; pr_info("Hyper-V: privilege flags low 0x%x, high 0x%x, hints 0x%x, misc 0x%x\n", diff --git a/arch/arm64/include/asm/mshyperv.h b/arch/arm64/include/asm/mshyperv.h index a975e1a689dd..2e2f83bafcfb 100644 --- a/arch/arm64/include/asm/mshyperv.h +++ b/arch/arm64/include/asm/mshyperv.h @@ -6,9 +6,8 @@ * the ARM64 architecture. See include/asm-generic/mshyperv.h for * definitions are that architecture independent. * - * Definitions that are specified in the Hyper-V Top Level Functional - * Spec (TLFS) should not go in this file, but should instead go in - * hyperv-tlfs.h. + * Definitions that are derived from Hyper-V code or headers should not go in + * this file, but should instead go in the relevant files in include/hyperv. * * Copyright (C) 2021, Microsoft, Inc. * @@ -20,7 +19,7 @@ #include #include -#include +#include /* * Declare calls to get and set Hyper-V VP register values on ARM64, which diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c index 3562826915f9..3cf2a227d666 100644 --- a/arch/x86/hyperv/hv_init.c +++ b/arch/x86/hyperv/hv_init.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include @@ -415,24 +415,24 @@ static void __init hv_get_partition_id(void) static u8 __init get_vtl(void) { u64 control = HV_HYPERCALL_REP_COMP_1 | HVCALL_GET_VP_REGISTERS; - struct hv_get_vp_registers_input *input; - struct hv_get_vp_registers_output *output; + struct hv_input_get_vp_registers *input; + struct hv_register_assoc *output; unsigned long flags; u64 ret; local_irq_save(flags); input = *this_cpu_ptr(hyperv_pcpu_input_arg); - output = (struct hv_get_vp_registers_output *)input; + output = (struct hv_register_assoc *)input; - memset(input, 0, struct_size(input, element, 1)); - input->header.partitionid = HV_PARTITION_ID_SELF; - input->header.vpindex = HV_VP_INDEX_SELF; - input->header.inputvtl = 0; - input->element[0].name0 = HV_X64_REGISTER_VSM_VP_STATUS; + memset(input, 0, struct_size(input, names, 1)); + input->partition_id = HV_PARTITION_ID_SELF; + input->vp_index = HV_VP_INDEX
Re: [PATCH 0/2] hyperv: Move some features to common code
On 12/7/2024 6:59 PM, Michael Kelley wrote: > From: Nuno Das Neves Sent: Friday, > December 6, 2024 2:22 PM >> >> There are several bits of Hyper-V-related code that today live in >> arch/x86 but are not really specific to x86_64 and will work on arm64 >> too. >> >> Some of these will be needed in the upcoming mshv driver code (for >> Linux as root partition on Hyper-V). > > Previously, Linux as the root partition on Hyper-V was x86 only, which is > why the code is currently under arch/x86. So evidently the mshv driver > is being expanded to support both x86 and arm64, correct? Assuming > that's the case, I have some thoughts about how the source code should > be organized and built. It's probably best to get this right to start with so > it doesn't need to be changed again. Yes, we plan on supporting both architectures (eventually). I completely agree that it's better to sort out these issues now rather than later. > > * Patch 2 of this series moves hv_call_deposit_pages() and >hv_call_create_vp() to common code, but does not move >hv_call_add_logical_proc(). All three are used together, so >I'm wondering why hv_call_add_logical_proc() isn't moved. > The only reason is that in our internal tree there's no common or arm64 code yet that uses it - there is no reason it can't also become common code! > * These three functions were originally put in a separate source >code file because of being specific to running in the root partition, >and not needed for generic Linux guest support. I think there's >value in keeping them in a separate file, rather than merging them >into hv_common.c. Maybe just move the entire hv_proc.c file? Agreed. I think it should be renamed too - this file will eventually contain some additional hypercall helper functions, some of which may also be shared by the driver code. Something like "hv_call_common.c"? >And then later, perhaps move the entire irqdomain.c file as well? Yes, may as well move it too. >There's also an interesting question of whether to move them into >drivers/hv, or create a new directory virt/hyperv. Hyper-V support >started out 15 years ago structured as a driver, hence "drivers/hv". >But over the time, the support has become significantly more than >just a driver, so "virt/hyperv" might be a better location for >non-driver code that had previously been under arch/x86 but is >now common to all architectures. > I'd be fine with using "virt/hyperv", but I thought "virt" was only for KVM. Another option would be to create subdirectories in "drivers/hv" to organize the different modules more cleanly (i.e. when the /dev/mshv driver code is introduced). > * Today, the code for running in the root partition is built along >with the rest of the Hyper-V support, and so is present in kernels >built for normal Linux guests on Hyper-V. I haven't thought about >all the implications, but perhaps there's value in having a CONFIG >option to build for the root partition, so that code can be dropped >from normal kernels. There's a significant amount of new code still >to come for mshv that could be excluded from normal guests in this >way. Also, the tests of the hv_root_partition variable could be >changed to a function the compiler detects is always "false" in a >kernel built without the CONFIG option, in which case it can drop >the code for where hv_root_partition is "true". > Using hv_root_partition is a good way to do it, since it won't require many #ifdefs or moving the existing code around too much. I can certainly give it a try, and create a separate patch series introducing the option. I suppose "CONFIG_HYPERV_ROOT" makes sense as a name? > * The code currently in hv_proc.c is built for x86 only, and validly >assumes the page size is 4K. But when the code moves to be >common across architectures, that assumption is no longer >valid in the general case. Perhaps the intent is that kernels for >the root partition should always be built with page size 4K on >arm64, but nothing enforces that intent. Personally, I think the code >should be made to work with page sizes other than 4K so as to not >leave technical debt. But I realize you may have other priorities. If >there were a CONFIG option for building for the root partition, >that option could be setup to enforce the 4K page size on arm64. > That makes sense. I suppose this can be done by selecting PAGE_SIZE_4KB under HYPERV in drivers/hv/Kconfig? I'm not how easy it will be to make the code work w
Re: [PATCH v3 1/5] hyperv: Move hv_connection_id to hyperv-tlfs.h
On 12/8/2024 4:07 PM, Wei Liu wrote: > On Mon, Nov 25, 2024 at 03:24:40PM -0800, Nuno Das Neves wrote: >> This definition is in the wrong file; it is part of the TLFS doc. >> >> Acked-by: Wei Liu >> Reviewed-by: Easwar Hariharan >> Reviewed-by: Michael Kelley >> Signed-off-by: Nuno Das Neves > > One comment about the ordering of the tags. It is better to organize > them in the following order: > > Signed-off-by: Nuno Das Neves > Acked-by: Wei Liu > Reviewed-by: Easwar Hariharan > Reviewed-by: Michael Kelley > > I've made the change for you while applying the patch. > Thank you, noted for next time. > Thanks, > Wei.
[PATCH v3 1/2] hyperv: Move hv_current_partition_id to arch-generic code
Move hv_current_partition_id and hv_get_partition_id() to hv_common.c, and call hv_get_partition_id() on arm64 in hyperv_init(). These aren't specific to x86_64 and will be needed by common code. Set hv_current_partition_id to HV_PARTITION_ID_SELF by default. Rename struct hv_get_partition_id to hv_output_get_partition_id, to make it distinct from the function hv_get_partition_id(), and match the original Hyper-V struct name. Remove the BUG()s. Failing to get the id need not crash the machine. Signed-off-by: Nuno Das Neves --- arch/arm64/hyperv/mshyperv.c| 3 +++ arch/x86/hyperv/hv_init.c | 25 + arch/x86/include/asm/mshyperv.h | 2 -- drivers/hv/hv_common.c | 22 ++ include/asm-generic/mshyperv.h | 2 ++ include/hyperv/hvgdk_mini.h | 2 +- 6 files changed, 29 insertions(+), 27 deletions(-) diff --git a/arch/arm64/hyperv/mshyperv.c b/arch/arm64/hyperv/mshyperv.c index fc49949b7df6..29fcfd595f48 100644 --- a/arch/arm64/hyperv/mshyperv.c +++ b/arch/arm64/hyperv/mshyperv.c @@ -72,6 +72,9 @@ static int __init hyperv_init(void) return ret; } + if (ms_hyperv.priv_high & HV_ACCESS_PARTITION_ID) + hv_get_partition_id(); + ms_hyperv_late_init(); hyperv_initialized = true; diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c index 173005e6a95d..9be1446f5bd3 100644 --- a/arch/x86/hyperv/hv_init.c +++ b/arch/x86/hyperv/hv_init.c @@ -34,9 +34,6 @@ #include #include -u64 hv_current_partition_id = ~0ull; -EXPORT_SYMBOL_GPL(hv_current_partition_id); - void *hv_hypercall_pg; EXPORT_SYMBOL_GPL(hv_hypercall_pg); @@ -393,24 +390,6 @@ static void __init hv_stimer_setup_percpu_clockev(void) old_setup_percpu_clockev(); } -static void __init hv_get_partition_id(void) -{ - struct hv_get_partition_id *output_page; - u64 status; - unsigned long flags; - - local_irq_save(flags); - output_page = *this_cpu_ptr(hyperv_pcpu_output_arg); - status = hv_do_hypercall(HVCALL_GET_PARTITION_ID, NULL, output_page); - if (!hv_result_success(status)) { - /* No point in proceeding if this failed */ - pr_err("Failed to get partition ID: %lld\n", status); - BUG(); - } - hv_current_partition_id = output_page->partition_id; - local_irq_restore(flags); -} - #if IS_ENABLED(CONFIG_HYPERV_VTL_MODE) static u8 __init get_vtl(void) { @@ -605,11 +584,9 @@ void __init hyperv_init(void) register_syscore_ops(&hv_syscore_ops); - if (cpuid_ebx(HYPERV_CPUID_FEATURES) & HV_ACCESS_PARTITION_ID) + if (ms_hyperv.priv_high & HV_ACCESS_PARTITION_ID) hv_get_partition_id(); - BUG_ON(hv_root_partition && hv_current_partition_id == ~0ull); - #ifdef CONFIG_PCI_MSI /* * If we're running as root, we want to create our own PCI MSI domain. diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h index f91ab1e75f9f..8d3ada3e8d0d 100644 --- a/arch/x86/include/asm/mshyperv.h +++ b/arch/x86/include/asm/mshyperv.h @@ -43,8 +43,6 @@ extern bool hyperv_paravisor_present; extern void *hv_hypercall_pg; -extern u64 hv_current_partition_id; - extern union hv_ghcb * __percpu *hv_ghcb_pg; bool hv_isolation_type_snp(void); diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c index af5d1dc451f6..cb3ea49020ef 100644 --- a/drivers/hv/hv_common.c +++ b/drivers/hv/hv_common.c @@ -31,6 +31,9 @@ #include #include +u64 hv_current_partition_id = HV_PARTITION_ID_SELF; +EXPORT_SYMBOL_GPL(hv_current_partition_id); + /* * hv_root_partition, ms_hyperv and hv_nested are defined here with other * Hyper-V specific globals so they are shared across all architectures and are @@ -283,6 +286,25 @@ static inline bool hv_output_page_exists(void) return hv_root_partition || IS_ENABLED(CONFIG_HYPERV_VTL_MODE); } +void __init hv_get_partition_id(void) +{ + struct hv_output_get_partition_id *output; + unsigned long flags; + u64 status, pt_id; + + local_irq_save(flags); + output = *this_cpu_ptr(hyperv_pcpu_input_arg); + status = hv_do_hypercall(HVCALL_GET_PARTITION_ID, NULL, &output); + pt_id = output->partition_id; + local_irq_restore(flags); + + if (hv_result_success(status)) + hv_current_partition_id = pt_id; + else + pr_err("Hyper-V: failed to get partition ID: %#lx\n", + hv_result(status)); +} + int __init hv_common_init(void) { int i; diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h index a7bbe504e4f3..febeddf6cd8a 100644 --- a/include/asm-generic/mshyperv.h +++ b/include/asm-generic/mshyperv.h @@ -58,6 +58,7 @@ struct ms_hyperv_info { }; extern struct ms_hyperv_info ms_hyperv; extern boo
[PATCH v3 2/2] hyperv: Move arch/x86/hyperv/hv_proc.c to drivers/hv
These helpers are not specific to x86_64 and will be needed by common code. Remove some unnecessary #includes. Reviewed-by: Michael Kelley Signed-off-by: Nuno Das Neves --- arch/x86/hyperv/Makefile | 2 +- arch/x86/include/asm/mshyperv.h | 4 drivers/hv/Makefile | 2 +- {arch/x86/hyperv => drivers/hv}/hv_proc.c | 4 include/asm-generic/mshyperv.h| 4 5 files changed, 6 insertions(+), 10 deletions(-) rename {arch/x86/hyperv => drivers/hv}/hv_proc.c (98%) diff --git a/arch/x86/hyperv/Makefile b/arch/x86/hyperv/Makefile index 3a1548054b48..d55f494f471d 100644 --- a/arch/x86/hyperv/Makefile +++ b/arch/x86/hyperv/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only obj-y := hv_init.o mmu.o nested.o irqdomain.o ivm.o -obj-$(CONFIG_X86_64) += hv_apic.o hv_proc.o +obj-$(CONFIG_X86_64) += hv_apic.o obj-$(CONFIG_HYPERV_VTL_MODE) += hv_vtl.o ifdef CONFIG_X86_64 diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h index 8d3ada3e8d0d..7dfca93ef048 100644 --- a/arch/x86/include/asm/mshyperv.h +++ b/arch/x86/include/asm/mshyperv.h @@ -56,10 +56,6 @@ u64 hv_tdx_hypercall(u64 control, u64 param1, u64 param2); #define HV_AP_INIT_GPAT_DEFAULT0x0007040600070406ULL #define HV_AP_SEGMENT_LIMIT0x -int hv_call_deposit_pages(int node, u64 partition_id, u32 num_pages); -int hv_call_add_logical_proc(int node, u32 lp_index, u32 acpi_id); -int hv_call_create_vp(int node, u64 partition_id, u32 vp_index, u32 flags); - /* * If the hypercall involves no input or output parameters, the hypervisor * ignores the corresponding GPA pointer. diff --git a/drivers/hv/Makefile b/drivers/hv/Makefile index b992c0ed182b..9afcabb3fbd2 100644 --- a/drivers/hv/Makefile +++ b/drivers/hv/Makefile @@ -13,4 +13,4 @@ hv_vmbus-$(CONFIG_HYPERV_TESTING) += hv_debugfs.o hv_utils-y := hv_util.o hv_kvp.o hv_snapshot.o hv_utils_transport.o # Code that must be built-in -obj-$(subst m,y,$(CONFIG_HYPERV)) += hv_common.o +obj-$(subst m,y,$(CONFIG_HYPERV)) += hv_common.o hv_proc.o diff --git a/arch/x86/hyperv/hv_proc.c b/drivers/hv/hv_proc.c similarity index 98% rename from arch/x86/hyperv/hv_proc.c rename to drivers/hv/hv_proc.c index ac4c834d4435..3e410489f480 100644 --- a/arch/x86/hyperv/hv_proc.c +++ b/drivers/hv/hv_proc.c @@ -6,11 +6,7 @@ #include #include #include -#include #include -#include - -#include /* * See struct hv_deposit_memory. The first u64 is partition ID, the rest diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h index febeddf6cd8a..7adc10a4fa3e 100644 --- a/include/asm-generic/mshyperv.h +++ b/include/asm-generic/mshyperv.h @@ -218,6 +218,10 @@ void *hv_alloc_hyperv_page(void); void *hv_alloc_hyperv_zeroed_page(void); void hv_free_hyperv_page(void *addr); +int hv_call_deposit_pages(int node, u64 partition_id, u32 num_pages); +int hv_call_add_logical_proc(int node, u32 lp_index, u32 acpi_id); +int hv_call_create_vp(int node, u64 partition_id, u32 vp_index, u32 flags); + /** * hv_cpu_number_to_vp_number() - Map CPU to VP. * @cpu_number: CPU number in Linux terms -- 2.34.1
[PATCH v3 0/2] hyperv: Move some features to common code
There are several bits of Hyper-V-related code that today live in arch/x86 but are not really specific to x86_64 and will work on arm64 too. Some of these will be needed in the upcoming mshv driver code (for Linux as root partition on Hyper-V). So this is a good time to move them to drivers/hv. Signed-off-by: Nuno Das Neves --- Changes in v3: * Just use percpu input page for the hypercall [Michael Kelley] * Move the calls to hv_get_partition_id() back to arch code [Michael Kelley] * Rename struct hv_get_partition_id to hv_output_get_partition_id [Michael Kelley] Changes in v2: * Fix dependence on percpu output page by using a stack variable for the hypercall output [Michael Kelley] * Remove unnecessary WARN()s [Michael Kelley] * Define hv_current_partition_id in hv_common.c [Michael Kelley] * Move entire hv_proc.c to drivers/hv [Michael Kelley] Nuno Das Neves (2): hyperv: Move hv_current_partition_id to arch-generic code hyperv: Move arch/x86/hyperv/hv_proc.c to drivers/hv arch/arm64/hyperv/mshyperv.c | 3 +++ arch/x86/hyperv/Makefile | 2 +- arch/x86/hyperv/hv_init.c | 25 +-- arch/x86/include/asm/mshyperv.h | 6 -- drivers/hv/Makefile | 2 +- drivers/hv/hv_common.c| 22 {arch/x86/hyperv => drivers/hv}/hv_proc.c | 4 include/asm-generic/mshyperv.h| 6 ++ include/hyperv/hvgdk_mini.h | 2 +- 9 files changed, 35 insertions(+), 37 deletions(-) rename {arch/x86/hyperv => drivers/hv}/hv_proc.c (98%) -- 2.34.1
[PATCH] hyperv: Add CONFIG_MSHV_ROOT to gate hv_root_partition checks
Introduce CONFIG_MSHV_ROOT as a tristate to enable root partition booting and future mshv driver functionality. Change hv_root_partition into a function which always returns false if CONFIG_MSHV_ROOT=n. Introduce hv_current_partition_type to store the type of partition (guest, root, or other kinds in future), and hv_identify_partition_type() to it up early in Hyper-V initialization. Signed-off-by: Nuno Das Neves --- Depends on https://lore.kernel.org/linux-hyperv/1738955002-20821-3-git-send-email-nunodasne...@linux.microsoft.com/ arch/arm64/hyperv/mshyperv.c | 2 ++ arch/x86/hyperv/hv_init.c | 10 arch/x86/kernel/cpu/mshyperv.c | 24 ++ drivers/clocksource/hyperv_timer.c | 4 +-- drivers/hv/Kconfig | 12 + drivers/hv/Makefile| 3 ++- drivers/hv/hv.c| 10 drivers/hv/hv_common.c | 32 +++- drivers/hv/vmbus_drv.c | 2 +- drivers/iommu/hyperv-iommu.c | 4 +-- include/asm-generic/mshyperv.h | 39 +- 11 files changed, 92 insertions(+), 50 deletions(-) diff --git a/arch/arm64/hyperv/mshyperv.c b/arch/arm64/hyperv/mshyperv.c index 29fcfd595f48..2265ea5ce5ad 100644 --- a/arch/arm64/hyperv/mshyperv.c +++ b/arch/arm64/hyperv/mshyperv.c @@ -61,6 +61,8 @@ static int __init hyperv_init(void) ms_hyperv.features, ms_hyperv.priv_high, ms_hyperv.hints, ms_hyperv.misc_features); + hv_identify_partition_type(); + ret = hv_common_init(); if (ret) return ret; diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c index 9be1446f5bd3..ddeb40930bc8 100644 --- a/arch/x86/hyperv/hv_init.c +++ b/arch/x86/hyperv/hv_init.c @@ -90,7 +90,7 @@ static int hv_cpu_init(unsigned int cpu) return 0; hvp = &hv_vp_assist_page[cpu]; - if (hv_root_partition) { + if (hv_root_partition()) { /* * For root partition we get the hypervisor provided VP assist * page, instead of allocating a new page. @@ -242,7 +242,7 @@ static int hv_cpu_die(unsigned int cpu) if (hv_vp_assist_page && hv_vp_assist_page[cpu]) { union hv_vp_assist_msr_contents msr = { 0 }; - if (hv_root_partition) { + if (hv_root_partition()) { /* * For root partition the VP assist page is mapped to * hypervisor provided page, and thus we unmap the @@ -317,7 +317,7 @@ static int hv_suspend(void) union hv_x64_msr_hypercall_contents hypercall_msr; int ret; - if (hv_root_partition) + if (hv_root_partition()) return -EPERM; /* @@ -518,7 +518,7 @@ void __init hyperv_init(void) rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); hypercall_msr.enable = 1; - if (hv_root_partition) { + if (hv_root_partition()) { struct page *pg; void *src; @@ -592,7 +592,7 @@ void __init hyperv_init(void) * If we're running as root, we want to create our own PCI MSI domain. * We can't set this in hv_pci_init because that would be too late. */ - if (hv_root_partition) + if (hv_root_partition()) x86_init.irqs.create_pci_msi_domain = hv_create_pci_msi_domain; #endif diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c index f285757618fc..4f01f424ea5b 100644 --- a/arch/x86/kernel/cpu/mshyperv.c +++ b/arch/x86/kernel/cpu/mshyperv.c @@ -33,8 +33,6 @@ #include #include -/* Is Linux running as the root partition? */ -bool hv_root_partition; /* Is Linux running on nested Microsoft Hypervisor */ bool hv_nested; struct ms_hyperv_info ms_hyperv; @@ -451,25 +449,7 @@ static void __init ms_hyperv_init_platform(void) pr_debug("Hyper-V: max %u virtual processors, %u logical processors\n", ms_hyperv.max_vp_index, ms_hyperv.max_lp_index); - /* -* Check CPU management privilege. -* -* To mirror what Windows does we should extract CPU management -* features and use the ReservedIdentityBit to detect if Linux is the -* root partition. But that requires negotiating CPU management -* interface (a process to be finalized). For now, use the privilege -* flag as the indicator for running as root. -* -* Hyper-V should never specify running as root and as a Confidential -* VM. But to protect against a compromised/malicious Hyper-V trying -* to exploit root behavior to expose Confidential VM memory, ignore -* the root partition setting if also a Confidential VM. -*/ - if ((ms_hyperv.priv_high & HV_CPU_MANAGEMENT) && -
Re: [PATCH 1/2] hyperv: Move hv_current_partition_id to arch-generic code
On 12/7/2024 7:01 PM, Michael Kelley wrote: > From: Nuno Das Neves Sent: Friday, > December 6, 2024 2:22 PM >> >> Make hv_current_partition_id available in both x86_64 and arm64. >> This feature isn't specific to x86_64 and will be needed by common >> code. >> >> While at it, replace the BUG()s with WARN()s. Failing to get the id >> need not crash the machine (although it is a very bad sign). >> >> Signed-off-by: Nuno Das Neves >> --- >> arch/arm64/hyperv/mshyperv.c| 3 +++ >> arch/x86/hyperv/hv_init.c | 25 + >> arch/x86/include/asm/mshyperv.h | 2 -- >> drivers/hv/hv_common.c | 23 +++ >> include/asm-generic/mshyperv.h | 2 ++ >> 5 files changed, 29 insertions(+), 26 deletions(-) >> >> diff --git a/arch/arm64/hyperv/mshyperv.c b/arch/arm64/hyperv/mshyperv.c >> index b1a4de4eee29..5050e748d266 100644 >> --- a/arch/arm64/hyperv/mshyperv.c >> +++ b/arch/arm64/hyperv/mshyperv.c >> @@ -19,6 +19,9 @@ >> >> static bool hyperv_initialized; >> >> +u64 hv_current_partition_id = HV_PARTITION_ID_SELF; >> +EXPORT_SYMBOL_GPL(hv_current_partition_id); >> + > > Instead of adding a definition of hv_current_partition_id on > the arm64 side, couldn't the definition on the x86 side in > hv_init.c be moved to hv_common.c (or maybe somewhere > else that is specific to running in the root partition, per my > comments in the cover letter), so there is only one definition > shared by both architectures? > Yes, that's a better idea. >> int hv_get_hypervisor_version(union hv_hypervisor_version_info *info) >> { >> hv_get_vpreg_128(HV_REGISTER_HYPERVISOR_VERSION, >> diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c >> index 95eada2994e1..950f5ccdb9d9 100644 >> --- a/arch/x86/hyperv/hv_init.c >> +++ b/arch/x86/hyperv/hv_init.c >> @@ -35,7 +35,7 @@ >> #include >> #include >> >> -u64 hv_current_partition_id = ~0ull; >> +u64 hv_current_partition_id = HV_PARTITION_ID_SELF; >> EXPORT_SYMBOL_GPL(hv_current_partition_id); >> >> void *hv_hypercall_pg; >> @@ -394,24 +394,6 @@ static void __init hv_stimer_setup_percpu_clockev(void) >> old_setup_percpu_clockev(); >> } >> >> -static void __init hv_get_partition_id(void) >> -{ >> -struct hv_get_partition_id *output_page; >> -u64 status; >> -unsigned long flags; >> - >> -local_irq_save(flags); >> -output_page = *this_cpu_ptr(hyperv_pcpu_output_arg); >> -status = hv_do_hypercall(HVCALL_GET_PARTITION_ID, NULL, output_page); >> -if (!hv_result_success(status)) { >> -/* No point in proceeding if this failed */ >> -pr_err("Failed to get partition ID: %lld\n", status); >> -BUG(); >> -} >> -hv_current_partition_id = output_page->partition_id; >> -local_irq_restore(flags); >> -} >> - >> #if IS_ENABLED(CONFIG_HYPERV_VTL_MODE) >> static u8 __init get_vtl(void) >> { >> @@ -606,11 +588,6 @@ void __init hyperv_init(void) >> >> register_syscore_ops(&hv_syscore_ops); >> >> -if (cpuid_ebx(HYPERV_CPUID_FEATURES) & HV_ACCESS_PARTITION_ID) >> -hv_get_partition_id(); >> - >> -BUG_ON(hv_root_partition && hv_current_partition_id == ~0ull); >> - >> #ifdef CONFIG_PCI_MSI >> /* >> * If we're running as root, we want to create our own PCI MSI domain. >> diff --git a/arch/x86/include/asm/mshyperv.h >> b/arch/x86/include/asm/mshyperv.h >> index 5f0bc6a6d025..9eeca2a6d047 100644 >> --- a/arch/x86/include/asm/mshyperv.h >> +++ b/arch/x86/include/asm/mshyperv.h >> @@ -44,8 +44,6 @@ extern bool hyperv_paravisor_present; >> >> extern void *hv_hypercall_pg; >> >> -extern u64 hv_current_partition_id; >> - >> extern union hv_ghcb * __percpu *hv_ghcb_pg; >> >> bool hv_isolation_type_snp(void); >> diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c >> index 7a35c82976e0..819bcfd2b149 100644 >> --- a/drivers/hv/hv_common.c >> +++ b/drivers/hv/hv_common.c >> @@ -278,11 +278,34 @@ static void hv_kmsg_dump_register(void) >> } >> } >> >> +static void __init hv_get_partition_id(void) >> +{ >> +struct hv_get_partition_id *output_page; >> +u64 status; >> +unsigned long flags; >> + >> +local_irq_save(flags); >> +output_page = *this_cpu_pt
Re: [PATCH 1/2] hyperv: Fix pointer type for the output of the hypercall in get_vtl(void)
On 12/18/2024 12:54 PM, Roman Kisel wrote: > Commit bc905fa8b633 ("hyperv: Switch from hyperv-tlfs.h to hyperv/hvhdk.h") > changed the type of the output pointer to `struct hv_register_assoc` from > `struct hv_get_vp_registers_output`. That leads to an incorrect computation, > and leaves the system broken. > My bad! But, lets not use `struct hv_get_registers_output`. Instead, use `struct hv_register_value`, since that is the more complete definition of a register value. The output of the get_vp_registers hypercall is just an array of these values. Ideally we remove `struct hv_get_vp_registers_output` at some point, since it serves the same role as `struct hv_register_value` but in a more limited capacity. Thanks Nuno > Use the correct pointer type for the output of the GetVpRegisters hypercall. > > Fixes: bc905fa8b633 ("hyperv: Switch from hyperv-tlfs.h to hyperv/hvhdk.h") > Signed-off-by: Roman Kisel > --- > arch/x86/hyperv/hv_init.c | 6 +++--- > include/hyperv/hvgdk_mini.h | 3 --- > 2 files changed, 3 insertions(+), 6 deletions(-) > > diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c > index 3cf2a227d666..c7185c6a290b 100644 > --- a/arch/x86/hyperv/hv_init.c > +++ b/arch/x86/hyperv/hv_init.c > @@ -416,13 +416,13 @@ static u8 __init get_vtl(void) > { > u64 control = HV_HYPERCALL_REP_COMP_1 | HVCALL_GET_VP_REGISTERS; > struct hv_input_get_vp_registers *input; > - struct hv_register_assoc *output; > + struct hv_get_vp_registers_output *output; > unsigned long flags; > u64 ret; > > local_irq_save(flags); > input = *this_cpu_ptr(hyperv_pcpu_input_arg); > - output = (struct hv_register_assoc *)input; > + output = (struct hv_get_vp_registers_output *)input; > > memset(input, 0, struct_size(input, names, 1)); > input->partition_id = HV_PARTITION_ID_SELF; > @@ -432,7 +432,7 @@ static u8 __init get_vtl(void) > > ret = hv_do_hypercall(control, input, output); > if (hv_result_success(ret)) { > - ret = output->value.reg8 & HV_X64_VTL_MASK; > + ret = output->as64.low & HV_X64_VTL_MASK; > } else { > pr_err("Failed to get VTL(error: %lld) exiting...\n", ret); > BUG(); > diff --git a/include/hyperv/hvgdk_mini.h b/include/hyperv/hvgdk_mini.h > index db3d1aaf7330..0b1a10828f33 100644 > --- a/include/hyperv/hvgdk_mini.h > +++ b/include/hyperv/hvgdk_mini.h > @@ -1107,7 +1107,6 @@ union hv_register_value { > union hv_x64_pending_interruption_register pending_interruption; > }; > > -#if defined(CONFIG_ARM64) > /* HvGetVpRegisters returns an array of these output elements */ > struct hv_get_vp_registers_output { > union { > @@ -1124,8 +1123,6 @@ struct hv_get_vp_registers_output { > }; > }; > > -#endif /* CONFIG_ARM64 */ > - > struct hv_register_assoc { > u32 name; /* enum hv_register_name */ > u32 reserved1;
Re: [PATCH 1/2] hyperv: Fix pointer type for the output of the hypercall in get_vtl(void)
On 12/19/2024 11:13 AM, Easwar Hariharan wrote: > On 12/19/2024 10:40 AM, Nuno Das Neves wrote: >> On 12/18/2024 12:54 PM, Roman Kisel wrote: >>> Commit bc905fa8b633 ("hyperv: Switch from hyperv-tlfs.h to hyperv/hvhdk.h") >>> changed the type of the output pointer to `struct hv_register_assoc` from >>> `struct hv_get_vp_registers_output`. That leads to an incorrect computation, >>> and leaves the system broken. >>> >> My bad! But, lets not use `struct hv_get_registers_output`. Instead, use >> `struct hv_register_value`, since that is the more complete definition of a >> register value. The output of the get_vp_registers hypercall is just an array >> of these values. >> >> Ideally we remove `struct hv_get_vp_registers_output` at some point, since >> it serves the same role as `struct hv_register_value` but in a more limited >> capacity. >> >> Thanks >> Nuno >> > > I had much the same conversation with Roman off-list yesterday. > > The choice is between using hv_get_registers_output which is clearly the > output of the GetVpRegisters hypercall by name, albeit limited as you If it's desirable to have a more 'friendly' naming here, then I'd be okay with: ``` /* NOTE: Linux helper struct - NOT from Hyper-V code */ struct hv_output_get_vp_registers { DECLARE_FLEX_ARRAY(struct hv_register_value, values); } ``` Note also the name is prefixed with "hv_output_" to match other hypercall outputs. > said, and hv_register_value which is the more complete definition and > what the hypervisor actually returns, but does not currently include the > arm64 definitions in our copy of hvgdk_mini.h. hv_get_registers_output > and hv_register_value overlap in layout for Roman's purposes. > > FWIW, I'm in favor of adding the arm64 definitions to hv_register_value > and using it for this get_vtl() patch. > > This could be accompanied with migration of hv_get_vpreg128 in arm64/ > and removal of struct hv_get_registers_output, or that could be deferred > to a later patch. I'd be happy to submit a followup patch to update the arm64 code to use hv_register_value, or a new struct as outlined above. It is a pretty small change though, it might be easier to just include it in this series. Nuno > > - Easwar
[PATCH 2/2] hyperv: Move create_vp and deposit_pages hvcalls to hv_common.c
From: Nuno Das Neves These are not specific to x86_64 and will be needed by common code. Signed-off-by: Nuno Das Neves --- arch/x86/hyperv/hv_proc.c | 144 --- arch/x86/include/asm/mshyperv.h | 2 - drivers/hv/hv_common.c | 145 include/asm-generic/mshyperv.h | 2 + 4 files changed, 147 insertions(+), 146 deletions(-) diff --git a/arch/x86/hyperv/hv_proc.c b/arch/x86/hyperv/hv_proc.c index 3fa1f2ee7b0d..119354d00637 100644 --- a/arch/x86/hyperv/hv_proc.c +++ b/arch/x86/hyperv/hv_proc.c @@ -10,109 +10,8 @@ #include #include #include - #include -/* - * See struct hv_deposit_memory. The first u64 is partition ID, the rest - * are GPAs. - */ -#define HV_DEPOSIT_MAX (HV_HYP_PAGE_SIZE / sizeof(u64) - 1) - -/* Deposits exact number of pages. Must be called with interrupts enabled. */ -int hv_call_deposit_pages(int node, u64 partition_id, u32 num_pages) -{ - struct page **pages, *page; - int *counts; - int num_allocations; - int i, j, page_count; - int order; - u64 status; - int ret; - u64 base_pfn; - struct hv_deposit_memory *input_page; - unsigned long flags; - - if (num_pages > HV_DEPOSIT_MAX) - return -E2BIG; - if (!num_pages) - return 0; - - /* One buffer for page pointers and counts */ - page = alloc_page(GFP_KERNEL); - if (!page) - return -ENOMEM; - pages = page_address(page); - - counts = kcalloc(HV_DEPOSIT_MAX, sizeof(int), GFP_KERNEL); - if (!counts) { - free_page((unsigned long)pages); - return -ENOMEM; - } - - /* Allocate all the pages before disabling interrupts */ - i = 0; - - while (num_pages) { - /* Find highest order we can actually allocate */ - order = 31 - __builtin_clz(num_pages); - - while (1) { - pages[i] = alloc_pages_node(node, GFP_KERNEL, order); - if (pages[i]) - break; - if (!order) { - ret = -ENOMEM; - num_allocations = i; - goto err_free_allocations; - } - --order; - } - - split_page(pages[i], order); - counts[i] = 1 << order; - num_pages -= counts[i]; - i++; - } - num_allocations = i; - - local_irq_save(flags); - - input_page = *this_cpu_ptr(hyperv_pcpu_input_arg); - - input_page->partition_id = partition_id; - - /* Populate gpa_page_list - these will fit on the input page */ - for (i = 0, page_count = 0; i < num_allocations; ++i) { - base_pfn = page_to_pfn(pages[i]); - for (j = 0; j < counts[i]; ++j, ++page_count) - input_page->gpa_page_list[page_count] = base_pfn + j; - } - status = hv_do_rep_hypercall(HVCALL_DEPOSIT_MEMORY, -page_count, 0, input_page, NULL); - local_irq_restore(flags); - if (!hv_result_success(status)) { - pr_err("Failed to deposit pages: %lld\n", status); - ret = hv_result(status); - goto err_free_allocations; - } - - ret = 0; - goto free_buf; - -err_free_allocations: - for (i = 0; i < num_allocations; ++i) { - base_pfn = page_to_pfn(pages[i]); - for (j = 0; j < counts[i]; ++j) - __free_page(pfn_to_page(base_pfn + j)); - } - -free_buf: - free_page((unsigned long)pages); - kfree(counts); - return ret; -} - int hv_call_add_logical_proc(int node, u32 lp_index, u32 apic_id) { struct hv_input_add_logical_processor *input; @@ -154,46 +53,3 @@ int hv_call_add_logical_proc(int node, u32 lp_index, u32 apic_id) return ret; } -int hv_call_create_vp(int node, u64 partition_id, u32 vp_index, u32 flags) -{ - struct hv_create_vp *input; - u64 status; - unsigned long irq_flags; - int ret = HV_STATUS_SUCCESS; - - /* Root VPs don't seem to need pages deposited */ - if (partition_id != hv_current_partition_id) { - /* The value 90 is empirically determined. It may change. */ - ret = hv_call_deposit_pages(node, partition_id, 90); - if (ret) - return ret; - } - - do { - local_irq_save(irq_flags); - - input = *this_cpu_ptr(hyperv_pcpu_input_arg); - - input->partition_id = partition_id; - input->vp_index = vp_index; - input->flags = flags; - input->subnode_type = HvSubnodeAny; - input-
[PATCH 1/2] hyperv: Move hv_current_partition_id to arch-generic code
From: Nuno Das Neves Make hv_current_partition_id available in both x86_64 and arm64. This feature isn't specific to x86_64 and will be needed by common code. While at it, replace the BUG()s with WARN()s. Failing to get the id need not crash the machine (although it is a very bad sign). Signed-off-by: Nuno Das Neves --- arch/arm64/hyperv/mshyperv.c| 3 +++ arch/x86/hyperv/hv_init.c | 25 + arch/x86/include/asm/mshyperv.h | 2 -- drivers/hv/hv_common.c | 23 +++ include/asm-generic/mshyperv.h | 2 ++ 5 files changed, 29 insertions(+), 26 deletions(-) diff --git a/arch/arm64/hyperv/mshyperv.c b/arch/arm64/hyperv/mshyperv.c index b1a4de4eee29..5050e748d266 100644 --- a/arch/arm64/hyperv/mshyperv.c +++ b/arch/arm64/hyperv/mshyperv.c @@ -19,6 +19,9 @@ static bool hyperv_initialized; +u64 hv_current_partition_id = HV_PARTITION_ID_SELF; +EXPORT_SYMBOL_GPL(hv_current_partition_id); + int hv_get_hypervisor_version(union hv_hypervisor_version_info *info) { hv_get_vpreg_128(HV_REGISTER_HYPERVISOR_VERSION, diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c index 95eada2994e1..950f5ccdb9d9 100644 --- a/arch/x86/hyperv/hv_init.c +++ b/arch/x86/hyperv/hv_init.c @@ -35,7 +35,7 @@ #include #include -u64 hv_current_partition_id = ~0ull; +u64 hv_current_partition_id = HV_PARTITION_ID_SELF; EXPORT_SYMBOL_GPL(hv_current_partition_id); void *hv_hypercall_pg; @@ -394,24 +394,6 @@ static void __init hv_stimer_setup_percpu_clockev(void) old_setup_percpu_clockev(); } -static void __init hv_get_partition_id(void) -{ - struct hv_get_partition_id *output_page; - u64 status; - unsigned long flags; - - local_irq_save(flags); - output_page = *this_cpu_ptr(hyperv_pcpu_output_arg); - status = hv_do_hypercall(HVCALL_GET_PARTITION_ID, NULL, output_page); - if (!hv_result_success(status)) { - /* No point in proceeding if this failed */ - pr_err("Failed to get partition ID: %lld\n", status); - BUG(); - } - hv_current_partition_id = output_page->partition_id; - local_irq_restore(flags); -} - #if IS_ENABLED(CONFIG_HYPERV_VTL_MODE) static u8 __init get_vtl(void) { @@ -606,11 +588,6 @@ void __init hyperv_init(void) register_syscore_ops(&hv_syscore_ops); - if (cpuid_ebx(HYPERV_CPUID_FEATURES) & HV_ACCESS_PARTITION_ID) - hv_get_partition_id(); - - BUG_ON(hv_root_partition && hv_current_partition_id == ~0ull); - #ifdef CONFIG_PCI_MSI /* * If we're running as root, we want to create our own PCI MSI domain. diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h index 5f0bc6a6d025..9eeca2a6d047 100644 --- a/arch/x86/include/asm/mshyperv.h +++ b/arch/x86/include/asm/mshyperv.h @@ -44,8 +44,6 @@ extern bool hyperv_paravisor_present; extern void *hv_hypercall_pg; -extern u64 hv_current_partition_id; - extern union hv_ghcb * __percpu *hv_ghcb_pg; bool hv_isolation_type_snp(void); diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c index 7a35c82976e0..819bcfd2b149 100644 --- a/drivers/hv/hv_common.c +++ b/drivers/hv/hv_common.c @@ -278,11 +278,34 @@ static void hv_kmsg_dump_register(void) } } +static void __init hv_get_partition_id(void) +{ + struct hv_get_partition_id *output_page; + u64 status; + unsigned long flags; + + local_irq_save(flags); + output_page = *this_cpu_ptr(hyperv_pcpu_output_arg); + status = hv_do_hypercall(HVCALL_GET_PARTITION_ID, NULL, output_page); + if (!hv_result_success(status)) { + local_irq_restore(flags); + WARN(true, "Failed to get partition ID: %lld\n", status); + return; + } + hv_current_partition_id = output_page->partition_id; + local_irq_restore(flags); +} + int __init hv_common_init(void) { int i; union hv_hypervisor_version_info version; + if (ms_hyperv.priv_high & HV_ACCESS_PARTITION_ID) + hv_get_partition_id(); + + WARN_ON(hv_root_partition && hv_current_partition_id == HV_PARTITION_ID_SELF); + /* Get information about the Hyper-V host version */ if (!hv_get_hypervisor_version(&version)) pr_info("Hyper-V: Host Build %d.%d.%d.%d-%d-%d\n", diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h index 8fe7aaab2599..8c4ff6e9aae7 100644 --- a/include/asm-generic/mshyperv.h +++ b/include/asm-generic/mshyperv.h @@ -60,6 +60,8 @@ struct ms_hyperv_info { extern struct ms_hyperv_info ms_hyperv; extern bool hv_nested; +extern u64 hv_current_partition_id; + extern void * __percpu *hyperv_pcpu_input_arg; extern void * __percpu *hyperv_pcpu_output_arg; -- 2.34.1
[PATCH 0/2] hyperv: Move some features to common code
There are several bits of Hyper-V-related code that today live in arch/x86 but are not really specific to x86_64 and will work on arm64 too. Some of these will be needed in the upcoming mshv driver code (for Linux as root partition on Hyper-V). So this is a good time to move them to hv_common.c. Signed-off-by: Nuno Das Neves Nuno Das Neves (2): hyperv: Move hv_current_partition_id to arch-generic code hyperv: Move create_vp and deposit_pages hvcalls to hv_common.c arch/arm64/hyperv/mshyperv.c| 3 + arch/x86/hyperv/hv_init.c | 25 + arch/x86/hyperv/hv_proc.c | 144 --- arch/x86/include/asm/mshyperv.h | 4 - drivers/hv/hv_common.c | 168 include/asm-generic/mshyperv.h | 4 + 6 files changed, 176 insertions(+), 172 deletions(-) -- 2.34.1
Re: [PATCH v5 2/5] hyperv: Fix pointer type in get_vtl(void)
On 12/30/2024 10:09 AM, Roman Kisel wrote: > Commit bc905fa8b633 ("hyperv: Switch from hyperv-tlfs.h to hyperv/hvhdk.h") > changed the type of the output pointer to `struct hv_register_assoc` from > `struct hv_get_vp_registers_output`. That leads to an incorrect computation, > and leaves the system broken. > > Use the correct pointer type for the output of the GetVpRegisters hypercall. > > Signed-off-by: Roman Kisel > --- > arch/x86/hyperv/hv_init.c | 6 +++--- > 1 file changed, 3 insertions(+), 3 deletions(-) > > diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c > index 9e5e8328df6b..f82d1aefaa8a 100644 > --- a/arch/x86/hyperv/hv_init.c > +++ b/arch/x86/hyperv/hv_init.c > @@ -416,13 +416,13 @@ static u8 __init get_vtl(void) > { > u64 control = HV_HYPERCALL_REP_COMP_1 | HVCALL_GET_VP_REGISTERS; > struct hv_input_get_vp_registers *input; > - struct hv_register_assoc *output; > + struct hv_output_get_vp_registers *output; > unsigned long flags; > u64 ret; > > local_irq_save(flags); > input = *this_cpu_ptr(hyperv_pcpu_input_arg); > - output = (struct hv_register_assoc *)input; > + output = (struct hv_output_get_vp_registers *)input; > > memset(input, 0, struct_size(input, names, 1)); > input->partition_id = HV_PARTITION_ID_SELF; > @@ -432,7 +432,7 @@ static u8 __init get_vtl(void) > > ret = hv_do_hypercall(control, input, output); > if (hv_result_success(ret)) { > - ret = output->value.reg8 & HV_X64_VTL_MASK; > + ret = output->values[0].reg8 & HV_X64_VTL_MASK; > } else { > pr_err("Failed to get VTL(error: %lld) exiting...\n", ret); > BUG(); Reviewed-by: Nuno Das Neves
Re: [PATCH v5 1/5] hyperv: Define struct hv_output_get_vp_registers
On 1/6/2025 9:37 AM, Michael Kelley wrote: > From: Roman Kisel Sent: Monday, December 30, > 2024 10:10 AM >> >> There is no definition of the output structure for the >> GetVpRegisters hypercall. Hence, using the hypercall >> is not possible when the output value has some structure >> to it. Even getting a datum of a primitive type reads >> as ad-hoc without that definition. >> >> Define struct hv_output_get_vp_registers to enable using >> the GetVpRegisters hypercall. Make provisions for all >> supported architectures. No functional changes. >> >> Signed-off-by: Roman Kisel >> --- >> include/hyperv/hvgdk_mini.h | 49 + >> 1 file changed, 49 insertions(+) >> >> diff --git a/include/hyperv/hvgdk_mini.h b/include/hyperv/hvgdk_mini.h >> index db3d1aaf7330..e8e3faa78e15 100644 >> --- a/include/hyperv/hvgdk_mini.h >> +++ b/include/hyperv/hvgdk_mini.h >> @@ -1068,6 +1068,35 @@ union hv_dispatch_suspend_register { >> } __packed; >> }; >> >> +union hv_arm64_pending_interruption_register { >> +u64 as_uint64; >> +struct { >> +u64 interruption_pending : 1; >> +u64 interruption_type : 1; >> +u64 reserved : 30; >> +u32 error_code; > > These bit field definitions don't look right. We want to "fill up" > the field size, so that we're explicit about each bit, and not leave > it to the compiler to add padding (which __packed tells the > compiler not to do). So in aggregate, the "u64" bit fields should > account for all 64 bits, but here you account for only 32 bits. > There are two ways to fix this: > > u32 interruption_pending : 1; > u32 interruption_type: 1; > u32 reserved : 30; > u32 error_code; > Or > u64 interruption_pending : 1; > u64 interruption_type: 1; > u64 reserved : 30; > u64 error_code : 32; > Agreed. In the spirit of matching the original headers, I'd prefer the second one. But either will work. >> +} __packed; >> +}; >> + >> +union hv_arm64_interrupt_state_register { >> +u64 as_uint64; >> +struct { >> +u64 interrupt_shadow : 1; >> +u64 reserved : 63; >> +} __packed; >> +}; >> + >> +union hv_arm64_pending_synthetic_exception_event { >> +u64 as_uint64[2]; >> +struct { >> +u32 event_pending : 1; >> +u32 event_type : 3; >> +u32 reserved : 4; > > Same here. Expand the "reserved" field to 28 bits? Or maybe > there's a reason to have two separate reserved fields of 4 bits > and 24 bits. I'm not sure what the register layout is supposed to > be. Looking at hv_arm64_pending_synthetic_exception_event > in the OHCL-Linux-Kernel github tree shows the same gap of > 24 bits, so that doesn't provide any guidance. > Hmm..these should be u8 bitfields according to the Hyper-V code. However that leaves a 24 bit gap as you pointed out. In the Hyper-V code, these structures aren't actually packed, which means sometimes the explicit padding is left out (unintentionally). Please add the 24 bits of padding to make it explicit here. I suggest making the bitfields u8 as in the original code, and adding another padding field after, like: u8 event_pending : 1; u8 event_type : 3; u8 reserved : 4; u8 rsvd[3]; >> +u32 exception_type; >> +u64 context; >> +} __packed; >> +}; >> + >> union hv_x64_interrupt_state_register { >> u64 as_uint64; >> struct { >> @@ -1103,8 +1132,28 @@ union hv_register_value { >> union hv_explicit_suspend_register explicit_suspend; >> union hv_intercept_suspend_register intercept_suspend; >> union hv_dispatch_suspend_register dispatch_suspend; >> +#ifdef CONFIG_ARM64 >> +union hv_arm64_interrupt_state_register interrupt_state; >> +union hv_arm64_pending_interruption_register pending_interruption; >> +#endif >> +#ifdef CONFIG_X86 >> union hv_x64_interrupt_state_register interrupt_state; >> union hv_x64_pending_interruption_register pending_interruption; >> +#endif >> +union hv_arm64_pending_synthetic_exception_event >> pending_synthetic_exception_event; >> +}; > > Per the previous discussion, I can see that the #ifdef's are needed > here to disambiguate the field names that are the same, but have > different unions on x86 and arm64. > > But on the flip side, I wonder if the field names should really be the > same. Because of the different unions, it seems like they couldn't be > accessed by architecture neutral code (unless the access is just using > the "as_uint64" option?). So giving the fields names like > "x86_interrupt_state" and "arm64_interrupt_state" instead of just > "interrupt_state" might be more consistent with how the rest of this > file handles architecture differences. But I don't know all the implications > of making such a change. > > Nuno -- your thoughts? My main preference is to match with the original code unl
Re: [PATCH 1/2] hyperv: Move hv_current_partition_id to arch-generic code
On 12/6/2024 11:36 PM, Wei Liu wrote: > On Fri, Dec 06, 2024 at 02:21:46PM -0800, Nuno Das Neves wrote: >> From: Nuno Das Neves >> >> Make hv_current_partition_id available in both x86_64 and arm64. >> This feature isn't specific to x86_64 and will be needed by common >> code. >> >> While at it, replace the BUG()s with WARN()s. Failing to get the id >> need not crash the machine (although it is a very bad sign). >> > > A lot of things have changed since it was introduced. I don't remember > why I decided to use BUG() instead of WARN() in the first place. > > If the system can still function without knowing its partition id, then > can this be removed completely? We can always use the SELF id. > Missed this earlier, sorry. I checked the code and it seems that HV_PARTITION_ID_SELF may be sufficient. However, I'm not sure if there is some case where it is actually needed, so I'm hesitant to remove it at the moment. Nuno > Thanks, > Wei. > >> Signed-off-by: Nuno Das Neves >> --- >> arch/arm64/hyperv/mshyperv.c| 3 +++ >> arch/x86/hyperv/hv_init.c | 25 + >> arch/x86/include/asm/mshyperv.h | 2 -- >> drivers/hv/hv_common.c | 23 +++ >> include/asm-generic/mshyperv.h | 2 ++ >> 5 files changed, 29 insertions(+), 26 deletions(-) >> >> diff --git a/arch/arm64/hyperv/mshyperv.c b/arch/arm64/hyperv/mshyperv.c >> index b1a4de4eee29..5050e748d266 100644 >> --- a/arch/arm64/hyperv/mshyperv.c >> +++ b/arch/arm64/hyperv/mshyperv.c >> @@ -19,6 +19,9 @@ >> >> static bool hyperv_initialized; >> >> +u64 hv_current_partition_id = HV_PARTITION_ID_SELF; >> +EXPORT_SYMBOL_GPL(hv_current_partition_id); >> + >> int hv_get_hypervisor_version(union hv_hypervisor_version_info *info) >> { >> hv_get_vpreg_128(HV_REGISTER_HYPERVISOR_VERSION, >> diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c >> index 95eada2994e1..950f5ccdb9d9 100644 >> --- a/arch/x86/hyperv/hv_init.c >> +++ b/arch/x86/hyperv/hv_init.c >> @@ -35,7 +35,7 @@ >> #include >> #include >> >> -u64 hv_current_partition_id = ~0ull; >> +u64 hv_current_partition_id = HV_PARTITION_ID_SELF; >> EXPORT_SYMBOL_GPL(hv_current_partition_id); >> >> void *hv_hypercall_pg; >> @@ -394,24 +394,6 @@ static void __init hv_stimer_setup_percpu_clockev(void) >> old_setup_percpu_clockev(); >> } >> >> -static void __init hv_get_partition_id(void) >> -{ >> -struct hv_get_partition_id *output_page; >> -u64 status; >> -unsigned long flags; >> - >> -local_irq_save(flags); >> -output_page = *this_cpu_ptr(hyperv_pcpu_output_arg); >> -status = hv_do_hypercall(HVCALL_GET_PARTITION_ID, NULL, output_page); >> -if (!hv_result_success(status)) { >> -/* No point in proceeding if this failed */ >> -pr_err("Failed to get partition ID: %lld\n", status); >> -BUG(); >> -} >> -hv_current_partition_id = output_page->partition_id; >> -local_irq_restore(flags); >> -} >> - >> #if IS_ENABLED(CONFIG_HYPERV_VTL_MODE) >> static u8 __init get_vtl(void) >> { >> @@ -606,11 +588,6 @@ void __init hyperv_init(void) >> >> register_syscore_ops(&hv_syscore_ops); >> >> -if (cpuid_ebx(HYPERV_CPUID_FEATURES) & HV_ACCESS_PARTITION_ID) >> -hv_get_partition_id(); >> - >> -BUG_ON(hv_root_partition && hv_current_partition_id == ~0ull); >> - >> #ifdef CONFIG_PCI_MSI >> /* >> * If we're running as root, we want to create our own PCI MSI domain. >> diff --git a/arch/x86/include/asm/mshyperv.h >> b/arch/x86/include/asm/mshyperv.h >> index 5f0bc6a6d025..9eeca2a6d047 100644 >> --- a/arch/x86/include/asm/mshyperv.h >> +++ b/arch/x86/include/asm/mshyperv.h >> @@ -44,8 +44,6 @@ extern bool hyperv_paravisor_present; >> >> extern void *hv_hypercall_pg; >> >> -extern u64 hv_current_partition_id; >> - >> extern union hv_ghcb * __percpu *hv_ghcb_pg; >> >> bool hv_isolation_type_snp(void); >> diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c >> index 7a35c82976e0..819bcfd2b149 100644 >> --- a/drivers/hv/hv_common.c >> +++ b/drivers/hv/hv_common.c >> @@ -278,11 +278,34 @@ static void hv_kmsg_dump_register(void) >> } >> } >> >> +static void __init hv_get_partition_id(void) >
Re: [PATCH 0/2] hyperv: Move some features to common code
On 12/17/2024 9:48 AM, Michael Kelley wrote: > From: Nuno Das Neves Sent: Monday, > December 9, 2024 12:20 PM >> >> On 12/7/2024 6:59 PM, Michael Kelley wrote: >>> From: Nuno Das Neves Sent: Friday, >>> December 6, 2024 2:22 PM >>>> >>>> There are several bits of Hyper-V-related code that today live in >>>> arch/x86 but are not really specific to x86_64 and will work on arm64 >>>> too. >>>> >>>> Some of these will be needed in the upcoming mshv driver code (for >>>> Linux as root partition on Hyper-V). >>> >>> Previously, Linux as the root partition on Hyper-V was x86 only, which is >>> why the code is currently under arch/x86. So evidently the mshv driver >>> is being expanded to support both x86 and arm64, correct? Assuming >>> that's the case, I have some thoughts about how the source code should >>> be organized and built. It's probably best to get this right to start with >>> so >>> it doesn't need to be changed again. >> >> Yes, we plan on supporting both architectures (eventually). I completely >> agree >> that it's better to sort out these issues now rather than later. >> >>> >>> * Patch 2 of this series moves hv_call_deposit_pages() and >>>hv_call_create_vp() to common code, but does not move >>>hv_call_add_logical_proc(). All three are used together, so >>>I'm wondering why hv_call_add_logical_proc() isn't moved. >>> >> >> The only reason is that in our internal tree there's no common or arm64 code >> yet that uses it - there is no reason it can't also become common code! > > Maybe I'm missing your point, but hv_call_add_logical_proc() and > hv_call_create_vp() are called in succession in hv_smp_prepare_cpus(), > so it seems like they very much go together. Presumably a similar > sequence will be needed on the arm64 side when running as the > root partition? > Yes that's right, sorry I wasn't being too clear. >> >>> * These three functions were originally put in a separate source >>>code file because of being specific to running in the root partition, >>>and not needed for generic Linux guest support. I think there's >>>value in keeping them in a separate file, rather than merging them >>>into hv_common.c. Maybe just move the entire hv_proc.c file? >> >> Agreed. I think it should be renamed too - this file will eventually >> contain some additional hypercall helper functions, some of which may also be >> shared by the driver code. Something like "hv_call_common.c"? > > I went back and looked at your patch series from a year ago [1], and > got a better understanding of where this work is headed. I wanted > to comment on that series back then, but got subsumed in wrapping > things up for my retirement. :-( I see significant portions of that > series have been posted independently and accepted, so my further > comments here assume the rest of the series is still the macro-level > approach you are taking. > >>From that series, you are planning three modules, controlled by > CONFIG_MSHV, CONFIG_MSHV_ROOT, and CONFIG_MSHV_VTL. > That makes sense, and addresses one of my top-level concerns, > which is that normal guest kernels shouldn't include all that code. > And apparently that code works as a module as well as built-in. > > The code currently in hv_proc.c is similar to the code in hv_call.c > and mshv_root_hv_call.c from that series -- it's a wrapper around > Hyper-V hypercalls. But a difference is that the code in hv_proc.c > can't be a module because it is called from hv_smp_prepare_cpus(), > which must be built-in. So it can't be added to the proposed > hv_call.c without making all of hv_call.c built-in. Ideally, there > would be a separate source file just for the code that must be > built-in. I'm not familiar enough with root partition requirements > to understand what hv_smp_prepare_cpus() and its calls to > hv_call_add_logical_proc() and hv_call_create_vp() are doing. > Evidently it is related to bringing up CPUs in the root partition, > and not related to guest VMs. But those two hv_call_* functions > would also be used for managing guest VMs from /dev/mshv. > It makes sense to keep the different kinds of functionality separated based on where they are needed. I do wonder if it will be cumbersome to keep all the cases in their own files - builtin/module, root/guest, and separated into arch directories vs drivers/hv... > As for the name, I don't really like "common&qu
[PATCH v2 2/2] hyperv: Move arch/x86/hyperv/hv_proc.c to drivers/hv
These helpers are not specific to x86_64 and will be needed by common code. Remove some unnecessary #includes. Signed-off-by: Nuno Das Neves --- arch/x86/hyperv/Makefile | 2 +- arch/x86/include/asm/mshyperv.h | 4 drivers/hv/Makefile | 2 +- {arch/x86/hyperv => drivers/hv}/hv_proc.c | 4 include/asm-generic/mshyperv.h| 4 5 files changed, 6 insertions(+), 10 deletions(-) rename {arch/x86/hyperv => drivers/hv}/hv_proc.c (98%) diff --git a/arch/x86/hyperv/Makefile b/arch/x86/hyperv/Makefile index 3a1548054b48..d55f494f471d 100644 --- a/arch/x86/hyperv/Makefile +++ b/arch/x86/hyperv/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only obj-y := hv_init.o mmu.o nested.o irqdomain.o ivm.o -obj-$(CONFIG_X86_64) += hv_apic.o hv_proc.o +obj-$(CONFIG_X86_64) += hv_apic.o obj-$(CONFIG_HYPERV_VTL_MODE) += hv_vtl.o ifdef CONFIG_X86_64 diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h index 8d3ada3e8d0d..7dfca93ef048 100644 --- a/arch/x86/include/asm/mshyperv.h +++ b/arch/x86/include/asm/mshyperv.h @@ -56,10 +56,6 @@ u64 hv_tdx_hypercall(u64 control, u64 param1, u64 param2); #define HV_AP_INIT_GPAT_DEFAULT0x0007040600070406ULL #define HV_AP_SEGMENT_LIMIT0x -int hv_call_deposit_pages(int node, u64 partition_id, u32 num_pages); -int hv_call_add_logical_proc(int node, u32 lp_index, u32 acpi_id); -int hv_call_create_vp(int node, u64 partition_id, u32 vp_index, u32 flags); - /* * If the hypercall involves no input or output parameters, the hypervisor * ignores the corresponding GPA pointer. diff --git a/drivers/hv/Makefile b/drivers/hv/Makefile index b992c0ed182b..9afcabb3fbd2 100644 --- a/drivers/hv/Makefile +++ b/drivers/hv/Makefile @@ -13,4 +13,4 @@ hv_vmbus-$(CONFIG_HYPERV_TESTING) += hv_debugfs.o hv_utils-y := hv_util.o hv_kvp.o hv_snapshot.o hv_utils_transport.o # Code that must be built-in -obj-$(subst m,y,$(CONFIG_HYPERV)) += hv_common.o +obj-$(subst m,y,$(CONFIG_HYPERV)) += hv_common.o hv_proc.o diff --git a/arch/x86/hyperv/hv_proc.c b/drivers/hv/hv_proc.c similarity index 98% rename from arch/x86/hyperv/hv_proc.c rename to drivers/hv/hv_proc.c index ac4c834d4435..3e410489f480 100644 --- a/arch/x86/hyperv/hv_proc.c +++ b/drivers/hv/hv_proc.c @@ -6,11 +6,7 @@ #include #include #include -#include #include -#include - -#include /* * See struct hv_deposit_memory. The first u64 is partition ID, the rest diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h index 98100466e0b2..faf5d27a76b1 100644 --- a/include/asm-generic/mshyperv.h +++ b/include/asm-generic/mshyperv.h @@ -217,6 +217,10 @@ void *hv_alloc_hyperv_page(void); void *hv_alloc_hyperv_zeroed_page(void); void hv_free_hyperv_page(void *addr); +int hv_call_deposit_pages(int node, u64 partition_id, u32 num_pages); +int hv_call_add_logical_proc(int node, u32 lp_index, u32 acpi_id); +int hv_call_create_vp(int node, u64 partition_id, u32 vp_index, u32 flags); + /** * hv_cpu_number_to_vp_number() - Map CPU to VP. * @cpu_number: CPU number in Linux terms -- 2.34.1
[PATCH v2 0/2] hyperv: Move some features to common code
There are several bits of Hyper-V-related code that today live in arch/x86 but are not really specific to x86_64 and will work on arm64 too. Some of these will be needed in the upcoming mshv driver code (for Linux as root partition on Hyper-V). So this is a good time to move them to drivers/hv. Signed-off-by: Nuno Das Neves --- Changes in v2: * Fix dependence on percpu output page by using a stack variable for the hypercall output [Michael Kelley] * Remove unnecessary WARN()s [Michael Kelley] * Define hv_current_partition_id in hv_common.c [Michael Kelley] * Move entire hv_proc.c to drivers/hv [Michael Kelley] Nuno Das Neves (2): hyperv: Move hv_current_partition_id to arch-generic code hyperv: Move arch/x86/hyperv/hv_proc.c to drivers/hv arch/x86/hyperv/Makefile | 2 +- arch/x86/hyperv/hv_init.c | 26 --- arch/x86/include/asm/mshyperv.h | 6 -- drivers/hv/Makefile | 2 +- drivers/hv/hv_common.c| 23 {arch/x86/hyperv => drivers/hv}/hv_proc.c | 4 include/asm-generic/mshyperv.h| 5 + 7 files changed, 30 insertions(+), 38 deletions(-) rename {arch/x86/hyperv => drivers/hv}/hv_proc.c (98%) -- 2.34.1
[PATCH v2 1/2] hyperv: Move hv_current_partition_id to arch-generic code
From: Nuno Das Neves Move hv_current_partition_id and hv_get_partition_id() to hv_common.c. These aren't specific to x86_64 and will be needed by common code. Set hv_current_partition_id to HV_PARTITION_ID_SELF by default. Use a stack variable for the output of the hypercall. This allows moving the call of hv_get_partition_id() to hv_common_init() before the percpu pages are initialized. Remove the BUG()s. Failing to get the id need not crash the machine. Signed-off-by: Nuno Das Neves --- arch/x86/hyperv/hv_init.c | 26 -- arch/x86/include/asm/mshyperv.h | 2 -- drivers/hv/hv_common.c | 23 +++ include/asm-generic/mshyperv.h | 1 + 4 files changed, 24 insertions(+), 28 deletions(-) diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c index 173005e6a95d..6b9f6f9f704d 100644 --- a/arch/x86/hyperv/hv_init.c +++ b/arch/x86/hyperv/hv_init.c @@ -34,9 +34,6 @@ #include #include -u64 hv_current_partition_id = ~0ull; -EXPORT_SYMBOL_GPL(hv_current_partition_id); - void *hv_hypercall_pg; EXPORT_SYMBOL_GPL(hv_hypercall_pg); @@ -393,24 +390,6 @@ static void __init hv_stimer_setup_percpu_clockev(void) old_setup_percpu_clockev(); } -static void __init hv_get_partition_id(void) -{ - struct hv_get_partition_id *output_page; - u64 status; - unsigned long flags; - - local_irq_save(flags); - output_page = *this_cpu_ptr(hyperv_pcpu_output_arg); - status = hv_do_hypercall(HVCALL_GET_PARTITION_ID, NULL, output_page); - if (!hv_result_success(status)) { - /* No point in proceeding if this failed */ - pr_err("Failed to get partition ID: %lld\n", status); - BUG(); - } - hv_current_partition_id = output_page->partition_id; - local_irq_restore(flags); -} - #if IS_ENABLED(CONFIG_HYPERV_VTL_MODE) static u8 __init get_vtl(void) { @@ -605,11 +584,6 @@ void __init hyperv_init(void) register_syscore_ops(&hv_syscore_ops); - if (cpuid_ebx(HYPERV_CPUID_FEATURES) & HV_ACCESS_PARTITION_ID) - hv_get_partition_id(); - - BUG_ON(hv_root_partition && hv_current_partition_id == ~0ull); - #ifdef CONFIG_PCI_MSI /* * If we're running as root, we want to create our own PCI MSI domain. diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h index f91ab1e75f9f..8d3ada3e8d0d 100644 --- a/arch/x86/include/asm/mshyperv.h +++ b/arch/x86/include/asm/mshyperv.h @@ -43,8 +43,6 @@ extern bool hyperv_paravisor_present; extern void *hv_hypercall_pg; -extern u64 hv_current_partition_id; - extern union hv_ghcb * __percpu *hv_ghcb_pg; bool hv_isolation_type_snp(void); diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c index af5d1dc451f6..1da19b64ef16 100644 --- a/drivers/hv/hv_common.c +++ b/drivers/hv/hv_common.c @@ -31,6 +31,9 @@ #include #include +u64 hv_current_partition_id = HV_PARTITION_ID_SELF; +EXPORT_SYMBOL_GPL(hv_current_partition_id); + /* * hv_root_partition, ms_hyperv and hv_nested are defined here with other * Hyper-V specific globals so they are shared across all architectures and are @@ -283,6 +286,23 @@ static inline bool hv_output_page_exists(void) return hv_root_partition || IS_ENABLED(CONFIG_HYPERV_VTL_MODE); } +static void __init hv_get_partition_id(void) +{ + /* +* Note in this case the output can be on the stack because it is just +* a single u64 and hence won't cross a page boundary. +*/ + struct hv_get_partition_id output; + u64 status; + + status = hv_do_hypercall(HVCALL_GET_PARTITION_ID, NULL, &output); + if (!hv_result_success(status)) { + pr_err("Hyper-V: failed to get partition ID: %#lx\n", status); + return; + } + hv_current_partition_id = output.partition_id; +} + int __init hv_common_init(void) { int i; @@ -298,6 +318,9 @@ int __init hv_common_init(void) if (hv_is_isolation_supported()) sysctl_record_panic_msg = 0; + if (ms_hyperv.priv_high & HV_ACCESS_PARTITION_ID) + hv_get_partition_id(); + /* * Hyper-V expects to get crash register data or kmsg when * crash enlightment is available and system crashes. Set diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h index a7bbe504e4f3..98100466e0b2 100644 --- a/include/asm-generic/mshyperv.h +++ b/include/asm-generic/mshyperv.h @@ -58,6 +58,7 @@ struct ms_hyperv_info { }; extern struct ms_hyperv_info ms_hyperv; extern bool hv_nested; +extern u64 hv_current_partition_id; extern void * __percpu *hyperv_pcpu_input_arg; extern void * __percpu *hyperv_pcpu_output_arg; -- 2.34.1