Skip to content

Commit a5b3d86

Browse files
committed
Merge tag 'hyperv-next-signed-20250324' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux
Pull hyperv updates from Wei Liu: - Add support for running as the root partition in Hyper-V (Microsoft Hypervisor) by exposing /dev/mshv (Nuno and various people) - Add support for CPU offlining in Hyper-V (Hamza Mahfooz) - Misc fixes and cleanups (Roman Kisel, Tianyu Lan, Wei Liu, Michael Kelley, Thorsten Blum) * tag 'hyperv-next-signed-20250324' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux: (24 commits) x86/hyperv: fix an indentation issue in mshyperv.h x86/hyperv: Add comments about hv_vpset and var size hypercall input args Drivers: hv: Introduce mshv_root module to expose /dev/mshv to VMMs hyperv: Add definitions for root partition driver to hv headers x86: hyperv: Add mshv_handler() irq handler and setup function Drivers: hv: Introduce per-cpu event ring tail Drivers: hv: Export some functions for use by root partition module acpi: numa: Export node_to_pxm() hyperv: Introduce hv_recommend_using_aeoi() arm64/hyperv: Add some missing functions to arm64 x86/mshyperv: Add support for extended Hyper-V features hyperv: Log hypercall status codes as strings x86/hyperv: Fix check of return value from snp_set_vmsa() x86/hyperv: Add VTL mode callback for restarting the system x86/hyperv: Add VTL mode emergency restart callback hyperv: Remove unused union and structs hyperv: Add CONFIG_MSHV_ROOT to gate root partition support hyperv: Change hv_root_partition into a function hyperv: Convert hypercall statuses to linux error codes drivers/hv: add CPU offlining support ...
2 parents dce3ab4 + 628cc04 commit a5b3d86

39 files changed

+6514
-228
lines changed

Documentation/userspace-api/ioctl/ioctl-number.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,8 @@ Code Seq# Include File Comments
370370
0xB7 all uapi/linux/remoteproc_cdev.h <mailto:linux-remoteproc@vger.kernel.org>
371371
0xB7 all uapi/linux/nsfs.h <mailto:Andrei Vagin <avagin@openvz.org>>
372372
0xB8 01-02 uapi/misc/mrvl_cn10k_dpi.h Marvell CN10K DPI driver
373+
0xB8 all uapi/linux/mshv.h Microsoft Hyper-V /dev/mshv driver
374+
<mailto:linux-hyperv@vger.kernel.org>
373375
0xC0 00-0F linux/usb/iowarrior.h
374376
0xCA 00-0F uapi/misc/cxl.h
375377
0xCA 10-2F uapi/misc/ocxl.h

arch/arm64/hyperv/hv_core.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,23 @@ u64 hv_do_fast_hypercall8(u16 code, u64 input)
5353
}
5454
EXPORT_SYMBOL_GPL(hv_do_fast_hypercall8);
5555

56+
/*
57+
* hv_do_fast_hypercall16 -- Invoke the specified hypercall
58+
* with arguments in registers instead of physical memory.
59+
* Avoids the overhead of virt_to_phys for simple hypercalls.
60+
*/
61+
u64 hv_do_fast_hypercall16(u16 code, u64 input1, u64 input2)
62+
{
63+
struct arm_smccc_res res;
64+
u64 control;
65+
66+
control = (u64)code | HV_HYPERCALL_FAST_BIT;
67+
68+
arm_smccc_1_1_hvc(HV_FUNC_ID, control, input1, input2, &res);
69+
return res.a0;
70+
}
71+
EXPORT_SYMBOL_GPL(hv_do_fast_hypercall16);
72+
5673
/*
5774
* Set a single VP register to a 64-bit value.
5875
*/

arch/arm64/hyperv/mshyperv.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ int hv_get_hypervisor_version(union hv_hypervisor_version_info *info)
2626

2727
return 0;
2828
}
29+
EXPORT_SYMBOL_GPL(hv_get_hypervisor_version);
2930

3031
static int __init hyperv_init(void)
3132
{
@@ -61,6 +62,8 @@ static int __init hyperv_init(void)
6162
ms_hyperv.features, ms_hyperv.priv_high, ms_hyperv.hints,
6263
ms_hyperv.misc_features);
6364

65+
hv_identify_partition_type();
66+
6467
ret = hv_common_init();
6568
if (ret)
6669
return ret;
@@ -72,6 +75,9 @@ static int __init hyperv_init(void)
7275
return ret;
7376
}
7477

78+
if (ms_hyperv.priv_high & HV_ACCESS_PARTITION_ID)
79+
hv_get_partition_id();
80+
7581
ms_hyperv_late_init();
7682

7783
hyperv_initialized = true;

arch/arm64/include/asm/mshyperv.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,19 @@ static inline u64 hv_get_msr(unsigned int reg)
4040
return hv_get_vpreg(reg);
4141
}
4242

43+
/*
44+
* Nested is not supported on arm64
45+
*/
46+
static inline void hv_set_non_nested_msr(unsigned int reg, u64 value)
47+
{
48+
hv_set_msr(reg, value);
49+
}
50+
51+
static inline u64 hv_get_non_nested_msr(unsigned int reg)
52+
{
53+
return hv_get_msr(reg);
54+
}
55+
4356
/* SMCCC hypercall parameters */
4457
#define HV_SMCCC_FUNC_NUMBER 1
4558
#define HV_FUNC_ID ARM_SMCCC_CALL_VAL( \

arch/x86/hyperv/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# SPDX-License-Identifier: GPL-2.0-only
22
obj-y := hv_init.o mmu.o nested.o irqdomain.o ivm.o
3-
obj-$(CONFIG_X86_64) += hv_apic.o hv_proc.o
3+
obj-$(CONFIG_X86_64) += hv_apic.o
44
obj-$(CONFIG_HYPERV_VTL_MODE) += hv_vtl.o
55

66
ifdef CONFIG_X86_64

arch/x86/hyperv/hv_apic.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,11 @@ static bool __send_ipi_mask_ex(const struct cpumask *mask, int vector,
145145
ipi_arg->vp_set.format = HV_GENERIC_SET_ALL;
146146
}
147147

148+
/*
149+
* For this hypercall, Hyper-V treats the valid_bank_mask field
150+
* of ipi_arg->vp_set as part of the fixed size input header.
151+
* So the variable input header size is equal to nr_bank.
152+
*/
148153
status = hv_do_rep_hypercall(HVCALL_SEND_IPI_EX, 0, nr_bank,
149154
ipi_arg, NULL);
150155

arch/x86/hyperv/hv_init.c

Lines changed: 6 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,6 @@
3434
#include <clocksource/hyperv_timer.h>
3535
#include <linux/highmem.h>
3636

37-
u64 hv_current_partition_id = ~0ull;
38-
EXPORT_SYMBOL_GPL(hv_current_partition_id);
39-
4037
void *hv_hypercall_pg;
4138
EXPORT_SYMBOL_GPL(hv_hypercall_pg);
4239

@@ -93,7 +90,7 @@ static int hv_cpu_init(unsigned int cpu)
9390
return 0;
9491

9592
hvp = &hv_vp_assist_page[cpu];
96-
if (hv_root_partition) {
93+
if (hv_root_partition()) {
9794
/*
9895
* For root partition we get the hypervisor provided VP assist
9996
* page, instead of allocating a new page.
@@ -245,7 +242,7 @@ static int hv_cpu_die(unsigned int cpu)
245242

246243
if (hv_vp_assist_page && hv_vp_assist_page[cpu]) {
247244
union hv_vp_assist_msr_contents msr = { 0 };
248-
if (hv_root_partition) {
245+
if (hv_root_partition()) {
249246
/*
250247
* For root partition the VP assist page is mapped to
251248
* hypervisor provided page, and thus we unmap the
@@ -320,7 +317,7 @@ static int hv_suspend(void)
320317
union hv_x64_msr_hypercall_contents hypercall_msr;
321318
int ret;
322319

323-
if (hv_root_partition)
320+
if (hv_root_partition())
324321
return -EPERM;
325322

326323
/*
@@ -393,24 +390,6 @@ static void __init hv_stimer_setup_percpu_clockev(void)
393390
old_setup_percpu_clockev();
394391
}
395392

396-
static void __init hv_get_partition_id(void)
397-
{
398-
struct hv_get_partition_id *output_page;
399-
u64 status;
400-
unsigned long flags;
401-
402-
local_irq_save(flags);
403-
output_page = *this_cpu_ptr(hyperv_pcpu_output_arg);
404-
status = hv_do_hypercall(HVCALL_GET_PARTITION_ID, NULL, output_page);
405-
if (!hv_result_success(status)) {
406-
/* No point in proceeding if this failed */
407-
pr_err("Failed to get partition ID: %lld\n", status);
408-
BUG();
409-
}
410-
hv_current_partition_id = output_page->partition_id;
411-
local_irq_restore(flags);
412-
}
413-
414393
#if IS_ENABLED(CONFIG_HYPERV_VTL_MODE)
415394
static u8 __init get_vtl(void)
416395
{
@@ -539,7 +518,7 @@ void __init hyperv_init(void)
539518
rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
540519
hypercall_msr.enable = 1;
541520

542-
if (hv_root_partition) {
521+
if (hv_root_partition()) {
543522
struct page *pg;
544523
void *src;
545524

@@ -605,17 +584,15 @@ void __init hyperv_init(void)
605584

606585
register_syscore_ops(&hv_syscore_ops);
607586

608-
if (cpuid_ebx(HYPERV_CPUID_FEATURES) & HV_ACCESS_PARTITION_ID)
587+
if (ms_hyperv.priv_high & HV_ACCESS_PARTITION_ID)
609588
hv_get_partition_id();
610589

611-
BUG_ON(hv_root_partition && hv_current_partition_id == ~0ull);
612-
613590
#ifdef CONFIG_PCI_MSI
614591
/*
615592
* If we're running as root, we want to create our own PCI MSI domain.
616593
* We can't set this in hv_pci_init because that would be too late.
617594
*/
618-
if (hv_root_partition)
595+
if (hv_root_partition())
619596
x86_init.irqs.create_pci_msi_domain = hv_create_pci_msi_domain;
620597
#endif
621598

arch/x86/hyperv/hv_vtl.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <asm/i8259.h>
1313
#include <asm/mshyperv.h>
1414
#include <asm/realmode.h>
15+
#include <asm/reboot.h>
1516
#include <../kernel/smpboot.h>
1617

1718
extern struct boot_params boot_params;
@@ -22,6 +23,36 @@ static bool __init hv_vtl_msi_ext_dest_id(void)
2223
return true;
2324
}
2425

26+
/*
27+
* The `native_machine_emergency_restart` function from `reboot.c` writes
28+
* to the physical address 0x472 to indicate the type of reboot for the
29+
* firmware. We cannot have that in VSM as the memory composition might
30+
* be more generic, and such write effectively corrupts the memory thus
31+
* making diagnostics harder at the very least.
32+
*/
33+
static void __noreturn hv_vtl_emergency_restart(void)
34+
{
35+
/*
36+
* Cause a triple fault and the immediate reset. Here the code does not run
37+
* on the top of any firmware, whereby cannot reach out to its services.
38+
* The inifinite loop is for the improbable case that the triple fault does
39+
* not work and have to preserve the state intact for debugging.
40+
*/
41+
for (;;) {
42+
idt_invalidate();
43+
__asm__ __volatile__("int3");
44+
}
45+
}
46+
47+
/*
48+
* The only way to restart in the VTL mode is to triple fault as the kernel runs
49+
* as firmware.
50+
*/
51+
static void __noreturn hv_vtl_restart(char __maybe_unused *cmd)
52+
{
53+
hv_vtl_emergency_restart();
54+
}
55+
2556
void __init hv_vtl_init_platform(void)
2657
{
2758
pr_info("Linux runs in Hyper-V Virtual Trust Level\n");
@@ -236,6 +267,9 @@ static int hv_vtl_wakeup_secondary_cpu(u32 apicid, unsigned long start_eip)
236267

237268
int __init hv_vtl_early_init(void)
238269
{
270+
machine_ops.emergency_restart = hv_vtl_emergency_restart;
271+
machine_ops.restart = hv_vtl_restart;
272+
239273
/*
240274
* `boot_cpu_has` returns the runtime feature support,
241275
* and here is the earliest it can be used.

arch/x86/hyperv/irqdomain.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ static int hv_map_interrupt(union hv_device_id device_id, bool level,
6464
local_irq_restore(flags);
6565

6666
if (!hv_result_success(status))
67-
pr_err("%s: hypercall failed, status %lld\n", __func__, status);
67+
hv_status_err(status, "\n");
6868

6969
return hv_result(status);
7070
}
@@ -224,7 +224,7 @@ static void hv_irq_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
224224
kfree(stored_entry);
225225

226226
if (status != HV_STATUS_SUCCESS) {
227-
pr_debug("%s: failed to unmap, status %lld", __func__, status);
227+
hv_status_debug(status, "failed to unmap\n");
228228
return;
229229
}
230230
}
@@ -273,7 +273,7 @@ static void hv_teardown_msi_irq(struct pci_dev *dev, struct irq_data *irqd)
273273
status = hv_unmap_msi_interrupt(dev, &old_entry);
274274

275275
if (status != HV_STATUS_SUCCESS)
276-
pr_err("%s: hypercall failed, status %lld\n", __func__, status);
276+
hv_status_err(status, "\n");
277277
}
278278

279279
static void hv_msi_free_irq(struct irq_domain *domain,

arch/x86/hyperv/ivm.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ int hv_snp_boot_ap(u32 cpu, unsigned long start_ip)
338338
vmsa->sev_features = sev_status >> 2;
339339

340340
ret = snp_set_vmsa(vmsa, true);
341-
if (!ret) {
341+
if (ret) {
342342
pr_err("RMPADJUST(%llx) failed: %llx\n", (u64)vmsa, ret);
343343
free_page((u64)vmsa);
344344
return ret;

0 commit comments

Comments
 (0)