c8c1a9440a
Without theses changes from sles11sp2 installation in a Xen HVM guest can not work in factory because the installer uses kexec to boot into second stage.. - Fix xen cpuid() inline asm to not clobber stack's red zone See xen-unstable changeset 24344:72f4e4cb7440 - Balloon up in a Xen PVonHVM guest before kexec (bnc#694863) - Update xen_present check for xenfs in pv_ops kernel (bnc#694863) - Change xen_present hv check (bnc#658413) OBS-URL: https://build.opensuse.org/request/show/125015 OBS-URL: https://build.opensuse.org/package/show/Kernel:kdump/kexec-tools?expand=0&rev=21
134 lines
3.5 KiB
Diff
134 lines
3.5 KiB
Diff
From: Olaf Hering <ohering@novell.com>
|
|
References: bnc#658413, bnc#694863
|
|
Subject: xen_present() should be named is_xen_pv() (includes also dom0).
|
|
|
|
A hvm guest is like physical hardware and should not need special handling.
|
|
Use code from xen-detect.c instead of stat() to distinguish hvm from pv because
|
|
xenfs in a pv_ops kernel generates /proc/xen/capabilities unconditionally.
|
|
|
|
---
|
|
kexec/crashdump-xen.c | 100 +++++++++++++++++++++++++++++++++++++++++++++++---
|
|
1 file changed, 95 insertions(+), 5 deletions(-)
|
|
|
|
Index: kexec-tools-2.0.2/kexec/crashdump-xen.c
|
|
===================================================================
|
|
--- kexec-tools-2.0.2.orig/kexec/crashdump-xen.c
|
|
+++ kexec-tools-2.0.2/kexec/crashdump-xen.c
|
|
@@ -10,6 +10,8 @@
|
|
#include <sys/stat.h>
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
+#include <setjmp.h>
|
|
+#include <signal.h>
|
|
#include "kexec.h"
|
|
#include "crashdump.h"
|
|
#include "kexec-syscall.h"
|
|
@@ -25,14 +27,102 @@ struct crash_note_info {
|
|
unsigned long length;
|
|
};
|
|
|
|
-int xen_phys_cpus = 0;
|
|
-struct crash_note_info *xen_phys_notes;
|
|
+static int xen_phys_cpus;
|
|
+static struct crash_note_info *xen_phys_notes;
|
|
|
|
-int xen_present(void)
|
|
+/* based on code from xen-detect.c */
|
|
+static int is_dom0;
|
|
+#if defined(__i386__) || defined(__x86_64__)
|
|
+static jmp_buf xen_sigill_jmp;
|
|
+void xen_sigill_handler(int sig)
|
|
+{
|
|
+ longjmp(xen_sigill_jmp, 1);
|
|
+}
|
|
+
|
|
+static void xen_cpuid(uint32_t idx, uint32_t *regs, int pv_context)
|
|
+{
|
|
+#ifdef __i386__
|
|
+ /* Use the stack to avoid reg constraint failures with some gcc flags */
|
|
+ asm volatile (
|
|
+ "push %%eax; push %%ebx; push %%ecx; push %%edx\n\t"
|
|
+ "test %1,%1 ; jz 1f ; ud2a ; .ascii \"xen\" ; 1: cpuid\n\t"
|
|
+ "mov %%eax,(%2); mov %%ebx,4(%2)\n\t"
|
|
+ "mov %%ecx,8(%2); mov %%edx,12(%2)\n\t"
|
|
+ "pop %%edx; pop %%ecx; pop %%ebx; pop %%eax\n\t"
|
|
+ : : "a" (idx), "c" (pv_context), "S" (regs) : "memory" );
|
|
+#else
|
|
+ asm volatile (
|
|
+ "test %5,%5 ; jz 1f ; ud2a ; .ascii \"xen\" ; 1: cpuid\n\t"
|
|
+ : "=a" (regs[0]), "=b" (regs[1]), "=c" (regs[2]), "=d" (regs[3])
|
|
+ : "0" (idx), "1" (pv_context), "2" (0) );
|
|
+#endif
|
|
+}
|
|
+
|
|
+static int check_for_xen(int pv_context)
|
|
{
|
|
- struct stat buf;
|
|
+ uint32_t regs[4];
|
|
+ char signature[13];
|
|
+ uint32_t base;
|
|
+
|
|
+ for (base = 0x40000000; base < 0x40010000; base += 0x100)
|
|
+ {
|
|
+ xen_cpuid(base, regs, pv_context);
|
|
+
|
|
+ *(uint32_t *)(signature + 0) = regs[1];
|
|
+ *(uint32_t *)(signature + 4) = regs[2];
|
|
+ *(uint32_t *)(signature + 8) = regs[3];
|
|
+ signature[12] = '\0';
|
|
+
|
|
+ if (strcmp("XenVMMXenVMM", signature) == 0 && regs[0] >= (base + 2))
|
|
+ goto found;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+
|
|
+found:
|
|
+ xen_cpuid(base + 1, regs, pv_context);
|
|
+ return regs[0];
|
|
+}
|
|
|
|
- return stat("/proc/xen", &buf) == 0;
|
|
+static int xen_detect_pv_guest(void)
|
|
+{
|
|
+ struct sigaction act, oldact;
|
|
+ int is_pv = -1;
|
|
+
|
|
+ if (setjmp(xen_sigill_jmp))
|
|
+ return is_pv;
|
|
+
|
|
+ memset(&act, 0, sizeof(act));
|
|
+ act.sa_handler = xen_sigill_handler;
|
|
+ sigemptyset (&act.sa_mask);
|
|
+ if (sigaction(SIGILL, &act, &oldact))
|
|
+ return is_pv;
|
|
+ if (check_for_xen(1))
|
|
+ is_pv = 1;
|
|
+ sigaction(SIGILL, &oldact, NULL);
|
|
+ return is_pv;
|
|
+}
|
|
+#else
|
|
+static int xen_detect_pv_guest(void)
|
|
+{
|
|
+ return 1;
|
|
+}
|
|
+#endif
|
|
+
|
|
+/*
|
|
+ * Return 1 if its a PV guest.
|
|
+ * This includes dom0, which is the only PV guest where kexec/kdump works.
|
|
+ * HVM guests have to be handled as native hardware.
|
|
+ */
|
|
+int xen_present(void)
|
|
+{
|
|
+ if (!is_dom0) {
|
|
+ if (access("/proc/xen", F_OK) == 0)
|
|
+ is_dom0 = xen_detect_pv_guest();
|
|
+ else
|
|
+ is_dom0 = -1;
|
|
+ }
|
|
+ return is_dom0 > 0;
|
|
}
|
|
|
|
unsigned long xen_architecture(struct crash_elf_info *elf_info)
|