aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/xen
diff options
context:
space:
mode:
authorKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>2012-10-10 13:23:36 -0400
committerKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>2012-10-12 08:49:21 -0400
commitcb6b6df111e46b9d0f79eb971575fd50555f43f4 (patch)
tree7587983a02f37b0a70b0e930344b497e607b0581 /drivers/xen
parent1a7bbda5b1ab0e02622761305a32dc38735b90b2 (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/xen')
-rw-r--r--drivers/xen/xenbus/xenbus_xs.c21
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
52struct xs_stored_msg { 53struct 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 */
628static 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}
622static void xs_reset_watches(void) 640static 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)