Skip to content

Commit da46b58

Browse files
committed
Merge tag 'hyperv-next-signed-20230424' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux
Pull hyperv updates from Wei Liu: - PCI passthrough for Hyper-V confidential VMs (Michael Kelley) - Hyper-V VTL mode support (Saurabh Sengar) - Move panic report initialization code earlier (Long Li) - Various improvements and bug fixes (Dexuan Cui and Michael Kelley) * tag 'hyperv-next-signed-20230424' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux: (22 commits) PCI: hv: Replace retarget_msi_interrupt_params with hyperv_pcpu_input_arg Drivers: hv: move panic report code from vmbus to hv early init code x86/hyperv: VTL support for Hyper-V Drivers: hv: Kconfig: Add HYPERV_VTL_MODE x86/hyperv: Make hv_get_nmi_reason public x86/hyperv: Add VTL specific structs and hypercalls x86/init: Make get/set_rtc_noop() public x86/hyperv: Exclude lazy TLB mode CPUs from enlightened TLB flushes x86/hyperv: Add callback filter to cpumask_to_vpset() Drivers: hv: vmbus: Remove the per-CPU post_msg_page clocksource: hyper-v: make sure Invariant-TSC is used if it is available PCI: hv: Enable PCI pass-thru devices in Confidential VMs Drivers: hv: Don't remap addresses that are above shared_gpa_boundary hv_netvsc: Remove second mapping of send and recv buffers Drivers: hv: vmbus: Remove second way of mapping ring buffers Drivers: hv: vmbus: Remove second mapping of VMBus monitor pages swiotlb: Remove bounce buffer remapping for Hyper-V Driver: VMBus: Add Devicetree support dt-bindings: bus: Add Hyper-V VMBus Drivers: hv: vmbus: Convert acpi_device to more generic platform_device ...
2 parents 8ccd54f + a494aef commit da46b58

30 files changed

Lines changed: 1065 additions & 687 deletions

File tree

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2+
%YAML 1.2
3+
---
4+
$id: http://devicetree.org/schemas/bus/microsoft,vmbus.yaml#
5+
$schema: http://devicetree.org/meta-schemas/core.yaml#
6+
7+
title: Microsoft Hyper-V VMBus
8+
9+
maintainers:
10+
- Saurabh Sengar <ssengar@linux.microsoft.com>
11+
12+
description:
13+
VMBus is a software bus that implement the protocols for communication
14+
between the root or host OS and guest OSs (virtual machines).
15+
16+
properties:
17+
compatible:
18+
const: microsoft,vmbus
19+
20+
ranges: true
21+
22+
'#address-cells':
23+
const: 2
24+
25+
'#size-cells':
26+
const: 1
27+
28+
required:
29+
- compatible
30+
- ranges
31+
- '#address-cells'
32+
- '#size-cells'
33+
34+
additionalProperties: false
35+
36+
examples:
37+
- |
38+
soc {
39+
#address-cells = <2>;
40+
#size-cells = <1>;
41+
bus {
42+
compatible = "simple-bus";
43+
#address-cells = <2>;
44+
#size-cells = <1>;
45+
ranges;
46+
47+
vmbus@ff0000000 {
48+
compatible = "microsoft,vmbus";
49+
#address-cells = <2>;
50+
#size-cells = <1>;
51+
ranges = <0x0f 0xf0000000 0x0f 0xf0000000 0x10000000>;
52+
};
53+
};
54+
};

MAINTAINERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9588,6 +9588,7 @@ S: Supported
95889588
T: git git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux.git
95899589
F: Documentation/ABI/stable/sysfs-bus-vmbus
95909590
F: Documentation/ABI/testing/debugfs-hyperv
9591+
F: Documentation/devicetree/bindings/bus/microsoft,vmbus.yaml
95919592
F: Documentation/virt/hyperv
95929593
F: Documentation/networking/device_drivers/ethernet/microsoft/netvsc.rst
95939594
F: arch/arm64/hyperv

arch/x86/hyperv/Makefile

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

56
ifdef CONFIG_X86_64
67
obj-$(CONFIG_PARAVIRT_SPINLOCKS) += hv_spinlock.o

arch/x86/hyperv/hv_apic.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,11 @@ static void hv_apic_eoi_write(u32 reg, u32 val)
9696
wrmsr(HV_X64_MSR_EOI, val, 0);
9797
}
9898

99+
static bool cpu_is_self(int cpu)
100+
{
101+
return cpu == smp_processor_id();
102+
}
103+
99104
/*
100105
* IPI implementation on Hyper-V.
101106
*/
@@ -128,10 +133,9 @@ static bool __send_ipi_mask_ex(const struct cpumask *mask, int vector,
128133
*/
129134
if (!cpumask_equal(mask, cpu_present_mask) || exclude_self) {
130135
ipi_arg->vp_set.format = HV_GENERIC_SET_SPARSE_4K;
131-
if (exclude_self)
132-
nr_bank = cpumask_to_vpset_noself(&(ipi_arg->vp_set), mask);
133-
else
134-
nr_bank = cpumask_to_vpset(&(ipi_arg->vp_set), mask);
136+
137+
nr_bank = cpumask_to_vpset_skip(&(ipi_arg->vp_set), mask,
138+
exclude_self ? cpu_is_self : NULL);
135139

136140
/*
137141
* 'nr_bank <= 0' means some CPUs in cpumask can't be

arch/x86/hyperv/hv_init.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,10 @@ static int hyperv_init_ghcb(void)
6363
* memory boundary and map it here.
6464
*/
6565
rdmsrl(MSR_AMD64_SEV_ES_GHCB, ghcb_gpa);
66-
ghcb_va = memremap(ghcb_gpa, HV_HYP_PAGE_SIZE, MEMREMAP_WB);
66+
67+
/* Mask out vTOM bit. ioremap_cache() maps decrypted */
68+
ghcb_gpa &= ~ms_hyperv.shared_gpa_boundary;
69+
ghcb_va = (void *)ioremap_cache(ghcb_gpa, HV_HYP_PAGE_SIZE);
6770
if (!ghcb_va)
6871
return -ENOMEM;
6972

@@ -217,7 +220,7 @@ static int hv_cpu_die(unsigned int cpu)
217220
if (hv_ghcb_pg) {
218221
ghcb_va = (void **)this_cpu_ptr(hv_ghcb_pg);
219222
if (*ghcb_va)
220-
memunmap(*ghcb_va);
223+
iounmap(*ghcb_va);
221224
*ghcb_va = NULL;
222225
}
223226

arch/x86/hyperv/hv_vtl.c

Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* Copyright (c) 2023, Microsoft Corporation.
4+
*
5+
* Author:
6+
* Saurabh Sengar <ssengar@microsoft.com>
7+
*/
8+
9+
#include <asm/apic.h>
10+
#include <asm/boot.h>
11+
#include <asm/desc.h>
12+
#include <asm/i8259.h>
13+
#include <asm/mshyperv.h>
14+
#include <asm/realmode.h>
15+
16+
extern struct boot_params boot_params;
17+
static struct real_mode_header hv_vtl_real_mode_header;
18+
19+
void __init hv_vtl_init_platform(void)
20+
{
21+
pr_info("Linux runs in Hyper-V Virtual Trust Level\n");
22+
23+
x86_init.irqs.pre_vector_init = x86_init_noop;
24+
x86_init.timers.timer_init = x86_init_noop;
25+
26+
x86_platform.get_wallclock = get_rtc_noop;
27+
x86_platform.set_wallclock = set_rtc_noop;
28+
x86_platform.get_nmi_reason = hv_get_nmi_reason;
29+
30+
x86_platform.legacy.i8042 = X86_LEGACY_I8042_PLATFORM_ABSENT;
31+
x86_platform.legacy.rtc = 0;
32+
x86_platform.legacy.warm_reset = 0;
33+
x86_platform.legacy.reserve_bios_regions = 0;
34+
x86_platform.legacy.devices.pnpbios = 0;
35+
}
36+
37+
static inline u64 hv_vtl_system_desc_base(struct ldttss_desc *desc)
38+
{
39+
return ((u64)desc->base3 << 32) | ((u64)desc->base2 << 24) |
40+
(desc->base1 << 16) | desc->base0;
41+
}
42+
43+
static inline u32 hv_vtl_system_desc_limit(struct ldttss_desc *desc)
44+
{
45+
return ((u32)desc->limit1 << 16) | (u32)desc->limit0;
46+
}
47+
48+
typedef void (*secondary_startup_64_fn)(void*, void*);
49+
static void hv_vtl_ap_entry(void)
50+
{
51+
((secondary_startup_64_fn)secondary_startup_64)(&boot_params, &boot_params);
52+
}
53+
54+
static int hv_vtl_bringup_vcpu(u32 target_vp_index, u64 eip_ignored)
55+
{
56+
u64 status;
57+
int ret = 0;
58+
struct hv_enable_vp_vtl *input;
59+
unsigned long irq_flags;
60+
61+
struct desc_ptr gdt_ptr;
62+
struct desc_ptr idt_ptr;
63+
64+
struct ldttss_desc *tss;
65+
struct ldttss_desc *ldt;
66+
struct desc_struct *gdt;
67+
68+
u64 rsp = current->thread.sp;
69+
u64 rip = (u64)&hv_vtl_ap_entry;
70+
71+
native_store_gdt(&gdt_ptr);
72+
store_idt(&idt_ptr);
73+
74+
gdt = (struct desc_struct *)((void *)(gdt_ptr.address));
75+
tss = (struct ldttss_desc *)(gdt + GDT_ENTRY_TSS);
76+
ldt = (struct ldttss_desc *)(gdt + GDT_ENTRY_LDT);
77+
78+
local_irq_save(irq_flags);
79+
80+
input = *this_cpu_ptr(hyperv_pcpu_input_arg);
81+
memset(input, 0, sizeof(*input));
82+
83+
input->partition_id = HV_PARTITION_ID_SELF;
84+
input->vp_index = target_vp_index;
85+
input->target_vtl.target_vtl = HV_VTL_MGMT;
86+
87+
/*
88+
* The x86_64 Linux kernel follows the 16-bit -> 32-bit -> 64-bit
89+
* mode transition sequence after waking up an AP with SIPI whose
90+
* vector points to the 16-bit AP startup trampoline code. Here in
91+
* VTL2, we can't perform that sequence as the AP has to start in
92+
* the 64-bit mode.
93+
*
94+
* To make this happen, we tell the hypervisor to load a valid 64-bit
95+
* context (most of which is just magic numbers from the CPU manual)
96+
* so that AP jumps right to the 64-bit entry of the kernel, and the
97+
* control registers are loaded with values that let the AP fetch the
98+
* code and data and carry on with work it gets assigned.
99+
*/
100+
101+
input->vp_context.rip = rip;
102+
input->vp_context.rsp = rsp;
103+
input->vp_context.rflags = 0x0000000000000002;
104+
input->vp_context.efer = __rdmsr(MSR_EFER);
105+
input->vp_context.cr0 = native_read_cr0();
106+
input->vp_context.cr3 = __native_read_cr3();
107+
input->vp_context.cr4 = native_read_cr4();
108+
input->vp_context.msr_cr_pat = __rdmsr(MSR_IA32_CR_PAT);
109+
input->vp_context.idtr.limit = idt_ptr.size;
110+
input->vp_context.idtr.base = idt_ptr.address;
111+
input->vp_context.gdtr.limit = gdt_ptr.size;
112+
input->vp_context.gdtr.base = gdt_ptr.address;
113+
114+
/* Non-system desc (64bit), long, code, present */
115+
input->vp_context.cs.selector = __KERNEL_CS;
116+
input->vp_context.cs.base = 0;
117+
input->vp_context.cs.limit = 0xffffffff;
118+
input->vp_context.cs.attributes = 0xa09b;
119+
/* Non-system desc (64bit), data, present, granularity, default */
120+
input->vp_context.ss.selector = __KERNEL_DS;
121+
input->vp_context.ss.base = 0;
122+
input->vp_context.ss.limit = 0xffffffff;
123+
input->vp_context.ss.attributes = 0xc093;
124+
125+
/* System desc (128bit), present, LDT */
126+
input->vp_context.ldtr.selector = GDT_ENTRY_LDT * 8;
127+
input->vp_context.ldtr.base = hv_vtl_system_desc_base(ldt);
128+
input->vp_context.ldtr.limit = hv_vtl_system_desc_limit(ldt);
129+
input->vp_context.ldtr.attributes = 0x82;
130+
131+
/* System desc (128bit), present, TSS, 0x8b - busy, 0x89 -- default */
132+
input->vp_context.tr.selector = GDT_ENTRY_TSS * 8;
133+
input->vp_context.tr.base = hv_vtl_system_desc_base(tss);
134+
input->vp_context.tr.limit = hv_vtl_system_desc_limit(tss);
135+
input->vp_context.tr.attributes = 0x8b;
136+
137+
status = hv_do_hypercall(HVCALL_ENABLE_VP_VTL, input, NULL);
138+
139+
if (!hv_result_success(status) &&
140+
hv_result(status) != HV_STATUS_VTL_ALREADY_ENABLED) {
141+
pr_err("HVCALL_ENABLE_VP_VTL failed for VP : %d ! [Err: %#llx\n]",
142+
target_vp_index, status);
143+
ret = -EINVAL;
144+
goto free_lock;
145+
}
146+
147+
status = hv_do_hypercall(HVCALL_START_VP, input, NULL);
148+
149+
if (!hv_result_success(status)) {
150+
pr_err("HVCALL_START_VP failed for VP : %d ! [Err: %#llx]\n",
151+
target_vp_index, status);
152+
ret = -EINVAL;
153+
}
154+
155+
free_lock:
156+
local_irq_restore(irq_flags);
157+
158+
return ret;
159+
}
160+
161+
static int hv_vtl_apicid_to_vp_id(u32 apic_id)
162+
{
163+
u64 control;
164+
u64 status;
165+
unsigned long irq_flags;
166+
struct hv_get_vp_from_apic_id_in *input;
167+
u32 *output, ret;
168+
169+
local_irq_save(irq_flags);
170+
171+
input = *this_cpu_ptr(hyperv_pcpu_input_arg);
172+
memset(input, 0, sizeof(*input));
173+
input->partition_id = HV_PARTITION_ID_SELF;
174+
input->apic_ids[0] = apic_id;
175+
176+
output = (u32 *)input;
177+
178+
control = HV_HYPERCALL_REP_COMP_1 | HVCALL_GET_VP_ID_FROM_APIC_ID;
179+
status = hv_do_hypercall(control, input, output);
180+
ret = output[0];
181+
182+
local_irq_restore(irq_flags);
183+
184+
if (!hv_result_success(status)) {
185+
pr_err("failed to get vp id from apic id %d, status %#llx\n",
186+
apic_id, status);
187+
return -EINVAL;
188+
}
189+
190+
return ret;
191+
}
192+
193+
static int hv_vtl_wakeup_secondary_cpu(int apicid, unsigned long start_eip)
194+
{
195+
int vp_id;
196+
197+
pr_debug("Bringing up CPU with APIC ID %d in VTL2...\n", apicid);
198+
vp_id = hv_vtl_apicid_to_vp_id(apicid);
199+
200+
if (vp_id < 0) {
201+
pr_err("Couldn't find CPU with APIC ID %d\n", apicid);
202+
return -EINVAL;
203+
}
204+
if (vp_id > ms_hyperv.max_vp_index) {
205+
pr_err("Invalid CPU id %d for APIC ID %d\n", vp_id, apicid);
206+
return -EINVAL;
207+
}
208+
209+
return hv_vtl_bringup_vcpu(vp_id, start_eip);
210+
}
211+
212+
static int __init hv_vtl_early_init(void)
213+
{
214+
/*
215+
* `boot_cpu_has` returns the runtime feature support,
216+
* and here is the earliest it can be used.
217+
*/
218+
if (cpu_feature_enabled(X86_FEATURE_XSAVE))
219+
panic("XSAVE has to be disabled as it is not supported by this module.\n"
220+
"Please add 'noxsave' to the kernel command line.\n");
221+
222+
real_mode_header = &hv_vtl_real_mode_header;
223+
apic->wakeup_secondary_cpu_64 = hv_vtl_wakeup_secondary_cpu;
224+
225+
return 0;
226+
}
227+
early_initcall(hv_vtl_early_init);

arch/x86/hyperv/ivm.c

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -376,34 +376,6 @@ void __init hv_vtom_init(void)
376376

377377
#endif /* CONFIG_AMD_MEM_ENCRYPT */
378378

379-
/*
380-
* hv_map_memory - map memory to extra space in the AMD SEV-SNP Isolation VM.
381-
*/
382-
void *hv_map_memory(void *addr, unsigned long size)
383-
{
384-
unsigned long *pfns = kcalloc(size / PAGE_SIZE,
385-
sizeof(unsigned long), GFP_KERNEL);
386-
void *vaddr;
387-
int i;
388-
389-
if (!pfns)
390-
return NULL;
391-
392-
for (i = 0; i < size / PAGE_SIZE; i++)
393-
pfns[i] = vmalloc_to_pfn(addr + i * PAGE_SIZE) +
394-
(ms_hyperv.shared_gpa_boundary >> PAGE_SHIFT);
395-
396-
vaddr = vmap_pfn(pfns, size / PAGE_SIZE, pgprot_decrypted(PAGE_KERNEL));
397-
kfree(pfns);
398-
399-
return vaddr;
400-
}
401-
402-
void hv_unmap_memory(void *addr)
403-
{
404-
vunmap(addr);
405-
}
406-
407379
enum hv_isolation_type hv_get_isolation_type(void)
408380
{
409381
if (!(ms_hyperv.priv_high & HV_ISOLATION))

0 commit comments

Comments
 (0)