Skip to content

Commit 7fec185

Browse files
Jinank Jainliuw
authored andcommitted
Drivers: hv: Setup synic registers in case of nested root partition
Child partitions are free to allocate SynIC message and event page but in case of root partition it must use the pages allocated by Microsoft Hypervisor (MSHV). Base address for these pages can be found using synthetic MSRs exposed by MSHV. There is a slight difference in those MSRs for nested vs non-nested root partition. Signed-off-by: Jinank Jain <[email protected]> Reviewed-by: Nuno Das Neves <[email protected]> Reviewed-by: Michael Kelley <[email protected]> Link: https://lore.kernel.org/r/cb951fb1ad6814996fc54f4a255c5841a20a151f.1672639707.git.jinankjain@linux.microsoft.com Signed-off-by: Wei Liu <[email protected]>
1 parent c4bdf94 commit 7fec185

File tree

4 files changed

+93
-31
lines changed

4 files changed

+93
-31
lines changed

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,17 @@ enum hv_isolation_type {
227227
#define HV_REGISTER_SINT14 0x4000009E
228228
#define HV_REGISTER_SINT15 0x4000009F
229229

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+
230241
/*
231242
* Synthetic Timer MSRs. Four timers per vcpu.
232243
*/

arch/x86/include/asm/mshyperv.h

Lines changed: 6 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -196,30 +196,10 @@ static inline bool hv_is_synic_reg(unsigned int reg)
196196
return false;
197197
}
198198

199-
static inline u64 hv_get_register(unsigned int reg)
200-
{
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;
208-
}
209-
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-
}
199+
u64 hv_get_register(unsigned int reg);
200+
void hv_set_register(unsigned int reg, u64 value);
201+
u64 hv_get_non_nested_register(unsigned int reg);
202+
void hv_set_non_nested_register(unsigned int reg, u64 value);
223203

224204
#else /* CONFIG_HYPERV */
225205
static inline void hyperv_init(void) {}
@@ -239,6 +219,8 @@ static inline int hyperv_flush_guest_mapping_range(u64 as,
239219
}
240220
static inline void hv_set_register(unsigned int reg, u64 value) { }
241221
static inline u64 hv_get_register(unsigned int reg) { return 0; }
222+
static inline void hv_set_non_nested_register(unsigned int reg, u64 value) { }
223+
static inline u64 hv_get_non_nested_register(unsigned int reg) { return 0; }
242224
static inline int hv_set_mem_host_visibility(unsigned long addr, int numpages,
243225
bool visible)
244226
{

arch/x86/kernel/cpu/mshyperv.c

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,71 @@ bool hv_nested;
4242
struct ms_hyperv_info ms_hyperv;
4343

4444
#if IS_ENABLED(CONFIG_HYPERV)
45+
static inline unsigned int hv_get_nested_reg(unsigned int reg)
46+
{
47+
switch (reg) {
48+
case HV_REGISTER_SIMP:
49+
return HV_REGISTER_NESTED_SIMP;
50+
case HV_REGISTER_SIEFP:
51+
return HV_REGISTER_NESTED_SIEFP;
52+
case HV_REGISTER_SVERSION:
53+
return HV_REGISTER_NESTED_SVERSION;
54+
case HV_REGISTER_SCONTROL:
55+
return HV_REGISTER_NESTED_SCONTROL;
56+
case HV_REGISTER_SINT0:
57+
return HV_REGISTER_NESTED_SINT0;
58+
case HV_REGISTER_EOM:
59+
return HV_REGISTER_NESTED_EOM;
60+
default:
61+
return reg;
62+
}
63+
}
64+
65+
u64 hv_get_non_nested_register(unsigned int reg)
66+
{
67+
u64 value;
68+
69+
if (hv_is_synic_reg(reg) && hv_isolation_type_snp())
70+
hv_ghcb_msr_read(reg, &value);
71+
else
72+
rdmsrl(reg, value);
73+
return value;
74+
}
75+
EXPORT_SYMBOL_GPL(hv_get_non_nested_register);
76+
77+
void hv_set_non_nested_register(unsigned int reg, u64 value)
78+
{
79+
if (hv_is_synic_reg(reg) && hv_isolation_type_snp()) {
80+
hv_ghcb_msr_write(reg, value);
81+
82+
/* Write proxy bit via wrmsl instruction */
83+
if (reg >= HV_REGISTER_SINT0 &&
84+
reg <= HV_REGISTER_SINT15)
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+
45110
static void (*vmbus_handler)(void);
46111
static void (*hv_stimer0_handler)(void);
47112
static void (*hv_kexec_handler)(void);

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

0 commit comments

Comments
 (0)