浏览代码

Merge tag 'for-linus-4.3b-rc4-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip

Pull xen bug fixes from David Vrabel:

 - Fix VM save performance regression with x86 PV guests

 - Make kexec work in x86 PVHVM guests (if Xen has the soft-reset ABI)

 - Other minor fixes.

* tag 'for-linus-4.3b-rc4-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip:
  x86/xen/p2m: hint at the last populated P2M entry
  x86/xen: Do not clip xen_e820_map to xen_e820_map_entries when sanitizing map
  x86/xen: Support kexec/kdump in HVM guests by doing a soft reset
  xen/x86: Don't try to write syscall-related MSRs for PV guests
  xen: use correct type for HYPERVISOR_memory_op()
Linus Torvalds 9 年之前
父节点
当前提交
f6702681a0
共有 5 个文件被更改,包括 54 次插入5 次删除
  1. 2 2
      arch/x86/include/asm/xen/hypercall.h
  2. 24 0
      arch/x86/xen/enlighten.c
  3. 18 1
      arch/x86/xen/p2m.c
  4. 2 2
      arch/x86/xen/setup.c
  5. 8 0
      include/xen/interface/sched.h

+ 2 - 2
arch/x86/include/asm/xen/hypercall.h

@@ -336,10 +336,10 @@ HYPERVISOR_update_descriptor(u64 ma, u64 desc)
 	return _hypercall4(int, update_descriptor, ma, ma>>32, desc, desc>>32);
 	return _hypercall4(int, update_descriptor, ma, ma>>32, desc, desc>>32);
 }
 }
 
 
-static inline int
+static inline long
 HYPERVISOR_memory_op(unsigned int cmd, void *arg)
 HYPERVISOR_memory_op(unsigned int cmd, void *arg)
 {
 {
-	return _hypercall2(int, memory_op, cmd, arg);
+	return _hypercall2(long, memory_op, cmd, arg);
 }
 }
 
 
 static inline int
 static inline int

+ 24 - 0
arch/x86/xen/enlighten.c

@@ -33,6 +33,10 @@
 #include <linux/memblock.h>
 #include <linux/memblock.h>
 #include <linux/edd.h>
 #include <linux/edd.h>
 
 
+#ifdef CONFIG_KEXEC_CORE
+#include <linux/kexec.h>
+#endif
+
 #include <xen/xen.h>
 #include <xen/xen.h>
 #include <xen/events.h>
 #include <xen/events.h>
 #include <xen/interface/xen.h>
 #include <xen/interface/xen.h>
@@ -1077,6 +1081,7 @@ static int xen_write_msr_safe(unsigned int msr, unsigned low, unsigned high)
 		/* Fast syscall setup is all done in hypercalls, so
 		/* Fast syscall setup is all done in hypercalls, so
 		   these are all ignored.  Stub them out here to stop
 		   these are all ignored.  Stub them out here to stop
 		   Xen console noise. */
 		   Xen console noise. */
+		break;
 
 
 	default:
 	default:
 		if (!pmu_msr_write(msr, low, high, &ret))
 		if (!pmu_msr_write(msr, low, high, &ret))
@@ -1807,6 +1812,21 @@ static struct notifier_block xen_hvm_cpu_notifier = {
 	.notifier_call	= xen_hvm_cpu_notify,
 	.notifier_call	= xen_hvm_cpu_notify,
 };
 };
 
 
+#ifdef CONFIG_KEXEC_CORE
+static void xen_hvm_shutdown(void)
+{
+	native_machine_shutdown();
+	if (kexec_in_progress)
+		xen_reboot(SHUTDOWN_soft_reset);
+}
+
+static void xen_hvm_crash_shutdown(struct pt_regs *regs)
+{
+	native_machine_crash_shutdown(regs);
+	xen_reboot(SHUTDOWN_soft_reset);
+}
+#endif
+
 static void __init xen_hvm_guest_init(void)
 static void __init xen_hvm_guest_init(void)
 {
 {
 	if (xen_pv_domain())
 	if (xen_pv_domain())
@@ -1826,6 +1846,10 @@ static void __init xen_hvm_guest_init(void)
 	x86_init.irqs.intr_init = xen_init_IRQ;
 	x86_init.irqs.intr_init = xen_init_IRQ;
 	xen_hvm_init_time_ops();
 	xen_hvm_init_time_ops();
 	xen_hvm_init_mmu_ops();
 	xen_hvm_init_mmu_ops();
+#ifdef CONFIG_KEXEC_CORE
+	machine_ops.shutdown = xen_hvm_shutdown;
+	machine_ops.crash_shutdown = xen_hvm_crash_shutdown;
+#endif
 }
 }
 #endif
 #endif
 
 

+ 18 - 1
arch/x86/xen/p2m.c

@@ -112,6 +112,15 @@ static unsigned long *p2m_identity;
 static pte_t *p2m_missing_pte;
 static pte_t *p2m_missing_pte;
 static pte_t *p2m_identity_pte;
 static pte_t *p2m_identity_pte;
 
 
+/*
+ * Hint at last populated PFN.
+ *
+ * Used to set HYPERVISOR_shared_info->arch.max_pfn so the toolstack
+ * can avoid scanning the whole P2M (which may be sized to account for
+ * hotplugged memory).
+ */
+static unsigned long xen_p2m_last_pfn;
+
 static inline unsigned p2m_top_index(unsigned long pfn)
 static inline unsigned p2m_top_index(unsigned long pfn)
 {
 {
 	BUG_ON(pfn >= MAX_P2M_PFN);
 	BUG_ON(pfn >= MAX_P2M_PFN);
@@ -270,7 +279,7 @@ void xen_setup_mfn_list_list(void)
 	else
 	else
 		HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list =
 		HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list =
 			virt_to_mfn(p2m_top_mfn);
 			virt_to_mfn(p2m_top_mfn);
-	HYPERVISOR_shared_info->arch.max_pfn = xen_max_p2m_pfn;
+	HYPERVISOR_shared_info->arch.max_pfn = xen_p2m_last_pfn;
 	HYPERVISOR_shared_info->arch.p2m_generation = 0;
 	HYPERVISOR_shared_info->arch.p2m_generation = 0;
 	HYPERVISOR_shared_info->arch.p2m_vaddr = (unsigned long)xen_p2m_addr;
 	HYPERVISOR_shared_info->arch.p2m_vaddr = (unsigned long)xen_p2m_addr;
 	HYPERVISOR_shared_info->arch.p2m_cr3 =
 	HYPERVISOR_shared_info->arch.p2m_cr3 =
@@ -406,6 +415,8 @@ void __init xen_vmalloc_p2m_tree(void)
 	static struct vm_struct vm;
 	static struct vm_struct vm;
 	unsigned long p2m_limit;
 	unsigned long p2m_limit;
 
 
+	xen_p2m_last_pfn = xen_max_p2m_pfn;
+
 	p2m_limit = (phys_addr_t)P2M_LIMIT * 1024 * 1024 * 1024 / PAGE_SIZE;
 	p2m_limit = (phys_addr_t)P2M_LIMIT * 1024 * 1024 * 1024 / PAGE_SIZE;
 	vm.flags = VM_ALLOC;
 	vm.flags = VM_ALLOC;
 	vm.size = ALIGN(sizeof(unsigned long) * max(xen_max_p2m_pfn, p2m_limit),
 	vm.size = ALIGN(sizeof(unsigned long) * max(xen_max_p2m_pfn, p2m_limit),
@@ -608,6 +619,12 @@ static bool alloc_p2m(unsigned long pfn)
 			free_p2m_page(p2m);
 			free_p2m_page(p2m);
 	}
 	}
 
 
+	/* Expanded the p2m? */
+	if (pfn > xen_p2m_last_pfn) {
+		xen_p2m_last_pfn = pfn;
+		HYPERVISOR_shared_info->arch.max_pfn = xen_p2m_last_pfn;
+	}
+
 	return true;
 	return true;
 }
 }
 
 

+ 2 - 2
arch/x86/xen/setup.c

@@ -548,7 +548,7 @@ static unsigned long __init xen_get_max_pages(void)
 {
 {
 	unsigned long max_pages, limit;
 	unsigned long max_pages, limit;
 	domid_t domid = DOMID_SELF;
 	domid_t domid = DOMID_SELF;
-	int ret;
+	long ret;
 
 
 	limit = xen_get_pages_limit();
 	limit = xen_get_pages_limit();
 	max_pages = limit;
 	max_pages = limit;
@@ -798,7 +798,7 @@ char * __init xen_memory_setup(void)
 		xen_ignore_unusable();
 		xen_ignore_unusable();
 
 
 	/* Make sure the Xen-supplied memory map is well-ordered. */
 	/* Make sure the Xen-supplied memory map is well-ordered. */
-	sanitize_e820_map(xen_e820_map, xen_e820_map_entries,
+	sanitize_e820_map(xen_e820_map, ARRAY_SIZE(xen_e820_map),
 			  &xen_e820_map_entries);
 			  &xen_e820_map_entries);
 
 
 	max_pages = xen_get_max_pages();
 	max_pages = xen_get_max_pages();

+ 8 - 0
include/xen/interface/sched.h

@@ -107,5 +107,13 @@ struct sched_watchdog {
 #define SHUTDOWN_suspend    2  /* Clean up, save suspend info, kill.         */
 #define SHUTDOWN_suspend    2  /* Clean up, save suspend info, kill.         */
 #define SHUTDOWN_crash      3  /* Tell controller we've crashed.             */
 #define SHUTDOWN_crash      3  /* Tell controller we've crashed.             */
 #define SHUTDOWN_watchdog   4  /* Restart because watchdog time expired.     */
 #define SHUTDOWN_watchdog   4  /* Restart because watchdog time expired.     */
+/*
+ * Domain asked to perform 'soft reset' for it. The expected behavior is to
+ * reset internal Xen state for the domain returning it to the point where it
+ * was created but leaving the domain's memory contents and vCPU contexts
+ * intact. This will allow the domain to start over and set up all Xen specific
+ * interfaces again.
+ */
+#define SHUTDOWN_soft_reset 5
 
 
 #endif /* __XEN_PUBLIC_SCHED_H__ */
 #endif /* __XEN_PUBLIC_SCHED_H__ */