diff options
author | Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | 2012-10-10 13:23:36 -0400 |
---|---|---|
committer | Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | 2012-10-12 08:49:21 -0400 |
commit | cb6b6df111e46b9d0f79eb971575fd50555f43f4 (patch) | |
tree | 7587983a02f37b0a70b0e930344b497e607b0581 /drivers | |
parent | 1a7bbda5b1ab0e02622761305a32dc38735b90b2 (diff) |
xen/pv-on-hvm kexec: add quirk for Xen 3.4 and shutdown watches.
The commit 254d1a3f02ebc10ccc6e4903394d8d3f484f715e, titled
"xen/pv-on-hvm kexec: shutdown watches from old kernel" assumes that the
XenBus backend can deal with reading of values from:
"control/platform-feature-xs_reset_watches":
... a patch for xenstored is required so that it
accepts the XS_RESET_WATCHES request from a client (see changeset
23839:42a45baf037d in xen-unstable.hg). Without the patch for xenstored
the registration of watches will fail and some features of a PVonHVM
guest are not available. The guest is still able to boot, but repeated
kexec boots will fail."
Sadly this is not true when using a Xen 3.4 hypervisor and booting a PVHVM
guest. We end up hanging at:
err = xenbus_scanf(XBT_NIL, "control",
"platform-feature-xs_reset_watches", "%d", &supported);
This can easily be seen with guests hanging at xenbus_init:
NX (Execute Disable) protection: active
SMBIOS 2.4 present.
DMI: Xen HVM domU, BIOS 3.4.0 05/13/2011
Hypervisor detected: Xen HVM
Xen version 3.4.
Xen Platform PCI: I/O protocol version 1
... snip ..
calling xenbus_init+0x0/0x27e @ 1
Reverting the commit or using the attached patch fixes the issue. This fix
checks whether the hypervisor is older than 4.0 and if so does not try to
perform the read.
Fixes-Oracle-Bug: 14708233
CC: stable@vger.kernel.org
Acked-by: Olaf Hering <olaf@aepfle.de>
[v2: Added a comment in the source code]
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/xen/xenbus/xenbus_xs.c | 21 |
1 files changed, 21 insertions, 0 deletions
diff --git a/drivers/xen/xenbus/xenbus_xs.c b/drivers/xen/xenbus/xenbus_xs.c index 131dec04794e..48220e129f85 100644 --- a/drivers/xen/xenbus/xenbus_xs.c +++ b/drivers/xen/xenbus/xenbus_xs.c | |||
@@ -48,6 +48,7 @@ | |||
48 | #include <xen/xenbus.h> | 48 | #include <xen/xenbus.h> |
49 | #include <xen/xen.h> | 49 | #include <xen/xen.h> |
50 | #include "xenbus_comms.h" | 50 | #include "xenbus_comms.h" |
51 | #include <asm/xen/hypervisor.h> | ||
51 | 52 | ||
52 | struct xs_stored_msg { | 53 | struct xs_stored_msg { |
53 | struct list_head list; | 54 | struct list_head list; |
@@ -618,7 +619,24 @@ static struct xenbus_watch *find_watch(const char *token) | |||
618 | 619 | ||
619 | return NULL; | 620 | return NULL; |
620 | } | 621 | } |
622 | /* | ||
623 | * Certain older XenBus toolstack cannot handle reading values that are | ||
624 | * not populated. Some Xen 3.4 installation are incapable of doing this | ||
625 | * so if we are running on anything older than 4 do not attempt to read | ||
626 | * control/platform-feature-xs_reset_watches. | ||
627 | */ | ||
628 | static bool xen_strict_xenbus_quirk() | ||
629 | { | ||
630 | uint32_t eax, ebx, ecx, edx, base; | ||
631 | |||
632 | base = xen_cpuid_base(); | ||
633 | cpuid(base + 1, &eax, &ebx, &ecx, &edx); | ||
621 | 634 | ||
635 | if ((eax >> 16) < 4) | ||
636 | return true; | ||
637 | return false; | ||
638 | |||
639 | } | ||
622 | static void xs_reset_watches(void) | 640 | static void xs_reset_watches(void) |
623 | { | 641 | { |
624 | int err, supported = 0; | 642 | int err, supported = 0; |
@@ -626,6 +644,9 @@ static void xs_reset_watches(void) | |||
626 | if (!xen_hvm_domain() || xen_initial_domain()) | 644 | if (!xen_hvm_domain() || xen_initial_domain()) |
627 | return; | 645 | return; |
628 | 646 | ||
647 | if (xen_strict_xenbus_quirk()) | ||
648 | return; | ||
649 | |||
629 | err = xenbus_scanf(XBT_NIL, "control", | 650 | err = xenbus_scanf(XBT_NIL, "control", |
630 | "platform-feature-xs_reset_watches", "%d", &supported); | 651 | "platform-feature-xs_reset_watches", "%d", &supported); |
631 | if (err != 1 || !supported) | 652 | if (err != 1 || !supported) |