Accepting request 125015 from home:olh:branches:Kernel:kdump

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
This commit is contained in:
Petr Tesařík 2012-06-19 12:31:17 +00:00 committed by Git OBS Bridge
parent 660ec8c794
commit c8c1a9440a
4 changed files with 381 additions and 0 deletions

View File

@ -0,0 +1,231 @@
Reference: bnc#694863
A PVonHVM guest can not kexec if balloon driver gave some memory back to hypervisor.
Disable ballooning before doing kexec.
---
kexec/crashdump-xen.c | 118 +++++++++++++++++++++++++++++++++++++++++++++++---
kexec/crashdump.h | 1
kexec/kexec.c | 6 ++
3 files changed, 119 insertions(+), 6 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
@@ -8,6 +8,7 @@
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/select.h>
#include <unistd.h>
#include <fcntl.h>
#include <setjmp.h>
@@ -30,9 +31,20 @@ struct crash_note_info {
static int xen_phys_cpus;
static struct crash_note_info *xen_phys_notes;
+#define XEN_MEM0_DIR "/sys/devices/system/xen_memory/xen_memory0"
+#define XEN_MEM0_TARGET XEN_MEM0_DIR "/target_kb"
+#define XEN_MEM0_LOW XEN_MEM0_DIR "/info/low_kb"
+#define XEN_MEM0_HIGH XEN_MEM0_DIR "/info/high_kb"
+
/* based on code from xen-detect.c */
static int is_dom0;
#if defined(__i386__) || defined(__x86_64__)
+enum {
+ XEN_PV = 1,
+ XEN_HVM = 2,
+ XEN_NONE = 3,
+};
+static int guest_type;
static jmp_buf xen_sigill_jmp;
void xen_sigill_handler(int sig)
{
@@ -81,29 +93,118 @@ found:
return regs[0];
}
-static int xen_detect_pv_guest(void)
+static void xen_detect_guest_type(void)
{
struct sigaction act, oldact;
- int is_pv = -1;
+
+ guest_type = XEN_NONE;
+ if (check_for_xen(0)) {
+ guest_type = XEN_HVM;
+ return;
+ }
if (setjmp(xen_sigill_jmp))
- return is_pv;
+ return;
memset(&act, 0, sizeof(act));
act.sa_handler = xen_sigill_handler;
sigemptyset (&act.sa_mask);
if (sigaction(SIGILL, &act, &oldact))
- return is_pv;
+ return;
if (check_for_xen(1))
- is_pv = 1;
+ guest_type = XEN_PV;
sigaction(SIGILL, &oldact, NULL);
- return is_pv;
+ return;
+}
+
+static int xen_detect_pv_guest(void)
+{
+ if (!guest_type)
+ xen_detect_guest_type();
+
+ return guest_type == XEN_PV ? 1 : -1;
}
+
+static int do_balloon_up(void)
+{
+ char line[123];
+ FILE *f;
+ int done = 0, seen_lo, seen_hi;
+ long long lo, hi, prev_lo = 0, prev_hi = 0;
+
+ if (!guest_type)
+ xen_detect_guest_type();
+
+ if (guest_type != XEN_HVM)
+ return 0;
+
+ /* Nothing to do if no balloon driver */
+ f = fopen(XEN_MEM0_TARGET, "w");
+ if (!f)
+ return 0;
+
+ /* Balloon up to maximum, the guest can not exceed its max_memkb */
+ printf("Ballooning up in PVonHVM guest.\n");
+ snprintf(line, sizeof(line), "%llu", -1LL);
+ fwrite(line, strlen(line), 1, f);
+ fclose(f);
+
+ do {
+ struct timeval timeout = {.tv_usec = 654321, };
+ seen_lo = seen_hi = 0;
+ lo = hi = -1;
+
+ /* Wait for balloon driver to reach maximum */
+ if (select(0, NULL, NULL, NULL, &timeout) < 0) {
+ perror("select");
+ break;
+ }
+
+ /* Check ballooned low mem */
+ f = fopen(XEN_MEM0_LOW, "r");
+ if (!f)
+ break;
+ if (fscanf(f, "%lld", &lo) == 1)
+ seen_lo = 1;
+ fclose(f);
+
+ /* Check ballooned high mem */
+ f = fopen(XEN_MEM0_HIGH, "r");
+ if (!f)
+ break;
+ if (fscanf(f, "%lld", &hi) == 1)
+ seen_hi = 1;
+ fclose(f);
+
+ /* Print progress if current values changed */
+ if ((seen_lo || seen_hi) && (hi || lo) && (lo != prev_lo || hi != prev_hi)) {
+ printf("h: %lld, l: %lld\n", hi, lo);
+ if (seen_lo && lo != prev_lo)
+ prev_lo = lo;
+ if (seen_hi && hi != prev_hi)
+ prev_hi = hi;
+ }
+
+ /* Exit loop if nothing is ballooned anymore */
+ if (seen_lo && seen_hi && hi == 0 && lo == 0)
+ done = 1;
+
+ } while (!done);
+
+ printf("%s.\n", done ? "Done" : "Not done");
+ return !done;
+}
+
#else
static int xen_detect_pv_guest(void)
{
return 1;
}
+
+static int do_balloon_up(void)
+{
+ return 0;
+}
#endif
/*
@@ -122,6 +223,11 @@ int xen_present(void)
return is_dom0 > 0;
}
+int xen_balloon_up(void)
+{
+ return do_balloon_up();
+}
+
unsigned long xen_architecture(struct crash_elf_info *elf_info)
{
unsigned long machine = elf_info->machine;
Index: kexec-tools-2.0.2/kexec/crashdump.h
===================================================================
--- kexec-tools-2.0.2.orig/kexec/crashdump.h
+++ kexec-tools-2.0.2/kexec/crashdump.h
@@ -50,6 +50,7 @@ unsigned long phys_to_virt(struct crash_
unsigned long paddr);
int xen_present(void);
+int xen_balloon_up(void);
unsigned long xen_architecture(struct crash_elf_info *elf_info);
int xen_get_nr_phys_cpus(void);
int xen_get_note(int cpu, uint64_t *addr, uint64_t *len);
Index: kexec-tools-2.0.2/kexec/kexec.c
===================================================================
--- kexec-tools-2.0.2.orig/kexec/kexec.c
+++ kexec-tools-2.0.2/kexec/kexec.c
@@ -1048,6 +1048,7 @@ int main(int argc, char *argv[])
int do_shutdown = 1;
int do_sync = 1;
int do_ifdown = 0;
+ int do_balloon = 0;
int do_unload = 0;
int do_reuse_initrd = 0;
void *entry = 0;
@@ -1082,6 +1083,7 @@ int main(int argc, char *argv[])
do_shutdown = 0;
do_sync = 1;
do_ifdown = 1;
+ do_balloon = 1;
do_exec = 1;
break;
case OPT_LOAD:
@@ -1100,6 +1102,7 @@ int main(int argc, char *argv[])
do_shutdown = 0;
do_sync = 1;
do_ifdown = 1;
+ do_balloon = 1;
do_exec = 1;
break;
case OPT_LOAD_JUMP_BACK_HELPER:
@@ -1222,6 +1225,9 @@ int main(int argc, char *argv[])
if ((result == 0) && do_ifdown) {
ifdown();
}
+ if ((result == 0) && do_balloon) {
+ result = xen_balloon_up();
+ }
if ((result == 0) && do_exec) {
result = my_exec();
}

View File

@ -0,0 +1,133 @@
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)

View File

@ -1,3 +1,16 @@
-------------------------------------------------------------------
Thu Jun 14 16:23:58 CEST 2012 - ohering@suse.de
- Fix xen cpuid() inline asm to not clobber stack's red zone
See xen-unstable changeset 24344:72f4e4cb7440
-------------------------------------------------------------------
Thu Jun 14 11:26:16 CEST 2012 - ohering@suse.de
- 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)
-------------------------------------------------------------------
Fri Apr 20 16:19:26 UTC 2012 - rschweikert@suse.com

View File

@ -37,6 +37,8 @@ Patch0: %{name}-no-vga-output.diff
Patch1: %{name}-xen-static.diff
Patch2: gcc-no-undefined-flag-fix.patch
Patch3: kexec-fix-strncat.patch
Patch4: kexec-tools-xen-present.diff
Patch5: kexec-tools-xen-balloon-up.patch
Url: ftp://kernel.org/pub/linux/utils/kernel/kexec/%{name}-%{version}.tar.bz2
BuildRoot: %{_tmppath}/%{name}-%{version}-build
#!BuildIgnore: fop
@ -74,6 +76,8 @@ Authors:
%patch1 -p1
%patch2 -p1
%patch3 -p1
%patch4 -p1
%patch5 -p1
%build
# disable as-needed