Skip to content

Commit b8878e5

Browse files
committed
Merge tag 'hyperv-next-signed-20230220' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux
Pull hyperv updates from Wei Liu: - allow Linux to run as the nested root partition for Microsoft Hypervisor (Jinank Jain and Nuno Das Neves) - clean up the return type of callback functions (Dawei Li) * tag 'hyperv-next-signed-20230220' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux: x86/hyperv: Fix hv_get/set_register for nested bringup Drivers: hv: Make remove callback of hyperv driver void returned Drivers: hv: Enable vmbus driver for nested root partition x86/hyperv: Add an interface to do nested hypercalls Drivers: hv: Setup synic registers in case of nested root partition x86/hyperv: Add support for detecting nested hypervisor
2 parents 8bf1a52 + b14033a commit b8878e5

File tree

20 files changed

+172
-79
lines changed

20 files changed

+172
-79
lines changed

arch/x86/include/asm/hyperv-tlfs.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,9 @@
116116
/* Recommend using the newer ExProcessorMasks interface */
117117
#define HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED BIT(11)
118118

119+
/* Indicates that the hypervisor is nested within a Hyper-V partition. */
120+
#define HV_X64_HYPERV_NESTED BIT(12)
121+
119122
/* Recommend using enlightened VMCS */
120123
#define HV_X64_ENLIGHTENED_VMCS_RECOMMENDED BIT(14)
121124

@@ -224,6 +227,17 @@ enum hv_isolation_type {
224227
#define HV_REGISTER_SINT14 0x4000009E
225228
#define HV_REGISTER_SINT15 0x4000009F
226229

230+
/*
231+
* Define synthetic interrupt controller model specific registers for
232+
* nested hypervisor.
233+
*/
234+
#define HV_REGISTER_NESTED_SCONTROL 0x40001080
235+
#define HV_REGISTER_NESTED_SVERSION 0x40001081
236+
#define HV_REGISTER_NESTED_SIEFP 0x40001082
237+
#define HV_REGISTER_NESTED_SIMP 0x40001083
238+
#define HV_REGISTER_NESTED_EOM 0x40001084
239+
#define HV_REGISTER_NESTED_SINT0 0x40001090
240+
227241
/*
228242
* Synthetic Timer MSRs. Four timers per vcpu.
229243
*/
@@ -368,7 +382,8 @@ struct hv_nested_enlightenments_control {
368382
__u32 reserved:31;
369383
} features;
370384
struct {
371-
__u32 reserved;
385+
__u32 inter_partition_comm:1;
386+
__u32 reserved:31;
372387
} hypercallControls;
373388
} __packed;
374389

arch/x86/include/asm/mshyperv.h

Lines changed: 49 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,16 @@ static inline u64 hv_do_hypercall(u64 control, void *input, void *output)
7272
return hv_status;
7373
}
7474

75+
/* Hypercall to the L0 hypervisor */
76+
static inline u64 hv_do_nested_hypercall(u64 control, void *input, void *output)
77+
{
78+
return hv_do_hypercall(control | HV_HYPERCALL_NESTED, input, output);
79+
}
80+
7581
/* Fast hypercall with 8 bytes of input and no output */
76-
static inline u64 hv_do_fast_hypercall8(u16 code, u64 input1)
82+
static inline u64 _hv_do_fast_hypercall8(u64 control, u64 input1)
7783
{
78-
u64 hv_status, control = (u64)code | HV_HYPERCALL_FAST_BIT;
84+
u64 hv_status;
7985

8086
#ifdef CONFIG_X86_64
8187
{
@@ -103,10 +109,24 @@ static inline u64 hv_do_fast_hypercall8(u16 code, u64 input1)
103109
return hv_status;
104110
}
105111

112+
static inline u64 hv_do_fast_hypercall8(u16 code, u64 input1)
113+
{
114+
u64 control = (u64)code | HV_HYPERCALL_FAST_BIT;
115+
116+
return _hv_do_fast_hypercall8(control, input1);
117+
}
118+
119+
static inline u64 hv_do_fast_nested_hypercall8(u16 code, u64 input1)
120+
{
121+
u64 control = (u64)code | HV_HYPERCALL_FAST_BIT | HV_HYPERCALL_NESTED;
122+
123+
return _hv_do_fast_hypercall8(control, input1);
124+
}
125+
106126
/* Fast hypercall with 16 bytes of input */
107-
static inline u64 hv_do_fast_hypercall16(u16 code, u64 input1, u64 input2)
127+
static inline u64 _hv_do_fast_hypercall16(u64 control, u64 input1, u64 input2)
108128
{
109-
u64 hv_status, control = (u64)code | HV_HYPERCALL_FAST_BIT;
129+
u64 hv_status;
110130

111131
#ifdef CONFIG_X86_64
112132
{
@@ -137,6 +157,20 @@ static inline u64 hv_do_fast_hypercall16(u16 code, u64 input1, u64 input2)
137157
return hv_status;
138158
}
139159

160+
static inline u64 hv_do_fast_hypercall16(u16 code, u64 input1, u64 input2)
161+
{
162+
u64 control = (u64)code | HV_HYPERCALL_FAST_BIT;
163+
164+
return _hv_do_fast_hypercall16(control, input1, input2);
165+
}
166+
167+
static inline u64 hv_do_fast_nested_hypercall16(u16 code, u64 input1, u64 input2)
168+
{
169+
u64 control = (u64)code | HV_HYPERCALL_FAST_BIT | HV_HYPERCALL_NESTED;
170+
171+
return _hv_do_fast_hypercall16(control, input1, input2);
172+
}
173+
140174
extern struct hv_vp_assist_page **hv_vp_assist_page;
141175

142176
static inline struct hv_vp_assist_page *hv_get_vp_assist_page(unsigned int cpu)
@@ -190,36 +224,20 @@ extern bool hv_isolation_type_snp(void);
190224

191225
static inline bool hv_is_synic_reg(unsigned int reg)
192226
{
193-
if ((reg >= HV_REGISTER_SCONTROL) &&
194-
(reg <= HV_REGISTER_SINT15))
195-
return true;
196-
return false;
227+
return (reg >= HV_REGISTER_SCONTROL) &&
228+
(reg <= HV_REGISTER_SINT15);
197229
}
198230

199-
static inline u64 hv_get_register(unsigned int reg)
231+
static inline bool hv_is_sint_reg(unsigned int reg)
200232
{
201-
u64 value;
202-
203-
if (hv_is_synic_reg(reg) && hv_isolation_type_snp())
204-
hv_ghcb_msr_read(reg, &value);
205-
else
206-
rdmsrl(reg, value);
207-
return value;
233+
return (reg >= HV_REGISTER_SINT0) &&
234+
(reg <= HV_REGISTER_SINT15);
208235
}
209236

210-
static inline void hv_set_register(unsigned int reg, u64 value)
211-
{
212-
if (hv_is_synic_reg(reg) && hv_isolation_type_snp()) {
213-
hv_ghcb_msr_write(reg, value);
214-
215-
/* Write proxy bit via wrmsl instruction */
216-
if (reg >= HV_REGISTER_SINT0 &&
217-
reg <= HV_REGISTER_SINT15)
218-
wrmsrl(reg, value | 1 << 20);
219-
} else {
220-
wrmsrl(reg, value);
221-
}
222-
}
237+
u64 hv_get_register(unsigned int reg);
238+
void hv_set_register(unsigned int reg, u64 value);
239+
u64 hv_get_non_nested_register(unsigned int reg);
240+
void hv_set_non_nested_register(unsigned int reg, u64 value);
223241

224242
#else /* CONFIG_HYPERV */
225243
static inline void hyperv_init(void) {}
@@ -239,6 +257,8 @@ static inline int hyperv_flush_guest_mapping_range(u64 as,
239257
}
240258
static inline void hv_set_register(unsigned int reg, u64 value) { }
241259
static inline u64 hv_get_register(unsigned int reg) { return 0; }
260+
static inline void hv_set_non_nested_register(unsigned int reg, u64 value) { }
261+
static inline u64 hv_get_non_nested_register(unsigned int reg) { return 0; }
242262
static inline int hv_set_mem_host_visibility(unsigned long addr, int numpages,
243263
bool visible)
244264
{

arch/x86/kernel/cpu/mshyperv.c

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,76 @@
3737

3838
/* Is Linux running as the root partition? */
3939
bool hv_root_partition;
40+
/* Is Linux running on nested Microsoft Hypervisor */
41+
bool hv_nested;
4042
struct ms_hyperv_info ms_hyperv;
4143

4244
#if IS_ENABLED(CONFIG_HYPERV)
45+
static inline unsigned int hv_get_nested_reg(unsigned int reg)
46+
{
47+
if (hv_is_sint_reg(reg))
48+
return reg - HV_REGISTER_SINT0 + HV_REGISTER_NESTED_SINT0;
49+
50+
switch (reg) {
51+
case HV_REGISTER_SIMP:
52+
return HV_REGISTER_NESTED_SIMP;
53+
case HV_REGISTER_SIEFP:
54+
return HV_REGISTER_NESTED_SIEFP;
55+
case HV_REGISTER_SVERSION:
56+
return HV_REGISTER_NESTED_SVERSION;
57+
case HV_REGISTER_SCONTROL:
58+
return HV_REGISTER_NESTED_SCONTROL;
59+
case HV_REGISTER_EOM:
60+
return HV_REGISTER_NESTED_EOM;
61+
default:
62+
return reg;
63+
}
64+
}
65+
66+
u64 hv_get_non_nested_register(unsigned int reg)
67+
{
68+
u64 value;
69+
70+
if (hv_is_synic_reg(reg) && hv_isolation_type_snp())
71+
hv_ghcb_msr_read(reg, &value);
72+
else
73+
rdmsrl(reg, value);
74+
return value;
75+
}
76+
EXPORT_SYMBOL_GPL(hv_get_non_nested_register);
77+
78+
void hv_set_non_nested_register(unsigned int reg, u64 value)
79+
{
80+
if (hv_is_synic_reg(reg) && hv_isolation_type_snp()) {
81+
hv_ghcb_msr_write(reg, value);
82+
83+
/* Write proxy bit via wrmsl instruction */
84+
if (hv_is_sint_reg(reg))
85+
wrmsrl(reg, value | 1 << 20);
86+
} else {
87+
wrmsrl(reg, value);
88+
}
89+
}
90+
EXPORT_SYMBOL_GPL(hv_set_non_nested_register);
91+
92+
u64 hv_get_register(unsigned int reg)
93+
{
94+
if (hv_nested)
95+
reg = hv_get_nested_reg(reg);
96+
97+
return hv_get_non_nested_register(reg);
98+
}
99+
EXPORT_SYMBOL_GPL(hv_get_register);
100+
101+
void hv_set_register(unsigned int reg, u64 value)
102+
{
103+
if (hv_nested)
104+
reg = hv_get_nested_reg(reg);
105+
106+
hv_set_non_nested_register(reg, value);
107+
}
108+
EXPORT_SYMBOL_GPL(hv_set_register);
109+
43110
static void (*vmbus_handler)(void);
44111
static void (*hv_stimer0_handler)(void);
45112
static void (*hv_kexec_handler)(void);
@@ -301,6 +368,11 @@ static void __init ms_hyperv_init_platform(void)
301368
pr_info("Hyper-V: running as root partition\n");
302369
}
303370

371+
if (ms_hyperv.hints & HV_X64_HYPERV_NESTED) {
372+
hv_nested = true;
373+
pr_info("Hyper-V: running on a nested hypervisor\n");
374+
}
375+
304376
/*
305377
* Extract host information.
306378
*/

drivers/gpu/drm/hyperv/hyperv_drm_drv.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ static int hyperv_vmbus_probe(struct hv_device *hdev,
165165
return ret;
166166
}
167167

168-
static int hyperv_vmbus_remove(struct hv_device *hdev)
168+
static void hyperv_vmbus_remove(struct hv_device *hdev)
169169
{
170170
struct drm_device *dev = hv_get_drvdata(hdev);
171171
struct hyperv_drm_device *hv = to_hv(dev);
@@ -176,8 +176,6 @@ static int hyperv_vmbus_remove(struct hv_device *hdev)
176176
hv_set_drvdata(hdev, NULL);
177177

178178
vmbus_free_mmio(hv->mem->start, hv->fb_size);
179-
180-
return 0;
181179
}
182180

183181
static int hyperv_vmbus_suspend(struct hv_device *hdev)

drivers/hid/hid-hyperv.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -524,7 +524,7 @@ static int mousevsc_probe(struct hv_device *device,
524524
}
525525

526526

527-
static int mousevsc_remove(struct hv_device *dev)
527+
static void mousevsc_remove(struct hv_device *dev)
528528
{
529529
struct mousevsc_dev *input_dev = hv_get_drvdata(dev);
530530

@@ -533,8 +533,6 @@ static int mousevsc_remove(struct hv_device *dev)
533533
hid_hw_stop(input_dev->hid_device);
534534
hid_destroy_device(input_dev->hid_device);
535535
mousevsc_free_device(input_dev);
536-
537-
return 0;
538536
}
539537

540538
static int mousevsc_suspend(struct hv_device *dev)

drivers/hv/hv.c

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ int hv_synic_alloc(void)
147147
* Synic message and event pages are allocated by paravisor.
148148
* Skip these pages allocation here.
149149
*/
150-
if (!hv_isolation_type_snp()) {
150+
if (!hv_isolation_type_snp() && !hv_root_partition) {
151151
hv_cpu->synic_message_page =
152152
(void *)get_zeroed_page(GFP_ATOMIC);
153153
if (hv_cpu->synic_message_page == NULL) {
@@ -216,7 +216,7 @@ void hv_synic_enable_regs(unsigned int cpu)
216216
simp.as_uint64 = hv_get_register(HV_REGISTER_SIMP);
217217
simp.simp_enabled = 1;
218218

219-
if (hv_isolation_type_snp()) {
219+
if (hv_isolation_type_snp() || hv_root_partition) {
220220
hv_cpu->synic_message_page
221221
= memremap(simp.base_simp_gpa << HV_HYP_PAGE_SHIFT,
222222
HV_HYP_PAGE_SIZE, MEMREMAP_WB);
@@ -233,7 +233,7 @@ void hv_synic_enable_regs(unsigned int cpu)
233233
siefp.as_uint64 = hv_get_register(HV_REGISTER_SIEFP);
234234
siefp.siefp_enabled = 1;
235235

236-
if (hv_isolation_type_snp()) {
236+
if (hv_isolation_type_snp() || hv_root_partition) {
237237
hv_cpu->synic_event_page =
238238
memremap(siefp.base_siefp_gpa << HV_HYP_PAGE_SHIFT,
239239
HV_HYP_PAGE_SIZE, MEMREMAP_WB);
@@ -315,20 +315,24 @@ void hv_synic_disable_regs(unsigned int cpu)
315315
* addresses.
316316
*/
317317
simp.simp_enabled = 0;
318-
if (hv_isolation_type_snp())
318+
if (hv_isolation_type_snp() || hv_root_partition) {
319319
memunmap(hv_cpu->synic_message_page);
320-
else
320+
hv_cpu->synic_message_page = NULL;
321+
} else {
321322
simp.base_simp_gpa = 0;
323+
}
322324

323325
hv_set_register(HV_REGISTER_SIMP, simp.as_uint64);
324326

325327
siefp.as_uint64 = hv_get_register(HV_REGISTER_SIEFP);
326328
siefp.siefp_enabled = 0;
327329

328-
if (hv_isolation_type_snp())
330+
if (hv_isolation_type_snp() || hv_root_partition) {
329331
memunmap(hv_cpu->synic_event_page);
330-
else
332+
hv_cpu->synic_event_page = NULL;
333+
} else {
331334
siefp.base_siefp_gpa = 0;
335+
}
332336

333337
hv_set_register(HV_REGISTER_SIEFP, siefp.as_uint64);
334338

drivers/hv/hv_balloon.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2042,7 +2042,7 @@ static int balloon_probe(struct hv_device *dev,
20422042
return ret;
20432043
}
20442044

2045-
static int balloon_remove(struct hv_device *dev)
2045+
static void balloon_remove(struct hv_device *dev)
20462046
{
20472047
struct hv_dynmem_device *dm = hv_get_drvdata(dev);
20482048
struct hv_hotadd_state *has, *tmp;
@@ -2083,8 +2083,6 @@ static int balloon_remove(struct hv_device *dev)
20832083
kfree(has);
20842084
}
20852085
spin_unlock_irqrestore(&dm_device.ha_lock, flags);
2086-
2087-
return 0;
20882086
}
20892087

20902088
static int balloon_suspend(struct hv_device *hv_dev)

drivers/hv/hv_common.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,20 @@
2525
#include <asm/mshyperv.h>
2626

2727
/*
28-
* hv_root_partition and ms_hyperv are defined here with other Hyper-V
29-
* specific globals so they are shared across all architectures and are
28+
* hv_root_partition, ms_hyperv and hv_nested are defined here with other
29+
* Hyper-V specific globals so they are shared across all architectures and are
3030
* built only when CONFIG_HYPERV is defined. But on x86,
3131
* ms_hyperv_init_platform() is built even when CONFIG_HYPERV is not
32-
* defined, and it uses these two variables. So mark them as __weak
32+
* defined, and it uses these three variables. So mark them as __weak
3333
* here, allowing for an overriding definition in the module containing
3434
* ms_hyperv_init_platform().
3535
*/
3636
bool __weak hv_root_partition;
3737
EXPORT_SYMBOL_GPL(hv_root_partition);
3838

39+
bool __weak hv_nested;
40+
EXPORT_SYMBOL_GPL(hv_nested);
41+
3942
struct ms_hyperv_info __weak ms_hyperv;
4043
EXPORT_SYMBOL_GPL(ms_hyperv);
4144

0 commit comments

Comments
 (0)