Hello community, here is the log from the commit of package kexec-tools for openSUSE:Factory checked in at 2012-06-25 12:33:31 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/kexec-tools (Old) and /work/SRC/openSUSE:Factory/.kexec-tools.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "kexec-tools", Maintainer is "to...@suse.com" Changes: -------- --- /work/SRC/openSUSE:Factory/kexec-tools/kexec-tools.changes 2012-05-21 07:27:58.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.kexec-tools.new/kexec-tools.changes 2012-06-25 12:33:32.000000000 +0200 @@ -1,0 +2,13 @@ +Thu Jun 14 16:23:58 CEST 2012 - oher...@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 - oher...@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) + +------------------------------------------------------------------- New: ---- kexec-tools-xen-balloon-up.patch kexec-tools-xen-present.diff ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ kexec-tools.spec ++++++ --- /var/tmp/diff_new_pack.zmr6iC/_old 2012-06-25 12:33:34.000000000 +0200 +++ /var/tmp/diff_new_pack.zmr6iC/_new 2012-06-25 12:33:34.000000000 +0200 @@ -37,6 +37,8 @@ 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 @@ %patch1 -p1 %patch2 -p1 %patch3 -p1 +%patch4 -p1 +%patch5 -p1 %build # disable as-needed ++++++ kexec-tools-xen-balloon-up.patch ++++++ 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(); } ++++++ kexec-tools-xen-present.diff ++++++ From: Olaf Hering <oher...@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) -- To unsubscribe, e-mail: opensuse-commit+unsubscr...@opensuse.org For additional commands, e-mail: opensuse-commit+h...@opensuse.org