diff mbox

[2/5] x86/hyper-v: allocate and use Virtual Processor Assist Pages

Message ID 20180131171341.21478-3-vkuznets@redhat.com (mailing list archive)
State New, archived
Headers show

Commit Message

Vitaly Kuznetsov Jan. 31, 2018, 5:13 p.m. UTC
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>
---
 arch/x86/hyperv/hv_init.c          | 33 +++++++++++++++++++++++++++++++++
 arch/x86/include/asm/mshyperv.h    | 10 ++++++++++
 arch/x86/include/uapi/asm/hyperv.h | 10 ++++++++++
 3 files changed, 53 insertions(+)

Comments

kernel test robot Feb. 3, 2018, 3:10 p.m. UTC | #1
Hi Vitaly,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on kvm/linux-next]
[also build test ERROR on next-20180202]
[cannot apply to tip/x86/core v4.15]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Vitaly-Kuznetsov/Enlightened-VMCS-support-for-KVM-on-Hyper-V/20180203-201607
base:   https://git.kernel.org/pub/scm/virt/kvm/kvm.git linux-next
config: x86_64-federa-25 (attached as .config)
compiler: gcc-7 (Debian 7.2.0-12) 7.2.1 20171025
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

Note: the linux-review/Vitaly-Kuznetsov/Enlightened-VMCS-support-for-KVM-on-Hyper-V/20180203-201607 HEAD cdf144fafed59cc093693dc168ba6cc21dc49d6c builds fine.
      It only hurts bisectibility.

All errors (new ones prefixed by >>):

   arch/x86/hyperv/hv_init.c: In function 'hyperv_init':
>> arch/x86/hyperv/hv_init.c:273:23: error: 'HV_X64_ENLIGHTENED_VMCS_RECOMMENDED' undeclared (first use in this function); did you mean 'HV_X64_APIC_ACCESS_RECOMMENDED'?
      ms_hyperv.hints &= ~HV_X64_ENLIGHTENED_VMCS_RECOMMENDED;
                          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                          HV_X64_APIC_ACCESS_RECOMMENDED
   arch/x86/hyperv/hv_init.c:273:23: note: each undeclared identifier is reported only once for each function it appears in

vim +273 arch/x86/hyperv/hv_init.c

   241	
   242	/*
   243	 * This function is to be invoked early in the boot sequence after the
   244	 * hypervisor has been detected.
   245	 *
   246	 * 1. Setup the hypercall page.
   247	 * 2. Register Hyper-V specific clocksource.
   248	 */
   249	void hyperv_init(void)
   250	{
   251		u64 guest_id, required_msrs;
   252		union hv_x64_msr_hypercall_contents hypercall_msr;
   253	
   254		if (x86_hyper_type != X86_HYPER_MS_HYPERV)
   255			return;
   256	
   257		/* Absolutely required MSRs */
   258		required_msrs = HV_X64_MSR_HYPERCALL_AVAILABLE |
   259			HV_X64_MSR_VP_INDEX_AVAILABLE;
   260	
   261		if ((ms_hyperv.features & required_msrs) != required_msrs)
   262			return;
   263	
   264		/* Allocate percpu VP index */
   265		hv_vp_index = kmalloc_array(num_possible_cpus(), sizeof(*hv_vp_index),
   266					    GFP_KERNEL);
   267		if (!hv_vp_index)
   268			return;
   269	
   270		hv_vp_assist_page = kcalloc(num_possible_cpus(),
   271					    sizeof(*hv_vp_assist_page), GFP_KERNEL);
   272		if (!hv_vp_assist_page) {
 > 273			ms_hyperv.hints &= ~HV_X64_ENLIGHTENED_VMCS_RECOMMENDED;
   274			return;
   275		}
   276	
   277		if (cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "x86/hyperv_init:online",
   278				      hv_cpu_init, hv_cpu_die) < 0)
   279			goto free_vp_index;
   280	
   281		/*
   282		 * Setup the hypercall page and enable hypercalls.
   283		 * 1. Register the guest ID
   284		 * 2. Enable the hypercall and register the hypercall page
   285		 */
   286		guest_id = generate_guest_id(0, LINUX_VERSION_CODE, 0);
   287		wrmsrl(HV_X64_MSR_GUEST_OS_ID, guest_id);
   288	
   289		hv_hypercall_pg  = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL_RX);
   290		if (hv_hypercall_pg == NULL) {
   291			wrmsrl(HV_X64_MSR_GUEST_OS_ID, 0);
   292			goto free_vp_index;
   293		}
   294	
   295		rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
   296		hypercall_msr.enable = 1;
   297		hypercall_msr.guest_physical_address = vmalloc_to_pfn(hv_hypercall_pg);
   298		wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
   299	
   300		hyper_alloc_mmu();
   301	
   302		/*
   303		 * Register Hyper-V specific clocksource.
   304		 */
   305	#ifdef CONFIG_HYPERV_TSCPAGE
   306		if (ms_hyperv.features & HV_X64_MSR_REFERENCE_TSC_AVAILABLE) {
   307			union hv_x64_msr_hypercall_contents tsc_msr;
   308	
   309			tsc_pg = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL);
   310			if (!tsc_pg)
   311				goto register_msr_cs;
   312	
   313			hyperv_cs = &hyperv_cs_tsc;
   314	
   315			rdmsrl(HV_X64_MSR_REFERENCE_TSC, tsc_msr.as_uint64);
   316	
   317			tsc_msr.enable = 1;
   318			tsc_msr.guest_physical_address = vmalloc_to_pfn(tsc_pg);
   319	
   320			wrmsrl(HV_X64_MSR_REFERENCE_TSC, tsc_msr.as_uint64);
   321	
   322			hyperv_cs_tsc.archdata.vclock_mode = VCLOCK_HVCLOCK;
   323	
   324			clocksource_register_hz(&hyperv_cs_tsc, NSEC_PER_SEC/100);
   325			return;
   326		}
   327	register_msr_cs:
   328	#endif
   329		/*
   330		 * For 32 bit guests just use the MSR based mechanism for reading
   331		 * the partition counter.
   332		 */
   333	
   334		hyperv_cs = &hyperv_cs_msr;
   335		if (ms_hyperv.features & HV_X64_MSR_TIME_REF_COUNT_AVAILABLE)
   336			clocksource_register_hz(&hyperv_cs_msr, NSEC_PER_SEC/100);
   337	
   338		return;
   339	
   340	free_vp_index:
   341		kfree(hv_vp_index);
   342		hv_vp_index = NULL;
   343	}
   344	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
diff mbox

Patch

diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c
index a3adece392f1..103b9c986e14 100644
--- a/arch/x86/hyperv/hv_init.c
+++ b/arch/x86/hyperv/hv_init.c
@@ -88,6 +88,9 @@  EXPORT_SYMBOL_GPL(hyperv_cs);
 u32 *hv_vp_index;
 EXPORT_SYMBOL_GPL(hv_vp_index);
 
+struct hv_vp_assist_page **hv_vp_assist_page;
+EXPORT_SYMBOL_GPL(hv_vp_assist_page);
+
 u32 hv_max_vp_index;
 
 static int hv_cpu_init(unsigned int cpu)
@@ -101,6 +104,23 @@  static int hv_cpu_init(unsigned int cpu)
 	if (msr_vp_index > hv_max_vp_index)
 		hv_max_vp_index = msr_vp_index;
 
+	if (!hv_vp_assist_page)
+		return 0;
+
+	if (!hv_vp_assist_page[smp_processor_id()])
+		hv_vp_assist_page[smp_processor_id()] =
+			__vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL);
+
+	if (hv_vp_assist_page[smp_processor_id()]) {
+		u64 val;
+
+		val = vmalloc_to_pfn(hv_vp_assist_page[smp_processor_id()]);
+		val = (val << HV_X64_MSR_VP_ASSIST_PAGE_ADDRESS_SHIFT) |
+			HV_X64_MSR_VP_ASSIST_PAGE_ENABLE;
+
+		wrmsrl(HV_X64_MSR_VP_ASSIST_PAGE, val);
+	}
+
 	return 0;
 }
 
@@ -198,6 +218,12 @@  static int hv_cpu_die(unsigned int cpu)
 	struct hv_reenlightenment_control re_ctrl;
 	unsigned int new_cpu;
 
+	if (hv_vp_assist_page && hv_vp_assist_page[cpu]) {
+		wrmsrl(HV_X64_MSR_VP_ASSIST_PAGE, 0);
+		vfree(hv_vp_assist_page[cpu]);
+		hv_vp_assist_page[cpu] = NULL;
+	}
+
 	if (hv_reenlightenment_cb == NULL)
 		return 0;
 
@@ -241,6 +267,13 @@  void hyperv_init(void)
 	if (!hv_vp_index)
 		return;
 
+	hv_vp_assist_page = kcalloc(num_possible_cpus(),
+				    sizeof(*hv_vp_assist_page), GFP_KERNEL);
+	if (!hv_vp_assist_page) {
+		ms_hyperv.hints &= ~HV_X64_ENLIGHTENED_VMCS_RECOMMENDED;
+		return;
+	}
+
 	if (cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "x86/hyperv_init:online",
 			      hv_cpu_init, hv_cpu_die) < 0)
 		goto free_vp_index;
diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h
index 1790002a2052..ba8dc52a2c9b 100644
--- a/arch/x86/include/asm/mshyperv.h
+++ b/arch/x86/include/asm/mshyperv.h
@@ -294,6 +294,12 @@  static inline u64 hv_do_rep_hypercall(u16 code, u16 rep_count, u16 varhead_size,
  */
 extern u32 *hv_vp_index;
 extern u32 hv_max_vp_index;
+extern struct hv_vp_assist_page **hv_vp_assist_page;
+
+static inline struct hv_vp_assist_page *hv_get_vp_assist_page(unsigned int cpu)
+{
+	return hv_vp_assist_page[cpu];
+}
 
 /**
  * hv_cpu_number_to_vp_number() - Map CPU to VP.
@@ -330,6 +336,10 @@  static inline void hyperv_setup_mmu_ops(void) {}
 static inline void set_hv_tscchange_cb(void (*cb)(void)) {}
 static inline void clear_hv_tscchange_cb(void) {}
 static inline void hyperv_stop_tsc_emulation(void) {};
+static inline struct hv_vp_assist_page *hv_get_vp_assist_page(unsigned int cpu)
+{
+	return NULL;
+}
 #endif /* CONFIG_HYPERV */
 
 #ifdef CONFIG_HYPERV_TSCPAGE
diff --git a/arch/x86/include/uapi/asm/hyperv.h b/arch/x86/include/uapi/asm/hyperv.h
index 929036b22b4c..ffaad7c93bcc 100644
--- a/arch/x86/include/uapi/asm/hyperv.h
+++ b/arch/x86/include/uapi/asm/hyperv.h
@@ -412,6 +412,16 @@  struct hv_timer_message_payload {
 	__u64 delivery_time;	/* When the message was delivered */
 };
 
+/* Define virtual processor assist page structure. */
+struct hv_vp_assist_page {
+	__u32 apic_assist;
+	__u32 reserved;
+	__u64 vtl_control[2];
+	__u64 nested_enlightenments_control[2];
+	__u32 enlighten_vmentry;
+	__u64 current_nested_vmcs;
+};
+
 #define HV_STIMER_ENABLE		(1ULL << 0)
 #define HV_STIMER_PERIODIC		(1ULL << 1)
 #define HV_STIMER_LAZY			(1ULL << 2)