From mboxrd@z Thu Jan 1 00:00:00 1970 From: Gerd Hoffmann Subject: Re: 32-on-64: pvfb issue Date: Tue, 23 Jan 2007 13:53:28 +0100 Message-ID: <45B60548.4060003@suse.de> References: Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="------------000505040008020109050601" Return-path: In-Reply-To: List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xensource.com Errors-To: xen-devel-bounces@lists.xensource.com To: Keir Fraser Cc: Xen devel list , Markus Armbruster List-Id: xen-devel@lists.xenproject.org This is a multi-part message in MIME format. --------------000505040008020109050601 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Keir Fraser wrote: > On 22/1/07 14:01, "Gerd Hoffmann" wrote: > >> Here we go. Compile-tested on 32bit, more tests coming, full rebuild >> still in progress ... > > Yeah, I like these. They can go in as soon as you're happy with them. One > exception is blkback -- I'm not keen on the v1/v2 thing as it is. I think we > should continue to include public/io/blkif.h and use the struct definition > there when protocol==XEN_IO_PROTO_ABI_NATIVE. Fixed. New versions attached, with comments added/updated and signed-off-by. They are partly tested only though, 32-on-64 seems to be broken in current unstable, mixing 32bit and 64bit domains doesn't work. Time to get the domain builder bits merged too, so this can be added to the regression tests ... please apply, Gerd -- Gerd Hoffmann --------------000505040008020109050601 Content-Type: text/x-patch; name="protocol-bimodal.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="protocol-bimodal.diff" bimodal: header file with protocol names. This patch adds a header file with the protocol names. Signed-off-by: Gerd Hoffmann --- xen/include/public/io/protocols.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) Index: build-32-unstable-13495/xen/include/public/io/protocols.h =================================================================== --- /dev/null +++ build-32-unstable-13495/xen/include/public/io/protocols.h @@ -0,0 +1,21 @@ +#ifndef __XEN_PROTOCOLS_H__ +#define __XEN_PROTOCOLS_H__ + +#define XEN_IO_PROTO_ABI_X86_32 "x86_32-abi" +#define XEN_IO_PROTO_ABI_X86_64 "x86_64-abi" +#define XEN_IO_PROTO_ABI_IA64 "ia64-abi" +#define XEN_IO_PROTO_ABI_POWERPC64 "powerpc64-abi" + +#if defined(__i386__) +# define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_X86_32 +#elif defined(__x86_64__) +# define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_X86_64 +#elif defined(__ia64__) +# define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_IA64 +#elif defined(__powerpc64__) +# define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_POWERPC64 +#else +# error arch fixup needed here +#endif + +#endif --------------000505040008020109050601 Content-Type: text/x-patch; name="blkfront-bimodal.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="blkfront-bimodal.diff" bimodal: blkfront Create a new node "protocol" in xenstore, add the protocol name it speaks there. Signed-off-by: Gerd Hoffmann --- linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c | 7 +++++++ 1 file changed, 7 insertions(+) Index: build-32-unstable-13534/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c =================================================================== --- build-32-unstable-13534.orig/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c +++ build-32-unstable-13534/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -180,6 +181,12 @@ again: message = "writing event-channel"; goto abort_transaction; } + err = xenbus_printf(xbt, dev->nodename, "protocol", "%s", + XEN_IO_PROTO_ABI_NATIVE); + if (err) { + message = "writing protocol"; + goto abort_transaction; + } err = xenbus_transaction_end(xbt, 0); if (err) { --------------000505040008020109050601 Content-Type: text/x-patch; name="fbfront-bimodal.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="fbfront-bimodal.diff" bimodal: pvfb frontend Create a new node "protocol" in xenstore, add the protocol name it speaks there. Signed-off-by: Gerd Hoffmann --- linux-2.6-xen-sparse/drivers/xen/fbfront/xenfb.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) Index: build-32-unstable-13495/linux-2.6-xen-sparse/drivers/xen/fbfront/xenfb.c =================================================================== --- build-32-unstable-13495.orig/linux-2.6-xen-sparse/drivers/xen/fbfront/xenfb.c +++ build-32-unstable-13495/linux-2.6-xen-sparse/drivers/xen/fbfront/xenfb.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -479,7 +480,7 @@ static int __devinit xenfb_probe(struct goto error_nomem; /* set up shared page */ - info->page = (void *)__get_free_page(GFP_KERNEL); + info->page = (void *)__get_free_page(GFP_KERNEL | __GFP_ZERO); if (!info->page) goto error_nomem; @@ -640,6 +641,10 @@ static int xenfb_connect_backend(struct irq_to_evtchn_port(info->irq)); if (ret) goto error_xenbus; + ret = xenbus_printf(xbt, dev->nodename, "protocol", "%s", + XEN_IO_PROTO_ABI_NATIVE); + if (ret) + goto error_xenbus; ret = xenbus_printf(xbt, dev->nodename, "feature-update", "1"); if (ret) goto error_xenbus; --------------000505040008020109050601 Content-Type: text/x-patch; name="blkback-bimodal.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="blkback-bimodal.diff" multiprotocol blkback drivers. This is a patch for the block interface, frontend drivers, backend drivers and tools to support multiple ring protocols. Right there are now just two: the 32bit and the 64bit one. If needed it can be extended. Interface changes (io/blkif.h) * Have both request structs there, with "v1" and "v2" added to the name. The old name is aliased to the native protocol of the architecture. * Add helper functions to convert v1/v2 requests to native. Backend changes: * Look at the "protocol" name of the frontend and switch ring handling accordingly. If the protocol node isn't present it assumes native protocol. * As the request struct is copied anyway before being processed (for security reasons) it is converted to native at that point so most backend code doesn't need to know what the frontend speaks. * In case of blktap this is completely transparent to userspace, the kernel/userspace ring is always native no matter what the frontend speaks. --- linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c | 71 ++++++++++---- linux-2.6-xen-sparse/drivers/xen/blkback/common.h | 6 - linux-2.6-xen-sparse/drivers/xen/blkback/interface.c | 25 ++++- linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c | 19 +++ linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c | 74 ++++++++++---- linux-2.6-xen-sparse/drivers/xen/blktap/common.h | 6 - linux-2.6-xen-sparse/drivers/xen/blktap/interface.c | 25 ++++- linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c | 19 +++ linux-2.6-xen-sparse/include/xen/blkif.h | 95 +++++++++++++++++++ xen/include/public/io/blkif.h | 14 +- 10 files changed, 290 insertions(+), 64 deletions(-) Index: build-32-unstable-13534/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c =================================================================== --- build-32-unstable-13534.orig/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c +++ build-32-unstable-13534/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c @@ -298,17 +298,20 @@ irqreturn_t blkif_be_int(int irq, void * static int do_block_io_op(blkif_t *blkif) { - blkif_back_ring_t *blk_ring = &blkif->blk_ring; + blkif_back_rings_t *blk_rings = &blkif->blk_rings; blkif_request_t req; pending_req_t *pending_req; RING_IDX rc, rp; int more_to_do = 0; - rc = blk_ring->req_cons; - rp = blk_ring->sring->req_prod; + rc = blk_rings->common.req_cons; + rp = blk_rings->common.sring->req_prod; rmb(); /* Ensure we see queued requests up to 'rp'. */ - while ((rc != rp) && !RING_REQUEST_CONS_OVERFLOW(blk_ring, rc)) { + while ((rc != rp)) { + + if (RING_REQUEST_CONS_OVERFLOW(&blk_rings->common, rc)) + break; pending_req = alloc_req(); if (NULL == pending_req) { @@ -317,8 +320,20 @@ static int do_block_io_op(blkif_t *blkif break; } - memcpy(&req, RING_GET_REQUEST(blk_ring, rc), sizeof(req)); - blk_ring->req_cons = ++rc; /* before make_response() */ + switch (blkif->blk_protocol) { + case BLKIF_PROTOCOL_NATIVE: + memcpy(&req, RING_GET_REQUEST(&blk_rings->native, rc), sizeof(req)); + break; + case BLKIF_PROTOCOL_X86_32: + blkif_get_x86_32_req(&req, RING_GET_REQUEST(&blk_rings->x86_32, rc)); + break; + case BLKIF_PROTOCOL_X86_64: + blkif_get_x86_64_req(&req, RING_GET_REQUEST(&blk_rings->x86_64, rc)); + break; + default: + BUG(); + } + blk_rings->common.req_cons = ++rc; /* before make_response() */ switch (req.operation) { case BLKIF_OP_READ: @@ -498,34 +513,48 @@ static void dispatch_rw_block_io(blkif_t static void make_response(blkif_t *blkif, unsigned long id, unsigned short op, int st) { - blkif_response_t *resp; + blkif_response_t resp; unsigned long flags; - blkif_back_ring_t *blk_ring = &blkif->blk_ring; + blkif_back_rings_t *blk_rings = &blkif->blk_rings; int more_to_do = 0; int notify; - spin_lock_irqsave(&blkif->blk_ring_lock, flags); - - /* Place on the response ring for the relevant domain. */ - resp = RING_GET_RESPONSE(blk_ring, blk_ring->rsp_prod_pvt); - resp->id = id; - resp->operation = op; - resp->status = st; - blk_ring->rsp_prod_pvt++; - RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(blk_ring, notify); + resp.id = id; + resp.operation = op; + resp.status = st; - if (blk_ring->rsp_prod_pvt == blk_ring->req_cons) { + spin_lock_irqsave(&blkif->blk_ring_lock, flags); + /* Place on the response ring for the relevant domain. */ + switch (blkif->blk_protocol) { + case BLKIF_PROTOCOL_NATIVE: + memcpy(RING_GET_RESPONSE(&blk_rings->native, blk_rings->native.rsp_prod_pvt), + &resp, sizeof(resp)); + break; + case BLKIF_PROTOCOL_X86_32: + memcpy(RING_GET_RESPONSE(&blk_rings->x86_32, blk_rings->x86_32.rsp_prod_pvt), + &resp, sizeof(resp)); + break; + case BLKIF_PROTOCOL_X86_64: + memcpy(RING_GET_RESPONSE(&blk_rings->x86_64, blk_rings->x86_64.rsp_prod_pvt), + &resp, sizeof(resp)); + break; + default: + BUG(); + } + blk_rings->common.rsp_prod_pvt++; + RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&blk_rings->common, notify); + if (blk_rings->common.rsp_prod_pvt == blk_rings->common.req_cons) { /* * Tail check for pending requests. Allows frontend to avoid * notifications if requests are already in flight (lower * overheads and promotes batching). */ - RING_FINAL_CHECK_FOR_REQUESTS(blk_ring, more_to_do); + RING_FINAL_CHECK_FOR_REQUESTS(&blk_rings->common, more_to_do); - } else if (RING_HAS_UNCONSUMED_REQUESTS(blk_ring)) { + } else if (RING_HAS_UNCONSUMED_REQUESTS(&blk_rings->common)) { more_to_do = 1; - } + spin_unlock_irqrestore(&blkif->blk_ring_lock, flags); if (more_to_do) Index: build-32-unstable-13534/linux-2.6-xen-sparse/drivers/xen/blkback/common.h =================================================================== --- build-32-unstable-13534.orig/linux-2.6-xen-sparse/drivers/xen/blkback/common.h +++ build-32-unstable-13534/linux-2.6-xen-sparse/drivers/xen/blkback/common.h @@ -40,8 +40,7 @@ #include #include #include -#include -#include +#include #include #include #include @@ -67,7 +66,8 @@ typedef struct blkif_st { /* Physical parameters of the comms window. */ unsigned int irq; /* Comms information. */ - blkif_back_ring_t blk_ring; + int blk_protocol; + blkif_back_rings_t blk_rings; struct vm_struct *blk_ring_area; /* The VBD attached to this interface. */ struct vbd vbd; Index: build-32-unstable-13534/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c =================================================================== --- build-32-unstable-13534.orig/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c +++ build-32-unstable-13534/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c @@ -95,7 +95,6 @@ static void unmap_frontend_page(blkif_t int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn) { - blkif_sring_t *sring; int err; /* Already connected through? */ @@ -111,8 +110,24 @@ int blkif_map(blkif_t *blkif, unsigned l return err; } - sring = (blkif_sring_t *)blkif->blk_ring_area->addr; - BACK_RING_INIT(&blkif->blk_ring, sring, PAGE_SIZE); + switch (blkif->blk_protocol) { + case 1: + { + blkif_x86_32_sring_t *sring_x86_32; + sring_x86_32 = (blkif_x86_32_sring_t *)blkif->blk_ring_area->addr; + BACK_RING_INIT(&blkif->blk_rings.x86_32, sring_x86_32, PAGE_SIZE); + break; + } + case 2: + { + blkif_x86_64_sring_t *sring_x86_64; + sring_x86_64 = (blkif_x86_64_sring_t *)blkif->blk_ring_area->addr; + BACK_RING_INIT(&blkif->blk_rings.x86_64, sring_x86_64, PAGE_SIZE); + break; + } + default: + BUG(); + } err = bind_interdomain_evtchn_to_irqhandler( blkif->domid, evtchn, blkif_be_int, 0, "blkif-backend", blkif); @@ -143,10 +158,10 @@ void blkif_disconnect(blkif_t *blkif) blkif->irq = 0; } - if (blkif->blk_ring.sring) { + if (blkif->blk_rings.common.sring) { unmap_frontend_page(blkif); free_vm_area(blkif->blk_ring_area); - blkif->blk_ring.sring = NULL; + blkif->blk_rings.common.sring = NULL; } } Index: build-32-unstable-13534/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c =================================================================== --- build-32-unstable-13534.orig/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c +++ build-32-unstable-13534/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c @@ -459,6 +459,7 @@ static int connect_ring(struct backend_i struct xenbus_device *dev = be->dev; unsigned long ring_ref; unsigned int evtchn; + char protocol[64] = ""; int err; DPRINTK("%s", dev->otherend); @@ -472,6 +473,24 @@ static int connect_ring(struct backend_i return err; } + 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"); + 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)) + be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_32; + else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_X86_64)) + be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_64; + else { + xenbus_dev_fatal(dev, err, "unknown fe protocol %s", protocol); + return -1; + } + printk("blkback: ring-ref %ld, event-channel %d, protocol %d (%s)\n", + ring_ref, evtchn, be->blkif->blk_protocol, protocol); + /* Map the shared frame, irq etc. */ err = blkif_map(be->blkif, ring_ref, evtchn); if (err) { Index: build-32-unstable-13534/xen/include/public/io/blkif.h =================================================================== --- build-32-unstable-13534.orig/xen/include/public/io/blkif.h +++ build-32-unstable-13534/xen/include/public/io/blkif.h @@ -71,18 +71,20 @@ */ #define BLKIF_MAX_SEGMENTS_PER_REQUEST 11 +struct blkif_request_segment { + grant_ref_t gref; /* reference to I/O buffer frame */ + /* @first_sect: first sector in frame to transfer (inclusive). */ + /* @last_sect: last sector in frame to transfer (inclusive). */ + uint8_t first_sect, last_sect; +}; + struct blkif_request { uint8_t operation; /* BLKIF_OP_??? */ uint8_t nr_segments; /* number of segments */ blkif_vdev_t handle; /* only for read/write requests */ uint64_t id; /* private guest value, echoed in resp */ blkif_sector_t sector_number;/* start sector idx on disk (r/w only) */ - struct blkif_request_segment { - grant_ref_t gref; /* reference to I/O buffer frame */ - /* @first_sect: first sector in frame to transfer (inclusive). */ - /* @last_sect: last sector in frame to transfer (inclusive). */ - uint8_t first_sect, last_sect; - } seg[BLKIF_MAX_SEGMENTS_PER_REQUEST]; + struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST]; }; typedef struct blkif_request blkif_request_t; Index: build-32-unstable-13534/linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c =================================================================== --- build-32-unstable-13534.orig/linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c +++ build-32-unstable-13534/linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c @@ -1091,15 +1091,15 @@ irqreturn_t tap_blkif_be_int(int irq, vo static int print_dbug = 1; static int do_block_io_op(blkif_t *blkif) { - blkif_back_ring_t *blk_ring = &blkif->blk_ring; + blkif_back_rings_t *blk_rings = &blkif->blk_rings; blkif_request_t req; pending_req_t *pending_req; RING_IDX rc, rp; int more_to_do = 0; tap_blkif_t *info; - rc = blk_ring->req_cons; - rp = blk_ring->sring->req_prod; + rc = blk_rings->common.req_cons; + rp = blk_rings->common.sring->req_prod; rmb(); /* Ensure we see queued requests up to 'rp'. */ /*Check blkif has corresponding UE ring*/ @@ -1130,8 +1130,8 @@ static int do_block_io_op(blkif_t *blkif more_to_do = 1; break; } - - if (RING_REQUEST_CONS_OVERFLOW(blk_ring, rc)) { + + if (RING_REQUEST_CONS_OVERFLOW(&blk_rings->common, rc)) { WPRINTK("RING_REQUEST_CONS_OVERFLOW!" " More to do\n"); more_to_do = 1; @@ -1145,8 +1145,21 @@ static int do_block_io_op(blkif_t *blkif break; } - memcpy(&req, RING_GET_REQUEST(blk_ring, rc), sizeof(req)); - blk_ring->req_cons = ++rc; /* before make_response() */ + switch (blkif->blk_protocol) { + case BLKIF_PROTOCOL_NATIVE: + memcpy(&req, RING_GET_REQUEST(&blk_rings->native, rc), + sizeof(req)); + break; + case BLKIF_PROTOCOL_X86_32: + blkif_get_x86_32_req(&req, RING_GET_REQUEST(&blk_rings->x86_32, rc)); + break; + case BLKIF_PROTOCOL_X86_64: + blkif_get_x86_64_req(&req, RING_GET_REQUEST(&blk_rings->x86_64, rc)); + break; + default: + BUG(); + } + blk_rings->common.req_cons = ++rc; /* before make_response() */ switch (req.operation) { case BLKIF_OP_READ: @@ -1222,7 +1235,7 @@ static void dispatch_rw_block_io(blkif_t WPRINTK("blktap: fe_ring is full, can't add " "IO Request will be dropped. %d %d\n", RING_SIZE(&info->ufe_ring), - RING_SIZE(&blkif->blk_ring)); + RING_SIZE(&blkif->blk_rings.common)); goto fail_response; } @@ -1410,32 +1423,51 @@ static void dispatch_rw_block_io(blkif_t static void make_response(blkif_t *blkif, unsigned long id, unsigned short op, int st) { - blkif_response_t *resp; + blkif_response_t resp; unsigned long flags; - blkif_back_ring_t *blk_ring = &blkif->blk_ring; + blkif_back_rings_t *blk_rings = &blkif->blk_rings; int more_to_do = 0; int notify; + resp.id = id; + resp.operation = op; + resp.status = st; + spin_lock_irqsave(&blkif->blk_ring_lock, flags); - /* Place on the response ring for the relevant domain. */ - resp = RING_GET_RESPONSE(blk_ring, blk_ring->rsp_prod_pvt); - resp->id = id; - resp->operation = op; - resp->status = st; - blk_ring->rsp_prod_pvt++; - RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(blk_ring, notify); + /* Place on the response ring for the relevant domain. */ + switch (blkif->blk_protocol) { + case BLKIF_PROTOCOL_NATIVE: + memcpy(RING_GET_RESPONSE(&blk_rings->native, + blk_rings->native.rsp_prod_pvt), + &resp, sizeof(resp)); + break; + case BLKIF_PROTOCOL_X86_32: + memcpy(RING_GET_RESPONSE(&blk_rings->x86_32, + blk_rings->x86_32.rsp_prod_pvt), + &resp, sizeof(resp)); + break; + case BLKIF_PROTOCOL_X86_64: + memcpy(RING_GET_RESPONSE(&blk_rings->x86_64, + blk_rings->x86_64.rsp_prod_pvt), + &resp, sizeof(resp)); + break; + default: + BUG(); + } + blk_rings->common.rsp_prod_pvt++; + RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&blk_rings->common, notify); - if (blk_ring->rsp_prod_pvt == blk_ring->req_cons) { + if (blk_rings->common.rsp_prod_pvt == blk_rings->common.req_cons) { /* * Tail check for pending requests. Allows frontend to avoid * notifications if requests are already in flight (lower * overheads and promotes batching). */ - RING_FINAL_CHECK_FOR_REQUESTS(blk_ring, more_to_do); - } else if (RING_HAS_UNCONSUMED_REQUESTS(blk_ring)) { + RING_FINAL_CHECK_FOR_REQUESTS(&blk_rings->common, more_to_do); + } else if (RING_HAS_UNCONSUMED_REQUESTS(&blk_rings->common)) { more_to_do = 1; + } - } spin_unlock_irqrestore(&blkif->blk_ring_lock, flags); if (more_to_do) blkif_notify_work(blkif); Index: build-32-unstable-13534/linux-2.6-xen-sparse/drivers/xen/blktap/common.h =================================================================== --- build-32-unstable-13534.orig/linux-2.6-xen-sparse/drivers/xen/blktap/common.h +++ build-32-unstable-13534/linux-2.6-xen-sparse/drivers/xen/blktap/common.h @@ -39,8 +39,7 @@ #include #include #include -#include -#include +#include #include #include @@ -58,7 +57,8 @@ typedef struct blkif_st { /* Physical parameters of the comms window. */ unsigned int irq; /* Comms information. */ - blkif_back_ring_t blk_ring; + int blk_protocol; + blkif_back_rings_t blk_rings; struct vm_struct *blk_ring_area; /* Back pointer to the backend_info. */ struct backend_info *be; Index: build-32-unstable-13534/linux-2.6-xen-sparse/drivers/xen/blktap/interface.c =================================================================== --- build-32-unstable-13534.orig/linux-2.6-xen-sparse/drivers/xen/blktap/interface.c +++ build-32-unstable-13534/linux-2.6-xen-sparse/drivers/xen/blktap/interface.c @@ -96,7 +96,6 @@ static void unmap_frontend_page(blkif_t int tap_blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn) { - blkif_sring_t *sring; int err; /* Already connected through? */ @@ -112,8 +111,24 @@ int tap_blkif_map(blkif_t *blkif, unsign return err; } - sring = (blkif_sring_t *)blkif->blk_ring_area->addr; - BACK_RING_INIT(&blkif->blk_ring, sring, PAGE_SIZE); + switch (blkif->blk_protocol) { + case 1: + { + blkif_x86_32_sring_t *sring_x86_32; + sring_x86_32 = (blkif_x86_32_sring_t *)blkif->blk_ring_area->addr; + BACK_RING_INIT(&blkif->blk_rings.x86_32, sring_x86_32, PAGE_SIZE); + break; + } + case 2: + { + blkif_x86_64_sring_t *sring_x86_64; + sring_x86_64 = (blkif_x86_64_sring_t *)blkif->blk_ring_area->addr; + BACK_RING_INIT(&blkif->blk_rings.x86_64, sring_x86_64, PAGE_SIZE); + break; + } + default: + BUG(); + } err = bind_interdomain_evtchn_to_irqhandler( blkif->domid, evtchn, tap_blkif_be_int, @@ -134,10 +149,10 @@ void tap_blkif_unmap(blkif_t *blkif) unbind_from_irqhandler(blkif->irq, blkif); blkif->irq = 0; } - if (blkif->blk_ring.sring) { + if (blkif->blk_rings.common.sring) { unmap_frontend_page(blkif); free_vm_area(blkif->blk_ring_area); - blkif->blk_ring.sring = NULL; + blkif->blk_rings.common.sring = NULL; } } Index: build-32-unstable-13534/linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c =================================================================== --- build-32-unstable-13534.orig/linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c +++ build-32-unstable-13534/linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c @@ -340,6 +340,7 @@ static int connect_ring(struct backend_i struct xenbus_device *dev = be->dev; unsigned long ring_ref; unsigned int evtchn; + char protocol[64]; int err; DPRINTK("%s\n", dev->otherend); @@ -353,6 +354,24 @@ static int connect_ring(struct backend_i return err; } + 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"); + 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)) + be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_32; + else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_X86_64)) + be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_64; + else { + xenbus_dev_fatal(dev, err, "unknown fe protocol %s", protocol); + return -1; + } + printk("blktap: ring-ref %ld, event-channel %d, protocol %d (%s)\n", + ring_ref, evtchn, be->blkif->blk_protocol, protocol); + /* Map the shared frame, irq etc. */ err = tap_blkif_map(be->blkif, ring_ref, evtchn); if (err) { Index: build-32-unstable-13534/linux-2.6-xen-sparse/include/xen/blkif.h =================================================================== --- /dev/null +++ build-32-unstable-13534/linux-2.6-xen-sparse/include/xen/blkif.h @@ -0,0 +1,95 @@ +#ifndef __XEN_BLKIF_H__ +#define __XEN_BLKIF_H__ + +#include +#include +#include + +/* Not a real protocol. Used to generate ring structs which contain + * the elements common to all protocols only. This way we get a + * compiler-checkable way to use common struct elements, so we can + * avoid using switch(protocol) in a number of places. */ +struct blkif_common_request { + char dummy; +}; +struct blkif_common_response { + char dummy; +}; + +/* i386 protocol version */ +#pragma pack(push, 4) +struct blkif_x86_32_request { + uint8_t operation; /* BLKIF_OP_??? */ + uint8_t nr_segments; /* number of segments */ + blkif_vdev_t handle; /* only for read/write requests */ + uint64_t id; /* private guest value, echoed in resp */ + blkif_sector_t sector_number;/* start sector idx on disk (r/w only) */ + struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST]; +}; +struct blkif_x86_32_response { + uint64_t id; /* copied from request */ + uint8_t operation; /* copied from request */ + int16_t status; /* BLKIF_RSP_??? */ +}; +typedef struct blkif_x86_32_request blkif_x86_32_request_t; +typedef struct blkif_x86_32_response blkif_x86_32_response_t; +#pragma pack(pop) + +/* x86_64 protocol version */ +struct blkif_x86_64_request { + uint8_t operation; /* BLKIF_OP_??? */ + uint8_t nr_segments; /* number of segments */ + blkif_vdev_t handle; /* only for read/write requests */ + uint64_t __attribute__((__aligned__(8))) id; + blkif_sector_t sector_number;/* start sector idx on disk (r/w only) */ + struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST]; +}; +struct blkif_x86_64_response { + uint64_t __attribute__((__aligned__(8))) id; + uint8_t operation; /* copied from request */ + int16_t status; /* BLKIF_RSP_??? */ +}; +typedef struct blkif_x86_64_request blkif_x86_64_request_t; +typedef struct blkif_x86_64_response blkif_x86_64_response_t; + +DEFINE_RING_TYPES(blkif_common, struct blkif_common_request, struct blkif_common_response); +DEFINE_RING_TYPES(blkif_x86_32, struct blkif_x86_32_request, struct blkif_x86_32_response); +DEFINE_RING_TYPES(blkif_x86_64, struct blkif_x86_64_request, struct blkif_x86_64_response); + +union blkif_back_rings { + blkif_back_ring_t native; + blkif_common_back_ring_t common; + blkif_x86_32_back_ring_t x86_32; + blkif_x86_64_back_ring_t x86_64; +}; +typedef union blkif_back_rings blkif_back_rings_t; + +#define BLKIF_PROTOCOL_NATIVE 1 +#define BLKIF_PROTOCOL_X86_32 2 +#define BLKIF_PROTOCOL_X86_64 3 + +static void inline blkif_get_x86_32_req(blkif_request_t *dst, blkif_x86_32_request_t *src) +{ + int i; + dst->operation = src->operation; + dst->nr_segments = src->nr_segments; + dst->handle = src->handle; + dst->id = src->id; + dst->sector_number = src->sector_number; + for (i = 0; i < src->nr_segments; i++) + dst->seg[i] = src->seg[i]; +} + +static void inline blkif_get_x86_64_req(blkif_request_t *dst, blkif_x86_64_request_t *src) +{ + int i; + dst->operation = src->operation; + dst->nr_segments = src->nr_segments; + dst->handle = src->handle; + dst->id = src->id; + dst->sector_number = src->sector_number; + for (i = 0; i < src->nr_segments; i++) + dst->seg[i] = src->seg[i]; +} + +#endif /* __XEN_BLKIF_H__ */ --------------000505040008020109050601 Content-Type: text/x-patch; name="fbback-bimodal.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="fbback-bimodal.diff" bimodal: pvfb backend Teach pvfb backend to deal with bith 32 and 64 bit frontends. Signed-off-by: Gerd Hoffmann --- tools/xenfb/xenfb.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 92 insertions(+), 11 deletions(-) Index: build-32-unstable-13495/tools/xenfb/xenfb.c =================================================================== --- build-32-unstable-13495.orig/tools/xenfb/xenfb.c +++ build-32-unstable-13495/tools/xenfb/xenfb.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -40,6 +41,7 @@ struct xenfb_private { struct xs_handle *xsh; /* xs daemon handle */ struct xenfb_device fb, kbd; size_t fb_len; /* size of framebuffer */ + char protocol[64]; /* frontend protocol */ }; static void xenfb_detach_dom(struct xenfb_private *); @@ -324,36 +326,112 @@ static int xenfb_wait_for_frontend_initi return 0; } +static void xenfb_copy_mfns(int mode, int count, unsigned long *dst, void *src) +{ + uint32_t *src32 = src; + uint64_t *src64 = src; + int i; + + if (32 == mode) { + for (i = 0; i < count; i++) + dst[i] = src32[i]; + } else { + for (i = 0; i < count; i++) + dst[i] = src64[i]; + } +} + static int xenfb_map_fb(struct xenfb_private *xenfb, int domid) { struct xenfb_page *page = xenfb->fb.page; int n_fbmfns; int n_fbdirs; - unsigned long *fbmfns; + unsigned long *pgmfns = NULL; + unsigned long *fbmfns = NULL; + void *map, *pd; + int mode, ret = -1; + + /* default to native */ + pd = page->pd; + mode = sizeof(unsigned long) * 8; + + if (0 == strlen(xenfb->protocol)) { + /* + * Undefined protocol, some guesswork needed. + * + * Old frontends which don't set the protocol use + * one page directory only, thus pd[1] must be zero. + * pd[1] of the 32bit struct layout and the lower + * 32 bits of pd[0] of the 64bit struct layout have + * the same location, so we can check that ... + */ + uint32_t *ptr32 = NULL; + uint32_t *ptr64 = NULL; +#if defined(__i386_) + ptr32 = page->pd; + ptr64 = ((void*)page->pd) + 4; +#elif defined(__x86_64__) + ptr32 = ((void*)page->pd) - 4; + ptr64 = page->pd; +#endif + if (ptr32) { + if (0 == ptr32[1]) { + mode = 32; + pd = ptr32; + } else { + mode = 64; + pd = ptr64; + } + } +#if defined(__x86_64__) + } else if (0 == strcmp(xenfb->protocol, XEN_IO_PROTO_ABI_X86_32)) { + /* 64bit dom0, 32bit domU */ + mode = 32; + pd = ((void*)page->pd) - 4; +#elif defined(__i386_) + } else if (0 == strcmp(xenfb->protocol, XEN_IO_PROTO_ABI_X86_64)) { + /* 32bit dom0, 64bit domU */ + mode = 64; + pd = ((void*)page->pd) + 4; +#endif + } n_fbmfns = (xenfb->fb_len + (XC_PAGE_SIZE - 1)) / XC_PAGE_SIZE; - n_fbdirs = n_fbmfns * sizeof(unsigned long); + n_fbdirs = n_fbmfns * mode / 8; n_fbdirs = (n_fbdirs + (XC_PAGE_SIZE - 1)) / XC_PAGE_SIZE; + pgmfns = malloc(sizeof(unsigned long) * n_fbdirs); + fbmfns = malloc(sizeof(unsigned long) * n_fbmfns); + if (!pgmfns || !fbmfns) + goto out; + /* * Bug alert: xc_map_foreign_batch() can fail partly and * return a non-null value. This is a design flaw. When it * happens, we happily continue here, and later crash on * access. */ - fbmfns = xc_map_foreign_batch(xenfb->xc, domid, - PROT_READ, page->pd, n_fbdirs); - if (fbmfns == NULL) - return -1; + xenfb_copy_mfns(mode, n_fbdirs, pgmfns, pd); + map = xc_map_foreign_batch(xenfb->xc, domid, + PROT_READ, pgmfns, n_fbdirs); + if (map == NULL) + goto out; + xenfb_copy_mfns(mode, n_fbmfns, fbmfns, map); + munmap(map, n_fbdirs * XC_PAGE_SIZE); xenfb->pub.pixels = xc_map_foreign_batch(xenfb->xc, domid, PROT_READ | PROT_WRITE, fbmfns, n_fbmfns); - if (xenfb->pub.pixels == NULL) { - munmap(fbmfns, n_fbdirs * XC_PAGE_SIZE); - return -1; - } + if (xenfb->pub.pixels == NULL) + goto out; - return munmap(fbmfns, n_fbdirs * XC_PAGE_SIZE); + ret = 0; /* all is fine */ + + out: + if (pgmfns) + free(pgmfns); + if (fbmfns) + free(fbmfns); + return ret; } static int xenfb_bind(struct xenfb_device *dev) @@ -368,6 +446,9 @@ static int xenfb_bind(struct xenfb_devic if (xenfb_xs_scanf1(xenfb->xsh, dev->otherend, "event-channel", "%u", &evtchn) < 0) return -1; + if (xenfb_xs_scanf1(xenfb->xsh, dev->otherend, "protocol", "%63s", + xenfb->protocol) < 0) + xenfb->protocol[0] = '\0'; dev->port = xc_evtchn_bind_interdomain(xenfb->evt_xch, dev->otherend_id, evtchn); --------------000505040008020109050601 Content-Type: text/x-patch; name="blktools-bimodal.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="blktools-bimodal.diff" bimodal: blk tools Add one more option to the disk configuration, so one can specify the protocol the frontend speaks in the config file. This is needed for old frontends which don't advertise the protocol they are speaking themself. I'm not that happy with this approach, but it works for now and I'm kida lost in the stack of python classes doing domain and device handling ... Signed-off-by: Gerd Hoffmann --- tools/python/xen/xend/server/blkif.py | 3 +++ tools/python/xen/xm/create.py | 7 ++++++- 2 files changed, 9 insertions(+), 1 deletion(-) Index: build-32-unstable-13534/tools/python/xen/xend/server/blkif.py =================================================================== --- build-32-unstable-13534.orig/tools/python/xen/xend/server/blkif.py +++ build-32-unstable-13534/tools/python/xen/xend/server/blkif.py @@ -38,6 +38,7 @@ class BlkifController(DevController): """@see DevController.getDeviceDetails""" uname = config.get('uname', '') dev = config.get('dev', '') + protocol = config.get('protocol') if 'ioemu:' in dev: (_, dev) = string.split(dev, ':', 1) @@ -85,6 +86,8 @@ class BlkifController(DevController): front = { 'virtual-device' : "%i" % devid, 'device-type' : dev_type } + if protocol: + front.update({ 'protocol' : protocol }); return (devid, back, front) Index: build-32-unstable-13534/tools/python/xen/xm/create.py =================================================================== --- build-32-unstable-13534.orig/tools/python/xen/xm/create.py +++ build-32-unstable-13534/tools/python/xen/xm/create.py @@ -537,7 +537,7 @@ def configure_image(vals): def configure_disks(config_devs, vals): """Create the config for disks (virtual block devices). """ - for (uname, dev, mode, backend) in vals.disk: + for (uname, dev, mode, backend, protocol) in vals.disk: if uname.startswith('tap:'): cls = 'tap' else: @@ -549,6 +549,8 @@ def configure_disks(config_devs, vals): ['mode', mode ] ] if backend: config_vbd.append(['backend', backend]) + if protocol: + config_vbd.append(['protocol', protocol]) config_devs.append(['device', config_vbd]) def configure_pci(config_devs, vals): @@ -803,7 +805,10 @@ def preprocess_disk(vals): n = len(d) if n == 3: d.append(None) + d.append(None) elif n == 4: + d.append(None) + elif n == 5: pass else: err('Invalid disk specifier: ' + v) --------------000505040008020109050601 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel --------------000505040008020109050601--