226 lines
7.2 KiB
Plaintext
226 lines
7.2 KiB
Plaintext
Subject: 32-on-64 blkif protocol negotiation fallback for old guests.
|
|
From: kraxel@suse.de
|
|
References: 244055
|
|
Patch-mainline: never.
|
|
|
|
See the comment below. Oh well.
|
|
|
|
--- head-2010-04-29.orig/drivers/xen/Kconfig 2010-03-31 14:08:31.000000000 +0200
|
|
+++ head-2010-04-29/drivers/xen/Kconfig 2010-03-31 14:08:50.000000000 +0200
|
|
@@ -30,6 +30,9 @@ config XEN_PRIVCMD
|
|
def_bool y
|
|
depends on PROC_FS
|
|
|
|
+config XEN_DOMCTL
|
|
+ tristate
|
|
+
|
|
config XEN_XENBUS_DEV
|
|
def_bool y
|
|
depends on PROC_FS
|
|
@@ -49,6 +52,7 @@ config XEN_BLKDEV_BACKEND
|
|
tristate "Block-device backend driver"
|
|
depends on XEN_BACKEND
|
|
default XEN_BACKEND
|
|
+ select XEN_DOMCTL
|
|
help
|
|
The block-device backend driver allows the kernel to export its
|
|
block devices to other guests via a high-performance shared-memory
|
|
@@ -58,6 +62,7 @@ config XEN_BLKDEV_TAP
|
|
tristate "Block-device tap backend driver"
|
|
depends on XEN_BACKEND
|
|
default XEN_BACKEND
|
|
+ select XEN_DOMCTL
|
|
help
|
|
The block tap driver is an alternative to the block back driver
|
|
and allows VM block requests to be redirected to userspace through
|
|
--- head-2010-04-29.orig/drivers/xen/blkback/xenbus.c 2010-03-25 14:37:55.000000000 +0100
|
|
+++ head-2010-04-29/drivers/xen/blkback/xenbus.c 2010-03-25 14:37:59.000000000 +0100
|
|
@@ -21,6 +21,7 @@
|
|
#include <linux/module.h>
|
|
#include <linux/kthread.h>
|
|
#include "common.h"
|
|
+#include "../core/domctl.h"
|
|
|
|
#undef DPRINTK
|
|
#define DPRINTK(fmt, args...) \
|
|
@@ -492,8 +493,10 @@ static int connect_ring(struct backend_i
|
|
be->blkif->blk_protocol = BLKIF_PROTOCOL_NATIVE;
|
|
err = xenbus_gather(XBT_NIL, dev->otherend, "protocol",
|
|
"%63s", protocol, NULL);
|
|
- if (err)
|
|
- strcpy(protocol, "unspecified, assuming native");
|
|
+ if (err) {
|
|
+ strcpy(protocol, "unspecified");
|
|
+ be->blkif->blk_protocol = xen_guest_blkif_protocol(be->blkif->domid);
|
|
+ }
|
|
else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_NATIVE))
|
|
be->blkif->blk_protocol = BLKIF_PROTOCOL_NATIVE;
|
|
else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_X86_32))
|
|
--- head-2010-04-29.orig/drivers/xen/blktap/xenbus.c 2010-04-29 10:15:25.000000000 +0200
|
|
+++ head-2010-04-29/drivers/xen/blktap/xenbus.c 2010-04-29 10:15:31.000000000 +0200
|
|
@@ -39,6 +39,7 @@
|
|
#include <linux/kthread.h>
|
|
#include <xen/xenbus.h>
|
|
#include "common.h"
|
|
+#include "../core/domctl.h"
|
|
|
|
|
|
struct backend_info
|
|
@@ -433,8 +434,10 @@ static int connect_ring(struct backend_i
|
|
be->blkif->blk_protocol = BLKIF_PROTOCOL_NATIVE;
|
|
err = xenbus_gather(XBT_NIL, dev->otherend, "protocol",
|
|
"%63s", protocol, NULL);
|
|
- if (err)
|
|
- strcpy(protocol, "unspecified, assuming native");
|
|
+ if (err) {
|
|
+ strcpy(protocol, "unspecified");
|
|
+ be->blkif->blk_protocol = xen_guest_blkif_protocol(be->blkif->domid);
|
|
+ }
|
|
else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_NATIVE))
|
|
be->blkif->blk_protocol = BLKIF_PROTOCOL_NATIVE;
|
|
else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_X86_32))
|
|
--- head-2010-04-29.orig/drivers/xen/core/Makefile 2010-04-19 14:52:49.000000000 +0200
|
|
+++ head-2010-04-29/drivers/xen/core/Makefile 2010-04-19 14:55:02.000000000 +0200
|
|
@@ -12,3 +12,6 @@ obj-$(CONFIG_XEN_SYSFS) += xen_sysfs.o
|
|
obj-$(CONFIG_XEN_SMPBOOT) += smpboot.o
|
|
obj-$(CONFIG_SMP) += spinlock.o
|
|
obj-$(CONFIG_KEXEC) += machine_kexec.o
|
|
+obj-$(CONFIG_XEN_DOMCTL) += domctl.o
|
|
+CFLAGS_domctl.o := -D__XEN_PUBLIC_XEN_H__ -D__XEN_PUBLIC_GRANT_TABLE_H__
|
|
+CFLAGS_domctl.o += -D__XEN_TOOLS__ -imacros xen/interface/domctl.h
|
|
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
|
|
+++ head-2010-04-29/drivers/xen/core/domctl.c 2010-05-07 12:12:03.000000000 +0200
|
|
@@ -0,0 +1,127 @@
|
|
+/*
|
|
+ * !!! dirty hack alert !!!
|
|
+ *
|
|
+ * Problem: old guests kernels don't have a "protocol" node
|
|
+ * in the frontend xenstore directory, so mixing
|
|
+ * 32 and 64bit domains doesn't work.
|
|
+ *
|
|
+ * Upstream plans to solve this in the tools, by letting them
|
|
+ * create a protocol node. Which certainly makes sense.
|
|
+ * But it isn't trivial and isn't done yet. Too bad.
|
|
+ *
|
|
+ * So for the time being we use the get_address_size domctl
|
|
+ * hypercall for a pretty good guess. Not nice as the domctl
|
|
+ * hypercall isn't supposed to be used by the kernel. Because
|
|
+ * we don't want to have dependencies between dom0 kernel and
|
|
+ * xen kernel versions. Now we have one. Ouch.
|
|
+ */
|
|
+#undef __XEN_PUBLIC_XEN_H__
|
|
+#undef __XEN_PUBLIC_GRANT_TABLE_H__
|
|
+#undef __XEN_TOOLS__
|
|
+#include <linux/kernel.h>
|
|
+#include <linux/module.h>
|
|
+#include <asm/hypervisor.h>
|
|
+#include <xen/blkif.h>
|
|
+
|
|
+#include "domctl.h"
|
|
+
|
|
+/* stuff copied from xen/interface/domctl.h, which we can't
|
|
+ * include directly for the reasons outlined above .... */
|
|
+
|
|
+typedef struct xen_domctl_address_size {
|
|
+ uint32_t size;
|
|
+} xen_domctl_address_size_t;
|
|
+
|
|
+typedef __attribute__((aligned(8))) uint64_t uint64_aligned_t;
|
|
+
|
|
+union xen_domctl {
|
|
+ /* v4: sle10 sp1: xen 3.0.4 + 32-on-64 patches */
|
|
+ struct {
|
|
+ uint32_t cmd;
|
|
+ uint32_t interface_version;
|
|
+ domid_t domain;
|
|
+ union {
|
|
+ /* left out lots of other struct xen_domctl_foobar */
|
|
+ struct xen_domctl_address_size address_size;
|
|
+ uint64_t dummy_align;
|
|
+ uint8_t dummy_pad[128];
|
|
+ };
|
|
+ } v4;
|
|
+
|
|
+ /*
|
|
+ * v5: upstream: xen 3.1
|
|
+ * v6: upstream: xen 4.0
|
|
+ * v7: sle11 sp1: xen 4.0 + cpupools patches
|
|
+ */
|
|
+ struct {
|
|
+ uint32_t cmd;
|
|
+ uint32_t interface_version;
|
|
+ domid_t domain;
|
|
+ union {
|
|
+ struct xen_domctl_address_size address_size;
|
|
+ uint64_aligned_t dummy_align;
|
|
+ uint8_t dummy_pad[128];
|
|
+ };
|
|
+ } v5, v6, v7;
|
|
+};
|
|
+
|
|
+/* The actual code comes here */
|
|
+
|
|
+static inline int hypervisor_domctl(void *domctl)
|
|
+{
|
|
+ return _hypercall1(int, domctl, domctl);
|
|
+}
|
|
+
|
|
+int xen_guest_address_size(int domid)
|
|
+{
|
|
+ union xen_domctl domctl;
|
|
+ int low, ret;
|
|
+
|
|
+#define guest_address_size(ver) do { \
|
|
+ memset(&domctl, 0, sizeof(domctl)); \
|
|
+ domctl.v##ver.cmd = XEN_DOMCTL_get_address_size; \
|
|
+ domctl.v##ver.interface_version = low = ver; \
|
|
+ domctl.v##ver.domain = domid; \
|
|
+ ret = hypervisor_domctl(&domctl) ?: domctl.v##ver.address_size.size; \
|
|
+ if (ret == 32 || ret == 64) { \
|
|
+ printk("v" #ver " domctl worked ok: dom%d is %d-bit\n", \
|
|
+ domid, ret); \
|
|
+ return ret; \
|
|
+ } \
|
|
+} while (0)
|
|
+
|
|
+ BUILD_BUG_ON(XEN_DOMCTL_INTERFACE_VERSION > 7);
|
|
+ guest_address_size(7);
|
|
+#if CONFIG_XEN_COMPAT < 0x040100
|
|
+ guest_address_size(6);
|
|
+#endif
|
|
+#if CONFIG_XEN_COMPAT < 0x040000
|
|
+ guest_address_size(5);
|
|
+#endif
|
|
+#if CONFIG_XEN_COMPAT < 0x030100
|
|
+ guest_address_size(4);
|
|
+#endif
|
|
+
|
|
+ ret = BITS_PER_LONG;
|
|
+ printk("v%d...7 domctls failed, assuming dom%d is native: %d\n",
|
|
+ low, domid, ret);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+EXPORT_SYMBOL_GPL(xen_guest_address_size);
|
|
+
|
|
+int xen_guest_blkif_protocol(int domid)
|
|
+{
|
|
+ int address_size = xen_guest_address_size(domid);
|
|
+
|
|
+ if (address_size == BITS_PER_LONG)
|
|
+ return BLKIF_PROTOCOL_NATIVE;
|
|
+ if (address_size == 32)
|
|
+ return BLKIF_PROTOCOL_X86_32;
|
|
+ if (address_size == 64)
|
|
+ return BLKIF_PROTOCOL_X86_64;
|
|
+ return BLKIF_PROTOCOL_NATIVE;
|
|
+}
|
|
+EXPORT_SYMBOL_GPL(xen_guest_blkif_protocol);
|
|
+
|
|
+MODULE_LICENSE("GPL");
|
|
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
|
|
+++ head-2010-04-29/drivers/xen/core/domctl.h 2010-03-25 14:37:59.000000000 +0100
|
|
@@ -0,0 +1,2 @@
|
|
+int xen_guest_address_size(int domid);
|
|
+int xen_guest_blkif_protocol(int domid);
|