aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVitaly Kuznetsov <vkuznets@redhat.com>2018-03-20 10:02:08 -0400
committerRadim Krčmář <rkrcmar@redhat.com>2018-03-28 16:47:06 -0400
commita46d15cc1ae5af905afac2af4cc0c188c2eb59b0 (patch)
tree583e833789b6b1e72a6ecbad409227d9b42c1289
parentd4abc577bb03a3facc0f21cc1f2c6b27cd0f5d07 (diff)
x86/hyper-v: allocate and use Virtual Processor Assist Pages
Virtual Processor Assist Pages usage allows us to do optimized EOI processing for APIC, enable Enlightened VMCS support in KVM and more. struct hv_vp_assist_page is defined according to the Hyper-V TLFS v5.0b. Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com> Reviewed-by: Thomas Gleixner <tglx@linutronix.de> Acked-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Radim Krčmář <rkrcmar@redhat.com>
-rw-r--r--arch/x86/hyperv/hv_init.c43
-rw-r--r--arch/x86/include/asm/hyperv-tlfs.h13
-rw-r--r--arch/x86/include/asm/mshyperv.h13
3 files changed, 66 insertions, 3 deletions
diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c
index 4b82bc206929..cfecc2272f2d 100644
--- a/arch/x86/hyperv/hv_init.c
+++ b/arch/x86/hyperv/hv_init.c
@@ -88,11 +88,15 @@ EXPORT_SYMBOL_GPL(hyperv_cs);
88u32 *hv_vp_index; 88u32 *hv_vp_index;
89EXPORT_SYMBOL_GPL(hv_vp_index); 89EXPORT_SYMBOL_GPL(hv_vp_index);
90 90
91struct hv_vp_assist_page **hv_vp_assist_page;
92EXPORT_SYMBOL_GPL(hv_vp_assist_page);
93
91u32 hv_max_vp_index; 94u32 hv_max_vp_index;
92 95
93static int hv_cpu_init(unsigned int cpu) 96static int hv_cpu_init(unsigned int cpu)
94{ 97{
95 u64 msr_vp_index; 98 u64 msr_vp_index;
99 struct hv_vp_assist_page **hvp = &hv_vp_assist_page[smp_processor_id()];
96 100
97 hv_get_vp_index(msr_vp_index); 101 hv_get_vp_index(msr_vp_index);
98 102
@@ -101,6 +105,22 @@ static int hv_cpu_init(unsigned int cpu)
101 if (msr_vp_index > hv_max_vp_index) 105 if (msr_vp_index > hv_max_vp_index)
102 hv_max_vp_index = msr_vp_index; 106 hv_max_vp_index = msr_vp_index;
103 107
108 if (!hv_vp_assist_page)
109 return 0;
110
111 if (!*hvp)
112 *hvp = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL);
113
114 if (*hvp) {
115 u64 val;
116
117 val = vmalloc_to_pfn(*hvp);
118 val = (val << HV_X64_MSR_VP_ASSIST_PAGE_ADDRESS_SHIFT) |
119 HV_X64_MSR_VP_ASSIST_PAGE_ENABLE;
120
121 wrmsrl(HV_X64_MSR_VP_ASSIST_PAGE, val);
122 }
123
104 return 0; 124 return 0;
105} 125}
106 126
@@ -198,6 +218,9 @@ static int hv_cpu_die(unsigned int cpu)
198 struct hv_reenlightenment_control re_ctrl; 218 struct hv_reenlightenment_control re_ctrl;
199 unsigned int new_cpu; 219 unsigned int new_cpu;
200 220
221 if (hv_vp_assist_page && hv_vp_assist_page[cpu])
222 wrmsrl(HV_X64_MSR_VP_ASSIST_PAGE, 0);
223
201 if (hv_reenlightenment_cb == NULL) 224 if (hv_reenlightenment_cb == NULL)
202 return 0; 225 return 0;
203 226
@@ -224,6 +247,7 @@ void hyperv_init(void)
224{ 247{
225 u64 guest_id, required_msrs; 248 u64 guest_id, required_msrs;
226 union hv_x64_msr_hypercall_contents hypercall_msr; 249 union hv_x64_msr_hypercall_contents hypercall_msr;
250 int cpuhp;
227 251
228 if (x86_hyper_type != X86_HYPER_MS_HYPERV) 252 if (x86_hyper_type != X86_HYPER_MS_HYPERV)
229 return; 253 return;
@@ -241,9 +265,17 @@ void hyperv_init(void)
241 if (!hv_vp_index) 265 if (!hv_vp_index)
242 return; 266 return;
243 267
244 if (cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "x86/hyperv_init:online", 268 hv_vp_assist_page = kcalloc(num_possible_cpus(),
245 hv_cpu_init, hv_cpu_die) < 0) 269 sizeof(*hv_vp_assist_page), GFP_KERNEL);
270 if (!hv_vp_assist_page) {
271 ms_hyperv.hints &= ~HV_X64_ENLIGHTENED_VMCS_RECOMMENDED;
246 goto free_vp_index; 272 goto free_vp_index;
273 }
274
275 cpuhp = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "x86/hyperv_init:online",
276 hv_cpu_init, hv_cpu_die);
277 if (cpuhp < 0)
278 goto free_vp_assist_page;
247 279
248 /* 280 /*
249 * Setup the hypercall page and enable hypercalls. 281 * Setup the hypercall page and enable hypercalls.
@@ -256,7 +288,7 @@ void hyperv_init(void)
256 hv_hypercall_pg = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL_RX); 288 hv_hypercall_pg = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL_RX);
257 if (hv_hypercall_pg == NULL) { 289 if (hv_hypercall_pg == NULL) {
258 wrmsrl(HV_X64_MSR_GUEST_OS_ID, 0); 290 wrmsrl(HV_X64_MSR_GUEST_OS_ID, 0);
259 goto free_vp_index; 291 goto remove_cpuhp_state;
260 } 292 }
261 293
262 rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); 294 rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
@@ -304,6 +336,11 @@ register_msr_cs:
304 336
305 return; 337 return;
306 338
339remove_cpuhp_state:
340 cpuhp_remove_state(cpuhp);
341free_vp_assist_page:
342 kfree(hv_vp_assist_page);
343 hv_vp_assist_page = NULL;
307free_vp_index: 344free_vp_index:
308 kfree(hv_vp_index); 345 kfree(hv_vp_index);
309 hv_vp_index = NULL; 346 hv_vp_index = NULL;
diff --git a/arch/x86/include/asm/hyperv-tlfs.h b/arch/x86/include/asm/hyperv-tlfs.h
index a36ad742eac7..8d5a71702764 100644
--- a/arch/x86/include/asm/hyperv-tlfs.h
+++ b/arch/x86/include/asm/hyperv-tlfs.h
@@ -163,6 +163,9 @@
163/* Recommend using the newer ExProcessorMasks interface */ 163/* Recommend using the newer ExProcessorMasks interface */
164#define HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED (1 << 11) 164#define HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED (1 << 11)
165 165
166/* Recommend using enlightened VMCS */
167#define HV_X64_ENLIGHTENED_VMCS_RECOMMENDED (1 << 14)
168
166/* 169/*
167 * Crash notification flag. 170 * Crash notification flag.
168 */ 171 */
@@ -480,6 +483,16 @@ struct hv_timer_message_payload {
480 __u64 delivery_time; /* When the message was delivered */ 483 __u64 delivery_time; /* When the message was delivered */
481}; 484};
482 485
486/* Define virtual processor assist page structure. */
487struct hv_vp_assist_page {
488 __u32 apic_assist;
489 __u32 reserved;
490 __u64 vtl_control[2];
491 __u64 nested_enlightenments_control[2];
492 __u32 enlighten_vmentry;
493 __u64 current_nested_vmcs;
494};
495
483#define HV_STIMER_ENABLE (1ULL << 0) 496#define HV_STIMER_ENABLE (1ULL << 0)
484#define HV_STIMER_PERIODIC (1ULL << 1) 497#define HV_STIMER_PERIODIC (1ULL << 1)
485#define HV_STIMER_LAZY (1ULL << 2) 498#define HV_STIMER_LAZY (1ULL << 2)
diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h
index 38cfbe9a5794..3f162353f180 100644
--- a/arch/x86/include/asm/mshyperv.h
+++ b/arch/x86/include/asm/mshyperv.h
@@ -218,6 +218,15 @@ static inline u64 hv_do_rep_hypercall(u16 code, u16 rep_count, u16 varhead_size,
218 */ 218 */
219extern u32 *hv_vp_index; 219extern u32 *hv_vp_index;
220extern u32 hv_max_vp_index; 220extern u32 hv_max_vp_index;
221extern struct hv_vp_assist_page **hv_vp_assist_page;
222
223static inline struct hv_vp_assist_page *hv_get_vp_assist_page(unsigned int cpu)
224{
225 if (!hv_vp_assist_page)
226 return NULL;
227
228 return hv_vp_assist_page[cpu];
229}
221 230
222/** 231/**
223 * hv_cpu_number_to_vp_number() - Map CPU to VP. 232 * hv_cpu_number_to_vp_number() - Map CPU to VP.
@@ -254,6 +263,10 @@ static inline void hyperv_setup_mmu_ops(void) {}
254static inline void set_hv_tscchange_cb(void (*cb)(void)) {} 263static inline void set_hv_tscchange_cb(void (*cb)(void)) {}
255static inline void clear_hv_tscchange_cb(void) {} 264static inline void clear_hv_tscchange_cb(void) {}
256static inline void hyperv_stop_tsc_emulation(void) {}; 265static inline void hyperv_stop_tsc_emulation(void) {};
266static inline struct hv_vp_assist_page *hv_get_vp_assist_page(unsigned int cpu)
267{
268 return NULL;
269}
257#endif /* CONFIG_HYPERV */ 270#endif /* CONFIG_HYPERV */
258 271
259#ifdef CONFIG_HYPERV_TSCPAGE 272#ifdef CONFIG_HYPERV_TSCPAGE