diff options
Diffstat (limited to 'trunk/2.6.22/20070_xen-blkif-protocol-fallback-hack.patch1')
-rw-r--r-- | trunk/2.6.22/20070_xen-blkif-protocol-fallback-hack.patch1 | 229 |
1 files changed, 229 insertions, 0 deletions
diff --git a/trunk/2.6.22/20070_xen-blkif-protocol-fallback-hack.patch1 b/trunk/2.6.22/20070_xen-blkif-protocol-fallback-hack.patch1 new file mode 100644 index 0000000..9b2b0b1 --- /dev/null +++ b/trunk/2.6.22/20070_xen-blkif-protocol-fallback-hack.patch1 @@ -0,0 +1,229 @@ +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. + +--- + drivers/xen/blkback/xenbus.c | 8 +- + drivers/xen/blktap/xenbus.c | 8 +- + drivers/xen/core/Makefile | 2 + drivers/xen/core/domctl.c | 133 +++++++++++++++++++++++++++++++++++++++++++ + drivers/xen/core/domctl.h | 2 + 5 files changed, 146 insertions(+), 7 deletions(-) + +--- a/drivers/xen/blkback/xenbus.c 2007-08-27 14:01:27.000000000 -0400 ++++ b/drivers/xen/blkback/xenbus.c 2007-08-27 14:01:47.000000000 -0400 +@@ -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...) \ +@@ -457,7 +458,6 @@ again: + xenbus_transaction_end(xbt, 1); + } + +- + static int connect_ring(struct backend_info *be) + { + struct xenbus_device *dev = be->dev; +@@ -480,8 +480,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)) +--- a/drivers/xen/blktap/xenbus.c 2007-08-27 14:01:27.000000000 -0400 ++++ b/drivers/xen/blktap/xenbus.c 2007-08-27 14:01:27.000000000 -0400 +@@ -39,6 +39,7 @@ + #include <linux/kthread.h> + #include <xen/xenbus.h> + #include "common.h" ++#include "../core/domctl.h" + + + struct backend_info +@@ -397,7 +398,6 @@ static void connect(struct backend_info + return; + } + +- + static int connect_ring(struct backend_info *be) + { + struct xenbus_device *dev = be->dev; +@@ -420,8 +420,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)) +--- a/drivers/xen/core/Makefile 2007-08-27 14:01:25.000000000 -0400 ++++ b/drivers/xen/core/Makefile 2007-08-27 14:01:27.000000000 -0400 +@@ -2,7 +2,7 @@ + # Makefile for the linux kernel. + # + +-obj-y := evtchn.o gnttab.o features.o reboot.o machine_reboot.o firmware.o ++obj-y := evtchn.o gnttab.o features.o reboot.o machine_reboot.o firmware.o domctl.o + + obj-$(CONFIG_PROC_FS) += xen_proc.o + obj-$(CONFIG_SYS_HYPERVISOR) += hypervisor_sysfs.o +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ b/drivers/xen/core/domctl.c 2007-08-27 14:01:27.000000000 -0400 +@@ -0,0 +1,133 @@ ++/* ++ * !!! 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. ++ */ ++ ++#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 .... */ ++ ++#define XEN_DOMCTL_set_address_size 35 ++#define XEN_DOMCTL_get_address_size 36 ++typedef struct xen_domctl_address_size { ++ uint32_t size; ++} xen_domctl_address_size_t; ++ ++#define native_address_size (sizeof(unsigned long)*8) ++ ++/* v4: sles10 sp1: xen 3.0.4 + 32-on-64 patches */ ++struct xen_domctl_v4 { ++ uint32_t cmd; ++ uint32_t interface_version; /* XEN_DOMCTL_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]; ++ } u; ++}; ++ ++/* v5: upstream: xen 3.0.5 */ ++typedef __attribute__((aligned(8))) uint64_t uint64_aligned_t; ++struct xen_domctl_v5 { ++ 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]; ++ } u; ++}; ++ ++/* The actual code comes here */ ++ ++static int xen_guest_address_size_v4(int domid) ++{ ++ struct xen_domctl_v4 domctl; ++ int rc; ++ ++ memset(&domctl, 0, sizeof(domctl)); ++ domctl.cmd = XEN_DOMCTL_get_address_size; ++ domctl.interface_version = 4; ++ domctl.domain = domid; ++ if (0 != (rc = _hypercall1(int, domctl, &domctl))) ++ return rc; ++ return domctl.u.address_size.size; ++} ++ ++static int xen_guest_address_size_v5(int domid) ++{ ++ struct xen_domctl_v5 domctl; ++ int rc; ++ ++ memset(&domctl, 0, sizeof(domctl)); ++ domctl.cmd = XEN_DOMCTL_get_address_size; ++ domctl.interface_version = 5; ++ domctl.domain = domid; ++ if (0 != (rc = _hypercall1(int, domctl, &domctl))) ++ return rc; ++ return domctl.u.address_size.size; ++} ++ ++int xen_guest_address_size(int domid) ++{ ++ int ret; ++ ++ ret = xen_guest_address_size_v4(domid); ++ if (ret == 32 || ret == 64) { ++ printk("%s: v4 domctl worked ok: %d\n", __FUNCTION__, ret); ++ goto done; ++ } ++ ++ ret = xen_guest_address_size_v5(domid); ++ if (ret == 32 || ret == 64) { ++ printk("%s: v5 domctl worked ok: %d\n", __FUNCTION__, ret); ++ goto done; ++ } ++ ++ ret = native_address_size; ++ printk("%s: v4,v5 domctls failed, assuming native: %d\n", ++ __FUNCTION__, ret); ++ ++ done: ++ return ret; ++} ++EXPORT_SYMBOL_GPL(xen_guest_address_size); ++ ++int xen_guest_blkif_protocol(int domid) ++{ ++ int address_size; ++ ++ address_size = xen_guest_address_size(domid); ++ printk(KERN_DEBUG "%s: domain %d: got address size %d\n", ++ __FUNCTION__, domid, address_size); ++ if (address_size == native_address_size) ++ 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); +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ b/drivers/xen/core/domctl.h 2007-08-27 14:01:27.000000000 -0400 +@@ -0,0 +1,2 @@ ++int xen_guest_address_size(int domid); ++int xen_guest_blkif_protocol(int domid); |