Mailing List Archive

Merged.
# HG changeset patch
# User emellor@ewan
# Node ID 10759a44ce3b9431b730eadde2417777ca8f9943
# Parent eba5afe9aa37d3cb96c22cd93b8b7ec7c8e3e1ca
# Parent 28db21fb75453d80636142432b9e324fcd472c52
Merged.

diff -r eba5afe9aa37 -r 10759a44ce3b linux-2.6-xen-sparse/arch/xen/Kconfig
--- a/linux-2.6-xen-sparse/arch/xen/Kconfig Thu Sep 22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/arch/xen/Kconfig Thu Sep 22 15:12:14 2005
@@ -110,13 +110,6 @@
network interfaces within another guest OS. Unless you are building a
dedicated device-driver domain, or your master control domain
(domain 0), then you almost certainly want to say Y here.
-
-config XEN_NETDEV_GRANT
- bool "Grant table substrate for network drivers (DANGEROUS)"
- default n
- help
- This introduces the use of grant tables as a data exhange mechanism
- between the frontend and backend network drivers.

config XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER
bool "Pipelined transmitter (DANGEROUS)"
diff -r eba5afe9aa37 -r 10759a44ce3b linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_x86_32
--- a/linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_x86_32 Thu Sep 22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_x86_32 Thu Sep 22 15:12:14 2005
@@ -19,7 +19,6 @@
# CONFIG_XEN_TPMDEV_BACKEND is not set
CONFIG_XEN_BLKDEV_FRONTEND=y
CONFIG_XEN_NETDEV_FRONTEND=y
-CONFIG_XEN_NETDEV_GRANT=y
# CONFIG_XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER is not set
# CONFIG_XEN_BLKDEV_TAP is not set
# CONFIG_XEN_SHADOW_MODE is not set
diff -r eba5afe9aa37 -r 10759a44ce3b linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_x86_64
--- a/linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_x86_64 Thu Sep 22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_x86_64 Thu Sep 22 15:12:14 2005
@@ -19,7 +19,6 @@
# CONFIG_XEN_TPMDEV_BACKEND is not set
CONFIG_XEN_BLKDEV_FRONTEND=y
CONFIG_XEN_NETDEV_FRONTEND=y
-CONFIG_XEN_NETDEV_GRANT=y
# CONFIG_XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER is not set
# CONFIG_XEN_BLKDEV_TAP is not set
# CONFIG_XEN_SHADOW_MODE is not set
diff -r eba5afe9aa37 -r 10759a44ce3b linux-2.6-xen-sparse/arch/xen/configs/xenU_defconfig_x86_32
--- a/linux-2.6-xen-sparse/arch/xen/configs/xenU_defconfig_x86_32 Thu Sep 22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/arch/xen/configs/xenU_defconfig_x86_32 Thu Sep 22 15:12:14 2005
@@ -16,7 +16,6 @@
# CONFIG_XEN_TPMDEV_BACKEND is not set
CONFIG_XEN_BLKDEV_FRONTEND=y
CONFIG_XEN_NETDEV_FRONTEND=y
-CONFIG_XEN_NETDEV_GRANT=y
# CONFIG_XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER is not set
# CONFIG_XEN_BLKDEV_TAP is not set
# CONFIG_XEN_SHADOW_MODE is not set
diff -r eba5afe9aa37 -r 10759a44ce3b linux-2.6-xen-sparse/arch/xen/configs/xenU_defconfig_x86_64
--- a/linux-2.6-xen-sparse/arch/xen/configs/xenU_defconfig_x86_64 Thu Sep 22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/arch/xen/configs/xenU_defconfig_x86_64 Thu Sep 22 15:12:14 2005
@@ -16,7 +16,6 @@
# CONFIG_XEN_TPMDEV_BACKEND is not set
CONFIG_XEN_BLKDEV_FRONTEND=y
CONFIG_XEN_NETDEV_FRONTEND=y
-CONFIG_XEN_NETDEV_GRANT=y
# CONFIG_XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER is not set
# CONFIG_XEN_BLKDEV_TAP is not set
# CONFIG_XEN_SHADOW_MODE is not set
diff -r eba5afe9aa37 -r 10759a44ce3b linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_32
--- a/linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_32 Thu Sep 22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_32 Thu Sep 22 15:12:14 2005
@@ -19,7 +19,6 @@
# CONFIG_XEN_TPMDEV_BACKEND is not set
CONFIG_XEN_BLKDEV_FRONTEND=y
CONFIG_XEN_NETDEV_FRONTEND=y
-CONFIG_XEN_NETDEV_GRANT=y
# CONFIG_XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER is not set
# CONFIG_XEN_BLKDEV_TAP is not set
# CONFIG_XEN_SHADOW_MODE is not set
diff -r eba5afe9aa37 -r 10759a44ce3b linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_64
--- a/linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_64 Thu Sep 22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_64 Thu Sep 22 15:12:14 2005
@@ -19,7 +19,6 @@
# CONFIG_XEN_TPMDEV_BACKEND is not set
CONFIG_XEN_BLKDEV_FRONTEND=y
CONFIG_XEN_NETDEV_FRONTEND=y
-CONFIG_XEN_NETDEV_GRANT=y
# CONFIG_XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER is not set
# CONFIG_XEN_BLKDEV_TAP is not set
# CONFIG_XEN_SHADOW_MODE is not set
diff -r eba5afe9aa37 -r 10759a44ce3b linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c
--- a/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c Thu Sep 22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c Thu Sep 22 15:12:14 2005
@@ -28,12 +28,12 @@
#define BATCH_PER_DOMAIN 16

static unsigned long mmap_vstart;
-#define MMAP_PAGES \
- (MAX_PENDING_REQS * BLKIF_MAX_SEGMENTS_PER_REQUEST)
-#define MMAP_VADDR(_req,_seg) \
- (mmap_vstart + \
- ((_req) * BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE) + \
- ((_seg) * PAGE_SIZE))
+#define MMAP_PAGES \
+ (MAX_PENDING_REQS * BLKIF_MAX_SEGMENTS_PER_REQUEST)
+#define MMAP_VADDR(_req,_seg) \
+ (mmap_vstart + \
+ ((_req) * BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE) + \
+ ((_seg) * PAGE_SIZE))

/*
* Each outstanding request that we've passed to the lower device layers has a
@@ -42,12 +42,12 @@
* response queued for it, with the saved 'id' passed back.
*/
typedef struct {
- blkif_t *blkif;
- unsigned long id;
- int nr_pages;
- atomic_t pendcnt;
- unsigned short operation;
- int status;
+ blkif_t *blkif;
+ unsigned long id;
+ int nr_pages;
+ atomic_t pendcnt;
+ unsigned short operation;
+ int status;
} pending_req_t;

/*
@@ -68,14 +68,13 @@
static request_queue_t *plugged_queue;
static inline void flush_plugged_queue(void)
{
- request_queue_t *q = plugged_queue;
- if ( q != NULL )
- {
- if ( q->unplug_fn != NULL )
- q->unplug_fn(q);
- blk_put_queue(q);
- plugged_queue = NULL;
- }
+ request_queue_t *q = plugged_queue;
+ if (q != NULL) {
+ if ( q->unplug_fn != NULL )
+ q->unplug_fn(q);
+ blk_put_queue(q);
+ plugged_queue = NULL;
+ }
}

/* When using grant tables to map a frame for device access then the
@@ -106,24 +105,23 @@

static void fast_flush_area(int idx, int nr_pages)
{
- struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST];
- unsigned int i, invcount = 0;
- u16 handle;
-
- for ( i = 0; i < nr_pages; i++ )
- {
- if ( BLKBACK_INVALID_HANDLE != ( handle = pending_handle(idx, i) ) )
- {
- unmap[i].host_addr = MMAP_VADDR(idx, i);
- unmap[i].dev_bus_addr = 0;
- unmap[i].handle = handle;
- pending_handle(idx, i) = BLKBACK_INVALID_HANDLE;
- invcount++;
- }
- }
- if ( unlikely(HYPERVISOR_grant_table_op(
- GNTTABOP_unmap_grant_ref, unmap, invcount)))
- BUG();
+ struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+ unsigned int i, invcount = 0;
+ u16 handle;
+
+ for (i = 0; i < nr_pages; i++) {
+ handle = pending_handle(idx, i);
+ if (handle == BLKBACK_INVALID_HANDLE)
+ continue;
+ unmap[i].host_addr = MMAP_VADDR(idx, i);
+ unmap[i].dev_bus_addr = 0;
+ unmap[i].handle = handle;
+ pending_handle(idx, i) = BLKBACK_INVALID_HANDLE;
+ invcount++;
+ }
+
+ BUG_ON(HYPERVISOR_grant_table_op(
+ GNTTABOP_unmap_grant_ref, unmap, invcount));
}


@@ -136,34 +134,38 @@

static int __on_blkdev_list(blkif_t *blkif)
{
- return blkif->blkdev_list.next != NULL;
+ return blkif->blkdev_list.next != NULL;
}

static void remove_from_blkdev_list(blkif_t *blkif)
{
- unsigned long flags;
- if ( !__on_blkdev_list(blkif) ) return;
- spin_lock_irqsave(&blkio_schedule_list_lock, flags);
- if ( __on_blkdev_list(blkif) )
- {
- list_del(&blkif->blkdev_list);
- blkif->blkdev_list.next = NULL;
- blkif_put(blkif);
- }
- spin_unlock_irqrestore(&blkio_schedule_list_lock, flags);
+ unsigned long flags;
+
+ if (!__on_blkdev_list(blkif))
+ return;
+
+ spin_lock_irqsave(&blkio_schedule_list_lock, flags);
+ if (__on_blkdev_list(blkif)) {
+ list_del(&blkif->blkdev_list);
+ blkif->blkdev_list.next = NULL;
+ blkif_put(blkif);
+ }
+ spin_unlock_irqrestore(&blkio_schedule_list_lock, flags);
}

static void add_to_blkdev_list_tail(blkif_t *blkif)
{
- unsigned long flags;
- if ( __on_blkdev_list(blkif) ) return;
- spin_lock_irqsave(&blkio_schedule_list_lock, flags);
- if ( !__on_blkdev_list(blkif) && (blkif->status == CONNECTED) )
- {
- list_add_tail(&blkif->blkdev_list, &blkio_schedule_list);
- blkif_get(blkif);
- }
- spin_unlock_irqrestore(&blkio_schedule_list_lock, flags);
+ unsigned long flags;
+
+ if (__on_blkdev_list(blkif))
+ return;
+
+ spin_lock_irqsave(&blkio_schedule_list_lock, flags);
+ if (!__on_blkdev_list(blkif) && (blkif->status == CONNECTED)) {
+ list_add_tail(&blkif->blkdev_list, &blkio_schedule_list);
+ blkif_get(blkif);
+ }
+ spin_unlock_irqrestore(&blkio_schedule_list_lock, flags);
}


@@ -175,54 +177,53 @@

static int blkio_schedule(void *arg)
{
- DECLARE_WAITQUEUE(wq, current);
-
- blkif_t *blkif;
- struct list_head *ent;
-
- daemonize("xenblkd");
-
- for ( ; ; )
- {
- /* Wait for work to do. */
- add_wait_queue(&blkio_schedule_wait, &wq);
- set_current_state(TASK_INTERRUPTIBLE);
- if ( (NR_PENDING_REQS == MAX_PENDING_REQS) ||
- list_empty(&blkio_schedule_list) )
- schedule();
- __set_current_state(TASK_RUNNING);
- remove_wait_queue(&blkio_schedule_wait, &wq);
-
- /* Queue up a batch of requests. */
- while ( (NR_PENDING_REQS < MAX_PENDING_REQS) &&
- !list_empty(&blkio_schedule_list) )
- {
- ent = blkio_schedule_list.next;
- blkif = list_entry(ent, blkif_t, blkdev_list);
- blkif_get(blkif);
- remove_from_blkdev_list(blkif);
- if ( do_block_io_op(blkif, BATCH_PER_DOMAIN) )
- add_to_blkdev_list_tail(blkif);
- blkif_put(blkif);
- }
-
- /* Push the batch through to disc. */
- flush_plugged_queue();
- }
+ DECLARE_WAITQUEUE(wq, current);
+
+ blkif_t *blkif;
+ struct list_head *ent;
+
+ daemonize("xenblkd");
+
+ for (;;) {
+ /* Wait for work to do. */
+ add_wait_queue(&blkio_schedule_wait, &wq);
+ set_current_state(TASK_INTERRUPTIBLE);
+ if ( (NR_PENDING_REQS == MAX_PENDING_REQS) ||
+ list_empty(&blkio_schedule_list) )
+ schedule();
+ __set_current_state(TASK_RUNNING);
+ remove_wait_queue(&blkio_schedule_wait, &wq);
+
+ /* Queue up a batch of requests. */
+ while ((NR_PENDING_REQS < MAX_PENDING_REQS) &&
+ !list_empty(&blkio_schedule_list)) {
+ ent = blkio_schedule_list.next;
+ blkif = list_entry(ent, blkif_t, blkdev_list);
+ blkif_get(blkif);
+ remove_from_blkdev_list(blkif);
+ if (do_block_io_op(blkif, BATCH_PER_DOMAIN))
+ add_to_blkdev_list_tail(blkif);
+ blkif_put(blkif);
+ }
+
+ /* Push the batch through to disc. */
+ flush_plugged_queue();
+ }
}

static void maybe_trigger_blkio_schedule(void)
{
- /*
- * Needed so that two processes, who together make the following predicate
- * true, don't both read stale values and evaluate the predicate
- * incorrectly. Incredibly unlikely to stall the scheduler on x86, but...
- */
- smp_mb();
-
- if ( (NR_PENDING_REQS < (MAX_PENDING_REQS/2)) &&
- !list_empty(&blkio_schedule_list) )
- wake_up(&blkio_schedule_wait);
+ /*
+ * Needed so that two processes, which together make the following
+ * predicate true, don't both read stale values and evaluate the
+ * predicate incorrectly. Incredibly unlikely to stall the scheduler
+ * on x86, but...
+ */
+ smp_mb();
+
+ if ((NR_PENDING_REQS < (MAX_PENDING_REQS/2)) &&
+ !list_empty(&blkio_schedule_list))
+ wake_up(&blkio_schedule_wait);
}


@@ -233,36 +234,34 @@

static void __end_block_io_op(pending_req_t *pending_req, int uptodate)
{
- unsigned long flags;
-
- /* An error fails the entire request. */
- if ( !uptodate )
- {
- DPRINTK("Buffer not up-to-date at end of operation\n");
- pending_req->status = BLKIF_RSP_ERROR;
- }
-
- if ( atomic_dec_and_test(&pending_req->pendcnt) )
- {
- int pending_idx = pending_req - pending_reqs;
- fast_flush_area(pending_idx, pending_req->nr_pages);
- make_response(pending_req->blkif, pending_req->id,
- pending_req->operation, pending_req->status);
- blkif_put(pending_req->blkif);
- spin_lock_irqsave(&pend_prod_lock, flags);
- pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx;
- spin_unlock_irqrestore(&pend_prod_lock, flags);
- maybe_trigger_blkio_schedule();
- }
+ unsigned long flags;
+
+ /* An error fails the entire request. */
+ if (!uptodate) {
+ DPRINTK("Buffer not up-to-date at end of operation\n");
+ pending_req->status = BLKIF_RSP_ERROR;
+ }
+
+ if (atomic_dec_and_test(&pending_req->pendcnt)) {
+ int pending_idx = pending_req - pending_reqs;
+ fast_flush_area(pending_idx, pending_req->nr_pages);
+ make_response(pending_req->blkif, pending_req->id,
+ pending_req->operation, pending_req->status);
+ blkif_put(pending_req->blkif);
+ spin_lock_irqsave(&pend_prod_lock, flags);
+ pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx;
+ spin_unlock_irqrestore(&pend_prod_lock, flags);
+ maybe_trigger_blkio_schedule();
+ }
}

static int end_block_io_op(struct bio *bio, unsigned int done, int error)
{
- if ( bio->bi_size != 0 )
- return 1;
- __end_block_io_op(bio->bi_private, !error);
- bio_put(bio);
- return error;
+ if (bio->bi_size != 0)
+ return 1;
+ __end_block_io_op(bio->bi_private, !error);
+ bio_put(bio);
+ return error;
}


@@ -272,10 +271,10 @@

irqreturn_t blkif_be_int(int irq, void *dev_id, struct pt_regs *regs)
{
- blkif_t *blkif = dev_id;
- add_to_blkdev_list_tail(blkif);
- maybe_trigger_blkio_schedule();
- return IRQ_HANDLED;
+ blkif_t *blkif = dev_id;
+ add_to_blkdev_list_tail(blkif);
+ maybe_trigger_blkio_schedule();
+ return IRQ_HANDLED;
}


@@ -286,183 +285,174 @@

static int do_block_io_op(blkif_t *blkif, int max_to_do)
{
- blkif_back_ring_t *blk_ring = &blkif->blk_ring;
- blkif_request_t *req;
- RING_IDX i, rp;
- int more_to_do = 0;
-
- rp = blk_ring->sring->req_prod;
- rmb(); /* Ensure we see queued requests up to 'rp'. */
-
- for ( i = blk_ring->req_cons;
- (i != rp) && !RING_REQUEST_CONS_OVERFLOW(blk_ring, i);
- i++ )
- {
- if ( (max_to_do-- == 0) || (NR_PENDING_REQS == MAX_PENDING_REQS) )
- {
- more_to_do = 1;
- break;
- }
+ blkif_back_ring_t *blk_ring = &blkif->blk_ring;
+ blkif_request_t *req;
+ RING_IDX i, rp;
+ int more_to_do = 0;
+
+ rp = blk_ring->sring->req_prod;
+ rmb(); /* Ensure we see queued requests up to 'rp'. */
+
+ for (i = blk_ring->req_cons;
+ (i != rp) && !RING_REQUEST_CONS_OVERFLOW(blk_ring, i);
+ i++) {
+ if ((max_to_do-- == 0) ||
+ (NR_PENDING_REQS == MAX_PENDING_REQS)) {
+ more_to_do = 1;
+ break;
+ }

- req = RING_GET_REQUEST(blk_ring, i);
- switch ( req->operation )
- {
- case BLKIF_OP_READ:
- case BLKIF_OP_WRITE:
- dispatch_rw_block_io(blkif, req);
- break;
-
- default:
- DPRINTK("error: unknown block io operation [%d]\n",
- req->operation);
- make_response(blkif, req->id, req->operation, BLKIF_RSP_ERROR);
- break;
- }
- }
-
- blk_ring->req_cons = i;
- return more_to_do;
+ req = RING_GET_REQUEST(blk_ring, i);
+ switch (req->operation) {
+ case BLKIF_OP_READ:
+ case BLKIF_OP_WRITE:
+ dispatch_rw_block_io(blkif, req);
+ break;
+
+ default:
+ DPRINTK("error: unknown block io operation [%d]\n",
+ req->operation);
+ make_response(blkif, req->id, req->operation,
+ BLKIF_RSP_ERROR);
+ break;
+ }
+ }
+
+ blk_ring->req_cons = i;
+ return more_to_do;
}

static void dispatch_rw_block_io(blkif_t *blkif, blkif_request_t *req)
{
- extern void ll_rw_block(int rw, int nr, struct buffer_head * bhs[]);
- int operation = (req->operation == BLKIF_OP_WRITE) ? WRITE : READ;
- unsigned long fas = 0;
- int i, pending_idx = pending_ring[MASK_PEND_IDX(pending_cons)];
- pending_req_t *pending_req;
- struct gnttab_map_grant_ref map[BLKIF_MAX_SEGMENTS_PER_REQUEST];
- struct phys_req preq;
- struct {
- unsigned long buf; unsigned int nsec;
- } seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
- unsigned int nseg;
- struct bio *bio = NULL, *biolist[BLKIF_MAX_SEGMENTS_PER_REQUEST];
- int nbio = 0;
- request_queue_t *q;
-
- /* Check that number of segments is sane. */
- nseg = req->nr_segments;
- if ( unlikely(nseg == 0) ||
- unlikely(nseg > BLKIF_MAX_SEGMENTS_PER_REQUEST) )
- {
- DPRINTK("Bad number of segments in request (%d)\n", nseg);
- goto bad_descriptor;
- }
-
- preq.dev = req->handle;
- preq.sector_number = req->sector_number;
- preq.nr_sects = 0;
-
- for ( i = 0; i < nseg; i++ )
- {
- fas = req->frame_and_sects[i];
- seg[i].nsec = blkif_last_sect(fas) - blkif_first_sect(fas) + 1;
-
- if ( seg[i].nsec <= 0 )
- goto bad_descriptor;
- preq.nr_sects += seg[i].nsec;
-
- map[i].host_addr = MMAP_VADDR(pending_idx, i);
- map[i].dom = blkif->domid;
- map[i].ref = blkif_gref_from_fas(fas);
- map[i].flags = GNTMAP_host_map;
- if ( operation == WRITE )
- map[i].flags |= GNTMAP_readonly;
- }
-
- if ( unlikely(HYPERVISOR_grant_table_op(
- GNTTABOP_map_grant_ref, map, nseg)))
- BUG();
-
- for ( i = 0; i < nseg; i++ )
- {
- if ( unlikely(map[i].handle < 0) )
- {
- DPRINTK("invalid buffer -- could not remap it\n");
- fast_flush_area(pending_idx, nseg);
- goto bad_descriptor;
- }
-
- phys_to_machine_mapping[__pa(MMAP_VADDR(pending_idx, i))>>PAGE_SHIFT] =
- FOREIGN_FRAME(map[i].dev_bus_addr >> PAGE_SHIFT);
-
- pending_handle(pending_idx, i) = map[i].handle;
- }
-
- for ( i = 0; i < nseg; i++ )
- {
- fas = req->frame_and_sects[i];
- seg[i].buf = map[i].dev_bus_addr | (blkif_first_sect(fas) << 9);
- }
-
- if ( vbd_translate(&preq, blkif, operation) != 0 )
- {
- DPRINTK("access denied: %s of [%llu,%llu] on dev=%04x\n",
- operation == READ ? "read" : "write", preq.sector_number,
- preq.sector_number + preq.nr_sects, preq.dev);
- goto bad_descriptor;
- }
-
- pending_req = &pending_reqs[pending_idx];
- pending_req->blkif = blkif;
- pending_req->id = req->id;
- pending_req->operation = operation;
- pending_req->status = BLKIF_RSP_OKAY;
- pending_req->nr_pages = nseg;
-
- for ( i = 0; i < nseg; i++ )
- {
- if ( ((int)preq.sector_number|(int)seg[i].nsec) &
- ((bdev_hardsect_size(preq.bdev) >> 9) - 1) )
- {
- DPRINTK("Misaligned I/O request from domain %d", blkif->domid);
- goto cleanup_and_fail;
- }
-
- while ( (bio == NULL) ||
- (bio_add_page(bio,
- virt_to_page(MMAP_VADDR(pending_idx, i)),
- seg[i].nsec << 9,
- seg[i].buf & ~PAGE_MASK) == 0) )
- {
- bio = biolist[nbio++] = bio_alloc(GFP_KERNEL, nseg-i);
- if ( unlikely(bio == NULL) )
- {
- cleanup_and_fail:
- for ( i = 0; i < (nbio-1); i++ )
- bio_put(biolist[i]);
- fast_flush_area(pending_idx, nseg);
- goto bad_descriptor;
- }
+ extern void ll_rw_block(int rw, int nr, struct buffer_head * bhs[]);
+ int operation = (req->operation == BLKIF_OP_WRITE) ? WRITE : READ;
+ unsigned long fas = 0;
+ int i, pending_idx = pending_ring[MASK_PEND_IDX(pending_cons)];
+ pending_req_t *pending_req;
+ struct gnttab_map_grant_ref map[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+ struct phys_req preq;
+ struct {
+ unsigned long buf; unsigned int nsec;
+ } seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+ unsigned int nseg;
+ struct bio *bio = NULL, *biolist[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+ int nbio = 0;
+ request_queue_t *q;
+
+ /* Check that number of segments is sane. */
+ nseg = req->nr_segments;
+ if (unlikely(nseg == 0) ||
+ unlikely(nseg > BLKIF_MAX_SEGMENTS_PER_REQUEST)) {
+ DPRINTK("Bad number of segments in request (%d)\n", nseg);
+ goto bad_descriptor;
+ }
+
+ preq.dev = req->handle;
+ preq.sector_number = req->sector_number;
+ preq.nr_sects = 0;
+
+ for (i = 0; i < nseg; i++) {
+ fas = req->frame_and_sects[i];
+ seg[i].nsec = blkif_last_sect(fas) - blkif_first_sect(fas) + 1;
+
+ if (seg[i].nsec <= 0)
+ goto bad_descriptor;
+ preq.nr_sects += seg[i].nsec;
+
+ map[i].host_addr = MMAP_VADDR(pending_idx, i);
+ map[i].dom = blkif->domid;
+ map[i].ref = blkif_gref_from_fas(fas);
+ map[i].flags = GNTMAP_host_map;
+ if ( operation == WRITE )
+ map[i].flags |= GNTMAP_readonly;
+ }
+
+ BUG_ON(HYPERVISOR_grant_table_op(
+ GNTTABOP_map_grant_ref, map, nseg));
+
+ for (i = 0; i < nseg; i++) {
+ if (unlikely(map[i].handle < 0)) {
+ DPRINTK("invalid buffer -- could not remap it\n");
+ fast_flush_area(pending_idx, nseg);
+ goto bad_descriptor;
+ }
+
+ phys_to_machine_mapping[__pa(MMAP_VADDR(
+ pending_idx, i)) >> PAGE_SHIFT] =
+ FOREIGN_FRAME(map[i].dev_bus_addr >> PAGE_SHIFT);
+
+ pending_handle(pending_idx, i) = map[i].handle;
+ }
+
+ for (i = 0; i < nseg; i++) {
+ fas = req->frame_and_sects[i];
+ seg[i].buf = map[i].dev_bus_addr |
+ (blkif_first_sect(fas) << 9);
+ }
+
+ if (vbd_translate(&preq, blkif, operation) != 0) {
+ DPRINTK("access denied: %s of [%llu,%llu] on dev=%04x\n",
+ operation == READ ? "read" : "write",
+ preq.sector_number,
+ preq.sector_number + preq.nr_sects, preq.dev);
+ goto bad_descriptor;
+ }
+
+ pending_req = &pending_reqs[pending_idx];
+ pending_req->blkif = blkif;
+ pending_req->id = req->id;
+ pending_req->operation = operation;
+ pending_req->status = BLKIF_RSP_OKAY;
+ pending_req->nr_pages = nseg;
+
+ for (i = 0; i < nseg; i++) {
+ if (((int)preq.sector_number|(int)seg[i].nsec) &
+ ((bdev_hardsect_size(preq.bdev) >> 9) - 1)) {
+ DPRINTK("Misaligned I/O request from domain %d",
+ blkif->domid);
+ goto cleanup_and_fail;
+ }
+
+ while ((bio == NULL) ||
+ (bio_add_page(bio,
+ virt_to_page(MMAP_VADDR(pending_idx, i)),
+ seg[i].nsec << 9,
+ seg[i].buf & ~PAGE_MASK) == 0)) {
+ bio = biolist[nbio++] = bio_alloc(GFP_KERNEL, nseg-i);
+ if (unlikely(bio == NULL)) {
+ cleanup_and_fail:
+ for (i = 0; i < (nbio-1); i++)
+ bio_put(biolist[i]);
+ fast_flush_area(pending_idx, nseg);
+ goto bad_descriptor;
+ }

- bio->bi_bdev = preq.bdev;
- bio->bi_private = pending_req;
- bio->bi_end_io = end_block_io_op;
- bio->bi_sector = preq.sector_number;
- }
-
- preq.sector_number += seg[i].nsec;
- }
-
- if ( (q = bdev_get_queue(bio->bi_bdev)) != plugged_queue )
- {
- flush_plugged_queue();
- blk_get_queue(q);
- plugged_queue = q;
- }
-
- atomic_set(&pending_req->pendcnt, nbio);
- pending_cons++;
- blkif_get(blkif);
-
- for ( i = 0; i < nbio; i++ )
- submit_bio(operation, biolist[i]);
-
- return;
+ bio->bi_bdev = preq.bdev;
+ bio->bi_private = pending_req;
+ bio->bi_end_io = end_block_io_op;
+ bio->bi_sector = preq.sector_number;
+ }
+
+ preq.sector_number += seg[i].nsec;
+ }
+
+ if ((q = bdev_get_queue(bio->bi_bdev)) != plugged_queue) {
+ flush_plugged_queue();
+ blk_get_queue(q);
+ plugged_queue = q;
+ }
+
+ atomic_set(&pending_req->pendcnt, nbio);
+ pending_cons++;
+ blkif_get(blkif);
+
+ for (i = 0; i < nbio; i++)
+ submit_bio(operation, biolist[i]);
+
+ return;

bad_descriptor:
- make_response(blkif, req->id, req->operation, BLKIF_RSP_ERROR);
+ make_response(blkif, req->id, req->operation, BLKIF_RSP_ERROR);
}


@@ -475,66 +465,71 @@
static void make_response(blkif_t *blkif, unsigned long id,
unsigned short op, int st)
{
- blkif_response_t *resp;
- unsigned long flags;
- blkif_back_ring_t *blk_ring = &blkif->blk_ring;
-
- /* Place on the response ring for the relevant domain. */
- spin_lock_irqsave(&blkif->blk_ring_lock, flags);
- resp = RING_GET_RESPONSE(blk_ring, blk_ring->rsp_prod_pvt);
- resp->id = id;
- resp->operation = op;
- resp->status = st;
- wmb(); /* Ensure other side can see the response fields. */
- blk_ring->rsp_prod_pvt++;
- RING_PUSH_RESPONSES(blk_ring);
- spin_unlock_irqrestore(&blkif->blk_ring_lock, flags);
-
- /* Kick the relevant domain. */
- notify_via_evtchn(blkif->evtchn);
+ blkif_response_t *resp;
+ unsigned long flags;
+ blkif_back_ring_t *blk_ring = &blkif->blk_ring;
+
+ /* Place on the response ring for the relevant domain. */
+ spin_lock_irqsave(&blkif->blk_ring_lock, flags);
+ resp = RING_GET_RESPONSE(blk_ring, blk_ring->rsp_prod_pvt);
+ resp->id = id;
+ resp->operation = op;
+ resp->status = st;
+ wmb(); /* Ensure other side can see the response fields. */
+ blk_ring->rsp_prod_pvt++;
+ RING_PUSH_RESPONSES(blk_ring);
+ spin_unlock_irqrestore(&blkif->blk_ring_lock, flags);
+
+ /* Kick the relevant domain. */
+ notify_via_evtchn(blkif->evtchn);
}

void blkif_deschedule(blkif_t *blkif)
{
- remove_from_blkdev_list(blkif);
+ remove_from_blkdev_list(blkif);
}

static int __init blkif_init(void)
{
- int i;
- struct page *page;
-
- if ( !(xen_start_info->flags & SIF_INITDOMAIN) &&
- !(xen_start_info->flags & SIF_BLK_BE_DOMAIN) )
- return 0;
-
- blkif_interface_init();
-
- page = balloon_alloc_empty_page_range(MMAP_PAGES);
- BUG_ON(page == NULL);
- mmap_vstart = (unsigned long)pfn_to_kaddr(page_to_pfn(page));
-
- pending_cons = 0;
- pending_prod = MAX_PENDING_REQS;
- memset(pending_reqs, 0, sizeof(pending_reqs));
- for ( i = 0; i < MAX_PENDING_REQS; i++ )
- pending_ring[i] = i;
+ int i;
+ struct page *page;
+
+ if (!(xen_start_info->flags & SIF_INITDOMAIN) &&
+ !(xen_start_info->flags & SIF_BLK_BE_DOMAIN))
+ return 0;
+
+ blkif_interface_init();
+
+ page = balloon_alloc_empty_page_range(MMAP_PAGES);
+ BUG_ON(page == NULL);
+ mmap_vstart = (unsigned long)pfn_to_kaddr(page_to_pfn(page));
+
+ pending_cons = 0;
+ pending_prod = MAX_PENDING_REQS;
+ memset(pending_reqs, 0, sizeof(pending_reqs));
+ for (i = 0; i < MAX_PENDING_REQS; i++)
+ pending_ring[i] = i;

- spin_lock_init(&blkio_schedule_list_lock);
- INIT_LIST_HEAD(&blkio_schedule_list);
-
- if ( kernel_thread(blkio_schedule, 0, CLONE_FS | CLONE_FILES) < 0 )
- BUG();
-
- blkif_xenbus_init();
-
- memset( pending_grant_handles, BLKBACK_INVALID_HANDLE, MMAP_PAGES );
-
-#ifdef CONFIG_XEN_BLKDEV_TAP_BE
- printk(KERN_ALERT "NOTE: Blkif backend is running with tap support on!\n");
-#endif
-
- return 0;
+ spin_lock_init(&blkio_schedule_list_lock);
+ INIT_LIST_HEAD(&blkio_schedule_list);
+
+ BUG_ON(kernel_thread(blkio_schedule, 0, CLONE_FS | CLONE_FILES) < 0);
+
+ blkif_xenbus_init();
+
+ memset(pending_grant_handles, BLKBACK_INVALID_HANDLE, MMAP_PAGES);
+
+ return 0;
}

__initcall(blkif_init);
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r eba5afe9aa37 -r 10759a44ce3b linux-2.6-xen-sparse/drivers/xen/blkback/common.h
--- a/linux-2.6-xen-sparse/drivers/xen/blkback/common.h Thu Sep 22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blkback/common.h Thu Sep 22 15:12:14 2005
@@ -31,39 +31,39 @@
#endif

struct vbd {
- blkif_vdev_t handle; /* what the domain refers to this vbd as */
- unsigned char readonly; /* Non-zero -> read-only */
- unsigned char type; /* VDISK_xxx */
- u32 pdevice; /* phys device that this vbd maps to */
- struct block_device *bdev;
+ blkif_vdev_t handle; /* what the domain refers to this vbd as */
+ unsigned char readonly; /* Non-zero -> read-only */
+ unsigned char type; /* VDISK_xxx */
+ u32 pdevice; /* phys device that this vbd maps to */
+ struct block_device *bdev;
};

typedef struct blkif_st {
- /* Unique identifier for this interface. */
- domid_t domid;
- unsigned int handle;
- /* Physical parameters of the comms window. */
- unsigned int evtchn;
- unsigned int remote_evtchn;
- /* Comms information. */
- blkif_back_ring_t blk_ring;
- struct vm_struct *blk_ring_area;
- /* VBDs attached to this interface. */
- struct vbd vbd;
- /* Private fields. */
- enum { DISCONNECTED, CONNECTED } status;
+ /* Unique identifier for this interface. */
+ domid_t domid;
+ unsigned int handle;
+ /* Physical parameters of the comms window. */
+ unsigned int evtchn;
+ unsigned int remote_evtchn;
+ /* Comms information. */
+ blkif_back_ring_t blk_ring;
+ struct vm_struct *blk_ring_area;
+ /* VBDs attached to this interface. */
+ struct vbd vbd;
+ /* Private fields. */
+ enum { DISCONNECTED, CONNECTED } status;
#ifdef CONFIG_XEN_BLKDEV_TAP_BE
- /* Is this a blktap frontend */
- unsigned int is_blktap;
+ /* Is this a blktap frontend */
+ unsigned int is_blktap;
#endif
- struct list_head blkdev_list;
- spinlock_t blk_ring_lock;
- atomic_t refcnt;
+ struct list_head blkdev_list;
+ spinlock_t blk_ring_lock;
+ atomic_t refcnt;

- struct work_struct free_work;
+ struct work_struct free_work;

- u16 shmem_handle;
- grant_ref_t shmem_ref;
+ u16 shmem_handle;
+ grant_ref_t shmem_ref;
} blkif_t;

blkif_t *alloc_blkif(domid_t domid);
@@ -71,11 +71,11 @@
int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn);

#define blkif_get(_b) (atomic_inc(&(_b)->refcnt))
-#define blkif_put(_b) \
- do { \
- if ( atomic_dec_and_test(&(_b)->refcnt) ) \
- free_blkif_callback(_b); \
- } while (0)
+#define blkif_put(_b) \
+ do { \
+ if (atomic_dec_and_test(&(_b)->refcnt)) \
+ free_blkif_callback(_b); \
+ } while (0)

/* Create a vbd. */
int vbd_create(blkif_t *blkif, blkif_vdev_t vdevice, u32 pdevice,
@@ -87,10 +87,10 @@
unsigned long vbd_secsize(struct vbd *vbd);

struct phys_req {
- unsigned short dev;
- unsigned short nr_sects;
- struct block_device *bdev;
- blkif_sector_t sector_number;
+ unsigned short dev;
+ unsigned short nr_sects;
+ struct block_device *bdev;
+ blkif_sector_t sector_number;
};

int vbd_translate(struct phys_req *req, blkif_t *blkif, int operation);
@@ -104,3 +104,13 @@
irqreturn_t blkif_be_int(int irq, void *dev_id, struct pt_regs *regs);

#endif /* __BLKIF__BACKEND__COMMON_H__ */
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r eba5afe9aa37 -r 10759a44ce3b linux-2.6-xen-sparse/drivers/xen/blkback/interface.c
--- a/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c Thu Sep 22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c Thu Sep 22 15:12:14 2005
@@ -13,134 +13,144 @@

blkif_t *alloc_blkif(domid_t domid)
{
- blkif_t *blkif;
+ blkif_t *blkif;

- blkif = kmem_cache_alloc(blkif_cachep, GFP_KERNEL);
- if (!blkif)
- return ERR_PTR(-ENOMEM);
+ blkif = kmem_cache_alloc(blkif_cachep, GFP_KERNEL);
+ if (!blkif)
+ return ERR_PTR(-ENOMEM);

- memset(blkif, 0, sizeof(*blkif));
- blkif->domid = domid;
- blkif->status = DISCONNECTED;
- spin_lock_init(&blkif->blk_ring_lock);
- atomic_set(&blkif->refcnt, 1);
+ memset(blkif, 0, sizeof(*blkif));
+ blkif->domid = domid;
+ blkif->status = DISCONNECTED;
+ spin_lock_init(&blkif->blk_ring_lock);
+ atomic_set(&blkif->refcnt, 1);

- return blkif;
+ return blkif;
}

static int map_frontend_page(blkif_t *blkif, unsigned long shared_page)
{
- struct gnttab_map_grant_ref op;
+ struct gnttab_map_grant_ref op;

- op.host_addr = (unsigned long)blkif->blk_ring_area->addr;
- op.flags = GNTMAP_host_map;
- op.ref = shared_page;
- op.dom = blkif->domid;
+ op.host_addr = (unsigned long)blkif->blk_ring_area->addr;
+ op.flags = GNTMAP_host_map;
+ op.ref = shared_page;
+ op.dom = blkif->domid;

- lock_vm_area(blkif->blk_ring_area);
- BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1));
- unlock_vm_area(blkif->blk_ring_area);
+ lock_vm_area(blkif->blk_ring_area);
+ BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1));
+ unlock_vm_area(blkif->blk_ring_area);

- if (op.handle < 0) {
- DPRINTK(" Grant table operation failure !\n");
- return op.handle;
- }
+ if (op.handle < 0) {
+ DPRINTK(" Grant table operation failure !\n");
+ return op.handle;
+ }

- blkif->shmem_ref = shared_page;
- blkif->shmem_handle = op.handle;
+ blkif->shmem_ref = shared_page;
+ blkif->shmem_handle = op.handle;

- return 0;
+ return 0;
}

static void unmap_frontend_page(blkif_t *blkif)
{
- struct gnttab_unmap_grant_ref op;
+ struct gnttab_unmap_grant_ref op;

- op.host_addr = (unsigned long)blkif->blk_ring_area->addr;
- op.handle = blkif->shmem_handle;
- op.dev_bus_addr = 0;
+ op.host_addr = (unsigned long)blkif->blk_ring_area->addr;
+ op.handle = blkif->shmem_handle;
+ op.dev_bus_addr = 0;

- lock_vm_area(blkif->blk_ring_area);
- BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1));
- unlock_vm_area(blkif->blk_ring_area);
+ lock_vm_area(blkif->blk_ring_area);
+ BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1));
+ unlock_vm_area(blkif->blk_ring_area);
}

int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn)
{
- blkif_sring_t *sring;
- evtchn_op_t op = { .cmd = EVTCHNOP_bind_interdomain };
- int err;
+ blkif_sring_t *sring;
+ evtchn_op_t op = { .cmd = EVTCHNOP_bind_interdomain };
+ int err;

- BUG_ON(blkif->remote_evtchn);
+ BUG_ON(blkif->remote_evtchn);

- if ( (blkif->blk_ring_area = alloc_vm_area(PAGE_SIZE)) == NULL )
- return -ENOMEM;
+ if ( (blkif->blk_ring_area = alloc_vm_area(PAGE_SIZE)) == NULL )
+ return -ENOMEM;

- err = map_frontend_page(blkif, shared_page);
- if (err) {
- free_vm_area(blkif->blk_ring_area);
- return err;
- }
+ err = map_frontend_page(blkif, shared_page);
+ if (err) {
+ free_vm_area(blkif->blk_ring_area);
+ return err;
+ }

- op.u.bind_interdomain.dom1 = DOMID_SELF;
- op.u.bind_interdomain.dom2 = blkif->domid;
- op.u.bind_interdomain.port1 = 0;
- op.u.bind_interdomain.port2 = evtchn;
- err = HYPERVISOR_event_channel_op(&op);
- if (err) {
- unmap_frontend_page(blkif);
- free_vm_area(blkif->blk_ring_area);
- return err;
- }
+ op.u.bind_interdomain.dom1 = DOMID_SELF;
+ op.u.bind_interdomain.dom2 = blkif->domid;
+ op.u.bind_interdomain.port1 = 0;
+ op.u.bind_interdomain.port2 = evtchn;
+ err = HYPERVISOR_event_channel_op(&op);
+ if (err) {
+ unmap_frontend_page(blkif);
+ free_vm_area(blkif->blk_ring_area);
+ return err;
+ }

- blkif->evtchn = op.u.bind_interdomain.port1;
- blkif->remote_evtchn = evtchn;
+ blkif->evtchn = op.u.bind_interdomain.port1;
+ blkif->remote_evtchn = evtchn;

- sring = (blkif_sring_t *)blkif->blk_ring_area->addr;
- SHARED_RING_INIT(sring);
- BACK_RING_INIT(&blkif->blk_ring, sring, PAGE_SIZE);
+ sring = (blkif_sring_t *)blkif->blk_ring_area->addr;
+ SHARED_RING_INIT(sring);
+ BACK_RING_INIT(&blkif->blk_ring, sring, PAGE_SIZE);

- bind_evtchn_to_irqhandler(blkif->evtchn, blkif_be_int, 0, "blkif-backend",
- blkif);
- blkif->status = CONNECTED;
+ bind_evtchn_to_irqhandler(
+ blkif->evtchn, blkif_be_int, 0, "blkif-backend", blkif);
+ blkif->status = CONNECTED;

- return 0;
+ return 0;
}

static void free_blkif(void *arg)
{
- evtchn_op_t op = { .cmd = EVTCHNOP_close };
- blkif_t *blkif = (blkif_t *)arg;
+ evtchn_op_t op = { .cmd = EVTCHNOP_close };
+ blkif_t *blkif = (blkif_t *)arg;

- op.u.close.port = blkif->evtchn;
- op.u.close.dom = DOMID_SELF;
- HYPERVISOR_event_channel_op(&op);
- op.u.close.port = blkif->remote_evtchn;
- op.u.close.dom = blkif->domid;
- HYPERVISOR_event_channel_op(&op);
+ op.u.close.port = blkif->evtchn;
+ op.u.close.dom = DOMID_SELF;
+ HYPERVISOR_event_channel_op(&op);
+ op.u.close.port = blkif->remote_evtchn;
+ op.u.close.dom = blkif->domid;
+ HYPERVISOR_event_channel_op(&op);

- vbd_free(&blkif->vbd);
+ vbd_free(&blkif->vbd);

- if (blkif->evtchn)
- unbind_evtchn_from_irqhandler(blkif->evtchn, blkif);
+ if (blkif->evtchn)
+ unbind_evtchn_from_irqhandler(blkif->evtchn, blkif);

- if (blkif->blk_ring.sring) {
- unmap_frontend_page(blkif);
- free_vm_area(blkif->blk_ring_area);
- blkif->blk_ring.sring = NULL;
- }
+ if (blkif->blk_ring.sring) {
+ unmap_frontend_page(blkif);
+ free_vm_area(blkif->blk_ring_area);
+ blkif->blk_ring.sring = NULL;
+ }

- kmem_cache_free(blkif_cachep, blkif);
+ kmem_cache_free(blkif_cachep, blkif);
}

void free_blkif_callback(blkif_t *blkif)
{
- INIT_WORK(&blkif->free_work, free_blkif, (void *)blkif);
- schedule_work(&blkif->free_work);
+ INIT_WORK(&blkif->free_work, free_blkif, (void *)blkif);
+ schedule_work(&blkif->free_work);
}

void __init blkif_interface_init(void)
{
- blkif_cachep = kmem_cache_create("blkif_cache", sizeof(blkif_t),
- 0, 0, NULL, NULL);
+ blkif_cachep = kmem_cache_create("blkif_cache", sizeof(blkif_t),
+ 0, 0, NULL, NULL);
}
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r eba5afe9aa37 -r 10759a44ce3b linux-2.6-xen-sparse/drivers/xen/blkback/vbd.c
--- a/linux-2.6-xen-sparse/drivers/xen/blkback/vbd.c Thu Sep 22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blkback/vbd.c Thu Sep 22 15:12:14 2005
@@ -11,10 +11,10 @@

static inline dev_t vbd_map_devnum(u32 cookie)
{
- return MKDEV(BLKIF_MAJOR(cookie), BLKIF_MINOR(cookie));
+ return MKDEV(BLKIF_MAJOR(cookie), BLKIF_MINOR(cookie));
}
-#define vbd_sz(_v) ((_v)->bdev->bd_part ? \
- (_v)->bdev->bd_part->nr_sects : (_v)->bdev->bd_disk->capacity)
+#define vbd_sz(_v) ((_v)->bdev->bd_part ? \
+ (_v)->bdev->bd_part->nr_sects : (_v)->bdev->bd_disk->capacity)
#define bdev_put(_b) blkdev_put(_b)

unsigned long vbd_size(struct vbd *vbd)
@@ -35,63 +35,73 @@
int vbd_create(blkif_t *blkif, blkif_vdev_t handle,
u32 pdevice, int readonly)
{
- struct vbd *vbd;
+ struct vbd *vbd;

- vbd = &blkif->vbd;
- vbd->handle = handle;
- vbd->readonly = readonly;
- vbd->type = 0;
+ vbd = &blkif->vbd;
+ vbd->handle = handle;
+ vbd->readonly = readonly;
+ vbd->type = 0;

- vbd->pdevice = pdevice;
+ vbd->pdevice = pdevice;

- vbd->bdev = open_by_devnum(
- vbd_map_devnum(vbd->pdevice),
- vbd->readonly ? FMODE_READ : FMODE_WRITE);
- if ( IS_ERR(vbd->bdev) )
- {
- DPRINTK("vbd_creat: device %08x doesn't exist.\n", vbd->pdevice);
- return -ENOENT;
- }
+ vbd->bdev = open_by_devnum(
+ vbd_map_devnum(vbd->pdevice),
+ vbd->readonly ? FMODE_READ : FMODE_WRITE);
+ if (IS_ERR(vbd->bdev)) {
+ DPRINTK("vbd_creat: device %08x doesn't exist.\n",
+ vbd->pdevice);
+ return -ENOENT;
+ }

- if ( (vbd->bdev->bd_disk == NULL) )
- {
- DPRINTK("vbd_creat: device %08x doesn't exist.\n", vbd->pdevice);
- vbd_free(vbd);
- return -ENOENT;
- }
+ if (vbd->bdev->bd_disk == NULL) {
+ DPRINTK("vbd_creat: device %08x doesn't exist.\n",
+ vbd->pdevice);
+ vbd_free(vbd);
+ return -ENOENT;
+ }

- if ( vbd->bdev->bd_disk->flags & GENHD_FL_CD )
- vbd->type |= VDISK_CDROM;
- if ( vbd->bdev->bd_disk->flags & GENHD_FL_REMOVABLE )
- vbd->type |= VDISK_REMOVABLE;
+ if (vbd->bdev->bd_disk->flags & GENHD_FL_CD)
+ vbd->type |= VDISK_CDROM;
+ if (vbd->bdev->bd_disk->flags & GENHD_FL_REMOVABLE)
+ vbd->type |= VDISK_REMOVABLE;

- DPRINTK("Successful creation of handle=%04x (dom=%u)\n",
- handle, blkif->domid);
- return 0;
+ DPRINTK("Successful creation of handle=%04x (dom=%u)\n",
+ handle, blkif->domid);
+ return 0;
}

void vbd_free(struct vbd *vbd)
{
- if (vbd->bdev)
- bdev_put(vbd->bdev);
- vbd->bdev = NULL;
+ if (vbd->bdev)
+ bdev_put(vbd->bdev);
+ vbd->bdev = NULL;
}

int vbd_translate(struct phys_req *req, blkif_t *blkif, int operation)
{
- struct vbd *vbd = &blkif->vbd;
- int rc = -EACCES;
+ struct vbd *vbd = &blkif->vbd;
+ int rc = -EACCES;

- if ((operation == WRITE) && vbd->readonly)
- goto out;
+ if ((operation == WRITE) && vbd->readonly)
+ goto out;

- if (unlikely((req->sector_number + req->nr_sects) > vbd_sz(vbd)))
- goto out;
+ if (unlikely((req->sector_number + req->nr_sects) > vbd_sz(vbd)))
+ goto out;

- req->dev = vbd->pdevice;
- req->bdev = vbd->bdev;
- rc = 0;
+ req->dev = vbd->pdevice;
+ req->bdev = vbd->bdev;
+ rc = 0;

out:
- return rc;
+ return rc;
}
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r eba5afe9aa37 -r 10759a44ce3b linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c
--- a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c Thu Sep 22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c Thu Sep 22 15:12:14 2005
@@ -124,7 +124,7 @@

return;

-abort:
+ abort:
xenbus_transaction_end(1);
}

@@ -278,3 +278,13 @@
{
xenbus_register_backend(&blkback);
}
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r eba5afe9aa37 -r 10759a44ce3b linux-2.6-xen-sparse/drivers/xen/blkfront/block.h
--- a/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h Thu Sep 22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h Thu Sep 22 15:12:14 2005
@@ -146,4 +146,15 @@
int xlvbd_add(blkif_sector_t capacity, int device,
u16 vdisk_info, u16 sector_size, struct blkfront_info *info);
void xlvbd_del(struct blkfront_info *info);
+
#endif /* __XEN_DRIVERS_BLOCK_H__ */
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r eba5afe9aa37 -r 10759a44ce3b linux-2.6-xen-sparse/drivers/xen/blkfront/vbd.c
--- a/linux-2.6-xen-sparse/drivers/xen/blkfront/vbd.c Thu Sep 22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/vbd.c Thu Sep 22 15:12:14 2005
@@ -65,7 +65,7 @@
};

static struct xlbd_major_info *major_info[NUM_IDE_MAJORS + NUM_SCSI_MAJORS +
- NUM_VBD_MAJORS];
+ NUM_VBD_MAJORS];

#define XLBD_MAJOR_IDE_START 0
#define XLBD_MAJOR_SCSI_START (NUM_IDE_MAJORS)
@@ -309,3 +309,13 @@

bdput(bd);
}
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r eba5afe9aa37 -r 10759a44ce3b linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c
--- a/linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c Thu Sep 22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c Thu Sep 22 15:12:14 2005
@@ -4,7 +4,6 @@
* This is a modified version of the block backend driver that remaps requests
* to a user-space memory region. It is intended to be used to write
* application-level servers that provide block interfaces to client VMs.
- *
*/

#include <linux/kernel.h>
@@ -67,20 +66,19 @@

static inline int BLKTAP_MODE_VALID(unsigned long arg)
{
- return (
- ( arg == BLKTAP_MODE_PASSTHROUGH ) ||
- ( arg == BLKTAP_MODE_INTERCEPT_FE ) ||
- ( arg == BLKTAP_MODE_INTERPOSE ) );
+ return ((arg == BLKTAP_MODE_PASSTHROUGH ) ||
+ (arg == BLKTAP_MODE_INTERCEPT_FE) ||
+ (arg == BLKTAP_MODE_INTERPOSE ));
/*
- return (
- ( arg == BLKTAP_MODE_PASSTHROUGH ) ||
- ( arg == BLKTAP_MODE_INTERCEPT_FE ) ||
- ( arg == BLKTAP_MODE_INTERCEPT_BE ) ||
- ( arg == BLKTAP_MODE_INTERPOSE ) ||
- ( (arg & ~BLKTAP_MODE_COPY_FE_PAGES) == BLKTAP_MODE_COPY_FE ) ||
- ( (arg & ~BLKTAP_MODE_COPY_BE_PAGES) == BLKTAP_MODE_COPY_BE ) ||
- ( (arg & ~BLKTAP_MODE_COPY_BOTH_PAGES) == BLKTAP_MODE_COPY_BOTH )
- );
+ return (
+ ( arg == BLKTAP_MODE_PASSTHROUGH ) ||
+ ( arg == BLKTAP_MODE_INTERCEPT_FE ) ||
+ ( arg == BLKTAP_MODE_INTERCEPT_BE ) ||
+ ( arg == BLKTAP_MODE_INTERPOSE ) ||
+ ( (arg & ~BLKTAP_MODE_COPY_FE_PAGES) == BLKTAP_MODE_COPY_FE ) ||
+ ( (arg & ~BLKTAP_MODE_COPY_BE_PAGES) == BLKTAP_MODE_COPY_BE ) ||
+ ( (arg & ~BLKTAP_MODE_COPY_BOTH_PAGES) == BLKTAP_MODE_COPY_BOTH )
+ );
*/
}

@@ -110,14 +108,12 @@
unsigned long rings_vstart; /* start of mmaped vma */
unsigned long user_vstart; /* start of user mappings */

-#define MMAP_PAGES \
- (MAX_PENDING_REQS * BLKIF_MAX_SEGMENTS_PER_REQUEST)
-#define MMAP_VADDR(_start, _req,_seg) \
- (_start + \
- ((_req) * BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE) + \
- ((_seg) * PAGE_SIZE))
-
-
+#define MMAP_PAGES \
+ (MAX_PENDING_REQS * BLKIF_MAX_SEGMENTS_PER_REQUEST)
+#define MMAP_VADDR(_start, _req,_seg) \
+ (_start + \
+ ((_req) * BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE) + \
+ ((_seg) * PAGE_SIZE))

/*
* Each outstanding request that we've passed to the lower device layers has a
@@ -126,12 +122,12 @@
* response queued for it, with the saved 'id' passed back.
*/
typedef struct {
- blkif_t *blkif;
- unsigned long id;
- int nr_pages;
- atomic_t pendcnt;
- unsigned short operation;
- int status;
+ blkif_t *blkif;
+ unsigned long id;
+ int nr_pages;
+ atomic_t pendcnt;
+ unsigned short operation;
+ int status;
} pending_req_t;

/*
@@ -156,17 +152,17 @@

static inline unsigned long MAKE_ID(domid_t fe_dom, PEND_RING_IDX idx)
{
- return ( (fe_dom << 16) | MASK_PEND_IDX(idx) );
+ return ((fe_dom << 16) | MASK_PEND_IDX(idx));
}

extern inline PEND_RING_IDX ID_TO_IDX(unsigned long id)
{
- return (PEND_RING_IDX)( id & 0x0000ffff );
+ return (PEND_RING_IDX)(id & 0x0000ffff);
}

extern inline domid_t ID_TO_DOM(unsigned long id)
{
- return (domid_t)(id >> 16);
+ return (domid_t)(id >> 16);
}


@@ -181,8 +177,8 @@
*/
struct grant_handle_pair
{
- u16 kernel;
- u16 user;
+ u16 kernel;
+ u16 user;
};
static struct grant_handle_pair pending_grant_handles[MMAP_PAGES];
#define pending_handle(_idx, _i) \
@@ -199,21 +195,20 @@
*/

static struct page *blktap_nopage(struct vm_area_struct *vma,
- unsigned long address,
- int *type)
-{
- /*
- * if the page has not been mapped in by the driver then generate
- * a SIGBUS to the domain.
- */
-
- force_sig(SIGBUS, current);
-
- return 0;
+ unsigned long address,
+ int *type)
+{
+ /*
+ * if the page has not been mapped in by the driver then generate
+ * a SIGBUS to the domain.
+ */
+ force_sig(SIGBUS, current);
+
+ return 0;
}

struct vm_operations_struct blktap_vm_ops = {
- nopage: blktap_nopage,
+ nopage: blktap_nopage,
};

/******************************************************************
@@ -222,44 +217,45 @@

static int blktap_open(struct inode *inode, struct file *filp)
{
- blkif_sring_t *sring;
+ blkif_sring_t *sring;
+
+ if (test_and_set_bit(0, &blktap_dev_inuse))
+ return -EBUSY;

- if ( test_and_set_bit(0, &blktap_dev_inuse) )
- return -EBUSY;
+ /* Allocate the fe ring. */
+ sring = (blkif_sring_t *)get_zeroed_page(GFP_KERNEL);
+ if (sring == NULL)
+ goto fail_nomem;
+
+ SetPageReserved(virt_to_page(sring));

- /* Allocate the fe ring. */
- sring = (blkif_sring_t *)get_zeroed_page(GFP_KERNEL);
- if (sring == NULL)
- goto fail_nomem;
-
- SetPageReserved(virt_to_page(sring));
-
- SHARED_RING_INIT(sring);
- FRONT_RING_INIT(&blktap_ufe_ring, sring, PAGE_SIZE);
-
- return 0;
+ SHARED_RING_INIT(sring);
+ FRONT_RING_INIT(&blktap_ufe_ring, sring, PAGE_SIZE);
+
+ return 0;

fail_nomem:
- return -ENOMEM;
+ return -ENOMEM;
}

static int blktap_release(struct inode *inode, struct file *filp)
{
- blktap_dev_inuse = 0;
- blktap_ring_ok = 0;
-
- /* Free the ring page. */
- ClearPageReserved(virt_to_page(blktap_ufe_ring.sring));
- free_page((unsigned long) blktap_ufe_ring.sring);
-
- /* Clear any active mappings and free foreign map table */
- if (blktap_vma != NULL) {
- zap_page_range(blktap_vma, blktap_vma->vm_start,
- blktap_vma->vm_end - blktap_vma->vm_start, NULL);
- blktap_vma = NULL;
- }
-
- return 0;
+ blktap_dev_inuse = 0;
+ blktap_ring_ok = 0;
+
+ /* Free the ring page. */
+ ClearPageReserved(virt_to_page(blktap_ufe_ring.sring));
+ free_page((unsigned long) blktap_ufe_ring.sring);
+
+ /* Clear any active mappings and free foreign map table */
+ if (blktap_vma != NULL) {
+ zap_page_range(
+ blktap_vma, blktap_vma->vm_start,
+ blktap_vma->vm_end - blktap_vma->vm_start, NULL);
+ blktap_vma = NULL;
+ }
+
+ return 0;
}


@@ -283,128 +279,124 @@
*/
static int blktap_mmap(struct file *filp, struct vm_area_struct *vma)
{
- int size;
- struct page **map;
- int i;
-
- DPRINTK(KERN_ALERT "blktap mmap (%lx, %lx)\n",
- vma->vm_start, vma->vm_end);
-
- vma->vm_flags |= VM_RESERVED;
- vma->vm_ops = &blktap_vm_ops;
-
- size = vma->vm_end - vma->vm_start;
- if ( size != ( (MMAP_PAGES + RING_PAGES) << PAGE_SHIFT ) ) {
- printk(KERN_INFO
- "blktap: you _must_ map exactly %d pages!\n",
- MMAP_PAGES + RING_PAGES);
- return -EAGAIN;
- }
-
- size >>= PAGE_SHIFT;
- DPRINTK(KERN_INFO "blktap: 2 rings + %d pages.\n", size-1);
+ int size;
+ struct page **map;
+ int i;
+
+ DPRINTK(KERN_ALERT "blktap mmap (%lx, %lx)\n",
+ vma->vm_start, vma->vm_end);
+
+ vma->vm_flags |= VM_RESERVED;
+ vma->vm_ops = &blktap_vm_ops;
+
+ size = vma->vm_end - vma->vm_start;
+ if (size != ((MMAP_PAGES + RING_PAGES) << PAGE_SHIFT)) {
+ printk(KERN_INFO
+ "blktap: you _must_ map exactly %d pages!\n",
+ MMAP_PAGES + RING_PAGES);
+ return -EAGAIN;
+ }
+
+ size >>= PAGE_SHIFT;
+ DPRINTK(KERN_INFO "blktap: 2 rings + %d pages.\n", size-1);

- rings_vstart = vma->vm_start;
- user_vstart = rings_vstart + (RING_PAGES << PAGE_SHIFT);
+ rings_vstart = vma->vm_start;
+ user_vstart = rings_vstart + (RING_PAGES << PAGE_SHIFT);

- /* Map the ring pages to the start of the region and reserve it. */
-
- /* not sure if I really need to do this... */
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-
- if (remap_pfn_range(vma, vma->vm_start,
- __pa(blktap_ufe_ring.sring) >> PAGE_SHIFT,
- PAGE_SIZE, vma->vm_page_prot))
- {
- WPRINTK("Mapping user ring failed!\n");
- goto fail;
- }
-
- /* Mark this VM as containing foreign pages, and set up mappings. */
- map = kmalloc(((vma->vm_end - vma->vm_start) >> PAGE_SHIFT)
- * sizeof(struct page_struct*),
- GFP_KERNEL);
- if (map == NULL)
- {
- WPRINTK("Couldn't alloc VM_FOREIGH map.\n");
- goto fail;
- }
-
- for (i=0; i<((vma->vm_end - vma->vm_start) >> PAGE_SHIFT); i++)
- map[i] = NULL;
+ /* Map the ring pages to the start of the region and reserve it. */
+
+ /* not sure if I really need to do this... */
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+ if (remap_pfn_range(vma, vma->vm_start,
+ __pa(blktap_ufe_ring.sring) >> PAGE_SHIFT,
+ PAGE_SIZE, vma->vm_page_prot)) {
+ WPRINTK("Mapping user ring failed!\n");
+ goto fail;
+ }
+
+ /* Mark this VM as containing foreign pages, and set up mappings. */
+ map = kmalloc(((vma->vm_end - vma->vm_start) >> PAGE_SHIFT)
+ * sizeof(struct page_struct*),
+ GFP_KERNEL);
+ if (map == NULL) {
+ WPRINTK("Couldn't alloc VM_FOREIGH map.\n");
+ goto fail;
+ }
+
+ for (i = 0; i < ((vma->vm_end - vma->vm_start) >> PAGE_SHIFT); i++)
+ map[i] = NULL;

- vma->vm_private_data = map;
- vma->vm_flags |= VM_FOREIGN;
-
- blktap_vma = vma;
- blktap_ring_ok = 1;
-
- return 0;
+ vma->vm_private_data = map;
+ vma->vm_flags |= VM_FOREIGN;
+
+ blktap_vma = vma;
+ blktap_ring_ok = 1;
+
+ return 0;
fail:
- /* Clear any active mappings. */
- zap_page_range(vma, vma->vm_start,
- vma->vm_end - vma->vm_start, NULL);
-
- return -ENOMEM;
+ /* Clear any active mappings. */
+ zap_page_range(vma, vma->vm_start,
+ vma->vm_end - vma->vm_start, NULL);
+
+ return -ENOMEM;
}

static int blktap_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- switch(cmd) {
- case BLKTAP_IOCTL_KICK_FE: /* There are fe messages to process. */
- return blktap_read_ufe_ring();
-
- case BLKTAP_IOCTL_SETMODE:
- if (BLKTAP_MODE_VALID(arg)) {
- blktap_mode = arg;
- /* XXX: may need to flush rings here. */
- printk(KERN_INFO "blktap: set mode to %lx\n", arg);
- return 0;
- }
- case BLKTAP_IOCTL_PRINT_IDXS:
+ switch(cmd) {
+ case BLKTAP_IOCTL_KICK_FE: /* There are fe messages to process. */
+ return blktap_read_ufe_ring();
+
+ case BLKTAP_IOCTL_SETMODE:
+ if (BLKTAP_MODE_VALID(arg)) {
+ blktap_mode = arg;
+ /* XXX: may need to flush rings here. */
+ printk(KERN_INFO "blktap: set mode to %lx\n", arg);
+ return 0;
+ }
+ case BLKTAP_IOCTL_PRINT_IDXS:
{
- //print_fe_ring_idxs();
- WPRINTK("User Rings: \n-----------\n");
- WPRINTK("UF: rsp_cons: %2d, req_prod_prv: %2d "
- "| req_prod: %2d, rsp_prod: %2d\n",
- blktap_ufe_ring.rsp_cons,
- blktap_ufe_ring.req_prod_pvt,
- blktap_ufe_ring.sring->req_prod,
- blktap_ufe_ring.sring->rsp_prod);
+ //print_fe_ring_idxs();
+ WPRINTK("User Rings: \n-----------\n");
+ WPRINTK("UF: rsp_cons: %2d, req_prod_prv: %2d "
+ "| req_prod: %2d, rsp_prod: %2d\n",
+ blktap_ufe_ring.rsp_cons,
+ blktap_ufe_ring.req_prod_pvt,
+ blktap_ufe_ring.sring->req_prod,
+ blktap_ufe_ring.sring->rsp_prod);

}
- }
- return -ENOIOCTLCMD;
+ }
+ return -ENOIOCTLCMD;
}

static unsigned int blktap_poll(struct file *file, poll_table *wait)
{
- poll_wait(file, &blktap_wait, wait);
- if ( RING_HAS_UNPUSHED_REQUESTS(&blktap_ufe_ring) )
- {
- flush_tlb_all();
-
- RING_PUSH_REQUESTS(&blktap_ufe_ring);
- return POLLIN | POLLRDNORM;
- }
-
- return 0;
+ poll_wait(file, &blktap_wait, wait);
+ if (RING_HAS_UNPUSHED_REQUESTS(&blktap_ufe_ring)) {
+ flush_tlb_all();
+ RING_PUSH_REQUESTS(&blktap_ufe_ring);
+ return POLLIN | POLLRDNORM;
+ }
+
+ return 0;
}

void blktap_kick_user(void)
{
- /* blktap_ring->req_prod = blktap_req_prod; */
- wake_up_interruptible(&blktap_wait);
+ /* blktap_ring->req_prod = blktap_req_prod; */
+ wake_up_interruptible(&blktap_wait);
}

static struct file_operations blktap_fops = {
- owner: THIS_MODULE,
- poll: blktap_poll,
- ioctl: blktap_ioctl,
- open: blktap_open,
- release: blktap_release,
- mmap: blktap_mmap,
+ owner: THIS_MODULE,
+ poll: blktap_poll,
+ ioctl: blktap_ioctl,
+ open: blktap_open,
+ release: blktap_release,
+ mmap: blktap_mmap,
};


@@ -417,44 +409,44 @@

static void fast_flush_area(int idx, int nr_pages)
{
- struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST*2];
- unsigned int i, op = 0;
- struct grant_handle_pair *handle;
- unsigned long ptep;
-
- for (i=0; i<nr_pages; i++)
- {
- handle = &pending_handle(idx, i);
- if (!BLKTAP_INVALID_HANDLE(handle))
- {
-
- unmap[op].host_addr = MMAP_VADDR(mmap_vstart, idx, i);
- unmap[op].dev_bus_addr = 0;
- unmap[op].handle = handle->kernel;
- op++;
-
- if (create_lookup_pte_addr(blktap_vma->vm_mm,
- MMAP_VADDR(user_vstart, idx, i),
- &ptep) !=0) {
- DPRINTK("Couldn't get a pte addr!\n");
- return;
- }
- unmap[op].host_addr = ptep;
- unmap[op].dev_bus_addr = 0;
- unmap[op].handle = handle->user;
- op++;
+ struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST*2];
+ unsigned int i, op = 0;
+ struct grant_handle_pair *handle;
+ unsigned long ptep;
+
+ for ( i = 0; i < nr_pages; i++)
+ {
+ handle = &pending_handle(idx, i);
+ if (BLKTAP_INVALID_HANDLE(handle))
+ continue;
+
+ unmap[op].host_addr = MMAP_VADDR(mmap_vstart, idx, i);
+ unmap[op].dev_bus_addr = 0;
+ unmap[op].handle = handle->kernel;
+ op++;
+
+ if (create_lookup_pte_addr(
+ blktap_vma->vm_mm,
+ MMAP_VADDR(user_vstart, idx, i),
+ &ptep) !=0) {
+ DPRINTK("Couldn't get a pte addr!\n");
+ return;
+ }
+ unmap[op].host_addr = ptep;
+ unmap[op].dev_bus_addr = 0;
+ unmap[op].handle = handle->user;
+ op++;

- BLKTAP_INVALIDATE_HANDLE(handle);
- }
- }
- if ( unlikely(HYPERVISOR_grant_table_op(
- GNTTABOP_unmap_grant_ref, unmap, op)))
- BUG();
-
- if (blktap_vma != NULL)
- zap_page_range(blktap_vma,
- MMAP_VADDR(user_vstart, idx, 0),
- nr_pages << PAGE_SHIFT, NULL);
+ BLKTAP_INVALIDATE_HANDLE(handle);
+ }
+
+ BUG_ON(HYPERVISOR_grant_table_op(
+ GNTTABOP_unmap_grant_ref, unmap, op));
+
+ if (blktap_vma != NULL)
+ zap_page_range(blktap_vma,
+ MMAP_VADDR(user_vstart, idx, 0),
+ nr_pages << PAGE_SHIFT, NULL);
}

/******************************************************************
@@ -466,34 +458,38 @@

static int __on_blkdev_list(blkif_t *blkif)
{
- return blkif->blkdev_list.next != NULL;
+ return blkif->blkdev_list.next != NULL;
}

static void remove_from_blkdev_list(blkif_t *blkif)
{
- unsigned long flags;
- if ( !__on_blkdev_list(blkif) ) return;
- spin_lock_irqsave(&blkio_schedule_list_lock, flags);
- if ( __on_blkdev_list(blkif) )
- {
- list_del(&blkif->blkdev_list);
- blkif->blkdev_list.next = NULL;
- blkif_put(blkif);
- }
- spin_unlock_irqrestore(&blkio_schedule_list_lock, flags);
+ unsigned long flags;
+
+ if (!__on_blkdev_list(blkif))
+ return;
+
+ spin_lock_irqsave(&blkio_schedule_list_lock, flags);
+ if (__on_blkdev_list(blkif)) {
+ list_del(&blkif->blkdev_list);
+ blkif->blkdev_list.next = NULL;
+ blkif_put(blkif);
+ }
+ spin_unlock_irqrestore(&blkio_schedule_list_lock, flags);
}

static void add_to_blkdev_list_tail(blkif_t *blkif)
{
- unsigned long flags;
- if ( __on_blkdev_list(blkif) ) return;
- spin_lock_irqsave(&blkio_schedule_list_lock, flags);
- if ( !__on_blkdev_list(blkif) && (blkif->status == CONNECTED) )
- {
- list_add_tail(&blkif->blkdev_list, &blkio_schedule_list);
- blkif_get(blkif);
- }
- spin_unlock_irqrestore(&blkio_schedule_list_lock, flags);
+ unsigned long flags;
+
+ if (__on_blkdev_list(blkif))
+ return;
+
+ spin_lock_irqsave(&blkio_schedule_list_lock, flags);
+ if (!__on_blkdev_list(blkif) && (blkif->status == CONNECTED)) {
+ list_add_tail(&blkif->blkdev_list, &blkio_schedule_list);
+ blkif_get(blkif);
+ }
+ spin_unlock_irqrestore(&blkio_schedule_list_lock, flags);
}


@@ -505,51 +501,50 @@

static int blkio_schedule(void *arg)
{
- DECLARE_WAITQUEUE(wq, current);
-
- blkif_t *blkif;
- struct list_head *ent;
-
- daemonize("xenblkd");
-
- for ( ; ; )
- {
- /* Wait for work to do. */
- add_wait_queue(&blkio_schedule_wait, &wq);
- set_current_state(TASK_INTERRUPTIBLE);
- if ( (NR_PENDING_REQS == MAX_PENDING_REQS) ||
- list_empty(&blkio_schedule_list) )
- schedule();
- __set_current_state(TASK_RUNNING);
- remove_wait_queue(&blkio_schedule_wait, &wq);
-
- /* Queue up a batch of requests. */
- while ( (NR_PENDING_REQS < MAX_PENDING_REQS) &&
- !list_empty(&blkio_schedule_list) )
- {
- ent = blkio_schedule_list.next;
- blkif = list_entry(ent, blkif_t, blkdev_list);
- blkif_get(blkif);
- remove_from_blkdev_list(blkif);
- if ( do_block_io_op(blkif, BATCH_PER_DOMAIN) )
- add_to_blkdev_list_tail(blkif);
- blkif_put(blkif);
- }
- }
+ DECLARE_WAITQUEUE(wq, current);
+
+ blkif_t *blkif;
+ struct list_head *ent;
+
+ daemonize("xenblkd");
+
+ for (;;) {
+ /* Wait for work to do. */
+ add_wait_queue(&blkio_schedule_wait, &wq);
+ set_current_state(TASK_INTERRUPTIBLE);
+ if ((NR_PENDING_REQS == MAX_PENDING_REQS) ||
+ list_empty(&blkio_schedule_list))
+ schedule();
+ __set_current_state(TASK_RUNNING);
+ remove_wait_queue(&blkio_schedule_wait, &wq);
+
+ /* Queue up a batch of requests. */
+ while ((NR_PENDING_REQS < MAX_PENDING_REQS) &&
+ !list_empty(&blkio_schedule_list)) {
+ ent = blkio_schedule_list.next;
+ blkif = list_entry(ent, blkif_t, blkdev_list);
+ blkif_get(blkif);
+ remove_from_blkdev_list(blkif);
+ if (do_block_io_op(blkif, BATCH_PER_DOMAIN))
+ add_to_blkdev_list_tail(blkif);
+ blkif_put(blkif);
+ }
+ }
}

static void maybe_trigger_blkio_schedule(void)
{
- /*
- * Needed so that two processes, who together make the following predicate
- * true, don't both read stale values and evaluate the predicate
- * incorrectly. Incredibly unlikely to stall the scheduler on x86, but...
- */
- smp_mb();
-
- if ( (NR_PENDING_REQS < (MAX_PENDING_REQS/2)) &&
- !list_empty(&blkio_schedule_list) )
- wake_up(&blkio_schedule_wait);
+ /*
+ * Needed so that two processes, who together make the following
+ * predicate true, don't both read stale values and evaluate the
+ * predicate incorrectly. Incredibly unlikely to stall the scheduler
+ * on the x86, but...
+ */
+ smp_mb();
+
+ if ((NR_PENDING_REQS < (MAX_PENDING_REQS/2)) &&
+ !list_empty(&blkio_schedule_list))
+ wake_up(&blkio_schedule_wait);
}


@@ -561,54 +556,53 @@

static int blktap_read_ufe_ring(void)
{
- /* This is called to read responses from the UFE ring. */
-
- RING_IDX i, j, rp;
- blkif_response_t *resp;
- blkif_t *blkif;
- int pending_idx;
- pending_req_t *pending_req;
- unsigned long flags;
-
- /* if we are forwarding from UFERring to FERing */
- if (blktap_mode & BLKTAP_MODE_INTERCEPT_FE) {
-
- /* for each outstanding message on the UFEring */
- rp = blktap_ufe_ring.sring->rsp_prod;
- rmb();
+ /* This is called to read responses from the UFE ring. */
+
+ RING_IDX i, j, rp;
+ blkif_response_t *resp;
+ blkif_t *blkif;
+ int pending_idx;
+ pending_req_t *pending_req;
+ unsigned long flags;
+
+ /* if we are forwarding from UFERring to FERing */
+ if (blktap_mode & BLKTAP_MODE_INTERCEPT_FE) {
+
+ /* for each outstanding message on the UFEring */
+ rp = blktap_ufe_ring.sring->rsp_prod;
+ rmb();

- for ( i = blktap_ufe_ring.rsp_cons; i != rp; i++ )
- {
- resp = RING_GET_RESPONSE(&blktap_ufe_ring, i);
- pending_idx = MASK_PEND_IDX(ID_TO_IDX(resp->id));
- pending_req = &pending_reqs[pending_idx];
+ for (i = blktap_ufe_ring.rsp_cons; i != rp; i++) {
+ resp = RING_GET_RESPONSE(&blktap_ufe_ring, i);
+ pending_idx = MASK_PEND_IDX(ID_TO_IDX(resp->id));
+ pending_req = &pending_reqs[pending_idx];

- blkif = pending_req->blkif;
- for (j = 0; j < pending_req->nr_pages; j++) {
- unsigned long vaddr;
- struct page **map = blktap_vma->vm_private_data;
- int offset;
-
- vaddr = MMAP_VADDR(user_vstart, pending_idx, j);
- offset = (vaddr - blktap_vma->vm_start) >> PAGE_SHIFT;
-
- //ClearPageReserved(virt_to_page(vaddr));
- ClearPageReserved((struct page *)map[offset]);
- map[offset] = NULL;
- }
-
- fast_flush_area(pending_idx, pending_req->nr_pages);
- make_response(blkif, pending_req->id, resp->operation,
- resp->status);
- blkif_put(pending_req->blkif);
- spin_lock_irqsave(&pend_prod_lock, flags);
- pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx;
- spin_unlock_irqrestore(&pend_prod_lock, flags);
- }
- blktap_ufe_ring.rsp_cons = i;
- maybe_trigger_blkio_schedule();
- }
- return 0;
+ blkif = pending_req->blkif;
+ for (j = 0; j < pending_req->nr_pages; j++) {
+ unsigned long vaddr;
+ struct page **map = blktap_vma->vm_private_data;
+ int offset;
+
+ vaddr = MMAP_VADDR(user_vstart, pending_idx, j);
+ offset = (vaddr - blktap_vma->vm_start) >> PAGE_SHIFT;
+
+ //ClearPageReserved(virt_to_page(vaddr));
+ ClearPageReserved((struct page *)map[offset]);
+ map[offset] = NULL;
+ }
+
+ fast_flush_area(pending_idx, pending_req->nr_pages);
+ make_response(blkif, pending_req->id, resp->operation,
+ resp->status);
+ blkif_put(pending_req->blkif);
+ spin_lock_irqsave(&pend_prod_lock, flags);
+ pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx;
+ spin_unlock_irqrestore(&pend_prod_lock, flags);
+ }
+ blktap_ufe_ring.rsp_cons = i;
+ maybe_trigger_blkio_schedule();
+ }
+ return 0;
}


@@ -618,10 +612,10 @@

irqreturn_t blkif_be_int(int irq, void *dev_id, struct pt_regs *regs)
{
- blkif_t *blkif = dev_id;
- add_to_blkdev_list_tail(blkif);
- maybe_trigger_blkio_schedule();
- return IRQ_HANDLED;
+ blkif_t *blkif = dev_id;
+ add_to_blkdev_list_tail(blkif);
+ maybe_trigger_blkio_schedule();
+ return IRQ_HANDLED;
}


@@ -632,199 +626,194 @@

static int do_block_io_op(blkif_t *blkif, int max_to_do)
{
- blkif_back_ring_t *blk_ring = &blkif->blk_ring;
- blkif_request_t *req;
- RING_IDX i, rp;
- int more_to_do = 0;
+ blkif_back_ring_t *blk_ring = &blkif->blk_ring;
+ blkif_request_t *req;
+ RING_IDX i, rp;
+ int more_to_do = 0;

- rp = blk_ring->sring->req_prod;
- rmb(); /* Ensure we see queued requests up to 'rp'. */
-
- for ( i = blk_ring->req_cons;
- (i != rp) && !RING_REQUEST_CONS_OVERFLOW(blk_ring, i);
- i++ )
- {
- if ( (max_to_do-- == 0) || (NR_PENDING_REQS == MAX_PENDING_REQS) )
- {
- more_to_do = 1;
- break;
- }
+ rp = blk_ring->sring->req_prod;
+ rmb(); /* Ensure we see queued requests up to 'rp'. */
+
+ for (i = blk_ring->req_cons;
+ (i != rp) && !RING_REQUEST_CONS_OVERFLOW(blk_ring, i);
+ i++ ) {
+ if ((max_to_do-- == 0) ||
+ (NR_PENDING_REQS == MAX_PENDING_REQS)) {
+ more_to_do = 1;
+ break;
+ }

- req = RING_GET_REQUEST(blk_ring, i);
- switch ( req->operation )
- {
- case BLKIF_OP_READ:
- case BLKIF_OP_WRITE:
- dispatch_rw_block_io(blkif, req);
- break;
-
- default:
- DPRINTK("error: unknown block io operation [%d]\n",
- req->operation);
- make_response(blkif, req->id, req->operation, BLKIF_RSP_ERROR);
- break;
- }
- }
-
- blk_ring->req_cons = i;
- blktap_kick_user();
-
- return more_to_do;
+ req = RING_GET_REQUEST(blk_ring, i);
+ switch (req->operation) {
+ case BLKIF_OP_READ:
+ case BLKIF_OP_WRITE:
+ dispatch_rw_block_io(blkif, req);
+ break;
+
+ default:
+ DPRINTK("error: unknown block io operation [%d]\n",
+ req->operation);
+ make_response(blkif, req->id, req->operation,
+ BLKIF_RSP_ERROR);
+ break;
+ }
+ }
+
+ blk_ring->req_cons = i;
+ blktap_kick_user();
+
+ return more_to_do;
}

static void dispatch_rw_block_io(blkif_t *blkif, blkif_request_t *req)
{
- blkif_request_t *target;
- int i, pending_idx = pending_ring[MASK_PEND_IDX(pending_cons)];
- pending_req_t *pending_req;
- struct gnttab_map_grant_ref map[BLKIF_MAX_SEGMENTS_PER_REQUEST*2];
- int op, ret;
- unsigned int nseg;
-
- /* Check that number of segments is sane. */
- nseg = req->nr_segments;
- if ( unlikely(nseg == 0) ||
- unlikely(nseg > BLKIF_MAX_SEGMENTS_PER_REQUEST) )
- {
- DPRINTK("Bad number of segments in request (%d)\n", nseg);
- goto bad_descriptor;
- }
-
- /* Make sure userspace is ready. */
- if (!blktap_ring_ok) {
- DPRINTK("blktap: ring not ready for requests!\n");
- goto bad_descriptor;
- }
+ blkif_request_t *target;
+ int i, pending_idx = pending_ring[MASK_PEND_IDX(pending_cons)];
+ pending_req_t *pending_req;
+ struct gnttab_map_grant_ref map[BLKIF_MAX_SEGMENTS_PER_REQUEST*2];
+ int op, ret;
+ unsigned int nseg;
+
+ /* Check that number of segments is sane. */
+ nseg = req->nr_segments;
+ if (unlikely(nseg == 0) ||
+ unlikely(nseg > BLKIF_MAX_SEGMENTS_PER_REQUEST)) {
+ DPRINTK("Bad number of segments in request (%d)\n", nseg);
+ goto bad_descriptor;
+ }
+
+ /* Make sure userspace is ready. */
+ if (!blktap_ring_ok) {
+ DPRINTK("blktap: ring not ready for requests!\n");
+ goto bad_descriptor;
+ }


- if ( RING_FULL(&blktap_ufe_ring) ) {
- WPRINTK("blktap: fe_ring is full, can't add (very broken!).\n");
- goto bad_descriptor;
- }
-
- flush_cache_all(); /* a noop on intel... */
-
- /* Map the foreign pages directly in to the application */
- op = 0;
- for (i=0; i<req->nr_segments; i++) {
-
- unsigned long uvaddr;
- unsigned long kvaddr;
- unsigned long ptep;
-
- uvaddr = MMAP_VADDR(user_vstart, pending_idx, i);
- kvaddr = MMAP_VADDR(mmap_vstart, pending_idx, i);
-
- /* Map the remote page to kernel. */
- map[op].host_addr = kvaddr;
- map[op].dom = blkif->domid;
- map[op].ref = blkif_gref_from_fas(req->frame_and_sects[i]);
- map[op].flags = GNTMAP_host_map;
- /* This needs a bit more thought in terms of interposition:
- * If we want to be able to modify pages during write using
- * grant table mappings, the guest will either need to allow
- * it, or we'll need to incur a copy. Bit of an fbufs moment. ;) */
- if (req->operation == BLKIF_OP_WRITE)
- map[op].flags |= GNTMAP_readonly;
- op++;
-
- /* Now map it to user. */
- ret = create_lookup_pte_addr(blktap_vma->vm_mm, uvaddr, &ptep);
- if (ret)
- {
- DPRINTK("Couldn't get a pte addr!\n");
- fast_flush_area(pending_idx, req->nr_segments);
- goto bad_descriptor;
- }
-
- map[op].host_addr = ptep;
- map[op].dom = blkif->domid;
- map[op].ref = blkif_gref_from_fas(req->frame_and_sects[i]);
- map[op].flags = GNTMAP_host_map | GNTMAP_application_map
- | GNTMAP_contains_pte;
- /* Above interposition comment applies here as well. */
- if (req->operation == BLKIF_OP_WRITE)
- map[op].flags |= GNTMAP_readonly;
- op++;
- }
-
- if ( unlikely(HYPERVISOR_grant_table_op(
- GNTTABOP_map_grant_ref, map, op)))
- BUG();
-
- op = 0;
- for (i=0; i<(req->nr_segments*2); i+=2) {
- unsigned long uvaddr;
- unsigned long kvaddr;
- unsigned long offset;
- int cancel = 0;
-
- uvaddr = MMAP_VADDR(user_vstart, pending_idx, i/2);
- kvaddr = MMAP_VADDR(mmap_vstart, pending_idx, i/2);
-
- if ( unlikely(map[i].handle < 0) )
- {
- DPRINTK("Error on kernel grant mapping (%d)\n", map[i].handle);
- ret = map[i].handle;
- cancel = 1;
- }
-
- if ( unlikely(map[i+1].handle < 0) )
- {
- DPRINTK("Error on user grant mapping (%d)\n", map[i+1].handle);
- ret = map[i+1].handle;
- cancel = 1;
- }
-
- if (cancel)
- {
- fast_flush_area(pending_idx, req->nr_segments);
- goto bad_descriptor;
- }
-
- /* Set the necessary mappings in p2m and in the VM_FOREIGN
- * vm_area_struct to allow user vaddr -> struct page lookups
- * to work. This is needed for direct IO to foreign pages. */
- phys_to_machine_mapping[__pa(kvaddr) >> PAGE_SHIFT] =
- FOREIGN_FRAME(map[i].dev_bus_addr >> PAGE_SHIFT);
-
- offset = (uvaddr - blktap_vma->vm_start) >> PAGE_SHIFT;
- ((struct page **)blktap_vma->vm_private_data)[offset] =
- pfn_to_page(__pa(kvaddr) >> PAGE_SHIFT);
-
- /* Save handles for unmapping later. */
- pending_handle(pending_idx, i/2).kernel = map[i].handle;
- pending_handle(pending_idx, i/2).user = map[i+1].handle;
- }
-
- /* Mark mapped pages as reserved: */
- for ( i = 0; i < req->nr_segments; i++ )
- {
- unsigned long kvaddr;
-
- kvaddr = MMAP_VADDR(mmap_vstart, pending_idx, i);
- SetPageReserved(pfn_to_page(__pa(kvaddr) >> PAGE_SHIFT));
- }
-
- pending_req = &pending_reqs[pending_idx];
- pending_req->blkif = blkif;
- pending_req->id = req->id;
- pending_req->operation = req->operation;
- pending_req->status = BLKIF_RSP_OKAY;
- pending_req->nr_pages = nseg;
- req->id = MAKE_ID(blkif->domid, pending_idx);
- //atomic_set(&pending_req->pendcnt, nbio);
- pending_cons++;
- blkif_get(blkif);
-
- /* Finally, write the request message to the user ring. */
- target = RING_GET_REQUEST(&blktap_ufe_ring, blktap_ufe_ring.req_prod_pvt);
- memcpy(target, req, sizeof(*req));
- blktap_ufe_ring.req_prod_pvt++;
- return;
+ if (RING_FULL(&blktap_ufe_ring)) {
+ WPRINTK("blktap: fe_ring is full, can't add "
+ "(very broken!).\n");
+ goto bad_descriptor;
+ }
+
+ flush_cache_all(); /* a noop on intel... */
+
+ /* Map the foreign pages directly in to the application */
+ op = 0;
+ for (i = 0; i < req->nr_segments; i++) {
+
+ unsigned long uvaddr;
+ unsigned long kvaddr;
+ unsigned long ptep;
+
+ uvaddr = MMAP_VADDR(user_vstart, pending_idx, i);
+ kvaddr = MMAP_VADDR(mmap_vstart, pending_idx, i);
+
+ /* Map the remote page to kernel. */
+ map[op].host_addr = kvaddr;
+ map[op].dom = blkif->domid;
+ map[op].ref = blkif_gref_from_fas(req->frame_and_sects[i]);
+ map[op].flags = GNTMAP_host_map;
+ /* This needs a bit more thought in terms of interposition:
+ * If we want to be able to modify pages during write using
+ * grant table mappings, the guest will either need to allow
+ * it, or we'll need to incur a copy. Bit of an fbufs moment. ;) */
+ if (req->operation == BLKIF_OP_WRITE)
+ map[op].flags |= GNTMAP_readonly;
+ op++;
+
+ /* Now map it to user. */
+ ret = create_lookup_pte_addr(blktap_vma->vm_mm, uvaddr, &ptep);
+ if (ret) {
+ DPRINTK("Couldn't get a pte addr!\n");
+ fast_flush_area(pending_idx, req->nr_segments);
+ goto bad_descriptor;
+ }
+
+ map[op].host_addr = ptep;
+ map[op].dom = blkif->domid;
+ map[op].ref = blkif_gref_from_fas(req->frame_and_sects[i]);
+ map[op].flags = GNTMAP_host_map | GNTMAP_application_map
+ | GNTMAP_contains_pte;
+ /* Above interposition comment applies here as well. */
+ if (req->operation == BLKIF_OP_WRITE)
+ map[op].flags |= GNTMAP_readonly;
+ op++;
+ }
+
+ BUG_ON(HYPERVISOR_grant_table_op(
+ GNTTABOP_map_grant_ref, map, op));
+
+ op = 0;
+ for (i = 0; i < (req->nr_segments*2); i += 2) {
+ unsigned long uvaddr;
+ unsigned long kvaddr;
+ unsigned long offset;
+ int cancel = 0;
+
+ uvaddr = MMAP_VADDR(user_vstart, pending_idx, i/2);
+ kvaddr = MMAP_VADDR(mmap_vstart, pending_idx, i/2);
+
+ if (unlikely(map[i].handle < 0)) {
+ DPRINTK("Error on kernel grant mapping (%d)\n",
+ map[i].handle);
+ ret = map[i].handle;
+ cancel = 1;
+ }
+
+ if (unlikely(map[i+1].handle < 0)) {
+ DPRINTK("Error on user grant mapping (%d)\n",
+ map[i+1].handle);
+ ret = map[i+1].handle;
+ cancel = 1;
+ }
+
+ if (cancel) {
+ fast_flush_area(pending_idx, req->nr_segments);
+ goto bad_descriptor;
+ }
+
+ /* Set the necessary mappings in p2m and in the VM_FOREIGN
+ * vm_area_struct to allow user vaddr -> struct page lookups
+ * to work. This is needed for direct IO to foreign pages. */
+ phys_to_machine_mapping[__pa(kvaddr) >> PAGE_SHIFT] =
+ FOREIGN_FRAME(map[i].dev_bus_addr >> PAGE_SHIFT);
+
+ offset = (uvaddr - blktap_vma->vm_start) >> PAGE_SHIFT;
+ ((struct page **)blktap_vma->vm_private_data)[offset] =
+ pfn_to_page(__pa(kvaddr) >> PAGE_SHIFT);
+
+ /* Save handles for unmapping later. */
+ pending_handle(pending_idx, i/2).kernel = map[i].handle;
+ pending_handle(pending_idx, i/2).user = map[i+1].handle;
+ }
+
+ /* Mark mapped pages as reserved: */
+ for (i = 0; i < req->nr_segments; i++) {
+ unsigned long kvaddr;
+ kvaddr = MMAP_VADDR(mmap_vstart, pending_idx, i);
+ SetPageReserved(pfn_to_page(__pa(kvaddr) >> PAGE_SHIFT));
+ }
+
+ pending_req = &pending_reqs[pending_idx];
+ pending_req->blkif = blkif;
+ pending_req->id = req->id;
+ pending_req->operation = req->operation;
+ pending_req->status = BLKIF_RSP_OKAY;
+ pending_req->nr_pages = nseg;
+ req->id = MAKE_ID(blkif->domid, pending_idx);
+ //atomic_set(&pending_req->pendcnt, nbio);
+ pending_cons++;
+ blkif_get(blkif);
+
+ /* Finally, write the request message to the user ring. */
+ target = RING_GET_REQUEST(&blktap_ufe_ring,
+ blktap_ufe_ring.req_prod_pvt);
+ memcpy(target, req, sizeof(*req));
+ blktap_ufe_ring.req_prod_pvt++;
+ return;

bad_descriptor:
- make_response(blkif, req->id, req->operation, BLKIF_RSP_ERROR);
+ make_response(blkif, req->id, req->operation, BLKIF_RSP_ERROR);
}


@@ -837,80 +826,89 @@
static void make_response(blkif_t *blkif, unsigned long id,
unsigned short op, int st)
{
- blkif_response_t *resp;
- unsigned long flags;
- blkif_back_ring_t *blk_ring = &blkif->blk_ring;
-
- /* Place on the response ring for the relevant domain. */
- spin_lock_irqsave(&blkif->blk_ring_lock, flags);
- resp = RING_GET_RESPONSE(blk_ring, blk_ring->rsp_prod_pvt);
- resp->id = id;
- resp->operation = op;
- resp->status = st;
- wmb(); /* Ensure other side can see the response fields. */
- blk_ring->rsp_prod_pvt++;
- RING_PUSH_RESPONSES(blk_ring);
- spin_unlock_irqrestore(&blkif->blk_ring_lock, flags);
-
- /* Kick the relevant domain. */
- notify_via_evtchn(blkif->evtchn);
+ blkif_response_t *resp;
+ unsigned long flags;
+ blkif_back_ring_t *blk_ring = &blkif->blk_ring;
+
+ /* Place on the response ring for the relevant domain. */
+ spin_lock_irqsave(&blkif->blk_ring_lock, flags);
+ resp = RING_GET_RESPONSE(blk_ring, blk_ring->rsp_prod_pvt);
+ resp->id = id;
+ resp->operation = op;
+ resp->status = st;
+ wmb(); /* Ensure other side can see the response fields. */
+ blk_ring->rsp_prod_pvt++;
+ RING_PUSH_RESPONSES(blk_ring);
+ spin_unlock_irqrestore(&blkif->blk_ring_lock, flags);
+
+ /* Kick the relevant domain. */
+ notify_via_evtchn(blkif->evtchn);
}

static struct miscdevice blktap_miscdev = {
- .minor = BLKTAP_MINOR,
- .name = "blktap",
- .fops = &blktap_fops,
- .devfs_name = "misc/blktap",
+ .minor = BLKTAP_MINOR,
+ .name = "blktap",
+ .fops = &blktap_fops,
+ .devfs_name = "misc/blktap",
};

void blkif_deschedule(blkif_t *blkif)
{
- remove_from_blkdev_list(blkif);
+ remove_from_blkdev_list(blkif);
}

static int __init blkif_init(void)
{
- int i, j, err;
- struct page *page;
+ int i, j, err;
+ struct page *page;
/*
- if ( !(xen_start_info->flags & SIF_INITDOMAIN) &&
- !(xen_start_info->flags & SIF_BLK_BE_DOMAIN) )
- return 0;
+ if ( !(xen_start_info->flags & SIF_INITDOMAIN) &&
+ !(xen_start_info->flags & SIF_BLK_BE_DOMAIN) )
+ return 0;
*/
- blkif_interface_init();
-
- page = balloon_alloc_empty_page_range(MMAP_PAGES);
- BUG_ON(page == NULL);
- mmap_vstart = (unsigned long)pfn_to_kaddr(page_to_pfn(page));
-
- pending_cons = 0;
- pending_prod = MAX_PENDING_REQS;
- memset(pending_reqs, 0, sizeof(pending_reqs));
- for ( i = 0; i < MAX_PENDING_REQS; i++ )
- pending_ring[i] = i;
+ blkif_interface_init();
+
+ page = balloon_alloc_empty_page_range(MMAP_PAGES);
+ BUG_ON(page == NULL);
+ mmap_vstart = (unsigned long)pfn_to_kaddr(page_to_pfn(page));
+
+ pending_cons = 0;
+ pending_prod = MAX_PENDING_REQS;
+ memset(pending_reqs, 0, sizeof(pending_reqs));
+ for ( i = 0; i < MAX_PENDING_REQS; i++ )
+ pending_ring[i] = i;

- spin_lock_init(&blkio_schedule_list_lock);
- INIT_LIST_HEAD(&blkio_schedule_list);
-
- if ( kernel_thread(blkio_schedule, 0, CLONE_FS | CLONE_FILES) < 0 )
- BUG();
-
- blkif_xenbus_init();
-
- for (i=0; i<MAX_PENDING_REQS ; i++)
- for (j=0; j<BLKIF_MAX_SEGMENTS_PER_REQUEST; j++)
- BLKTAP_INVALIDATE_HANDLE(&pending_handle(i, j));
-
- err = misc_register(&blktap_miscdev);
- if ( err != 0 )
- {
- printk(KERN_ALERT "Couldn't register /dev/misc/blktap (%d)\n", err);
- return err;
- }
-
- init_waitqueue_head(&blktap_wait);
-
- return 0;
+ spin_lock_init(&blkio_schedule_list_lock);
+ INIT_LIST_HEAD(&blkio_schedule_list);
+
+ BUG_ON(kernel_thread(blkio_schedule, 0, CLONE_FS | CLONE_FILES) < 0);
+
+ blkif_xenbus_init();
+
+ for (i = 0; i < MAX_PENDING_REQS ; i++)
+ for (j = 0; j < BLKIF_MAX_SEGMENTS_PER_REQUEST; j++)
+ BLKTAP_INVALIDATE_HANDLE(&pending_handle(i, j));
+
+ err = misc_register(&blktap_miscdev);
+ if (err != 0) {
+ printk(KERN_ALERT "Couldn't register /dev/misc/blktap (%d)\n",
+ err);
+ return err;
+ }
+
+ init_waitqueue_head(&blktap_wait);
+
+ return 0;
}

__initcall(blkif_init);
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r eba5afe9aa37 -r 10759a44ce3b linux-2.6-xen-sparse/drivers/xen/blktap/common.h
--- a/linux-2.6-xen-sparse/drivers/xen/blktap/common.h Thu Sep 22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blktap/common.h Thu Sep 22 15:12:14 2005
@@ -33,39 +33,39 @@
#define WPRINTK(fmt, args...) printk(KERN_WARNING "blk_tap: " fmt, ##args)

struct vbd {
- blkif_vdev_t handle; /* what the domain refers to this vbd as */
- unsigned char readonly; /* Non-zero -> read-only */
- unsigned char type; /* VDISK_xxx */
- u32 pdevice; /* phys device that this vbd maps to */
- struct block_device *bdev;
+ blkif_vdev_t handle; /* what the domain refers to this vbd as */
+ unsigned char readonly; /* Non-zero -> read-only */
+ unsigned char type; /* VDISK_xxx */
+ u32 pdevice; /* phys device that this vbd maps to */
+ struct block_device *bdev;
};

typedef struct blkif_st {
- /* Unique identifier for this interface. */
- domid_t domid;
- unsigned int handle;
- /* Physical parameters of the comms window. */
- unsigned int evtchn;
- unsigned int remote_evtchn;
- /* Comms information. */
- blkif_back_ring_t blk_ring;
- struct vm_struct *blk_ring_area;
- /* VBDs attached to this interface. */
- struct vbd vbd;
- /* Private fields. */
- enum { DISCONNECTED, CONNECTED } status;
+ /* Unique identifier for this interface. */
+ domid_t domid;
+ unsigned int handle;
+ /* Physical parameters of the comms window. */
+ unsigned int evtchn;
+ unsigned int remote_evtchn;
+ /* Comms information. */
+ blkif_back_ring_t blk_ring;
+ struct vm_struct *blk_ring_area;
+ /* VBDs attached to this interface. */
+ struct vbd vbd;
+ /* Private fields. */
+ enum { DISCONNECTED, CONNECTED } status;
#ifdef CONFIG_XEN_BLKDEV_TAP_BE
- /* Is this a blktap frontend */
- unsigned int is_blktap;
+ /* Is this a blktap frontend */
+ unsigned int is_blktap;
#endif
- struct list_head blkdev_list;
- spinlock_t blk_ring_lock;
- atomic_t refcnt;
+ struct list_head blkdev_list;
+ spinlock_t blk_ring_lock;
+ atomic_t refcnt;

- struct work_struct free_work;
+ struct work_struct free_work;

- u16 shmem_handle;
- grant_ref_t shmem_ref;
+ u16 shmem_handle;
+ grant_ref_t shmem_ref;
} blkif_t;

blkif_t *alloc_blkif(domid_t domid);
@@ -89,10 +89,10 @@
unsigned long vbd_secsize(struct vbd *vbd);

struct phys_req {
- unsigned short dev;
- unsigned short nr_sects;
- struct block_device *bdev;
- blkif_sector_t sector_number;
+ unsigned short dev;
+ unsigned short nr_sects;
+ struct block_device *bdev;
+ blkif_sector_t sector_number;
};

int vbd_translate(struct phys_req *req, blkif_t *blkif, int operation);
@@ -106,3 +106,13 @@
irqreturn_t blkif_be_int(int irq, void *dev_id, struct pt_regs *regs);

#endif /* __BLKIF__BACKEND__COMMON_H__ */
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r eba5afe9aa37 -r 10759a44ce3b linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c
--- a/linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c Thu Sep 22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c Thu Sep 22 15:12:14 2005
@@ -222,3 +222,13 @@
{
xenbus_register_backend(&blkback);
}
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r eba5afe9aa37 -r 10759a44ce3b linux-2.6-xen-sparse/drivers/xen/console/console.c
--- a/linux-2.6-xen-sparse/drivers/xen/console/console.c Thu Sep 22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/console/console.c Thu Sep 22 15:12:14 2005
@@ -75,31 +75,33 @@

static int __init xencons_setup(char *str)
{
- char *q;
- int n;
-
- if ( !strncmp(str, "ttyS", 4) )
- xc_mode = XC_SERIAL;
- else if ( !strncmp(str, "tty", 3) )
- xc_mode = XC_TTY;
- else if ( !strncmp(str, "off", 3) )
- xc_mode = XC_OFF;
-
- switch ( xc_mode )
- {
- case XC_SERIAL:
- n = simple_strtol( str+4, &q, 10 );
- if ( q > (str + 4) ) xc_num = n;
- break;
- case XC_TTY:
- n = simple_strtol( str+3, &q, 10 );
- if ( q > (str + 3) ) xc_num = n;
- break;
- default:
- break;
- }
-
- return 1;
+ char *q;
+ int n;
+
+ if (!strncmp(str, "ttyS", 4))
+ xc_mode = XC_SERIAL;
+ else if (!strncmp(str, "tty", 3))
+ xc_mode = XC_TTY;
+ else if (!strncmp(str, "off", 3))
+ xc_mode = XC_OFF;
+
+ switch ( xc_mode )
+ {
+ case XC_SERIAL:
+ n = simple_strtol(str+4, &q, 10);
+ if (q > (str + 4))
+ xc_num = n;
+ break;
+ case XC_TTY:
+ n = simple_strtol(str+3, &q, 10);
+ if (q > (str + 3))
+ xc_num = n;
+ break;
+ default:
+ break;
+ }
+
+ return 1;
}
__setup("xencons=", xencons_setup);

@@ -111,11 +113,11 @@

static int __init xencons_bufsz_setup(char *str)
{
- unsigned int goal;
- goal = simple_strtoul(str, NULL, 0);
- while ( wbuf_size < goal )
- wbuf_size <<= 1;
- return 1;
+ unsigned int goal;
+ goal = simple_strtoul(str, NULL, 0);
+ while (wbuf_size < goal)
+ wbuf_size <<= 1;
+ return 1;
}
__setup("xencons_bufsz=", xencons_bufsz_setup);

@@ -135,57 +137,55 @@
/******************** Kernel console driver ********************************/

static void kcons_write(
- struct console *c, const char *s, unsigned int count)
-{
- int i;
- unsigned long flags;
-
- spin_lock_irqsave(&xencons_lock, flags);
+ struct console *c, const char *s, unsigned int count)
+{
+ int i;
+ unsigned long flags;
+
+ spin_lock_irqsave(&xencons_lock, flags);

- for ( i = 0; i < count; i++ )
- {
- if ( (wp - wc) >= (wbuf_size - 1) )
- break;
- if ( (wbuf[WBUF_MASK(wp++)] = s[i]) == '\n' )
- wbuf[WBUF_MASK(wp++)] = '\r';
- }
-
- __xencons_tx_flush();
-
- spin_unlock_irqrestore(&xencons_lock, flags);
+ for (i = 0; i < count; i++) {
+ if ((wp - wc) >= (wbuf_size - 1))
+ break;
+ if ((wbuf[WBUF_MASK(wp++)] = s[i]) == '\n')
+ wbuf[WBUF_MASK(wp++)] = '\r';
+ }
+
+ __xencons_tx_flush();
+
+ spin_unlock_irqrestore(&xencons_lock, flags);
}

static void kcons_write_dom0(
- struct console *c, const char *s, unsigned int count)
-{
- int rc;
-
- while ( (count > 0) &&
- ((rc = HYPERVISOR_console_io(
- CONSOLEIO_write, count, (char *)s)) > 0) )
- {
- count -= rc;
- s += rc;
- }
+ struct console *c, const char *s, unsigned int count)
+{
+ int rc;
+
+ while ((count > 0) &&
+ ((rc = HYPERVISOR_console_io(
+ CONSOLEIO_write, count, (char *)s)) > 0)) {
+ count -= rc;
+ s += rc;
+ }
}

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
static struct tty_driver *kcons_device(struct console *c, int *index)
{
- *index = c->index;
- return xencons_driver;
+ *index = c->index;
+ return xencons_driver;
}
#else
static kdev_t kcons_device(struct console *c)
{
- return MKDEV(TTY_MAJOR, (xc_mode == XC_SERIAL) ? 64 : 1);
+ return MKDEV(TTY_MAJOR, (xc_mode == XC_SERIAL) ? 64 : 1);
}
#endif

static struct console kcons_info = {
- .device = kcons_device,
- .flags = CON_PRINTBUFFER,
- .index = -1,
+ .device = kcons_device,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
};

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
@@ -196,44 +196,42 @@
void xen_console_init(void)
#endif
{
- if ( xen_start_info->flags & SIF_INITDOMAIN )
- {
- if ( xc_mode == XC_DEFAULT )
- xc_mode = XC_SERIAL;
- kcons_info.write = kcons_write_dom0;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- if ( xc_mode == XC_SERIAL )
- kcons_info.flags |= CON_ENABLED;
-#endif
- }
- else
- {
- if ( xc_mode == XC_DEFAULT )
- xc_mode = XC_TTY;
- kcons_info.write = kcons_write;
- }
-
- switch ( xc_mode )
- {
- case XC_SERIAL:
- strcpy(kcons_info.name, "ttyS");
- if ( xc_num == -1 ) xc_num = 0;
- break;
-
- case XC_TTY:
- strcpy(kcons_info.name, "tty");
- if ( xc_num == -1 ) xc_num = 1;
- break;
-
- default:
- return __RETCODE;
- }
-
- wbuf = alloc_bootmem(wbuf_size);
-
- register_console(&kcons_info);
-
- return __RETCODE;
+ if (xen_start_info->flags & SIF_INITDOMAIN) {
+ if (xc_mode == XC_DEFAULT)
+ xc_mode = XC_SERIAL;
+ kcons_info.write = kcons_write_dom0;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ if (xc_mode == XC_SERIAL)
+ kcons_info.flags |= CON_ENABLED;
+#endif
+ } else {
+ if (xc_mode == XC_DEFAULT)
+ xc_mode = XC_TTY;
+ kcons_info.write = kcons_write;
+ }
+
+ switch (xc_mode) {
+ case XC_SERIAL:
+ strcpy(kcons_info.name, "ttyS");
+ if (xc_num == -1)
+ xc_num = 0;
+ break;
+
+ case XC_TTY:
+ strcpy(kcons_info.name, "tty");
+ if (xc_num == -1)
+ xc_num = 1;
+ break;
+
+ default:
+ return __RETCODE;
+ }
+
+ wbuf = alloc_bootmem(wbuf_size);
+
+ register_console(&kcons_info);
+
+ return __RETCODE;
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
console_initcall(xen_console_init);
@@ -246,41 +244,40 @@
asmlinkage int xprintk(const char *fmt, ...)
#endif
{
- va_list args;
- int printk_len;
- static char printk_buf[1024];
+ va_list args;
+ int printk_len;
+ static char printk_buf[1024];

- /* Emit the output into the temporary buffer */
- va_start(args, fmt);
- printk_len = vsnprintf(printk_buf, sizeof(printk_buf), fmt, args);
- va_end(args);
-
- /* Send the processed output directly to Xen. */
- kcons_write_dom0(NULL, printk_buf, printk_len);
-
- return 0;
+ /* Emit the output into the temporary buffer */
+ va_start(args, fmt);
+ printk_len = vsnprintf(printk_buf, sizeof(printk_buf), fmt, args);
+ va_end(args);
+
+ /* Send the processed output directly to Xen. */
+ kcons_write_dom0(NULL, printk_buf, printk_len);
+
+ return 0;
}

/*** Forcibly flush console data before dying. ***/
void xencons_force_flush(void)
{
- int sz;
-
- /* Emergency console is synchronous, so there's nothing to flush. */
- if ( xen_start_info->flags & SIF_INITDOMAIN )
- return;
-
-
- /* Spin until console data is flushed through to the domain controller. */
- while ( (wc != wp) )
- {
- int sent = 0;
- if ( (sz = wp - wc) == 0 )
- continue;
- sent = xencons_ring_send(&wbuf[WBUF_MASK(wc)], sz);
- if (sent > 0)
- wc += sent;
- }
+ int sz;
+
+ /* Emergency console is synchronous, so there's nothing to flush. */
+ if (xen_start_info->flags & SIF_INITDOMAIN)
+ return;
+
+
+ /* Spin until console data is flushed through to the daemon. */
+ while (wc != wp) {
+ int sent = 0;
+ if ((sz = wp - wc) == 0)
+ continue;
+ sent = xencons_ring_send(&wbuf[WBUF_MASK(wc)], sz);
+ if (sent > 0)
+ wc += sent;
+ }
}


@@ -305,362 +302,358 @@
/* Non-privileged receive callback. */
static void xencons_rx(char *buf, unsigned len, struct pt_regs *regs)
{
- int i;
- unsigned long flags;
-
- spin_lock_irqsave(&xencons_lock, flags);
- if ( xencons_tty != NULL )
- {
- for ( i = 0; i < len; i++ ) {
+ int i;
+ unsigned long flags;
+
+ spin_lock_irqsave(&xencons_lock, flags);
+ if (xencons_tty == NULL)
+ goto out;
+
+ for (i = 0; i < len; i++) {
#ifdef CONFIG_MAGIC_SYSRQ
- if (sysrq_enabled) {
- if (buf[i] == '\x0f') { /* ^O */
- sysrq_requested = jiffies;
- continue; /* don't print the sysrq key */
- } else if (sysrq_requested) {
- unsigned long sysrq_timeout = sysrq_requested + HZ*2;
- sysrq_requested = 0;
- /* if it's been less than a timeout, do the sysrq */
- if (time_before(jiffies, sysrq_timeout)) {
- spin_unlock_irqrestore(&xencons_lock, flags);
- handle_sysrq(buf[i], regs, xencons_tty);
- spin_lock_irqsave(&xencons_lock, flags);
- continue;
- }
- }
- }
-#endif
- tty_insert_flip_char(xencons_tty, buf[i], 0);
- }
- tty_flip_buffer_push(xencons_tty);
- }
- spin_unlock_irqrestore(&xencons_lock, flags);
-
+ if (sysrq_enabled) {
+ if (buf[i] == '\x0f') { /* ^O */
+ sysrq_requested = jiffies;
+ continue; /* don't print the sysrq key */
+ } else if (sysrq_requested) {
+ unsigned long sysrq_timeout =
+ sysrq_requested + HZ*2;
+ sysrq_requested = 0;
+ if (time_before(jiffies, sysrq_timeout)) {
+ spin_unlock_irqrestore(
+ &xencons_lock, flags);
+ handle_sysrq(
+ buf[i], regs, xencons_tty);
+ spin_lock_irqsave(
+ &xencons_lock, flags);
+ continue;
+ }
+ }
+ }
+#endif
+ tty_insert_flip_char(xencons_tty, buf[i], 0);
+ }
+ tty_flip_buffer_push(xencons_tty);
+
+ out:
+ spin_unlock_irqrestore(&xencons_lock, flags);
}

/* Privileged and non-privileged transmit worker. */
static void __xencons_tx_flush(void)
{
- int sz, work_done = 0;
-
- if ( xen_start_info->flags & SIF_INITDOMAIN )
- {
- if ( x_char )
- {
- kcons_write_dom0(NULL, &x_char, 1);
- x_char = 0;
- work_done = 1;
- }
-
- while ( wc != wp )
- {
- sz = wp - wc;
- if ( sz > (wbuf_size - WBUF_MASK(wc)) )
- sz = wbuf_size - WBUF_MASK(wc);
- kcons_write_dom0(NULL, &wbuf[WBUF_MASK(wc)], sz);
- wc += sz;
- work_done = 1;
- }
- }
- else
- {
- while ( x_char )
- {
- if (xencons_ring_send(&x_char, 1) == 1) {
- x_char = 0;
- work_done = 1;
- }
- }
-
- while ( wc != wp )
- {
- int sent;
- sz = wp - wc;
- if ( sz > (wbuf_size - WBUF_MASK(wc)) )
- sz = wbuf_size - WBUF_MASK(wc);
- sent = xencons_ring_send(&wbuf[WBUF_MASK(wc)], sz);
- if ( sent > 0 ) {
- wc += sent;
- work_done = 1;
- }
- }
- }
-
- if ( work_done && (xencons_tty != NULL) )
- {
- wake_up_interruptible(&xencons_tty->write_wait);
- if ( (xencons_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
- (xencons_tty->ldisc.write_wakeup != NULL) )
- (xencons_tty->ldisc.write_wakeup)(xencons_tty);
- }
+ int sz, work_done = 0;
+
+ if (xen_start_info->flags & SIF_INITDOMAIN) {
+ if (x_char) {
+ kcons_write_dom0(NULL, &x_char, 1);
+ x_char = 0;
+ work_done = 1;
+ }
+
+ while (wc != wp) {
+ sz = wp - wc;
+ if (sz > (wbuf_size - WBUF_MASK(wc)))
+ sz = wbuf_size - WBUF_MASK(wc);
+ kcons_write_dom0(NULL, &wbuf[WBUF_MASK(wc)], sz);
+ wc += sz;
+ work_done = 1;
+ }
+ } else {
+ while (x_char) {
+ if (xencons_ring_send(&x_char, 1) == 1) {
+ x_char = 0;
+ work_done = 1;
+ }
+ }
+
+ while (wc != wp) {
+ int sent;
+ sz = wp - wc;
+ if (sz > (wbuf_size - WBUF_MASK(wc)))
+ sz = wbuf_size - WBUF_MASK(wc);
+ sent = xencons_ring_send(&wbuf[WBUF_MASK(wc)], sz);
+ if (sent > 0) {
+ wc += sent;
+ work_done = 1;
+ }
+ }
+ }
+
+ if (work_done && (xencons_tty != NULL))
+ {
+ wake_up_interruptible(&xencons_tty->write_wait);
+ if ((xencons_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+ (xencons_tty->ldisc.write_wakeup != NULL))
+ (xencons_tty->ldisc.write_wakeup)(xencons_tty);
+ }
}

/* Privileged receive callback and transmit kicker. */
static irqreturn_t xencons_priv_interrupt(int irq, void *dev_id,
struct pt_regs *regs)
{
- static char rbuf[16];
- int i, l;
- unsigned long flags;
-
- spin_lock_irqsave(&xencons_lock, flags);
-
- if ( xencons_tty != NULL )
- {
- /* Receive work. */
- while ( (l = HYPERVISOR_console_io(CONSOLEIO_read, 16, rbuf)) > 0 )
- for ( i = 0; i < l; i++ )
- tty_insert_flip_char(xencons_tty, rbuf[i], 0);
- if ( xencons_tty->flip.count != 0 )
- tty_flip_buffer_push(xencons_tty);
- }
-
- /* Transmit work. */
- __xencons_tx_flush();
-
- spin_unlock_irqrestore(&xencons_lock, flags);
-
- return IRQ_HANDLED;
+ static char rbuf[16];
+ int i, l;
+ unsigned long flags;
+
+ spin_lock_irqsave(&xencons_lock, flags);
+
+ if (xencons_tty != NULL)
+ {
+ /* Receive work. */
+ while ((l = HYPERVISOR_console_io(
+ CONSOLEIO_read, 16, rbuf)) > 0)
+ for (i = 0; i < l; i++)
+ tty_insert_flip_char(xencons_tty, rbuf[i], 0);
+ if (xencons_tty->flip.count != 0)
+ tty_flip_buffer_push(xencons_tty);
+ }
+
+ /* Transmit work. */
+ __xencons_tx_flush();
+
+ spin_unlock_irqrestore(&xencons_lock, flags);
+
+ return IRQ_HANDLED;
}

static int xencons_write_room(struct tty_struct *tty)
{
- return wbuf_size - (wp - wc);
+ return wbuf_size - (wp - wc);
}

static int xencons_chars_in_buffer(struct tty_struct *tty)
{
- return wp - wc;
+ return wp - wc;
}

static void xencons_send_xchar(struct tty_struct *tty, char ch)
{
- unsigned long flags;
-
- if ( TTY_INDEX(tty) != 0 )
- return;
-
- spin_lock_irqsave(&xencons_lock, flags);
- x_char = ch;
- __xencons_tx_flush();
- spin_unlock_irqrestore(&xencons_lock, flags);
+ unsigned long flags;
+
+ if (TTY_INDEX(tty) != 0)
+ return;
+
+ spin_lock_irqsave(&xencons_lock, flags);
+ x_char = ch;
+ __xencons_tx_flush();
+ spin_unlock_irqrestore(&xencons_lock, flags);
}

static void xencons_throttle(struct tty_struct *tty)
{
- if ( TTY_INDEX(tty) != 0 )
- return;
-
- if ( I_IXOFF(tty) )
- xencons_send_xchar(tty, STOP_CHAR(tty));
+ if (TTY_INDEX(tty) != 0)
+ return;
+
+ if (I_IXOFF(tty))
+ xencons_send_xchar(tty, STOP_CHAR(tty));
}

static void xencons_unthrottle(struct tty_struct *tty)
{
- if ( TTY_INDEX(tty) != 0 )
- return;
-
- if ( I_IXOFF(tty) )
- {
- if ( x_char != 0 )
- x_char = 0;
- else
- xencons_send_xchar(tty, START_CHAR(tty));
- }
+ if (TTY_INDEX(tty) != 0)
+ return;
+
+ if (I_IXOFF(tty)) {
+ if (x_char != 0)
+ x_char = 0;
+ else
+ xencons_send_xchar(tty, START_CHAR(tty));
+ }
}

static void xencons_flush_buffer(struct tty_struct *tty)
{
- unsigned long flags;
-
- if ( TTY_INDEX(tty) != 0 )
- return;
-
- spin_lock_irqsave(&xencons_lock, flags);
- wc = wp = 0;
- spin_unlock_irqrestore(&xencons_lock, flags);
+ unsigned long flags;
+
+ if (TTY_INDEX(tty) != 0)
+ return;
+
+ spin_lock_irqsave(&xencons_lock, flags);
+ wc = wp = 0;
+ spin_unlock_irqrestore(&xencons_lock, flags);
}

static inline int __xencons_put_char(int ch)
{
- char _ch = (char)ch;
- if ( (wp - wc) == wbuf_size )
- return 0;
- wbuf[WBUF_MASK(wp++)] = _ch;
- return 1;
+ char _ch = (char)ch;
+ if ((wp - wc) == wbuf_size)
+ return 0;
+ wbuf[WBUF_MASK(wp++)] = _ch;
+ return 1;
}

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
static int xencons_write(
- struct tty_struct *tty,
- const unsigned char *buf,
- int count)
-{
- int i;
- unsigned long flags;
-
- if ( TTY_INDEX(tty) != 0 )
- return count;
-
- spin_lock_irqsave(&xencons_lock, flags);
-
- for ( i = 0; i < count; i++ )
- if ( !__xencons_put_char(buf[i]) )
- break;
-
- if ( i != 0 )
- __xencons_tx_flush();
-
- spin_unlock_irqrestore(&xencons_lock, flags);
-
- return i;
+ struct tty_struct *tty,
+ const unsigned char *buf,
+ int count)
+{
+ int i;
+ unsigned long flags;
+
+ if (TTY_INDEX(tty) != 0)
+ return count;
+
+ spin_lock_irqsave(&xencons_lock, flags);
+
+ for (i = 0; i < count; i++)
+ if (!__xencons_put_char(buf[i]))
+ break;
+
+ if (i != 0)
+ __xencons_tx_flush();
+
+ spin_unlock_irqrestore(&xencons_lock, flags);
+
+ return i;
}
#else
static int xencons_write(
- struct tty_struct *tty,
- int from_user,
- const u_char *buf,
- int count)
-{
- int i;
- unsigned long flags;
-
- if ( from_user && verify_area(VERIFY_READ, buf, count) )
- return -EINVAL;
-
- if ( TTY_INDEX(tty) != 0 )
- return count;
-
- spin_lock_irqsave(&xencons_lock, flags);
-
- for ( i = 0; i < count; i++ )
- {
- char ch;
- if ( from_user )
- __get_user(ch, buf + i);
- else
- ch = buf[i];
- if ( !__xencons_put_char(ch) )
- break;
- }
-
- if ( i != 0 )
- __xencons_tx_flush();
-
- spin_unlock_irqrestore(&xencons_lock, flags);
-
- return i;
+ struct tty_struct *tty,
+ int from_user,
+ const u_char *buf,
+ int count)
+{
+ int i;
+ unsigned long flags;
+
+ if (from_user && verify_area(VERIFY_READ, buf, count))
+ return -EINVAL;
+
+ if (TTY_INDEX(tty) != 0)
+ return count;
+
+ spin_lock_irqsave(&xencons_lock, flags);
+
+ for (i = 0; i < count; i++) {
+ char ch;
+ if (from_user)
+ __get_user(ch, buf + i);
+ else
+ ch = buf[i];
+ if (!__xencons_put_char(ch))
+ break;
+ }
+
+ if (i != 0)
+ __xencons_tx_flush();
+
+ spin_unlock_irqrestore(&xencons_lock, flags);
+
+ return i;
}
#endif

static void xencons_put_char(struct tty_struct *tty, u_char ch)
{
- unsigned long flags;
-
- if ( TTY_INDEX(tty) != 0 )
- return;
-
- spin_lock_irqsave(&xencons_lock, flags);
- (void)__xencons_put_char(ch);
- spin_unlock_irqrestore(&xencons_lock, flags);
+ unsigned long flags;
+
+ if (TTY_INDEX(tty) != 0)
+ return;
+
+ spin_lock_irqsave(&xencons_lock, flags);
+ (void)__xencons_put_char(ch);
+ spin_unlock_irqrestore(&xencons_lock, flags);
}

static void xencons_flush_chars(struct tty_struct *tty)
{
- unsigned long flags;
-
- if ( TTY_INDEX(tty) != 0 )
- return;
-
- spin_lock_irqsave(&xencons_lock, flags);
- __xencons_tx_flush();
- spin_unlock_irqrestore(&xencons_lock, flags);
+ unsigned long flags;
+
+ if (TTY_INDEX(tty) != 0)
+ return;
+
+ spin_lock_irqsave(&xencons_lock, flags);
+ __xencons_tx_flush();
+ spin_unlock_irqrestore(&xencons_lock, flags);
}

static void xencons_wait_until_sent(struct tty_struct *tty, int timeout)
{
- unsigned long orig_jiffies = jiffies;
-
- if ( TTY_INDEX(tty) != 0 )
- return;
-
- while ( DRV(tty->driver)->chars_in_buffer(tty) )
- {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- if ( signal_pending(current) )
- break;
- if ( (timeout != 0) && time_after(jiffies, orig_jiffies + timeout) )
- break;
- }
+ unsigned long orig_jiffies = jiffies;
+
+ if (TTY_INDEX(tty) != 0)
+ return;
+
+ while (DRV(tty->driver)->chars_in_buffer(tty))
+ {
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(1);
+ if (signal_pending(current))
+ break;
+ if ( (timeout != 0) &&
+ time_after(jiffies, orig_jiffies + timeout) )
+ break;
+ }

- set_current_state(TASK_RUNNING);
+ set_current_state(TASK_RUNNING);
}

static int xencons_open(struct tty_struct *tty, struct file *filp)
{
- unsigned long flags;
-
- if ( TTY_INDEX(tty) != 0 )
- return 0;
-
- spin_lock_irqsave(&xencons_lock, flags);
- tty->driver_data = NULL;
- if ( xencons_tty == NULL )
- xencons_tty = tty;
- __xencons_tx_flush();
- spin_unlock_irqrestore(&xencons_lock, flags);
-
- return 0;
+ unsigned long flags;
+
+ if (TTY_INDEX(tty) != 0)
+ return 0;
+
+ spin_lock_irqsave(&xencons_lock, flags);
+ tty->driver_data = NULL;
+ if (xencons_tty == NULL)
+ xencons_tty = tty;
+ __xencons_tx_flush();
+ spin_unlock_irqrestore(&xencons_lock, flags);
+
+ return 0;
}

static void xencons_close(struct tty_struct *tty, struct file *filp)
{
- unsigned long flags;
-
- if ( TTY_INDEX(tty) != 0 )
- return;
-
- if ( tty->count == 1 )
- {
- tty->closing = 1;
- tty_wait_until_sent(tty, 0);
- if ( DRV(tty->driver)->flush_buffer != NULL )
- DRV(tty->driver)->flush_buffer(tty);
- if ( tty->ldisc.flush_buffer != NULL )
- tty->ldisc.flush_buffer(tty);
- tty->closing = 0;
- spin_lock_irqsave(&xencons_lock, flags);
- xencons_tty = NULL;
- spin_unlock_irqrestore(&xencons_lock, flags);
- }
+ unsigned long flags;
+
+ if (TTY_INDEX(tty) != 0)
+ return;
+
+ if (tty->count == 1) {
+ tty->closing = 1;
+ tty_wait_until_sent(tty, 0);
+ if (DRV(tty->driver)->flush_buffer != NULL)
+ DRV(tty->driver)->flush_buffer(tty);
+ if (tty->ldisc.flush_buffer != NULL)
+ tty->ldisc.flush_buffer(tty);
+ tty->closing = 0;
+ spin_lock_irqsave(&xencons_lock, flags);
+ xencons_tty = NULL;
+ spin_unlock_irqrestore(&xencons_lock, flags);
+ }
}

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
static struct tty_operations xencons_ops = {
- .open = xencons_open,
- .close = xencons_close,
- .write = xencons_write,
- .write_room = xencons_write_room,
- .put_char = xencons_put_char,
- .flush_chars = xencons_flush_chars,
- .chars_in_buffer = xencons_chars_in_buffer,
- .send_xchar = xencons_send_xchar,
- .flush_buffer = xencons_flush_buffer,
- .throttle = xencons_throttle,
- .unthrottle = xencons_unthrottle,
- .wait_until_sent = xencons_wait_until_sent,
+ .open = xencons_open,
+ .close = xencons_close,
+ .write = xencons_write,
+ .write_room = xencons_write_room,
+ .put_char = xencons_put_char,
+ .flush_chars = xencons_flush_chars,
+ .chars_in_buffer = xencons_chars_in_buffer,
+ .send_xchar = xencons_send_xchar,
+ .flush_buffer = xencons_flush_buffer,
+ .throttle = xencons_throttle,
+ .unthrottle = xencons_unthrottle,
+ .wait_until_sent = xencons_wait_until_sent,
};

#ifdef CONFIG_XEN_PRIVILEGED_GUEST
static const char *xennullcon_startup(void)
{
- return NULL;
+ return NULL;
}

static int xennullcon_dummy(void)
{
- return 0;
+ return 0;
}

#define DUMMY (void *)xennullcon_dummy
@@ -672,122 +665,128 @@
*/

const struct consw xennull_con = {
- .owner = THIS_MODULE,
- .con_startup = xennullcon_startup,
- .con_init = DUMMY,
- .con_deinit = DUMMY,
- .con_clear = DUMMY,
- .con_putc = DUMMY,
- .con_putcs = DUMMY,
- .con_cursor = DUMMY,
- .con_scroll = DUMMY,
- .con_bmove = DUMMY,
- .con_switch = DUMMY,
- .con_blank = DUMMY,
- .con_font_set = DUMMY,
- .con_font_get = DUMMY,
- .con_font_default = DUMMY,
- .con_font_copy = DUMMY,
- .con_set_palette = DUMMY,
- .con_scrolldelta = DUMMY,
+ .owner = THIS_MODULE,
+ .con_startup = xennullcon_startup,
+ .con_init = DUMMY,
+ .con_deinit = DUMMY,
+ .con_clear = DUMMY,
+ .con_putc = DUMMY,
+ .con_putcs = DUMMY,
+ .con_cursor = DUMMY,
+ .con_scroll = DUMMY,
+ .con_bmove = DUMMY,
+ .con_switch = DUMMY,
+ .con_blank = DUMMY,
+ .con_font_set = DUMMY,
+ .con_font_get = DUMMY,
+ .con_font_default = DUMMY,
+ .con_font_copy = DUMMY,
+ .con_set_palette = DUMMY,
+ .con_scrolldelta = DUMMY,
};
#endif
#endif

static int __init xencons_init(void)
{
- int rc;
-
- if ( xc_mode == XC_OFF )
- return 0;
-
- xencons_ring_init();
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- xencons_driver = alloc_tty_driver((xc_mode == XC_SERIAL) ?
- 1 : MAX_NR_CONSOLES);
- if ( xencons_driver == NULL )
- return -ENOMEM;
+ int rc;
+
+ if (xc_mode == XC_OFF)
+ return 0;
+
+ xencons_ring_init();
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ xencons_driver = alloc_tty_driver((xc_mode == XC_SERIAL) ?
+ 1 : MAX_NR_CONSOLES);
+ if (xencons_driver == NULL)
+ return -ENOMEM;
#else
- memset(&xencons_driver, 0, sizeof(struct tty_driver));
- xencons_driver.magic = TTY_DRIVER_MAGIC;
- xencons_driver.refcount = &xencons_refcount;
- xencons_driver.table = xencons_table;
- xencons_driver.num = (xc_mode == XC_SERIAL) ? 1 : MAX_NR_CONSOLES;
-#endif
-
- DRV(xencons_driver)->major = TTY_MAJOR;
- DRV(xencons_driver)->type = TTY_DRIVER_TYPE_SERIAL;
- DRV(xencons_driver)->subtype = SERIAL_TYPE_NORMAL;
- DRV(xencons_driver)->init_termios = tty_std_termios;
- DRV(xencons_driver)->flags =
- TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_NO_DEVFS;
- DRV(xencons_driver)->termios = xencons_termios;
- DRV(xencons_driver)->termios_locked = xencons_termios_locked;
-
- if ( xc_mode == XC_SERIAL )
- {
- DRV(xencons_driver)->name = "ttyS";
- DRV(xencons_driver)->minor_start = 64 + xc_num;
- DRV(xencons_driver)->name_base = 0 + xc_num;
- }
- else
- {
- DRV(xencons_driver)->name = "tty";
- DRV(xencons_driver)->minor_start = xc_num;
- DRV(xencons_driver)->name_base = xc_num;
- }
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- tty_set_operations(xencons_driver, &xencons_ops);
+ memset(&xencons_driver, 0, sizeof(struct tty_driver));
+ xencons_driver.magic = TTY_DRIVER_MAGIC;
+ xencons_driver.refcount = &xencons_refcount;
+ xencons_driver.table = xencons_table;
+ xencons_driver.num =
+ (xc_mode == XC_SERIAL) ? 1 : MAX_NR_CONSOLES;
+#endif
+
+ DRV(xencons_driver)->major = TTY_MAJOR;
+ DRV(xencons_driver)->type = TTY_DRIVER_TYPE_SERIAL;
+ DRV(xencons_driver)->subtype = SERIAL_TYPE_NORMAL;
+ DRV(xencons_driver)->init_termios = tty_std_termios;
+ DRV(xencons_driver)->flags =
+ TTY_DRIVER_REAL_RAW |
+ TTY_DRIVER_RESET_TERMIOS |
+ TTY_DRIVER_NO_DEVFS;
+ DRV(xencons_driver)->termios = xencons_termios;
+ DRV(xencons_driver)->termios_locked = xencons_termios_locked;
+
+ if (xc_mode == XC_SERIAL)
+ {
+ DRV(xencons_driver)->name = "ttyS";
+ DRV(xencons_driver)->minor_start = 64 + xc_num;
+ DRV(xencons_driver)->name_base = 0 + xc_num;
+ } else {
+ DRV(xencons_driver)->name = "tty";
+ DRV(xencons_driver)->minor_start = xc_num;
+ DRV(xencons_driver)->name_base = xc_num;
+ }
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ tty_set_operations(xencons_driver, &xencons_ops);
#else
- xencons_driver.open = xencons_open;
- xencons_driver.close = xencons_close;
- xencons_driver.write = xencons_write;
- xencons_driver.write_room = xencons_write_room;
- xencons_driver.put_char = xencons_put_char;
- xencons_driver.flush_chars = xencons_flush_chars;
- xencons_driver.chars_in_buffer = xencons_chars_in_buffer;
- xencons_driver.send_xchar = xencons_send_xchar;
- xencons_driver.flush_buffer = xencons_flush_buffer;
- xencons_driver.throttle = xencons_throttle;
- xencons_driver.unthrottle = xencons_unthrottle;
- xencons_driver.wait_until_sent = xencons_wait_until_sent;
-#endif
-
- if ( (rc = tty_register_driver(DRV(xencons_driver))) != 0 )
- {
- printk("WARNING: Failed to register Xen virtual "
- "console driver as '%s%d'\n",
- DRV(xencons_driver)->name, DRV(xencons_driver)->name_base);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- put_tty_driver(xencons_driver);
- xencons_driver = NULL;
-#endif
- return rc;
- }
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- tty_register_device(xencons_driver, 0, NULL);
-#endif
-
- if ( xen_start_info->flags & SIF_INITDOMAIN )
- {
- xencons_priv_irq = bind_virq_to_irq(VIRQ_CONSOLE);
- (void)request_irq(xencons_priv_irq,
- xencons_priv_interrupt, 0, "console", NULL);
- }
- else
- {
-
- xencons_ring_register_receiver(xencons_rx);
- }
-
- printk("Xen virtual console successfully installed as %s%d\n",
- DRV(xencons_driver)->name,
- DRV(xencons_driver)->name_base );
+ xencons_driver.open = xencons_open;
+ xencons_driver.close = xencons_close;
+ xencons_driver.write = xencons_write;
+ xencons_driver.write_room = xencons_write_room;
+ xencons_driver.put_char = xencons_put_char;
+ xencons_driver.flush_chars = xencons_flush_chars;
+ xencons_driver.chars_in_buffer = xencons_chars_in_buffer;
+ xencons_driver.send_xchar = xencons_send_xchar;
+ xencons_driver.flush_buffer = xencons_flush_buffer;
+ xencons_driver.throttle = xencons_throttle;
+ xencons_driver.unthrottle = xencons_unthrottle;
+ xencons_driver.wait_until_sent = xencons_wait_until_sent;
+#endif
+
+ if ((rc = tty_register_driver(DRV(xencons_driver))) != 0) {
+ printk("WARNING: Failed to register Xen virtual "
+ "console driver as '%s%d'\n",
+ DRV(xencons_driver)->name, DRV(xencons_driver)->name_base);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ put_tty_driver(xencons_driver);
+ xencons_driver = NULL;
+#endif
+ return rc;
+ }
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ tty_register_device(xencons_driver, 0, NULL);
+#endif
+
+ if (xen_start_info->flags & SIF_INITDOMAIN) {
+ xencons_priv_irq = bind_virq_to_irq(VIRQ_CONSOLE);
+ (void)request_irq(xencons_priv_irq,
+ xencons_priv_interrupt, 0, "console", NULL);
+ } else {
+ xencons_ring_register_receiver(xencons_rx);
+ }
+
+ printk("Xen virtual console successfully installed as %s%d\n",
+ DRV(xencons_driver)->name,
+ DRV(xencons_driver)->name_base );

- return 0;
+ return 0;
}

module_init(xencons_init);
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r eba5afe9aa37 -r 10759a44ce3b linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.c
--- a/linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.c Thu Sep 22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.c Thu Sep 22 15:12:14 2005
@@ -125,3 +125,13 @@

(void)xencons_ring_init();
}
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r eba5afe9aa37 -r 10759a44ce3b linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.h
--- a/linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.h Thu Sep 22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.h Thu Sep 22 15:12:14 2005
@@ -3,12 +3,21 @@

asmlinkage int xprintk(const char *fmt, ...);

-
int xencons_ring_init(void);
int xencons_ring_send(const char *data, unsigned len);

-typedef void (xencons_receiver_func)(char *buf, unsigned len,
- struct pt_regs *regs);
+typedef void (xencons_receiver_func)(
+ char *buf, unsigned len, struct pt_regs *regs);
void xencons_ring_register_receiver(xencons_receiver_func *f);

#endif /* _XENCONS_RING_H */
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r eba5afe9aa37 -r 10759a44ce3b linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c
--- a/linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c Thu Sep 22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c Thu Sep 22 15:12:14 2005
@@ -1,9 +1,9 @@
/******************************************************************************
* evtchn.c
*
- * Xenolinux driver for receiving and demuxing event-channel signals.
- *
- * Copyright (c) 2004, K A Fraser
+ * Driver for receiving and demuxing event-channel signals.
+ *
+ * Copyright (c) 2004-2005, K A Fraser
* Multi-process extensions Copyright (c) 2004, Steven Smith
*
* This file may be distributed separately from the Linux kernel, or
@@ -46,29 +46,18 @@
#include <linux/init.h>
#define XEN_EVTCHN_MASK_OPS
#include <asm-xen/evtchn.h>
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
-#include <linux/devfs_fs_kernel.h>
-#define OLD_DEVFS
-#else
#include <linux/gfp.h>
-#endif
-
-#ifdef OLD_DEVFS
-/* NB. This must be shared amongst drivers if more things go in /dev/xen */
-static devfs_handle_t xen_dev_dir;
-#endif

struct per_user_data {
- /* Notification ring, accessed via /dev/xen/evtchn. */
-# define EVTCHN_RING_SIZE 2048 /* 2048 16-bit entries */
-# define EVTCHN_RING_MASK(_i) ((_i)&(EVTCHN_RING_SIZE-1))
- u16 *ring;
- unsigned int ring_cons, ring_prod, ring_overflow;
-
- /* Processes wait on this queue when ring is empty. */
- wait_queue_head_t evtchn_wait;
- struct fasync_struct *evtchn_async_queue;
+ /* Notification ring, accessed via /dev/xen/evtchn. */
+#define EVTCHN_RING_SIZE 2048 /* 2048 16-bit entries */
+#define EVTCHN_RING_MASK(_i) ((_i)&(EVTCHN_RING_SIZE-1))
+ u16 *ring;
+ unsigned int ring_cons, ring_prod, ring_overflow;
+
+ /* Processes wait on this queue when ring is empty. */
+ wait_queue_head_t evtchn_wait;
+ struct fasync_struct *evtchn_async_queue;
};

/* Who's bound to each port? */
@@ -77,356 +66,310 @@

void evtchn_device_upcall(int port)
{
- struct per_user_data *u;
-
- spin_lock(&port_user_lock);
-
- mask_evtchn(port);
- clear_evtchn(port);
-
- if ( (u = port_user[port]) != NULL )
- {
- if ( (u->ring_prod - u->ring_cons) < EVTCHN_RING_SIZE )
- {
- u->ring[EVTCHN_RING_MASK(u->ring_prod)] = (u16)port;
- if ( u->ring_cons == u->ring_prod++ )
- {
- wake_up_interruptible(&u->evtchn_wait);
- kill_fasync(&u->evtchn_async_queue, SIGIO, POLL_IN);
- }
- }
- else
- {
- u->ring_overflow = 1;
- }
- }
-
- spin_unlock(&port_user_lock);
+ struct per_user_data *u;
+
+ spin_lock(&port_user_lock);
+
+ mask_evtchn(port);
+ clear_evtchn(port);
+
+ if ((u = port_user[port]) != NULL) {
+ if ((u->ring_prod - u->ring_cons) < EVTCHN_RING_SIZE) {
+ u->ring[EVTCHN_RING_MASK(u->ring_prod)] = (u16)port;
+ if (u->ring_cons == u->ring_prod++) {
+ wake_up_interruptible(&u->evtchn_wait);
+ kill_fasync(&u->evtchn_async_queue, SIGIO, POLL_IN);
+ }
+ } else {
+ u->ring_overflow = 1;
+ }
+ }
+
+ spin_unlock(&port_user_lock);
}

static ssize_t evtchn_read(struct file *file, char *buf,
size_t count, loff_t *ppos)
{
- int rc;
- unsigned int c, p, bytes1 = 0, bytes2 = 0;
- DECLARE_WAITQUEUE(wait, current);
- struct per_user_data *u = file->private_data;
-
- add_wait_queue(&u->evtchn_wait, &wait);
-
- count &= ~1; /* even number of bytes */
-
- if ( count == 0 )
- {
- rc = 0;
- goto out;
- }
-
- if ( count > PAGE_SIZE )
- count = PAGE_SIZE;
-
- for ( ; ; )
- {
- set_current_state(TASK_INTERRUPTIBLE);
-
- if ( (c = u->ring_cons) != (p = u->ring_prod) )
- break;
-
- if ( u->ring_overflow )
- {
- rc = -EFBIG;
- goto out;
- }
-
- if ( file->f_flags & O_NONBLOCK )
- {
- rc = -EAGAIN;
- goto out;
- }
-
- if ( signal_pending(current) )
- {
- rc = -ERESTARTSYS;
- goto out;
- }
-
- schedule();
- }
-
- /* Byte lengths of two chunks. Chunk split (if any) is at ring wrap. */
- if ( ((c ^ p) & EVTCHN_RING_SIZE) != 0 )
- {
- bytes1 = (EVTCHN_RING_SIZE - EVTCHN_RING_MASK(c)) * sizeof(u16);
- bytes2 = EVTCHN_RING_MASK(p) * sizeof(u16);
- }
- else
- {
- bytes1 = (p - c) * sizeof(u16);
- bytes2 = 0;
- }
-
- /* Truncate chunks according to caller's maximum byte count. */
- if ( bytes1 > count )
- {
- bytes1 = count;
- bytes2 = 0;
- }
- else if ( (bytes1 + bytes2) > count )
- {
- bytes2 = count - bytes1;
- }
-
- if ( copy_to_user(buf, &u->ring[EVTCHN_RING_MASK(c)], bytes1) ||
- ((bytes2 != 0) && copy_to_user(&buf[bytes1], &u->ring[0], bytes2)) )
- {
- rc = -EFAULT;
- goto out;
- }
-
- u->ring_cons += (bytes1 + bytes2) / sizeof(u16);
-
- rc = bytes1 + bytes2;
+ int rc;
+ unsigned int c, p, bytes1 = 0, bytes2 = 0;
+ DECLARE_WAITQUEUE(wait, current);
+ struct per_user_data *u = file->private_data;
+
+ add_wait_queue(&u->evtchn_wait, &wait);
+
+ count &= ~1; /* even number of bytes */
+
+ if (count == 0) {
+ rc = 0;
+ goto out;
+ }
+
+ if (count > PAGE_SIZE)
+ count = PAGE_SIZE;
+
+ for (;;) {
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ if ((c = u->ring_cons) != (p = u->ring_prod))
+ break;
+
+ if (u->ring_overflow) {
+ rc = -EFBIG;
+ goto out;
+ }
+
+ if (file->f_flags & O_NONBLOCK) {
+ rc = -EAGAIN;
+ goto out;
+ }
+
+ if (signal_pending(current)) {
+ rc = -ERESTARTSYS;
+ goto out;
+ }
+
+ schedule();
+ }
+
+ /* Byte lengths of two chunks. Chunk split (if any) is at ring wrap. */
+ if (((c ^ p) & EVTCHN_RING_SIZE) != 0) {
+ bytes1 = (EVTCHN_RING_SIZE - EVTCHN_RING_MASK(c)) *
+ sizeof(u16);
+ bytes2 = EVTCHN_RING_MASK(p) * sizeof(u16);
+ } else {
+ bytes1 = (p - c) * sizeof(u16);
+ bytes2 = 0;
+ }
+
+ /* Truncate chunks according to caller's maximum byte count. */
+ if (bytes1 > count) {
+ bytes1 = count;
+ bytes2 = 0;
+ } else if ((bytes1 + bytes2) > count) {
+ bytes2 = count - bytes1;
+ }
+
+ if (copy_to_user(buf, &u->ring[EVTCHN_RING_MASK(c)], bytes1) ||
+ ((bytes2 != 0) &&
+ copy_to_user(&buf[bytes1], &u->ring[0], bytes2))) {
+ rc = -EFAULT;
+ goto out;
+ }
+
+ u->ring_cons += (bytes1 + bytes2) / sizeof(u16);
+
+ rc = bytes1 + bytes2;

out:
- __set_current_state(TASK_RUNNING);
- remove_wait_queue(&u->evtchn_wait, &wait);
- return rc;
+ __set_current_state(TASK_RUNNING);
+ remove_wait_queue(&u->evtchn_wait, &wait);
+ return rc;
}

static ssize_t evtchn_write(struct file *file, const char *buf,
size_t count, loff_t *ppos)
{
- int rc, i;
- u16 *kbuf = (u16 *)__get_free_page(GFP_KERNEL);
- struct per_user_data *u = file->private_data;
-
- if ( kbuf == NULL )
- return -ENOMEM;
-
- count &= ~1; /* even number of bytes */
-
- if ( count == 0 )
- {
- rc = 0;
- goto out;
- }
-
- if ( count > PAGE_SIZE )
- count = PAGE_SIZE;
-
- if ( copy_from_user(kbuf, buf, count) != 0 )
- {
- rc = -EFAULT;
- goto out;
- }
-
- spin_lock_irq(&port_user_lock);
- for ( i = 0; i < (count/2); i++ )
- if ( (kbuf[i] < NR_EVENT_CHANNELS) && (port_user[kbuf[i]] == u) )
- unmask_evtchn(kbuf[i]);
- spin_unlock_irq(&port_user_lock);
-
- rc = count;
+ int rc, i;
+ u16 *kbuf = (u16 *)__get_free_page(GFP_KERNEL);
+ struct per_user_data *u = file->private_data;
+
+ if (kbuf == NULL)
+ return -ENOMEM;
+
+ count &= ~1; /* even number of bytes */
+
+ if (count == 0) {
+ rc = 0;
+ goto out;
+ }
+
+ if (count > PAGE_SIZE)
+ count = PAGE_SIZE;
+
+ if (copy_from_user(kbuf, buf, count) != 0) {
+ rc = -EFAULT;
+ goto out;
+ }
+
+ spin_lock_irq(&port_user_lock);
+ for (i = 0; i < (count/2); i++)
+ if ((kbuf[i] < NR_EVENT_CHANNELS) && (port_user[kbuf[i]] == u))
+ unmask_evtchn(kbuf[i]);
+ spin_unlock_irq(&port_user_lock);
+
+ rc = count;

out:
- free_page((unsigned long)kbuf);
- return rc;
+ free_page((unsigned long)kbuf);
+ return rc;
}

static int evtchn_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
- int rc = 0;
- struct per_user_data *u = file->private_data;
-
- spin_lock_irq(&port_user_lock);
+ int rc = 0;
+ struct per_user_data *u = file->private_data;
+
+ spin_lock_irq(&port_user_lock);

- switch ( cmd )
- {
- case EVTCHN_RESET:
- /* Initialise the ring to empty. Clear errors. */
- u->ring_cons = u->ring_prod = u->ring_overflow = 0;
- break;
-
- case EVTCHN_BIND:
- if ( arg >= NR_EVENT_CHANNELS )
- {
- rc = -EINVAL;
- }
- else if ( port_user[arg] != NULL )
- {
- rc = -EISCONN;
- }
- else
- {
- port_user[arg] = u;
- unmask_evtchn(arg);
- }
- break;
-
- case EVTCHN_UNBIND:
- if ( arg >= NR_EVENT_CHANNELS )
- {
- rc = -EINVAL;
- }
- else if ( port_user[arg] != u )
- {
- rc = -ENOTCONN;
- }
- else
- {
- port_user[arg] = NULL;
- mask_evtchn(arg);
- }
- break;
-
- default:
- rc = -ENOSYS;
- break;
- }
-
- spin_unlock_irq(&port_user_lock);
-
- return rc;
+ switch (cmd) {
+ case EVTCHN_RESET:
+ /* Initialise the ring to empty. Clear errors. */
+ u->ring_cons = u->ring_prod = u->ring_overflow = 0;
+ break;
+
+ case EVTCHN_BIND:
+ if (arg >= NR_EVENT_CHANNELS) {
+ rc = -EINVAL;
+ } else if (port_user[arg] != NULL) {
+ rc = -EISCONN;
+ } else {
+ port_user[arg] = u;
+ unmask_evtchn(arg);
+ }
+ break;
+
+ case EVTCHN_UNBIND:
+ if (arg >= NR_EVENT_CHANNELS) {
+ rc = -EINVAL;
+ } else if (port_user[arg] != u) {
+ rc = -ENOTCONN;
+ } else {
+ port_user[arg] = NULL;
+ mask_evtchn(arg);
+ }
+ break;
+
+ default:
+ rc = -ENOSYS;
+ break;
+ }
+
+ spin_unlock_irq(&port_user_lock);
+
+ return rc;
}

static unsigned int evtchn_poll(struct file *file, poll_table *wait)
{
- unsigned int mask = POLLOUT | POLLWRNORM;
- struct per_user_data *u = file->private_data;
-
- poll_wait(file, &u->evtchn_wait, wait);
- if ( u->ring_cons != u->ring_prod )
- mask |= POLLIN | POLLRDNORM;
- if ( u->ring_overflow )
- mask = POLLERR;
- return mask;
+ unsigned int mask = POLLOUT | POLLWRNORM;
+ struct per_user_data *u = file->private_data;
+
+ poll_wait(file, &u->evtchn_wait, wait);
+ if (u->ring_cons != u->ring_prod)
+ mask |= POLLIN | POLLRDNORM;
+ if (u->ring_overflow)
+ mask = POLLERR;
+ return mask;
}

static int evtchn_fasync(int fd, struct file *filp, int on)
{
- struct per_user_data *u = filp->private_data;
- return fasync_helper(fd, filp, on, &u->evtchn_async_queue);
+ struct per_user_data *u = filp->private_data;
+ return fasync_helper(fd, filp, on, &u->evtchn_async_queue);
}

static int evtchn_open(struct inode *inode, struct file *filp)
{
- struct per_user_data *u;
-
- if ( (u = kmalloc(sizeof(*u), GFP_KERNEL)) == NULL )
- return -ENOMEM;
-
- memset(u, 0, sizeof(*u));
- init_waitqueue_head(&u->evtchn_wait);
-
- if ( (u->ring = (u16 *)__get_free_page(GFP_KERNEL)) == NULL )
- {
- kfree(u);
- return -ENOMEM;
- }
-
- filp->private_data = u;
-
- return 0;
+ struct per_user_data *u;
+
+ if ((u = kmalloc(sizeof(*u), GFP_KERNEL)) == NULL)
+ return -ENOMEM;
+
+ memset(u, 0, sizeof(*u));
+ init_waitqueue_head(&u->evtchn_wait);
+
+ if ((u->ring = (u16 *)__get_free_page(GFP_KERNEL)) == NULL)
+ {
+ kfree(u);
+ return -ENOMEM;
+ }
+
+ filp->private_data = u;
+
+ return 0;
}

static int evtchn_release(struct inode *inode, struct file *filp)
{
- int i;
- struct per_user_data *u = filp->private_data;
-
- spin_lock_irq(&port_user_lock);
-
- free_page((unsigned long)u->ring);
-
- for ( i = 0; i < NR_EVENT_CHANNELS; i++ )
- {
- if ( port_user[i] == u )
- {
- port_user[i] = NULL;
- mask_evtchn(i);
- }
- }
-
- spin_unlock_irq(&port_user_lock);
-
- kfree(u);
-
- return 0;
+ int i;
+ struct per_user_data *u = filp->private_data;
+
+ spin_lock_irq(&port_user_lock);
+
+ free_page((unsigned long)u->ring);
+
+ for (i = 0; i < NR_EVENT_CHANNELS; i++)
+ {
+ if (port_user[i] == u)
+ {
+ port_user[i] = NULL;
+ mask_evtchn(i);
+ }
+ }
+
+ spin_unlock_irq(&port_user_lock);
+
+ kfree(u);
+
+ return 0;
}

static struct file_operations evtchn_fops = {
- .owner = THIS_MODULE,
- .read = evtchn_read,
- .write = evtchn_write,
- .ioctl = evtchn_ioctl,
- .poll = evtchn_poll,
- .fasync = evtchn_fasync,
- .open = evtchn_open,
- .release = evtchn_release,
+ .owner = THIS_MODULE,
+ .read = evtchn_read,
+ .write = evtchn_write,
+ .ioctl = evtchn_ioctl,
+ .poll = evtchn_poll,
+ .fasync = evtchn_fasync,
+ .open = evtchn_open,
+ .release = evtchn_release,
};

static struct miscdevice evtchn_miscdev = {
- .minor = EVTCHN_MINOR,
- .name = "evtchn",
- .fops = &evtchn_fops,
+ .minor = EVTCHN_MINOR,
+ .name = "evtchn",
+ .fops = &evtchn_fops,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- .devfs_name = "misc/evtchn",
+ .devfs_name = "misc/evtchn",
#endif
};

static int __init evtchn_init(void)
{
-#ifdef OLD_DEVFS
- devfs_handle_t symlink_handle;
- int pos;
- char link_dest[64];
-#endif
- int err;
-
- spin_lock_init(&port_user_lock);
- memset(port_user, 0, sizeof(port_user));
-
- /* (DEVFS) create '/dev/misc/evtchn'. */
- err = misc_register(&evtchn_miscdev);
- if ( err != 0 )
- {
- printk(KERN_ALERT "Could not register /dev/misc/evtchn\n");
- return err;
- }
-
-#ifdef OLD_DEVFS
- /* (DEVFS) create directory '/dev/xen'. */
- xen_dev_dir = devfs_mk_dir(NULL, "xen", NULL);
-
- /* (DEVFS) &link_dest[pos] == '../misc/evtchn'. */
- pos = devfs_generate_path(evtchn_miscdev.devfs_handle,
- &link_dest[3],
- sizeof(link_dest) - 3);
- if ( pos >= 0 )
- strncpy(&link_dest[pos], "../", 3);
-
- /* (DEVFS) symlink '/dev/xen/evtchn' -> '../misc/evtchn'. */
- (void)devfs_mk_symlink(xen_dev_dir,
- "evtchn",
- DEVFS_FL_DEFAULT,
- &link_dest[pos],
- &symlink_handle,
- NULL);
-
- /* (DEVFS) automatically destroy the symlink with its destination. */
- devfs_auto_unregister(evtchn_miscdev.devfs_handle, symlink_handle);
-#endif
-
- printk("Event-channel device installed.\n");
-
- return 0;
+ int err;
+
+ spin_lock_init(&port_user_lock);
+ memset(port_user, 0, sizeof(port_user));
+
+ /* (DEVFS) create '/dev/misc/evtchn'. */
+ err = misc_register(&evtchn_miscdev);
+ if (err != 0)
+ {
+ printk(KERN_ALERT "Could not register /dev/misc/evtchn\n");
+ return err;
+ }
+
+ printk("Event-channel device installed.\n");
+
+ return 0;
}

static void evtchn_cleanup(void)
{
- misc_deregister(&evtchn_miscdev);
+ misc_deregister(&evtchn_miscdev);
}

module_init(evtchn_init);
module_exit(evtchn_cleanup);
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r eba5afe9aa37 -r 10759a44ce3b linux-2.6-xen-sparse/drivers/xen/netback/common.h
--- a/linux-2.6-xen-sparse/drivers/xen/netback/common.h Thu Sep 22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/common.h Thu Sep 22 15:12:14 2005
@@ -62,9 +62,7 @@
/* Private indexes into shared ring. */
NETIF_RING_IDX rx_req_cons;
NETIF_RING_IDX rx_resp_prod; /* private version of shared variable */
-#ifdef CONFIG_XEN_NETDEV_GRANT
NETIF_RING_IDX rx_resp_prod_copy;
-#endif
NETIF_RING_IDX tx_req_cons;
NETIF_RING_IDX tx_resp_prod; /* private version of shared variable */

diff -r eba5afe9aa37 -r 10759a44ce3b linux-2.6-xen-sparse/drivers/xen/netback/netback.c
--- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Thu Sep 22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Thu Sep 22 15:12:14 2005
@@ -23,7 +23,7 @@
static int make_rx_response(netif_t *netif,
u16 id,
s8 st,
- unsigned long addr,
+ u16 offset,
u16 size,
u16 csum_valid);

@@ -41,11 +41,7 @@
static multicall_entry_t rx_mcl[NETIF_RX_RING_SIZE*2+1];
static mmu_update_t rx_mmu[NETIF_RX_RING_SIZE];

-#ifdef CONFIG_XEN_NETDEV_GRANT
static gnttab_transfer_t grant_rx_op[MAX_PENDING_REQS];
-#else
-static struct mmuext_op rx_mmuext[NETIF_RX_RING_SIZE];
-#endif
static unsigned char rx_notify[NR_EVENT_CHANNELS];

/* Don't currently gate addition of an interface to the tx scheduling list. */
@@ -72,14 +68,9 @@

static struct sk_buff_head tx_queue;

-#ifdef CONFIG_XEN_NETDEV_GRANT
static u16 grant_tx_ref[MAX_PENDING_REQS];
static gnttab_unmap_grant_ref_t tx_unmap_ops[MAX_PENDING_REQS];
static gnttab_map_grant_ref_t tx_map_ops[MAX_PENDING_REQS];
-
-#else
-static multicall_entry_t tx_mcl[MAX_PENDING_REQS];
-#endif

static struct list_head net_schedule_list;
static spinlock_t net_schedule_list_lock;
@@ -108,7 +99,7 @@
return mfn;
}

-#ifndef CONFIG_XEN_NETDEV_GRANT
+#if 0
static void free_mfn(unsigned long mfn)
{
unsigned long flags;
@@ -180,18 +171,7 @@
dev_kfree_skb(skb);
skb = nskb;
}
-#ifdef CONFIG_XEN_NETDEV_GRANT
-#ifdef DEBUG_GRANT
- printk(KERN_ALERT "#### be_xmit: req_prod=%d req_cons=%d "
- "id=%04x gr=%04x\n",
- netif->rx->req_prod,
- netif->rx_req_cons,
- netif->rx->ring[
- MASK_NETIF_RX_IDX(netif->rx_req_cons)].req.id,
- netif->rx->ring[
- MASK_NETIF_RX_IDX(netif->rx_req_cons)].req.gref);
-#endif
-#endif
+
netif->rx_req_cons++;
netif_get(netif);

@@ -232,11 +212,7 @@
u16 size, id, evtchn;
multicall_entry_t *mcl;
mmu_update_t *mmu;
-#ifdef CONFIG_XEN_NETDEV_GRANT
gnttab_transfer_t *gop;
-#else
- struct mmuext_op *mmuext;
-#endif
unsigned long vdata, old_mfn, new_mfn;
struct sk_buff_head rxq;
struct sk_buff *skb;
@@ -247,11 +223,7 @@

mcl = rx_mcl;
mmu = rx_mmu;
-#ifdef CONFIG_XEN_NETDEV_GRANT
gop = grant_rx_op;
-#else
- mmuext = rx_mmuext;
-#endif

while ((skb = skb_dequeue(&rx_queue)) != NULL) {
netif = netdev_priv(skb->dev);
@@ -277,25 +249,13 @@
pfn_pte_ma(new_mfn, PAGE_KERNEL), 0);
mcl++;

-#ifdef CONFIG_XEN_NETDEV_GRANT
gop->mfn = old_mfn;
gop->domid = netif->domid;
gop->ref = netif->rx->ring[
MASK_NETIF_RX_IDX(netif->rx_resp_prod_copy)].req.gref;
netif->rx_resp_prod_copy++;
gop++;
-#else
- mcl->op = __HYPERVISOR_mmuext_op;
- mcl->args[0] = (unsigned long)mmuext;
- mcl->args[1] = 1;
- mcl->args[2] = 0;
- mcl->args[3] = netif->domid;
- mcl++;
-
- mmuext->cmd = MMUEXT_REASSIGN_PAGE;
- mmuext->arg1.mfn = old_mfn;
- mmuext++;
-#endif
+
mmu->ptr = ((maddr_t)new_mfn << PAGE_SHIFT) |
MMU_MACHPHYS_UPDATE;
mmu->val = __pa(vdata) >> PAGE_SHIFT;
@@ -303,9 +263,6 @@

__skb_queue_tail(&rxq, skb);

-#ifdef DEBUG_GRANT
- dump_packet('a', old_mfn, vdata);
-#endif
/* Filled the batch queue? */
if ((mcl - rx_mcl) == ARRAY_SIZE(rx_mcl))
break;
@@ -321,17 +278,12 @@
mcl->args[3] = DOMID_SELF;
mcl++;

-#ifdef CONFIG_XEN_NETDEV_GRANT
mcl[-2].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_ALL;
-#else
- mcl[-3].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_ALL;
-#endif
BUG_ON(HYPERVISOR_multicall(rx_mcl, mcl - rx_mcl) != 0);

mcl = rx_mcl;
-#ifdef CONFIG_XEN_NETDEV_GRANT
- if(HYPERVISOR_grant_table_op(GNTTABOP_transfer, grant_rx_op,
- gop - grant_rx_op)) {
+ if( HYPERVISOR_grant_table_op(GNTTABOP_transfer, grant_rx_op,
+ gop - grant_rx_op)) {
/*
* The other side has given us a bad grant ref, or has no
* headroom, or has gone away. Unfortunately the current grant
@@ -343,20 +295,14 @@
grant_rx_op[0].domid, gop - grant_rx_op);
}
gop = grant_rx_op;
-#else
- mmuext = rx_mmuext;
-#endif
+
while ((skb = __skb_dequeue(&rxq)) != NULL) {
netif = netdev_priv(skb->dev);
size = skb->tail - skb->data;

/* Rederive the machine addresses. */
new_mfn = mcl[0].args[1] >> PAGE_SHIFT;
-#ifdef CONFIG_XEN_NETDEV_GRANT
old_mfn = 0; /* XXX Fix this so we can free_mfn() on error! */
-#else
- old_mfn = mmuext[0].arg1.mfn;
-#endif
atomic_set(&(skb_shinfo(skb)->dataref), 1);
skb_shinfo(skb)->nr_frags = 0;
skb_shinfo(skb)->frag_list = NULL;
@@ -369,27 +315,17 @@

/* Check the reassignment error code. */
status = NETIF_RSP_OKAY;
-#ifdef CONFIG_XEN_NETDEV_GRANT
if(gop->status != 0) {
DPRINTK("Bad status %d from grant transfer to DOM%u\n",
gop->status, netif->domid);
/* XXX SMH: should free 'old_mfn' here */
status = NETIF_RSP_ERROR;
}
-#else
- if (unlikely(mcl[1].result != 0)) {
- DPRINTK("Failed MMU update transferring to DOM%u\n",
- netif->domid);
- free_mfn(old_mfn);
- status = NETIF_RSP_ERROR;
- }
-#endif
evtchn = netif->evtchn;
id = netif->rx->ring[
MASK_NETIF_RX_IDX(netif->rx_resp_prod)].req.id;
if (make_rx_response(netif, id, status,
- (old_mfn << PAGE_SHIFT) | /* XXX */
- ((unsigned long)skb->data & ~PAGE_MASK),
+ (unsigned long)skb->data & ~PAGE_MASK,
size, skb->proto_csum_valid) &&
(rx_notify[evtchn] == 0)) {
rx_notify[evtchn] = 1;
@@ -398,13 +334,8 @@

netif_put(netif);
dev_kfree_skb(skb);
-#ifdef CONFIG_XEN_NETDEV_GRANT
mcl++;
gop++;
-#else
- mcl += 2;
- mmuext += 1;
-#endif
}

while (notify_nr != 0) {
@@ -486,11 +417,7 @@

inline static void net_tx_action_dealloc(void)
{
-#ifdef CONFIG_XEN_NETDEV_GRANT
gnttab_unmap_grant_ref_t *gop;
-#else
- multicall_entry_t *mcl;
-#endif
u16 pending_idx;
PEND_RING_IDX dc, dp;
netif_t *netif;
@@ -498,7 +425,6 @@
dc = dealloc_cons;
dp = dealloc_prod;

-#ifdef CONFIG_XEN_NETDEV_GRANT
/*
* Free up any grants we have finished using
*/
@@ -513,26 +439,8 @@
}
BUG_ON(HYPERVISOR_grant_table_op(
GNTTABOP_unmap_grant_ref, tx_unmap_ops, gop - tx_unmap_ops));
-#else
- mcl = tx_mcl;
- while (dc != dp) {
- pending_idx = dealloc_ring[MASK_PEND_IDX(dc++)];
- MULTI_update_va_mapping(mcl, MMAP_VADDR(pending_idx),
- __pte(0), 0);
- mcl++;
- }
-
- mcl[-1].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_ALL;
- BUG_ON(HYPERVISOR_multicall(tx_mcl, mcl - tx_mcl) != 0);
-
- mcl = tx_mcl;
-#endif
+
while (dealloc_cons != dp) {
-#ifndef CONFIG_XEN_NETDEV_GRANT
- /* The update_va_mapping() must not fail. */
- BUG_ON(mcl[0].result != 0);
-#endif
-
pending_idx = dealloc_ring[MASK_PEND_IDX(dealloc_cons++)];

netif = pending_tx_info[pending_idx].netif;
@@ -556,10 +464,6 @@
add_to_net_schedule_list_tail(netif);

netif_put(netif);
-
-#ifndef CONFIG_XEN_NETDEV_GRANT
- mcl++;
-#endif
}
}

@@ -572,21 +476,13 @@
netif_tx_request_t txreq;
u16 pending_idx;
NETIF_RING_IDX i;
-#ifdef CONFIG_XEN_NETDEV_GRANT
gnttab_map_grant_ref_t *mop;
-#else
- multicall_entry_t *mcl;
-#endif
unsigned int data_len;

if (dealloc_cons != dealloc_prod)
net_tx_action_dealloc();

-#ifdef CONFIG_XEN_NETDEV_GRANT
mop = tx_map_ops;
-#else
- mcl = tx_mcl;
-#endif
while ((NR_PENDING_REQS < MAX_PENDING_REQS) &&
!list_empty(&net_schedule_list)) {
/* Get a netif from the list with work to do. */
@@ -657,8 +553,7 @@
}

/* No crossing a page as the payload mustn't fragment. */
- if (unlikely(((txreq.addr & ~PAGE_MASK) + txreq.size) >=
- PAGE_SIZE)) {
+ if (unlikely((txreq.offset + txreq.size) >= PAGE_SIZE)) {
DPRINTK("txreq.addr: %lx, size: %u, end: %lu\n",
txreq.addr, txreq.size,
(txreq.addr &~PAGE_MASK) + txreq.size);
@@ -682,20 +577,12 @@

/* Packets passed to netif_rx() must have some headroom. */
skb_reserve(skb, 16);
-#ifdef CONFIG_XEN_NETDEV_GRANT
+
mop->host_addr = MMAP_VADDR(pending_idx);
mop->dom = netif->domid;
- mop->ref = txreq.addr >> PAGE_SHIFT;
+ mop->ref = txreq.gref;
mop->flags = GNTMAP_host_map | GNTMAP_readonly;
mop++;
-#else
- MULTI_update_va_mapping_otherdomain(
- mcl, MMAP_VADDR(pending_idx),
- pfn_pte_ma(txreq.addr >> PAGE_SHIFT, PAGE_KERNEL),
- 0, netif->domid);
-
- mcl++;
-#endif

memcpy(&pending_tx_info[pending_idx].req,
&txreq, sizeof(txreq));
@@ -706,17 +593,10 @@

pending_cons++;

-#ifdef CONFIG_XEN_NETDEV_GRANT
if ((mop - tx_map_ops) >= ARRAY_SIZE(tx_map_ops))
break;
-#else
- /* Filled the batch queue? */
- if ((mcl - tx_mcl) == ARRAY_SIZE(tx_mcl))
- break;
-#endif
- }
-
-#ifdef CONFIG_XEN_NETDEV_GRANT
+ }
+
if (mop == tx_map_ops)
return;

@@ -724,14 +604,6 @@
GNTTABOP_map_grant_ref, tx_map_ops, mop - tx_map_ops));

mop = tx_map_ops;
-#else
- if (mcl == tx_mcl)
- return;
-
- BUG_ON(HYPERVISOR_multicall(tx_mcl, mcl - tx_mcl) != 0);
-
- mcl = tx_mcl;
-#endif
while ((skb = __skb_dequeue(&tx_queue)) != NULL) {
pending_idx = *((u16 *)skb->data);
netif = pending_tx_info[pending_idx].netif;
@@ -739,7 +611,6 @@
sizeof(txreq));

/* Check the remap error code. */
-#ifdef CONFIG_XEN_NETDEV_GRANT
if (unlikely(mop->handle < 0)) {
printk(KERN_ALERT "#### netback grant fails\n");
make_tx_response(netif, txreq.id, NETIF_RSP_ERROR);
@@ -754,30 +625,13 @@
__pa(MMAP_VADDR(pending_idx)) >> PAGE_SHIFT] =
FOREIGN_FRAME(mop->dev_bus_addr >> PAGE_SHIFT);
grant_tx_ref[pending_idx] = mop->handle;
-#else
- if (unlikely(mcl[0].result != 0)) {
- DPRINTK("Bad page frame\n");
- make_tx_response(netif, txreq.id, NETIF_RSP_ERROR);
- netif_put(netif);
- kfree_skb(skb);
- mcl++;
- pending_ring[MASK_PEND_IDX(pending_prod++)] =
- pending_idx;
- continue;
- }
-
- phys_to_machine_mapping[__pa(MMAP_VADDR(pending_idx)) >>
- PAGE_SHIFT] =
- FOREIGN_FRAME(txreq.addr >> PAGE_SHIFT);
-#endif

data_len = (txreq.size > PKT_PROT_LEN) ?
PKT_PROT_LEN : txreq.size;

__skb_put(skb, data_len);
memcpy(skb->data,
- (void *)(MMAP_VADDR(pending_idx)|
- (txreq.addr&~PAGE_MASK)),
+ (void *)(MMAP_VADDR(pending_idx)|txreq.offset),
data_len);
if (data_len < txreq.size) {
/* Append the packet payload as a fragment. */
@@ -786,7 +640,7 @@
skb_shinfo(skb)->frags[0].size =
txreq.size - data_len;
skb_shinfo(skb)->frags[0].page_offset =
- (txreq.addr + data_len) & ~PAGE_MASK;
+ txreq.offset + data_len;
skb_shinfo(skb)->nr_frags = 1;
} else {
/* Schedule a response immediately. */
@@ -813,11 +667,7 @@
netif_rx(skb);
netif->dev->last_rx = jiffies;

-#ifdef CONFIG_XEN_NETDEV_GRANT
mop++;
-#else
- mcl++;
-#endif
}
}

@@ -874,7 +724,7 @@
static int make_rx_response(netif_t *netif,
u16 id,
s8 st,
- unsigned long addr,
+ u16 offset,
u16 size,
u16 csum_valid)
{
@@ -882,7 +732,7 @@
netif_rx_response_t *resp;

resp = &netif->rx->ring[MASK_NETIF_RX_IDX(i)].resp;
- resp->addr = addr;
+ resp->offset = offset;
resp->csum_valid = csum_valid;
resp->id = id;
resp->status = (s16)size;
@@ -937,9 +787,6 @@
return 0;

IPRINTK("Initialising Xen netif backend.\n");
-#ifdef CONFIG_XEN_NETDEV_GRANT
- IPRINTK("Using grant tables.\n");
-#endif

/* We can increase reservation by this much in net_rx_action(). */
balloon_update_driver_allowance(NETIF_RX_RING_SIZE);
diff -r eba5afe9aa37 -r 10759a44ce3b linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c
--- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Thu Sep 22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Thu Sep 22 15:12:14 2005
@@ -256,8 +256,8 @@
for (i = np->tx_resp_cons; i != prod; i++) {
id = np->tx->ring[MASK_NETIF_TX_IDX(i)].resp.id;
skb = np->tx_skbs[id];
-#ifdef CONFIG_XEN_NETDEV_GRANT
- if (unlikely(gnttab_query_foreign_access(np->grant_tx_ref[id]) != 0)) {
+ if (unlikely(gnttab_query_foreign_access(
+ np->grant_tx_ref[id]) != 0)) {
printk(KERN_ALERT "network_tx_buf_gc: warning "
"-- grant still in use by backend "
"domain.\n");
@@ -268,7 +268,6 @@
gnttab_release_grant_reference(
&np->gref_tx_head, np->grant_tx_ref[id]);
np->grant_tx_ref[id] = GRANT_INVALID_REF;
-#endif
ADD_ID_TO_FREELIST(np->tx_skbs, id);
dev_kfree_skb_irq(skb);
}
@@ -287,10 +286,7 @@
mb();
} while (prod != np->tx->resp_prod);

-#ifdef CONFIG_XEN_NETDEV_GRANT
out:
-#endif
-
if (np->tx_full && ((np->tx->req_prod - prod) < NETIF_TX_RING_SIZE)) {
np->tx_full = 0;
if (np->user_state == UST_OPEN)
@@ -307,9 +303,7 @@
int i, batch_target;
NETIF_RING_IDX req_prod = np->rx->req_prod;
struct xen_memory_reservation reservation;
-#ifdef CONFIG_XEN_NETDEV_GRANT
grant_ref_t ref;
-#endif

if (unlikely(np->backend_state != BEST_CONNECTED))
return;
@@ -343,13 +337,11 @@
np->rx_skbs[id] = skb;

np->rx->ring[MASK_NETIF_RX_IDX(req_prod + i)].req.id = id;
-#ifdef CONFIG_XEN_NETDEV_GRANT
ref = gnttab_claim_grant_reference(&np->gref_rx_head);
BUG_ON((signed short)ref < 0);
np->grant_rx_ref[id] = ref;
gnttab_grant_foreign_transfer_ref(ref, np->backend_id);
np->rx->ring[MASK_NETIF_RX_IDX(req_prod + i)].req.gref = ref;
-#endif
rx_pfn_array[i] = virt_to_mfn(skb->head);

/* Remove this page from map before passing back to Xen. */
@@ -400,10 +392,8 @@
struct net_private *np = netdev_priv(dev);
netif_tx_request_t *tx;
NETIF_RING_IDX i;
-#ifdef CONFIG_XEN_NETDEV_GRANT
grant_ref_t ref;
unsigned long mfn;
-#endif

if (unlikely(np->tx_full)) {
printk(KERN_ALERT "%s: full queue wasn't stopped!\n",
@@ -439,18 +429,13 @@
tx = &np->tx->ring[MASK_NETIF_TX_IDX(i)].req;

tx->id = id;
-#ifdef CONFIG_XEN_NETDEV_GRANT
ref = gnttab_claim_grant_reference(&np->gref_tx_head);
BUG_ON((signed short)ref < 0);
mfn = virt_to_mfn(skb->data);
gnttab_grant_foreign_access_ref(
ref, np->backend_id, mfn, GNTMAP_readonly);
- tx->addr = ref << PAGE_SHIFT;
- np->grant_tx_ref[id] = ref;
-#else
- tx->addr = virt_to_mfn(skb->data) << PAGE_SHIFT;
-#endif
- tx->addr |= (unsigned long)skb->data & ~PAGE_MASK;
+ tx->gref = np->grant_tx_ref[id] = ref;
+ tx->offset = (unsigned long)skb->data & ~PAGE_MASK;
tx->size = skb->len;
tx->csum_blank = (skb->ip_summed == CHECKSUM_HW);

@@ -511,10 +496,8 @@
int work_done, budget, more_to_do = 1;
struct sk_buff_head rxq;
unsigned long flags;
-#ifdef CONFIG_XEN_NETDEV_GRANT
unsigned long mfn;
grant_ref_t ref;
-#endif

spin_lock(&np->rx_lock);

@@ -550,7 +533,6 @@
continue;
}

-#ifdef CONFIG_XEN_NETDEV_GRANT
ref = np->grant_rx_ref[rx->id];

if(ref == GRANT_INVALID_REF) {
@@ -568,17 +550,12 @@
np->grant_rx_ref[rx->id] = GRANT_INVALID_REF;
mfn = gnttab_end_foreign_transfer_ref(ref);
gnttab_release_grant_reference(&np->gref_rx_head, ref);
-#endif

skb = np->rx_skbs[rx->id];
ADD_ID_TO_FREELIST(np->rx_skbs, rx->id);

/* NB. We handle skb overflow later. */
-#ifdef CONFIG_XEN_NETDEV_GRANT
- skb->data = skb->head + rx->addr;
-#else
- skb->data = skb->head + (rx->addr & ~PAGE_MASK);
-#endif
+ skb->data = skb->head + rx->offset;
skb->len = rx->status;
skb->tail = skb->data + skb->len;

@@ -589,30 +566,14 @@
np->stats.rx_bytes += rx->status;

/* Remap the page. */
-#ifdef CONFIG_XEN_NETDEV_GRANT
mmu->ptr = ((maddr_t)mfn << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE;
-#else
- mmu->ptr = (rx->addr & PAGE_MASK) | MMU_MACHPHYS_UPDATE;
-#endif
mmu->val = __pa(skb->head) >> PAGE_SHIFT;
mmu++;
-#ifdef CONFIG_XEN_NETDEV_GRANT
MULTI_update_va_mapping(mcl, (unsigned long)skb->head,
pfn_pte_ma(mfn, PAGE_KERNEL), 0);
-#else
- MULTI_update_va_mapping(mcl, (unsigned long)skb->head,
- pfn_pte_ma(rx->addr >> PAGE_SHIFT,
- PAGE_KERNEL), 0);
-#endif
mcl++;

-#ifdef CONFIG_XEN_NETDEV_GRANT
phys_to_machine_mapping[__pa(skb->head) >> PAGE_SHIFT] = mfn;
-#else
- phys_to_machine_mapping[__pa(skb->head) >> PAGE_SHIFT] =
- rx->addr >> PAGE_SHIFT;
-#endif
-

__skb_queue_tail(&rxq, skb);
}
@@ -773,16 +734,12 @@
tx = &np->tx->ring[requeue_idx++].req;

tx->id = i;
-#ifdef CONFIG_XEN_NETDEV_GRANT
gnttab_grant_foreign_access_ref(
np->grant_tx_ref[i], np->backend_id,
virt_to_mfn(np->tx_skbs[i]->data),
GNTMAP_readonly);
- tx->addr = np->grant_tx_ref[i] << PAGE_SHIFT;
-#else
- tx->addr = virt_to_mfn(skb->data) << PAGE_SHIFT;
-#endif
- tx->addr |= (unsigned long)skb->data & ~PAGE_MASK;
+ tx->gref = np->grant_tx_ref[i];
+ tx->offset = (unsigned long)skb->data & ~PAGE_MASK;
tx->size = skb->len;

np->stats.tx_bytes += skb->len;
@@ -795,12 +752,10 @@
/* Rebuild the RX buffer freelist and the RX ring itself. */
for (requeue_idx = 0, i = 1; i <= NETIF_RX_RING_SIZE; i++) {
if ((unsigned long)np->rx_skbs[i] >= __PAGE_OFFSET) {
-#ifdef CONFIG_XEN_NETDEV_GRANT
gnttab_grant_foreign_transfer_ref(
np->grant_rx_ref[i], np->backend_id);
np->rx->ring[requeue_idx].req.gref =
np->grant_rx_ref[i];
-#endif
np->rx->ring[requeue_idx].req.id = i;
requeue_idx++;
}
@@ -862,11 +817,9 @@

static void netif_uninit(struct net_device *dev)
{
-#ifdef CONFIG_XEN_NETDEV_GRANT
struct net_private *np = netdev_priv(dev);
gnttab_free_grant_references(np->gref_tx_head);
gnttab_free_grant_references(np->gref_rx_head);
-#endif
}

static struct ethtool_ops network_ethtool_ops =
@@ -911,19 +864,14 @@
/* Initialise {tx,rx}_skbs as a free chain containing every entry. */
for (i = 0; i <= NETIF_TX_RING_SIZE; i++) {
np->tx_skbs[i] = (void *)((unsigned long) i+1);
-#ifdef CONFIG_XEN_NETDEV_GRANT
np->grant_tx_ref[i] = GRANT_INVALID_REF;
-#endif
}

for (i = 0; i <= NETIF_RX_RING_SIZE; i++) {
np->rx_skbs[i] = (void *)((unsigned long) i+1);
-#ifdef CONFIG_XEN_NETDEV_GRANT
np->grant_rx_ref[i] = GRANT_INVALID_REF;
-#endif
- }
-
-#ifdef CONFIG_XEN_NETDEV_GRANT
+ }
+
/* A grant for every tx ring slot */
if (gnttab_alloc_grant_references(NETIF_TX_RING_SIZE,
&np->gref_tx_head) < 0) {
@@ -937,7 +885,6 @@
gnttab_free_grant_references(np->gref_tx_head);
goto exit;
}
-#endif

netdev->open = network_open;
netdev->hard_start_xmit = network_start_xmit;
@@ -971,10 +918,8 @@
return err;

exit_free_grefs:
-#ifdef CONFIG_XEN_NETDEV_GRANT
gnttab_free_grant_references(np->gref_tx_head);
gnttab_free_grant_references(np->gref_rx_head);
-#endif
goto exit;
}

@@ -1024,10 +969,8 @@
evtchn_op_t op = { .cmd = EVTCHNOP_alloc_unbound };
int err;

-#ifdef CONFIG_XEN_NETDEV_GRANT
info->tx_ring_ref = GRANT_INVALID_REF;
info->rx_ring_ref = GRANT_INVALID_REF;
-#endif

info->tx = (netif_tx_interface_t *)__get_free_page(GFP_KERNEL);
if (info->tx == 0) {
@@ -1045,7 +988,6 @@
memset(info->rx, 0, PAGE_SIZE);
info->backend_state = BEST_DISCONNECTED;

-#ifdef CONFIG_XEN_NETDEV_GRANT
err = gnttab_grant_foreign_access(info->backend_id,
virt_to_mfn(info->tx), 0);
if (err < 0) {
@@ -1061,11 +1003,6 @@
goto out;
}
info->rx_ring_ref = err;
-
-#else
- info->tx_ring_ref = virt_to_mfn(info->tx);
- info->rx_ring_ref = virt_to_mfn(info->rx);
-#endif

op.u.alloc_unbound.dom = info->backend_id;
err = HYPERVISOR_event_channel_op(&op);
@@ -1084,7 +1021,6 @@
free_page((unsigned long)info->rx);
info->rx = 0;

-#ifdef CONFIG_XEN_NETDEV_GRANT
if (info->tx_ring_ref != GRANT_INVALID_REF)
gnttab_end_foreign_access(info->tx_ring_ref, 0);
info->tx_ring_ref = GRANT_INVALID_REF;
@@ -1092,7 +1028,6 @@
if (info->rx_ring_ref != GRANT_INVALID_REF)
gnttab_end_foreign_access(info->rx_ring_ref, 0);
info->rx_ring_ref = GRANT_INVALID_REF;
-#endif

return err;
}
@@ -1106,7 +1041,6 @@
free_page((unsigned long)info->rx);
info->rx = 0;

-#ifdef CONFIG_XEN_NETDEV_GRANT
if (info->tx_ring_ref != GRANT_INVALID_REF)
gnttab_end_foreign_access(info->tx_ring_ref, 0);
info->tx_ring_ref = GRANT_INVALID_REF;
@@ -1114,7 +1048,6 @@
if (info->rx_ring_ref != GRANT_INVALID_REF)
gnttab_end_foreign_access(info->rx_ring_ref, 0);
info->rx_ring_ref = GRANT_INVALID_REF;
-#endif

unbind_evtchn_from_irqhandler(info->evtchn, info->netdev);
info->evtchn = 0;
diff -r eba5afe9aa37 -r 10759a44ce3b linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c
--- a/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c Thu Sep 22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c Thu Sep 22 15:12:14 2005
@@ -41,232 +41,253 @@
static int privcmd_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long data)
{
- int ret = -ENOSYS;
-
- switch ( cmd )
- {
- case IOCTL_PRIVCMD_HYPERCALL:
- {
- privcmd_hypercall_t hypercall;
+ int ret = -ENOSYS;
+
+ switch (cmd) {
+ case IOCTL_PRIVCMD_HYPERCALL: {
+ privcmd_hypercall_t hypercall;

- if ( copy_from_user(&hypercall, (void *)data, sizeof(hypercall)) )
- return -EFAULT;
+ if (copy_from_user(&hypercall, (void *)data,
+ sizeof(hypercall)))
+ return -EFAULT;

#if defined(__i386__)
- __asm__ __volatile__ (
- "pushl %%ebx; pushl %%ecx; pushl %%edx; pushl %%esi; pushl %%edi; "
- "movl 4(%%eax),%%ebx ;"
- "movl 8(%%eax),%%ecx ;"
- "movl 12(%%eax),%%edx ;"
- "movl 16(%%eax),%%esi ;"
- "movl 20(%%eax),%%edi ;"
- "movl (%%eax),%%eax ;"
- TRAP_INSTR "; "
- "popl %%edi; popl %%esi; popl %%edx; popl %%ecx; popl %%ebx"
- : "=a" (ret) : "0" (&hypercall) : "memory" );
+ __asm__ __volatile__ (
+ "pushl %%ebx; pushl %%ecx; pushl %%edx; "
+ "pushl %%esi; pushl %%edi; "
+ "movl 4(%%eax),%%ebx ;"
+ "movl 8(%%eax),%%ecx ;"
+ "movl 12(%%eax),%%edx ;"
+ "movl 16(%%eax),%%esi ;"
+ "movl 20(%%eax),%%edi ;"
+ "movl (%%eax),%%eax ;"
+ TRAP_INSTR "; "
+ "popl %%edi; popl %%esi; popl %%edx; "
+ "popl %%ecx; popl %%ebx"
+ : "=a" (ret) : "0" (&hypercall) : "memory" );
#elif defined (__x86_64__)
- {
- long ign1, ign2, ign3;
- __asm__ __volatile__ (
- "movq %8,%%r10; movq %9,%%r8;" TRAP_INSTR
- : "=a" (ret), "=D" (ign1), "=S" (ign2), "=d" (ign3)
- : "0" ((unsigned long)hypercall.op),
- "1" ((unsigned long)hypercall.arg[0]),
- "2" ((unsigned long)hypercall.arg[1]),
- "3" ((unsigned long)hypercall.arg[2]),
- "g" ((unsigned long)hypercall.arg[3]),
- "g" ((unsigned long)hypercall.arg[4])
- : "r11","rcx","r8","r10","memory");
- }
+ {
+ long ign1, ign2, ign3;
+ __asm__ __volatile__ (
+ "movq %8,%%r10; movq %9,%%r8;" TRAP_INSTR
+ : "=a" (ret), "=D" (ign1),
+ "=S" (ign2), "=d" (ign3)
+ : "0" ((unsigned long)hypercall.op),
+ "1" ((unsigned long)hypercall.arg[0]),
+ "2" ((unsigned long)hypercall.arg[1]),
+ "3" ((unsigned long)hypercall.arg[2]),
+ "g" ((unsigned long)hypercall.arg[3]),
+ "g" ((unsigned long)hypercall.arg[4])
+ : "r11","rcx","r8","r10","memory");
+ }
#elif defined (__ia64__)
- __asm__ __volatile__ (
- ";; mov r14=%2; mov r15=%3; mov r16=%4; mov r17=%5; mov r18=%6;"
- "mov r2=%1; break 0x1000;; mov %0=r8 ;;"
- : "=r" (ret)
- : "r" (hypercall.op),
- "r" (hypercall.arg[0]),
- "r" (hypercall.arg[1]),
- "r" (hypercall.arg[2]),
- "r" (hypercall.arg[3]),
- "r" (hypercall.arg[4])
- : "r14","r15","r16","r17","r18","r2","r8","memory");
+ __asm__ __volatile__ (
+ ";; mov r14=%2; mov r15=%3; "
+ "mov r16=%4; mov r17=%5; mov r18=%6;"
+ "mov r2=%1; break 0x1000;; mov %0=r8 ;;"
+ : "=r" (ret)
+ : "r" (hypercall.op),
+ "r" (hypercall.arg[0]),
+ "r" (hypercall.arg[1]),
+ "r" (hypercall.arg[2]),
+ "r" (hypercall.arg[3]),
+ "r" (hypercall.arg[4])
+ : "r14","r15","r16","r17","r18","r2","r8","memory");
#endif
- }
- break;
+ }
+ break;

#if defined(CONFIG_XEN_PRIVILEGED_GUEST)
- case IOCTL_PRIVCMD_MMAP:
- {
+ case IOCTL_PRIVCMD_MMAP: {
#define PRIVCMD_MMAP_SZ 32
- privcmd_mmap_t mmapcmd;
- privcmd_mmap_entry_t msg[PRIVCMD_MMAP_SZ], *p;
- int i, rc;
-
- if ( copy_from_user(&mmapcmd, (void *)data, sizeof(mmapcmd)) )
- return -EFAULT;
-
- p = mmapcmd.entry;
-
- for (i=0; i<mmapcmd.num; i+=PRIVCMD_MMAP_SZ, p+=PRIVCMD_MMAP_SZ)
- {
- int j, n = ((mmapcmd.num-i)>PRIVCMD_MMAP_SZ)?
- PRIVCMD_MMAP_SZ:(mmapcmd.num-i);
-
-
- if ( copy_from_user(&msg, p, n*sizeof(privcmd_mmap_entry_t)) )
- return -EFAULT;
+ privcmd_mmap_t mmapcmd;
+ privcmd_mmap_entry_t msg[PRIVCMD_MMAP_SZ], *p;
+ int i, rc;
+
+ if (copy_from_user(&mmapcmd, (void *)data, sizeof(mmapcmd)))
+ return -EFAULT;
+
+ p = mmapcmd.entry;
+
+ for (i = 0; i < mmapcmd.num;
+ i += PRIVCMD_MMAP_SZ, p += PRIVCMD_MMAP_SZ) {
+ int j, n = ((mmapcmd.num-i)>PRIVCMD_MMAP_SZ)?
+ PRIVCMD_MMAP_SZ:(mmapcmd.num-i);
+
+ if (copy_from_user(&msg, p,
+ n*sizeof(privcmd_mmap_entry_t)))
+ return -EFAULT;

- for ( j = 0; j < n; j++ )
- {
- struct vm_area_struct *vma =
- find_vma( current->mm, msg[j].va );
-
- if ( !vma )
- return -EINVAL;
-
- if ( msg[j].va > PAGE_OFFSET )
- return -EINVAL;
-
- if ( (msg[j].va + (msg[j].npages<<PAGE_SHIFT)) > vma->vm_end )
- return -EINVAL;
-
- if ( (rc = direct_remap_pfn_range(vma,
- msg[j].va&PAGE_MASK,
- msg[j].mfn,
- msg[j].npages<<PAGE_SHIFT,
- vma->vm_page_prot,
- mmapcmd.dom)) < 0 )
- return rc;
- }
- }
- ret = 0;
- }
- break;
-
- case IOCTL_PRIVCMD_MMAPBATCH:
- {
- mmu_update_t u;
- privcmd_mmapbatch_t m;
- struct vm_area_struct *vma = NULL;
- unsigned long *p, addr;
- unsigned long mfn, ptep;
- int i;
-
- if ( copy_from_user(&m, (void *)data, sizeof(m)) )
- { ret = -EFAULT; goto batch_err; }
-
- vma = find_vma( current->mm, m.addr );
-
- if ( !vma )
- { ret = -EINVAL; goto batch_err; }
-
- if ( m.addr > PAGE_OFFSET )
- { ret = -EFAULT; goto batch_err; }
-
- if ( (m.addr + (m.num<<PAGE_SHIFT)) > vma->vm_end )
- { ret = -EFAULT; goto batch_err; }
-
- p = m.arr;
- addr = m.addr;
- for ( i = 0; i < m.num; i++, addr += PAGE_SIZE, p++ )
- {
- if ( get_user(mfn, p) )
- return -EFAULT;
-
- ret = create_lookup_pte_addr(vma->vm_mm, addr, &ptep);
- if (ret)
- goto batch_err;
-
- u.val = pte_val_ma(pfn_pte_ma(mfn, vma->vm_page_prot));
- u.ptr = ptep;
-
- if ( unlikely(HYPERVISOR_mmu_update(&u, 1, NULL, m.dom) < 0) )
- put_user(0xF0000000 | mfn, p);
- }
-
- ret = 0;
- break;
-
- batch_err:
- printk("batch_err ret=%d vma=%p addr=%lx num=%d arr=%p %lx-%lx\n",
- ret, vma, m.addr, m.num, m.arr,
- vma ? vma->vm_start : 0, vma ? vma->vm_end : 0);
- break;
- }
- break;
+ for (j = 0; j < n; j++) {
+ struct vm_area_struct *vma =
+ find_vma( current->mm, msg[j].va );
+
+ if (!vma)
+ return -EINVAL;
+
+ if (msg[j].va > PAGE_OFFSET)
+ return -EINVAL;
+
+ if ((msg[j].va + (msg[j].npages << PAGE_SHIFT))
+ > vma->vm_end )
+ return -EINVAL;
+
+ if ((rc = direct_remap_pfn_range(
+ vma,
+ msg[j].va&PAGE_MASK,
+ msg[j].mfn,
+ msg[j].npages<<PAGE_SHIFT,
+ vma->vm_page_prot,
+ mmapcmd.dom)) < 0)
+ return rc;
+ }
+ }
+ ret = 0;
+ }
+ break;
+
+ case IOCTL_PRIVCMD_MMAPBATCH: {
+ mmu_update_t u;
+ privcmd_mmapbatch_t m;
+ struct vm_area_struct *vma = NULL;
+ unsigned long *p, addr;
+ unsigned long mfn, ptep;
+ int i;
+
+ if (copy_from_user(&m, (void *)data, sizeof(m))) {
+ ret = -EFAULT;
+ goto batch_err;
+ }
+
+ vma = find_vma( current->mm, m.addr );
+ if (!vma) {
+ ret = -EINVAL;
+ goto batch_err;
+ }
+
+ if (m.addr > PAGE_OFFSET) {
+ ret = -EFAULT;
+ goto batch_err;
+ }
+
+ if ((m.addr + (m.num<<PAGE_SHIFT)) > vma->vm_end) {
+ ret = -EFAULT;
+ goto batch_err;
+ }
+
+ p = m.arr;
+ addr = m.addr;
+ for (i = 0; i < m.num; i++, addr += PAGE_SIZE, p++) {
+ if (get_user(mfn, p))
+ return -EFAULT;
+
+ ret = create_lookup_pte_addr(vma->vm_mm, addr, &ptep);
+ if (ret)
+ goto batch_err;
+
+ u.val = pte_val_ma(pfn_pte_ma(mfn, vma->vm_page_prot));
+ u.ptr = ptep;
+
+ if (HYPERVISOR_mmu_update(&u, 1, NULL, m.dom) < 0)
+ put_user(0xF0000000 | mfn, p);
+ }
+
+ ret = 0;
+ break;
+
+ batch_err:
+ printk("batch_err ret=%d vma=%p addr=%lx "
+ "num=%d arr=%p %lx-%lx\n",
+ ret, vma, m.addr, m.num, m.arr,
+ vma ? vma->vm_start : 0, vma ? vma->vm_end : 0);
+ break;
+ }
+ break;
#endif

- case IOCTL_PRIVCMD_GET_MACH2PHYS_START_MFN:
- {
- unsigned long m2pv = (unsigned long)machine_to_phys_mapping;
- pgd_t *pgd = pgd_offset_k(m2pv);
- pud_t *pud = pud_offset(pgd, m2pv);
- pmd_t *pmd = pmd_offset(pud, m2pv);
- unsigned long m2p_start_mfn = (*(unsigned long *)pmd) >> PAGE_SHIFT;
- ret = put_user(m2p_start_mfn, (unsigned long *)data) ? -EFAULT: 0;
- }
- break;
-
- case IOCTL_PRIVCMD_INITDOMAIN_STORE:
- {
- extern int do_xenbus_probe(void*);
- unsigned long page;
-
- if (xen_start_info->store_evtchn != 0) {
- ret = xen_start_info->store_mfn;
- break;
- }
-
- /* Allocate page. */
- page = get_zeroed_page(GFP_KERNEL);
- if (!page) {
- ret = -ENOMEM;
- break;
- }
-
- /* We don't refcnt properly, so set reserved on page.
- * (this allocation is permanent) */
- SetPageReserved(virt_to_page(page));
-
- /* Initial connect. Setup channel and page. */
- xen_start_info->store_evtchn = data;
- xen_start_info->store_mfn = pfn_to_mfn(virt_to_phys((void *)page) >>
- PAGE_SHIFT);
- ret = xen_start_info->store_mfn;
-
- /* We'll return then this will wait for daemon to answer */
- kthread_run(do_xenbus_probe, NULL, "xenbus_probe");
- }
- break;
-
- default:
- ret = -EINVAL;
- break;
- }
- return ret;
+ case IOCTL_PRIVCMD_GET_MACH2PHYS_START_MFN: {
+ unsigned long m2pv = (unsigned long)machine_to_phys_mapping;
+ pgd_t *pgd = pgd_offset_k(m2pv);
+ pud_t *pud = pud_offset(pgd, m2pv);
+ pmd_t *pmd = pmd_offset(pud, m2pv);
+ unsigned long m2p_start_mfn =
+ (*(unsigned long *)pmd) >> PAGE_SHIFT;
+ ret = put_user(m2p_start_mfn, (unsigned long *)data) ?
+ -EFAULT: 0;
+ }
+ break;
+
+ case IOCTL_PRIVCMD_INITDOMAIN_STORE: {
+ extern int do_xenbus_probe(void*);
+ unsigned long page;
+
+ if (xen_start_info->store_evtchn != 0) {
+ ret = xen_start_info->store_mfn;
+ break;
+ }
+
+ /* Allocate page. */
+ page = get_zeroed_page(GFP_KERNEL);
+ if (!page) {
+ ret = -ENOMEM;
+ break;
+ }
+
+ /* We don't refcnt properly, so set reserved on page.
+ * (this allocation is permanent) */
+ SetPageReserved(virt_to_page(page));
+
+ /* Initial connect. Setup channel and page. */
+ xen_start_info->store_evtchn = data;
+ xen_start_info->store_mfn =
+ pfn_to_mfn(virt_to_phys((void *)page) >>
+ PAGE_SHIFT);
+ ret = xen_start_info->store_mfn;
+
+ /* We'll return then this will wait for daemon to answer */
+ kthread_run(do_xenbus_probe, NULL, "xenbus_probe");
+ }
+ break;
+
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
}

static int privcmd_mmap(struct file * file, struct vm_area_struct * vma)
{
- /* DONTCOPY is essential for Xen as copy_page_range is broken. */
- vma->vm_flags |= VM_RESERVED | VM_IO | VM_DONTCOPY;
-
- return 0;
+ /* DONTCOPY is essential for Xen as copy_page_range is broken. */
+ vma->vm_flags |= VM_RESERVED | VM_IO | VM_DONTCOPY;
+
+ return 0;
}

static struct file_operations privcmd_file_ops = {
- .ioctl = privcmd_ioctl,
- .mmap = privcmd_mmap,
+ .ioctl = privcmd_ioctl,
+ .mmap = privcmd_mmap,
};


static int __init privcmd_init(void)
{
- privcmd_intf = create_xen_proc_entry("privcmd", 0400);
- if ( privcmd_intf != NULL )
- privcmd_intf->proc_fops = &privcmd_file_ops;
-
- return 0;
+ privcmd_intf = create_xen_proc_entry("privcmd", 0400);
+ if (privcmd_intf != NULL)
+ privcmd_intf->proc_fops = &privcmd_file_ops;
+
+ return 0;
}

__initcall(privcmd_init);
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r eba5afe9aa37 -r 10759a44ce3b linux-2.6-xen-sparse/drivers/xen/tpmback/common.h
--- a/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h Thu Sep 22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h Thu Sep 22 15:12:14 2005
@@ -84,3 +84,13 @@
#define MMAP_VADDR(t,_req) ((t)->mmap_vstart + ((_req) * PAGE_SIZE))

#endif /* __TPMIF__BACKEND__COMMON_H__ */
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r eba5afe9aa37 -r 10759a44ce3b linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c
--- a/linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c Thu Sep 22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c Thu Sep 22 15:12:14 2005
@@ -566,7 +566,7 @@
* the more time we give the TPM to process the request.
*/
mod_timer(&pak->processing_timer,
- jiffies + (num_frontends * 10 * HZ));
+ jiffies + (num_frontends * 60 * HZ));
dataex.copied_so_far = 0;
}
}
@@ -850,7 +850,7 @@
write_lock_irqsave(&dataex.pak_lock, flags);
list_add_tail(&pak->next, &dataex.pending_pak);
/* give the TPM some time to pick up the request */
- mod_timer(&pak->processing_timer, jiffies + (10 * HZ));
+ mod_timer(&pak->processing_timer, jiffies + (30 * HZ));
write_unlock_irqrestore(&dataex.pak_lock,
flags);

@@ -1075,3 +1075,13 @@
}

__initcall(tpmback_init);
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r eba5afe9aa37 -r 10759a44ce3b linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c
--- a/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c Thu Sep 22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c Thu Sep 22 15:12:14 2005
@@ -268,3 +268,13 @@
{
xenbus_register_backend(&tpmback);
}
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r eba5afe9aa37 -r 10759a44ce3b linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c
--- a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c Thu Sep 22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c Thu Sep 22 15:12:14 2005
@@ -741,3 +741,13 @@
}

__initcall(tpmif_init);
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r eba5afe9aa37 -r 10759a44ce3b linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.h
--- a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.h Thu Sep 22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.h Thu Sep 22 15:12:14 2005
@@ -38,3 +38,13 @@
};

#endif
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r eba5afe9aa37 -r 10759a44ce3b linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c
--- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c Thu Sep 22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c Thu Sep 22 15:12:14 2005
@@ -231,3 +231,13 @@

unbind_evtchn_from_irqhandler(xen_start_info->store_evtchn, &xb_waitq);
}
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r eba5afe9aa37 -r 10759a44ce3b linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.h
--- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.h Thu Sep 22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.h Thu Sep 22 15:12:14 2005
@@ -39,3 +39,13 @@
extern wait_queue_head_t xb_waitq;

#endif /* _XENBUS_COMMS_H */
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r eba5afe9aa37 -r 10759a44ce3b linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c
--- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c Thu Sep 22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c Thu Sep 22 15:12:14 2005
@@ -186,3 +186,13 @@
}

__initcall(xenbus_dev_init);
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r eba5afe9aa37 -r 10759a44ce3b linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c
--- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Thu Sep 22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Thu Sep 22 15:12:14 2005
@@ -687,3 +687,13 @@
}

postcore_initcall(xenbus_probe_init);
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r eba5afe9aa37 -r 10759a44ce3b linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c
--- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c Thu Sep 22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c Thu Sep 22 15:12:14 2005
@@ -566,3 +566,13 @@
return PTR_ERR(watcher);
return 0;
}
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r eba5afe9aa37 -r 10759a44ce3b tools/python/xen/xend/XendDomain.py
--- a/tools/python/xen/xend/XendDomain.py Thu Sep 22 15:05:44 2005
+++ b/tools/python/xen/xend/XendDomain.py Thu Sep 22 15:12:14 2005
@@ -305,6 +305,13 @@

@param vmconfig: vm configuration
"""
+ # We accept our configuration specified as ['config' [...]], which
+ # some tools or configuration files may be using. For save-restore,
+ # we use the value of XendDomainInfo.sxpr() directly, which has no
+ # such item.
+ nested = sxp.child_value(config, 'config')
+ if nested:
+ config = nested
return XendDomainInfo.restore(self.dbmap.getPath(), config)

def domain_restore(self, src, progress=False):
diff -r eba5afe9aa37 -r 10759a44ce3b xen/include/public/io/netif.h
--- a/xen/include/public/io/netif.h Thu Sep 22 15:05:44 2005
+++ b/xen/include/public/io/netif.h Thu Sep 22 15:12:14 2005
@@ -10,10 +10,11 @@
#define __XEN_PUBLIC_IO_NETIF_H__

typedef struct netif_tx_request {
- unsigned long addr; /* Machine address of packet. */
+ grant_ref_t gref; /* Reference to buffer page */
+ u16 offset:15; /* Offset within buffer page */
u16 csum_blank:1; /* Proto csum field blank? */
- u16 id:15; /* Echoed in response message. */
- u16 size; /* Packet size in bytes. */
+ u16 id; /* Echoed in response message. */
+ u16 size; /* Packet size in bytes. */
} netif_tx_request_t;

typedef struct netif_tx_response {
@@ -22,21 +23,15 @@
} netif_tx_response_t;

typedef struct {
- u16 id; /* Echoed in response message. */
-#ifdef CONFIG_XEN_NETDEV_GRANT
- grant_ref_t gref; /* 2: Reference to incoming granted frame */
-#endif
+ u16 id; /* Echoed in response message. */
+ grant_ref_t gref; /* Reference to incoming granted frame */
} netif_rx_request_t;

typedef struct {
-#ifdef CONFIG_XEN_NETDEV_GRANT
- u32 addr; /* 0: Offset in page of start of received packet */
-#else
- unsigned long addr; /* Machine address of packet. */
-#endif
- u16 csum_valid:1; /* Protocol checksum is validated? */
- u16 id:15;
- s16 status; /* -ve: BLKIF_RSP_* ; +ve: Rx'ed pkt size. */
+ u16 offset; /* Offset in page of start of received packet */
+ u16 csum_valid; /* Protocol checksum is validated? */
+ u16 id;
+ s16 status; /* -ve: BLKIF_RSP_* ; +ve: Rx'ed pkt size. */
} netif_rx_response_t;

/*
@@ -53,18 +48,8 @@
#define MASK_NETIF_RX_IDX(_i) ((_i)&(NETIF_RX_RING_SIZE-1))
#define MASK_NETIF_TX_IDX(_i) ((_i)&(NETIF_TX_RING_SIZE-1))

-#ifdef __x86_64__
-/*
- * This restriction can be lifted when we move netfront/netback to use
- * grant tables. This will remove memory_t fields from the above structures
- * and thus relax natural alignment restrictions.
- */
-#define NETIF_TX_RING_SIZE 128
-#define NETIF_RX_RING_SIZE 128
-#else
#define NETIF_TX_RING_SIZE 256
#define NETIF_RX_RING_SIZE 256
-#endif

/* This structure must fit in a memory page. */
typedef struct netif_tx_interface {
diff -r eba5afe9aa37 -r 10759a44ce3b linux-2.6-xen-sparse/drivers/xen/usbback/common.h
--- a/linux-2.6-xen-sparse/drivers/xen/usbback/common.h Thu Sep 22 15:05:44 2005
+++ /dev/null Thu Sep 22 15:12:14 2005
@@ -1,84 +0,0 @@
-
-#ifndef __USBIF__BACKEND__COMMON_H__
-#define __USBIF__BACKEND__COMMON_H__
-
-#include <linux/config.h>
-#include <linux/version.h>
-#include <linux/module.h>
-#include <linux/rbtree.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/blkdev.h>
-#include <asm/io.h>
-#include <asm/setup.h>
-#include <asm/pgalloc.h>
-#include <asm/hypervisor.h>
-#include <asm-xen/driver_util.h>
-#include <asm-xen/xen-public/io/usbif.h>
-
-#if 0
-#define ASSERT(_p) \
- if ( !(_p) ) { printk("Assertion '%s' failed, line %d, file %s", #_p , \
- __LINE__, __FILE__); *(int*)0=0; }
-#define DPRINTK(_f, _a...) printk(KERN_ALERT "(file=%s, line=%d) " _f, \
- __FILE__ , __LINE__ , ## _a )
-#else
-#define ASSERT(_p) ((void)0)
-#define DPRINTK(_f, _a...) ((void)0)
-#endif
-
-typedef struct usbif_priv_st usbif_priv_t;
-
-struct usbif_priv_st {
- /* Unique identifier for this interface. */
- domid_t domid;
- unsigned int handle;
- /* Physical parameters of the comms window. */
- unsigned long shmem_frame;
- unsigned int evtchn;
- /* Comms Information */
- usbif_back_ring_t usb_ring;
- struct vm_struct *usb_ring_area;
- /* Private fields. */
- enum { DISCONNECTED, DISCONNECTING, CONNECTED } status;
- /*
- * DISCONNECT response is deferred until pending requests are ack'ed.
- * We therefore need to store the id from the original request.
- */
- u8 disconnect_rspid;
- usbif_priv_t *hash_next;
- struct list_head usbif_list;
- spinlock_t usb_ring_lock;
- atomic_t refcnt;
-
- struct work_struct work;
-};
-
-void usbif_create(usbif_be_create_t *create);
-void usbif_destroy(usbif_be_destroy_t *destroy);
-void usbif_connect(usbif_be_connect_t *connect);
-int usbif_disconnect(usbif_be_disconnect_t *disconnect, u8 rsp_id);
-void usbif_disconnect_complete(usbif_priv_t *up);
-
-void usbif_release_port(usbif_be_release_port_t *msg);
-int usbif_claim_port(usbif_be_claim_port_t *msg);
-void usbif_release_ports(usbif_priv_t *up);
-
-usbif_priv_t *usbif_find(domid_t domid);
-#define usbif_get(_b) (atomic_inc(&(_b)->refcnt))
-#define usbif_put(_b) \
- do { \
- if ( atomic_dec_and_test(&(_b)->refcnt) ) \
- usbif_disconnect_complete(_b); \
- } while (0)
-
-
-void usbif_interface_init(void);
-void usbif_ctrlif_init(void);
-
-void usbif_deschedule(usbif_priv_t *up);
-void remove_from_usbif_list(usbif_priv_t *up);
-
-irqreturn_t usbif_be_int(int irq, void *dev_id, struct pt_regs *regs);
-
-#endif /* __USBIF__BACKEND__COMMON_H__ */
diff -r eba5afe9aa37 -r 10759a44ce3b linux-2.6-xen-sparse/drivers/xen/usbback/control.c
--- a/linux-2.6-xen-sparse/drivers/xen/usbback/control.c Thu Sep 22 15:05:44 2005
+++ /dev/null Thu Sep 22 15:12:14 2005
@@ -1,61 +0,0 @@
-/******************************************************************************
- * arch/xen/drivers/usbif/backend/control.c
- *
- * Routines for interfacing with the control plane.
- *
- * Copyright (c) 2004, Keir Fraser
- */
-
-#include "common.h"
-
-static void usbif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id)
-{
- DPRINTK("Received usbif backend message, subtype=%d\n", msg->subtype);
-
- switch ( msg->subtype )
- {
- case CMSG_USBIF_BE_CREATE:
- usbif_create((usbif_be_create_t *)&msg->msg[0]);
- break;
- case CMSG_USBIF_BE_DESTROY:
- usbif_destroy((usbif_be_destroy_t *)&msg->msg[0]);
- break;
- case CMSG_USBIF_BE_CONNECT:
- usbif_connect((usbif_be_connect_t *)&msg->msg[0]);
- break;
- case CMSG_USBIF_BE_DISCONNECT:
- if ( !usbif_disconnect((usbif_be_disconnect_t *)&msg->msg[0],msg->id) )
- return; /* Sending the response is deferred until later. */
- break;
- case CMSG_USBIF_BE_CLAIM_PORT:
- usbif_claim_port((usbif_be_claim_port_t *)&msg->msg[0]);
- break;
- case CMSG_USBIF_BE_RELEASE_PORT:
- usbif_release_port((usbif_be_release_port_t *)&msg->msg[0]);
- break;
- default:
- DPRINTK("Parse error while reading message subtype %d, len %d\n",
- msg->subtype, msg->length);
- msg->length = 0;
- break;
- }
-
- ctrl_if_send_response(msg);
-}
-
-void usbif_ctrlif_init(void)
-{
- ctrl_msg_t cmsg;
- usbif_be_driver_status_changed_t st;
-
- (void)ctrl_if_register_receiver(CMSG_USBIF_BE, usbif_ctrlif_rx,
- CALLBACK_IN_BLOCKING_CONTEXT);
-
- /* Send a driver-UP notification to the domain controller. */
- cmsg.type = CMSG_USBIF_BE;
- cmsg.subtype = CMSG_USBIF_BE_DRIVER_STATUS_CHANGED;
- cmsg.length = sizeof(usbif_be_driver_status_changed_t);
- st.status = USBIF_DRIVER_STATUS_UP;
- memcpy(cmsg.msg, &st, sizeof(st));
- ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
-}
diff -r eba5afe9aa37 -r 10759a44ce3b linux-2.6-xen-sparse/drivers/xen/usbback/interface.c
--- a/linux-2.6-xen-sparse/drivers/xen/usbback/interface.c Thu Sep 22 15:05:44 2005
+++ /dev/null Thu Sep 22 15:12:14 2005
@@ -1,241 +0,0 @@
-/******************************************************************************
- * arch/xen/drivers/usbif/backend/interface.c
- *
- * USB device interface management.
- *
- * by Mark Williamson, Copyright (c) 2004
- */
-
-#include "common.h"
-
-#define USBIF_HASHSZ 1024
-#define USBIF_HASH(_d) (((int)(_d))&(USBIF_HASHSZ-1))
-
-static kmem_cache_t *usbif_priv_cachep;
-static usbif_priv_t *usbif_priv_hash[USBIF_HASHSZ];
-
-usbif_priv_t *usbif_find(domid_t domid)
-{
- usbif_priv_t *up = usbif_priv_hash[USBIF_HASH(domid)];
- while ( (up != NULL ) && ( up->domid != domid ) )
- up = up->hash_next;
- return up;
-}
-
-static void __usbif_disconnect_complete(void *arg)
-{
- usbif_priv_t *usbif = (usbif_priv_t *)arg;
- ctrl_msg_t cmsg;
- usbif_be_disconnect_t disc;
-
- /*
- * These can't be done in usbif_disconnect() because at that point there
- * may be outstanding requests at the device whose asynchronous responses
- * must still be notified to the remote driver.
- */
- free_vm_area(usbif->usb_ring_area);
-
- /* Construct the deferred response message. */
- cmsg.type = CMSG_USBIF_BE;
- cmsg.subtype = CMSG_USBIF_BE_DISCONNECT;
- cmsg.id = usbif->disconnect_rspid;
- cmsg.length = sizeof(usbif_be_disconnect_t);
- disc.domid = usbif->domid;
- disc.status = USBIF_BE_STATUS_OKAY;
- memcpy(cmsg.msg, &disc, sizeof(disc));
-
- /*
- * Make sure message is constructed /before/ status change, because
- * after the status change the 'usbif' structure could be deallocated at
- * any time. Also make sure we send the response /after/ status change,
- * as otherwise a subsequent CONNECT request could spuriously fail if
- * another CPU doesn't see the status change yet.
- */
- mb();
- if ( usbif->status != DISCONNECTING )
- BUG();
- usbif->status = DISCONNECTED;
- mb();
-
- /* Send the successful response. */
- ctrl_if_send_response(&cmsg);
-}
-
-void usbif_disconnect_complete(usbif_priv_t *up)
-{
- INIT_WORK(&up->work, __usbif_disconnect_complete, (void *)up);
- schedule_work(&up->work);
-}
-
-void usbif_create(usbif_be_create_t *create)
-{
- domid_t domid = create->domid;
- usbif_priv_t **pup, *up;
-
- if ( (up = kmem_cache_alloc(usbif_priv_cachep, GFP_KERNEL)) == NULL )
- {
- DPRINTK("Could not create usbif: out of memory\n");
- create->status = USBIF_BE_STATUS_OUT_OF_MEMORY;
- return;
- }
-
- memset(up, 0, sizeof(*up));
- up->domid = domid;
- up->status = DISCONNECTED;
- spin_lock_init(&up->usb_ring_lock);
- atomic_set(&up->refcnt, 0);
-
- pup = &usbif_priv_hash[USBIF_HASH(domid)];
- while ( *pup != NULL )
- {
- if ( (*pup)->domid == domid )
- {
- create->status = USBIF_BE_STATUS_INTERFACE_EXISTS;
- kmem_cache_free(usbif_priv_cachep, up);
- return;
- }
- pup = &(*pup)->hash_next;
- }
-
- up->hash_next = *pup;
- *pup = up;
-
- create->status = USBIF_BE_STATUS_OKAY;
-}
-
-void usbif_destroy(usbif_be_destroy_t *destroy)
-{
- domid_t domid = destroy->domid;
- usbif_priv_t **pup, *up;
-
- pup = &usbif_priv_hash[USBIF_HASH(domid)];
- while ( (up = *pup) != NULL )
- {
- if ( up->domid == domid )
- {
- if ( up->status != DISCONNECTED )
- goto still_connected;
- goto destroy;
- }
- pup = &up->hash_next;
- }
-
- destroy->status = USBIF_BE_STATUS_INTERFACE_NOT_FOUND;
- return;
-
- still_connected:
- destroy->status = USBIF_BE_STATUS_INTERFACE_CONNECTED;
- return;
-
- destroy:
- *pup = up->hash_next;
- usbif_release_ports(up);
- kmem_cache_free(usbif_priv_cachep, up);
- destroy->status = USBIF_BE_STATUS_OKAY;
-}
-
-void usbif_connect(usbif_be_connect_t *connect)
-{
- domid_t domid = connect->domid;
- unsigned int evtchn = connect->evtchn;
- unsigned long shmem_frame = connect->shmem_frame;
- pgprot_t prot;
- int error;
- usbif_priv_t *up;
- usbif_sring_t *sring;
-
- up = usbif_find(domid);
- if ( unlikely(up == NULL) )
- {
- DPRINTK("usbif_connect attempted for non-existent usbif (%u)\n",
- connect->domid);
- connect->status = USBIF_BE_STATUS_INTERFACE_NOT_FOUND;
- return;
- }
-
- if ( (up->usb_ring_area = alloc_vm_area(PAGE_SIZE)) == NULL )
- {
- connect->status = USBIF_BE_STATUS_OUT_OF_MEMORY;
- return;
- }
-
- prot = __pgprot(_KERNPG_TABLE);
- error = direct_remap_pfn_range(&init_mm, AREALLOC_AREADDR(area->addr),
- shmem_frame, PAGE_SIZE,
- prot, domid);
- if ( error != 0 )
- {
- if ( error == -ENOMEM )
- connect->status = USBIF_BE_STATUS_OUT_OF_MEMORY;
- else if ( error == -EFAULT )
- connect->status = USBIF_BE_STATUS_MAPPING_ERROR;
- else
- connect->status = USBIF_BE_STATUS_ERROR;
- free_vm_area(up->usb_ring_area);
- return;
- }
-
- if ( up->status != DISCONNECTED )
- {
- connect->status = USBIF_BE_STATUS_INTERFACE_CONNECTED;
- free_vm_area(up->usb_ring_area);
- return;
- }
-
- sring = (usbif_sring_t *)area->addr;
- SHARED_RING_INIT(sring);
- BACK_RING_INIT(&up->usb_ring, sring, PAGE_SIZE);
-
- up->evtchn = evtchn;
- up->shmem_frame = shmem_frame;
- up->status = CONNECTED;
- usbif_get(up);
-
- (void)bind_evtchn_to_irqhandler(
- evtchn, usbif_be_int, 0, "usbif-backend", up);
-
- connect->status = USBIF_BE_STATUS_OKAY;
-}
-
-/* Remove URBs for this interface before destroying it. */
-void usbif_deschedule(usbif_priv_t *up)
-{
- remove_from_usbif_list(up);
-}
-
-int usbif_disconnect(usbif_be_disconnect_t *disconnect, u8 rsp_id)
-{
- domid_t domid = disconnect->domid;
- usbif_priv_t *up;
-
- up = usbif_find(domid);
- if ( unlikely(up == NULL) )
- {
- DPRINTK("usbif_disconnect attempted for non-existent usbif"
- " (%u)\n", disconnect->domid);
- disconnect->status = USBIF_BE_STATUS_INTERFACE_NOT_FOUND;
- return 1; /* Caller will send response error message. */
- }
-
- if ( up->status == CONNECTED )
- {
- up->status = DISCONNECTING;
- up->disconnect_rspid = rsp_id;
- wmb(); /* Let other CPUs see the status change. */
- unbind_evtchn_from_irqhandler(up->evtchn, up);
- usbif_deschedule(up);
- usbif_put(up);
- return 0; /* Caller should not send response message. */
- }
-
- disconnect->status = USBIF_BE_STATUS_OKAY;
- return 1;
-}
-
-void __init usbif_interface_init(void)
-{
- usbif_priv_cachep = kmem_cache_create("usbif_priv_cache",
- sizeof(usbif_priv_t),
- 0, 0, NULL, NULL);
- memset(usbif_priv_hash, 0, sizeof(usbif_priv_hash));
-}
diff -r eba5afe9aa37 -r 10759a44ce3b linux-2.6-xen-sparse/drivers/xen/usbback/usbback.c
--- a/linux-2.6-xen-sparse/drivers/xen/usbback/usbback.c Thu Sep 22 15:05:44 2005
+++ /dev/null Thu Sep 22 15:12:14 2005
@@ -1,1068 +0,0 @@
-/******************************************************************************
- * arch/xen/drivers/usbif/backend/main.c
- *
- * Backend for the Xen virtual USB driver - provides an abstraction of a
- * USB host controller to the corresponding frontend driver.
- *
- * by Mark Williamson
- * Copyright (c) 2004 Intel Research Cambridge
- * Copyright (c) 2004, 2005 Mark Williamson
- *
- * Based on arch/xen/drivers/blkif/backend/main.c
- * Copyright (c) 2003-2004, Keir Fraser & Steve Hand
- */
-
-#include "common.h"
-
-
-#include <linux/list.h>
-#include <linux/usb.h>
-#include <linux/spinlock.h>
-#include <linux/module.h>
-#include <linux/tqueue.h>
-
-/*
- * This is rather arbitrary.
- */
-#define MAX_PENDING_REQS 4
-#define BATCH_PER_DOMAIN 1
-
-static unsigned long mmap_vstart;
-
-/* Needs to be sufficiently large that we can map the (large) buffers
- * the USB mass storage driver wants. */
-#define MMAP_PAGES_PER_REQUEST \
- (128)
-#define MMAP_PAGES \
- (MAX_PENDING_REQS * MMAP_PAGES_PER_REQUEST)
-
-#define MMAP_VADDR(_req,_seg) \
- (mmap_vstart + \
- ((_req) * MMAP_PAGES_PER_REQUEST * PAGE_SIZE) + \
- ((_seg) * PAGE_SIZE))
-
-
-static spinlock_t owned_ports_lock;
-LIST_HEAD(owned_ports);
-
-/* A list of these structures is used to track ownership of physical USB
- * ports. */
-typedef struct
-{
- usbif_priv_t *usbif_priv;
- char path[16];
- int guest_port;
- int enabled;
- struct list_head list;
- unsigned long guest_address; /* The USB device address that has been
- * assigned by the guest. */
- int dev_present; /* Is there a device present? */
- struct usb_device * dev;
- unsigned long ifaces; /* What interfaces are present on this device? */
-} owned_port_t;
-
-
-/*
- * Each outstanding request that we've passed to the lower device layers has a
- * 'pending_req' allocated to it. The request is complete, the specified
- * domain has a response queued for it, with the saved 'id' passed back.
- */
-typedef struct {
- usbif_priv_t *usbif_priv;
- unsigned long id;
- int nr_pages;
- unsigned short operation;
- int status;
-} pending_req_t;
-
-/*
- * We can't allocate pending_req's in order, since they may complete out of
- * order. We therefore maintain an allocation ring. This ring also indicates
- * when enough work has been passed down -- at that point the allocation ring
- * will be empty.
- */
-static pending_req_t pending_reqs[MAX_PENDING_REQS];
-static unsigned char pending_ring[MAX_PENDING_REQS];
-static spinlock_t pend_prod_lock;
-
-/* NB. We use a different index type to differentiate from shared usb rings. */
-typedef unsigned int PEND_RING_IDX;
-#define MASK_PEND_IDX(_i) ((_i)&(MAX_PENDING_REQS-1))
-static PEND_RING_IDX pending_prod, pending_cons;
-#define NR_PENDING_REQS (MAX_PENDING_REQS - pending_prod + pending_cons)
-
-static int do_usb_io_op(usbif_priv_t *usbif, int max_to_do);
-static void make_response(usbif_priv_t *usbif, unsigned long id,
- unsigned short op, int st, int inband,
- unsigned long actual_length);
-static void dispatch_usb_probe(usbif_priv_t *up, unsigned long id, unsigned long port);
-static void dispatch_usb_io(usbif_priv_t *up, usbif_request_t *req);
-static void dispatch_usb_reset(usbif_priv_t *up, unsigned long portid);
-static owned_port_t *usbif_find_port(char *);
-
-/******************************************************************
- * PRIVATE DEBUG FUNCTIONS
- */
-
-#undef DEBUG
-#ifdef DEBUG
-
-static void dump_port(owned_port_t *p)
-{
- printk(KERN_DEBUG "owned_port_t @ %p\n"
- " usbif_priv @ %p\n"
- " path: %s\n"
- " guest_port: %d\n"
- " guest_address: %ld\n"
- " dev_present: %d\n"
- " dev @ %p\n"
- " ifaces: 0x%lx\n",
- p, p->usbif_priv, p->path, p->guest_port, p->guest_address,
- p->dev_present, p->dev, p->ifaces);
-}
-
-
-static void dump_request(usbif_request_t *req)
-{
- printk(KERN_DEBUG "id = 0x%lx\n"
- "devnum %d\n"
- "endpoint 0x%x\n"
- "direction %d\n"
- "speed %d\n"
- "pipe_type 0x%x\n"
- "transfer_buffer 0x%lx\n"
- "length 0x%lx\n"
- "transfer_flags 0x%lx\n"
- "setup = { 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x }\n"
- "iso_schedule = 0x%lx\n"
- "num_iso %ld\n",
- req->id, req->devnum, req->endpoint, req->direction, req->speed,
- req->pipe_type, req->transfer_buffer, req->length,
- req->transfer_flags, req->setup[0], req->setup[1], req->setup[2],
- req->setup[3], req->setup[4], req->setup[5], req->setup[6],
- req->setup[7], req->iso_schedule, req->num_iso);
-}
-
-static void dump_urb(struct urb *urb)
-{
- printk(KERN_DEBUG "dumping urb @ %p\n", urb);
-
-#define DUMP_URB_FIELD(name, format) \
- printk(KERN_DEBUG " " # name " " format "\n", urb-> name)
-
- DUMP_URB_FIELD(pipe, "0x%x");
- DUMP_URB_FIELD(status, "%d");
- DUMP_URB_FIELD(transfer_flags, "0x%x");
- DUMP_URB_FIELD(transfer_buffer, "%p");
- DUMP_URB_FIELD(transfer_buffer_length, "%d");
- DUMP_URB_FIELD(actual_length, "%d");
-}
-
-static void dump_response(usbif_response_t *resp)
-{
- printk(KERN_DEBUG "usbback: Sending response:\n"
- " id = 0x%x\n"
- " op = %d\n"
- " status = %d\n"
- " data = %d\n"
- " length = %d\n",
- resp->id, resp->op, resp->status, resp->data, resp->length);
-}
-
-#else /* DEBUG */
-
-#define dump_port(blah) ((void)0)
-#define dump_request(blah) ((void)0)
-#define dump_urb(blah) ((void)0)
-#define dump_response(blah) ((void)0)
-
-#endif /* DEBUG */
-
-/******************************************************************
- * MEMORY MANAGEMENT
- */
-
-static void fast_flush_area(int idx, int nr_pages)
-{
- multicall_entry_t mcl[MMAP_PAGES_PER_REQUEST];
- int i;
-
- for ( i = 0; i < nr_pages; i++ )
- {
- MULTI_update_va_mapping(mcl+i, MMAP_VADDR(idx, i),
- __pte(0), 0);
- }
-
- mcl[nr_pages-1].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_ALL;
- if ( unlikely(HYPERVISOR_multicall(mcl, nr_pages) != 0) )
- BUG();
-}
-
-
-/******************************************************************
- * USB INTERFACE SCHEDULER LIST MAINTENANCE
- */
-
-static struct list_head usbio_schedule_list;
-static spinlock_t usbio_schedule_list_lock;
-
-static int __on_usbif_list(usbif_priv_t *up)
-{
- return up->usbif_list.next != NULL;
-}
-
-void remove_from_usbif_list(usbif_priv_t *up)
-{
- unsigned long flags;
- if ( !__on_usbif_list(up) ) return;
- spin_lock_irqsave(&usbio_schedule_list_lock, flags);
- if ( __on_usbif_list(up) )
- {
- list_del(&up->usbif_list);
- up->usbif_list.next = NULL;
- usbif_put(up);
- }
- spin_unlock_irqrestore(&usbio_schedule_list_lock, flags);
-}
-
-static void add_to_usbif_list_tail(usbif_priv_t *up)
-{
- unsigned long flags;
- if ( __on_usbif_list(up) ) return;
- spin_lock_irqsave(&usbio_schedule_list_lock, flags);
- if ( !__on_usbif_list(up) && (up->status == CONNECTED) )
- {
- list_add_tail(&up->usbif_list, &usbio_schedule_list);
- usbif_get(up);
- }
- spin_unlock_irqrestore(&usbio_schedule_list_lock, flags);
-}
-
-void free_pending(int pending_idx)
-{
- unsigned long flags;
-
- /* Free the pending request. */
- spin_lock_irqsave(&pend_prod_lock, flags);
- pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx;
- spin_unlock_irqrestore(&pend_prod_lock, flags);
-}
-
-/******************************************************************
- * COMPLETION CALLBACK -- Called as urb->complete()
- */
-
-static void maybe_trigger_usbio_schedule(void);
-
-static void __end_usb_io_op(struct urb *purb)
-{
- pending_req_t *pending_req;
- int pending_idx;
-
- pending_req = purb->context;
-
- pending_idx = pending_req - pending_reqs;
-
- ASSERT(purb->actual_length <= purb->transfer_buffer_length);
- ASSERT(purb->actual_length <= pending_req->nr_pages * PAGE_SIZE);
-
- /* An error fails the entire request. */
- if ( purb->status )
- {
- printk(KERN_WARNING "URB @ %p failed. Status %d\n", purb, purb->status);
- }
-
- if ( usb_pipetype(purb->pipe) == 0 )
- {
- int i;
- usbif_iso_t *sched = (usbif_iso_t *)MMAP_VADDR(pending_idx, pending_req->nr_pages - 1);
-
- /* If we're dealing with an iso pipe, we need to copy back the schedule. */
- for ( i = 0; i < purb->number_of_packets; i++ )
- {
- sched[i].length = purb->iso_frame_desc[i].actual_length;
- ASSERT(sched[i].buffer_offset ==
- purb->iso_frame_desc[i].offset);
- sched[i].status = purb->iso_frame_desc[i].status;
- }
- }
-
- fast_flush_area(pending_req - pending_reqs, pending_req->nr_pages);
-
- kfree(purb->setup_packet);
-
- make_response(pending_req->usbif_priv, pending_req->id,
- pending_req->operation, pending_req->status, 0, purb->actual_length);
- usbif_put(pending_req->usbif_priv);
-
- usb_free_urb(purb);
-
- free_pending(pending_idx);
-
- rmb();
-
- /* Check for anything still waiting in the rings, having freed a request... */
- maybe_trigger_usbio_schedule();
-}
-
-/******************************************************************
- * SCHEDULER FUNCTIONS
- */
-
-static DECLARE_WAIT_QUEUE_HEAD(usbio_schedule_wait);
-
-static int usbio_schedule(void *arg)
-{
- DECLARE_WAITQUEUE(wq, current);
-
- usbif_priv_t *up;
- struct list_head *ent;
-
- daemonize();
-
- for ( ; ; )
- {
- /* Wait for work to do. */
- add_wait_queue(&usbio_schedule_wait, &wq);
- set_current_state(TASK_INTERRUPTIBLE);
- if ( (NR_PENDING_REQS == MAX_PENDING_REQS) ||
- list_empty(&usbio_schedule_list) )
- schedule();
- __set_current_state(TASK_RUNNING);
- remove_wait_queue(&usbio_schedule_wait, &wq);
-
- /* Queue up a batch of requests. */
- while ( (NR_PENDING_REQS < MAX_PENDING_REQS) &&
- !list_empty(&usbio_schedule_list) )
- {
- ent = usbio_schedule_list.next;
- up = list_entry(ent, usbif_priv_t, usbif_list);
- usbif_get(up);
- remove_from_usbif_list(up);
- if ( do_usb_io_op(up, BATCH_PER_DOMAIN) )
- add_to_usbif_list_tail(up);
- usbif_put(up);
- }
- }
-}
-
-static void maybe_trigger_usbio_schedule(void)
-{
- /*
- * Needed so that two processes, who together make the following predicate
- * true, don't both read stale values and evaluate the predicate
- * incorrectly. Incredibly unlikely to stall the scheduler on x86, but...
- */
- smp_mb();
-
- if ( !list_empty(&usbio_schedule_list) )
- wake_up(&usbio_schedule_wait);
-}
-
-
-/******************************************************************************
- * NOTIFICATION FROM GUEST OS.
- */
-
-irqreturn_t usbif_be_int(int irq, void *dev_id, struct pt_regs *regs)
-{
- usbif_priv_t *up = dev_id;
-
- smp_mb();
-
- add_to_usbif_list_tail(up);
-
- /* Will in fact /always/ trigger an io schedule in this case. */
- maybe_trigger_usbio_schedule();
-
- return IRQ_HANDLED;
-}
-
-
-
-/******************************************************************
- * DOWNWARD CALLS -- These interface with the usb-device layer proper.
- */
-
-static int do_usb_io_op(usbif_priv_t *up, int max_to_do)
-{
- usbif_back_ring_t *usb_ring = &up->usb_ring;
- usbif_request_t *req;
- RING_IDX i, rp;
- int more_to_do = 0;
-
- rp = usb_ring->sring->req_prod;
- rmb(); /* Ensure we see queued requests up to 'rp'. */
-
- /* Take items off the comms ring, taking care not to overflow. */
- for ( i = usb_ring->req_cons;
- (i != rp) && !RING_REQUEST_CONS_OVERFLOW(usb_ring, i);
- i++ )
- {
- if ( (max_to_do-- == 0) || (NR_PENDING_REQS == MAX_PENDING_REQS) )
- {
- more_to_do = 1;
- break;
- }
-
- req = RING_GET_REQUEST(usb_ring, i);
-
- switch ( req->operation )
- {
- case USBIF_OP_PROBE:
- dispatch_usb_probe(up, req->id, req->port);
- break;
-
- case USBIF_OP_IO:
- /* Assemble an appropriate URB. */
- dispatch_usb_io(up, req);
- break;
-
- case USBIF_OP_RESET:
- dispatch_usb_reset(up, req->port);
- break;
-
- default:
- DPRINTK("error: unknown USB io operation [%d]\n",
- req->operation);
- make_response(up, req->id, req->operation, -EINVAL, 0, 0);
- break;
- }
- }
-
- usb_ring->req_cons = i;
-
- return more_to_do;
-}
-
-static owned_port_t *find_guest_port(usbif_priv_t *up, int port)
-{
- unsigned long flags;
- struct list_head *l;
-
- spin_lock_irqsave(&owned_ports_lock, flags);
- list_for_each(l, &owned_ports)
- {
- owned_port_t *p = list_entry(l, owned_port_t, list);
- if(p->usbif_priv == up && p->guest_port == port)
- {
- spin_unlock_irqrestore(&owned_ports_lock, flags);
- return p;
- }
- }
- spin_unlock_irqrestore(&owned_ports_lock, flags);
-
- return NULL;
-}
-
-static void dispatch_usb_reset(usbif_priv_t *up, unsigned long portid)
-{
- owned_port_t *port = find_guest_port(up, portid);
- int ret = 0;
-
-
- /* Allowing the guest to actually reset the device causes more problems
- * than it's worth. We just fake it out in software but we will do a real
- * reset when the interface is destroyed. */
-
- dump_port(port);
-
- port->guest_address = 0;
- /* If there's an attached device then the port is now enabled. */
- if ( port->dev_present )
- port->enabled = 1;
- else
- port->enabled = 0;
-
- make_response(up, 0, USBIF_OP_RESET, ret, 0, 0);
-}
-
-static void dispatch_usb_probe(usbif_priv_t *up, unsigned long id, unsigned long portid)
-{
- owned_port_t *port = find_guest_port(up, portid);
- int ret;
-
- if ( port != NULL )
- ret = port->dev_present;
- else
- {
- ret = -EINVAL;
- printk(KERN_INFO "dispatch_usb_probe(): invalid port probe request "
- "(port %ld)\n", portid);
- }
-
- /* Probe result is sent back in-band. Probes don't have an associated id
- * right now... */
- make_response(up, id, USBIF_OP_PROBE, ret, portid, 0);
-}
-
-/**
- * check_iso_schedule - safety check the isochronous schedule for an URB
- * @purb : the URB in question
- */
-static int check_iso_schedule(struct urb *purb)
-{
- int i;
- unsigned long total_length = 0;
-
- for ( i = 0; i < purb->number_of_packets; i++ )
- {
- struct usb_iso_packet_descriptor *desc = &purb->iso_frame_desc[i];
-
- if ( desc->offset >= purb->transfer_buffer_length
- || ( desc->offset + desc->length) > purb->transfer_buffer_length )
- return -EINVAL;
-
- total_length += desc->length;
-
- if ( total_length > purb->transfer_buffer_length )
- return -EINVAL;
- }
-
- return 0;
-}
-
-owned_port_t *find_port_for_request(usbif_priv_t *up, usbif_request_t *req);
-
-static void dispatch_usb_io(usbif_priv_t *up, usbif_request_t *req)
-{
- unsigned long buffer_mach;
- int i = 0, offset = 0,
- pending_idx = pending_ring[MASK_PEND_IDX(pending_cons)];
- pending_req_t *pending_req;
- unsigned long remap_prot;
- multicall_entry_t mcl[MMAP_PAGES_PER_REQUEST];
- struct urb *purb = NULL;
- owned_port_t *port;
- unsigned char *setup;
-
- dump_request(req);
-
- if ( NR_PENDING_REQS == MAX_PENDING_REQS )
- {
- printk(KERN_WARNING "usbback: Max requests already queued. "
- "Giving up!\n");
-
- return;
- }
-
- port = find_port_for_request(up, req);
-
- if ( port == NULL )
- {
- printk(KERN_WARNING "No such device! (%d)\n", req->devnum);
- dump_request(req);
-
- make_response(up, req->id, req->operation, -ENODEV, 0, 0);
- return;
- }
- else if ( !port->dev_present )
- {
- /* In normal operation, we'll only get here if a device is unplugged
- * and the frontend hasn't noticed yet. */
- make_response(up, req->id, req->operation, -ENODEV, 0, 0);
- return;
- }
-
-
- setup = kmalloc(8, GFP_KERNEL);
-
- if ( setup == NULL )
- goto no_mem;
-
- /* Copy request out for safety. */
- memcpy(setup, req->setup, 8);
-
- if( setup[0] == 0x0 && setup[1] == 0x5)
- {
- /* To virtualise the USB address space, we need to intercept
- * set_address messages and emulate. From the USB specification:
- * bmRequestType = 0x0;
- * Brequest = SET_ADDRESS (i.e. 0x5)
- * wValue = device address
- * wIndex = 0
- * wLength = 0
- * data = None
- */
- /* Store into the guest transfer buffer using cpu_to_le16 */
- port->guest_address = le16_to_cpu(*(u16 *)(setup + 2));
- /* Make a successful response. That was easy! */
-
- make_response(up, req->id, req->operation, 0, 0, 0);
-
- kfree(setup);
- return;
- }
- else if ( setup[0] == 0x0 && setup[1] == 0x9 )
- {
- /* The host kernel needs to know what device configuration is in use
- * because various error checks get confused otherwise. We just do
- * configuration settings here, under controlled conditions.
- */
-
- /* Ignore configuration setting and hope that the host kernel
- did it right. */
- /* usb_set_configuration(port->dev, setup[2]); */
-
- make_response(up, req->id, req->operation, 0, 0, 0);
-
- kfree(setup);
- return;
- }
- else if ( setup[0] == 0x1 && setup[1] == 0xB )
- {
- /* The host kernel needs to know what device interface is in use
- * because various error checks get confused otherwise. We just do
- * configuration settings here, under controlled conditions.
- */
- usb_set_interface(port->dev, (setup[4] | setup[5] << 8),
- (setup[2] | setup[3] << 8) );
-
- make_response(up, req->id, req->operation, 0, 0, 0);
-
- kfree(setup);
- return;
- }
-
- if ( ( req->transfer_buffer - (req->transfer_buffer & PAGE_MASK)
- + req->length )
- > MMAP_PAGES_PER_REQUEST * PAGE_SIZE )
- {
- printk(KERN_WARNING "usbback: request of %lu bytes too large\n",
- req->length);
- make_response(up, req->id, req->operation, -EINVAL, 0, 0);
- kfree(setup);
- return;
- }
-
- buffer_mach = req->transfer_buffer;
-
- if( buffer_mach == 0 )
- goto no_remap;
-
- ASSERT((req->length >> PAGE_SHIFT) <= MMAP_PAGES_PER_REQUEST);
- ASSERT(buffer_mach);
-
- /* Always map writeable for now. */
- remap_prot = _KERNPG_TABLE;
-
- for ( i = 0, offset = 0; offset < req->length;
- i++, offset += PAGE_SIZE )
- {
- MULTI_update_va_mapping_otherdomain(
- mcl+i, MMAP_VADDR(pending_idx, i),
- pfn_pte_ma((buffer_mach + offset) >> PAGE_SHIFT, remap_prot),
- 0, up->domid);
-
- phys_to_machine_mapping[__pa(MMAP_VADDR(pending_idx, i))>>PAGE_SHIFT] =
- FOREIGN_FRAME((buffer_mach + offset) >> PAGE_SHIFT);
-
- ASSERT(virt_to_mfn(MMAP_VADDR(pending_idx, i))
- == ((buffer_mach >> PAGE_SHIFT) + i));
- }
-
- if ( req->pipe_type == 0 && req->num_iso > 0 ) /* Maybe schedule ISO... */
- {
- /* Map in ISO schedule, if necessary. */
- MULTI_update_va_mapping_otherdomain(
- mcl+i, MMAP_VADDR(pending_idx, i),
- pfn_pte_ma(req->iso_schedule >> PAGE_SHIFT, remap_prot),
- 0, up->domid);
-
- phys_to_machine_mapping[__pa(MMAP_VADDR(pending_idx, i))>>PAGE_SHIFT] =
- FOREIGN_FRAME(req->iso_schedule >> PAGE_SHIFT);
-
- i++;
- }
-
- if ( unlikely(HYPERVISOR_multicall(mcl, i) != 0) )
- BUG();
-
- {
- int j;
- for ( j = 0; j < i; j++ )
- {
- if ( unlikely(mcl[j].result != 0) )
- {
- printk(KERN_WARNING
- "invalid buffer %d -- could not remap it\n", j);
- fast_flush_area(pending_idx, i);
- goto bad_descriptor;
- }
- }
- }
-
- no_remap:
-
- ASSERT(i <= MMAP_PAGES_PER_REQUEST);
- ASSERT(i * PAGE_SIZE >= req->length);
-
- /* We have to do this because some things might complete out of order. */
- pending_req = &pending_reqs[pending_idx];
- pending_req->usbif_priv= up;
- pending_req->id = req->id;
- pending_req->operation = req->operation;
- pending_req->nr_pages = i;
-
- pending_cons++;
-
- usbif_get(up);
-
- /* Fill out an actual request for the USB layer. */
- purb = usb_alloc_urb(req->num_iso);
-
- if ( purb == NULL )
- {
- usbif_put(up);
- free_pending(pending_idx);
- goto no_mem;
- }
-
- purb->dev = port->dev;
- purb->context = pending_req;
- purb->transfer_buffer =
- (void *)(MMAP_VADDR(pending_idx, 0) + (buffer_mach & ~PAGE_MASK));
- if(buffer_mach == 0)
- purb->transfer_buffer = NULL;
- purb->complete = __end_usb_io_op;
- purb->transfer_buffer_length = req->length;
- purb->transfer_flags = req->transfer_flags;
-
- purb->pipe = 0;
- purb->pipe |= req->direction << 7;
- purb->pipe |= port->dev->devnum << 8;
- purb->pipe |= req->speed << 26;
- purb->pipe |= req->pipe_type << 30;
- purb->pipe |= req->endpoint << 15;
-
- purb->number_of_packets = req->num_iso;
-
- if ( purb->number_of_packets * sizeof(usbif_iso_t) > PAGE_SIZE )
- goto urb_error;
-
- /* Make sure there's always some kind of timeout. */
- purb->timeout = ( req->timeout > 0 ) ? (req->timeout * HZ) / 1000
- : 1000;
-
- purb->setup_packet = setup;
-
- if ( req->pipe_type == 0 ) /* ISO */
- {
- int j;
- usbif_iso_t *iso_sched = (usbif_iso_t *)MMAP_VADDR(pending_idx, i - 1);
-
- /* If we're dealing with an iso pipe, we need to copy in a schedule. */
- for ( j = 0; j < purb->number_of_packets; j++ )
- {
- purb->iso_frame_desc[j].length = iso_sched[j].length;
- purb->iso_frame_desc[j].offset = iso_sched[j].buffer_offset;
- iso_sched[j].status = 0;
- }
- }
-
- if ( check_iso_schedule(purb) != 0 )
- goto urb_error;
-
- if ( usb_submit_urb(purb) != 0 )
- goto urb_error;
-
- return;
-
- urb_error:
- dump_urb(purb);
- usbif_put(up);
- free_pending(pending_idx);
-
- bad_descriptor:
- kfree ( setup );
- if ( purb != NULL )
- usb_free_urb(purb);
- make_response(up, req->id, req->operation, -EINVAL, 0, 0);
- return;
-
- no_mem:
- if ( setup != NULL )
- kfree(setup);
- make_response(up, req->id, req->operation, -ENOMEM, 0, 0);
- return;
-}
-
-
-
-/******************************************************************
- * MISCELLANEOUS SETUP / TEARDOWN / DEBUGGING
- */
-
-
-static void make_response(usbif_priv_t *up, unsigned long id,
- unsigned short op, int st, int inband,
- unsigned long length)
-{
- usbif_response_t *resp;
- unsigned long flags;
- usbif_back_ring_t *usb_ring = &up->usb_ring;
-
- /* Place on the response ring for the relevant domain. */
- spin_lock_irqsave(&up->usb_ring_lock, flags);
- resp = RING_GET_RESPONSE(usb_ring, usb_ring->rsp_prod_pvt);
- resp->id = id;
- resp->operation = op;
- resp->status = st;
- resp->data = inband;
- resp->length = length;
- wmb(); /* Ensure other side can see the response fields. */
-
- dump_response(resp);
-
- usb_ring->rsp_prod_pvt++;
- RING_PUSH_RESPONSES(usb_ring);
- spin_unlock_irqrestore(&up->usb_ring_lock, flags);
-
- /* Kick the relevant domain. */
- notify_via_evtchn(up->evtchn);
-}
-
-/**
- * usbif_claim_port - claim devices on a port on behalf of guest
- *
- * Once completed, this will ensure that any device attached to that
- * port is claimed by this driver for use by the guest.
- */
-int usbif_claim_port(usbif_be_claim_port_t *msg)
-{
- owned_port_t *o_p;
-
- /* Sanity... */
- if ( usbif_find_port(msg->path) != NULL )
- {
- printk(KERN_WARNING "usbback: Attempted to claim USB port "
- "we already own!\n");
- return -EINVAL;
- }
-
- /* No need for a slab cache - this should be infrequent. */
- o_p = kmalloc(sizeof(owned_port_t), GFP_KERNEL);
-
- if ( o_p == NULL )
- return -ENOMEM;
-
- o_p->enabled = 0;
- o_p->usbif_priv = usbif_find(msg->domid);
- o_p->guest_port = msg->usbif_port;
- o_p->dev_present = 0;
- o_p->guest_address = 0; /* Default address. */
-
- strcpy(o_p->path, msg->path);
-
- spin_lock_irq(&owned_ports_lock);
-
- list_add(&o_p->list, &owned_ports);
-
- spin_unlock_irq(&owned_ports_lock);
-
- printk(KERN_INFO "usbback: Claimed USB port (%s) for %d.%d\n", o_p->path,
- msg->domid, msg->usbif_port);
-
- /* Force a reprobe for unclaimed devices. */
- usb_scan_devices();
-
- return 0;
-}
-
-owned_port_t *find_port_for_request(usbif_priv_t *up, usbif_request_t *req)
-{
- unsigned long flags;
- struct list_head *port;
-
- /* I'm assuming this is not called from IRQ context - correct? I think
- * it's probably only called in response to control messages or plug events
- * in the USB hub kernel thread, so should be OK. */
- spin_lock_irqsave(&owned_ports_lock, flags);
- list_for_each(port, &owned_ports)
- {
- owned_port_t *p = list_entry(port, owned_port_t, list);
- if(p->usbif_priv == up && p->guest_address == req->devnum && p->enabled )
- {
- dump_port(p);
-
- spin_unlock_irqrestore(&owned_ports_lock, flags);
- return p;
- }
- }
- spin_unlock_irqrestore(&owned_ports_lock, flags);
-
- return NULL;
-}
-
-owned_port_t *__usbif_find_port(char *path)
-{
- struct list_head *port;
-
- list_for_each(port, &owned_ports)
- {
- owned_port_t *p = list_entry(port, owned_port_t, list);
- if(!strcmp(path, p->path))
- {
- return p;
- }
- }
-
- return NULL;
-}
-
-owned_port_t *usbif_find_port(char *path)
-{
- owned_port_t *ret;
- unsigned long flags;
-
- spin_lock_irqsave(&owned_ports_lock, flags);
- ret = __usbif_find_port(path);
- spin_unlock_irqrestore(&owned_ports_lock, flags);
-
- return ret;
-}
-
-
-static void *probe(struct usb_device *dev, unsigned iface,
- const struct usb_device_id *id)
-{
- owned_port_t *p;
-
- /* We don't care what the device is - if we own the port, we want it. We
- * don't deal with device-specifics in this driver, so we don't care what
- * the device actually is ;-) */
- if ( ( p = usbif_find_port(dev->devpath) ) != NULL )
- {
- printk(KERN_INFO "usbback: claimed device attached to owned port\n");
-
- p->dev_present = 1;
- p->dev = dev;
- set_bit(iface, &p->ifaces);
-
- return p->usbif_priv;
- }
- else
- printk(KERN_INFO "usbback: hotplug for non-owned port (%s), ignoring\n",
- dev->devpath);
-
-
- return NULL;
-}
-
-static void disconnect(struct usb_device *dev, void *usbif)
-{
- /* Note the device is removed so we can tell the guest when it probes. */
- owned_port_t *port = usbif_find_port(dev->devpath);
- port->dev_present = 0;
- port->dev = NULL;
- port->ifaces = 0;
-}
-
-
-struct usb_driver driver =
-{
- .owner = THIS_MODULE,
- .name = "Xen USB Backend",
- .probe = probe,
- .disconnect = disconnect,
- .id_table = NULL,
-};
-
-/* __usbif_release_port - internal mechanics for releasing a port */
-void __usbif_release_port(owned_port_t *p)
-{
- int i;
-
- for ( i = 0; p->ifaces != 0; i++)
- if ( p->ifaces & 1 << i )
- {
- usb_driver_release_interface(&driver, usb_ifnum_to_if(p->dev, i));
- clear_bit(i, &p->ifaces);
- }
- list_del(&p->list);
-
- /* Reset the real device. We don't simulate disconnect / probe for other
- * drivers in this kernel because we assume the device is completely under
- * the control of ourselves (i.e. the guest!). This should ensure that the
- * device is in a sane state for the next customer ;-) */
-
- /* MAW NB: we're not resetting the real device here. This looks perfectly
- * valid to me but it causes memory corruption. We seem to get away with not
- * resetting for now, although it'd be nice to have this tracked down. */
-/* if ( p->dev != NULL) */
-/* usb_reset_device(p->dev); */
-
- kfree(p);
-}
-
-
-/**
- * usbif_release_port - stop claiming devices on a port on behalf of guest
- */
-void usbif_release_port(usbif_be_release_port_t *msg)
-{
- owned_port_t *p;
-
- spin_lock_irq(&owned_ports_lock);
- p = __usbif_find_port(msg->path);
- __usbif_release_port(p);
- spin_unlock_irq(&owned_ports_lock);
-}
-
-void usbif_release_ports(usbif_priv_t *up)
-{
- struct list_head *port, *tmp;
- unsigned long flags;
-
- spin_lock_irqsave(&owned_ports_lock, flags);
- list_for_each_safe(port, tmp, &owned_ports)
- {
- owned_port_t *p = list_entry(port, owned_port_t, list);
- if ( p->usbif_priv == up )
- __usbif_release_port(p);
- }
- spin_unlock_irqrestore(&owned_ports_lock, flags);
-}
-
-static int __init usbif_init(void)
-{
- int i;
- struct page *page;
-
- if ( !(xen_start_info->flags & SIF_INITDOMAIN) &&
- !(xen_start_info->flags & SIF_USB_BE_DOMAIN) )
- return 0;
-
- page = balloon_alloc_empty_page_range(MMAP_PAGES);
- BUG_ON(page == NULL);
- mmap_vstart = (unsigned long)pfn_to_kaddr(page_to_pfn(page));
-
- pending_cons = 0;
- pending_prod = MAX_PENDING_REQS;
- memset(pending_reqs, 0, sizeof(pending_reqs));
- for ( i = 0; i < MAX_PENDING_REQS; i++ )
- pending_ring[i] = i;
-
- spin_lock_init(&pend_prod_lock);
-
- spin_lock_init(&owned_ports_lock);
- INIT_LIST_HEAD(&owned_ports);
-
- spin_lock_init(&usbio_schedule_list_lock);
- INIT_LIST_HEAD(&usbio_schedule_list);
-
- if ( kernel_thread(usbio_schedule, 0, CLONE_FS | CLONE_FILES) < 0 )
- BUG();
-
- usbif_interface_init();
-
- usbif_ctrlif_init();
-
- usb_register(&driver);
-
- printk(KERN_INFO "Xen USB Backend Initialised");
-
- return 0;
-}
-
-__initcall(usbif_init);
diff -r eba5afe9aa37 -r 10759a44ce3b linux-2.6-xen-sparse/drivers/xen/usbfront/usbfront.c
--- a/linux-2.6-xen-sparse/drivers/xen/usbfront/usbfront.c Thu Sep 22 15:05:44 2005
+++ /dev/null Thu Sep 22 15:12:14 2005
@@ -1,1735 +0,0 @@
-/*
- * Xen Virtual USB Frontend Driver
- *
- * This file contains the first version of the Xen virtual USB hub
- * that I've managed not to delete by mistake (3rd time lucky!).
- *
- * Based on Linux's uhci.c, original copyright notices are displayed
- * below. Portions also (c) 2004 Intel Research Cambridge
- * and (c) 2004, 2005 Mark Williamson
- *
- * Contact <mark.williamson@cl.cam.ac.uk> or
- * <xen-devel@lists.sourceforge.net> regarding this code.
- *
- * Still to be (maybe) implemented:
- * - migration / backend restart support?
- * - support for building / using as a module
- */
-
-/*
- * Universal Host Controller Interface driver for USB.
- *
- * Maintainer: Johannes Erdfelt <johannes@erdfelt.com>
- *
- * (C) Copyright 1999 Linus Torvalds
- * (C) Copyright 1999-2002 Johannes Erdfelt, johannes@erdfelt.com
- * (C) Copyright 1999 Randy Dunlap
- * (C) Copyright 1999 Georg Acher, acher@in.tum.de
- * (C) Copyright 1999 Deti Fliegl, deti@fliegl.de
- * (C) Copyright 1999 Thomas Sailer, sailer@ife.ee.ethz.ch
- * (C) Copyright 1999 Roman Weissgaerber, weissg@vienna.at
- * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface
- * support from usb-ohci.c by Adam Richter, adam@yggdrasil.com).
- * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c)
- *
- * Intel documents this fairly well, and as far as I know there
- * are no royalties or anything like that, but even so there are
- * people who decided that they want to do the same thing in a
- * completely different way.
- *
- * WARNING! The USB documentation is downright evil. Most of it
- * is just crap, written by a committee. You're better off ignoring
- * most of it, the important stuff is:
- * - the low-level protocol (fairly simple but lots of small details)
- * - working around the horridness of the rest
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#ifdef CONFIG_USB_DEBUG
-#define DEBUG
-#else
-#undef DEBUG
-#endif
-#include <linux/usb.h>
-
-#include <asm/irq.h>
-#include <asm/system.h>
-
-#include "xhci.h"
-
-#include "../../../../../drivers/usb/hcd.h"
-
-#include <asm-xen/xen-public/io/usbif.h>
-#include <asm/xen-public/io/domain_controller.h>
-
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.0"
-#define DRIVER_AUTHOR "Linus 'Frodo Rabbit' Torvalds, Johannes Erdfelt, " \
- "Randy Dunlap, Georg Acher, Deti Fliegl, " \
- "Thomas Sailer, Roman Weissgaerber, Mark Williamson"
-#define DRIVER_DESC "Xen Virtual USB Host Controller Interface"
-
-/*
- * debug = 0, no debugging messages
- * debug = 1, dump failed URB's except for stalls
- * debug = 2, dump all failed URB's (including stalls)
- */
-#ifdef DEBUG
-static int debug = 1;
-#else
-static int debug = 0;
-#endif
-MODULE_PARM(debug, "i");
-MODULE_PARM_DESC(debug, "Debug level");
-static char *errbuf;
-#define ERRBUF_LEN (PAGE_SIZE * 8)
-
-static int rh_submit_urb(struct urb *urb);
-static int rh_unlink_urb(struct urb *urb);
-static int xhci_unlink_urb(struct urb *urb);
-static void xhci_call_completion(struct urb *urb);
-static void xhci_drain_ring(void);
-static void xhci_transfer_result(struct xhci *xhci, struct urb *urb);
-static void xhci_finish_completion(void);
-
-#define MAX_URB_LOOP 2048 /* Maximum number of linked URB's */
-
-static kmem_cache_t *xhci_up_cachep; /* urb_priv cache */
-static struct xhci *xhci; /* XHCI structure for the interface */
-
-/******************************************************************************
- * DEBUGGING
- */
-
-#ifdef DEBUG
-
-static void dump_urb(struct urb *urb)
-{
- printk(KERN_DEBUG "dumping urb @ %p\n"
- " hcpriv = %p\n"
- " next = %p\n"
- " dev = %p\n"
- " pipe = 0x%lx\n"
- " status = %d\n"
- " transfer_flags = 0x%lx\n"
- " transfer_buffer = %p\n"
- " transfer_buffer_length = %d\n"
- " actual_length = %d\n"
- " bandwidth = %d\n"
- " setup_packet = %p\n",
- urb, urb->hcpriv, urb->next, urb->dev, urb->pipe, urb->status,
- urb->transfer_flags, urb->transfer_buffer,
- urb->transfer_buffer_length, urb->actual_length, urb->bandwidth,
- urb->setup_packet);
- if ( urb->setup_packet != NULL )
- printk(KERN_DEBUG
- "setup = { 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x }\n",
- urb->setup_packet[0], urb->setup_packet[1],
- urb->setup_packet[2], urb->setup_packet[3],
- urb->setup_packet[4], urb->setup_packet[5],
- urb->setup_packet[6], urb->setup_packet[7]);
- printk(KERN_DEBUG "complete = %p\n"
- "interval = %d\n", urb->complete, urb->interval);
-
-}
-
-static void xhci_show_resp(usbif_response_t *r)
-{
- printk(KERN_DEBUG "dumping response @ %p\n"
- " id=0x%lx\n"
- " op=0x%x\n"
- " data=0x%x\n"
- " status=0x%x\n"
- " length=0x%lx\n",
- r->id, r->operation, r->data, r->status, r->length);
-}
-
-#define DPRINK(...) printk(KERN_DEBUG __VA_ARGS__)
-
-#else /* DEBUG */
-
-#define dump_urb(blah) ((void)0)
-#define xhci_show_resp(blah) ((void)0)
-#define DPRINTK(blah,...) ((void)0)
-
-#endif /* DEBUG */
-
-/******************************************************************************
- * RING REQUEST HANDLING
- */
-
-#define RING_PLUGGED(_hc) ( RING_FULL(&_hc->usb_ring) || _hc->recovery )
-
-/**
- * xhci_construct_isoc - add isochronous information to a request
- */
-static int xhci_construct_isoc(usbif_request_t *req, struct urb *urb)
-{
- usbif_iso_t *schedule;
- int i;
- struct urb_priv *urb_priv = urb->hcpriv;
-
- req->num_iso = urb->number_of_packets;
- schedule = (usbif_iso_t *)__get_free_page(GFP_KERNEL);
-
- if ( schedule == NULL )
- return -ENOMEM;
-
- for ( i = 0; i < req->num_iso; i++ )
- {
- schedule[i].buffer_offset = urb->iso_frame_desc[i].offset;
- schedule[i].length = urb->iso_frame_desc[i].length;
- }
-
- urb_priv->schedule = schedule;
- req->iso_schedule = virt_to_mfn(schedule) << PAGE_SHIFT;
-
- return 0;
-}
-
-/**
- * xhci_queue_req - construct and queue request for an URB
- */
-static int xhci_queue_req(struct urb *urb)
-{
- unsigned long flags;
- usbif_request_t *req;
- usbif_front_ring_t *usb_ring = &xhci->usb_ring;
-
-#if DEBUG
- printk(KERN_DEBUG
- "usbif = %p, req_prod = %d (@ 0x%lx), resp_prod = %d, resp_cons = %d\n",
- usbif, usbif->req_prod, virt_to_mfn(&usbif->req_prod),
- usbif->resp_prod, xhci->usb_resp_cons);
-#endif
-
- spin_lock_irqsave(&xhci->ring_lock, flags);
-
- if ( RING_PLUGGED(xhci) )
- {
- printk(KERN_WARNING
- "xhci_queue_req(): USB ring plugged, not queuing request\n");
- spin_unlock_irqrestore(&xhci->ring_lock, flags);
- return -ENOBUFS;
- }
-
- /* Stick something in the shared communications ring. */
- req = RING_GET_REQUEST(usb_ring, usb_ring->req_prod_pvt);
-
- req->operation = USBIF_OP_IO;
- req->port = 0; /* We don't care what the port is. */
- req->id = (unsigned long) urb->hcpriv;
- req->transfer_buffer = virt_to_mfn(urb->transfer_buffer) << PAGE_SHIFT;
- req->devnum = usb_pipedevice(urb->pipe);
- req->direction = usb_pipein(urb->pipe);
- req->speed = usb_pipeslow(urb->pipe);
- req->pipe_type = usb_pipetype(urb->pipe);
- req->length = urb->transfer_buffer_length;
- req->transfer_flags = urb->transfer_flags;
- req->endpoint = usb_pipeendpoint(urb->pipe);
- req->speed = usb_pipeslow(urb->pipe);
- req->timeout = urb->timeout * (1000 / HZ);
-
- if ( usb_pipetype(urb->pipe) == 0 ) /* ISO */
- {
- int ret = xhci_construct_isoc(req, urb);
- if ( ret != 0 )
- return ret;
- }
-
- if(urb->setup_packet != NULL)
- memcpy(req->setup, urb->setup_packet, 8);
- else
- memset(req->setup, 0, 8);
-
- usb_ring->req_prod_pvt++;
- RING_PUSH_REQUESTS(usb_ring);
-
- spin_unlock_irqrestore(&xhci->ring_lock, flags);
-
- notify_via_evtchn(xhci->evtchn);
-
- DPRINTK("Queued request for an URB.\n");
- dump_urb(urb);
-
- return -EINPROGRESS;
-}
-
-/**
- * xhci_queue_probe - queue a probe request for a particular port
- */
-static inline usbif_request_t *xhci_queue_probe(usbif_vdev_t port)
-{
- usbif_request_t *req;
- usbif_front_ring_t *usb_ring = &xhci->usb_ring;
-
-#if DEBUG
- printk(KERN_DEBUG
- "queuing probe: req_prod = %d (@ 0x%lx), resp_prod = %d, "
- "resp_cons = %d\n", usbif->req_prod,
- virt_to_mfn(&usbif->req_prod),
- usbif->resp_prod, xhci->usb_resp_cons);
-#endif
-
- /* This is always called from the timer interrupt. */
- spin_lock(&xhci->ring_lock);
-
- if ( RING_PLUGGED(xhci) )
- {
- printk(KERN_WARNING
- "xhci_queue_probe(): ring full, not queuing request\n");
- spin_unlock(&xhci->ring_lock);
- return NULL;
- }
-
- /* Stick something in the shared communications ring. */
- req = RING_GET_REQUEST(usb_ring, usb_ring->req_prod_pvt);
-
- memset(req, 0, sizeof(*req));
-
- req->operation = USBIF_OP_PROBE;
- req->port = port;
-
- usb_ring->req_prod_pvt++;
- RING_PUSH_REQUESTS(usb_ring);
-
- spin_unlock(&xhci->ring_lock);
-
- notify_via_evtchn(xhci->evtchn);
-
- return req;
-}
-
-/**
- * xhci_port_reset - queue a reset request for a particular port
- */
-static int xhci_port_reset(usbif_vdev_t port)
-{
- usbif_request_t *req;
- usbif_front_ring_t *usb_ring = &xhci->usb_ring;
-
- /* Only ever happens from process context (hub thread). */
- spin_lock_irq(&xhci->ring_lock);
-
- if ( RING_PLUGGED(xhci) )
- {
- printk(KERN_WARNING
- "xhci_port_reset(): ring plugged, not queuing request\n");
- spin_unlock_irq(&xhci->ring_lock);
- return -ENOBUFS;
- }
-
- /* We only reset one port at a time, so we only need one variable per
- * hub. */
- xhci->awaiting_reset = 1;
-
- /* Stick something in the shared communications ring. */
- req = RING_GET_REQUEST(usb_ring, usb_ring->req_prod_pvt);
-
- memset(req, 0, sizeof(*req));
-
- req->operation = USBIF_OP_RESET;
- req->port = port;
-
- usb_ring->req_prod_pvt++;
- RING_PUSH_REQUESTS(usb_ring);
-
- spin_unlock_irq(&xhci->ring_lock);
-
- notify_via_evtchn(xhci->evtchn);
-
- while ( xhci->awaiting_reset > 0 )
- {
- mdelay(1);
- xhci_drain_ring();
- }
-
- xhci->rh.ports[port].pe = 1;
- xhci->rh.ports[port].pe_chg = 1;
-
- return xhci->awaiting_reset;
-}
-
-
-/******************************************************************************
- * RING RESPONSE HANDLING
- */
-
-static void receive_usb_reset(usbif_response_t *resp)
-{
- xhci->awaiting_reset = resp->status;
- rmb();
-
-}
-
-static void receive_usb_probe(usbif_response_t *resp)
-{
- spin_lock(&xhci->rh.port_state_lock);
-
- if ( resp->status >= 0 )
- {
- if ( resp->status == 1 )
- {
- /* If theres a device there and there wasn't one before there must
- * have been a connection status change. */
- if( xhci->rh.ports[resp->data].cs == 0 )
- {
- xhci->rh.ports[resp->data].cs = 1;
- xhci->rh.ports[resp->data].cs_chg = 1;
- }
- }
- else if ( resp->status == 0 )
- {
- if(xhci->rh.ports[resp->data].cs == 1 )
- {
- xhci->rh.ports[resp->data].cs = 0;
- xhci->rh.ports[resp->data].cs_chg = 1;
- xhci->rh.ports[resp->data].pe = 0;
- /* According to USB Spec v2.0, 11.24.2.7.2.2, we don't need
- * to set pe_chg since an error has not occurred. */
- }
- }
- else
- printk(KERN_WARNING "receive_usb_probe(): unexpected status %d "
- "for port %d\n", resp->status, resp->data);
- }
- else if ( resp->status < 0)
- printk(KERN_WARNING "receive_usb_probe(): got error status %d\n",
- resp->status);
-
- spin_unlock(&xhci->rh.port_state_lock);
-}
-
-static void receive_usb_io(usbif_response_t *resp)
-{
- struct urb_priv *urbp = (struct urb_priv *)resp->id;
- struct urb *urb = urbp->urb;
-
- urb->actual_length = resp->length;
- urbp->in_progress = 0;
-
- if( usb_pipetype(urb->pipe) == 0 ) /* ISO */
- {
- int i;
-
- /* Copy ISO schedule results back in. */
- for ( i = 0; i < urb->number_of_packets; i++ )
- {
- urb->iso_frame_desc[i].status
- = urbp->schedule[i].status;
- urb->iso_frame_desc[i].actual_length
- = urbp->schedule[i].length;
- }
- free_page((unsigned long)urbp->schedule);
- }
-
- /* Only set status if it's not been changed since submission. It might
- * have been changed if the URB has been unlinked asynchronously, for
- * instance. */
- if ( urb->status == -EINPROGRESS )
- urbp->status = urb->status = resp->status;
-}
-
-/**
- * xhci_drain_ring - drain responses from the ring, calling handlers
- *
- * This may be called from interrupt context when an event is received from the
- * backend domain, or sometimes in process context whilst waiting for a port
- * reset or URB completion.
- */
-static void xhci_drain_ring(void)
-{
- struct list_head *tmp, *head;
- usbif_front_ring_t *usb_ring = &xhci->usb_ring;
- usbif_response_t *resp;
- RING_IDX i, rp;
-
- /* Walk the ring here to get responses, updating URBs to show what
- * completed. */
-
- rp = usb_ring->sring->rsp_prod;
- rmb(); /* Ensure we see queued requests up to 'rp'. */
-
- /* Take items off the comms ring, taking care not to overflow. */
- for ( i = usb_ring->rsp_cons; i != rp; i++ )
- {
- resp = RING_GET_RESPONSE(usb_ring, i);
-
- /* May need to deal with batching and with putting a ceiling on
- the number dispatched for performance and anti-dos reasons */
-
- xhci_show_resp(resp);
-
- switch ( resp->operation )
- {
- case USBIF_OP_PROBE:
- receive_usb_probe(resp);
- break;
-
- case USBIF_OP_IO:
- receive_usb_io(resp);
- break;
-
- case USBIF_OP_RESET:
- receive_usb_reset(resp);
- break;
-
- default:
- printk(KERN_WARNING
- "error: unknown USB io operation response [%d]\n",
- resp->operation);
- break;
- }
- }
-
- usb_ring->rsp_cons = i;
-
- /* Walk the list of pending URB's to see which ones completed and do
- * callbacks, etc. */
- spin_lock(&xhci->urb_list_lock);
- head = &xhci->urb_list;
- tmp = head->next;
- while (tmp != head) {
- struct urb *urb = list_entry(tmp, struct urb, urb_list);
-
- tmp = tmp->next;
-
- /* Checks the status and does all of the magic necessary */
- xhci_transfer_result(xhci, urb);
- }
- spin_unlock(&xhci->urb_list_lock);
-
- xhci_finish_completion();
-}
-
-
-static void xhci_interrupt(int irq, void *__xhci, struct pt_regs *regs)
-{
- xhci_drain_ring();
-}
-
-/******************************************************************************
- * HOST CONTROLLER FUNCTIONALITY
- */
-
-/**
- * no-op implementation of private device alloc / free routines
- */
-static int xhci_do_nothing_dev(struct usb_device *dev)
-{
- return 0;
-}
-
-static inline void xhci_add_complete(struct urb *urb)
-{
- struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
- unsigned long flags;
-
- spin_lock_irqsave(&xhci->complete_list_lock, flags);
- list_add_tail(&urbp->complete_list, &xhci->complete_list);
- spin_unlock_irqrestore(&xhci->complete_list_lock, flags);
-}
-
-/* When this returns, the owner of the URB may free its
- * storage.
- *
- * We spin and wait for the URB to complete before returning.
- *
- * Call with urb->lock acquired.
- */
-static void xhci_delete_urb(struct urb *urb)
-{
- struct urb_priv *urbp;
-
- urbp = urb->hcpriv;
-
- /* If there's no urb_priv structure for this URB then it can't have
- * been submitted at all. */
- if ( urbp == NULL )
- return;
-
- /* For now we just spin until the URB completes. It shouldn't take too
- * long and we don't expect to have to do this very often. */
- while ( urb->status == -EINPROGRESS )
- {
- xhci_drain_ring();
- mdelay(1);
- }
-
- /* Now we know that further transfers to the buffer won't
- * occur, so we can safely return. */
-}
-
-static struct urb_priv *xhci_alloc_urb_priv(struct urb *urb)
-{
- struct urb_priv *urbp;
-
- urbp = kmem_cache_alloc(xhci_up_cachep, SLAB_ATOMIC);
- if (!urbp) {
- err("xhci_alloc_urb_priv: couldn't allocate memory for urb_priv\n");
- return NULL;
- }
-
- memset((void *)urbp, 0, sizeof(*urbp));
-
- urbp->inserttime = jiffies;
- urbp->urb = urb;
- urbp->dev = urb->dev;
-
- INIT_LIST_HEAD(&urbp->complete_list);
-
- urb->hcpriv = urbp;
-
- return urbp;
-}
-
-/*
- * MUST be called with urb->lock acquired
- */
-/* When is this called? Do we need to stop the transfer (as we
- * currently do)? */
-static void xhci_destroy_urb_priv(struct urb *urb)
-{
- struct urb_priv *urbp;
-
- urbp = (struct urb_priv *)urb->hcpriv;
- if (!urbp)
- return;
-
- if (!list_empty(&urb->urb_list))
- warn("xhci_destroy_urb_priv: urb %p still on xhci->urb_list", urb);
-
- if (!list_empty(&urbp->complete_list))
- warn("xhci_destroy_urb_priv: urb %p still on xhci->complete_list", urb);
-
- kmem_cache_free(xhci_up_cachep, urb->hcpriv);
-
- urb->hcpriv = NULL;
-}
-
-/**
- * Try to find URBs in progress on the same pipe to the same device.
- *
- * MUST be called with xhci->urb_list_lock acquired
- */
-static struct urb *xhci_find_urb_ep(struct xhci *xhci, struct urb *urb)
-{
- struct list_head *tmp, *head;
-
- /* We don't match Isoc transfers since they are special */
- if (usb_pipeisoc(urb->pipe))
- return NULL;
-
- head = &xhci->urb_list;
- tmp = head->next;
- while (tmp != head) {
- struct urb *u = list_entry(tmp, struct urb, urb_list);
-
- tmp = tmp->next;
-
- if (u->dev == urb->dev && u->pipe == urb->pipe &&
- u->status == -EINPROGRESS)
- return u;
- }
-
- return NULL;
-}
-
-static int xhci_submit_urb(struct urb *urb)
-{
- int ret = -EINVAL;
- unsigned long flags;
- struct urb *eurb;
- int bustime;
-
- DPRINTK("URB submitted to XHCI driver.\n");
- dump_urb(urb);
-
- if (!urb)
- return -EINVAL;
-
- if (!urb->dev || !urb->dev->bus || !urb->dev->bus->hcpriv) {
- warn("xhci_submit_urb: urb %p belongs to disconnected device or bus?", urb);
- return -ENODEV;
- }
-
- if ( urb->dev->devpath == NULL )
- BUG();
-
- usb_inc_dev_use(urb->dev);
-
- spin_lock_irqsave(&xhci->urb_list_lock, flags);
- spin_lock(&urb->lock);
-
- if (urb->status == -EINPROGRESS || urb->status == -ECONNRESET ||
- urb->status == -ECONNABORTED) {
- dbg("xhci_submit_urb: urb not available to submit (status = %d)", urb->status);
- /* Since we can have problems on the out path */
- spin_unlock(&urb->lock);
- spin_unlock_irqrestore(&xhci->urb_list_lock, flags);
- usb_dec_dev_use(urb->dev);
-
- return ret;
- }
-
- INIT_LIST_HEAD(&urb->urb_list);
- if (!xhci_alloc_urb_priv(urb)) {
- ret = -ENOMEM;
-
- goto out;
- }
-
- ( (struct urb_priv *)urb->hcpriv )->in_progress = 1;
-
- eurb = xhci_find_urb_ep(xhci, urb);
- if (eurb && !(urb->transfer_flags & USB_QUEUE_BULK)) {
- ret = -ENXIO;
-
- goto out;
- }
-
- /* Short circuit the virtual root hub */
- if (urb->dev == xhci->rh.dev) {
- ret = rh_submit_urb(urb);
-
- goto out;
- }
-
- switch (usb_pipetype(urb->pipe)) {
- case PIPE_CONTROL:
- case PIPE_BULK:
- ret = xhci_queue_req(urb);
- break;
-
- case PIPE_INTERRUPT:
- if (urb->bandwidth == 0) { /* not yet checked/allocated */
- bustime = usb_check_bandwidth(urb->dev, urb);
- if (bustime < 0)
- ret = bustime;
- else {
- ret = xhci_queue_req(urb);
- if (ret == -EINPROGRESS)
- usb_claim_bandwidth(urb->dev, urb,
- bustime, 0);
- }
- } else /* bandwidth is already set */
- ret = xhci_queue_req(urb);
- break;
-
- case PIPE_ISOCHRONOUS:
- if (urb->bandwidth == 0) { /* not yet checked/allocated */
- if (urb->number_of_packets <= 0) {
- ret = -EINVAL;
- break;
- }
- bustime = usb_check_bandwidth(urb->dev, urb);
- if (bustime < 0) {
- ret = bustime;
- break;
- }
-
- ret = xhci_queue_req(urb);
- if (ret == -EINPROGRESS)
- usb_claim_bandwidth(urb->dev, urb, bustime, 1);
- } else /* bandwidth is already set */
- ret = xhci_queue_req(urb);
- break;
- }
-out:
- urb->status = ret;
-
- if (ret == -EINPROGRESS) {
- /* We use _tail to make find_urb_ep more efficient */
- list_add_tail(&urb->urb_list, &xhci->urb_list);
-
- spin_unlock(&urb->lock);
- spin_unlock_irqrestore(&xhci->urb_list_lock, flags);
-
- return 0;
- }
-
- xhci_delete_urb(urb);
-
- spin_unlock(&urb->lock);
- spin_unlock_irqrestore(&xhci->urb_list_lock, flags);
-
- /* Only call completion if it was successful */
- if (!ret)
- xhci_call_completion(urb);
-
- return ret;
-}
-
-/*
- * Return the result of a transfer
- *
- * MUST be called with urb_list_lock acquired
- */
-static void xhci_transfer_result(struct xhci *xhci, struct urb *urb)
-{
- int ret = 0;
- unsigned long flags;
- struct urb_priv *urbp;
-
- /* The root hub is special */
- if (urb->dev == xhci->rh.dev)
- return;
-
- spin_lock_irqsave(&urb->lock, flags);
-
- urbp = (struct urb_priv *)urb->hcpriv;
-
- if ( ( (struct urb_priv *)urb->hcpriv )->in_progress )
- ret = -EINPROGRESS;
-
- if (urb->actual_length < urb->transfer_buffer_length) {
- if (urb->transfer_flags & USB_DISABLE_SPD) {
- ret = -EREMOTEIO;
- }
- }
-
- if (urb->status == -EPIPE)
- {
- ret = urb->status;
- /* endpoint has stalled - mark it halted */
- usb_endpoint_halt(urb->dev, usb_pipeendpoint(urb->pipe),
- usb_pipeout(urb->pipe));
- }
-
- if ((debug == 1 && ret != 0 && ret != -EPIPE) ||
- (ret != 0 && debug > 1)) {
- /* Some debugging code */
- dbg("xhci_result_interrupt/bulk() failed with status %x",
- status);
- }
-
- if (ret == -EINPROGRESS)
- goto out;
-
- switch (usb_pipetype(urb->pipe)) {
- case PIPE_CONTROL:
- case PIPE_BULK:
- case PIPE_ISOCHRONOUS:
- /* Release bandwidth for Interrupt or Isoc. transfers */
- /* Spinlock needed ? */
- if (urb->bandwidth)
- usb_release_bandwidth(urb->dev, urb, 1);
- xhci_delete_urb(urb);
- break;
- case PIPE_INTERRUPT:
- /* Interrupts are an exception */
- if (urb->interval)
- goto out_complete;
-
- /* Release bandwidth for Interrupt or Isoc. transfers */
- /* Spinlock needed ? */
- if (urb->bandwidth)
- usb_release_bandwidth(urb->dev, urb, 0);
- xhci_delete_urb(urb);
- break;
- default:
- info("xhci_transfer_result: unknown pipe type %d for urb %p\n",
- usb_pipetype(urb->pipe), urb);
- }
-
- /* Remove it from xhci->urb_list */
- list_del_init(&urb->urb_list);
-
-out_complete:
- xhci_add_complete(urb);
-
-out:
- spin_unlock_irqrestore(&urb->lock, flags);
-}
-
-static int xhci_unlink_urb(struct urb *urb)
-{
- unsigned long flags;
- struct urb_priv *urbp = urb->hcpriv;
-
- if (!urb)
- return -EINVAL;
-
- if (!urb->dev || !urb->dev->bus || !urb->dev->bus->hcpriv)
- return -ENODEV;
-
- spin_lock_irqsave(&xhci->urb_list_lock, flags);
- spin_lock(&urb->lock);
-
- /* Release bandwidth for Interrupt or Isoc. transfers */
- /* Spinlock needed ? */
- if (urb->bandwidth) {
- switch (usb_pipetype(urb->pipe)) {
- case PIPE_INTERRUPT:
- usb_release_bandwidth(urb->dev, urb, 0);
- break;
- case PIPE_ISOCHRONOUS:
- usb_release_bandwidth(urb->dev, urb, 1);
- break;
- default:
- break;
- }
- }
-
- if (urb->status != -EINPROGRESS) {
- spin_unlock(&urb->lock);
- spin_unlock_irqrestore(&xhci->urb_list_lock, flags);
- return 0;
- }
-
- list_del_init(&urb->urb_list);
-
- /* Short circuit the virtual root hub */
- if (urb->dev == xhci->rh.dev) {
- rh_unlink_urb(urb);
-
- spin_unlock(&urb->lock);
- spin_unlock_irqrestore(&xhci->urb_list_lock, flags);
-
- xhci_call_completion(urb);
- } else {
- if (urb->transfer_flags & USB_ASYNC_UNLINK) {
- /* We currently don't currently attempt to cancel URBs
- * that have been queued in the ring. We handle async
- * unlinked URBs when they complete. */
- urbp->status = urb->status = -ECONNABORTED;
- spin_unlock(&urb->lock);
- spin_unlock_irqrestore(&xhci->urb_list_lock, flags);
- } else {
- urb->status = -ENOENT;
-
- spin_unlock(&urb->lock);
- spin_unlock_irqrestore(&xhci->urb_list_lock, flags);
-
- if (in_interrupt()) { /* wait at least 1 frame */
- static int errorcount = 10;
-
- if (errorcount--)
- dbg("xhci_unlink_urb called from interrupt for urb %p", urb);
- udelay(1000);
- } else
- schedule_timeout(1+1*HZ/1000);
-
- xhci_delete_urb(urb);
-
- xhci_call_completion(urb);
- }
- }
-
- return 0;
-}
-
-static void xhci_call_completion(struct urb *urb)
-{
- struct urb_priv *urbp;
- struct usb_device *dev = urb->dev;
- int is_ring = 0, killed, resubmit_interrupt, status;
- struct urb *nurb;
- unsigned long flags;
-
- spin_lock_irqsave(&urb->lock, flags);
-
- urbp = (struct urb_priv *)urb->hcpriv;
- if (!urbp || !urb->dev) {
- spin_unlock_irqrestore(&urb->lock, flags);
- return;
- }
-
- killed = (urb->status == -ENOENT || urb->status == -ECONNABORTED ||
- urb->status == -ECONNRESET);
- resubmit_interrupt = (usb_pipetype(urb->pipe) == PIPE_INTERRUPT &&
- urb->interval);
-
- nurb = urb->next;
- if (nurb && !killed) {
- int count = 0;
-
- while (nurb && nurb != urb && count < MAX_URB_LOOP) {
- if (nurb->status == -ENOENT ||
- nurb->status == -ECONNABORTED ||
- nurb->status == -ECONNRESET) {
- killed = 1;
- break;
- }
-
- nurb = nurb->next;
- count++;
- }
-
- if (count == MAX_URB_LOOP)
- err("xhci_call_completion: too many linked URB's, loop? (first loop)");
-
- /* Check to see if chain is a ring */
- is_ring = (nurb == urb);
- }
-
- status = urbp->status;
- if (!resubmit_interrupt || killed)
- /* We don't need urb_priv anymore */
- xhci_destroy_urb_priv(urb);
-
- if (!killed)
- urb->status = status;
-
- spin_unlock_irqrestore(&urb->lock, flags);
-
- if (urb->complete)
- urb->complete(urb);
-
- if (resubmit_interrupt)
- /* Recheck the status. The completion handler may have */
- /* unlinked the resubmitting interrupt URB */
- killed = (urb->status == -ENOENT ||
- urb->status == -ECONNABORTED ||
- urb->status == -ECONNRESET);
-
- if (resubmit_interrupt && !killed) {
- if ( urb->dev != xhci->rh.dev )
- xhci_queue_req(urb); /* XXX What if this fails? */
- /* Don't need to resubmit URBs for the virtual root dev. */
- } else {
- if (is_ring && !killed) {
- urb->dev = dev;
- xhci_submit_urb(urb);
- } else {
- /* We decrement the usage count after we're done */
- /* with everything */
- usb_dec_dev_use(dev);
- }
- }
-}
-
-static void xhci_finish_completion(void)
-{
- struct list_head *tmp, *head;
- unsigned long flags;
-
- spin_lock_irqsave(&xhci->complete_list_lock, flags);
- head = &xhci->complete_list;
- tmp = head->next;
- while (tmp != head) {
- struct urb_priv *urbp = list_entry(tmp, struct urb_priv,
- complete_list);
- struct urb *urb = urbp->urb;
-
- list_del_init(&urbp->complete_list);
- spin_unlock_irqrestore(&xhci->complete_list_lock, flags);
-
- xhci_call_completion(urb);
-
- spin_lock_irqsave(&xhci->complete_list_lock, flags);
- head = &xhci->complete_list;
- tmp = head->next;
- }
- spin_unlock_irqrestore(&xhci->complete_list_lock, flags);
-}
-
-static struct usb_operations xhci_device_operations = {
- .allocate = xhci_do_nothing_dev,
- .deallocate = xhci_do_nothing_dev,
- /* It doesn't look like any drivers actually care what the frame number
- * is at the moment! If necessary, we could approximate the current
- * frame nubmer by passing it from the backend in response messages. */
- .get_frame_number = NULL,
- .submit_urb = xhci_submit_urb,
- .unlink_urb = xhci_unlink_urb
-};
-
-/******************************************************************************
- * VIRTUAL ROOT HUB EMULATION
- */
-
-static __u8 root_hub_dev_des[] =
-{
- 0x12, /* __u8 bLength; */
- 0x01, /* __u8 bDescriptorType; Device */
- 0x00, /* __u16 bcdUSB; v1.0 */
- 0x01,
- 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */
- 0x00, /* __u8 bDeviceSubClass; */
- 0x00, /* __u8 bDeviceProtocol; */
- 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */
- 0x00, /* __u16 idVendor; */
- 0x00,
- 0x00, /* __u16 idProduct; */
- 0x00,
- 0x00, /* __u16 bcdDevice; */
- 0x00,
- 0x00, /* __u8 iManufacturer; */
- 0x02, /* __u8 iProduct; */
- 0x01, /* __u8 iSerialNumber; */
- 0x01 /* __u8 bNumConfigurations; */
-};
-
-
-/* Configuration descriptor */
-static __u8 root_hub_config_des[] =
-{
- 0x09, /* __u8 bLength; */
- 0x02, /* __u8 bDescriptorType; Configuration */
- 0x19, /* __u16 wTotalLength; */
- 0x00,
- 0x01, /* __u8 bNumInterfaces; */
- 0x01, /* __u8 bConfigurationValue; */
- 0x00, /* __u8 iConfiguration; */
- 0x40, /* __u8 bmAttributes;
- Bit 7: Bus-powered, 6: Self-powered,
- Bit 5 Remote-wakeup, 4..0: resvd */
- 0x00, /* __u8 MaxPower; */
-
- /* interface */
- 0x09, /* __u8 if_bLength; */
- 0x04, /* __u8 if_bDescriptorType; Interface */
- 0x00, /* __u8 if_bInterfaceNumber; */
- 0x00, /* __u8 if_bAlternateSetting; */
- 0x01, /* __u8 if_bNumEndpoints; */
- 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */
- 0x00, /* __u8 if_bInterfaceSubClass; */
- 0x00, /* __u8 if_bInterfaceProtocol; */
- 0x00, /* __u8 if_iInterface; */
-
- /* endpoint */
- 0x07, /* __u8 ep_bLength; */
- 0x05, /* __u8 ep_bDescriptorType; Endpoint */
- 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */
- 0x03, /* __u8 ep_bmAttributes; Interrupt */
- 0x08, /* __u16 ep_wMaxPacketSize; 8 Bytes */
- 0x00,
- 0xff /* __u8 ep_bInterval; 255 ms */
-};
-
-static __u8 root_hub_hub_des[] =
-{
- 0x09, /* __u8 bLength; */
- 0x29, /* __u8 bDescriptorType; Hub-descriptor */
- 0x02, /* __u8 bNbrPorts; */
- 0x00, /* __u16 wHubCharacteristics; */
- 0x00,
- 0x01, /* __u8 bPwrOn2pwrGood; 2ms */
- 0x00, /* __u8 bHubContrCurrent; 0 mA */
- 0x00, /* __u8 DeviceRemovable; *** 7 Ports max *** */
- 0xff /* __u8 PortPwrCtrlMask; *** 7 ports max *** */
-};
-
-/* prepare Interrupt pipe transaction data; HUB INTERRUPT ENDPOINT */
-static int rh_send_irq(struct urb *urb)
-{
- struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
- xhci_port_t *ports = xhci->rh.ports;
- unsigned long flags;
- int i, len = 1;
- __u16 data = 0;
-
- spin_lock_irqsave(&urb->lock, flags);
- for (i = 0; i < xhci->rh.numports; i++) {
- /* Set a bit if anything at all has changed on the port, as per
- * USB spec 11.12 */
- data |= (ports[i].cs_chg || ports[i].pe_chg )
- ? (1 << (i + 1))
- : 0;
-
- len = (i + 1) / 8 + 1;
- }
-
- *(__u16 *) urb->transfer_buffer = cpu_to_le16(data);
- urb->actual_length = len;
- urbp->status = 0;
-
- spin_unlock_irqrestore(&urb->lock, flags);
-
- if ((data > 0) && (xhci->rh.send != 0)) {
- dbg("root-hub INT complete: data: %x", data);
- xhci_call_completion(urb);
- }
-
- return 0;
-}
-
-/* Virtual Root Hub INTs are polled by this timer every "interval" ms */
-static int rh_init_int_timer(struct urb *urb);
-
-static void rh_int_timer_do(unsigned long ptr)
-{
- struct urb *urb = (struct urb *)ptr;
- struct list_head list, *tmp, *head;
- unsigned long flags;
- int i;
-
- for ( i = 0; i < xhci->rh.numports; i++)
- xhci_queue_probe(i);
-
- if (xhci->rh.send)
- rh_send_irq(urb);
-
- INIT_LIST_HEAD(&list);
-
- spin_lock_irqsave(&xhci->urb_list_lock, flags);
- head = &xhci->urb_list;
- tmp = head->next;
- while (tmp != head) {
- struct urb *u = list_entry(tmp, struct urb, urb_list);
- struct urb_priv *up = (struct urb_priv *)u->hcpriv;
-
- tmp = tmp->next;
-
- spin_lock(&u->lock);
-
- /* Check if the URB timed out */
- if (u->timeout && time_after_eq(jiffies,
- up->inserttime + u->timeout)) {
- list_del(&u->urb_list);
- list_add_tail(&u->urb_list, &list);
- }
-
- spin_unlock(&u->lock);
- }
- spin_unlock_irqrestore(&xhci->urb_list_lock, flags);
-
- head = &list;
- tmp = head->next;
- while (tmp != head) {
- struct urb *u = list_entry(tmp, struct urb, urb_list);
-
- tmp = tmp->next;
-
- u->transfer_flags |= USB_ASYNC_UNLINK | USB_TIMEOUT_KILLED;
- xhci_unlink_urb(u);
- }
-
- rh_init_int_timer(urb);
-}
-
-/* Root Hub INTs are polled by this timer */
-static int rh_init_int_timer(struct urb *urb)
-{
- xhci->rh.interval = urb->interval;
- init_timer(&xhci->rh.rh_int_timer);
- xhci->rh.rh_int_timer.function = rh_int_timer_do;
- xhci->rh.rh_int_timer.data = (unsigned long)urb;
- xhci->rh.rh_int_timer.expires = jiffies
- + (HZ * (urb->interval < 30 ? 30 : urb->interval)) / 1000;
- add_timer(&xhci->rh.rh_int_timer);
-
- return 0;
-}
-
-#define OK(x) len = (x); break
-
-/* Root Hub Control Pipe */
-static int rh_submit_urb(struct urb *urb)
-{
- unsigned int pipe = urb->pipe;
- struct usb_ctrlrequest *cmd =
- (struct usb_ctrlrequest *)urb->setup_packet;
- void *data = urb->transfer_buffer;
- int leni = urb->transfer_buffer_length;
- int len = 0;
- xhci_port_t *status;
- int stat = 0;
- int i;
- int retstatus;
- unsigned long flags;
-
- __u16 cstatus;
- __u16 bmRType_bReq;
- __u16 wValue;
- __u16 wIndex;
- __u16 wLength;
-
- if (usb_pipetype(pipe) == PIPE_INTERRUPT) {
- xhci->rh.urb = urb;
- xhci->rh.send = 1;
- xhci->rh.interval = urb->interval;
- rh_init_int_timer(urb);
-
- return -EINPROGRESS;
- }
-
- bmRType_bReq = cmd->bRequestType | cmd->bRequest << 8;
- wValue = le16_to_cpu(cmd->wValue);
- wIndex = le16_to_cpu(cmd->wIndex);
- wLength = le16_to_cpu(cmd->wLength);
-
- for (i = 0; i < 8; i++)
- xhci->rh.c_p_r[i] = 0;
-
- status = &xhci->rh.ports[wIndex - 1];
-
- spin_lock_irqsave(&xhci->rh.port_state_lock, flags);
-
- switch (bmRType_bReq) {
- /* Request Destination:
- without flags: Device,
- RH_INTERFACE: interface,
- RH_ENDPOINT: endpoint,
- RH_CLASS means HUB here,
- RH_OTHER | RH_CLASS almost ever means HUB_PORT here
- */
-
- case RH_GET_STATUS:
- *(__u16 *)data = cpu_to_le16(1);
- OK(2);
- case RH_GET_STATUS | RH_INTERFACE:
- *(__u16 *)data = cpu_to_le16(0);
- OK(2);
- case RH_GET_STATUS | RH_ENDPOINT:
- *(__u16 *)data = cpu_to_le16(0);
- OK(2);
- case RH_GET_STATUS | RH_CLASS:
- *(__u32 *)data = cpu_to_le32(0);
- OK(4); /* hub power */
- case RH_GET_STATUS | RH_OTHER | RH_CLASS:
- cstatus = (status->cs_chg) |
- (status->pe_chg << 1) |
- (xhci->rh.c_p_r[wIndex - 1] << 4);
- retstatus = (status->cs) |
- (status->pe << 1) |
- (status->susp << 2) |
- (1 << 8) | /* power on */
- (status->lsda << 9);
- *(__u16 *)data = cpu_to_le16(retstatus);
- *(__u16 *)(data + 2) = cpu_to_le16(cstatus);
- OK(4);
- case RH_CLEAR_FEATURE | RH_ENDPOINT:
- switch (wValue) {
- case RH_ENDPOINT_STALL:
- OK(0);
- }
- break;
- case RH_CLEAR_FEATURE | RH_CLASS:
- switch (wValue) {
- case RH_C_HUB_OVER_CURRENT:
- OK(0); /* hub power over current */
- }
- break;
- case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
- switch (wValue) {
- case RH_PORT_ENABLE:
- status->pe = 0;
- OK(0);
- case RH_PORT_SUSPEND:
- status->susp = 0;
- OK(0);
- case RH_PORT_POWER:
- OK(0); /* port power */
- case RH_C_PORT_CONNECTION:
- status->cs_chg = 0;
- OK(0);
- case RH_C_PORT_ENABLE:
- status->pe_chg = 0;
- OK(0);
- case RH_C_PORT_SUSPEND:
- /*** WR_RH_PORTSTAT(RH_PS_PSSC); */
- OK(0);
- case RH_C_PORT_OVER_CURRENT:
- OK(0); /* port power over current */
- case RH_C_PORT_RESET:
- xhci->rh.c_p_r[wIndex - 1] = 0;
- OK(0);
- }
- break;
- case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
- switch (wValue) {
- case RH_PORT_SUSPEND:
- status->susp = 1;
- OK(0);
- case RH_PORT_RESET:
- {
- int ret;
- xhci->rh.c_p_r[wIndex - 1] = 1;
- status->pr = 0;
- status->pe = 1;
- ret = xhci_port_reset(wIndex - 1);
- /* XXX MAW: should probably cancel queued transfers during reset... *\/ */
- if ( ret == 0 ) { OK(0); }
- else { return ret; }
- }
- break;
- case RH_PORT_POWER:
- OK(0); /* port power ** */
- case RH_PORT_ENABLE:
- status->pe = 1;
- OK(0);
- }
- break;
- case RH_SET_ADDRESS:
- xhci->rh.devnum = wValue;
- OK(0);
- case RH_GET_DESCRIPTOR:
- switch ((wValue & 0xff00) >> 8) {
- case 0x01: /* device descriptor */
- len = min_t(unsigned int, leni,
- min_t(unsigned int,
- sizeof(root_hub_dev_des), wLength));
- memcpy(data, root_hub_dev_des, len);
- OK(len);
- case 0x02: /* configuration descriptor */
- len = min_t(unsigned int, leni,
- min_t(unsigned int,
- sizeof(root_hub_config_des), wLength));
- memcpy (data, root_hub_config_des, len);
- OK(len);
- case 0x03: /* string descriptors */
- len = usb_root_hub_string (wValue & 0xff,
- 0, "XHCI-alt",
- data, wLength);
- if (len > 0) {
- OK(min_t(int, leni, len));
- } else
- stat = -EPIPE;
- }
- break;
- case RH_GET_DESCRIPTOR | RH_CLASS:
- root_hub_hub_des[2] = xhci->rh.numports;
- len = min_t(unsigned int, leni,
- min_t(unsigned int, sizeof(root_hub_hub_des), wLength));
- memcpy(data, root_hub_hub_des, len);
- OK(len);
- case RH_GET_CONFIGURATION:
- *(__u8 *)data = 0x01;
- OK(1);
- case RH_SET_CONFIGURATION:
- OK(0);
- case RH_GET_INTERFACE | RH_INTERFACE:
- *(__u8 *)data = 0x00;
- OK(1);
- case RH_SET_INTERFACE | RH_INTERFACE:
- OK(0);
- default:
- stat = -EPIPE;
- }
-
- spin_unlock_irqrestore(&xhci->rh.port_state_lock, flags);
-
- urb->actual_length = len;
-
- return stat;
-}
-
-/*
- * MUST be called with urb->lock acquired
- */
-static int rh_unlink_urb(struct urb *urb)
-{
- if (xhci->rh.urb == urb) {
- urb->status = -ENOENT;
- xhci->rh.send = 0;
- xhci->rh.urb = NULL;
- del_timer(&xhci->rh.rh_int_timer);
- }
- return 0;
-}
-
-/******************************************************************************
- * CONTROL PLANE FUNCTIONALITY
- */
-
-/**
- * alloc_xhci - initialise a new virtual root hub for a new USB device channel
- */
-static int alloc_xhci(void)
-{
- int retval;
- struct usb_bus *bus;
-
- retval = -EBUSY;
-
- xhci = kmalloc(sizeof(*xhci), GFP_KERNEL);
- if (!xhci) {
- err("couldn't allocate xhci structure");
- retval = -ENOMEM;
- goto err_alloc_xhci;
- }
-
- xhci->state = USBIF_STATE_CLOSED;
-
- spin_lock_init(&xhci->urb_list_lock);
- INIT_LIST_HEAD(&xhci->urb_list);
-
- spin_lock_init(&xhci->complete_list_lock);
- INIT_LIST_HEAD(&xhci->complete_list);
-
- spin_lock_init(&xhci->frame_list_lock);
-
- bus = usb_alloc_bus(&xhci_device_operations);
-
- if (!bus) {
- err("unable to allocate bus");
- goto err_alloc_bus;
- }
-
- xhci->bus = bus;
- bus->bus_name = "XHCI";
- bus->hcpriv = xhci;
-
- usb_register_bus(xhci->bus);
-
- /* Initialize the root hub */
-
- xhci->rh.numports = 0;
-
- xhci->bus->root_hub = xhci->rh.dev = usb_alloc_dev(NULL, xhci->bus);
- if (!xhci->rh.dev) {
- err("unable to allocate root hub");
- goto err_alloc_root_hub;
- }
-
- xhci->state = 0;
-
- return 0;
-
-/*
- * error exits:
- */
-err_alloc_root_hub:
- usb_deregister_bus(xhci->bus);
- usb_free_bus(xhci->bus);
- xhci->bus = NULL;
-
-err_alloc_bus:
- kfree(xhci);
-
-err_alloc_xhci:
- return retval;
-}
-
-/**
- * usbif_status_change - deal with an incoming USB_INTERFACE_STATUS_ message
- */
-static void usbif_status_change(usbif_fe_interface_status_changed_t *status)
-{
- ctrl_msg_t cmsg;
- usbif_fe_interface_connect_t up;
- long rc;
- usbif_sring_t *sring;
-
- switch ( status->status )
- {
- case USBIF_INTERFACE_STATUS_DESTROYED:
- printk(KERN_WARNING "Unexpected usbif-DESTROYED message in state %d\n",
- xhci->state);
- break;
-
- case USBIF_INTERFACE_STATUS_DISCONNECTED:
- if ( xhci->state != USBIF_STATE_CLOSED )
- {
- printk(KERN_WARNING "Unexpected usbif-DISCONNECTED message"
- " in state %d\n", xhci->state);
- break;
- /* Not bothering to do recovery here for now. Keep things
- * simple. */
-
- spin_lock_irq(&xhci->ring_lock);
-
- /* Clean up resources. */
- free_page((unsigned long)xhci->usb_ring.sring);
- unbind_evtchn_from_irqhandler(xhci->evtchn, xhci);
-
- /* Plug the ring. */
- xhci->recovery = 1;
- wmb();
-
- spin_unlock_irq(&xhci->ring_lock);
- }
-
- /* Move from CLOSED to DISCONNECTED state. */
- sring = (usbif_sring_t *)__get_free_page(GFP_KERNEL);
- SHARED_RING_INIT(sring);
- FRONT_RING_INIT(&xhci->usb_ring, sring, PAGE_SIZE);
- xhci->state = USBIF_STATE_DISCONNECTED;
-
- /* Construct an interface-CONNECT message for the domain controller. */
- cmsg.type = CMSG_USBIF_FE;
- cmsg.subtype = CMSG_USBIF_FE_INTERFACE_CONNECT;
- cmsg.length = sizeof(usbif_fe_interface_connect_t);
- up.shmem_frame = virt_to_mfn(sring);
- memcpy(cmsg.msg, &up, sizeof(up));
-
- /* Tell the controller to bring up the interface. */
- ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
- break;
-
- case USBIF_INTERFACE_STATUS_CONNECTED:
- if ( xhci->state == USBIF_STATE_CLOSED )
- {
- printk(KERN_WARNING "Unexpected usbif-CONNECTED message"
- " in state %d\n", xhci->state);
- break;
- }
-
- xhci->evtchn = status->evtchn;
- xhci->bandwidth = status->bandwidth;
- xhci->rh.numports = status->num_ports;
-
- xhci->rh.ports = kmalloc (sizeof(xhci_port_t) * xhci->rh.numports, GFP_KERNEL);
-
- if ( xhci->rh.ports == NULL )
- goto alloc_ports_nomem;
-
- memset(xhci->rh.ports, 0, sizeof(xhci_port_t) * xhci->rh.numports);
-
- usb_connect(xhci->rh.dev);
-
- if (usb_new_device(xhci->rh.dev) != 0) {
- err("unable to start root hub");
- }
-
- /* Allocate the appropriate USB bandwidth here... Need to
- * somehow know what the total available is thought to be so we
- * can calculate the reservation correctly. */
- usb_claim_bandwidth(xhci->rh.dev, xhci->rh.urb,
- 1000 - xhci->bandwidth, 0);
-
- if ( (rc = bind_evtchn_to_irqhandler(xhci->evtchn, xhci_interrupt,
- SA_SAMPLE_RANDOM, "usbif", xhci)) )
- printk(KERN_ALERT"usbfront request_irq failed (%ld)\n",rc);
-
- DPRINTK(KERN_INFO __FILE__
- ": USB XHCI: SHM at %p (0x%lx), EVTCHN %d\n",
- xhci->usb_ring.sring, virt_to_mfn(xhci->usbif),
- xhci->evtchn);
-
- xhci->state = USBIF_STATE_CONNECTED;
-
- break;
-
- default:
- printk(KERN_WARNING "Status change to unknown value %d\n",
- status->status);
- break;
- }
-
- return;
-
- alloc_ports_nomem:
- printk(KERN_WARNING "Failed to allocate port memory, XHCI failed to connect.\n");
- return;
-}
-
-/**
- * usbif_ctrlif_rx - demux control messages by subtype
- */
-static void usbif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id)
-{
- switch ( msg->subtype )
- {
- case CMSG_USBIF_FE_INTERFACE_STATUS_CHANGED:
- usbif_status_change((usbif_fe_interface_status_changed_t *)
- &msg->msg[0]);
- break;
-
- /* New interface...? */
- default:
- msg->length = 0;
- break;
- }
-
- ctrl_if_send_response(msg);
-}
-
-static void send_driver_up(void)
-{
- control_msg_t cmsg;
- usbif_fe_interface_status_changed_t st;
-
- /* Send a driver-UP notification to the domain controller. */
- cmsg.type = CMSG_USBIF_FE;
- cmsg.subtype = CMSG_USBIF_FE_DRIVER_STATUS_CHANGED;
- cmsg.length = sizeof(usbif_fe_driver_status_changed_t);
- st.status = USBIF_DRIVER_STATUS_UP;
- memcpy(cmsg.msg, &st, sizeof(st));
- ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
-}
-
-void usbif_resume(void)
-{
- int i;
-
- /* Fake disconnection on all virtual USB ports (suspending / migrating
- * will destroy hard state associated will the USB devices anyhow). */
- /* No need to lock here. */
- for ( i = 0; i < xhci->rh.numports; i++ )
- {
- xhci->rh.ports[i].cs = 0;
- xhci->rh.ports[i].cs_chg = 1;
- xhci->rh.ports[i].pe = 0;
- }
-
- send_driver_up();
-}
-
-static int __init xhci_hcd_init(void)
-{
- int retval = -ENOMEM, i;
-
- if ( (xen_start_info->flags & SIF_INITDOMAIN) ||
- (xen_start_info->flags & SIF_USB_BE_DOMAIN) )
- return 0;
-
- info(DRIVER_DESC " " DRIVER_VERSION);
-
- if (debug) {
- errbuf = kmalloc(ERRBUF_LEN, GFP_KERNEL);
- if (!errbuf)
- goto errbuf_failed;
- }
-
- xhci_up_cachep = kmem_cache_create("xhci_urb_priv",
- sizeof(struct urb_priv), 0, 0, NULL, NULL);
- if (!xhci_up_cachep)
- goto up_failed;
-
- /* Let the domain controller know we're here. For now we wait until
- * connection, as for the block and net drivers. This is only strictly
- * necessary if we're going to boot off a USB device. */
- printk(KERN_INFO "Initialising Xen virtual USB hub\n");
-
- (void)ctrl_if_register_receiver(CMSG_USBIF_FE, usbif_ctrlif_rx,
- CALLBACK_IN_BLOCKING_CONTEXT);
-
- alloc_xhci();
-
- send_driver_up();
-
- /*
- * We should read 'nr_interfaces' from response message and wait
- * for notifications before proceeding. For now we assume that we
- * will be notified of exactly one interface.
- */
- for ( i=0; (xhci->state != USBIF_STATE_CONNECTED) && (i < 10*HZ); i++ )
- {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
-
- if (xhci->state != USBIF_STATE_CONNECTED)
- printk(KERN_WARNING "Timeout connecting USB frontend driver!\n");
-
- return 0;
-
-up_failed:
- if (errbuf)
- kfree(errbuf);
-
-errbuf_failed:
- return retval;
-}
-
-module_init(xhci_hcd_init);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
-
diff -r eba5afe9aa37 -r 10759a44ce3b linux-2.6-xen-sparse/drivers/xen/usbfront/xhci.h
--- a/linux-2.6-xen-sparse/drivers/xen/usbfront/xhci.h Thu Sep 22 15:05:44 2005
+++ /dev/null Thu Sep 22 15:12:14 2005
@@ -1,182 +0,0 @@
-/******************************************************************************
- * xhci.h
- *
- * Private definitions for the Xen Virtual USB Controller. Based on
- * drivers/usb/host/uhci.h from Linux. Copyright for the imported content is
- * retained by the original authors.
- *
- * Modifications are:
- * Copyright (C) 2004 Intel Research Cambridge
- * Copyright (C) 2004, 2005 Mark Williamson
- */
-
-#ifndef __LINUX_XHCI_H
-#define __LINUX_XHCI_H
-
-#include <linux/list.h>
-#include <linux/usb.h>
-#include <asm-xen/xen-public/io/usbif.h>
-#include <linux/spinlock.h>
-
-/* xhci_port_t - current known state of a virtual hub ports */
-typedef struct {
- unsigned int cs :1; /* Connection status. */
- unsigned int cs_chg :1; /* Connection status change. */
- unsigned int pe :1; /* Port enable. */
- unsigned int pe_chg :1; /* Port enable change. */
- unsigned int susp :1; /* Suspended. */
- unsigned int lsda :1; /* Low speed device attached. */
- unsigned int pr :1; /* Port reset. */
-} xhci_port_t;
-
-/* struct virt_root_hub - state related to the virtual root hub */
-struct virt_root_hub {
- struct usb_device *dev;
- int devnum; /* Address of Root Hub endpoint */
- struct urb *urb;
- void *int_addr;
- int send;
- int interval;
- int numports;
- int c_p_r[8];
- struct timer_list rh_int_timer;
- spinlock_t port_state_lock;
- xhci_port_t *ports;
-};
-
-/* struct xhci - contains the state associated with a single USB interface */
-struct xhci {
-
-#ifdef CONFIG_PROC_FS
- /* procfs */
- int num;
- struct proc_dir_entry *proc_entry;
-#endif
-
- int evtchn; /* Interdom channel to backend */
- enum {
- USBIF_STATE_CONNECTED = 2,
- USBIF_STATE_DISCONNECTED = 1,
- USBIF_STATE_CLOSED = 0
- } state; /* State of this USB interface */
- unsigned long recovery; /* boolean recovery in progress flag */
-
- unsigned long bandwidth;
-
- struct usb_bus *bus;
-
- /* Main list of URB's currently controlled by this HC */
- spinlock_t urb_list_lock;
- struct list_head urb_list; /* P: xhci->urb_list_lock */
-
- /* List of URB's awaiting completion callback */
- spinlock_t complete_list_lock;
- struct list_head complete_list; /* P: xhci->complete_list_lock */
-
- struct virt_root_hub rh; /* private data of the virtual root hub */
-
- spinlock_t ring_lock;
- usbif_front_ring_t usb_ring;
-
- int awaiting_reset;
-};
-
-/* per-URB private data structure for the host controller */
-struct urb_priv {
- struct urb *urb;
- usbif_iso_t *schedule;
- struct usb_device *dev;
-
- int in_progress : 1; /* QH was queued (not linked in) */
- int short_control_packet : 1; /* If we get a short packet during */
- /* a control transfer, retrigger */
- /* the status phase */
-
- int status; /* Final status */
-
- unsigned long inserttime; /* In jiffies */
-
- struct list_head complete_list; /* P: xhci->complete_list_lock */
-};
-
-/*
- * Locking in xhci.c
- *
- * spinlocks are used extensively to protect the many lists and data
- * structures we have. It's not that pretty, but it's necessary. We
- * need to be done with all of the locks (except complete_list_lock) when
- * we call urb->complete. I've tried to make it simple enough so I don't
- * have to spend hours racking my brain trying to figure out if the
- * locking is safe.
- *
- * Here's the safe locking order to prevent deadlocks:
- *
- * #1 xhci->urb_list_lock
- * #2 urb->lock
- * #3 xhci->urb_remove_list_lock
- * #4 xhci->complete_list_lock
- *
- * If you're going to grab 2 or more locks at once, ALWAYS grab the lock
- * at the lowest level FIRST and NEVER grab locks at the same level at the
- * same time.
- *
- * So, if you need xhci->urb_list_lock, grab it before you grab urb->lock
- */
-
-/* -------------------------------------------------------------------------
- Virtual Root HUB
- ------------------------------------------------------------------------- */
-/* destination of request */
-#define RH_DEVICE 0x00
-#define RH_INTERFACE 0x01
-#define RH_ENDPOINT 0x02
-#define RH_OTHER 0x03
-
-#define RH_CLASS 0x20
-#define RH_VENDOR 0x40
-
-/* Requests: bRequest << 8 | bmRequestType */
-#define RH_GET_STATUS 0x0080
-#define RH_CLEAR_FEATURE 0x0100
-#define RH_SET_FEATURE 0x0300
-#define RH_SET_ADDRESS 0x0500
-#define RH_GET_DESCRIPTOR 0x0680
-#define RH_SET_DESCRIPTOR 0x0700
-#define RH_GET_CONFIGURATION 0x0880
-#define RH_SET_CONFIGURATION 0x0900
-#define RH_GET_STATE 0x0280
-#define RH_GET_INTERFACE 0x0A80
-#define RH_SET_INTERFACE 0x0B00
-#define RH_SYNC_FRAME 0x0C80
-/* Our Vendor Specific Request */
-#define RH_SET_EP 0x2000
-
-/* Hub port features */
-#define RH_PORT_CONNECTION 0x00
-#define RH_PORT_ENABLE 0x01
-#define RH_PORT_SUSPEND 0x02
-#define RH_PORT_OVER_CURRENT 0x03
-#define RH_PORT_RESET 0x04
-#define RH_PORT_POWER 0x08
-#define RH_PORT_LOW_SPEED 0x09
-#define RH_C_PORT_CONNECTION 0x10
-#define RH_C_PORT_ENABLE 0x11
-#define RH_C_PORT_SUSPEND 0x12
-#define RH_C_PORT_OVER_CURRENT 0x13
-#define RH_C_PORT_RESET 0x14
-
-/* Hub features */
-#define RH_C_HUB_LOCAL_POWER 0x00
-#define RH_C_HUB_OVER_CURRENT 0x01
-#define RH_DEVICE_REMOTE_WAKEUP 0x00
-#define RH_ENDPOINT_STALL 0x01
-
-/* Our Vendor Specific feature */
-#define RH_REMOVE_EP 0x00
-
-#define RH_ACK 0x01
-#define RH_REQ_ERR -1
-#define RH_NACK 0x00
-
-#endif
-

_______________________________________________
Xen-changelog mailing list
Xen-changelog@lists.xensource.com
http://lists.xensource.com/xen-changelog
Merged. [ In reply to ]
# HG changeset patch
# User emellor@ewan
# Node ID ad0270abc9b96b382360899b63efca92c1026fc9
# Parent ab1c362ba0d18d1ae1d02ce0370f7dfc0b913198
# Parent 7ff651a39cfcfc5237a7dcb49fd148198d48fd9d
Merged.

diff -r ab1c362ba0d1 -r ad0270abc9b9 tools/libxc/xg_private.h
--- a/tools/libxc/xg_private.h Fri Sep 23 15:56:46 2005
+++ b/tools/libxc/xg_private.h Fri Sep 23 15:57:13 2005
@@ -28,25 +28,27 @@
#define _PAGE_PSE 0x080
#define _PAGE_GLOBAL 0x100

+#define L1_PAGETABLE_SHIFT_PAE 12
+#define L2_PAGETABLE_SHIFT_PAE 21
+#define L3_PAGETABLE_SHIFT_PAE 30
+
#if defined(__i386__)
#define L1_PAGETABLE_SHIFT 12
#define L2_PAGETABLE_SHIFT 22
-#define L1_PAGETABLE_SHIFT_PAE 12
-#define L2_PAGETABLE_SHIFT_PAE 21
-#define L3_PAGETABLE_SHIFT_PAE 30
#elif defined(__x86_64__)
-#define L1_PAGETABLE_SHIFT 12
-#define L2_PAGETABLE_SHIFT 21
-#define L3_PAGETABLE_SHIFT 30
-#define L4_PAGETABLE_SHIFT 39
+#define L1_PAGETABLE_SHIFT 12
+#define L2_PAGETABLE_SHIFT 21
+#define L3_PAGETABLE_SHIFT 30
+#define L4_PAGETABLE_SHIFT 39
#endif

-#if defined(__i386__)
-#define ENTRIES_PER_L1_PAGETABLE 1024
-#define ENTRIES_PER_L2_PAGETABLE 1024
#define L1_PAGETABLE_ENTRIES_PAE 512
#define L2_PAGETABLE_ENTRIES_PAE 512
#define L3_PAGETABLE_ENTRIES_PAE 4
+
+#if defined(__i386__)
+#define L1_PAGETABLE_ENTRIES 1024
+#define L2_PAGETABLE_ENTRIES 1024
#elif defined(__x86_64__)
#define L1_PAGETABLE_ENTRIES 512
#define L2_PAGETABLE_ENTRIES 512
@@ -70,17 +72,18 @@
typedef unsigned long l4_pgentry_t;
#endif

-#if defined(__i386__)
-#define l1_table_offset(_a) \
- (((_a) >> L1_PAGETABLE_SHIFT) & (ENTRIES_PER_L1_PAGETABLE - 1))
-#define l2_table_offset(_a) \
- ((_a) >> L2_PAGETABLE_SHIFT)
#define l1_table_offset_pae(_a) \
(((_a) >> L1_PAGETABLE_SHIFT_PAE) & (L1_PAGETABLE_ENTRIES_PAE - 1))
#define l2_table_offset_pae(_a) \
(((_a) >> L2_PAGETABLE_SHIFT_PAE) & (L2_PAGETABLE_ENTRIES_PAE - 1))
#define l3_table_offset_pae(_a) \
(((_a) >> L3_PAGETABLE_SHIFT_PAE) & (L3_PAGETABLE_ENTRIES_PAE - 1))
+
+#if defined(__i386__)
+#define l1_table_offset(_a) \
+ (((_a) >> L1_PAGETABLE_SHIFT) & (L1_PAGETABLE_ENTRIES - 1))
+#define l2_table_offset(_a) \
+ ((_a) >> L2_PAGETABLE_SHIFT)
#elif defined(__x86_64__)
#define l1_table_offset(_a) \
(((_a) >> L1_PAGETABLE_SHIFT) & (L1_PAGETABLE_ENTRIES - 1))
diff -r ab1c362ba0d1 -r ad0270abc9b9 xen/arch/x86/mm.c
--- a/xen/arch/x86/mm.c Fri Sep 23 15:56:46 2005
+++ b/xen/arch/x86/mm.c Fri Sep 23 15:57:13 2005
@@ -2273,8 +2273,7 @@


int update_grant_pte_mapping(
- unsigned long pte_addr, l1_pgentry_t _nl1e,
- struct domain *d, struct vcpu *v)
+ unsigned long pte_addr, l1_pgentry_t _nl1e, struct vcpu *v)
{
int rc = GNTST_okay;
void *va;
@@ -2282,6 +2281,7 @@
struct pfn_info *page;
u32 type_info;
l1_pgentry_t ol1e;
+ struct domain *d = v->domain;

ASSERT(spin_is_locked(&d->big_lock));
ASSERT(!shadow_mode_refcounts(d));
@@ -2318,8 +2318,6 @@
}

put_page_from_l1e(ol1e, d);
-
- rc = (l1e_get_flags(ol1e) & _PAGE_PRESENT) ? GNTST_flush_all : GNTST_okay;

if ( unlikely(shadow_mode_enabled(d)) )
{
@@ -2415,10 +2413,10 @@


int update_grant_va_mapping(
- unsigned long va, l1_pgentry_t _nl1e, struct domain *d, struct vcpu *v)
-{
- int rc = GNTST_okay;
+ unsigned long va, l1_pgentry_t _nl1e, struct vcpu *v)
+{
l1_pgentry_t *pl1e, ol1e;
+ struct domain *d = v->domain;

ASSERT(spin_is_locked(&d->big_lock));
ASSERT(!shadow_mode_refcounts(d));
@@ -2439,12 +2437,10 @@

put_page_from_l1e(ol1e, d);

- rc = (l1e_get_flags(ol1e) & _PAGE_PRESENT) ? GNTST_flush_one : GNTST_okay;
-
if ( unlikely(shadow_mode_enabled(d)) )
shadow_do_update_va_mapping(va, _nl1e, v);

- return rc;
+ return GNTST_okay;
}

int clear_grant_va_mapping(unsigned long addr, unsigned long frame)
diff -r ab1c362ba0d1 -r ad0270abc9b9 xen/common/grant_table.c
--- a/xen/common/grant_table.c Fri Sep 23 15:56:46 2005
+++ b/xen/common/grant_table.c Fri Sep 23 15:57:13 2005
@@ -24,10 +24,6 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

-#define GRANT_DEBUG 0
-#define GRANT_DEBUG_VERBOSE 0
-
-#include <xen/config.h>
#include <xen/lib.h>
#include <xen/sched.h>
#include <xen/shadow.h>
@@ -68,39 +64,32 @@
t->map_count--;
}

+/*
+ * Returns 0 if TLB flush / invalidate required by caller.
+ * va will indicate the address to be invalidated.
+ *
+ * addr is _either_ a host virtual address, or the address of the pte to
+ * update, as indicated by the GNTMAP_contains_pte flag.
+ */
static int
-__gnttab_activate_grant_ref(
- struct domain *mapping_d, /* IN */
- struct vcpu *mapping_ed,
- struct domain *granting_d,
- grant_ref_t ref,
- u16 dev_hst_ro_flags,
- u64 addr,
- unsigned long *pframe ) /* OUT */
-{
- domid_t sdom;
- u16 sflags;
+__gnttab_map_grant_ref(
+ gnttab_map_grant_ref_t *uop)
+{
+ domid_t dom;
+ grant_ref_t ref;
+ struct domain *ld, *rd;
+ struct vcpu *led;
+ u16 dev_hst_ro_flags;
+ int handle;
+ u64 addr;
+ unsigned long frame = 0;
+ int rc;
active_grant_entry_t *act;
- grant_entry_t *sha;
- s16 rc = 1;
- unsigned long frame = 0;
- int retries = 0;
-
- /*
- * Objectives of this function:
- * . Make the record ( granting_d, ref ) active, if not already.
- * . Update shared grant entry of owner, indicating frame is mapped.
- * . Increment the owner act->pin reference counts.
- * . get_page on shared frame if new mapping.
- * . get_page_type if this is first RW mapping of frame.
- * . Add PTE to virtual address space of mapping_d, if necessary.
- * Returns:
- * . -ve: error
- * . 1: ok
- * . 0: ok and TLB invalidate of host_addr needed.
- *
- * On success, *pframe contains mfn.
- */
+
+ /* Entry details from @rd's shared grant table. */
+ grant_entry_t *sha;
+ domid_t sdom;
+ u16 sflags;

/*
* We bound the number of times we retry CMPXCHG on memory locations that
@@ -110,11 +99,88 @@
* the guest to race our updates (e.g., to change the GTF_readonly flag),
* so we allow a few retries before failing.
*/
-
- act = &granting_d->grant_table->active[ref];
- sha = &granting_d->grant_table->shared[ref];
-
- spin_lock(&granting_d->grant_table->lock);
+ int retries = 0;
+
+ led = current;
+ ld = led->domain;
+
+ /* Bitwise-OR avoids short-circuiting which screws control flow. */
+ if ( unlikely(__get_user(dom, &uop->dom) |
+ __get_user(ref, &uop->ref) |
+ __get_user(addr, &uop->host_addr) |
+ __get_user(dev_hst_ro_flags, &uop->flags)) )
+ {
+ DPRINTK("Fault while reading gnttab_map_grant_ref_t.\n");
+ return -EFAULT; /* don't set status */
+ }
+
+ if ( unlikely(ref >= NR_GRANT_ENTRIES) ||
+ unlikely((dev_hst_ro_flags &
+ (GNTMAP_device_map|GNTMAP_host_map)) == 0) )
+ {
+ DPRINTK("Bad ref (%d) or flags (%x).\n", ref, dev_hst_ro_flags);
+ (void)__put_user(GNTST_bad_gntref, &uop->handle);
+ return GNTST_bad_gntref;
+ }
+
+ if ( acm_pre_grant_map_ref(dom) )
+ {
+ (void)__put_user(GNTST_permission_denied, &uop->handle);
+ return GNTST_permission_denied;
+ }
+
+ if ( unlikely((rd = find_domain_by_id(dom)) == NULL) ||
+ unlikely(ld == rd) )
+ {
+ if ( rd != NULL )
+ put_domain(rd);
+ DPRINTK("Could not find domain %d\n", dom);
+ (void)__put_user(GNTST_bad_domain, &uop->handle);
+ return GNTST_bad_domain;
+ }
+
+ /* Get a maptrack handle. */
+ if ( unlikely((handle = get_maptrack_handle(ld->grant_table)) == -1) )
+ {
+ int i;
+ grant_mapping_t *new_mt;
+ grant_table_t *lgt = ld->grant_table;
+
+ if ( (lgt->maptrack_limit << 1) > MAPTRACK_MAX_ENTRIES )
+ {
+ put_domain(rd);
+ DPRINTK("Maptrack table is at maximum size.\n");
+ (void)__put_user(GNTST_no_device_space, &uop->handle);
+ return GNTST_no_device_space;
+ }
+
+ /* Grow the maptrack table. */
+ new_mt = alloc_xenheap_pages(lgt->maptrack_order + 1);
+ if ( new_mt == NULL )
+ {
+ put_domain(rd);
+ DPRINTK("No more map handles available.\n");
+ (void)__put_user(GNTST_no_device_space, &uop->handle);
+ return GNTST_no_device_space;
+ }
+
+ memcpy(new_mt, lgt->maptrack, PAGE_SIZE << lgt->maptrack_order);
+ for ( i = lgt->maptrack_limit; i < (lgt->maptrack_limit << 1); i++ )
+ new_mt[i].ref_and_flags = (i+1) << MAPTRACK_REF_SHIFT;
+
+ free_xenheap_pages(lgt->maptrack, lgt->maptrack_order);
+ lgt->maptrack = new_mt;
+ lgt->maptrack_order += 1;
+ lgt->maptrack_limit <<= 1;
+
+ DPRINTK("Doubled maptrack size\n");
+ handle = get_maptrack_handle(ld->grant_table);
+ }
+
+ act = &rd->grant_table->active[ref];
+ sha = &rd->grant_table->shared[ref];
+
+ spin_lock(&rd->grant_table->lock);

if ( act->pin == 0 )
{
@@ -132,10 +198,10 @@
u32 scombo, prev_scombo, new_scombo;

if ( unlikely((sflags & GTF_type_mask) != GTF_permit_access) ||
- unlikely(sdom != mapping_d->domain_id) )
+ unlikely(sdom != led->domain->domain_id) )
PIN_FAIL(unlock_out, GNTST_general_error,
"Bad flags (%x) or dom (%d). (NB. expected dom %d)\n",
- sflags, sdom, mapping_d->domain_id);
+ sflags, sdom, led->domain->domain_id);

/* Merge two 16-bit values into a 32-bit combined update. */
/* NB. Endianness! */
@@ -173,12 +239,12 @@

/* rmb(); */ /* not on x86 */

- frame = __gpfn_to_mfn_foreign(granting_d, sha->frame);
+ frame = __gpfn_to_mfn_foreign(rd, sha->frame);

if ( unlikely(!pfn_valid(frame)) ||
unlikely(!((dev_hst_ro_flags & GNTMAP_readonly) ?
- get_page(&frame_table[frame], granting_d) :
- get_page_and_type(&frame_table[frame], granting_d,
+ get_page(&frame_table[frame], rd) :
+ get_page_and_type(&frame_table[frame], rd,
PGT_writable_page))) )
{
clear_bit(_GTF_writing, &sha->flags);
@@ -208,10 +274,11 @@
PIN_FAIL(unlock_out, ENOSPC,
"Risk of counter overflow %08x\n", act->pin);

- frame = act->frame;
-
- if ( !(dev_hst_ro_flags & GNTMAP_readonly) &&
- !((sflags = sha->flags) & GTF_writing) )
+ sflags = sha->flags;
+ frame = act->frame;
+
+ if ( !(dev_hst_ro_flags & GNTMAP_readonly) &&
+ !(act->pin & (GNTPIN_hstw_mask|GNTPIN_devw_mask)) )
{
for ( ; ; )
{
@@ -264,9 +331,9 @@
* frame contains the mfn.
*/

- spin_unlock(&granting_d->grant_table->lock);
-
- if ( (addr != 0) && (dev_hst_ro_flags & GNTMAP_host_map) )
+ spin_unlock(&rd->grant_table->lock);
+
+ if ( dev_hst_ro_flags & GNTMAP_host_map )
{
/* Write update into the pagetable. */
l1_pgentry_t pte;
@@ -278,18 +345,15 @@
l1e_add_flags(pte,_PAGE_RW);

if ( dev_hst_ro_flags & GNTMAP_contains_pte )
- rc = update_grant_pte_mapping(addr, pte, mapping_d, mapping_ed);
+ rc = update_grant_pte_mapping(addr, pte, led);
else
- rc = update_grant_va_mapping(addr, pte, mapping_d, mapping_ed);
-
- /* IMPORTANT: rc indicates the degree of TLB flush that is required.
- * GNTST_flush_one (1) or GNTST_flush_all (2). This is done in the
- * outer gnttab_map_grant_ref. */
+ rc = update_grant_va_mapping(addr, pte, led);
+
if ( rc < 0 )
{
/* Failure: undo and abort. */

- spin_lock(&granting_d->grant_table->lock);
+ spin_lock(&rd->grant_table->lock);

if ( dev_hst_ro_flags & GNTMAP_readonly )
{
@@ -311,160 +375,27 @@
put_page(&frame_table[frame]);
}

- spin_unlock(&granting_d->grant_table->lock);
- }
-
- }
-
- *pframe = frame;
+ spin_unlock(&rd->grant_table->lock);
+ }
+
+ }
+
+ ld->grant_table->maptrack[handle].domid = dom;
+ ld->grant_table->maptrack[handle].ref_and_flags =
+ (ref << MAPTRACK_REF_SHIFT) |
+ (dev_hst_ro_flags & MAPTRACK_GNTMAP_MASK);
+
+ (void)__put_user((u64)frame << PAGE_SHIFT, &uop->dev_bus_addr);
+ (void)__put_user(handle, &uop->handle);
+
+ put_domain(rd);
return rc;

+
unlock_out:
- spin_unlock(&granting_d->grant_table->lock);
- return rc;
-}
-
-/*
- * Returns 0 if TLB flush / invalidate required by caller.
- * va will indicate the address to be invalidated.
- *
- * addr is _either_ a host virtual address, or the address of the pte to
- * update, as indicated by the GNTMAP_contains_pte flag.
- */
-static int
-__gnttab_map_grant_ref(
- gnttab_map_grant_ref_t *uop,
- unsigned long *va)
-{
- domid_t dom;
- grant_ref_t ref;
- struct domain *ld, *rd;
- struct vcpu *led;
- u16 dev_hst_ro_flags;
- int handle;
- u64 addr;
- unsigned long frame = 0;
- int rc;
-
- led = current;
- ld = led->domain;
-
- /* Bitwise-OR avoids short-circuiting which screws control flow. */
- if ( unlikely(__get_user(dom, &uop->dom) |
- __get_user(ref, &uop->ref) |
- __get_user(addr, &uop->host_addr) |
- __get_user(dev_hst_ro_flags, &uop->flags)) )
- {
- DPRINTK("Fault while reading gnttab_map_grant_ref_t.\n");
- return -EFAULT; /* don't set status */
- }
-
- if ( (dev_hst_ro_flags & GNTMAP_host_map) &&
- ( (addr == 0) ||
- (!(dev_hst_ro_flags & GNTMAP_contains_pte) &&
- unlikely(!__addr_ok(addr))) ) )
- {
- DPRINTK("Bad virtual address (%"PRIx64") or flags (%"PRIx16").\n",
- addr, dev_hst_ro_flags);
- (void)__put_user(GNTST_bad_virt_addr, &uop->handle);
- return GNTST_bad_gntref;
- }
-
- if ( unlikely(ref >= NR_GRANT_ENTRIES) ||
- unlikely((dev_hst_ro_flags &
- (GNTMAP_device_map|GNTMAP_host_map)) == 0) )
- {
- DPRINTK("Bad ref (%d) or flags (%x).\n", ref, dev_hst_ro_flags);
- (void)__put_user(GNTST_bad_gntref, &uop->handle);
- return GNTST_bad_gntref;
- }
-
- if (acm_pre_grant_map_ref(dom)) {
- (void)__put_user(GNTST_permission_denied, &uop->handle);
- return GNTST_permission_denied;
- }
-
- if ( unlikely((rd = find_domain_by_id(dom)) == NULL) ||
- unlikely(ld == rd) )
- {
- if ( rd != NULL )
- put_domain(rd);
- DPRINTK("Could not find domain %d\n", dom);
- (void)__put_user(GNTST_bad_domain, &uop->handle);
- return GNTST_bad_domain;
- }
-
- /* Get a maptrack handle. */
- if ( unlikely((handle = get_maptrack_handle(ld->grant_table)) == -1) )
- {
- int i;
- grant_mapping_t *new_mt;
- grant_table_t *lgt = ld->grant_table;
-
- if ( (lgt->maptrack_limit << 1) > MAPTRACK_MAX_ENTRIES )
- {
- put_domain(rd);
- DPRINTK("Maptrack table is at maximum size.\n");
- (void)__put_user(GNTST_no_device_space, &uop->handle);
- return GNTST_no_device_space;
- }
-
- /* Grow the maptrack table. */
- new_mt = alloc_xenheap_pages(lgt->maptrack_order + 1);
- if ( new_mt == NULL )
- {
- put_domain(rd);
- DPRINTK("No more map handles available.\n");
- (void)__put_user(GNTST_no_device_space, &uop->handle);
- return GNTST_no_device_space;
- }
-
- memcpy(new_mt, lgt->maptrack, PAGE_SIZE << lgt->maptrack_order);
- for ( i = lgt->maptrack_limit; i < (lgt->maptrack_limit << 1); i++ )
- new_mt[i].ref_and_flags = (i+1) << MAPTRACK_REF_SHIFT;
-
- free_xenheap_pages(lgt->maptrack, lgt->maptrack_order);
- lgt->maptrack = new_mt;
- lgt->maptrack_order += 1;
- lgt->maptrack_limit <<= 1;
-
- DPRINTK("Doubled maptrack size\n");
- handle = get_maptrack_handle(ld->grant_table);
- }
-
-#if GRANT_DEBUG_VERBOSE
- DPRINTK("Mapping grant ref (%hu) for domain (%hu) with flags (%x)\n",
- ref, dom, dev_hst_ro_flags);
-#endif
-
- if ( (rc = __gnttab_activate_grant_ref(ld, led, rd, ref, dev_hst_ro_flags,
- addr, &frame)) >= 0 )
- {
- /*
- * Only make the maptrack live _after_ writing the pte, in case we
- * overwrite the same frame number, causing a maptrack walk to find it
- */
- ld->grant_table->maptrack[handle].domid = dom;
-
- ld->grant_table->maptrack[handle].ref_and_flags
- = (ref << MAPTRACK_REF_SHIFT) |
- (dev_hst_ro_flags & MAPTRACK_GNTMAP_MASK);
-
- (void)__put_user((u64)frame << PAGE_SHIFT, &uop->dev_bus_addr);
-
- if ( ( dev_hst_ro_flags & GNTMAP_host_map ) &&
- !( dev_hst_ro_flags & GNTMAP_contains_pte) )
- *va = addr;
-
- (void)__put_user(handle, &uop->handle);
- }
- else
- {
- (void)__put_user(rc, &uop->handle);
- put_maptrack_handle(ld->grant_table, handle);
- }
-
- put_domain(rd);
+ spin_unlock(&rd->grant_table->lock);
+ (void)__put_user(rc, &uop->handle);
+ put_maptrack_handle(ld->grant_table, handle);
return rc;
}

@@ -472,25 +403,17 @@
gnttab_map_grant_ref(
gnttab_map_grant_ref_t *uop, unsigned int count)
{
- int i, rc, flush = 0;
- unsigned long va = 0;
+ int i;

for ( i = 0; i < count; i++ )
- if ( (rc =__gnttab_map_grant_ref(&uop[i], &va)) >= 0 )
- flush += rc;
-
- if ( flush == 1 )
- flush_tlb_one_mask(current->domain->cpumask, va);
- else if ( flush != 0 )
- flush_tlb_mask(current->domain->cpumask);
+ (void)__gnttab_map_grant_ref(&uop[i]);

return 0;
}

static int
__gnttab_unmap_grant_ref(
- gnttab_unmap_grant_ref_t *uop,
- unsigned long *va)
+ gnttab_unmap_grant_ref_t *uop)
{
domid_t dom;
grant_ref_t ref;
@@ -500,7 +423,7 @@
grant_entry_t *sha;
grant_mapping_t *map;
u16 flags;
- s16 rc = 1;
+ s16 rc = 0;
u64 addr, dev_bus_addr;
unsigned long frame;

@@ -540,11 +463,6 @@
(void)__put_user(GNTST_bad_domain, &uop->status);
return GNTST_bad_domain;
}
-
-#if GRANT_DEBUG_VERBOSE
- DPRINTK("Unmapping grant ref (%hu) for domain (%hu) with handle (%hu)\n",
- ref, dom, handle);
-#endif

act = &rd->grant_table->active[ref];
sha = &rd->grant_table->shared[ref];
@@ -566,8 +484,6 @@

map->ref_and_flags &= ~GNTMAP_device_map;
(void)__put_user(0, &uop->dev_bus_addr);
-
- /* Frame is now unmapped for device access. */
}

if ( (addr != 0) &&
@@ -589,10 +505,6 @@

act->pin -= (flags & GNTMAP_readonly) ? GNTPIN_hstr_inc
: GNTPIN_hstw_inc;
-
- rc = 0;
- if ( !( flags & GNTMAP_contains_pte) )
- *va = addr;
}

if ( (map->ref_and_flags & (GNTMAP_device_map|GNTMAP_host_map)) == 0)
@@ -632,17 +544,12 @@
gnttab_unmap_grant_ref(
gnttab_unmap_grant_ref_t *uop, unsigned int count)
{
- int i, flush = 0;
- unsigned long va = 0;
+ int i;

for ( i = 0; i < count; i++ )
- if ( __gnttab_unmap_grant_ref(&uop[i], &va) == 0 )
- flush++;
-
- if ( flush == 1 )
- flush_tlb_one_mask(current->domain->cpumask, va);
- else if ( flush != 0 )
- flush_tlb_mask(current->domain->cpumask);
+ (void)__gnttab_unmap_grant_ref(&uop[i]);
+
+ flush_tlb_mask(current->domain->cpumask);

return 0;
}
@@ -703,9 +610,9 @@
return 0;
}

-#if GRANT_DEBUG
static int
-gnttab_dump_table(gnttab_dump_table_t *uop)
+gnttab_dump_table(
+ gnttab_dump_table_t *uop)
{
grant_table_t *gt;
gnttab_dump_table_t op;
@@ -716,6 +623,8 @@
grant_mapping_t *maptrack;
int i;

+ if ( !IS_PRIV(current->domain) )
+ return -EPERM;

if ( unlikely(copy_from_user(&op, uop, sizeof(op)) != 0) )
{
@@ -724,9 +633,7 @@
}

if ( op.dom == DOMID_SELF )
- {
op.dom = current->domain->domain_id;
- }

if ( unlikely((d = find_domain_by_id(op.dom)) == NULL) )
{
@@ -750,14 +657,11 @@

for ( i = 0; i < NR_GRANT_ENTRIES; i++ )
{
- sha_copy = gt->shared[i];
-
+ sha_copy = gt->shared[i];
if ( sha_copy.flags )
- {
DPRINTK("Grant: dom (%hu) SHARED (%d) flags:(%hx) "
"dom:(%hu) frame:(%x)\n",
op.dom, i, sha_copy.flags, sha_copy.domid, sha_copy.frame);
- }
}

spin_lock(&gt->lock);
@@ -765,28 +669,22 @@
for ( i = 0; i < NR_GRANT_ENTRIES; i++ )
{
act = &gt->active[i];
-
if ( act->pin )
- {
DPRINTK("Grant: dom (%hu) ACTIVE (%d) pin:(%x) "
"dom:(%hu) frame:(%lx)\n",
op.dom, i, act->pin, act->domid, act->frame);
- }
}

for ( i = 0; i < gt->maptrack_limit; i++ )
{
maptrack = &gt->maptrack[i];
-
if ( maptrack->ref_and_flags & MAPTRACK_GNTMAP_MASK )
- {
DPRINTK("Grant: dom (%hu) MAP (%d) ref:(%hu) flags:(%x) "
"dom:(%hu)\n",
op.dom, i,
maptrack->ref_and_flags >> MAPTRACK_REF_SHIFT,
maptrack->ref_and_flags & MAPTRACK_GNTMAP_MASK,
maptrack->domid);
- }
}

spin_unlock(&gt->lock);
@@ -794,10 +692,10 @@
put_domain(d);
return 0;
}
-#endif

static long
-gnttab_transfer(gnttab_transfer_t *uop, unsigned int count)
+gnttab_transfer(
+ gnttab_transfer_t *uop, unsigned int count)
{
struct domain *d = current->domain;
struct domain *e;
@@ -810,10 +708,7 @@
for ( i = 0; i < count; i++ )
{
gnttab_transfer_t *gop = &uop[i];
-#if GRANT_DEBUG
- printk("gnttab_transfer: i=%d mfn=%lx domid=%d gref=%08x\n",
- i, gop->mfn, gop->domid, gop->handle);
-#endif
+
page = &frame_table[gop->mfn];

if ( unlikely(IS_XEN_HEAP_FRAME(page)))
@@ -956,11 +851,9 @@
case GNTTABOP_setup_table:
rc = gnttab_setup_table((gnttab_setup_table_t *)uop, count);
break;
-#if GRANT_DEBUG
case GNTTABOP_dump_table:
rc = gnttab_dump_table((gnttab_dump_table_t *)uop);
break;
-#endif
case GNTTABOP_transfer:
if (unlikely(!array_access_ok(
uop, count, sizeof(gnttab_transfer_t))))
@@ -1001,12 +894,6 @@
int found = 0;

lgt = ld->grant_table;
-
-#if GRANT_DEBUG_VERBOSE
- if ( ld->domain_id != 0 )
- DPRINTK("Foreign unref rd(%d) ld(%d) frm(%lx) flgs(%x).\n",
- rd->domain_id, ld->domain_id, frame, readonly);
-#endif

/* Fast exit if we're not mapping anything using grant tables */
if ( lgt->map_count == 0 )
@@ -1098,11 +985,6 @@
int retries = 0;
unsigned long target_pfn;

-#if GRANT_DEBUG_VERBOSE
- DPRINTK("gnttab_prepare_for_transfer rd(%hu) ld(%hu) ref(%hu).\n",
- rd->domain_id, ld->domain_id, ref);
-#endif
-
if ( unlikely((rgt = rd->grant_table) == NULL) ||
unlikely(ref >= NR_GRANT_ENTRIES) )
{
diff -r ab1c362ba0d1 -r ad0270abc9b9 xen/include/asm-x86/mm.h
--- a/xen/include/asm-x86/mm.h Fri Sep 23 15:56:46 2005
+++ b/xen/include/asm-x86/mm.h Fri Sep 23 15:57:13 2005
@@ -380,11 +380,9 @@
* hold a reference to the page.
*/
int update_grant_va_mapping(
- unsigned long va, l1_pgentry_t _nl1e,
- struct domain *d, struct vcpu *v);
+ unsigned long va, l1_pgentry_t _nl1e, struct vcpu *v);
int update_grant_pte_mapping(
- unsigned long pte_addr, l1_pgentry_t _nl1e,
- struct domain *d, struct vcpu *v);
+ unsigned long pte_addr, l1_pgentry_t _nl1e, struct vcpu *v);
int clear_grant_va_mapping(unsigned long addr, unsigned long frame);
int clear_grant_pte_mapping(
unsigned long addr, unsigned long frame, struct domain *d);
diff -r ab1c362ba0d1 -r ad0270abc9b9 xen/include/xen/grant_table.h
--- a/xen/include/xen/grant_table.h Fri Sep 23 15:56:46 2005
+++ b/xen/include/xen/grant_table.h Fri Sep 23 15:57:13 2005
@@ -110,8 +110,4 @@
void
gnttab_release_dev_mappings(grant_table_t *gt);

-/* Extra GNTST_ values, for internal use only. */
-#define GNTST_flush_all (2) /* Success, need to flush entire TLB. */
-#define GNTST_flush_one (1) /* Success, need to flush a vaddr. */
-
#endif /* __XEN_GRANT_H__ */

_______________________________________________
Xen-changelog mailing list
Xen-changelog@lists.xensource.com
http://lists.xensource.com/xen-changelog
Merged. [ In reply to ]
# HG changeset patch
# User emellor@ewan
# Node ID 3eda5c985d67765cdcea79a36f92251923e7196a
# Parent 193022cb9cccceb6dda3bb2bdd7105703da60265
# Parent 7598dc3ed0cbf9edbe3f77ccf6d64970e865901b
Merged.


_______________________________________________
Xen-changelog mailing list
Xen-changelog@lists.xensource.com
http://lists.xensource.com/xen-changelog
Merged. [ In reply to ]
# HG changeset patch
# User emellor@ewan
# Node ID ea1373b5015d617ee7b2f2da792b3823a2a37ed1
# Parent 3eda5c985d67765cdcea79a36f92251923e7196a
Merged.


_______________________________________________
Xen-changelog mailing list
Xen-changelog@lists.xensource.com
http://lists.xensource.com/xen-changelog
Merged. [ In reply to ]
# HG changeset patch
# User emellor@ewan
# Node ID af12cff417fd31334ea34be491f5c7d90eef3c36
# Parent ea1373b5015d617ee7b2f2da792b3823a2a37ed1
Merged.


_______________________________________________
Xen-changelog mailing list
Xen-changelog@lists.xensource.com
http://lists.xensource.com/xen-changelog
Merged. [ In reply to ]
# HG changeset patch
# User emellor@ewan
# Node ID 07cc64b3bf86888c1d101ae898d00be1e437335b
# Parent af12cff417fd31334ea34be491f5c7d90eef3c36
Merged.

diff -r af12cff417fd -r 07cc64b3bf86 linux-2.6-xen-sparse/arch/xen/i386/mm/fault.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/mm/fault.c Wed Sep 28 14:02:42 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/mm/fault.c Wed Sep 28 14:03:00 2005
@@ -209,7 +209,10 @@
{
unsigned long *p, page;

- page = __pa(per_cpu(cur_pgd, smp_processor_id()));
+ preempt_disable();
+ page = __pa(per_cpu(cur_pgd, smp_processor_id()));
+ preempt_enable();
+
p = (unsigned long *)__va(page);
p += (address >> 30) * 2;
printk(KERN_ALERT "%08lx -> *pde = %08lx:%08lx\n", page, p[1], p[0]);
@@ -237,7 +240,12 @@
{
unsigned long page;

+ preempt_disable();
page = ((unsigned long *) per_cpu(cur_pgd, smp_processor_id()))
+ [address >> 22];
+ preempt_enable();
+
+ page = ((unsigned long *) per_cpu(cur_pgd, get_cpu()))
[address >> 22];
printk(KERN_ALERT "*pde = ma %08lx pa %08lx\n", page,
machine_to_phys(page));
@@ -567,7 +575,9 @@
pmd_t *pmd, *pmd_k;
pte_t *pte_k;

+ preempt_disable();
pgd = index + per_cpu(cur_pgd, smp_processor_id());
+ preempt_enable();
pgd_k = init_mm.pgd + index;

if (!pgd_present(*pgd_k))
diff -r af12cff417fd -r 07cc64b3bf86 linux-2.6-xen-sparse/arch/xen/x86_64/mm/fault.c
--- a/linux-2.6-xen-sparse/arch/xen/x86_64/mm/fault.c Wed Sep 28 14:02:42 2005
+++ b/linux-2.6-xen-sparse/arch/xen/x86_64/mm/fault.c Wed Sep 28 14:03:00 2005
@@ -149,7 +149,9 @@
pmd_t *pmd;
pte_t *pte;

+ preempt_disable();
pgd = (pgd_t *)per_cpu(cur_pgd, smp_processor_id());
+ preempt_enable();
pgd += pgd_index(address);

printk("PGD %lx ", pgd_val(*pgd));
@@ -252,7 +254,9 @@

/* On Xen the line below does not always work. Needs investigating! */
/*pgd = pgd_offset(current->mm ?: &init_mm, address);*/
+ preempt_disable();
pgd = (pgd_t *)per_cpu(cur_pgd, smp_processor_id());
+ preempt_enable();
pgd += pgd_index(address);

pgd_ref = pgd_offset_k(address);

_______________________________________________
Xen-changelog mailing list
Xen-changelog@lists.xensource.com
http://lists.xensource.com/xen-changelog
Merged. [ In reply to ]
# HG changeset patch
# User emellor@ewan
# Node ID d443f03f8be0f40af055543bf3c1ae46aac4d23e
# Parent 70d5bfbf23d4c7ba21b4029ad63471959f854b86
# Parent 9d047fb99e388fa48d50b22e58884a133051d260
Merged.

diff -r 70d5bfbf23d4 -r d443f03f8be0 linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.c
--- a/linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.c Sun Oct 2 17:22:22 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.c Sun Oct 2 17:24:41 2005
@@ -65,7 +65,8 @@
int xencons_ring_send(const char *data, unsigned len)
{
int sent = __xencons_ring_send(outring(), data, len);
- notify_remote_via_irq(xencons_irq);
+ /* Use evtchn: this is called early, before irq is set up. */
+ notify_remote_via_evtchn(xen_start_info->console_evtchn);
return sent;
}

diff -r 70d5bfbf23d4 -r d443f03f8be0 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c
--- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c Sun Oct 2 17:22:22 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c Sun Oct 2 17:24:41 2005
@@ -147,7 +147,7 @@
data += avail;
len -= avail;
update_output_chunk(out, avail);
- notify_remote_via_irq(xenbus_irq);
+ notify_remote_via_evtchn(xen_start_info->store_evtchn);
} while (len != 0);

return 0;
@@ -192,7 +192,7 @@
pr_debug("Finished read of %i bytes (%i to go)\n", avail, len);
/* If it was full, tell them we've taken some. */
if (was_full)
- notify_remote_via_irq(xenbus_irq);
+ notify_remote_via_evtchn(xen_start_info->store_evtchn);
}

/* If we left something, wake watch thread to deal with it. */

_______________________________________________
Xen-changelog mailing list
Xen-changelog@lists.xensource.com
http://lists.xensource.com/xen-changelog
Merged. [ In reply to ]
# HG changeset patch
# User emellor@ewan
# Node ID 96cc6aa196b6e079488fabcc2eef32c38f7ff890
# Parent 9c6b39746b78529441c4b65eee1cea3e733b2ec3
# Parent 549325dfa161a22263d5445f6f1ae28473b1f1e5
Merged.

diff -r 9c6b39746b78 -r 96cc6aa196b6 linux-2.6-xen-sparse/arch/xen/i386/kernel/setup.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/setup.c Tue Oct 4 10:14:50 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/setup.c Tue Oct 4 10:15:34 2005
@@ -365,6 +365,7 @@

/* Raw start-of-day parameters from the hypervisor. */
start_info_t *xen_start_info;
+EXPORT_SYMBOL(xen_start_info);

static void __init limit_regions(unsigned long long size)
{
diff -r 9c6b39746b78 -r 96cc6aa196b6 linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c
--- a/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c Tue Oct 4 10:14:50 2005
+++ b/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c Tue Oct 4 10:15:34 2005
@@ -629,6 +629,7 @@
if (VALID_EVTCHN(evtchn))
notify_remote_via_evtchn(evtchn);
}
+EXPORT_SYMBOL(notify_remote_via_irq);

void irq_resume(void)
{
diff -r 9c6b39746b78 -r 96cc6aa196b6 linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup.c
--- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup.c Tue Oct 4 10:14:50 2005
+++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup.c Tue Oct 4 10:15:34 2005
@@ -86,6 +86,7 @@

/* Raw start-of-day parameters from the hypervisor. */
start_info_t *xen_start_info;
+EXPORT_SYMBOL(xen_start_info);
#endif

/*

_______________________________________________
Xen-changelog mailing list
Xen-changelog@lists.xensource.com
http://lists.xensource.com/xen-changelog
Merged. [ In reply to ]
# HG changeset patch
# User emellor@ewan
# Node ID a746126c3bb121736c75b62bed34068da6a3b2c2
# Parent 488f8aaa402204240dd7eea6eae856d7bced2590
Merged.

Signed-off-by: Ewan Mellor <ewan@xensource.com>


_______________________________________________
Xen-changelog mailing list
Xen-changelog@lists.xensource.com
http://lists.xensource.com/xen-changelog
Merged. [ In reply to ]
# HG changeset patch
# User emellor@ewan
# Node ID b7d11c9b6be41a5303a3ca314d2499baff13ddd8
# Parent a746126c3bb121736c75b62bed34068da6a3b2c2
Merged.

Signed-off-by: Ewan Mellor <ewan@xensource.com>


_______________________________________________
Xen-changelog mailing list
Xen-changelog@lists.xensource.com
http://lists.xensource.com/xen-changelog
Merged. [ In reply to ]
# HG changeset patch
# User emellor@ewan
# Node ID 7b33b5e94cec59cc71f904717d2cde337612cdad
# Parent b7d11c9b6be41a5303a3ca314d2499baff13ddd8
Merged.

diff -r b7d11c9b6be4 -r 7b33b5e94cec linux-2.6-xen-sparse/include/asm-generic/pgtable.h
--- a/linux-2.6-xen-sparse/include/asm-generic/pgtable.h Tue Oct 4 10:30:51 2005
+++ /dev/null Tue Oct 4 10:31:31 2005
@@ -1,221 +0,0 @@
-#ifndef _ASM_GENERIC_PGTABLE_H
-#define _ASM_GENERIC_PGTABLE_H
-
-#ifndef __HAVE_ARCH_PTEP_ESTABLISH
-/*
- * Establish a new mapping:
- * - flush the old one
- * - update the page tables
- * - inform the TLB about the new one
- *
- * We hold the mm semaphore for reading and vma->vm_mm->page_table_lock.
- *
- * Note: the old pte is known to not be writable, so we don't need to
- * worry about dirty bits etc getting lost.
- */
-#ifndef __HAVE_ARCH_SET_PTE_ATOMIC
-#define ptep_establish(__vma, __address, __ptep, __entry) \
-do { \
- set_pte_at((__vma)->vm_mm, (__address), __ptep, __entry); \
- flush_tlb_page(__vma, __address); \
-} while (0)
-#else /* __HAVE_ARCH_SET_PTE_ATOMIC */
-#define ptep_establish(__vma, __address, __ptep, __entry) \
-do { \
- set_pte_atomic(__ptep, __entry); \
- flush_tlb_page(__vma, __address); \
-} while (0)
-#endif /* __HAVE_ARCH_SET_PTE_ATOMIC */
-#endif
-
-#ifndef __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
-/*
- * Largely same as above, but only sets the access flags (dirty,
- * accessed, and writable). Furthermore, we know it always gets set
- * to a "more permissive" setting, which allows most architectures
- * to optimize this.
- */
-#define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
-do { \
- set_pte_at((__vma)->vm_mm, (__address), __ptep, __entry); \
- flush_tlb_page(__vma, __address); \
-} while (0)
-#endif
-
-#ifndef __HAVE_ARCH_PTEP_ESTABLISH_NEW
-/*
- * Establish a mapping where none previously existed
- */
-#define ptep_establish_new(__vma, __address, __ptep, __entry) \
-do { \
- set_pte(__ptep, __entry); \
-} while (0)
-#endif
-
-#ifndef __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
-#define ptep_test_and_clear_young(__vma, __address, __ptep) \
-({ \
- pte_t __pte = *(__ptep); \
- int r = 1; \
- if (!pte_young(__pte)) \
- r = 0; \
- else \
- set_pte_at((__vma)->vm_mm, (__address), \
- (__ptep), pte_mkold(__pte)); \
- r; \
-})
-#endif
-
-#ifndef __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH
-#define ptep_clear_flush_young(__vma, __address, __ptep) \
-({ \
- int __young; \
- __young = ptep_test_and_clear_young(__vma, __address, __ptep); \
- if (__young) \
- flush_tlb_page(__vma, __address); \
- __young; \
-})
-#endif
-
-#ifndef __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
-#define ptep_test_and_clear_dirty(__vma, __address, __ptep) \
-({ \
- pte_t __pte = *__ptep; \
- int r = 1; \
- if (!pte_dirty(__pte)) \
- r = 0; \
- else \
- set_pte_at((__vma)->vm_mm, (__address), (__ptep), \
- pte_mkclean(__pte)); \
- r; \
-})
-#endif
-
-#ifndef __HAVE_ARCH_PTEP_CLEAR_DIRTY_FLUSH
-#define ptep_clear_flush_dirty(__vma, __address, __ptep) \
-({ \
- int __dirty; \
- __dirty = ptep_test_and_clear_dirty(__vma, __address, __ptep); \
- if (__dirty) \
- flush_tlb_page(__vma, __address); \
- __dirty; \
-})
-#endif
-
-#ifndef __HAVE_ARCH_PTEP_GET_AND_CLEAR
-#define ptep_get_and_clear(__mm, __address, __ptep) \
-({ \
- pte_t __pte = *(__ptep); \
- pte_clear((__mm), (__address), (__ptep)); \
- __pte; \
-})
-#endif
-
-#ifndef __HAVE_ARCH_PTEP_CLEAR_FLUSH
-#define ptep_clear_flush(__vma, __address, __ptep) \
-({ \
- pte_t __pte; \
- __pte = ptep_get_and_clear((__vma)->vm_mm, __address, __ptep); \
- flush_tlb_page(__vma, __address); \
- __pte; \
-})
-#endif
-
-#ifndef __HAVE_ARCH_PTEP_SET_WRPROTECT
-static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long address, pte_t *ptep)
-{
- pte_t old_pte = *ptep;
- set_pte_at(mm, address, ptep, pte_wrprotect(old_pte));
-}
-#endif
-
-#ifndef __HAVE_ARCH_PTE_SAME
-#define pte_same(A,B) (pte_val(A) == pte_val(B))
-#endif
-
-#ifndef __HAVE_ARCH_PAGE_TEST_AND_CLEAR_DIRTY
-#define page_test_and_clear_dirty(page) (0)
-#endif
-
-#ifndef __HAVE_ARCH_PAGE_TEST_AND_CLEAR_YOUNG
-#define page_test_and_clear_young(page) (0)
-#endif
-
-#ifndef __HAVE_ARCH_PGD_OFFSET_GATE
-#define pgd_offset_gate(mm, addr) pgd_offset(mm, addr)
-#endif
-
-#ifndef __HAVE_ARCH_LAZY_MMU_PROT_UPDATE
-#define lazy_mmu_prot_update(pte) do { } while (0)
-#endif
-
-/*
- * When walking page tables, get the address of the next boundary,
- * or the end address of the range if that comes earlier. Although no
- * vma end wraps to 0, rounded up __boundary may wrap to 0 throughout.
- */
-
-#define pgd_addr_end(addr, end) \
-({ unsigned long __boundary = ((addr) + PGDIR_SIZE) & PGDIR_MASK; \
- (__boundary - 1 < (end) - 1)? __boundary: (end); \
-})
-
-#ifndef pud_addr_end
-#define pud_addr_end(addr, end) \
-({ unsigned long __boundary = ((addr) + PUD_SIZE) & PUD_MASK; \
- (__boundary - 1 < (end) - 1)? __boundary: (end); \
-})
-#endif
-
-#ifndef pmd_addr_end
-#define pmd_addr_end(addr, end) \
-({ unsigned long __boundary = ((addr) + PMD_SIZE) & PMD_MASK; \
- (__boundary - 1 < (end) - 1)? __boundary: (end); \
-})
-#endif
-
-#ifndef __ASSEMBLY__
-/*
- * When walking page tables, we usually want to skip any p?d_none entries;
- * and any p?d_bad entries - reporting the error before resetting to none.
- * Do the tests inline, but report and clear the bad entry in mm/memory.c.
- */
-void pgd_clear_bad(pgd_t *);
-void pud_clear_bad(pud_t *);
-void pmd_clear_bad(pmd_t *);
-
-static inline int pgd_none_or_clear_bad(pgd_t *pgd)
-{
- if (pgd_none(*pgd))
- return 1;
- if (unlikely(pgd_bad(*pgd))) {
- pgd_clear_bad(pgd);
- return 1;
- }
- return 0;
-}
-
-static inline int pud_none_or_clear_bad(pud_t *pud)
-{
- if (pud_none(*pud))
- return 1;
- if (unlikely(pud_bad(*pud))) {
- pud_clear_bad(pud);
- return 1;
- }
- return 0;
-}
-
-static inline int pmd_none_or_clear_bad(pmd_t *pmd)
-{
- if (pmd_none(*pmd))
- return 1;
- if (unlikely(pmd_bad(*pmd))) {
- pmd_clear_bad(pmd);
- return 1;
- }
- return 0;
-}
-#endif /* !__ASSEMBLY__ */
-
-#endif /* _ASM_GENERIC_PGTABLE_H */

_______________________________________________
Xen-changelog mailing list
Xen-changelog@lists.xensource.com
http://lists.xensource.com/xen-changelog
Merged. [ In reply to ]
# HG changeset patch
# User emellor@ewan
# Node ID 83452b6cdcdb9a9c5e84f7b145b0358cc4f3aaef
# Parent 7b33b5e94cec59cc71f904717d2cde337612cdad
Merged.


_______________________________________________
Xen-changelog mailing list
Xen-changelog@lists.xensource.com
http://lists.xensource.com/xen-changelog
Merged. [ In reply to ]
# HG changeset patch
# User emellor@ewan
# Node ID ca6930f826825133792c9d9d3486b82345f9628a
# Parent 83452b6cdcdb9a9c5e84f7b145b0358cc4f3aaef
Merged.


_______________________________________________
Xen-changelog mailing list
Xen-changelog@lists.xensource.com
http://lists.xensource.com/xen-changelog
Merged. [ In reply to ]
# HG changeset patch
# User emellor@ewan
# Node ID ab729f38870a178d42f34ca00b445c429fbd102a
# Parent ca6930f826825133792c9d9d3486b82345f9628a
Merged.


_______________________________________________
Xen-changelog mailing list
Xen-changelog@lists.xensource.com
http://lists.xensource.com/xen-changelog
Merged. [ In reply to ]
# HG changeset patch
# User emellor@ewan
# Node ID 3075c005e694ee4cf62270ab5d62a2a90d99f901
# Parent ab729f38870a178d42f34ca00b445c429fbd102a
Merged.


_______________________________________________
Xen-changelog mailing list
Xen-changelog@lists.xensource.com
http://lists.xensource.com/xen-changelog
Merged. [ In reply to ]
# HG changeset patch
# User emellor@ewan
# Node ID 07b7411e385faa3c3ff320cb25528c6223767c7d
# Parent 3075c005e694ee4cf62270ab5d62a2a90d99f901
Merged.


_______________________________________________
Xen-changelog mailing list
Xen-changelog@lists.xensource.com
http://lists.xensource.com/xen-changelog
Merged. [ In reply to ]
# HG changeset patch
# User emellor@ewan
# Node ID f74f6df95ccd7ea66d4d5eb4084695bc09cea07d
# Parent 07b7411e385faa3c3ff320cb25528c6223767c7d
Merged.


_______________________________________________
Xen-changelog mailing list
Xen-changelog@lists.xensource.com
http://lists.xensource.com/xen-changelog
Merged. [ In reply to ]
# HG changeset patch
# User emellor@ewan
# Node ID 5a3d5f9ef44e6733e5f5098b378867ef681cb4ee
# Parent f74f6df95ccd7ea66d4d5eb4084695bc09cea07d
Merged.


_______________________________________________
Xen-changelog mailing list
Xen-changelog@lists.xensource.com
http://lists.xensource.com/xen-changelog
Merged. [ In reply to ]
# HG changeset patch
# User emellor@ewan
# Node ID bd37123974b293eafe307a36f1a9669c8ec2221b
# Parent 4ab4f023a6ce08999a4d64937b3206fef163c62c
# Parent ba0bbf9d29fffbef248beff9336be79f8f0ce45b
Merged.

diff -r 4ab4f023a6ce -r bd37123974b2 linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c
--- a/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c Thu Oct 6 10:11:16 2005
+++ b/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c Thu Oct 6 10:12:55 2005
@@ -180,14 +180,13 @@

int bind_virq_to_irq(int virq)
{
- evtchn_op_t op;
+ evtchn_op_t op = { .cmd = EVTCHNOP_bind_virq };
int evtchn, irq;
int cpu = smp_processor_id();

spin_lock(&irq_mapping_update_lock);

if ((irq = per_cpu(virq_to_irq, cpu)[virq]) == -1) {
- op.cmd = EVTCHNOP_bind_virq;
op.u.bind_virq.virq = virq;
op.u.bind_virq.vcpu = cpu;
BUG_ON(HYPERVISOR_event_channel_op(&op) != 0);
@@ -212,7 +211,7 @@

void unbind_virq_from_irq(int virq)
{
- evtchn_op_t op;
+ evtchn_op_t op = { .cmd = EVTCHNOP_close };
int cpu = smp_processor_id();
int irq = per_cpu(virq_to_irq, cpu)[virq];
int evtchn = irq_to_evtchn[irq];
@@ -220,7 +219,6 @@
spin_lock(&irq_mapping_update_lock);

if (--irq_bindcount[irq] == 0) {
- op.cmd = EVTCHNOP_close;
op.u.close.dom = DOMID_SELF;
op.u.close.port = evtchn;
BUG_ON(HYPERVISOR_event_channel_op(&op) != 0);
@@ -245,14 +243,13 @@

int bind_ipi_to_irq(int ipi)
{
- evtchn_op_t op;
+ evtchn_op_t op = { .cmd = EVTCHNOP_bind_ipi };
int evtchn, irq;
int cpu = smp_processor_id();

spin_lock(&irq_mapping_update_lock);

if ((evtchn = per_cpu(ipi_to_evtchn, cpu)[ipi]) == -1) {
- op.cmd = EVTCHNOP_bind_ipi;
op.u.bind_ipi.vcpu = cpu;
BUG_ON(HYPERVISOR_event_channel_op(&op) != 0);
evtchn = op.u.bind_ipi.port;
@@ -278,7 +275,7 @@

void unbind_ipi_from_irq(int ipi)
{
- evtchn_op_t op;
+ evtchn_op_t op = { .cmd = EVTCHNOP_close };
int cpu = smp_processor_id();
int evtchn = per_cpu(ipi_to_evtchn, cpu)[ipi];
int irq = evtchn_to_irq[evtchn];
@@ -286,7 +283,6 @@
spin_lock(&irq_mapping_update_lock);

if (--irq_bindcount[irq] == 0) {
- op.cmd = EVTCHNOP_close;
op.u.close.dom = DOMID_SELF;
op.u.close.port = evtchn;
BUG_ON(HYPERVISOR_event_channel_op(&op) != 0);
@@ -324,13 +320,12 @@

void unbind_evtchn_from_irq(unsigned int irq)
{
- evtchn_op_t op;
+ evtchn_op_t op = { .cmd = EVTCHNOP_close };
int evtchn = irq_to_evtchn[irq];

spin_lock(&irq_mapping_update_lock);

if ((--irq_bindcount[irq] == 0) && (evtchn != -1)) {
- op.cmd = EVTCHNOP_close;
op.u.close.dom = DOMID_SELF;
op.u.close.port = evtchn;
BUG_ON(HYPERVISOR_event_channel_op(&op) != 0);
@@ -378,7 +373,7 @@
/* Rebind an evtchn so that it gets delivered to a specific cpu */
static void rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
{
- evtchn_op_t op;
+ evtchn_op_t op = { .cmd = EVTCHNOP_bind_vcpu };
int evtchn;

spin_lock(&irq_mapping_update_lock);
@@ -389,7 +384,6 @@
}

/* Send future instances of this interrupt to other vcpu. */
- op.cmd = EVTCHNOP_bind_vcpu;
op.u.bind_vcpu.port = evtchn;
op.u.bind_vcpu.vcpu = tcpu;

@@ -518,10 +512,9 @@

static unsigned int startup_pirq(unsigned int irq)
{
- evtchn_op_t op;
+ evtchn_op_t op = { .cmd = EVTCHNOP_bind_pirq };
int evtchn;

- op.cmd = EVTCHNOP_bind_pirq;
op.u.bind_pirq.pirq = irq;
/* NB. We are happy to share unless we are probing. */
op.u.bind_pirq.flags = probing_irq(irq) ? 0 : BIND_PIRQ__WILL_SHARE;
@@ -547,7 +540,7 @@

static void shutdown_pirq(unsigned int irq)
{
- evtchn_op_t op;
+ evtchn_op_t op = { .cmd = EVTCHNOP_close };
int evtchn = irq_to_evtchn[irq];

if (!VALID_EVTCHN(evtchn))
@@ -555,7 +548,6 @@

mask_evtchn(evtchn);

- op.cmd = EVTCHNOP_close;
op.u.close.dom = DOMID_SELF;
op.u.close.port = evtchn;
BUG_ON(HYPERVISOR_event_channel_op(&op) != 0);
@@ -666,6 +658,7 @@
continue;

/* Get a new binding from Xen. */
+ memset(&op, 0, sizeof(op));
op.cmd = EVTCHNOP_bind_virq;
op.u.bind_virq.virq = virq;
op.u.bind_virq.vcpu = 0;
@@ -689,6 +682,7 @@
evtchn_to_irq[evtchn] = -1;

/* Get a new binding from Xen. */
+ memset(&op, 0, sizeof(op));
op.cmd = EVTCHNOP_bind_ipi;
op.u.bind_ipi.vcpu = 0;
BUG_ON(HYPERVISOR_event_channel_op(&op) != 0);
diff -r 4ab4f023a6ce -r bd37123974b2 linux-2.6-xen-sparse/drivers/xen/blkback/interface.c
--- a/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c Thu Oct 6 10:11:16 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c Thu Oct 6 10:12:55 2005
@@ -68,8 +68,13 @@
int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn)
{
blkif_sring_t *sring;
- evtchn_op_t op = { .cmd = EVTCHNOP_bind_interdomain };
int err;
+ evtchn_op_t op = {
+ .cmd = EVTCHNOP_bind_interdomain,
+ .u.bind_interdomain.dom1 = DOMID_SELF,
+ .u.bind_interdomain.dom2 = blkif->domid,
+ .u.bind_interdomain.port1 = 0,
+ .u.bind_interdomain.port2 = evtchn };

if ( (blkif->blk_ring_area = alloc_vm_area(PAGE_SIZE)) == NULL )
return -ENOMEM;
@@ -80,10 +85,6 @@
return err;
}

- op.u.bind_interdomain.dom1 = DOMID_SELF;
- op.u.bind_interdomain.dom2 = blkif->domid;
- op.u.bind_interdomain.port1 = 0;
- op.u.bind_interdomain.port2 = evtchn;
err = HYPERVISOR_event_channel_op(&op);
if (err) {
unmap_frontend_page(blkif);
diff -r 4ab4f023a6ce -r bd37123974b2 linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c
--- a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c Thu Oct 6 10:11:16 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c Thu Oct 6 10:12:55 2005
@@ -485,8 +485,11 @@
static int setup_blkring(struct xenbus_device *dev, struct blkfront_info *info)
{
blkif_sring_t *sring;
- evtchn_op_t op = { .cmd = EVTCHNOP_alloc_unbound };
int err;
+ evtchn_op_t op = {
+ .cmd = EVTCHNOP_alloc_unbound,
+ .u.alloc_unbound.dom = DOMID_SELF,
+ .u.alloc_unbound.remote_dom = info->backend_id };

info->ring_ref = GRANT_INVALID_REF;

@@ -508,7 +511,6 @@
}
info->ring_ref = err;

- op.u.alloc_unbound.dom = info->backend_id;
err = HYPERVISOR_event_channel_op(&op);
if (err) {
gnttab_end_foreign_access(info->ring_ref, 0);
@@ -518,7 +520,9 @@
xenbus_dev_error(dev, err, "allocating event channel");
return err;
}
+
blkif_connect(info, op.u.alloc_unbound.port);
+
return 0;
}

diff -r 4ab4f023a6ce -r bd37123974b2 linux-2.6-xen-sparse/drivers/xen/blktap/interface.c
--- a/linux-2.6-xen-sparse/drivers/xen/blktap/interface.c Thu Oct 6 10:11:16 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blktap/interface.c Thu Oct 6 10:12:55 2005
@@ -68,8 +68,13 @@
int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn)
{
blkif_sring_t *sring;
- evtchn_op_t op = { .cmd = EVTCHNOP_bind_interdomain };
int err;
+ evtchn_op_t op = {
+ .cmd = EVTCHNOP_bind_interdomain,
+ .u.bind_interdomain.dom1 = DOMID_SELF,
+ .u.bind_interdomain.dom2 = blkif->domid,
+ .u.bind_interdomain.port1 = 0,
+ .u.bind_interdomain.port2 = evtchn };

if ((blkif->blk_ring_area = alloc_vm_area(PAGE_SIZE)) == NULL)
return -ENOMEM;
@@ -80,10 +85,6 @@
return err;
}

- op.u.bind_interdomain.dom1 = DOMID_SELF;
- op.u.bind_interdomain.dom2 = blkif->domid;
- op.u.bind_interdomain.port1 = 0;
- op.u.bind_interdomain.port2 = evtchn;
err = HYPERVISOR_event_channel_op(&op);
if (err) {
unmap_frontend_page(blkif);
diff -r 4ab4f023a6ce -r bd37123974b2 linux-2.6-xen-sparse/drivers/xen/netback/interface.c
--- a/linux-2.6-xen-sparse/drivers/xen/netback/interface.c Thu Oct 6 10:11:16 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/interface.c Thu Oct 6 10:12:55 2005
@@ -177,8 +177,13 @@
int netif_map(netif_t *netif, unsigned long tx_ring_ref,
unsigned long rx_ring_ref, unsigned int evtchn)
{
- evtchn_op_t op = { .cmd = EVTCHNOP_bind_interdomain };
int err;
+ evtchn_op_t op = {
+ .cmd = EVTCHNOP_bind_interdomain,
+ .u.bind_interdomain.dom1 = DOMID_SELF,
+ .u.bind_interdomain.dom2 = netif->domid,
+ .u.bind_interdomain.port1 = 0,
+ .u.bind_interdomain.port2 = evtchn };

netif->comms_area = alloc_vm_area(2*PAGE_SIZE);
if (netif->comms_area == NULL)
@@ -190,10 +195,6 @@
return err;
}

- op.u.bind_interdomain.dom1 = DOMID_SELF;
- op.u.bind_interdomain.dom2 = netif->domid;
- op.u.bind_interdomain.port1 = 0;
- op.u.bind_interdomain.port2 = evtchn;
err = HYPERVISOR_event_channel_op(&op);
if (err) {
unmap_frontend_pages(netif);
diff -r 4ab4f023a6ce -r bd37123974b2 linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c
--- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Thu Oct 6 10:11:16 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Thu Oct 6 10:12:55 2005
@@ -972,8 +972,11 @@

static int setup_device(struct xenbus_device *dev, struct netfront_info *info)
{
- evtchn_op_t op = { .cmd = EVTCHNOP_alloc_unbound };
int err;
+ evtchn_op_t op = {
+ .cmd = EVTCHNOP_alloc_unbound,
+ .u.alloc_unbound.dom = DOMID_SELF,
+ .u.alloc_unbound.remote_dom = info->backend_id };

info->tx_ring_ref = GRANT_INVALID_REF;
info->rx_ring_ref = GRANT_INVALID_REF;
@@ -1010,13 +1013,14 @@
}
info->rx_ring_ref = err;

- op.u.alloc_unbound.dom = info->backend_id;
err = HYPERVISOR_event_channel_op(&op);
if (err) {
xenbus_dev_error(dev, err, "allocating event channel");
goto out;
}
+
connect_device(info, op.u.alloc_unbound.port);
+
return 0;

out:
diff -r 4ab4f023a6ce -r bd37123974b2 linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c
--- a/linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c Thu Oct 6 10:11:16 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c Thu Oct 6 10:12:55 2005
@@ -117,8 +117,13 @@
int
tpmif_map(tpmif_t *tpmif, unsigned long shared_page, unsigned int evtchn)
{
- evtchn_op_t op = {.cmd = EVTCHNOP_bind_interdomain };
int err;
+ evtchn_op_t op = {
+ .cmd = EVTCHNOP_bind_interdomain,
+ .u.bind_interdomain.dom1 = DOMID_SELF,
+ .u.bind_interdomain.dom2 = tpmif->domid,
+ .u.bind_interdomain.port1 = 0,
+ .u.bind_interdomain.port2 = evtchn };

if ((tpmif->tx_area = alloc_vm_area(PAGE_SIZE)) == NULL)
return -ENOMEM;
@@ -129,10 +134,6 @@
return err;
}

- op.u.bind_interdomain.dom1 = DOMID_SELF;
- op.u.bind_interdomain.dom2 = tpmif->domid;
- op.u.bind_interdomain.port1 = 0;
- op.u.bind_interdomain.port2 = evtchn;
err = HYPERVISOR_event_channel_op(&op);
if (err) {
unmap_frontend_page(tpmif);
diff -r 4ab4f023a6ce -r bd37123974b2 linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c
--- a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c Thu Oct 6 10:11:16 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c Thu Oct 6 10:12:55 2005
@@ -244,9 +244,11 @@
{
tpmif_tx_interface_t *sring;
struct tpm_private *tp = &my_private;
-
- evtchn_op_t op = { .cmd = EVTCHNOP_alloc_unbound };
int err;
+ evtchn_op_t op = {
+ .cmd = EVTCHNOP_alloc_unbound,
+ .u.alloc_unbound.dom = DOMID_SELF,
+ .u.alloc_unbound.remote_dom = backend_id } ;

sring = (void *)__get_free_page(GFP_KERNEL);
if (!sring) {
@@ -269,7 +271,6 @@
}
info->ring_ref = err;

- op.u.alloc_unbound.dom = backend_id;
err = HYPERVISOR_event_channel_op(&op);
if (err) {
gnttab_end_foreign_access(info->ring_ref, 0);
@@ -278,7 +279,9 @@
xenbus_dev_error(dev, err, "allocating event channel");
return err;
}
+
tpmif_connect(op.u.alloc_unbound.port, backend_id);
+
return 0;
}

@@ -439,26 +442,32 @@
return 0;
}

-static int tpmfront_suspend(struct xenbus_device *dev)
+static int
+tpmfront_suspend(struct xenbus_device *dev)
{
struct tpmfront_info *info = dev->data;
struct tpm_private *tp = &my_private;
-
- /* lock so no app can send */
+ u32 ctr = 0;
+
+ /* lock, so no app can send */
down(&suspend_lock);

- while (atomic_read(&tp->tx_busy)) {
- printk("---- TPMIF: Outstanding request.\n");
-#if 0
+ while (atomic_read(&tp->tx_busy) && ctr <= 25) {
+ if ((ctr % 10) == 0)
+ printk("INFO: Waiting for outstanding request.\n");
/*
- * Would like to wait until the outstanding request
- * has come back, but this does not work properly, yet.
+ * Wait for a request to be responded to.
*/
- interruptible_sleep_on_timeout(&tp->wait_q,
- 100);
-#else
- break;
-#endif
+ interruptible_sleep_on_timeout(&tp->wait_q, 100);
+ ctr++;
+ }
+
+ if (atomic_read(&tp->tx_busy)) {
+ /*
+ * A temporary work-around.
+ */
+ printk("WARNING: Resetting busy flag.");
+ atomic_set(&tp->tx_busy, 0);
}

unregister_xenbus_watch(&info->watch);
@@ -466,44 +475,34 @@
kfree(info->backend);
info->backend = NULL;

- destroy_tpmring(info, tp);
-
return 0;
}

-static int tpmif_recover(void)
-{
- return 0;
-}
-
-static int tpmfront_resume(struct xenbus_device *dev)
+static int
+tpmfront_resume(struct xenbus_device *dev)
{
struct tpmfront_info *info = dev->data;
- int err;
-
- err = talk_to_backend(dev, info);
- if (!err) {
- tpmif_recover();
- }
-
- /* unlock so apps can resume */
+ int err = talk_to_backend(dev, info);
+
+ /* unlock, so apps can resume sending */
up(&suspend_lock);

return err;
}

-static void tpmif_connect(u16 evtchn, domid_t domid)
+static void
+tpmif_connect(u16 evtchn, domid_t domid)
{
int err = 0;
struct tpm_private *tp = &my_private;

tp->evtchn = evtchn;
- tp->backend_id = domid;
-
- err = bind_evtchn_to_irqhandler(
- tp->evtchn,
- tpmif_int, SA_SAMPLE_RANDOM, "tpmif", tp);
- if ( err <= 0 ) {
+ tp->backend_id = domid;
+
+ err = bind_evtchn_to_irqhandler(tp->evtchn,
+ tpmif_int, SA_SAMPLE_RANDOM, "tpmif",
+ tp);
+ if (err <= 0) {
WPRINTK("bind_evtchn_to_irqhandler failed (err=%d)\n", err);
return;
}
@@ -638,7 +637,7 @@

if (NULL == txb) {
DPRINTK("txb (i=%d) is NULL. buffers initilized?\n", i);
- DPRINTK("Not transmittin anything!\n");
+ DPRINTK("Not transmitting anything!\n");
spin_unlock_irq(&tp->tx_lock);
return -EFAULT;
}
diff -r 4ab4f023a6ce -r bd37123974b2 linux-2.6-xen-sparse/include/asm-xen/evtchn.h
--- a/linux-2.6-xen-sparse/include/asm-xen/evtchn.h Thu Oct 6 10:11:16 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/evtchn.h Thu Oct 6 10:12:55 2005
@@ -123,9 +123,9 @@

static inline void notify_remote_via_evtchn(int port)
{
- evtchn_op_t op;
- op.cmd = EVTCHNOP_send;
- op.u.send.local_port = port;
+ evtchn_op_t op = {
+ .cmd = EVTCHNOP_send,
+ .u.send.local_port = port };
(void)HYPERVISOR_event_channel_op(&op);
}

diff -r 4ab4f023a6ce -r bd37123974b2 tools/examples/network-bridge
--- a/tools/examples/network-bridge Thu Oct 6 10:11:16 2005
+++ b/tools/examples/network-bridge Thu Oct 6 10:12:55 2005
@@ -38,22 +38,6 @@
# Print routes.
#
#============================================================================
-
-# Exit if anything goes wrong.
-set -e
-
-# First arg is the operation.
-OP=$1
-shift
-
-# Pull variables in args in to environment.
-for arg ; do export "${arg}" ; done
-
-bridge=${bridge:-xen-br0}
-netdev=${netdev:-eth0}
-antispoof=${antispoof:-no}
-
-echo "*network $OP bridge=$bridge netdev=$netdev antispoof=$antispoof" >&2

# Gentoo doesn't have ifup/ifdown: define appropriate alternatives
which ifup >& /dev/null
@@ -65,6 +49,22 @@
/etc/init.d/net.$1 stop
}
fi
+
+# Exit if anything goes wrong.
+set -e
+
+# First arg is the operation.
+OP=$1
+shift
+
+# Pull variables in args in to environment.
+for arg ; do export "${arg}" ; done
+
+bridge=${bridge:-xen-br0}
+netdev=${netdev:-eth0}
+antispoof=${antispoof:-no}
+
+echo "*network $OP bridge=$bridge netdev=$netdev antispoof=$antispoof" >&2

# Usage: transfer_addrs src dst
# Copy all IP addresses (including aliases) from device $src to device $dst.
diff -r 4ab4f023a6ce -r bd37123974b2 tools/libxc/xc_evtchn.c
--- a/tools/libxc/xc_evtchn.c Thu Oct 6 10:11:16 2005
+++ b/tools/libxc/xc_evtchn.c Thu Oct 6 10:12:55 2005
@@ -33,15 +33,16 @@


int xc_evtchn_alloc_unbound(int xc_handle,
+ u32 remote_dom,
u32 dom,
int *port)
{
- evtchn_op_t op;
int rc;
-
- op.cmd = EVTCHNOP_alloc_unbound;
- op.u.alloc_unbound.dom = (domid_t)dom;
- op.u.alloc_unbound.port = (port != NULL) ? *port : 0;
+ evtchn_op_t op = {
+ .cmd = EVTCHNOP_alloc_unbound,
+ .u.alloc_unbound.remote_dom = (domid_t)remote_dom,
+ .u.alloc_unbound.dom = (domid_t)dom,
+ .u.alloc_unbound.port = (port != NULL) ? *port : 0 };

if ( (rc = do_evtchn_op(xc_handle, &op)) == 0 )
{
@@ -59,15 +60,13 @@
int *port1,
int *port2)
{
- evtchn_op_t op;
int rc;
-
- op.cmd = EVTCHNOP_bind_interdomain;
- op.u.bind_interdomain.dom1 = (domid_t)dom1;
- op.u.bind_interdomain.dom2 = (domid_t)dom2;
- op.u.bind_interdomain.port1 = (port1 != NULL) ? *port1 : 0;
- op.u.bind_interdomain.port2 = (port2 != NULL) ? *port2 : 0;
-
+ evtchn_op_t op = {
+ .cmd = EVTCHNOP_bind_interdomain,
+ .u.bind_interdomain.dom1 = (domid_t)dom1,
+ .u.bind_interdomain.dom2 = (domid_t)dom2,
+ .u.bind_interdomain.port1 = (port1 != NULL) ? *port1 : 0,
+ .u.bind_interdomain.port2 = (port2 != NULL) ? *port2 : 0 };

if ( (rc = do_evtchn_op(xc_handle, &op)) == 0 )
{
@@ -85,12 +84,11 @@
int virq,
int *port)
{
- evtchn_op_t op;
int rc;
-
- op.cmd = EVTCHNOP_bind_virq;
- op.u.bind_virq.virq = (u32)virq;
- op.u.bind_virq.vcpu = 0;
+ evtchn_op_t op = {
+ .cmd = EVTCHNOP_bind_virq,
+ .u.bind_virq.virq = (u32)virq,
+ .u.bind_virq.vcpu = 0 };

if ( (rc = do_evtchn_op(xc_handle, &op)) == 0 )
{
@@ -106,10 +104,10 @@
u32 dom,
int port)
{
- evtchn_op_t op;
- op.cmd = EVTCHNOP_close;
- op.u.close.dom = (domid_t)dom;
- op.u.close.port = port;
+ evtchn_op_t op = {
+ .cmd = EVTCHNOP_close,
+ .u.close.dom = (domid_t)dom,
+ .u.close.port = port };
return do_evtchn_op(xc_handle, &op);
}

@@ -117,9 +115,9 @@
int xc_evtchn_send(int xc_handle,
int local_port)
{
- evtchn_op_t op;
- op.cmd = EVTCHNOP_send;
- op.u.send.local_port = local_port;
+ evtchn_op_t op = {
+ .cmd = EVTCHNOP_send,
+ .u.send.local_port = local_port };
return do_evtchn_op(xc_handle, &op);
}

@@ -129,13 +127,12 @@
int port,
xc_evtchn_status_t *status)
{
- evtchn_op_t op;
int rc;
+ evtchn_op_t op = {
+ .cmd = EVTCHNOP_status,
+ .u.status.dom = (domid_t)dom,
+ .u.status.port = port };

- op.cmd = EVTCHNOP_status;
- op.u.status.dom = (domid_t)dom;
- op.u.status.port = port;
-
if ( (rc = do_evtchn_op(xc_handle, &op)) == 0 )
memcpy(status, &op.u.status, sizeof(*status));

diff -r 4ab4f023a6ce -r bd37123974b2 tools/libxc/xenctrl.h
--- a/tools/libxc/xenctrl.h Thu Oct 6 10:11:16 2005
+++ b/tools/libxc/xenctrl.h Thu Oct 6 10:12:55 2005
@@ -306,13 +306,15 @@
* well-known port within a domain to receive events on.
*
* @parm xc_handle a handle to an open hypervisor interface
- * @parm dom the ID of the domain. This maybe DOMID_SELF
+ * @parm remote_dom the ID of the domain who will later bind
+ * @parm dom the ID of the local domain (the 'allocatee')
* @parm port a pointer to a port. This is an in/out parameter. If *port is
* 0, then a new port will be assigned, if port is > 0 then that
* port is allocated if the port is unallocated.
* @return 0 on success, -1 on failure
*/
int xc_evtchn_alloc_unbound(int xc_handle,
+ u32 remote_dom,
u32 dom,
int *port);

diff -r 4ab4f023a6ce -r bd37123974b2 tools/python/xen/lowlevel/xc/xc.c
--- a/tools/python/xen/lowlevel/xc/xc.c Thu Oct 6 10:11:16 2005
+++ b/tools/python/xen/lowlevel/xc/xc.c Thu Oct 6 10:12:55 2005
@@ -432,16 +432,16 @@
{
XcObject *xc = (XcObject *)self;

- u32 dom;
+ u32 dom = DOMID_SELF, remote_dom;
int port = 0;

- static char *kwd_list[] = { "dom", "port", NULL };
-
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list,
- &dom, &port) )
- return NULL;
-
- if ( xc_evtchn_alloc_unbound(xc->xc_handle, dom, &port) != 0 )
+ static char *kwd_list[] = { "remote_dom", "dom", "port", NULL };
+
+ if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|ii", kwd_list,
+ &remote_dom, &dom, &port) )
+ return NULL;
+
+ if ( xc_evtchn_alloc_unbound(xc->xc_handle, remote_dom, dom, &port) != 0 )
return PyErr_SetFromErrno(xc_error);

return PyInt_FromLong(port);
diff -r 4ab4f023a6ce -r bd37123974b2 tools/python/xen/xend/server/tpmif.py
--- a/tools/python/xen/xend/server/tpmif.py Thu Oct 6 10:11:16 2005
+++ b/tools/python/xen/xend/server/tpmif.py Thu Oct 6 10:12:55 2005
@@ -39,9 +39,24 @@
"""@see DevController.getDeviceDetails"""

devid = int(sxp.child_value(config, 'instance', '0'))
- log.debug("The domain has a TPM with instance %d." % devid)
+ log.info("The domain has a TPM with instance %d." % devid)

back = { 'instance' : "%i" % devid }
front = { 'handle' : "%i" % devid }

return (devid, back, front)
+
+ def configuration(self, devid):
+
+ log.info("The configuration method is called.")
+
+ result = DevContoller.configuration(self, devid)
+
+ (instance) = self.readBackend(devif,
+ 'instance')
+
+ if instance:
+ result.append(['instance', instance])
+ log.info("configuration: instance=%d." % instance)
+
+ return result
diff -r 4ab4f023a6ce -r bd37123974b2 tools/python/xen/xm/main.py
--- a/tools/python/xen/xm/main.py Thu Oct 6 10:11:16 2005
+++ b/tools/python/xen/xm/main.py Thu Oct 6 10:12:55 2005
@@ -86,8 +86,8 @@
shutdown [-w|-a] <DomId> shutdown a domain
sysrq <DomId> <letter> send a sysrq to a domain
unpause <DomId> unpause a paused domain
- vcpu-enable <DomId> <VCPU> disable VCPU in a domain
- vcpu-disable <DomId> <VCPU> enable VCPU in a domain
+ vcpu-enable <DomId> <VCPU> enable VCPU in a domain
+ vcpu-disable <DomId> <VCPU> disable VCPU in a domain
vcpu-list <DomId> get the list of VCPUs for a domain
vcpu-pin <DomId> <VCpu> <CPUS> set which cpus a VCPU can use.

diff -r 4ab4f023a6ce -r bd37123974b2 xen/arch/x86/x86_32/mm.c
--- a/xen/arch/x86/x86_32/mm.c Thu Oct 6 10:11:16 2005
+++ b/xen/arch/x86/x86_32/mm.c Thu Oct 6 10:12:55 2005
@@ -156,6 +156,7 @@
*/
if ( (offsetof(struct pfn_info, u.inuse._domain) !=
(offsetof(struct pfn_info, count_info) + sizeof(u32))) ||
+ ((offsetof(struct pfn_info, count_info) & 7) != 0) ||
(sizeof(struct pfn_info) != 24) )
{
printk("Weird pfn_info layout (%ld,%ld,%d)\n",
diff -r 4ab4f023a6ce -r bd37123974b2 xen/arch/x86/x86_64/mm.c
--- a/xen/arch/x86/x86_64/mm.c Thu Oct 6 10:11:16 2005
+++ b/xen/arch/x86/x86_64/mm.c Thu Oct 6 10:12:55 2005
@@ -137,8 +137,10 @@
* count_info and domain fields must be adjacent, as we perform atomic
* 64-bit operations on them.
*/
- if ( (offsetof(struct pfn_info, u.inuse._domain) !=
- (offsetof(struct pfn_info, count_info) + sizeof(u32))) )
+ if ( ((offsetof(struct pfn_info, u.inuse._domain) !=
+ (offsetof(struct pfn_info, count_info) + sizeof(u32)))) ||
+ ((offsetof(struct pfn_info, count_info) & 7) != 0) ||
+ (sizeof(struct pfn_info) != 40) )
{
printk("Weird pfn_info layout (%ld,%ld,%ld)\n",
offsetof(struct pfn_info, count_info),
diff -r 4ab4f023a6ce -r bd37123974b2 xen/common/event_channel.c
--- a/xen/common/event_channel.c Thu Oct 6 10:11:16 2005
+++ b/xen/common/event_channel.c Thu Oct 6 10:12:55 2005
@@ -63,9 +63,18 @@
static long evtchn_alloc_unbound(evtchn_alloc_unbound_t *alloc)
{
struct evtchn *chn;
- struct domain *d = current->domain;
+ struct domain *d;
int port = alloc->port;
+ domid_t dom = alloc->dom;
long rc = 0;
+
+ if ( dom == DOMID_SELF )
+ dom = current->domain->domain_id;
+ else if ( !IS_PRIV(current->domain) )
+ return -EPERM;
+
+ if ( (d = find_domain_by_id(dom)) == NULL )
+ return -ESRCH;

spin_lock(&d->evtchn_lock);

@@ -84,11 +93,11 @@
{
case ECS_FREE:
chn->state = ECS_UNBOUND;
- chn->u.unbound.remote_domid = alloc->dom;
+ chn->u.unbound.remote_domid = alloc->remote_dom;
break;

case ECS_UNBOUND:
- if ( chn->u.unbound.remote_domid != alloc->dom )
+ if ( chn->u.unbound.remote_domid != alloc->remote_dom )
ERROR_EXIT(-EINVAL);
break;

@@ -99,7 +108,10 @@
out:
spin_unlock(&d->evtchn_lock);

+ put_domain(d);
+
alloc->port = port;
+
return rc;
}

diff -r 4ab4f023a6ce -r bd37123974b2 xen/include/asm-x86/mm.h
--- a/xen/include/asm-x86/mm.h Thu Oct 6 10:11:16 2005
+++ b/xen/include/asm-x86/mm.h Thu Oct 6 10:12:55 2005
@@ -22,9 +22,6 @@
/* Each frame can be threaded onto a doubly-linked list. */
struct list_head list;

- /* Timestamp from 'TLB clock', used to reduce need for safety flushes. */
- u32 tlbflush_timestamp;
-
/* Reference count and various PGC_xxx flags and fields. */
u32 count_info;

@@ -37,17 +34,20 @@
u32 _domain; /* pickled format */
/* Type reference count and various PGT_xxx flags and fields. */
unsigned long type_info;
- } inuse;
+ } __attribute__ ((packed)) inuse;

/* Page is on a free list: ((count_info & PGC_count_mask) == 0). */
struct {
+ /* Order-size of the free chunk this page is the head of. */
+ u32 order;
/* Mask of possibly-tainted TLBs. */
cpumask_t cpumask;
- /* Order-size of the free chunk this page is the head of. */
- u8 order;
- } free;
+ } __attribute__ ((packed)) free;

} u;
+
+ /* Timestamp from 'TLB clock', used to reduce need for safety flushes. */
+ u32 tlbflush_timestamp;
};

/* The following page types are MUTUALLY EXCLUSIVE. */
diff -r 4ab4f023a6ce -r bd37123974b2 xen/include/public/event_channel.h
--- a/xen/include/public/event_channel.h Thu Oct 6 10:11:16 2005
+++ b/xen/include/public/event_channel.h Thu Oct 6 10:12:55 2005
@@ -10,14 +10,16 @@
#define __XEN_PUBLIC_EVENT_CHANNEL_H__

/*
- * EVTCHNOP_alloc_unbound: Prepare a local port for binding to <dom>.
- * <port> may be wildcarded by setting to zero, in which case a fresh port
- * will be allocated, and the field filled in on return.
+ * EVTCHNOP_alloc_unbound: Allocate a port in <dom> for later binding to
+ * <remote_dom>. <port> may be wildcarded by setting to zero, in which case a
+ * fresh port will be allocated, and the field filled in on return.
+ * NOTES:
+ * 1. If the caller is unprivileged then <dom> must be DOMID_SELF.
*/
#define EVTCHNOP_alloc_unbound 6
typedef struct evtchn_alloc_unbound {
/* IN parameters */
- domid_t dom;
+ domid_t dom, remote_dom;
/* IN/OUT parameters */
u32 port;
} evtchn_alloc_unbound_t;

_______________________________________________
Xen-changelog mailing list
Xen-changelog@lists.xensource.com
http://lists.xensource.com/xen-changelog
Merged. [ In reply to ]
# HG changeset patch
# User emellor@ewan
# Node ID 62190db8932678b3610fb17a770e6a02dedfdb3a
# Parent f5320ac7ed317ab4dfe3b3b44d1ac21c79324d37
# Parent 76a7a7aa27e40022fbfeacdd8d6ed9395e875894
Merged.

diff -r f5320ac7ed31 -r 62190db89326 linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c
--- a/linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c Thu Oct 6 18:41:29 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c Thu Oct 6 18:43:11 2005
@@ -44,9 +44,9 @@
#include <linux/poll.h>
#include <linux/irq.h>
#include <linux/init.h>
-#define XEN_EVTCHN_MASK_OPS
+#include <linux/gfp.h>
#include <asm-xen/evtchn.h>
-#include <linux/gfp.h>
+#include <asm-xen/linux-public/evtchn.h>

struct per_user_data {
/* Notification ring, accessed via /dev/xen/evtchn. */
@@ -78,7 +78,8 @@
u->ring[EVTCHN_RING_MASK(u->ring_prod)] = (u16)port;
if (u->ring_cons == u->ring_prod++) {
wake_up_interruptible(&u->evtchn_wait);
- kill_fasync(&u->evtchn_async_queue, SIGIO, POLL_IN);
+ kill_fasync(&u->evtchn_async_queue,
+ SIGIO, POLL_IN);
}
} else {
u->ring_overflow = 1;
@@ -208,38 +209,118 @@
static int evtchn_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
- int rc = 0;
+ int rc;
struct per_user_data *u = file->private_data;
+ evtchn_op_t op = { 0 };

spin_lock_irq(&port_user_lock);

switch (cmd) {
- case EVTCHN_RESET:
+ case IOCTL_EVTCHN_BIND_VIRQ: {
+ struct ioctl_evtchn_bind_virq bind;
+
+ rc = -EFAULT;
+ if (copy_from_user(&bind, (void *)arg, sizeof(bind)))
+ break;
+
+ op.cmd = EVTCHNOP_bind_virq;
+ op.u.bind_virq.virq = bind.virq;
+ op.u.bind_virq.vcpu = 0;
+ rc = HYPERVISOR_event_channel_op(&op);
+ if (rc != 0)
+ break;
+
+ rc = op.u.bind_virq.port;
+ port_user[rc] = u;
+ unmask_evtchn(rc);
+ break;
+ }
+
+ case IOCTL_EVTCHN_BIND_INTERDOMAIN: {
+ struct ioctl_evtchn_bind_interdomain bind;
+
+ rc = -EFAULT;
+ if (copy_from_user(&bind, (void *)arg, sizeof(bind)))
+ break;
+
+ op.cmd = EVTCHNOP_bind_interdomain;
+ op.u.bind_interdomain.dom1 = DOMID_SELF;
+ op.u.bind_interdomain.dom2 = bind.remote_domain;
+ op.u.bind_interdomain.port1 = 0;
+ op.u.bind_interdomain.port2 = bind.remote_port;
+ rc = HYPERVISOR_event_channel_op(&op);
+ if (rc != 0)
+ break;
+
+ rc = op.u.bind_interdomain.port1;
+ port_user[rc] = u;
+ unmask_evtchn(rc);
+ break;
+ }
+
+ case IOCTL_EVTCHN_BIND_UNBOUND_PORT: {
+ struct ioctl_evtchn_bind_unbound_port bind;
+
+ rc = -EFAULT;
+ if (copy_from_user(&bind, (void *)arg, sizeof(bind)))
+ break;
+
+ op.cmd = EVTCHNOP_alloc_unbound;
+ op.u.alloc_unbound.dom = DOMID_SELF;
+ op.u.alloc_unbound.remote_dom = bind.remote_domain;
+ rc = HYPERVISOR_event_channel_op(&op);
+ if (rc != 0)
+ break;
+
+ rc = op.u.alloc_unbound.port;
+ port_user[rc] = u;
+ unmask_evtchn(rc);
+ break;
+ }
+
+ case IOCTL_EVTCHN_UNBIND: {
+ struct ioctl_evtchn_unbind unbind;
+
+ rc = -EFAULT;
+ if (copy_from_user(&unbind, (void *)arg, sizeof(unbind)))
+ break;
+
+ if (unbind.port >= NR_EVENT_CHANNELS) {
+ rc = -EINVAL;
+ } else if (port_user[unbind.port] != u) {
+ rc = -ENOTCONN;
+ } else {
+ port_user[unbind.port] = NULL;
+ mask_evtchn(unbind.port);
+ rc = 0;
+ }
+ break;
+ }
+
+ case IOCTL_EVTCHN_NOTIFY: {
+ struct ioctl_evtchn_notify notify;
+
+ rc = -EFAULT;
+ if (copy_from_user(&notify, (void *)arg, sizeof(notify)))
+ break;
+
+ if (notify.port >= NR_EVENT_CHANNELS) {
+ rc = -EINVAL;
+ } else if (port_user[notify.port] != u) {
+ rc = -ENOTCONN;
+ } else {
+ notify_remote_via_evtchn(notify.port);
+ rc = 0;
+ }
+ break;
+ }
+
+ case IOCTL_EVTCHN_RESET: {
/* Initialise the ring to empty. Clear errors. */
u->ring_cons = u->ring_prod = u->ring_overflow = 0;
- break;
-
- case EVTCHN_BIND:
- if (arg >= NR_EVENT_CHANNELS) {
- rc = -EINVAL;
- } else if (port_user[arg] != NULL) {
- rc = -EISCONN;
- } else {
- port_user[arg] = u;
- unmask_evtchn(arg);
- }
- break;
-
- case EVTCHN_UNBIND:
- if (arg >= NR_EVENT_CHANNELS) {
- rc = -EINVAL;
- } else if (port_user[arg] != u) {
- rc = -ENOTCONN;
- } else {
- port_user[arg] = NULL;
- mask_evtchn(arg);
- }
- break;
+ rc = 0;
+ break;
+ }

default:
rc = -ENOSYS;
@@ -295,6 +376,7 @@
{
int i;
struct per_user_data *u = filp->private_data;
+ evtchn_op_t op = { 0 };

spin_lock_irq(&port_user_lock);

@@ -302,11 +384,16 @@

for (i = 0; i < NR_EVENT_CHANNELS; i++)
{
- if (port_user[i] == u)
- {
- port_user[i] = NULL;
- mask_evtchn(i);
- }
+ if (port_user[i] != u)
+ continue;
+
+ port_user[i] = NULL;
+ mask_evtchn(i);
+
+ op.cmd = EVTCHNOP_close;
+ op.u.close.dom = DOMID_SELF;
+ op.u.close.port = i;
+ BUG_ON(HYPERVISOR_event_channel_op(&op));
}

spin_unlock_irq(&port_user_lock);
diff -r f5320ac7ed31 -r 62190db89326 linux-2.6-xen-sparse/include/asm-xen/evtchn.h
--- a/linux-2.6-xen-sparse/include/asm-xen/evtchn.h Thu Oct 6 18:41:29 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/evtchn.h Thu Oct 6 18:43:11 2005
@@ -129,21 +129,6 @@
(void)HYPERVISOR_event_channel_op(&op);
}

-/*
- * CHARACTER-DEVICE DEFINITIONS
- */
-
-/* /dev/xen/evtchn resides at device number major=10, minor=201 */
-#define EVTCHN_MINOR 201
-
-/* /dev/xen/evtchn ioctls: */
-/* EVTCHN_RESET: Clear and reinit the event buffer. Clear error condition. */
-#define EVTCHN_RESET _IO('E', 1)
-/* EVTCHN_BIND: Bind to teh specified event-channel port. */
-#define EVTCHN_BIND _IO('E', 2)
-/* EVTCHN_UNBIND: Unbind from the specified event-channel port. */
-#define EVTCHN_UNBIND _IO('E', 3)
-
#endif /* __ASM_EVTCHN_H__ */

/*
diff -r f5320ac7ed31 -r 62190db89326 linux-2.6-xen-sparse/include/asm-xen/linux-public/privcmd.h
--- a/linux-2.6-xen-sparse/include/asm-xen/linux-public/privcmd.h Thu Oct 6 18:41:29 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/linux-public/privcmd.h Thu Oct 6 18:43:11 2005
@@ -3,7 +3,7 @@
*
* Interface to /proc/xen/privcmd.
*
- * Copyright (c) 2003-2004, K A Fraser
+ * Copyright (c) 2003-2005, K A Fraser
*
* This file may be distributed separately from the Linux kernel, or
* incorporated into other software packages, subject to the following license:
@@ -27,39 +27,39 @@
* IN THE SOFTWARE.
*/

-#ifndef __PRIVCMD_H__
-#define __PRIVCMD_H__
+#ifndef __LINUX_PUBLIC_PRIVCMD_H__
+#define __LINUX_PUBLIC_PRIVCMD_H__

typedef struct privcmd_hypercall
{
- unsigned long op;
- unsigned long arg[5];
+ unsigned long op;
+ unsigned long arg[5];
} privcmd_hypercall_t;

typedef struct privcmd_mmap_entry {
- unsigned long va;
- unsigned long mfn;
- unsigned long npages;
+ unsigned long va;
+ unsigned long mfn;
+ unsigned long npages;
} privcmd_mmap_entry_t;

typedef struct privcmd_mmap {
- int num;
- domid_t dom; /* target domain */
- privcmd_mmap_entry_t *entry;
+ int num;
+ domid_t dom; /* target domain */
+ privcmd_mmap_entry_t *entry;
} privcmd_mmap_t;

typedef struct privcmd_mmapbatch {
- int num; /* number of pages to populate */
- domid_t dom; /* target domain */
- unsigned long addr; /* virtual address */
- unsigned long *arr; /* array of mfns - top nibble set on err */
+ int num; /* number of pages to populate */
+ domid_t dom; /* target domain */
+ unsigned long addr; /* virtual address */
+ unsigned long *arr; /* array of mfns - top nibble set on err */
} privcmd_mmapbatch_t;

typedef struct privcmd_blkmsg
{
- unsigned long op;
- void *buf;
- int buf_size;
+ unsigned long op;
+ void *buf;
+ int buf_size;
} privcmd_blkmsg_t;

/*
@@ -67,16 +67,26 @@
* @arg: &privcmd_hypercall_t
* Return: Value returned from execution of the specified hypercall.
*/
-#define IOCTL_PRIVCMD_HYPERCALL \
- _IOC(_IOC_NONE, 'P', 0, sizeof(privcmd_hypercall_t))
+#define IOCTL_PRIVCMD_HYPERCALL \
+ _IOC(_IOC_NONE, 'P', 0, sizeof(privcmd_hypercall_t))

-#define IOCTL_PRIVCMD_MMAP \
- _IOC(_IOC_NONE, 'P', 2, sizeof(privcmd_mmap_t))
-#define IOCTL_PRIVCMD_MMAPBATCH \
- _IOC(_IOC_NONE, 'P', 3, sizeof(privcmd_mmapbatch_t))
-#define IOCTL_PRIVCMD_GET_MACH2PHYS_START_MFN \
- _IOC(_IOC_READ, 'P', 4, sizeof(unsigned long))
-#define IOCTL_PRIVCMD_INITDOMAIN_STORE \
- _IOC(_IOC_READ, 'P', 5, 0)
+#define IOCTL_PRIVCMD_MMAP \
+ _IOC(_IOC_NONE, 'P', 2, sizeof(privcmd_mmap_t))
+#define IOCTL_PRIVCMD_MMAPBATCH \
+ _IOC(_IOC_NONE, 'P', 3, sizeof(privcmd_mmapbatch_t))
+#define IOCTL_PRIVCMD_GET_MACH2PHYS_START_MFN \
+ _IOC(_IOC_READ, 'P', 4, sizeof(unsigned long))
+#define IOCTL_PRIVCMD_INITDOMAIN_STORE \
+ _IOC(_IOC_READ, 'P', 5, 0)

-#endif /* __PRIVCMD_H__ */
+#endif /* __LINUX_PUBLIC_PRIVCMD_H__ */
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r f5320ac7ed31 -r 62190db89326 tools/console/daemon/io.c
--- a/tools/console/daemon/io.c Thu Oct 6 18:41:29 2005
+++ b/tools/console/daemon/io.c Thu Oct 6 18:43:11 2005
@@ -1,4 +1,4 @@
-/*\
+/*
* Copyright (C) International Business Machines Corp., 2005
* Author(s): Anthony Liguori <aliguori@us.ibm.com>
*
@@ -16,14 +16,15 @@
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-\*/
+ */

#define _GNU_SOURCE

#include "utils.h"
#include "io.h"
-#include "xenctrl.h"
-#include "xs.h"
+#include <xenctrl.h>
+#include <xs.h>
+#include <xen/linux/evtchn.h>

#include <malloc.h>
#include <stdlib.h>
@@ -80,6 +81,13 @@
#define XENCONS_FULL(ring) (((ring)->prod - (ring)->cons) == XENCONS_RING_SIZE)
#define XENCONS_SPACE(ring) (XENCONS_RING_SIZE - ((ring)->prod - (ring)->cons))

+static void evtchn_notify(struct domain *dom)
+{
+ struct ioctl_evtchn_notify notify;
+ notify.port = dom->local_port;
+ (void)ioctl(dom->evtchn_fd, IOCTL_EVTCHN_NOTIFY, &notify);
+}
+
static void buffer_append(struct domain *dom)
{
struct buffer *buffer = &dom->buffer;
@@ -120,7 +128,7 @@
}

if (notify)
- xc_evtchn_send(xc, dom->local_port);
+ evtchn_notify(dom);
}

static bool buffer_empty(struct buffer *buffer)
@@ -225,16 +233,14 @@
return ret;
}

-#define EVENTCHN_BIND _IO('E', 2)
-#define EVENTCHN_UNBIND _IO('E', 3)
-
static int domain_create_ring(struct domain *dom)
{
- int err, local_port, ring_ref;
+ int err, remote_port, ring_ref, rc;
+ struct ioctl_evtchn_bind_interdomain bind;

err = xs_gather(xs, dom->conspath,
"ring-ref", "%u", &ring_ref,
- "port", "%i", &local_port,
+ "port", "%i", &remote_port,
NULL);
if (err)
goto out;
@@ -252,26 +258,28 @@
dom->ring_ref = ring_ref;
}

- if (local_port != dom->local_port) {
- dom->local_port = -1;
- if (dom->evtchn_fd != -1)
- close(dom->evtchn_fd);
- /* Opening evtchn independently for each console is a bit
- * wastefule, but that's how the code is structured... */
- dom->evtchn_fd = open("/dev/xen/evtchn", O_RDWR);
- if (dom->evtchn_fd == -1) {
- err = errno;
- goto out;
- }
+ dom->local_port = -1;
+ if (dom->evtchn_fd != -1)
+ close(dom->evtchn_fd);
+
+ /* Opening evtchn independently for each console is a bit
+ * wasteful, but that's how the code is structured... */
+ dom->evtchn_fd = open("/dev/xen/evtchn", O_RDWR);
+ if (dom->evtchn_fd == -1) {
+ err = errno;
+ goto out;
+ }

- if (ioctl(dom->evtchn_fd, EVENTCHN_BIND, local_port) == -1) {
- err = errno;
- close(dom->evtchn_fd);
- dom->evtchn_fd = -1;
- goto out;
- }
- dom->local_port = local_port;
- }
+ bind.remote_domain = dom->domid;
+ bind.remote_port = remote_port;
+ rc = ioctl(dom->evtchn_fd, IOCTL_EVTCHN_BIND_INTERDOMAIN, &bind);
+ if (rc == -1) {
+ err = errno;
+ close(dom->evtchn_fd);
+ dom->evtchn_fd = -1;
+ goto out;
+ }
+ dom->local_port = rc;

out:
return err;
@@ -439,7 +447,7 @@
inring->buf[XENCONS_IDX(inring->prod)] = msg[i];
inring->prod++;
}
- xc_evtchn_send(xc, dom->local_port);
+ evtchn_notify(dom);
} else {
close(dom->tty_fd);
dom->tty_fd = -1;
diff -r f5320ac7ed31 -r 62190db89326 tools/debugger/pdb/pdb_xen.c
--- a/tools/debugger/pdb/pdb_xen.c Thu Oct 6 18:41:29 2005
+++ b/tools/debugger/pdb/pdb_xen.c Thu Oct 6 18:43:11 2005
@@ -43,11 +43,7 @@


#include <sys/ioctl.h>
-
-/* /dev/xen/evtchn ioctls */
-#define EVTCHN_RESET _IO('E', 1) /* clear & reinit buffer */
-#define EVTCHN_BIND _IO('E', 2) /* bind to event channel */
-#define EVTCHN_UNBIND _IO('E', 3) /* unbind from event channel */
+#include <xen/linux/evtchn.h>

int
xen_evtchn_bind (int evtchn_fd, int idx)
diff -r f5320ac7ed31 -r 62190db89326 tools/ioemu/target-i386-dm/helper2.c
--- a/tools/ioemu/target-i386-dm/helper2.c Thu Oct 6 18:41:29 2005
+++ b/tools/ioemu/target-i386-dm/helper2.c Thu Oct 6 18:43:11 2005
@@ -49,10 +49,13 @@

#include <xenctrl.h>
#include <xen/io/ioreq.h>
+#include <xen/linux/evtchn.h>

#include "cpu.h"
#include "exec-all.h"
#include "vl.h"
+
+extern int domid;

void *shared_vram;

@@ -119,7 +122,7 @@
//the evtchn fd for polling
int evtchn_fd = -1;
//the evtchn port for polling the notification, should be inputed as bochs's parameter
-u16 ioreq_port = 0;
+u16 ioreq_remote_port, ioreq_local_port;

//some functions to handle the io req packet
void
@@ -156,9 +159,9 @@
int rc;
u16 buf[2];
rc = read(evtchn_fd, buf, 2);
- if (rc == 2 && buf[0] == ioreq_port){//got only one matched 16bit port index
+ if (rc == 2 && buf[0] == ioreq_local_port){//got only one matched 16bit port index
// unmask the wanted port again
- write(evtchn_fd, &ioreq_port, 2);
+ write(evtchn_fd, &ioreq_local_port, 2);

//get the io packet from shared memory
return __cpu_get_ioreq();
@@ -417,7 +420,6 @@
void
destroy_vmx_domain(void)
{
- extern int domid;
extern FILE* logfile;
char destroy_cmd[20];
sprintf(destroy_cmd, "xm destroy %d", domid);
@@ -484,11 +486,9 @@
do_ioapic();
#endif
if (env->send_event) {
- int ret;
- ret = xc_evtchn_send(xc_handle, ioreq_port);
- if (ret == -1) {
- fprintf(logfile, "evtchn_send failed on port: %d\n", ioreq_port);
- }
+ struct ioctl_evtchn_notify notify;
+ notify.port = ioreq_local_port;
+ (void)ioctl(evtchn_fd, IOCTL_EVTCHN_NOTIFY, &notify);
}
}
destroy_vmx_domain();
@@ -499,7 +499,6 @@
qemu_vmx_reset(void *unused)
{
char cmd[255];
- extern int domid;

/* pause domain first, to avoid repeated reboot request*/
xc_domain_pause (xc_handle, domid);
@@ -512,6 +511,8 @@
cpu_init()
{
CPUX86State *env;
+ struct ioctl_evtchn_bind_interdomain bind;
+ int rc;

cpu_exec_init();
qemu_register_reset(qemu_vmx_reset, NULL);
@@ -532,12 +533,14 @@
return NULL;
}

- fprintf(logfile, "listening to port: %d\n", ioreq_port);
- /*unmask the wanted port -- bind*/
- if (ioctl(evtchn_fd, ('E'<<8)|2, ioreq_port) == -1) {
+ bind.remote_domain = domid;
+ bind.remote_port = ioreq_remote_port;
+ rc = ioctl(evtchn_fd, IOCTL_EVTCHN_BIND_INTERDOMAIN, &bind);
+ if (rc == -1) {
perror("ioctl");
return NULL;
}
+ ioreq_local_port = rc;

return env;
}
diff -r f5320ac7ed31 -r 62190db89326 tools/ioemu/vl.c
--- a/tools/ioemu/vl.c Thu Oct 6 18:41:29 2005
+++ b/tools/ioemu/vl.c Thu Oct 6 18:43:11 2005
@@ -2806,9 +2806,9 @@

case QEMU_OPTION_p:
{
- extern short ioreq_port;
- ioreq_port = atoi(optarg);
- printf("port: %d\n", ioreq_port);
+ extern short ioreq_remote_port;
+ ioreq_remote_port = atoi(optarg);
+ printf("port: %d\n", ioreq_remote_port);
}
break;
case QEMU_OPTION_l:
diff -r f5320ac7ed31 -r 62190db89326 tools/libxc/xc_evtchn.c
--- a/tools/libxc/xc_evtchn.c Thu Oct 6 18:41:29 2005
+++ b/tools/libxc/xc_evtchn.c Thu Oct 6 18:43:11 2005
@@ -33,92 +33,19 @@


int xc_evtchn_alloc_unbound(int xc_handle,
- u32 remote_dom,
u32 dom,
- int *port)
+ u32 remote_dom)
{
int rc;
evtchn_op_t op = {
.cmd = EVTCHNOP_alloc_unbound,
- .u.alloc_unbound.remote_dom = (domid_t)remote_dom,
- .u.alloc_unbound.dom = (domid_t)dom,
- .u.alloc_unbound.port = (port != NULL) ? *port : 0 };
+ .u.alloc_unbound.dom = (domid_t)dom,
+ .u.alloc_unbound.remote_dom = (domid_t)remote_dom };

if ( (rc = do_evtchn_op(xc_handle, &op)) == 0 )
- {
- if ( port != NULL )
- *port = op.u.alloc_unbound.port;
- }
+ rc = op.u.alloc_unbound.port;

return rc;
-}
-
-
-int xc_evtchn_bind_interdomain(int xc_handle,
- u32 dom1,
- u32 dom2,
- int *port1,
- int *port2)
-{
- int rc;
- evtchn_op_t op = {
- .cmd = EVTCHNOP_bind_interdomain,
- .u.bind_interdomain.dom1 = (domid_t)dom1,
- .u.bind_interdomain.dom2 = (domid_t)dom2,
- .u.bind_interdomain.port1 = (port1 != NULL) ? *port1 : 0,
- .u.bind_interdomain.port2 = (port2 != NULL) ? *port2 : 0 };
-
- if ( (rc = do_evtchn_op(xc_handle, &op)) == 0 )
- {
- if ( port1 != NULL )
- *port1 = op.u.bind_interdomain.port1;
- if ( port2 != NULL )
- *port2 = op.u.bind_interdomain.port2;
- }
-
- return rc;
-}
-
-
-int xc_evtchn_bind_virq(int xc_handle,
- int virq,
- int *port)
-{
- int rc;
- evtchn_op_t op = {
- .cmd = EVTCHNOP_bind_virq,
- .u.bind_virq.virq = (u32)virq,
- .u.bind_virq.vcpu = 0 };
-
- if ( (rc = do_evtchn_op(xc_handle, &op)) == 0 )
- {
- if ( port != NULL )
- *port = op.u.bind_virq.port;
- }
-
- return rc;
-}
-
-
-int xc_evtchn_close(int xc_handle,
- u32 dom,
- int port)
-{
- evtchn_op_t op = {
- .cmd = EVTCHNOP_close,
- .u.close.dom = (domid_t)dom,
- .u.close.port = port };
- return do_evtchn_op(xc_handle, &op);
-}
-
-
-int xc_evtchn_send(int xc_handle,
- int local_port)
-{
- evtchn_op_t op = {
- .cmd = EVTCHNOP_send,
- .u.send.local_port = local_port };
- return do_evtchn_op(xc_handle, &op);
}


diff -r f5320ac7ed31 -r 62190db89326 tools/libxc/xenctrl.h
--- a/tools/libxc/xenctrl.h Thu Oct 6 18:41:29 2005
+++ b/tools/libxc/xenctrl.h Thu Oct 6 18:43:11 2005
@@ -306,68 +306,14 @@
* well-known port within a domain to receive events on.
*
* @parm xc_handle a handle to an open hypervisor interface
+ * @parm dom the ID of the local domain (the 'allocatee')
* @parm remote_dom the ID of the domain who will later bind
- * @parm dom the ID of the local domain (the 'allocatee')
- * @parm port a pointer to a port. This is an in/out parameter. If *port is
- * 0, then a new port will be assigned, if port is > 0 then that
- * port is allocated if the port is unallocated.
- * @return 0 on success, -1 on failure
+ * @return allocated port (in @dom) on success, -1 on failure
*/
int xc_evtchn_alloc_unbound(int xc_handle,
- u32 remote_dom,
u32 dom,
- int *port);
-
-/**
- * This function creates a pair of ports between two domains. A port can only
- * be bound once within a domain.
- *
- * @parm xc_handle a handle to an open hypervisor interface
- * @parm dom1 one of the two domains to connect. Can be DOMID_SELF.
- * @parm dom2 the other domain to connect. Can be DOMID_SELF.
- * @parm port1 an in/out parameter. If > 0, then try to connect *port. If
- * 0, then allocate a new port and store the port in *port.
- * @parm port2 the port connected on port2. This parameter behaves the same
- * way as port1.
- * @return 0 on success, -1 on error.
- */
-int xc_evtchn_bind_interdomain(int xc_handle,
- u32 dom1,
- u32 dom2,
- int *port1,
- int *port2);
-int xc_evtchn_bind_virq(int xc_handle,
- int virq,
- int *port);
-
-/**
- * This function will close a single port on an event channel.
- *
- * @parm xc_handle a handle to an open hypervisor interface
- * @parm dom the domain that the port exists on. May be DOMID_SELF.
- * @parm port the port to close
- * @return 0 on success, -1 on error
- */
-int xc_evtchn_close(int xc_handle,
- u32 dom, /* may be DOMID_SELF */
- int port);
-
-/**
- * This function generates a notify event on a bound port.
- *
- * Notifies can be read within Linux by opening /dev/xen/evtchn and reading
- * a 16 bit value. The result will be the port the event occurred on. When
- * events occur, the port is masked until the 16 bit port value is written back
- * to the file. When /dev/xen/evtchn is opened, it has to be bound via an
- * ioctl to each port to listen on. The ioctl for binding is _IO('E', 2). The
- * parameter is the port to listen on.
- *
- * @parm xc_handle a handle to an open hypervisor interface
- * @parm local_port the port to generate the notify on
- * @return 0 on success, -1 on error
- */
-int xc_evtchn_send(int xc_handle,
- int local_port);
+ u32 remote_dom);
+
int xc_evtchn_status(int xc_handle,
u32 dom, /* may be DOMID_SELF */
int port,
diff -r f5320ac7ed31 -r 62190db89326 tools/python/xen/lowlevel/xc/xc.c
--- a/tools/python/xen/lowlevel/xc/xc.c Thu Oct 6 18:41:29 2005
+++ b/tools/python/xen/lowlevel/xc/xc.c Thu Oct 6 18:43:11 2005
@@ -433,103 +433,18 @@
XcObject *xc = (XcObject *)self;

u32 dom = DOMID_SELF, remote_dom;
- int port = 0;
-
- static char *kwd_list[] = { "remote_dom", "dom", "port", NULL };
-
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|ii", kwd_list,
- &remote_dom, &dom, &port) )
- return NULL;
-
- if ( xc_evtchn_alloc_unbound(xc->xc_handle, remote_dom, dom, &port) != 0 )
+ int port;
+
+ static char *kwd_list[] = { "remote_dom", "dom", NULL };
+
+ if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list,
+ &remote_dom, &dom) )
+ return NULL;
+
+ if ( (port = xc_evtchn_alloc_unbound(xc->xc_handle, dom, remote_dom)) < 0 )
return PyErr_SetFromErrno(xc_error);

return PyInt_FromLong(port);
-}
-
-static PyObject *pyxc_evtchn_bind_interdomain(PyObject *self,
- PyObject *args,
- PyObject *kwds)
-{
- XcObject *xc = (XcObject *)self;
-
- u32 dom1 = DOMID_SELF, dom2 = DOMID_SELF;
- int port1 = 0, port2 = 0;
-
- static char *kwd_list[] = { "dom1", "dom2", "port1", "port2", NULL };
-
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|iiii", kwd_list,
- &dom1, &dom2, &port1, &port2) )
- return NULL;
-
- if ( xc_evtchn_bind_interdomain(xc->xc_handle, dom1,
- dom2, &port1, &port2) != 0 )
- return PyErr_SetFromErrno(xc_error);
-
- return Py_BuildValue("{s:i,s:i}",
- "port1", port1,
- "port2", port2);
-}
-
-static PyObject *pyxc_evtchn_bind_virq(PyObject *self,
- PyObject *args,
- PyObject *kwds)
-{
- XcObject *xc = (XcObject *)self;
-
- int virq, port;
-
- static char *kwd_list[] = { "virq", NULL };
-
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &virq) )
- return NULL;
-
- if ( xc_evtchn_bind_virq(xc->xc_handle, virq, &port) != 0 )
- return PyErr_SetFromErrno(xc_error);
-
- return PyInt_FromLong(port);
-}
-
-static PyObject *pyxc_evtchn_close(PyObject *self,
- PyObject *args,
- PyObject *kwds)
-{
- XcObject *xc = (XcObject *)self;
-
- u32 dom = DOMID_SELF;
- int port;
-
- static char *kwd_list[] = { "port", "dom", NULL };
-
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list,
- &port, &dom) )
- return NULL;
-
- if ( xc_evtchn_close(xc->xc_handle, dom, port) != 0 )
- return PyErr_SetFromErrno(xc_error);
-
- Py_INCREF(zero);
- return zero;
-}
-
-static PyObject *pyxc_evtchn_send(PyObject *self,
- PyObject *args,
- PyObject *kwds)
-{
- XcObject *xc = (XcObject *)self;
-
- int port;
-
- static char *kwd_list[] = { "port", NULL };
-
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &port) )
- return NULL;
-
- if ( xc_evtchn_send(xc->xc_handle, port) != 0 )
- return PyErr_SetFromErrno(xc_error);
-
- Py_INCREF(zero);
- return zero;
}

static PyObject *pyxc_evtchn_status(PyObject *self,
@@ -1032,38 +947,6 @@
" dom [int]: Remote domain to accept connections from.\n\n"
"Returns: [int] Unbound event-channel port.\n" },

- { "evtchn_bind_interdomain",
- (PyCFunction)pyxc_evtchn_bind_interdomain,
- METH_VARARGS | METH_KEYWORDS, "\n"
- "Open an event channel between two domains.\n"
- " dom1 [int, SELF]: First domain to be connected.\n"
- " dom2 [int, SELF]: Second domain to be connected.\n\n"
- "Returns: [dict] dictionary is empty on failure.\n"
- " port1 [int]: Port-id for endpoint at dom1.\n"
- " port2 [int]: Port-id for endpoint at dom2.\n" },
-
- { "evtchn_bind_virq",
- (PyCFunction)pyxc_evtchn_bind_virq,
- METH_VARARGS | METH_KEYWORDS, "\n"
- "Bind an event channel to the specified VIRQ.\n"
- " virq [int]: VIRQ to bind.\n\n"
- "Returns: [int] Bound event-channel port.\n" },
-
- { "evtchn_close",
- (PyCFunction)pyxc_evtchn_close,
- METH_VARARGS | METH_KEYWORDS, "\n"
- "Close an event channel. If interdomain, sets remote end to 'unbound'.\n"
- " dom [int, SELF]: Dom-id of one endpoint of the channel.\n"
- " port [int]: Port-id of one endpoint of the channel.\n\n"
- "Returns: [int] 0 on success; -1 on error.\n" },
-
- { "evtchn_send",
- (PyCFunction)pyxc_evtchn_send,
- METH_VARARGS | METH_KEYWORDS, "\n"
- "Send an event along a locally-connected event channel.\n"
- " port [int]: Port-id of a local channel endpoint.\n\n"
- "Returns: [int] 0 on success; -1 on error.\n" },
-
{ "evtchn_status",
(PyCFunction)pyxc_evtchn_status,
METH_VARARGS | METH_KEYWORDS, "\n"
diff -r f5320ac7ed31 -r 62190db89326 tools/python/xen/xend/XendCheckpoint.py
--- a/tools/python/xen/xend/XendCheckpoint.py Thu Oct 6 18:41:29 2005
+++ b/tools/python/xen/xend/XendCheckpoint.py Thu Oct 6 18:43:11 2005
@@ -126,8 +126,8 @@
raise XendError(
"not a valid guest state file: pfn count out of range")

- store_evtchn = dominfo.store_channel.port2
- console_evtchn = dominfo.console_channel.port2
+ store_evtchn = dominfo.store_channel
+ console_evtchn = dominfo.console_channel

cmd = [.PATH_XC_RESTORE, str(xc.handle()), str(fd),
str(dominfo.getDomid()), str(nr_pfns),
@@ -146,7 +146,7 @@
dominfo.getDomainPath())
IntroduceDomain(dominfo.getDomid(),
store_mfn,
- dominfo.store_channel.port1,
+ dominfo.store_channel,
dominfo.getDomainPath())
else:
m = re.match(r"^(console-mfn) (\d+)$", line)
diff -r f5320ac7ed31 -r 62190db89326 tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py Thu Oct 6 18:41:29 2005
+++ b/tools/python/xen/xend/XendDomainInfo.py Thu Oct 6 18:43:11 2005
@@ -31,8 +31,6 @@

import xen.lowlevel.xc
from xen.util.blkif import blkdev_uname_to_file
-
-from xen.xend.server import channel

from xen.xend import image
from xen.xend import scheduler
@@ -785,32 +783,6 @@
self.domid, self.info['name'])


- def closeChannel(self, chan, entry):
- """Close the given channel, if set, and remove the given entry in the
- store. Nothrow guarantee."""
-
- if chan:
- chan.close()
- try:
- self.removeDom(entry)
- except:
- log.exception('Removing entry %s failed', entry)
-
-
- def closeStoreChannel(self):
- """Close the store channel, if any. Nothrow guarantee."""
-
- self.closeChannel(self.store_channel, "store/port")
- self.store_channel = None
-
-
- def closeConsoleChannel(self):
- """Close the console channel, if any. Nothrow guarantee."""
-
- self.closeChannel(self.console_channel, "console/port")
- self.console_channel = None
-
-
## public:

def setConsoleRef(self, ref):
@@ -964,12 +936,8 @@
sxpr.append(['up_time', str(up_time) ])
sxpr.append(['start_time', str(self.info['start_time']) ])

- if self.store_channel:
- sxpr.append(self.store_channel.sxpr())
if self.store_mfn:
sxpr.append(['store_mfn', self.store_mfn])
- if self.console_channel:
- sxpr.append(['console_channel', self.console_channel.sxpr()])
if self.console_mfn:
sxpr.append(['console_mfn', self.console_mfn])

@@ -1077,7 +1045,7 @@
self.create_channel()
self.image.createImage()
IntroduceDomain(self.domid, self.store_mfn,
- self.store_channel.port1, self.dompath)
+ self.store_channel, self.dompath)


## public:
@@ -1087,8 +1055,6 @@
guarantee."""

self.release_devices()
- self.closeStoreChannel()
- self.closeConsoleChannel()

if self.image:
try:
@@ -1168,35 +1134,22 @@

@param path under which port is stored in db
"""
- port = 0
if path:
try:
- port = int(self.readDom(path))
+ return int(self.readDom(path))
except:
# The port is not yet set, i.e. the channel has not yet been
# created.
pass

- # Stale port information from above causes an Invalid Argument to be
- # thrown by the eventChannel call below. To recover, we throw away
- # port if it turns out to be bad, and just create a new channel.
- # If creating a new channel with two new ports fails, then something
- # else is going wrong, so we bail.
- while True:
- try:
- ret = channel.eventChannel(0, self.domid, port1 = port,
- port2 = 0)
- break
- except:
- log.exception("Exception in eventChannel(0, %d, %d, %d)",
- self.domid, port, 0)
- if port == 0:
- raise
- else:
- port = 0
- log.error("Recovering from above exception.")
- self.storeDom(path, ret.port1)
- return ret
+ try:
+ port = xc.evtchn_alloc_unbound(dom=self.domid, remote_dom=0)
+ except:
+ log.exception("Exception in alloc_unbound(%d)", self.domid)
+ raise
+
+ self.storeDom(path, port)
+ return port

def create_channel(self):
"""Create the channels to the domain.
@@ -1423,11 +1376,11 @@


def initStoreConnection(self):
- ref = xc.init_store(self.store_channel.port2)
+ ref = xc.init_store(self.store_channel)
if ref and ref >= 0:
self.setStoreRef(ref)
try:
- IntroduceDomain(self.domid, ref, self.store_channel.port1,
+ IntroduceDomain(self.domid, ref, self.store_channel,
self.dompath)
except RuntimeError, ex:
if ex.args[0] == errno.EISCONN:
diff -r f5320ac7ed31 -r 62190db89326 tools/python/xen/xend/image.py
--- a/tools/python/xen/xend/image.py Thu Oct 6 18:41:29 2005
+++ b/tools/python/xen/xend/image.py Thu Oct 6 18:43:11 2005
@@ -25,8 +25,6 @@
from xen.xend.XendError import VmError
from xen.xend.XendLogging import log

-from xen.xend.server import channel
-

xc = xen.lowlevel.xc.new()

@@ -168,11 +166,11 @@

def buildDomain(self):
if self.vm.store_channel:
- store_evtchn = self.vm.store_channel.port2
+ store_evtchn = self.vm.store_channel
else:
store_evtchn = 0
if self.vm.console_channel:
- console_evtchn = self.vm.console_channel.port2
+ console_evtchn = self.vm.console_channel
else:
console_evtchn = 0

@@ -228,16 +226,17 @@

def buildDomain(self):
# Create an event channel
- self.device_channel = channel.eventChannel(0, self.vm.getDomid())
- log.info("VMX device model port: %d", self.device_channel.port2)
+ self.device_channel = xc.evtchn_alloc_unbound(dom=self.vm.getDomid(),
+ remote_dom=0)
+ log.info("VMX device model port: %d", self.device_channel)
if self.vm.store_channel:
- store_evtchn = self.vm.store_channel.port2
+ store_evtchn = self.vm.store_channel
else:
store_evtchn = 0

log.debug("dom = %d", self.vm.getDomid())
log.debug("image = %s", self.kernel)
- log.debug("control_evtchn = %d", self.device_channel.port2)
+ log.debug("control_evtchn = %d", self.device_channel)
log.debug("store_evtchn = %d", store_evtchn)
log.debug("memsize = %d", self.vm.getMemoryTarget() / 1024)
log.debug("flags = %d", self.flags)
@@ -245,7 +244,7 @@

ret = xc.vmx_build(dom = self.vm.getDomid(),
image = self.kernel,
- control_evtchn = self.device_channel.port2,
+ control_evtchn = self.device_channel,
store_evtchn = store_evtchn,
memsize = self.vm.getMemoryTarget() / 1024,
flags = self.flags,
@@ -334,7 +333,7 @@
if len(vnc):
args = args + vnc
args = args + ([. "-d", "%d" % self.vm.getDomid(),
- "-p", "%d" % self.device_channel.port1,
+ "-p", "%d" % self.device_channel,
"-m", "%s" % (self.vm.getMemoryTarget() / 1024)])
args = args + self.dmargs
env = dict(os.environ)
@@ -358,8 +357,6 @@
return vncconnect

def destroy(self):
- if self.device_channel:
- self.device_channel.close()
import signal
if not self.pid:
return
diff -r f5320ac7ed31 -r 62190db89326 tools/xenstore/Makefile
--- a/tools/xenstore/Makefile Thu Oct 6 18:41:29 2005
+++ b/tools/xenstore/Makefile Thu Oct 6 18:43:11 2005
@@ -29,7 +29,7 @@

all: libxenstore.so xenstored $(CLIENTS) xs_tdb_dump

-testcode: xs_test xenstored_test xs_random xs_dom0_test
+testcode: xs_test xenstored_test xs_random

xenstored: xenstored_core.o xenstored_watch.o xenstored_domain.o xenstored_transaction.o xs_lib.o talloc.o utils.o tdb.o
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -lxenctrl -o $@
@@ -74,7 +74,7 @@
clean: testsuite-clean
rm -f *.o *.opic *.so
rm -f xenstored xs_random xs_stress xs_crashme
- rm -f xs_test xenstored_test xs_dom0_test
+ rm -f xs_test xenstored_test
$(RM) $(PROG_DEP)

print-dir:
@@ -120,9 +120,6 @@
rm -rf $(TESTDIR)/store $(TESTDIR)/transactions
export $(TESTENV); PID=`./xenstored_test --output-pid --trace-file=/tmp/trace`; ./xs_stress 5000; ret=$$?; kill $$PID; exit $$ret

-xs_dom0_test: xs_dom0_test.o utils.o
- $(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -lxenctrl -o $@
-
TAGS:
etags `find . -name '*.[ch]'`

diff -r f5320ac7ed31 -r 62190db89326 tools/xenstore/fake_libxc.c
--- a/tools/xenstore/fake_libxc.c Thu Oct 6 18:41:29 2005
+++ b/tools/xenstore/fake_libxc.c Thu Oct 6 18:43:11 2005
@@ -36,12 +36,11 @@
static u16 port;

/* The event channel maps to a signal, shared page to an mmapped file. */
-int xc_evtchn_send(int xc_handle __attribute__((unused)), int local_port)
+void evtchn_notify(int local_port)
{
assert(local_port == port);
if (kill(xs_test_pid, SIGUSR2) != 0)
barf_perror("fake event channel failed");
- return 0;
}

void *xc_map_foreign_range(int xc_handle, u32 dom __attribute__((unused)),
@@ -107,15 +106,6 @@
return 1;
}

-int xc_evtchn_bind_virq(int xc_handle __attribute__((unused)),
- int virq __attribute__((unused)),
- int *port)
-{
- if (port)
- *port = 0;
- return 0;
-}
-
static void send_to_fd(int signo __attribute__((unused)))
{
int saved_errno = errno;
diff -r f5320ac7ed31 -r 62190db89326 tools/xenstore/xenstored_core.c
--- a/tools/xenstore/xenstored_core.c Thu Oct 6 18:41:29 2005
+++ b/tools/xenstore/xenstored_core.c Thu Oct 6 18:43:11 2005
@@ -51,6 +51,8 @@
#include "xenstored_domain.h"
#include "xenctrl.h"
#include "tdb.h"
+
+int event_fd;

static bool verbose;
LIST_HEAD(connections);
@@ -309,8 +311,7 @@
return 0;
}

-static int initialize_set(fd_set *inset, fd_set *outset, int sock, int ro_sock,
- int event_fd)
+static int initialize_set(fd_set *inset, fd_set *outset, int sock, int ro_sock)
{
struct connection *i;
int max;
@@ -1464,7 +1465,7 @@

int main(int argc, char *argv[])
{
- int opt, *sock, *ro_sock, event_fd, max;
+ int opt, *sock, *ro_sock, max;
struct sockaddr_un addr;
fd_set inset, outset;
bool dofork = true;
@@ -1568,7 +1569,7 @@
#endif

/* Get ready to listen to the tools. */
- max = initialize_set(&inset, &outset, *sock, *ro_sock, event_fd);
+ max = initialize_set(&inset, &outset, *sock, *ro_sock);

/* Main loop. */
/* FIXME: Rewrite so noone can starve. */
@@ -1588,7 +1589,7 @@
accept_connection(*ro_sock, false);

if (FD_ISSET(event_fd, &inset))
- handle_event(event_fd);
+ handle_event();

list_for_each_entry(i, &connections, list) {
if (i->domain)
@@ -1624,7 +1625,6 @@
}
}

- max = initialize_set(&inset, &outset, *sock, *ro_sock,
- event_fd);
- }
-}
+ max = initialize_set(&inset, &outset, *sock, *ro_sock);
+ }
+}
diff -r f5320ac7ed31 -r 62190db89326 tools/xenstore/xenstored_core.h
--- a/tools/xenstore/xenstored_core.h Thu Oct 6 18:41:29 2005
+++ b/tools/xenstore/xenstored_core.h Thu Oct 6 18:43:11 2005
@@ -173,4 +173,6 @@
void trace_watch_timeout(const struct connection *conn, const char *node, const char *token);
void trace(const char *fmt, ...);

+extern int event_fd;
+
#endif /* _XENSTORED_CORE_H */
diff -r f5320ac7ed31 -r 62190db89326 tools/xenstore/xenstored_domain.c
--- a/tools/xenstore/xenstored_domain.c Thu Oct 6 18:41:29 2005
+++ b/tools/xenstore/xenstored_domain.c Thu Oct 6 18:43:11 2005
@@ -36,6 +36,8 @@
#include "xenstored_watch.h"
#include "xenstored_test.h"

+#include <xen/linux/evtchn.h>
+
static int *xc_handle;
static int eventchn_fd;
static int virq_port;
@@ -77,8 +79,16 @@
char buf[0];
} __attribute__((packed));

-#define EVENTCHN_BIND _IO('E', 2)
-#define EVENTCHN_UNBIND _IO('E', 3)
+#ifndef TESTING
+static void evtchn_notify(int port)
+{
+ struct ioctl_evtchn_notify notify;
+ notify.port = port;
+ (void)ioctl(event_fd, IOCTL_EVTCHN_NOTIFY, &notify);
+}
+#else
+extern void evtchn_notify(int port);
+#endif

/* FIXME: Mark connection as broken (close it?) when this happens. */
static bool check_buffer(const struct ringbuf_head *h)
@@ -165,9 +175,7 @@
memcpy(dest, data, len);
mb();
update_output_chunk(conn->domain->output, len);
- /* FIXME: Probably not neccessary. */
- mb();
- xc_evtchn_send(*xc_handle, conn->domain->port);
+ evtchn_notify(conn->domain->port);
return len;
}

@@ -200,21 +208,24 @@

/* If it was full, tell them we've taken some. */
if (was_full)
- xc_evtchn_send(*xc_handle, conn->domain->port);
+ evtchn_notify(conn->domain->port);
return len;
}

static int destroy_domain(void *_domain)
{
struct domain *domain = _domain;
+ struct ioctl_evtchn_unbind unbind;

list_del(&domain->list);

- if (domain->port &&
- (ioctl(eventchn_fd, EVENTCHN_UNBIND, domain->port) != 0))
- eprintf("> Unbinding port %i failed!\n", domain->port);
-
- if(domain->page)
+ if (domain->port) {
+ unbind.port = domain->port;
+ if (ioctl(eventchn_fd, IOCTL_EVTCHN_UNBIND, &unbind) == -1)
+ eprintf("> Unbinding port %i failed!\n", domain->port);
+ }
+
+ if (domain->page)
munmap(domain->page, getpagesize());

return 0;
@@ -247,7 +258,7 @@
}

/* We scan all domains rather than use the information given here. */
-void handle_event(int event_fd)
+void handle_event(void)
{
u16 port;

@@ -278,6 +289,9 @@
const char *path)
{
struct domain *domain;
+ struct ioctl_evtchn_bind_interdomain bind;
+ int rc;
+
domain = talloc(context, struct domain);
domain->port = 0;
domain->shutdown = 0;
@@ -298,10 +312,13 @@
domain->output = domain->page + getpagesize()/2;

/* Tell kernel we're interested in this event. */
- if (ioctl(eventchn_fd, EVENTCHN_BIND, port) != 0)
+ bind.remote_domain = domid;
+ bind.remote_port = port;
+ rc = ioctl(eventchn_fd, IOCTL_EVTCHN_BIND_INTERDOMAIN, &bind);
+ if (rc == -1)
return NULL;

- domain->port = port;
+ domain->port = rc;
domain->conn = new_connection(writechn, readchn);
domain->conn->domain = domain;
return domain;
@@ -445,6 +462,8 @@
int domain_init(void)
{
struct stat st;
+ struct ioctl_evtchn_bind_virq bind;
+ int rc;

/* The size of the ringbuffer: half a page minus head structure. */
ringbuf_datasize = getpagesize() / 2 - sizeof(struct ringbuf_head);
@@ -482,11 +501,11 @@
if (eventchn_fd < 0)
barf_perror("Failed to open evtchn device");

- if (xc_evtchn_bind_virq(*xc_handle, VIRQ_DOM_EXC, &virq_port))
- barf_perror("Failed to bind to domain exception virq");
-
- if (ioctl(eventchn_fd, EVENTCHN_BIND, virq_port) != 0)
+ bind.virq = VIRQ_DOM_EXC;
+ rc = ioctl(eventchn_fd, IOCTL_EVTCHN_BIND_VIRQ, &bind);
+ if (rc == -1)
barf_perror("Failed to bind to domain exception virq port");
+ virq_port = rc;

return eventchn_fd;
}
diff -r f5320ac7ed31 -r 62190db89326 tools/xenstore/xenstored_domain.h
--- a/tools/xenstore/xenstored_domain.h Thu Oct 6 18:41:29 2005
+++ b/tools/xenstore/xenstored_domain.h Thu Oct 6 18:43:11 2005
@@ -20,7 +20,7 @@
#ifndef _XENSTORED_DOMAIN_H
#define _XENSTORED_DOMAIN_H

-void handle_event(int event_fd);
+void handle_event(void);

/* domid, mfn, eventchn, path */
void do_introduce(struct connection *conn, struct buffered_data *in);
diff -r f5320ac7ed31 -r 62190db89326 xen/common/event_channel.c
--- a/xen/common/event_channel.c Thu Oct 6 18:41:29 2005
+++ b/xen/common/event_channel.c Thu Oct 6 18:43:11 2005
@@ -36,7 +36,13 @@
#define evtchn_from_port(d,p) \
(&(bucket_from_port(d,p))[(p)&(EVTCHNS_PER_BUCKET-1)])

-#define ERROR_EXIT(_errno) do { rc = (_errno); goto out; } while ( 0 )
+#define ERROR_EXIT(_errno) \
+ do { \
+ DPRINTK("EVTCHNOP failure: domain %d, error %d, line %d\n", \
+ current->domain->domain_id, (_errno), __LINE__); \
+ rc = (_errno); \
+ goto out; \
+ } while ( 0 )

static int get_free_port(struct domain *d)
{
diff -r f5320ac7ed31 -r 62190db89326 linux-2.6-xen-sparse/include/asm-xen/linux-public/evtchn.h
--- /dev/null Thu Oct 6 18:41:29 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/linux-public/evtchn.h Thu Oct 6 18:43:11 2005
@@ -0,0 +1,98 @@
+/******************************************************************************
+ * evtchn.h
+ *
+ * Interface to /dev/xen/evtchn.
+ *
+ * Copyright (c) 2003-2005, K A Fraser
+ *
+ * This file may be distributed separately from the Linux kernel, or
+ * incorporated into other software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef __LINUX_PUBLIC_EVTCHN_H__
+#define __LINUX_PUBLIC_EVTCHN_H__
+
+/* /dev/xen/evtchn resides at device number major=10, minor=201 */
+#define EVTCHN_MINOR 201
+
+/*
+ * Bind a fresh port to VIRQ @virq.
+ * Return allocated port.
+ */
+#define IOCTL_EVTCHN_BIND_VIRQ \
+ _IOC(_IOC_NONE, 'E', 0, sizeof(struct ioctl_evtchn_bind_virq))
+struct ioctl_evtchn_bind_virq {
+ unsigned int virq;
+};
+
+/*
+ * Bind a fresh port to remote <@remote_domain, @remote_port>.
+ * Return allocated port.
+ */
+#define IOCTL_EVTCHN_BIND_INTERDOMAIN \
+ _IOC(_IOC_NONE, 'E', 1, sizeof(struct ioctl_evtchn_bind_interdomain))
+struct ioctl_evtchn_bind_interdomain {
+ unsigned int remote_domain, remote_port;
+};
+
+/*
+ * Allocate a fresh port for binding to @remote_domain.
+ * Return allocated port.
+ */
+#define IOCTL_EVTCHN_BIND_UNBOUND_PORT \
+ _IOC(_IOC_NONE, 'E', 2, sizeof(struct ioctl_evtchn_bind_unbound_port))
+struct ioctl_evtchn_bind_unbound_port {
+ unsigned int remote_domain;
+};
+
+/*
+ * Unbind previously allocated @port.
+ */
+#define IOCTL_EVTCHN_UNBIND \
+ _IOC(_IOC_NONE, 'E', 3, sizeof(struct ioctl_evtchn_unbind))
+struct ioctl_evtchn_unbind {
+ unsigned int port;
+};
+
+/*
+ * Unbind previously allocated @port.
+ */
+#define IOCTL_EVTCHN_NOTIFY \
+ _IOC(_IOC_NONE, 'E', 4, sizeof(struct ioctl_evtchn_notify))
+struct ioctl_evtchn_notify {
+ unsigned int port;
+};
+
+/* Clear and reinitialise the event buffer. Clear error condition. */
+#define IOCTL_EVTCHN_RESET \
+ _IOC(_IOC_NONE, 'E', 5, 0)
+
+#endif /* __LINUX_PUBLIC_EVTCHN_H__ */
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r f5320ac7ed31 -r 62190db89326 tools/python/xen/xend/server/channel.py
--- a/tools/python/xen/xend/server/channel.py Thu Oct 6 18:41:29 2005
+++ /dev/null Thu Oct 6 18:43:11 2005
@@ -1,76 +0,0 @@
-#============================================================================
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of version 2.1 of the GNU Lesser General Public
-# License as published by the Free Software Foundation.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#============================================================================
-# Copyright (C) 2004, 2005 Mike Wray <mike.wray@hp.com>
-# Copyright (C) 2005 XenSource Ltd
-#============================================================================
-
-import xen.lowlevel.xc
-
-from xen.xend.XendLogging import log
-
-
-xc = xen.lowlevel.xc.new()
-
-
-class EventChannel:
- """An event channel between domains.
- """
-
- def __init__(self, dom1, dom2, port1, port2):
- self.dom1 = dom1
- self.dom2 = dom2
- self.port1 = port1
- self.port2 = port2
-
-
- def close(self):
- """Close the event channel. Nothrow guarantee.
- """
- def evtchn_close(dom, port):
- try:
- xc.evtchn_close(dom=dom, port=port)
- except Exception:
- log.exception("Exception closing event channel %d, %d.", dom,
- port)
-
- evtchn_close(self.dom1, self.port1)
- evtchn_close(self.dom2, self.port2)
-
-
- def sxpr(self):
- return ['event-channel',
- ['dom1', self.dom1 ],
- ['port1', self.port1 ],
- ['dom2', self.dom2 ],
- ['port2', self.port2 ]
- ]
-
-
- def __repr__(self):
- return ("<EventChannel dom1:%d:%d dom2:%d:%d>"
- % (self.dom1, self.port1, self.dom2, self.port2))
-
-
-def eventChannel(dom1, dom2, port1 = 0, port2 = 0):
- """Create an event channel between domains.
-
- @return EventChannel (None on error)
- """
- v = xc.evtchn_bind_interdomain(dom1=dom1, dom2=dom2,
- port1=port1, port2=port2)
- if v and v.get('port1'):
- return EventChannel(dom1, dom2, v['port1'], v['port2'])
- else:
- return None
diff -r f5320ac7ed31 -r 62190db89326 tools/xenstore/xs_dom0_test.c
--- a/tools/xenstore/xs_dom0_test.c Thu Oct 6 18:41:29 2005
+++ /dev/null Thu Oct 6 18:43:11 2005
@@ -1,43 +0,0 @@
-/* Test introduction of domain 0 */
-#include <linux/ioctl.h>
-#include <sys/ioctl.h>
-#include "xs.h"
-#include "utils.h"
-#include <xenctrl.h>
-#include <xen/linux/privcmd.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <sys/mman.h>
-
-int main()
-{
- int h, local = 0, kernel = 0;
- long err;
- void *page;
-
- h = xc_interface_open();
- if (h < 0)
- barf_perror("Failed to open xc");
-
- if (xc_evtchn_bind_interdomain(h, DOMID_SELF, 0, &local, &kernel) != 0)
- barf_perror("Failed to bind interdomain");
-
- printf("Got ports %i & %i\n", local, kernel);
-
- err = ioctl(h, IOCTL_PRIVCMD_INITDOMAIN_STORE, kernel);
- if (err < 0)
- barf_perror("Failed to initialize store");
- printf("Got mfn %li\n", err);
-
- page = xc_map_foreign_range(h, 0, getpagesize(), PROT_READ|PROT_WRITE,
- err);
- if (!page)
- barf_perror("Failed to map page %li", err);
- printf("Mapped page at %p\n", page);
- printf("Page says %s\n", (char *)page);
- munmap(page, getpagesize());
- printf("unmapped\n");
-
- return 0;
-}
-

_______________________________________________
Xen-changelog mailing list
Xen-changelog@lists.xensource.com
http://lists.xensource.com/xen-changelog
Merged. [ In reply to ]
# HG changeset patch
# User emellor@ewan
# Node ID e9e10e783ccd7f7dfaf5443fcdaf8394c5c2a65e
# Parent b5c5360a61d01912ccd71c0d07b03d424024d14f
# Parent 99532f6b2ae37ed5bf103e07b1e2bf7c29e5ce1d
Merged.

diff -r b5c5360a61d0 -r e9e10e783ccd linux-2.6-xen-sparse/arch/ia64/xen/drivers/evtchn_ia64.c
--- a/linux-2.6-xen-sparse/arch/ia64/xen/drivers/evtchn_ia64.c Fri Oct 7 12:34:10 2005
+++ b/linux-2.6-xen-sparse/arch/ia64/xen/drivers/evtchn_ia64.c Fri Oct 7 12:34:45 2005
@@ -65,12 +65,6 @@

mask_evtchn(evtchn);
evtchns[evtchn].handler = NULL;
-}
-
-void unbind_evtchn_from_irq(unsigned int evtchn)
-{
- printk("unbind_evtchn_from_irq called... FIXME??\n");
- while(1);
}

irqreturn_t evtchn_interrupt(int irq, void *dev_id, struct pt_regs *regs)
diff -r b5c5360a61d0 -r e9e10e783ccd linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c
--- a/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c Fri Oct 7 12:34:10 2005
+++ b/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c Fri Oct 7 12:34:45 2005
@@ -296,7 +296,7 @@
}
EXPORT_SYMBOL(unbind_ipi_from_irq);

-int bind_evtchn_to_irq(unsigned int evtchn)
+static int bind_evtchn_to_irq(unsigned int evtchn)
{
int irq;

@@ -314,9 +314,8 @@

return irq;
}
-EXPORT_SYMBOL(bind_evtchn_to_irq);
-
-void unbind_evtchn_from_irq(unsigned int irq)
+
+static void unbind_evtchn_from_irq(unsigned int irq)
{
evtchn_op_t op = { .cmd = EVTCHNOP_close };
int evtchn = irq_to_evtchn[irq];
@@ -333,7 +332,6 @@

spin_unlock(&irq_mapping_update_lock);
}
-EXPORT_SYMBOL(unbind_evtchn_from_irq);

int bind_evtchn_to_irqhandler(
unsigned int evtchn,
@@ -347,8 +345,10 @@

irq = bind_evtchn_to_irq(evtchn);
retval = request_irq(irq, handler, irqflags, devname, dev_id);
- if (retval != 0)
+ if (retval != 0) {
unbind_evtchn_from_irq(irq);
+ return retval;
+ }

return irq;
}
diff -r b5c5360a61d0 -r e9e10e783ccd linux-2.6-xen-sparse/drivers/xen/blkback/interface.c
--- a/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c Fri Oct 7 12:34:10 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c Fri Oct 7 12:34:45 2005
@@ -74,6 +74,10 @@
.u.bind_interdomain.remote_dom = blkif->domid,
.u.bind_interdomain.remote_port = evtchn };

+ /* Already connected through? */
+ if (blkif->irq)
+ return 0;
+
if ( (blkif->blk_ring_area = alloc_vm_area(PAGE_SIZE)) == NULL )
return -ENOMEM;

@@ -107,8 +111,12 @@
{
blkif_t *blkif = (blkif_t *)arg;

- if (blkif->irq)
- unbind_evtchn_from_irqhandler(blkif->irq, blkif);
+ /* Already disconnected? */
+ if (!blkif->irq)
+ return;
+
+ unbind_evtchn_from_irqhandler(blkif->irq, blkif);
+ blkif->irq = 0;

vbd_free(&blkif->vbd);

diff -r b5c5360a61d0 -r e9e10e783ccd linux-2.6-xen-sparse/drivers/xen/netback/interface.c
--- a/linux-2.6-xen-sparse/drivers/xen/netback/interface.c Fri Oct 7 12:34:10 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/interface.c Fri Oct 7 12:34:45 2005
@@ -183,6 +183,10 @@
.u.bind_interdomain.remote_dom = netif->domid,
.u.bind_interdomain.remote_port = evtchn };

+ /* Already connected through? */
+ if (netif->irq)
+ return 0;
+
netif->comms_area = alloc_vm_area(2*PAGE_SIZE);
if (netif->comms_area == NULL)
return -ENOMEM;
@@ -227,13 +231,12 @@
{
netif_t *netif = (netif_t *)arg;

- /*
- * This can't be done in netif_disconnect() because at that point
- * there may be outstanding requests in the network stack whose
- * asynchronous responses must still be notified to the remote driver.
- */
- if (netif->irq)
- unbind_evtchn_from_irqhandler(netif->irq, netif);
+ /* Already disconnected? */
+ if (!netif->irq)
+ return;
+
+ unbind_evtchn_from_irqhandler(netif->irq, netif);
+ netif->irq = 0;

unregister_netdev(netif->dev);

diff -r b5c5360a61d0 -r e9e10e783ccd linux-2.6-xen-sparse/include/asm-xen/evtchn.h
--- a/linux-2.6-xen-sparse/include/asm-xen/evtchn.h Fri Oct 7 12:34:10 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/evtchn.h Fri Oct 7 12:34:45 2005
@@ -50,14 +50,6 @@
/* Dynamically bind an IPI source to Linux IRQ space. */
extern int bind_ipi_to_irq(int ipi);
extern void unbind_ipi_from_irq(int ipi);
-
-/*
- * Dynamically bind an event-channel port to Linux IRQ space.
- * BIND: Returns IRQ or error.
- * UNBIND: Takes IRQ to unbind from; automatically closes the event channel.
- */
-extern int bind_evtchn_to_irq(unsigned int evtchn);
-extern void unbind_evtchn_from_irq(unsigned int irq);

/*
* Dynamically bind an event-channel port to an IRQ-like callback handler.
diff -r b5c5360a61d0 -r e9e10e783ccd tools/examples/Makefile
--- a/tools/examples/Makefile Fri Oct 7 12:34:10 2005
+++ b/tools/examples/Makefile Fri Oct 7 12:34:45 2005
@@ -22,8 +22,7 @@
XEN_SCRIPTS = network-bridge vif-bridge
XEN_SCRIPTS += network-route vif-route
XEN_SCRIPTS += network-nat vif-nat
-XEN_SCRIPTS += block-phy
-XEN_SCRIPTS += block-file
+XEN_SCRIPTS += block
XEN_SCRIPTS += block-enbd

XEN_HOTPLUG_DIR = /etc/hotplug
diff -r b5c5360a61d0 -r e9e10e783ccd tools/examples/vif-bridge
--- a/tools/examples/vif-bridge Fri Oct 7 12:34:10 2005
+++ b/tools/examples/vif-bridge Fri Oct 7 12:34:45 2005
@@ -33,6 +33,7 @@

# Exit if anything goes wrong
set -e
+export PATH=/sbin:/bin:/usr/bin:/usr/sbin:$PATH

echo "*vif-bridge $*" >&2

diff -r b5c5360a61d0 -r e9e10e783ccd tools/examples/vif-nat
--- a/tools/examples/vif-nat Fri Oct 7 12:34:10 2005
+++ b/tools/examples/vif-nat Fri Oct 7 12:34:45 2005
@@ -22,7 +22,7 @@

# Exit if anything goes wrong
set -e
-
+export PATH=/sbin:/bin:/usr/bin:/usr/sbin:$PATH
echo "*vif-nat $*" >&2

# Operation name.
diff -r b5c5360a61d0 -r e9e10e783ccd tools/examples/vif-route
--- a/tools/examples/vif-route Fri Oct 7 12:34:10 2005
+++ b/tools/examples/vif-route Fri Oct 7 12:34:45 2005
@@ -23,7 +23,7 @@

# Exit if anything goes wrong
set -e
-
+export PATH=/sbin:/bin:/usr/bin:/usr/sbin:$PATH
echo "*vif-route $*" >&2

# Operation name.
diff -r b5c5360a61d0 -r e9e10e783ccd tools/examples/xen-backend.agent
--- a/tools/examples/xen-backend.agent Fri Oct 7 12:34:10 2005
+++ b/tools/examples/xen-backend.agent Fri Oct 7 12:34:45 2005
@@ -11,20 +11,14 @@
add)
case "$XENBUS_TYPE" in
vbd)
- t=$(xenstore-read "$XENBUS_PATH"/type)
- params=$(xenstore-read "$XENBUS_PATH"/params)
- [ -x /etc/xen/scripts/block-"$t" ] && \
- /etc/xen/scripts/block-"$t" bind $params
+ /etc/xen/scripts/block bind
;;
esac
;;
remove)
case "$XENBUS_TYPE" in
vbd)
- t=$(xenstore-read "$XENBUS_PATH"/type)
- node=$(xenstore-read "$XENBUS_PATH"/node)
- [ -x /etc/xen/scripts/block-"$t" ] && \
- /etc/xen/scripts/block-"$t" unbind $node
+ /etc/xen/scripts/block unbind
;;
esac
# remove device backend store entries
diff -r b5c5360a61d0 -r e9e10e783ccd tools/examples/block
--- /dev/null Fri Oct 7 12:34:10 2005
+++ b/tools/examples/block Fri Oct 7 12:34:45 2005
@@ -0,0 +1,82 @@
+#!/bin/sh
+
+set -e
+
+export PATH=/sbin:/bin:/usr/bin:/usr/sbin:$PATH
+
+expand_dev() {
+ local dev
+ case $1 in
+ /*)
+ dev=$1
+ ;;
+ *)
+ dev=/dev/$1
+ ;;
+ esac
+ echo -n $dev
+}
+
+write_dev() {
+ local major
+ local minor
+ local pdev
+
+ major=$(stat -L -c %t "$1")
+ minor=$(stat -L -c %T "$1")
+ pdev=$(printf "0x%02x%02x" 0x$major 0x$minor)
+ xenstore-write "$XENBUS_PATH"/physical-device $pdev \
+ "$XENBUS_PATH"/node $1
+}
+
+t=$(xenstore-read "$XENBUS_PATH"/type)
+
+case $1 in
+ bind)
+ p=$(xenstore-read "$XENBUS_PATH"/params)
+ case $t in
+ phy)
+ dev=$(expand_dev $p)
+ write_dev "$dev"
+ exit 0
+ ;;
+
+ file)
+ for dev in /dev/loop* ; do
+ echo "dev is $dev, p is $p"
+ if losetup $dev $p; then
+ write_dev "$dev"
+ exit 0
+ fi
+ done
+ exit 1
+ ;;
+
+ *)
+ [ -x /etc/xen/scripts/block-"$t" ] && \
+ /etc/xen/scripts/block-"$t" bind $p
+ ;;
+ esac
+ ;;
+
+ unbind)
+ node=$(xenstore-read "$XENBUS_PATH"/node)
+ case $t in
+ phy)
+ exit 0
+ ;;
+
+ file)
+ losetup -d $node
+ exit 0
+ ;;
+
+ *)
+ [ -x /etc/xen/scripts/block-"$t" ] && \
+ /etc/xen/scripts/block-"$t" unbind $node
+ ;;
+
+ esac
+ ;;
+
+esac
diff -r b5c5360a61d0 -r e9e10e783ccd tools/examples/xen-backend.rules
--- /dev/null Fri Oct 7 12:34:10 2005
+++ b/tools/examples/xen-backend.rules Fri Oct 7 12:34:45 2005
@@ -0,0 +1,4 @@
+SUBSYSTEM=="xen-backend", KERNEL=="vbd*", ACTION=="add", RUN+="/etc/xen/scripts/block bind"
+SUBSYSTEM=="xen-backend", KERNEL=="vbd*", ACTION=="remove", RUN+="/etc/xen/scripts/block unbind"
+SUBSYSTEM=="xen-backend", KERNEL=="vif*", ENV{PHYSDEVDRIVER}=="vif", ACTION=="online", RUN+="$env{script} up"
+SUBSYSTEM=="xen-backend", ACTION=="remove", RUN+="/usr/bin/xenstore-rm $env{XENBUS_PATH}"
diff -r b5c5360a61d0 -r e9e10e783ccd tools/examples/block-file
--- a/tools/examples/block-file Fri Oct 7 12:34:10 2005
+++ /dev/null Fri Oct 7 12:34:45 2005
@@ -1,31 +0,0 @@
-#!/bin/sh
-
-# Usage: block_loop [bind file|unbind node]
-#
-# The file argument to the bind command is the file we are to bind to a
-# loop device.
-#
-# The node argument to unbind is the name of the device node we are to
-# unbind.
-
-set -e
-
-case $1 in
- bind)
- for dev in /dev/loop*; do
- if losetup $dev $2; then
- major=$(stat -L -c %t "$dev")
- minor=$(stat -L -c %T "$dev")
- pdev=$(printf "0x%02x%02x" 0x$major 0x$minor)
- xenstore-write "$XENBUS_PATH"/physical-device $pdev \
- "$XENBUS_PATH"/node $dev
- exit 0
- fi
- done
- exit 1
- ;;
- unbind)
- losetup -d $2
- exit 0
- ;;
-esac
diff -r b5c5360a61d0 -r e9e10e783ccd tools/examples/block-phy
--- a/tools/examples/block-phy Fri Oct 7 12:34:10 2005
+++ /dev/null Fri Oct 7 12:34:45 2005
@@ -1,30 +0,0 @@
-#! /bin/sh
-
-set -e
-
-expand_dev() {
- local dev
- case $1 in
- /*)
- dev=$1
- ;;
- *)
- dev=/dev/$1
- ;;
- esac
- echo -n $dev
-}
-
-case $1 in
- bind)
- dev=$(expand_dev $2)
- major=$(stat -L -c %t "$dev")
- minor=$(stat -L -c %T "$dev")
- pdev=$(printf "0x%02x%02x" 0x$major 0x$minor)
- xenstore-write "$XENBUS_PATH"/physical-device $pdev \
- "$XENBUS_PATH"/node $dev
- exit 0
- ;;
- unbind)
- ;;
-esac

_______________________________________________
Xen-changelog mailing list
Xen-changelog@lists.xensource.com
http://lists.xensource.com/xen-changelog
Merged. [ In reply to ]
# HG changeset patch
# User emellor@ewan
# Node ID 1ac39c7a043541cfa94655f0e9ab98d4503c29a2
# Parent 0e7c48861e95b738fdf96d4a4df6b0ba90a8423d
# Parent b7dce4fe2488bf354e5718a84fdb82bed3919761
Merged.

diff -r 0e7c48861e95 -r 1ac39c7a0435 linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c Mon Oct 10 13:42:38 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c Mon Oct 10 13:46:53 2005
@@ -1327,18 +1327,14 @@
.callback = handle_vcpu_hotplug_event
};

-/* NB: Assumes xenbus_lock is held! */
static int setup_cpu_watcher(struct notifier_block *notifier,
unsigned long event, void *data)
{
- int err = 0;
-
- BUG_ON(down_trylock(&xenbus_lock) == 0);
+ int err;
+
err = register_xenbus_watch(&cpu_watch);
-
- if (err) {
+ if (err)
printk("Failed to register watch on /cpu\n");
- }

return NOTIFY_DONE;
}
@@ -1368,7 +1364,7 @@
return;

/* get the state value */
- err = xenbus_scanf(dir, "availability", "%s", state);
+ err = xenbus_scanf(NULL, dir, "availability", "%s", state);

if (err != 1) {
printk(KERN_ERR
@@ -1578,7 +1574,7 @@
void smp_resume(void)
{
smp_intr_init();
- local_setup_timer_irq();
+ local_setup_timer();
}

void vcpu_prepare(int vcpu)
diff -r 0e7c48861e95 -r 1ac39c7a0435 linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c Mon Oct 10 13:42:38 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c Mon Oct 10 13:46:53 2005
@@ -122,7 +122,7 @@
static u64 processed_system_time; /* System time (ns) at last processing. */
static DEFINE_PER_CPU(u64, processed_system_time);

-#define NS_PER_TICK (1000000000L/HZ)
+#define NS_PER_TICK (1000000000ULL/HZ)

static inline void __normalize_time(time_t *sec, s64 *nsec)
{
@@ -800,9 +800,9 @@
delta = j - jiffies;
/* NB. The next check can trigger in some wrap-around cases,
* but that's ok: we'll just end up with a shorter timeout. */
- if (delta < 1)
+ if (delta < 1)
delta = 1;
- st = processed_system_time + (delta * NS_PER_TICK);
+ st = processed_system_time + ((u64)delta * NS_PER_TICK);
} while (read_seqretry(&xtime_lock, seq));

return st;
@@ -816,7 +816,7 @@
{
unsigned int cpu = smp_processor_id();
unsigned long j;
-
+
/* s390 does this /before/ checking rcu_pending(). We copy them. */
cpu_set(cpu, nohz_cpu_mask);

diff -r 0e7c48861e95 -r 1ac39c7a0435 linux-2.6-xen-sparse/arch/xen/kernel/reboot.c
--- a/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c Mon Oct 10 13:42:38 2005
+++ b/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c Mon Oct 10 13:46:53 2005
@@ -275,22 +275,23 @@
{
static DECLARE_WORK(shutdown_work, __shutdown_handler, NULL);
char *str;
+ struct xenbus_transaction *xbt;
int err;

again:
- err = xenbus_transaction_start();
- if (err)
+ xbt = xenbus_transaction_start();
+ if (IS_ERR(xbt))
return;
- str = (char *)xenbus_read("control", "shutdown", NULL);
+ str = (char *)xenbus_read(xbt, "control", "shutdown", NULL);
/* Ignore read errors and empty reads. */
if (XENBUS_IS_ERR_READ(str)) {
- xenbus_transaction_end(1);
+ xenbus_transaction_end(xbt, 1);
return;
}

- xenbus_write("control", "shutdown", "");
-
- err = xenbus_transaction_end(0);
+ xenbus_write(xbt, "control", "shutdown", "");
+
+ err = xenbus_transaction_end(xbt, 0);
if (err == -EAGAIN) {
kfree(str);
goto again;
@@ -320,23 +321,24 @@
unsigned int len)
{
char sysrq_key = '\0';
+ struct xenbus_transaction *xbt;
int err;

again:
- err = xenbus_transaction_start();
- if (err)
+ xbt = xenbus_transaction_start();
+ if (IS_ERR(xbt))
return;
- if (!xenbus_scanf("control", "sysrq", "%c", &sysrq_key)) {
+ if (!xenbus_scanf(xbt, "control", "sysrq", "%c", &sysrq_key)) {
printk(KERN_ERR "Unable to read sysrq code in "
"control/sysrq\n");
- xenbus_transaction_end(1);
+ xenbus_transaction_end(xbt, 1);
return;
}

if (sysrq_key != '\0')
- xenbus_printf("control", "sysrq", "%c", '\0');
-
- err = xenbus_transaction_end(0);
+ xenbus_printf(xbt, "control", "sysrq", "%c", '\0');
+
+ err = xenbus_transaction_end(xbt, 0);
if (err == -EAGAIN)
goto again;

@@ -360,9 +362,6 @@

static struct notifier_block xenstore_notifier;

-/* Setup our watcher
- NB: Assumes xenbus_lock is held!
-*/
static int setup_shutdown_watcher(struct notifier_block *notifier,
unsigned long event,
void *data)
@@ -371,8 +370,6 @@
#ifdef CONFIG_MAGIC_SYSRQ
int err2 = 0;
#endif
-
- BUG_ON(down_trylock(&xenbus_lock) == 0);

err1 = register_xenbus_watch(&shutdown_watch);
#ifdef CONFIG_MAGIC_SYSRQ
diff -r 0e7c48861e95 -r 1ac39c7a0435 linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c
--- a/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c Mon Oct 10 13:42:38 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c Mon Oct 10 13:46:53 2005
@@ -357,7 +357,7 @@
unsigned long long new_target;
int err;

- err = xenbus_scanf("memory", "target", "%llu", &new_target);
+ err = xenbus_scanf(NULL, "memory", "target", "%llu", &new_target);
if (err != 1) {
printk(KERN_ERR "Unable to read memory/target\n");
return;
@@ -370,16 +370,11 @@

}

-/* Setup our watcher
- NB: Assumes xenbus_lock is held!
-*/
int balloon_init_watcher(struct notifier_block *notifier,
unsigned long event,
void *data)
{
int err;
-
- BUG_ON(down_trylock(&xenbus_lock) == 0);

err = register_xenbus_watch(&target_watch);
if (err)
diff -r 0e7c48861e95 -r 1ac39c7a0435 linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c
--- a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c Mon Oct 10 13:42:38 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c Mon Oct 10 13:46:53 2005
@@ -61,18 +61,19 @@
unsigned long ring_ref;
unsigned int evtchn;
int err;
+ struct xenbus_transaction *xbt;
struct backend_info *be
= container_of(watch, struct backend_info, watch);

/* If other end is gone, delete ourself. */
- if (vec && !xenbus_exists(be->frontpath, "")) {
+ if (vec && !xenbus_exists(NULL, be->frontpath, "")) {
device_unregister(&be->dev->dev);
return;
}
if (be->blkif == NULL || be->blkif->status == CONNECTED)
return;

- err = xenbus_gather(be->frontpath, "ring-ref", "%lu", &ring_ref,
+ err = xenbus_gather(NULL, be->frontpath, "ring-ref", "%lu", &ring_ref,
"event-channel", "%u", &evtchn, NULL);
if (err) {
xenbus_dev_error(be->dev, err,
@@ -84,7 +85,8 @@
/* Map the shared frame, irq etc. */
err = blkif_map(be->blkif, ring_ref, evtchn);
if (err) {
- xenbus_dev_error(be->dev, err, "mapping ring-ref %lu port %u",
+ xenbus_dev_error(be->dev, err,
+ "mapping ring-ref %lu port %u",
ring_ref, evtchn);
return;
}
@@ -92,13 +94,13 @@

again:
/* Supply the information about the device the frontend needs */
- err = xenbus_transaction_start();
- if (err) {
+ xbt = xenbus_transaction_start();
+ if (IS_ERR(xbt)) {
xenbus_dev_error(be->dev, err, "starting transaction");
return;
}

- err = xenbus_printf(be->dev->nodename, "sectors", "%lu",
+ err = xenbus_printf(xbt, be->dev->nodename, "sectors", "%lu",
vbd_size(&be->blkif->vbd));
if (err) {
xenbus_dev_error(be->dev, err, "writing %s/sectors",
@@ -107,14 +109,14 @@
}

/* FIXME: use a typename instead */
- err = xenbus_printf(be->dev->nodename, "info", "%u",
+ err = xenbus_printf(xbt, be->dev->nodename, "info", "%u",
vbd_info(&be->blkif->vbd));
if (err) {
xenbus_dev_error(be->dev, err, "writing %s/info",
be->dev->nodename);
goto abort;
}
- err = xenbus_printf(be->dev->nodename, "sector-size", "%lu",
+ err = xenbus_printf(xbt, be->dev->nodename, "sector-size", "%lu",
vbd_secsize(&be->blkif->vbd));
if (err) {
xenbus_dev_error(be->dev, err, "writing %s/sector-size",
@@ -122,7 +124,7 @@
goto abort;
}

- err = xenbus_transaction_end(0);
+ err = xenbus_transaction_end(xbt, 0);
if (err == -EAGAIN)
goto again;
if (err) {
@@ -136,7 +138,7 @@
return;

abort:
- xenbus_transaction_end(1);
+ xenbus_transaction_end(xbt, 1);
}

/*
@@ -154,7 +156,8 @@
= container_of(watch, struct backend_info, backend_watch);
struct xenbus_device *dev = be->dev;

- err = xenbus_scanf(dev->nodename, "physical-device", "%li", &pdev);
+ err = xenbus_scanf(NULL, dev->nodename,
+ "physical-device", "%li", &pdev);
if (XENBUS_EXIST_ERR(err))
return;
if (err < 0) {
@@ -169,7 +172,7 @@
be->pdev = pdev;

/* If there's a read-only node, we're read only. */
- p = xenbus_read(dev->nodename, "read-only", NULL);
+ p = xenbus_read(NULL, dev->nodename, "read-only", NULL);
if (!IS_ERR(p)) {
be->readonly = 1;
kfree(p);
@@ -184,7 +187,8 @@
if (IS_ERR(be->blkif)) {
err = PTR_ERR(be->blkif);
be->blkif = NULL;
- xenbus_dev_error(dev, err, "creating block interface");
+ xenbus_dev_error(dev, err,
+ "creating block interface");
return;
}

@@ -192,7 +196,8 @@
if (err) {
blkif_put(be->blkif);
be->blkif = NULL;
- xenbus_dev_error(dev, err, "creating vbd structure");
+ xenbus_dev_error(dev, err,
+ "creating vbd structure");
return;
}

@@ -210,13 +215,14 @@

be = kmalloc(sizeof(*be), GFP_KERNEL);
if (!be) {
- xenbus_dev_error(dev, -ENOMEM, "allocating backend structure");
+ xenbus_dev_error(dev, -ENOMEM,
+ "allocating backend structure");
return -ENOMEM;
}
memset(be, 0, sizeof(*be));

frontend = NULL;
- err = xenbus_gather(dev->nodename,
+ err = xenbus_gather(NULL, dev->nodename,
"frontend-id", "%li", &be->frontend_id,
"frontend", NULL, &frontend,
NULL);
@@ -228,7 +234,7 @@
dev->nodename);
goto free_be;
}
- if (strlen(frontend) == 0 || !xenbus_exists(frontend, "")) {
+ if (strlen(frontend) == 0 || !xenbus_exists(NULL, frontend, "")) {
/* If we can't get a frontend path and a frontend-id,
* then our bus-id is no longer valid and we need to
* destroy the backend device.
@@ -244,7 +250,8 @@
err = register_xenbus_watch(&be->backend_watch);
if (err) {
be->backend_watch.node = NULL;
- xenbus_dev_error(dev, err, "adding backend watch on %s",
+ xenbus_dev_error(dev, err,
+ "adding backend watch on %s",
dev->nodename);
goto free_be;
}
diff -r 0e7c48861e95 -r 1ac39c7a0435 linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c
--- a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c Mon Oct 10 13:42:38 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c Mon Oct 10 13:46:53 2005
@@ -460,7 +460,7 @@
if (info->connected == BLKIF_STATE_CONNECTED)
return;

- err = xenbus_gather(watch->node,
+ err = xenbus_gather(NULL, watch->node,
"sectors", "%lu", &sectors,
"info", "%u", &binfo,
"sector-size", "%lu", &sector_size,
@@ -532,10 +532,11 @@
{
char *backend;
const char *message;
+ struct xenbus_transaction *xbt;
int err;

backend = NULL;
- err = xenbus_gather(dev->nodename,
+ err = xenbus_gather(NULL, dev->nodename,
"backend-id", "%i", &info->backend_id,
"backend", NULL, &backend,
NULL);
@@ -559,25 +560,26 @@
}

again:
- err = xenbus_transaction_start();
- if (err) {
+ xbt = xenbus_transaction_start();
+ if (IS_ERR(xbt)) {
xenbus_dev_error(dev, err, "starting transaction");
goto destroy_blkring;
}

- err = xenbus_printf(dev->nodename, "ring-ref","%u", info->ring_ref);
+ err = xenbus_printf(xbt, dev->nodename,
+ "ring-ref","%u", info->ring_ref);
if (err) {
message = "writing ring-ref";
goto abort_transaction;
}
- err = xenbus_printf(dev->nodename,
+ err = xenbus_printf(xbt, dev->nodename,
"event-channel", "%u", info->evtchn);
if (err) {
message = "writing event-channel";
goto abort_transaction;
}

- err = xenbus_transaction_end(0);
+ err = xenbus_transaction_end(xbt, 0);
if (err) {
if (err == -EAGAIN)
goto again;
@@ -598,8 +600,7 @@
return 0;

abort_transaction:
- xenbus_transaction_end(1);
- /* Have to do this *outside* transaction. */
+ xenbus_transaction_end(xbt, 1);
xenbus_dev_error(dev, err, "%s", message);
destroy_blkring:
blkif_free(info);
@@ -620,7 +621,8 @@
struct blkfront_info *info;

/* FIXME: Use dynamic device id if this is not set. */
- err = xenbus_scanf(dev->nodename, "virtual-device", "%i", &vdevice);
+ err = xenbus_scanf(NULL, dev->nodename,
+ "virtual-device", "%i", &vdevice);
if (XENBUS_EXIST_ERR(err))
return err;
if (err < 0) {
diff -r 0e7c48861e95 -r 1ac39c7a0435 linux-2.6-xen-sparse/drivers/xen/blkfront/vbd.c
--- a/linux-2.6-xen-sparse/drivers/xen/blkfront/vbd.c Mon Oct 10 13:42:38 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/vbd.c Mon Oct 10 13:46:53 2005
@@ -160,7 +160,8 @@

mi = ((major_info[index] != NULL) ? major_info[index] :
xlbd_alloc_major_info(major, minor, index));
- mi->usage++;
+ if (mi)
+ mi->usage++;
return mi;
}

diff -r 0e7c48861e95 -r 1ac39c7a0435 linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c
--- a/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c Mon Oct 10 13:42:38 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c Mon Oct 10 13:46:53 2005
@@ -69,15 +69,15 @@
int i;

/* If other end is gone, delete ourself. */
- if (vec && !xenbus_exists(be->frontpath, "")) {
- xenbus_rm(be->dev->nodename, "");
+ if (vec && !xenbus_exists(NULL, be->frontpath, "")) {
+ xenbus_rm(NULL, be->dev->nodename, "");
device_unregister(&be->dev->dev);
return;
}
if (be->netif == NULL || be->netif->status == CONNECTED)
return;

- mac = xenbus_read(be->frontpath, "mac", NULL);
+ mac = xenbus_read(NULL, be->frontpath, "mac", NULL);
if (IS_ERR(mac)) {
err = PTR_ERR(mac);
xenbus_dev_error(be->dev, err, "reading %s/mac",
@@ -98,7 +98,8 @@
}
kfree(mac);

- err = xenbus_gather(be->frontpath, "tx-ring-ref", "%lu", &tx_ring_ref,
+ err = xenbus_gather(NULL, be->frontpath,
+ "tx-ring-ref", "%lu", &tx_ring_ref,
"rx-ring-ref", "%lu", &rx_ring_ref,
"event-channel", "%u", &evtchn, NULL);
if (err) {
@@ -137,7 +138,7 @@
struct xenbus_device *dev = be->dev;
u8 be_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };

- err = xenbus_scanf(dev->nodename, "handle", "%li", &handle);
+ err = xenbus_scanf(NULL, dev->nodename, "handle", "%li", &handle);
if (XENBUS_EXIST_ERR(err))
return;
if (err < 0) {
@@ -188,7 +189,7 @@

key = env_vars;
while (*key != NULL) {
- val = xenbus_read(xdev->nodename, *key, NULL);
+ val = xenbus_read(NULL, xdev->nodename, *key, NULL);
if (!IS_ERR(val)) {
char buf[strlen(*key) + 4];
sprintf(buf, "%s=%%s", *key);
@@ -220,7 +221,7 @@
memset(be, 0, sizeof(*be));

frontend = NULL;
- err = xenbus_gather(dev->nodename,
+ err = xenbus_gather(NULL, dev->nodename,
"frontend-id", "%li", &be->frontend_id,
"frontend", NULL, &frontend,
NULL);
@@ -232,7 +233,7 @@
dev->nodename);
goto free_be;
}
- if (strlen(frontend) == 0 || !xenbus_exists(frontend, "")) {
+ if (strlen(frontend) == 0 || !xenbus_exists(NULL, frontend, "")) {
/* If we can't get a frontend path and a frontend-id,
* then our bus-id is no longer valid and we need to
* destroy the backend device.
diff -r 0e7c48861e95 -r 1ac39c7a0435 linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c
--- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Mon Oct 10 13:42:38 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Mon Oct 10 13:46:53 2005
@@ -1083,10 +1083,11 @@
{
char *backend, *mac, *e, *s;
const char *message;
+ struct xenbus_transaction *xbt;
int err, i;

backend = NULL;
- err = xenbus_gather(dev->nodename,
+ err = xenbus_gather(NULL, dev->nodename,
"backend-id", "%i", &info->backend_id,
"backend", NULL, &backend,
NULL);
@@ -1102,7 +1103,7 @@
goto out;
}

- mac = xenbus_read(dev->nodename, "mac", NULL);
+ mac = xenbus_read(NULL, dev->nodename, "mac", NULL);
if (IS_ERR(mac)) {
err = PTR_ERR(mac);
xenbus_dev_error(dev, err, "reading %s/mac",
@@ -1131,32 +1132,32 @@
}

again:
- err = xenbus_transaction_start();
- if (err) {
+ xbt = xenbus_transaction_start();
+ if (IS_ERR(xbt)) {
xenbus_dev_error(dev, err, "starting transaction");
goto destroy_ring;
}

- err = xenbus_printf(dev->nodename, "tx-ring-ref","%u",
+ err = xenbus_printf(xbt, dev->nodename, "tx-ring-ref","%u",
info->tx_ring_ref);
if (err) {
message = "writing tx ring-ref";
goto abort_transaction;
}
- err = xenbus_printf(dev->nodename, "rx-ring-ref","%u",
+ err = xenbus_printf(xbt, dev->nodename, "rx-ring-ref","%u",
info->rx_ring_ref);
if (err) {
message = "writing rx ring-ref";
goto abort_transaction;
}
- err = xenbus_printf(dev->nodename,
+ err = xenbus_printf(xbt, dev->nodename,
"event-channel", "%u", info->evtchn);
if (err) {
message = "writing event-channel";
goto abort_transaction;
}

- err = xenbus_transaction_end(0);
+ err = xenbus_transaction_end(xbt, 0);
if (err) {
if (err == -EAGAIN)
goto again;
@@ -1177,8 +1178,7 @@
return 0;

abort_transaction:
- xenbus_transaction_end(1);
- /* Have to do this *outside* transaction. */
+ xenbus_transaction_end(xbt, 1);
xenbus_dev_error(dev, err, "%s", message);
destroy_ring:
shutdown_device(info);
@@ -1201,7 +1201,7 @@
struct netfront_info *info;
unsigned int handle;

- err = xenbus_scanf(dev->nodename, "handle", "%u", &handle);
+ err = xenbus_scanf(NULL, dev->nodename, "handle", "%u", &handle);
if (XENBUS_EXIST_ERR(err))
return err;
if (err < 0) {
diff -r 0e7c48861e95 -r 1ac39c7a0435 linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c
--- a/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c Mon Oct 10 13:42:38 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c Mon Oct 10 13:46:53 2005
@@ -246,7 +246,10 @@
PAGE_SHIFT);
ret = xen_start_info->store_mfn;

- /* We'll return then this will wait for daemon to answer */
+ /*
+ ** Complete initialization of xenbus (viz. set up the
+ ** connection to xenstored now that it has started).
+ */
kthread_run(do_xenbus_probe, NULL, "xenbus_probe");
}
break;
diff -r 0e7c48861e95 -r 1ac39c7a0435 linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c
--- a/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c Mon Oct 10 13:42:38 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c Mon Oct 10 13:46:53 2005
@@ -66,12 +66,13 @@
unsigned int evtchn;
unsigned long ready = 1;
int err;
+ struct xenbus_transaction *xbt;
struct backend_info *be
= container_of(watch, struct backend_info, watch);

/* If other end is gone, delete ourself. */
- if (vec && !xenbus_exists(be->frontpath, "")) {
- xenbus_rm(be->dev->nodename, "");
+ if (vec && !xenbus_exists(NULL, be->frontpath, "")) {
+ xenbus_rm(NULL, be->dev->nodename, "");
device_unregister(&be->dev->dev);
return;
}
@@ -79,7 +80,7 @@
if (be->tpmif == NULL || be->tpmif->status == CONNECTED)
return;

- err = xenbus_gather(be->frontpath,
+ err = xenbus_gather(NULL, be->frontpath,
"ring-ref", "%lu", &ringref,
"event-channel", "%u", &evtchn, NULL);
if (err) {
@@ -115,20 +116,20 @@
* unless something bad happens
*/
again:
- err = xenbus_transaction_start();
- if (err) {
+ xbt = xenbus_transaction_start();
+ if (IS_ERR(xbt)) {
xenbus_dev_error(be->dev, err, "starting transaction");
return;
}

- err = xenbus_printf(be->dev->nodename,
+ err = xenbus_printf(xbt, be->dev->nodename,
"ready", "%lu", ready);
if (err) {
xenbus_dev_error(be->dev, err, "writing 'ready'");
goto abort;
}

- err = xenbus_transaction_end(0);
+ err = xenbus_transaction_end(xbt, 0);
if (err == -EAGAIN)
goto again;
if (err) {
@@ -139,7 +140,7 @@
xenbus_dev_ok(be->dev);
return;
abort:
- xenbus_transaction_end(1);
+ xenbus_transaction_end(xbt, 1);
}


@@ -152,7 +153,7 @@
= container_of(watch, struct backend_info, backend_watch);
struct xenbus_device *dev = be->dev;

- err = xenbus_scanf(dev->nodename, "instance", "%li", &instance);
+ err = xenbus_scanf(NULL, dev->nodename, "instance", "%li", &instance);
if (XENBUS_EXIST_ERR(err))
return;
if (err < 0) {
@@ -205,7 +206,7 @@
memset(be, 0, sizeof(*be));

frontend = NULL;
- err = xenbus_gather(dev->nodename,
+ err = xenbus_gather(NULL, dev->nodename,
"frontend-id", "%li", &be->frontend_id,
"frontend", NULL, &frontend,
NULL);
@@ -217,7 +218,7 @@
dev->nodename);
goto free_be;
}
- if (strlen(frontend) == 0 || !xenbus_exists(frontend, "")) {
+ if (strlen(frontend) == 0 || !xenbus_exists(NULL, frontend, "")) {
/* If we can't get a frontend path and a frontend-id,
* then our bus-id is no longer valid and we need to
* destroy the backend device.
diff -r 0e7c48861e95 -r 1ac39c7a0435 linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c
--- a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c Mon Oct 10 13:42:38 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c Mon Oct 10 13:46:53 2005
@@ -226,7 +226,7 @@
if (tp->connected)
return;

- err = xenbus_gather(watch->node,
+ err = xenbus_gather(NULL, watch->node,
"ready", "%lu", &ready,
NULL);
if (err) {
@@ -311,9 +311,10 @@
const char *message;
int err;
int backend_id;
+ struct xenbus_transaction *xbt;

backend = NULL;
- err = xenbus_gather(dev->nodename,
+ err = xenbus_gather(NULL, dev->nodename,
"backend-id", "%i", &backend_id,
"backend", NULL, &backend,
NULL);
@@ -339,27 +340,27 @@
}

again:
- err = xenbus_transaction_start();
- if (err) {
+ xbt = xenbus_transaction_start();
+ if (IS_ERR(xbt)) {
xenbus_dev_error(dev, err, "starting transaction");
goto destroy_tpmring;
}

- err = xenbus_printf(dev->nodename,
+ err = xenbus_printf(xbt, dev->nodename,
"ring-ref","%u", info->ring_ref);
if (err) {
message = "writing ring-ref";
goto abort_transaction;
}

- err = xenbus_printf(dev->nodename,
+ err = xenbus_printf(xbt, dev->nodename,
"event-channel", "%u", my_private.evtchn);
if (err) {
message = "writing event-channel";
goto abort_transaction;
}

- err = xenbus_transaction_end(0);
+ err = xenbus_transaction_end(xbt, 0);
if (err == -EAGAIN)
goto again;
if (err) {
@@ -380,8 +381,7 @@
return 0;

abort_transaction:
- xenbus_transaction_end(1);
- /* Have to do this *outside* transaction. */
+ xenbus_transaction_end(xbt, 1);
xenbus_dev_error(dev, err, "%s", message);
destroy_tpmring:
destroy_tpmring(info, &my_private);
@@ -399,7 +399,7 @@
struct tpmfront_info *info;
int handle;

- err = xenbus_scanf(dev->nodename,
+ err = xenbus_scanf(NULL, dev->nodename,
"handle", "%i", &handle);
if (XENBUS_EXIST_ERR(err))
return err;
diff -r 0e7c48861e95 -r 1ac39c7a0435 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c
--- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c Mon Oct 10 13:42:38 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c Mon Oct 10 13:46:53 2005
@@ -130,15 +130,10 @@

wait_event(xb_waitq, output_avail(out));

- /* Read, then check: not that we don't trust store.
- * Hell, some of my best friends are daemons. But,
- * in this post-911 world... */
+ mb();
h = *out;
- mb();
- if (!check_buffer(&h)) {
- set_current_state(TASK_RUNNING);
- return -EIO; /* ETERRORIST! */
- }
+ if (!check_buffer(&h))
+ return -EIO;

dst = get_output_chunk(&h, out->buf, &avail);
if (avail > len)
@@ -173,12 +168,11 @@
const char *src;

wait_event(xb_waitq, xs_input_avail());
+
+ mb();
h = *in;
- mb();
- if (!check_buffer(&h)) {
- set_current_state(TASK_RUNNING);
+ if (!check_buffer(&h))
return -EIO;
- }

src = get_input_chunk(&h, in->buf, &avail);
if (avail > len)
@@ -195,10 +189,6 @@
notify_remote_via_evtchn(xen_start_info->store_evtchn);
}

- /* If we left something, wake watch thread to deal with it. */
- if (xs_input_avail())
- wake_up(&xb_waitq);
-
return 0;
}

diff -r 0e7c48861e95 -r 1ac39c7a0435 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c
--- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c Mon Oct 10 13:42:38 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c Mon Oct 10 13:46:53 2005
@@ -46,85 +46,113 @@
#include <asm/hypervisor.h>

struct xenbus_dev_data {
- /* Are there bytes left to be read in this message? */
- int bytes_left;
- /* Are we still waiting for the reply to a message we wrote? */
- int awaiting_reply;
- /* Buffer for outgoing messages. */
+ int in_transaction;
+
+ /* Partial request. */
unsigned int len;
union {
struct xsd_sockmsg msg;
char buffer[PAGE_SIZE];
} u;
+
+ /* Response queue. */
+#define MASK_READ_IDX(idx) ((idx)&(PAGE_SIZE-1))
+ char read_buffer[PAGE_SIZE];
+ unsigned int read_cons, read_prod;
+ wait_queue_head_t read_waitq;
};

static struct proc_dir_entry *xenbus_dev_intf;

-/* Reply can be long (dir, getperm): don't buffer, just examine
- * headers so we can discard rest if they die. */
static ssize_t xenbus_dev_read(struct file *filp,
char __user *ubuf,
size_t len, loff_t *ppos)
{
- struct xenbus_dev_data *data = filp->private_data;
- struct xsd_sockmsg msg;
- int err;
-
- /* Refill empty buffer? */
- if (data->bytes_left == 0) {
- if (len < sizeof(msg))
- return -EINVAL;
-
- err = xb_read(&msg, sizeof(msg));
- if (err)
- return err;
- data->bytes_left = msg.len;
- if (ubuf && copy_to_user(ubuf, &msg, sizeof(msg)) != 0)
- return -EFAULT;
- /* We can receive spurious XS_WATCH_EVENT messages. */
- if (msg.type != XS_WATCH_EVENT)
- data->awaiting_reply = 0;
- return sizeof(msg);
+ struct xenbus_dev_data *u = filp->private_data;
+ int i;
+
+ if (wait_event_interruptible(u->read_waitq,
+ u->read_prod != u->read_cons))
+ return -EINTR;
+
+ for (i = 0; i < len; i++) {
+ if (u->read_cons == u->read_prod)
+ break;
+ put_user(u->read_buffer[MASK_READ_IDX(u->read_cons)], ubuf+i);
+ u->read_cons++;
}

- /* Don't read over next header, or over temporary buffer. */
- if (len > sizeof(data->u.buffer))
- len = sizeof(data->u.buffer);
- if (len > data->bytes_left)
- len = data->bytes_left;
-
- err = xb_read(data->u.buffer, len);
- if (err)
- return err;
-
- data->bytes_left -= len;
- if (ubuf && copy_to_user(ubuf, data->u.buffer, len) != 0)
- return -EFAULT;
- return len;
-}
-
-/* We do v. basic sanity checking so they don't screw up kernel later. */
+ return i;
+}
+
+static void queue_reply(struct xenbus_dev_data *u,
+ char *data, unsigned int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++, u->read_prod++)
+ u->read_buffer[MASK_READ_IDX(u->read_prod)] = data[i];
+
+ BUG_ON((u->read_prod - u->read_cons) > sizeof(u->read_buffer));
+
+ wake_up(&u->read_waitq);
+}
+
static ssize_t xenbus_dev_write(struct file *filp,
const char __user *ubuf,
size_t len, loff_t *ppos)
{
- struct xenbus_dev_data *data = filp->private_data;
- int err;
-
- /* We gather data in buffer until we're ready to send it. */
- if (len > data->len + sizeof(data->u))
+ struct xenbus_dev_data *u = filp->private_data;
+ void *reply;
+ int err = 0;
+
+ if ((len + u->len) > sizeof(u->u.buffer))
return -EINVAL;
- if (copy_from_user(data->u.buffer + data->len, ubuf, len) != 0)
+
+ if (copy_from_user(u->u.buffer + u->len, ubuf, len) != 0)
return -EFAULT;
- data->len += len;
- if (data->len >= sizeof(data->u.msg) + data->u.msg.len) {
- err = xb_write(data->u.buffer, data->len);
- if (err)
- return err;
- data->len = 0;
- data->awaiting_reply = 1;
+
+ u->len += len;
+ if (u->len < (sizeof(u->u.msg) + u->u.msg.len))
+ return len;
+
+ switch (u->u.msg.type) {
+ case XS_TRANSACTION_START:
+ case XS_TRANSACTION_END:
+ case XS_DIRECTORY:
+ case XS_READ:
+ case XS_GET_PERMS:
+ case XS_RELEASE:
+ case XS_GET_DOMAIN_PATH:
+ case XS_WRITE:
+ case XS_MKDIR:
+ case XS_RM:
+ case XS_SET_PERMS:
+ reply = xenbus_dev_request_and_reply(&u->u.msg);
+ if (IS_ERR(reply))
+ err = PTR_ERR(reply);
+ else {
+ if (u->u.msg.type == XS_TRANSACTION_START)
+ u->in_transaction = 1;
+ if (u->u.msg.type == XS_TRANSACTION_END)
+ u->in_transaction = 0;
+ queue_reply(u, (char *)&u->u.msg, sizeof(u->u.msg));
+ queue_reply(u, (char *)reply, u->u.msg.len);
+ kfree(reply);
+ }
+ break;
+
+ default:
+ err = -EINVAL;
+ break;
}
- return len;
+
+ if (err == 0) {
+ u->len = 0;
+ err = len;
+ }
+
+ return err;
}

static int xenbus_dev_open(struct inode *inode, struct file *filp)
@@ -134,7 +162,6 @@
if (xen_start_info->store_evtchn == 0)
return -ENOENT;

- /* Don't try seeking. */
nonseekable_open(inode, filp);

u = kmalloc(sizeof(*u), GFP_KERNEL);
@@ -142,28 +169,21 @@
return -ENOMEM;

memset(u, 0, sizeof(*u));
+ init_waitqueue_head(&u->read_waitq);

filp->private_data = u;

- down(&xenbus_lock);
-
return 0;
}

static int xenbus_dev_release(struct inode *inode, struct file *filp)
{
- struct xenbus_dev_data *data = filp->private_data;
-
- /* Discard any unread replies. */
- while (data->bytes_left || data->awaiting_reply)
- xenbus_dev_read(filp, NULL, sizeof(data->u.buffer), NULL);
-
- /* Harmless if no transaction in progress. */
- xenbus_transaction_end(1);
-
- up(&xenbus_lock);
-
- kfree(data);
+ struct xenbus_dev_data *u = filp->private_data;
+
+ if (u->in_transaction)
+ xenbus_transaction_end((struct xenbus_transaction *)1, 1);
+
+ kfree(u);

return 0;
}
diff -r 0e7c48861e95 -r 1ac39c7a0435 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c
--- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Mon Oct 10 13:42:38 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Mon Oct 10 13:46:53 2005
@@ -43,6 +43,9 @@

static struct notifier_block *xenstore_chain;

+/* Now used to protect xenbus probes against save/restore. */
+static DECLARE_MUTEX(xenbus_lock);
+
/* If something in array of ids matches this device, return it. */
static const struct xenbus_device_id *
match_device(const struct xenbus_device_id *arr, struct xenbus_device *dev)
@@ -125,7 +128,7 @@

devid = strrchr(nodename, '/') + 1;

- err = xenbus_gather(nodename, "frontend-id", "%i", &domid,
+ err = xenbus_gather(NULL, nodename, "frontend-id", "%i", &domid,
"frontend", NULL, &frontend,
NULL);
if (err)
@@ -133,7 +136,7 @@
if (strlen(frontend) == 0)
err = -ERANGE;

- if (!err && !xenbus_exists(frontend, ""))
+ if (!err && !xenbus_exists(NULL, frontend, ""))
err = -ENOENT;

if (err) {
@@ -447,7 +450,7 @@
if (!nodename)
return -ENOMEM;

- dir = xenbus_directory(nodename, "", &dir_n);
+ dir = xenbus_directory(NULL, nodename, "", &dir_n);
if (IS_ERR(dir)) {
kfree(nodename);
return PTR_ERR(dir);
@@ -470,7 +473,7 @@
unsigned int dir_n = 0;
int i;

- dir = xenbus_directory(bus->root, type, &dir_n);
+ dir = xenbus_directory(NULL, bus->root, type, &dir_n);
if (IS_ERR(dir))
return PTR_ERR(dir);

@@ -489,7 +492,7 @@
char **dir;
unsigned int i, dir_n;

- dir = xenbus_directory(bus->root, "", &dir_n);
+ dir = xenbus_directory(NULL, bus->root, "", &dir_n);
if (IS_ERR(dir))
return PTR_ERR(dir);

@@ -535,7 +538,7 @@
if (char_count(node, '/') < 2)
return;

- exists = xenbus_exists(node, "");
+ exists = xenbus_exists(NULL, node, "");
if (!exists) {
xenbus_cleanup_devices(node, &bus->bus);
return;
@@ -625,12 +628,13 @@
down(&xenbus_lock);
bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, suspend_dev);
bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, suspend_dev);
+ xs_suspend();
}

void xenbus_resume(void)
{
xb_init_comms();
- reregister_xenbus_watches();
+ xs_resume();
bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, resume_dev);
bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, resume_dev);
up(&xenbus_lock);
@@ -662,12 +666,16 @@
}
EXPORT_SYMBOL(unregister_xenstore_notifier);

-/* called from a thread in privcmd/privcmd.c */
+/*
+** Called either from below xenbus_probe_init() initcall (for domUs)
+** or, for dom0, from a thread created in privcmd/privcmd.c (after
+** the user-space tools have invoked initDomainStore())
+*/
int do_xenbus_probe(void *unused)
{
int err = 0;

- /* Initialize xenstore comms unless already done. */
+ /* Initialize the interface to xenstore. */
err = xs_init();
if (err) {
printk("XENBUS: Error initializing xenstore comms:"
@@ -685,6 +693,7 @@
/* Notify others that xenstore is up */
notifier_call_chain(&xenstore_chain, 0, 0);
up(&xenbus_lock);
+
return 0;
}

@@ -698,6 +707,10 @@
device_register(&xenbus_frontend.dev);
device_register(&xenbus_backend.dev);

+ /*
+ ** Domain0 doesn't have a store_evtchn yet - this will
+ ** be set up later by xend invoking initDomainStore()
+ */
if (!xen_start_info->store_evtchn)
return 0;

diff -r 0e7c48861e95 -r 1ac39c7a0435 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c
--- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c Mon Oct 10 13:42:38 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c Mon Oct 10 13:46:53 2005
@@ -42,11 +42,67 @@

#define streq(a, b) (strcmp((a), (b)) == 0)

-static char printf_buffer[4096];
+struct xs_stored_msg {
+ struct xsd_sockmsg hdr;
+
+ union {
+ /* Stored replies. */
+ struct {
+ struct list_head list;
+ char *body;
+ } reply;
+
+ /* Queued watch callbacks. */
+ struct {
+ struct work_struct work;
+ struct xenbus_watch *handle;
+ char **vec;
+ unsigned int vec_size;
+ } watch;
+ } u;
+};
+
+struct xs_handle {
+ /* A list of replies. Currently only one will ever be outstanding. */
+ struct list_head reply_list;
+ spinlock_t reply_lock;
+ wait_queue_head_t reply_waitq;
+
+ /* One request at a time. */
+ struct semaphore request_mutex;
+
+ /* One transaction at a time. */
+ struct semaphore transaction_mutex;
+ int transaction_pid;
+};
+
+static struct xs_handle xs_state;
+
static LIST_HEAD(watches);
-
-DECLARE_MUTEX(xenbus_lock);
-EXPORT_SYMBOL(xenbus_lock);
+static DEFINE_SPINLOCK(watches_lock);
+
+/* Can wait on !xs_resuming for suspend/resume cycle to complete. */
+static int xs_resuming;
+static DECLARE_WAIT_QUEUE_HEAD(xs_resuming_waitq);
+
+static void request_mutex_acquire(void)
+{
+ /*
+ * We can't distinguish non-transactional from transactional
+ * requests right now. So temporarily acquire the transaction mutex
+ * if this task is outside transaction context.
+ */
+ if (xs_state.transaction_pid != current->pid)
+ down(&xs_state.transaction_mutex);
+ down(&xs_state.request_mutex);
+}
+
+static void request_mutex_release(void)
+{
+ up(&xs_state.request_mutex);
+ if (xs_state.transaction_pid != current->pid)
+ up(&xs_state.transaction_mutex);
+}

static int get_error(const char *errorstring)
{
@@ -65,29 +121,32 @@

static void *read_reply(enum xsd_sockmsg_type *type, unsigned int *len)
{
- struct xsd_sockmsg msg;
- void *ret;
- int err;
-
- err = xb_read(&msg, sizeof(msg));
- if (err)
- return ERR_PTR(err);
-
- ret = kmalloc(msg.len + 1, GFP_KERNEL);
- if (!ret)
- return ERR_PTR(-ENOMEM);
-
- err = xb_read(ret, msg.len);
- if (err) {
- kfree(ret);
- return ERR_PTR(err);
- }
- ((char*)ret)[msg.len] = '\0';
-
- *type = msg.type;
+ struct xs_stored_msg *msg;
+ char *body;
+
+ spin_lock(&xs_state.reply_lock);
+
+ while (list_empty(&xs_state.reply_list)) {
+ spin_unlock(&xs_state.reply_lock);
+ wait_event(xs_state.reply_waitq,
+ !list_empty(&xs_state.reply_list));
+ spin_lock(&xs_state.reply_lock);
+ }
+
+ msg = list_entry(xs_state.reply_list.next,
+ struct xs_stored_msg, u.reply.list);
+ list_del(&msg->u.reply.list);
+
+ spin_unlock(&xs_state.reply_lock);
+
+ *type = msg->hdr.type;
if (len)
- *len = msg.len;
- return ret;
+ *len = msg->hdr.len;
+ body = msg->u.reply.body;
+
+ kfree(msg);
+
+ return body;
}

/* Emergency write. */
@@ -98,10 +157,45 @@
msg.type = XS_DEBUG;
msg.len = sizeof("print") + count + 1;

+ request_mutex_acquire();
xb_write(&msg, sizeof(msg));
xb_write("print", sizeof("print"));
xb_write(str, count);
xb_write("", 1);
+ request_mutex_release();
+}
+
+void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg)
+{
+ void *ret;
+ struct xsd_sockmsg req_msg = *msg;
+ int err;
+
+ if (req_msg.type == XS_TRANSACTION_START) {
+ down(&xs_state.transaction_mutex);
+ xs_state.transaction_pid = current->pid;
+ }
+
+ request_mutex_acquire();
+
+ err = xb_write(msg, sizeof(*msg) + msg->len);
+ if (err) {
+ msg->type = XS_ERROR;
+ ret = ERR_PTR(err);
+ } else {
+ ret = read_reply(&msg->type, &msg->len);
+ }
+
+ request_mutex_release();
+
+ if ((msg->type == XS_TRANSACTION_END) ||
+ ((req_msg.type == XS_TRANSACTION_START) &&
+ (msg->type == XS_ERROR))) {
+ xs_state.transaction_pid = -1;
+ up(&xs_state.transaction_mutex);
+ }
+
+ return ret;
}

/* Send message to xs, get kmalloc'ed reply. ERR_PTR() on error. */
@@ -115,31 +209,33 @@
unsigned int i;
int err;

- WARN_ON(down_trylock(&xenbus_lock) == 0);
-
msg.type = type;
msg.len = 0;
for (i = 0; i < num_vecs; i++)
msg.len += iovec[i].iov_len;

+ request_mutex_acquire();
+
err = xb_write(&msg, sizeof(msg));
- if (err)
+ if (err) {
+ up(&xs_state.request_mutex);
return ERR_PTR(err);
+ }

for (i = 0; i < num_vecs; i++) {
err = xb_write(iovec[i].iov_base, iovec[i].iov_len);;
- if (err)
+ if (err) {
+ request_mutex_release();
return ERR_PTR(err);
- }
-
- /* Watches can have fired before reply comes: daemon detects
- * and re-transmits, so we can ignore this. */
- do {
- kfree(ret);
- ret = read_reply(&msg.type, len);
- if (IS_ERR(ret))
- return ret;
- } while (msg.type == XS_WATCH_EVENT);
+ }
+ }
+
+ ret = read_reply(&msg.type, len);
+
+ request_mutex_release();
+
+ if (IS_ERR(ret))
+ return ret;

if (msg.type == XS_ERROR) {
err = get_error(ret);
@@ -187,8 +283,6 @@
{
static char buffer[4096];

- BUG_ON(down_trylock(&xenbus_lock) == 0);
- /* XXX FIXME: might not be correct if name == "" */
BUG_ON(strlen(dir) + strlen("/") + strlen(name) + 1 > sizeof(buffer));

strcpy(buffer, dir);
@@ -207,7 +301,7 @@
*num = count_strings(strings, len);

/* Transfer to one big alloc for easy freeing. */
- ret = kmalloc(*num * sizeof(char *) + len, GFP_ATOMIC);
+ ret = kmalloc(*num * sizeof(char *) + len, GFP_KERNEL);
if (!ret) {
kfree(strings);
return ERR_PTR(-ENOMEM);
@@ -222,7 +316,8 @@
return ret;
}

-char **xenbus_directory(const char *dir, const char *node, unsigned int *num)
+char **xenbus_directory(struct xenbus_transaction *t,
+ const char *dir, const char *node, unsigned int *num)
{
char *strings;
unsigned int len;
@@ -236,12 +331,13 @@
EXPORT_SYMBOL(xenbus_directory);

/* Check if a path exists. Return 1 if it does. */
-int xenbus_exists(const char *dir, const char *node)
+int xenbus_exists(struct xenbus_transaction *t,
+ const char *dir, const char *node)
{
char **d;
int dir_n;

- d = xenbus_directory(dir, node, &dir_n);
+ d = xenbus_directory(t, dir, node, &dir_n);
if (IS_ERR(d))
return 0;
kfree(d);
@@ -253,7 +349,8 @@
* Returns a kmalloced value: call free() on it after use.
* len indicates length in bytes.
*/
-void *xenbus_read(const char *dir, const char *node, unsigned int *len)
+void *xenbus_read(struct xenbus_transaction *t,
+ const char *dir, const char *node, unsigned int *len)
{
return xs_single(XS_READ, join(dir, node), len);
}
@@ -262,7 +359,8 @@
/* Write the value of a single file.
* Returns -err on failure.
*/
-int xenbus_write(const char *dir, const char *node, const char *string)
+int xenbus_write(struct xenbus_transaction *t,
+ const char *dir, const char *node, const char *string)
{
const char *path;
struct kvec iovec[2];
@@ -279,14 +377,15 @@
EXPORT_SYMBOL(xenbus_write);

/* Create a new directory. */
-int xenbus_mkdir(const char *dir, const char *node)
+int xenbus_mkdir(struct xenbus_transaction *t,
+ const char *dir, const char *node)
{
return xs_error(xs_single(XS_MKDIR, join(dir, node), NULL));
}
EXPORT_SYMBOL(xenbus_mkdir);

/* Destroy a file or directory (directories must be empty). */
-int xenbus_rm(const char *dir, const char *node)
+int xenbus_rm(struct xenbus_transaction *t, const char *dir, const char *node)
{
return xs_error(xs_single(XS_RM, join(dir, node), NULL));
}
@@ -294,37 +393,57 @@

/* Start a transaction: changes by others will not be seen during this
* transaction, and changes will not be visible to others until end.
- * You can only have one transaction at any time.
*/
-int xenbus_transaction_start(void)
-{
- return xs_error(xs_single(XS_TRANSACTION_START, "", NULL));
+struct xenbus_transaction *xenbus_transaction_start(void)
+{
+ int err;
+
+ down(&xs_state.transaction_mutex);
+ xs_state.transaction_pid = current->pid;
+
+ err = xs_error(xs_single(XS_TRANSACTION_START, "", NULL));
+ if (err) {
+ xs_state.transaction_pid = -1;
+ up(&xs_state.transaction_mutex);
+ }
+
+ return err ? ERR_PTR(err) : (struct xenbus_transaction *)1;
}
EXPORT_SYMBOL(xenbus_transaction_start);

/* End a transaction.
* If abandon is true, transaction is discarded instead of committed.
*/
-int xenbus_transaction_end(int abort)
+int xenbus_transaction_end(struct xenbus_transaction *t, int abort)
{
char abortstr[2];
+ int err;
+
+ BUG_ON(t == NULL);

if (abort)
strcpy(abortstr, "F");
else
strcpy(abortstr, "T");
- return xs_error(xs_single(XS_TRANSACTION_END, abortstr, NULL));
+
+ err = xs_error(xs_single(XS_TRANSACTION_END, abortstr, NULL));
+
+ xs_state.transaction_pid = -1;
+ up(&xs_state.transaction_mutex);
+
+ return err;
}
EXPORT_SYMBOL(xenbus_transaction_end);

/* Single read and scanf: returns -errno or num scanned. */
-int xenbus_scanf(const char *dir, const char *node, const char *fmt, ...)
+int xenbus_scanf(struct xenbus_transaction *t,
+ const char *dir, const char *node, const char *fmt, ...)
{
va_list ap;
int ret;
char *val;

- val = xenbus_read(dir, node, NULL);
+ val = xenbus_read(t, dir, node, NULL);
if (IS_ERR(val))
return PTR_ERR(val);

@@ -340,18 +459,28 @@
EXPORT_SYMBOL(xenbus_scanf);

/* Single printf and write: returns -errno or 0. */
-int xenbus_printf(const char *dir, const char *node, const char *fmt, ...)
+int xenbus_printf(struct xenbus_transaction *t,
+ const char *dir, const char *node, const char *fmt, ...)
{
va_list ap;
int ret;
-
- BUG_ON(down_trylock(&xenbus_lock) == 0);
+#define PRINTF_BUFFER_SIZE 4096
+ char *printf_buffer;
+
+ printf_buffer = kmalloc(PRINTF_BUFFER_SIZE, GFP_KERNEL);
+ if (printf_buffer == NULL)
+ return -ENOMEM;
+
va_start(ap, fmt);
- ret = vsnprintf(printf_buffer, sizeof(printf_buffer), fmt, ap);
+ ret = vsnprintf(printf_buffer, PRINTF_BUFFER_SIZE, fmt, ap);
va_end(ap);

- BUG_ON(ret > sizeof(printf_buffer)-1);
- return xenbus_write(dir, node, printf_buffer);
+ BUG_ON(ret > PRINTF_BUFFER_SIZE-1);
+ ret = xenbus_write(t, dir, node, printf_buffer);
+
+ kfree(printf_buffer);
+
+ return ret;
}
EXPORT_SYMBOL(xenbus_printf);

@@ -361,19 +490,28 @@
va_list ap;
int ret;
unsigned int len;
-
- BUG_ON(down_trylock(&xenbus_lock) == 0);
+ char *printf_buffer;
+
+ printf_buffer = kmalloc(PRINTF_BUFFER_SIZE, GFP_KERNEL);
+ if (printf_buffer == NULL)
+ goto fail;

len = sprintf(printf_buffer, "%i ", -err);
va_start(ap, fmt);
- ret = vsnprintf(printf_buffer+len, sizeof(printf_buffer)-len, fmt, ap);
+ ret = vsnprintf(printf_buffer+len, PRINTF_BUFFER_SIZE-len, fmt, ap);
va_end(ap);

- BUG_ON(len + ret > sizeof(printf_buffer)-1);
+ BUG_ON(len + ret > PRINTF_BUFFER_SIZE-1);
dev->has_error = 1;
- if (xenbus_write(dev->nodename, "error", printf_buffer) != 0)
- printk("xenbus: failed to write error node for %s (%s)\n",
- dev->nodename, printf_buffer);
+ if (xenbus_write(NULL, dev->nodename, "error", printf_buffer) != 0)
+ goto fail;
+
+ kfree(printf_buffer);
+ return;
+
+ fail:
+ printk("xenbus: failed to write error node for %s (%s)\n",
+ dev->nodename, printf_buffer);
}
EXPORT_SYMBOL(xenbus_dev_error);

@@ -381,7 +519,7 @@
void xenbus_dev_ok(struct xenbus_device *dev)
{
if (dev->has_error) {
- if (xenbus_rm(dev->nodename, "error") != 0)
+ if (xenbus_rm(NULL, dev->nodename, "error") != 0)
printk("xenbus: failed to clear error node for %s\n",
dev->nodename);
else
@@ -391,7 +529,7 @@
EXPORT_SYMBOL(xenbus_dev_ok);

/* Takes tuples of names, scanf-style args, and void **, NULL terminated. */
-int xenbus_gather(const char *dir, ...)
+int xenbus_gather(struct xenbus_transaction *t, const char *dir, ...)
{
va_list ap;
const char *name;
@@ -403,7 +541,7 @@
void *result = va_arg(ap, void *);
char *p;

- p = xenbus_read(dir, name, NULL);
+ p = xenbus_read(t, dir, name, NULL);
if (IS_ERR(p)) {
ret = PTR_ERR(p);
break;
@@ -432,26 +570,6 @@
return xs_error(xs_talkv(XS_WATCH, iov, ARRAY_SIZE(iov), NULL));
}

-static char **xs_read_watch(unsigned int *num)
-{
- enum xsd_sockmsg_type type;
- char *strings;
- unsigned int len;
-
- strings = read_reply(&type, &len);
- if (IS_ERR(strings))
- return (char **)strings;
-
- BUG_ON(type != XS_WATCH_EVENT);
-
- return split(strings, len, num);
-}
-
-static int xs_acknowledge_watch(const char *token)
-{
- return xs_error(xs_single(XS_WATCH_ACK, token, NULL));
-}
-
static int xs_unwatch(const char *path, const char *token)
{
struct kvec iov[2];
@@ -464,7 +582,6 @@
return xs_error(xs_talkv(XS_UNWATCH, iov, ARRAY_SIZE(iov), NULL));
}

-/* A little paranoia: we don't just trust token. */
static struct xenbus_watch *find_watch(const char *token)
{
struct xenbus_watch *i, *cmp;
@@ -474,6 +591,7 @@
list_for_each_entry(i, &watches, list)
if (i == cmp)
return i;
+
return NULL;
}

@@ -485,11 +603,20 @@
int err;

sprintf(token, "%lX", (long)watch);
+
+ spin_lock(&watches_lock);
BUG_ON(find_watch(token));
+ spin_unlock(&watches_lock);

err = xs_watch(watch->node, token);
- if (!err)
+
+ /* Ignore errors due to multiple registration. */
+ if ((err == 0) || (err == -EEXIST)) {
+ spin_lock(&watches_lock);
list_add(&watch->list, &watches);
+ spin_unlock(&watches_lock);
+ }
+
return err;
}
EXPORT_SYMBOL(register_xenbus_watch);
@@ -500,77 +627,192 @@
int err;

sprintf(token, "%lX", (long)watch);
+
+ spin_lock(&watches_lock);
BUG_ON(!find_watch(token));
+ list_del(&watch->list);
+ spin_unlock(&watches_lock);
+
+ /* Ensure xs_resume() is not in progress (see comments there). */
+ wait_event(xs_resuming_waitq, !xs_resuming);

err = xs_unwatch(watch->node, token);
- list_del(&watch->list);
-
if (err)
printk(KERN_WARNING
"XENBUS Failed to release watch %s: %i\n",
watch->node, err);
+
+ /* Make sure watch is not in use. */
+ flush_scheduled_work();
}
EXPORT_SYMBOL(unregister_xenbus_watch);

-/* Re-register callbacks to all watches. */
-void reregister_xenbus_watches(void)
-{
+void xs_suspend(void)
+{
+ down(&xs_state.transaction_mutex);
+ down(&xs_state.request_mutex);
+}
+
+void xs_resume(void)
+{
+ struct list_head *ent, *prev_ent = &watches;
struct xenbus_watch *watch;
char token[sizeof(watch) * 2 + 1];

- list_for_each_entry(watch, &watches, list) {
- sprintf(token, "%lX", (long)watch);
- xs_watch(watch->node, token);
- }
-}
-
-static int watch_thread(void *unused)
-{
+ /* Protect against concurrent unregistration and freeing of watches. */
+ BUG_ON(xs_resuming);
+ xs_resuming = 1;
+
+ up(&xs_state.request_mutex);
+ up(&xs_state.transaction_mutex);
+
+ /*
+ * Iterate over the watch list re-registering each node. We must
+ * be careful about concurrent registrations and unregistrations.
+ * We search for the node immediately following the previously
+ * re-registered node. If we get no match then either we are done
+ * (previous node is last in list) or the node was unregistered, in
+ * which case we restart from the beginning of the list.
+ * register_xenbus_watch() + unregister_xenbus_watch() is safe because
+ * it will only ever move a watch node earlier in the list, so it
+ * cannot cause us to skip nodes.
+ */
for (;;) {
- char **vec = NULL;
- unsigned int num;
-
- wait_event(xb_waitq, xs_input_avail());
-
- /* If this is a spurious wakeup caused by someone
- * doing an op, they'll hold the lock and the buffer
- * will be empty by the time we get there.
- */
- down(&xenbus_lock);
- if (xs_input_avail())
- vec = xs_read_watch(&num);
-
- if (vec && !IS_ERR(vec)) {
- struct xenbus_watch *w;
- int err;
-
- err = xs_acknowledge_watch(vec[XS_WATCH_TOKEN]);
- if (err)
- printk(KERN_WARNING "XENBUS ack %s fail %i\n",
- vec[XS_WATCH_TOKEN], err);
- w = find_watch(vec[XS_WATCH_TOKEN]);
- BUG_ON(!w);
- w->callback(w, (const char **)vec, num);
- kfree(vec);
- } else if (vec)
- printk(KERN_WARNING "XENBUS xs_read_watch: %li\n",
- PTR_ERR(vec));
- up(&xenbus_lock);
- }
-}
-
+ spin_lock(&watches_lock);
+ list_for_each(ent, &watches)
+ if (ent->prev == prev_ent)
+ break;
+ spin_unlock(&watches_lock);
+
+ /* No match because prev_ent is at the end of the list? */
+ if ((ent == &watches) && (watches.prev == prev_ent))
+ break; /* We're done! */
+
+ if ((prev_ent = ent) != &watches) {
+ /*
+ * Safe even with watch_lock not held. We are saved by
+ * (xs_resumed==1) check in unregister_xenbus_watch.
+ */
+ watch = list_entry(ent, struct xenbus_watch, list);
+ sprintf(token, "%lX", (long)watch);
+ xs_watch(watch->node, token);
+ }
+ }
+
+ xs_resuming = 0;
+ wake_up(&xs_resuming_waitq);
+}
+
+static void xenbus_fire_watch(void *arg)
+{
+ struct xs_stored_msg *msg = arg;
+
+ msg->u.watch.handle->callback(msg->u.watch.handle,
+ (const char **)msg->u.watch.vec,
+ msg->u.watch.vec_size);
+
+ kfree(msg->u.watch.vec);
+ kfree(msg);
+}
+
+static int process_msg(void)
+{
+ struct xs_stored_msg *msg;
+ char *body;
+ int err;
+
+ msg = kmalloc(sizeof(*msg), GFP_KERNEL);
+ if (msg == NULL)
+ return -ENOMEM;
+
+ err = xb_read(&msg->hdr, sizeof(msg->hdr));
+ if (err) {
+ kfree(msg);
+ return err;
+ }
+
+ body = kmalloc(msg->hdr.len + 1, GFP_KERNEL);
+ if (body == NULL) {
+ kfree(msg);
+ return -ENOMEM;
+ }
+
+ err = xb_read(body, msg->hdr.len);
+ if (err) {
+ kfree(body);
+ kfree(msg);
+ return err;
+ }
+ body[msg->hdr.len] = '\0';
+
+ if (msg->hdr.type == XS_WATCH_EVENT) {
+ INIT_WORK(&msg->u.watch.work, xenbus_fire_watch, msg);
+
+ msg->u.watch.vec = split(body, msg->hdr.len,
+ &msg->u.watch.vec_size);
+ if (IS_ERR(msg->u.watch.vec)) {
+ kfree(msg);
+ return PTR_ERR(msg->u.watch.vec);
+ }
+
+ spin_lock(&watches_lock);
+ msg->u.watch.handle = find_watch(
+ msg->u.watch.vec[XS_WATCH_TOKEN]);
+ if (msg->u.watch.handle != NULL) {
+ schedule_work(&msg->u.watch.work);
+ } else {
+ kfree(msg->u.watch.vec);
+ kfree(msg);
+ }
+ spin_unlock(&watches_lock);
+ } else {
+ msg->u.reply.body = body;
+ spin_lock(&xs_state.reply_lock);
+ list_add_tail(&msg->u.reply.list, &xs_state.reply_list);
+ spin_unlock(&xs_state.reply_lock);
+ wake_up(&xs_state.reply_waitq);
+ }
+
+ return 0;
+}
+
+static int read_thread(void *unused)
+{
+ int err;
+
+ for (;;) {
+ err = process_msg();
+ if (err)
+ printk(KERN_WARNING "XENBUS error %d while reading "
+ "message\n", err);
+ }
+}
+
+/*
+** Initialize the interface to xenstore.
+*/
int xs_init(void)
{
int err;
- struct task_struct *watcher;
-
+ struct task_struct *reader;
+
+ INIT_LIST_HEAD(&xs_state.reply_list);
+ spin_lock_init(&xs_state.reply_lock);
+ init_waitqueue_head(&xs_state.reply_waitq);
+
+ init_MUTEX(&xs_state.request_mutex);
+ init_MUTEX(&xs_state.transaction_mutex);
+ xs_state.transaction_pid = -1;
+
+ /* Initialize the shared memory rings to talk to xenstored */
err = xb_init_comms();
if (err)
return err;

- watcher = kthread_run(watch_thread, NULL, "kxbwatch");
- if (IS_ERR(watcher))
- return PTR_ERR(watcher);
+ reader = kthread_run(read_thread, NULL, "xenbusd");
+ if (IS_ERR(reader))
+ return PTR_ERR(reader);
+
return 0;
}

diff -r 0e7c48861e95 -r 1ac39c7a0435 linux-2.6-xen-sparse/include/asm-xen/xenbus.h
--- a/linux-2.6-xen-sparse/include/asm-xen/xenbus.h Mon Oct 10 13:42:38 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/xenbus.h Mon Oct 10 13:46:53 2005
@@ -78,30 +78,35 @@
int xenbus_register_backend(struct xenbus_driver *drv);
void xenbus_unregister_driver(struct xenbus_driver *drv);

-/* Caller must hold this lock to call these functions: it's also held
- * across watch callbacks. */
-extern struct semaphore xenbus_lock;
+struct xenbus_transaction;

-char **xenbus_directory(const char *dir, const char *node, unsigned int *num);
-void *xenbus_read(const char *dir, const char *node, unsigned int *len);
-int xenbus_write(const char *dir, const char *node, const char *string);
-int xenbus_mkdir(const char *dir, const char *node);
-int xenbus_exists(const char *dir, const char *node);
-int xenbus_rm(const char *dir, const char *node);
-int xenbus_transaction_start(void);
-int xenbus_transaction_end(int abort);
+char **xenbus_directory(struct xenbus_transaction *t,
+ const char *dir, const char *node, unsigned int *num);
+void *xenbus_read(struct xenbus_transaction *t,
+ const char *dir, const char *node, unsigned int *len);
+int xenbus_write(struct xenbus_transaction *t,
+ const char *dir, const char *node, const char *string);
+int xenbus_mkdir(struct xenbus_transaction *t,
+ const char *dir, const char *node);
+int xenbus_exists(struct xenbus_transaction *t,
+ const char *dir, const char *node);
+int xenbus_rm(struct xenbus_transaction *t, const char *dir, const char *node);
+struct xenbus_transaction *xenbus_transaction_start(void);
+int xenbus_transaction_end(struct xenbus_transaction *t, int abort);

/* Single read and scanf: returns -errno or num scanned if > 0. */
-int xenbus_scanf(const char *dir, const char *node, const char *fmt, ...)
- __attribute__((format(scanf, 3, 4)));
+int xenbus_scanf(struct xenbus_transaction *t,
+ const char *dir, const char *node, const char *fmt, ...)
+ __attribute__((format(scanf, 4, 5)));

/* Single printf and write: returns -errno or 0. */
-int xenbus_printf(const char *dir, const char *node, const char *fmt, ...)
- __attribute__((format(printf, 3, 4)));
+int xenbus_printf(struct xenbus_transaction *t,
+ const char *dir, const char *node, const char *fmt, ...)
+ __attribute__((format(printf, 4, 5)));

/* Generic read function: NULL-terminated triples of name,
* sprintf-style type string, and pointer. Returns 0 or errno.*/
-int xenbus_gather(const char *dir, ...);
+int xenbus_gather(struct xenbus_transaction *t, const char *dir, ...);

/* Report a (negative) errno into the store, with explanation. */
void xenbus_dev_error(struct xenbus_device *dev, int err, const char *fmt,...);
@@ -113,7 +118,11 @@
struct xenbus_watch
{
struct list_head list;
+
+ /* Path being watched. */
char *node;
+
+ /* Callback (executed in a process context with no locks held). */
void (*callback)(struct xenbus_watch *,
const char **vec, unsigned int len);
};
@@ -124,7 +133,11 @@

int register_xenbus_watch(struct xenbus_watch *watch);
void unregister_xenbus_watch(struct xenbus_watch *watch);
-void reregister_xenbus_watches(void);
+void xs_suspend(void);
+void xs_resume(void);
+
+/* Used by xenbus_dev to borrow kernel's store connection. */
+void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg);

/* Called from xen core code. */
void xenbus_suspend(void);
diff -r 0e7c48861e95 -r 1ac39c7a0435 tools/blktap/xenbus.c
--- a/tools/blktap/xenbus.c Mon Oct 10 13:42:38 2005
+++ b/tools/blktap/xenbus.c Mon Oct 10 13:46:53 2005
@@ -260,10 +260,6 @@
node = res[XS_WATCH_PATH];
token = res[XS_WATCH_TOKEN];

- er = xs_acknowledge_watch(h, token);
- if (er == 0)
- warn("Couldn't acknowledge watch (%s)", token);
-
w = find_watch(token);
if (!w)
{
diff -r 0e7c48861e95 -r 1ac39c7a0435 tools/console/client/main.c
--- a/tools/console/client/main.c Mon Oct 10 13:42:38 2005
+++ b/tools/console/client/main.c Mon Oct 10 13:46:53 2005
@@ -220,7 +220,7 @@
if (path == NULL)
err(ENOMEM, "realloc");
strcat(path, "/console/tty");
- str_pty = xs_read(xs, path, &len);
+ str_pty = xs_read(xs, NULL, path, &len);

/* FIXME consoled currently does not assume domain-0 doesn't have a
console which is good when we break domain-0 up. To keep us
@@ -245,7 +245,7 @@
struct timeval tv = { 0, 500 };
select(0, NULL, NULL, NULL, &tv); /* pause briefly */

- str_pty = xs_read(xs, path, &len);
+ str_pty = xs_read(xs, NULL, path, &len);
}

if (str_pty == NULL) {
diff -r 0e7c48861e95 -r 1ac39c7a0435 tools/console/daemon/io.c
--- a/tools/console/daemon/io.c Mon Oct 10 13:42:38 2005
+++ b/tools/console/daemon/io.c Mon Oct 10 13:46:53 2005
@@ -179,7 +179,7 @@
success = asprintf(&path, "%s/tty", dom->conspath) != -1;
if (!success)
goto out;
- success = xs_write(xs, path, slave, strlen(slave));
+ success = xs_write(xs, NULL, path, slave, strlen(slave));
free(path);
if (!success)
goto out;
@@ -187,7 +187,7 @@
success = asprintf(&path, "%s/limit", dom->conspath) != -1;
if (!success)
goto out;
- data = xs_read(xs, path, &len);
+ data = xs_read(xs, NULL, path, &len);
if (data) {
dom->buffer.max_capacity = strtoul(data, 0, 0);
free(data);
@@ -216,7 +216,7 @@
char *p;

asprintf(&path, "%s/%s", dir, name);
- p = xs_read(xs, path, NULL);
+ p = xs_read(xs, NULL, path, NULL);
free(path);
if (p == NULL) {
ret = ENOENT;
@@ -505,7 +505,6 @@
domain_create_ring(dom);
}

- xs_acknowledge_watch(xs, vec[1]);
free(vec);
}

diff -r 0e7c48861e95 -r 1ac39c7a0435 tools/python/xen/lowlevel/xs/xs.c
--- a/tools/python/xen/lowlevel/xs/xs.c Mon Oct 10 13:42:38 2005
+++ b/tools/python/xen/lowlevel/xs/xs.c Mon Oct 10 13:46:53 2005
@@ -80,8 +80,8 @@

static PyObject *xspy_read(PyObject *self, PyObject *args, PyObject *kwds)
{
- static char *kwd_spec[] = { "path", NULL };
- static char *arg_spec = "s|";
+ static char *kwd_spec[] = { "transaction", "path", NULL };
+ static char *arg_spec = "ss";
char *path = NULL;

struct xs_handle *xh = xshandle(self);
@@ -89,13 +89,19 @@
unsigned int xsval_n = 0;
PyObject *val = NULL;

- if (!xh)
- goto exit;
- if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
- &path))
- goto exit;
- Py_BEGIN_ALLOW_THREADS
- xsval = xs_read(xh, path, &xsval_n);
+ struct xs_transaction_handle *th;
+ char *thstr;
+
+ if (!xh)
+ goto exit;
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
+ &thstr, &path))
+ goto exit;
+
+ th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16);
+
+ Py_BEGIN_ALLOW_THREADS
+ xsval = xs_read(xh, th, path, &xsval_n);
Py_END_ALLOW_THREADS
if (!xsval) {
if (errno == ENOENT) {
@@ -123,8 +129,8 @@

static PyObject *xspy_write(PyObject *self, PyObject *args, PyObject *kwds)
{
- static char *kwd_spec[] = { "path", "data", NULL };
- static char *arg_spec = "ss#";
+ static char *kwd_spec[] = { "transaction", "path", "data", NULL };
+ static char *arg_spec = "sss#";
char *path = NULL;
char *data = NULL;
int data_n = 0;
@@ -133,13 +139,19 @@
PyObject *val = NULL;
int xsval = 0;

- if (!xh)
- goto exit;
- if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
- &path, &data, &data_n))
- goto exit;
- Py_BEGIN_ALLOW_THREADS
- xsval = xs_write(xh, path, data, data_n);
+ struct xs_transaction_handle *th;
+ char *thstr;
+
+ if (!xh)
+ goto exit;
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
+ &thstr, &path, &data, &data_n))
+ goto exit;
+
+ th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16);
+
+ Py_BEGIN_ALLOW_THREADS
+ xsval = xs_write(xh, th, path, data, data_n);
Py_END_ALLOW_THREADS
if (!xsval) {
PyErr_SetFromErrno(PyExc_RuntimeError);
@@ -162,8 +174,8 @@

static PyObject *xspy_ls(PyObject *self, PyObject *args, PyObject *kwds)
{
- static char *kwd_spec[] = { "path", NULL };
- static char *arg_spec = "s|";
+ static char *kwd_spec[] = { "transaction", "path", NULL };
+ static char *arg_spec = "ss";
char *path = NULL;

struct xs_handle *xh = xshandle(self);
@@ -172,12 +184,20 @@
unsigned int xsval_n = 0;
int i;

- if (!xh)
- goto exit;
- if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
- goto exit;
- Py_BEGIN_ALLOW_THREADS
- xsval = xs_directory(xh, path, &xsval_n);
+ struct xs_transaction_handle *th;
+ char *thstr;
+
+ if (!xh)
+ goto exit;
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
+ &thstr, &path))
+ goto exit;
+
+
+ th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16);
+
+ Py_BEGIN_ALLOW_THREADS
+ xsval = xs_directory(xh, th, path, &xsval_n);
Py_END_ALLOW_THREADS
if (!xsval) {
if (errno == ENOENT) {
@@ -205,20 +225,27 @@

static PyObject *xspy_mkdir(PyObject *self, PyObject *args, PyObject *kwds)
{
- static char *kwd_spec[] = { "path", NULL };
- static char *arg_spec = "s|";
+ static char *kwd_spec[] = { "transaction", "path", NULL };
+ static char *arg_spec = "ss";
char *path = NULL;

struct xs_handle *xh = xshandle(self);
PyObject *val = NULL;
int xsval = 0;

- if (!xh)
- goto exit;
- if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
- goto exit;
- Py_BEGIN_ALLOW_THREADS
- xsval = xs_mkdir(xh, path);
+ struct xs_transaction_handle *th;
+ char *thstr;
+
+ if (!xh)
+ goto exit;
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
+ &thstr, &path))
+ goto exit;
+
+ th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16);
+
+ Py_BEGIN_ALLOW_THREADS
+ xsval = xs_mkdir(xh, th, path);
Py_END_ALLOW_THREADS
if (!xsval) {
PyErr_SetFromErrno(PyExc_RuntimeError);
@@ -240,20 +267,27 @@

static PyObject *xspy_rm(PyObject *self, PyObject *args, PyObject *kwds)
{
- static char *kwd_spec[] = { "path", NULL };
- static char *arg_spec = "s|";
+ static char *kwd_spec[] = { "transaction", "path", NULL };
+ static char *arg_spec = "ss";
char *path = NULL;

struct xs_handle *xh = xshandle(self);
PyObject *val = NULL;
int xsval = 0;

- if (!xh)
- goto exit;
- if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
- goto exit;
- Py_BEGIN_ALLOW_THREADS
- xsval = xs_rm(xh, path);
+ struct xs_transaction_handle *th;
+ char *thstr;
+
+ if (!xh)
+ goto exit;
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
+ &thstr, &path))
+ goto exit;
+
+ th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16);
+
+ Py_BEGIN_ALLOW_THREADS
+ xsval = xs_rm(xh, th, path);
Py_END_ALLOW_THREADS
if (!xsval && errno != ENOENT) {
PyErr_SetFromErrno(PyExc_RuntimeError);
@@ -276,8 +310,8 @@
static PyObject *xspy_get_permissions(PyObject *self, PyObject *args,
PyObject *kwds)
{
- static char *kwd_spec[] = { "path", NULL };
- static char *arg_spec = "s|";
+ static char *kwd_spec[] = { "transaction", "path", NULL };
+ static char *arg_spec = "ss";
char *path = NULL;

struct xs_handle *xh = xshandle(self);
@@ -286,12 +320,19 @@
unsigned int perms_n = 0;
int i;

- if (!xh)
- goto exit;
- if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
- goto exit;
- Py_BEGIN_ALLOW_THREADS
- perms = xs_get_permissions(xh, path, &perms_n);
+ struct xs_transaction_handle *th;
+ char *thstr;
+
+ if (!xh)
+ goto exit;
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
+ &thstr, &path))
+ goto exit;
+
+ th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16);
+
+ Py_BEGIN_ALLOW_THREADS
+ perms = xs_get_permissions(xh, th, path, &perms_n);
Py_END_ALLOW_THREADS
if (!perms) {
PyErr_SetFromErrno(PyExc_RuntimeError);
@@ -321,8 +362,8 @@
static PyObject *xspy_set_permissions(PyObject *self, PyObject *args,
PyObject *kwds)
{
- static char *kwd_spec[] = { "path", "perms", NULL };
- static char *arg_spec = "sO";
+ static char *kwd_spec[] = { "transaction", "path", "perms", NULL };
+ static char *arg_spec = "ssO";
char *path = NULL;
PyObject *perms = NULL;
static char *perm_names[] = { "dom", "read", "write", NULL };
@@ -335,11 +376,17 @@
PyObject *tuple0 = NULL;
PyObject *val = NULL;

- if (!xh)
- goto exit;
- if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
- &path, &perms))
- goto exit;
+ struct xs_transaction_handle *th;
+ char *thstr;
+
+ if (!xh)
+ goto exit;
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
+ &thstr, &path, &perms))
+ goto exit;
+
+ th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16);
+
if (!PyList_Check(perms)) {
PyErr_SetString(PyExc_RuntimeError, "perms must be a list");
goto exit;
@@ -369,7 +416,7 @@
xsperms[i].perms |= XS_PERM_WRITE;
}
Py_BEGIN_ALLOW_THREADS
- xsval = xs_set_permissions(xh, path, xsperms, xsperms_n);
+ xsval = xs_set_permissions(xh, th, path, xsperms, xsperms_n);
Py_END_ALLOW_THREADS
if (!xsval) {
PyErr_SetFromErrno(PyExc_RuntimeError);
@@ -442,9 +489,6 @@

#define xspy_read_watch_doc "\n" \
"Read a watch notification.\n" \
- "The notification must be acknowledged by passing\n" \
- "the token to acknowledge_watch().\n" \
- " path [string]: xenstore path.\n" \
"\n" \
"Returns: [tuple] (path, token).\n" \
"Raises RuntimeError on error.\n" \
@@ -492,44 +536,6 @@
exit:
if (xsval)
free(xsval);
- return val;
-}
-
-#define xspy_acknowledge_watch_doc "\n" \
- "Acknowledge a watch notification that has been read.\n" \
- " token [string] : from the watch notification\n" \
- "\n" \
- "Returns None on success.\n" \
- "Raises RuntimeError on error.\n" \
- "\n"
-
-static PyObject *xspy_acknowledge_watch(PyObject *self, PyObject *args,
- PyObject *kwds)
-{
- static char *kwd_spec[] = { "token", NULL };
- static char *arg_spec = "O";
- PyObject *token;
- char token_str[MAX_STRLEN(unsigned long) + 1];
-
- struct xs_handle *xh = xshandle(self);
- PyObject *val = NULL;
- int xsval = 0;
-
- if (!xh)
- goto exit;
- if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &token))
- goto exit;
- sprintf(token_str, "%li", (unsigned long)token);
- Py_BEGIN_ALLOW_THREADS
- xsval = xs_acknowledge_watch(xh, token_str);
- Py_END_ALLOW_THREADS
- if (!xsval) {
- PyErr_SetFromErrno(PyExc_RuntimeError);
- goto exit;
- }
- Py_INCREF(Py_None);
- val = Py_None;
- exit:
return val;
}

@@ -584,9 +590,8 @@

#define xspy_transaction_start_doc "\n" \
"Start a transaction.\n" \
- "Only one transaction can be active at a time.\n" \
"\n" \
- "Returns None on success.\n" \
+ "Returns transaction handle on success.\n" \
"Raises RuntimeError on error.\n" \
"\n"

@@ -599,21 +604,23 @@

struct xs_handle *xh = xshandle(self);
PyObject *val = NULL;
- int xsval = 0;
+ struct xs_transaction_handle *th;
+ char thstr[20];

if (!xh)
goto exit;
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
goto exit;
Py_BEGIN_ALLOW_THREADS
- xsval = xs_transaction_start(xh);
- Py_END_ALLOW_THREADS
- if (!xsval) {
- PyErr_SetFromErrno(PyExc_RuntimeError);
- goto exit;
- }
- Py_INCREF(Py_None);
- val = Py_None;
+ th = xs_transaction_start(xh);
+ Py_END_ALLOW_THREADS
+ if (th == NULL) {
+ PyErr_SetFromErrno(PyExc_RuntimeError);
+ goto exit;
+ }
+
+ sprintf(thstr, "%lX", (unsigned long)th);
+ val = PyString_FromString(thstr);
exit:
return val;
}
@@ -630,20 +637,27 @@
static PyObject *xspy_transaction_end(PyObject *self, PyObject *args,
PyObject *kwds)
{
- static char *kwd_spec[] = { "abort", NULL };
- static char *arg_spec = "|i";
+ static char *kwd_spec[] = { "transaction", "abort", NULL };
+ static char *arg_spec = "s|i";
int abort = 0;

struct xs_handle *xh = xshandle(self);
PyObject *val = NULL;
int xsval = 0;

- if (!xh)
- goto exit;
- if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &abort))
- goto exit;
- Py_BEGIN_ALLOW_THREADS
- xsval = xs_transaction_end(xh, abort);
+ struct xs_transaction_handle *th;
+ char *thstr;
+
+ if (!xh)
+ goto exit;
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
+ &thstr, &abort))
+ goto exit;
+
+ th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16);
+
+ Py_BEGIN_ALLOW_THREADS
+ xsval = xs_transaction_end(xh, th, abort);
Py_END_ALLOW_THREADS
if (!xsval) {
if (errno == EAGAIN) {
@@ -833,7 +847,6 @@
XSPY_METH(set_permissions),
XSPY_METH(watch),
XSPY_METH(read_watch),
- XSPY_METH(acknowledge_watch),
XSPY_METH(unwatch),
XSPY_METH(transaction_start),
XSPY_METH(transaction_end),
diff -r 0e7c48861e95 -r 1ac39c7a0435 tools/python/xen/xend/xenstore/xstransact.py
--- a/tools/python/xen/xend/xenstore/xstransact.py Mon Oct 10 13:42:38 2005
+++ b/tools/python/xen/xend/xenstore/xstransact.py Mon Oct 10 13:46:53 2005
@@ -14,29 +14,34 @@
class xstransact:

def __init__(self, path):
- self.in_transaction = False
self.path = path.rstrip("/")
- xshandle().transaction_start()
+ self.transaction = xshandle().transaction_start()
self.in_transaction = True

def __del__(self):
if self.in_transaction:
- xshandle().transaction_end(True)
+ xshandle().transaction_end(self.transaction, True)

def commit(self):
if not self.in_transaction:
raise RuntimeError
self.in_transaction = False
- return xshandle().transaction_end(False)
+ rc = xshandle().transaction_end(self.transaction, False)
+ self.transaction = "0"
+ return rc

def abort(self):
+ if not self.in_transaction:
+ return True
self.in_transaction = False
- return xshandle().transaction_end(True)
+ rc = xshandle().transaction_end(self.transaction, True)
+ self.transaction = "0"
+ return rc

def _read(self, key):
path = "%s/%s" % (self.path, key)
try:
- return xshandle().read(path)
+ return xshandle().read(self.transaction, path)
except RuntimeError, ex:
raise RuntimeError(ex.args[0],
'%s, while reading %s' % (ex.args[1], path))
@@ -50,7 +55,7 @@
instead.
"""
if len(args) == 0:
- return xshandle().read(self.path)
+ return xshandle().read(self.transaction, self.path)
if len(args) == 1:
return self._read(args[0])
ret = []
@@ -61,7 +66,7 @@
def _write(self, key, data):
path = "%s/%s" % (self.path, key)
try:
- xshandle().write(path, data)
+ xshandle().write(self.transaction, path, data)
except RuntimeError, ex:
raise RuntimeError(ex.args[0],
('%s, while writing %s : %s' %
@@ -93,7 +98,7 @@

def _remove(self, key):
path = "%s/%s" % (self.path, key)
- return xshandle().rm(path)
+ return xshandle().rm(self.transaction, path)

def remove(self, *args):
"""If no arguments are given, remove this transaction's path.
@@ -101,14 +106,14 @@
path, and remove each of those instead.
"""
if len(args) == 0:
- xshandle().rm(self.path)
+ xshandle().rm(self.transaction, self.path)
else:
for key in args:
self._remove(key)

def _list(self, key):
path = "%s/%s" % (self.path, key)
- l = xshandle().ls(path)
+ l = xshandle().ls(self.transaction, path)
if l:
return map(lambda x: key + "/" + x, l)
return []
@@ -120,7 +125,7 @@
path, and return the cumulative listing of each of those instead.
"""
if len(args) == 0:
- ret = xshandle().ls(self.path)
+ ret = xshandle().ls(self.transaction, self.path)
if ret is None:
return []
else:
@@ -136,11 +141,11 @@
ret = []
for key in keys:
new_subdir = subdir + "/" + key
- l = xshandle().ls(new_subdir)
+ l = xshandle().ls(self.transaction, new_subdir)
if l:
ret.append([key, self.list_recursive_(new_subdir, l)])
else:
- ret.append([key, xshandle().read(new_subdir)])
+ ret.append([key, xshandle().read(self.transaction, new_subdir)])
return ret


diff -r 0e7c48861e95 -r 1ac39c7a0435 tools/python/xen/xend/xenstore/xswatch.py
--- a/tools/python/xen/xend/xenstore/xswatch.py Mon Oct 10 13:42:38 2005
+++ b/tools/python/xen/xend/xenstore/xswatch.py Mon Oct 10 13:46:53 2005
@@ -8,6 +8,7 @@
import select
import threading
from xen.lowlevel import xs
+from xen.xend.xenstore.xsutil import xshandle

class xswatch:

@@ -27,10 +28,7 @@
if cls.watchThread:
cls.xslock.release()
return
- # XXX: When we fix xenstored to have better watch semantics,
- # this can change to shared xshandle(). Currently that would result
- # in duplicate watch firings, thus failed extra xs.acknowledge_watch.
- cls.xs = xs.open()
+ cls.xs = xshandle()
cls.watchThread = threading.Thread(name="Watcher",
target=cls.watchMain)
cls.watchThread.setDaemon(True)
@@ -43,11 +41,10 @@
while True:
try:
we = cls.xs.read_watch()
- watch = we[1]
- cls.xs.acknowledge_watch(watch)
except RuntimeError, ex:
print ex
raise
+ watch = we[1]
watch.fn(*watch.args, **watch.kwargs)

watchMain = classmethod(watchMain)
diff -r 0e7c48861e95 -r 1ac39c7a0435 tools/xenstore/Makefile
--- a/tools/xenstore/Makefile Mon Oct 10 13:42:38 2005
+++ b/tools/xenstore/Makefile Mon Oct 10 13:46:53 2005
@@ -8,7 +8,7 @@
INSTALL_DIR = $(INSTALL) -d -m0755

PROFILE=#-pg
-BASECFLAGS=-Wall -W -g -Werror
+BASECFLAGS=-Wall -g -Werror
# Make gcc generate dependencies.
BASECFLAGS += -Wp,-MD,.$(@F).d
PROG_DEP = .*.d
diff -r 0e7c48861e95 -r 1ac39c7a0435 tools/xenstore/testsuite/07watch.test
--- a/tools/xenstore/testsuite/07watch.test Mon Oct 10 13:42:38 2005
+++ b/tools/xenstore/testsuite/07watch.test Mon Oct 10 13:46:53 2005
@@ -5,7 +5,6 @@
2 write /test contents2
expect 1:/test:token
1 waitwatch
-1 ackwatch token
1 close

# Check that reads don't set it off.
@@ -22,15 +21,12 @@
2 mkdir /dir/newdir
expect 1:/dir/newdir:token
1 waitwatch
-1 ackwatch token
2 setperm /dir/newdir 0 READ
expect 1:/dir/newdir:token
1 waitwatch
-1 ackwatch token
2 rm /dir/newdir
expect 1:/dir/newdir:token
1 waitwatch
-1 ackwatch token
1 close
2 close

@@ -49,7 +45,6 @@
read /dir/test
expect /dir/test:token
waitwatch
-ackwatch token
close

# watch priority test: all simultaneous
@@ -59,13 +54,10 @@
write /dir/test contents
expect 3:/dir/test:token3
3 waitwatch
-3 ackwatch token3
expect 2:/dir/test:token2
2 waitwatch
-2 ackwatch token2
expect 1:/dir/test:token1
1 waitwatch
-1 ackwatch token1
1 close
2 close
3 close
@@ -79,7 +71,6 @@
2 close
expect 1:/dir/test:token1
1 waitwatch
-1 ackwatch token1
1 close

# If one dies (without reading at all), the other should still get ack.
@@ -89,7 +80,6 @@
2 close
expect 1:/dir/test:token1
1 waitwatch
-1 ackwatch token1
1 close
2 close

@@ -111,7 +101,6 @@
2 unwatch /dir token2
expect 1:/dir/test:token1
1 waitwatch
-1 ackwatch token1
1 close
2 close

@@ -123,14 +112,12 @@
write /dir/test contents2
expect 1:/dir/test:token2
1 waitwatch
-1 ackwatch token2

# check we only get notified once.
1 watch /test token
2 write /test contents2
expect 1:/test:token
1 waitwatch
-1 ackwatch token
expect 1: waitwatch failed: Connection timed out
1 waitwatch
1 close
@@ -142,13 +129,10 @@
2 write /test3 contents
expect 1:/test1:token
1 waitwatch
-1 ackwatch token
expect 1:/test2:token
1 waitwatch
-1 ackwatch token
expect 1:/test3:token
1 waitwatch
-1 ackwatch token
1 close

# Creation of subpaths should be covered correctly.
@@ -157,10 +141,8 @@
2 write /test/subnode/subnode contents2
expect 1:/test/subnode:token
1 waitwatch
-1 ackwatch token
expect 1:/test/subnode/subnode:token
1 waitwatch
-1 ackwatch token
expect 1: waitwatch failed: Connection timed out
1 waitwatch
1 close
@@ -171,7 +153,6 @@
1 watchnoack / token2 0
expect 1:/test/subnode:token
1 waitwatch
-1 ackwatch token
expect 1:/:token2
1 waitwatch
expect 1: waitwatch failed: Connection timed out
@@ -183,7 +164,6 @@
2 rm /test
expect 1:/test/subnode:token
1 waitwatch
-1 ackwatch token

# Watch should not double-send after we ack, even if we did something in between.
1 watch /test2 token
@@ -192,6 +172,5 @@
1 waitwatch
expect 1:contents2
1 read /test2/foo
-1 ackwatch token
expect 1: waitwatch failed: Connection timed out
1 waitwatch
diff -r 0e7c48861e95 -r 1ac39c7a0435 tools/xenstore/testsuite/08transaction.test
--- a/tools/xenstore/testsuite/08transaction.test Mon Oct 10 13:42:38 2005
+++ b/tools/xenstore/testsuite/08transaction.test Mon Oct 10 13:46:53 2005
@@ -68,7 +68,6 @@
2 commit
expect 1:/test/dir/sub:token
1 waitwatch
-1 ackwatch token
1 close

# Rm inside transaction works like rm outside: children get notified.
@@ -78,7 +77,6 @@
2 commit
expect 1:/test/dir/sub:token
1 waitwatch
-1 ackwatch token
1 close

# Multiple events from single transaction don't trigger assert
@@ -89,8 +87,6 @@
2 commit
expect 1:/test/1:token
1 waitwatch
-1 ackwatch token
expect 1:/test/2:token
1 waitwatch
-1 ackwatch token
1 close
diff -r 0e7c48861e95 -r 1ac39c7a0435 tools/xenstore/testsuite/10domain-homedir.test
--- a/tools/xenstore/testsuite/10domain-homedir.test Mon Oct 10 13:42:38 2005
+++ b/tools/xenstore/testsuite/10domain-homedir.test Mon Oct 10 13:46:53 2005
@@ -16,4 +16,3 @@
write /home/foo/bar contents
expect 1:foo/bar:token
1 waitwatch
-1 ackwatch token
diff -r 0e7c48861e95 -r 1ac39c7a0435 tools/xenstore/testsuite/11domain-watch.test
--- a/tools/xenstore/testsuite/11domain-watch.test Mon Oct 10 13:42:38 2005
+++ b/tools/xenstore/testsuite/11domain-watch.test Mon Oct 10 13:46:53 2005
@@ -10,7 +10,6 @@
write /test contents2
expect 1:/test:token
1 waitwatch
-1 ackwatch token
1 unwatch /test token
release 1
1 close
@@ -25,7 +24,6 @@
1 write /dir/test4 contents4
expect 1:/dir/test:token
1 waitwatch
-1 ackwatch token
release 1
1 close

diff -r 0e7c48861e95 -r 1ac39c7a0435 tools/xenstore/testsuite/12readonly.test
--- a/tools/xenstore/testsuite/12readonly.test Mon Oct 10 13:42:38 2005
+++ b/tools/xenstore/testsuite/12readonly.test Mon Oct 10 13:46:53 2005
@@ -36,4 +36,3 @@
1 write /test contents
expect /test:token
waitwatch
-ackwatch token
diff -r 0e7c48861e95 -r 1ac39c7a0435 tools/xenstore/testsuite/13watch-ack.test
--- a/tools/xenstore/testsuite/13watch-ack.test Mon Oct 10 13:42:38 2005
+++ b/tools/xenstore/testsuite/13watch-ack.test Mon Oct 10 13:46:53 2005
@@ -18,5 +18,4 @@
1 waitwatch
3 write /test/1 contents1
4 write /test/3 contents3
-1 ackwatch token2
1 close
diff -r 0e7c48861e95 -r 1ac39c7a0435 tools/xenstore/xenstore_client.c
--- a/tools/xenstore/xenstore_client.c Mon Oct 10 13:42:38 2005
+++ b/tools/xenstore/xenstore_client.c Mon Oct 10 13:46:53 2005
@@ -32,6 +32,7 @@
main(int argc, char **argv)
{
struct xs_handle *xsh;
+ struct xs_transaction_handle *xth;
bool success;
int ret = 0;
#if defined(CLIENT_read) || defined(CLIENT_list)
@@ -84,13 +85,13 @@
#endif

again:
- success = xs_transaction_start(xsh);
- if (!success)
+ xth = xs_transaction_start(xsh);
+ if (xth == NULL)
errx(1, "couldn't start transaction");

while (optind < argc) {
#if defined(CLIENT_read)
- char *val = xs_read(xsh, argv[optind], NULL);
+ char *val = xs_read(xsh, xth, argv[optind], NULL);
if (val == NULL) {
warnx("couldn't read path %s", argv[optind]);
ret = 1;
@@ -102,7 +103,7 @@
free(val);
optind++;
#elif defined(CLIENT_write)
- success = xs_write(xsh, argv[optind], argv[optind + 1],
+ success = xs_write(xsh, xth, argv[optind], argv[optind + 1],
strlen(argv[optind + 1]));
if (!success) {
warnx("could not write path %s", argv[optind]);
@@ -111,7 +112,7 @@
}
optind += 2;
#elif defined(CLIENT_rm)
- success = xs_rm(xsh, argv[optind]);
+ success = xs_rm(xsh, xth, argv[optind]);
if (!success) {
warnx("could not remove path %s", argv[optind]);
ret = 1;
@@ -119,7 +120,7 @@
}
optind++;
#elif defined(CLIENT_exists)
- char *val = xs_read(xsh, argv[optind], NULL);
+ char *val = xs_read(xsh, xth, argv[optind], NULL);
if (val == NULL) {
ret = 1;
goto out;
@@ -128,7 +129,7 @@
optind++;
#elif defined(CLIENT_list)
unsigned int i, num;
- char **list = xs_directory(xsh, argv[optind], &num);
+ char **list = xs_directory(xsh, xth, argv[optind], &num);
if (list == NULL) {
warnx("could not list path %s", argv[optind]);
ret = 1;
@@ -145,7 +146,7 @@
}

out:
- success = xs_transaction_end(xsh, ret ? true : false);
+ success = xs_transaction_end(xsh, xth, ret ? true : false);
if (!success) {
if (ret == 0 && errno == EAGAIN)
goto again;
diff -r 0e7c48861e95 -r 1ac39c7a0435 tools/xenstore/xenstored_core.c
--- a/tools/xenstore/xenstored_core.c Mon Oct 10 13:42:38 2005
+++ b/tools/xenstore/xenstored_core.c Mon Oct 10 13:46:53 2005
@@ -154,7 +154,6 @@
case XS_READ: return "READ";
case XS_GET_PERMS: return "GET_PERMS";
case XS_WATCH: return "WATCH";
- case XS_WATCH_ACK: return "WATCH_ACK";
case XS_UNWATCH: return "UNWATCH";
case XS_TRANSACTION_START: return "TRANSACTION_START";
case XS_TRANSACTION_END: return "TRANSACTION_END";
@@ -236,52 +235,50 @@
talloc_free(str);
}

-static bool write_message(struct connection *conn)
+static bool write_messages(struct connection *conn)
{
int ret;
- struct buffered_data *out = conn->out;
-
- if (out->inhdr) {
- if (verbose)
- xprintf("Writing msg %s (%s) out to %p\n",
- sockmsg_string(out->hdr.msg.type),
- out->buffer, conn);
- ret = conn->write(conn, out->hdr.raw + out->used,
- sizeof(out->hdr) - out->used);
+ struct buffered_data *out, *tmp;
+
+ list_for_each_entry_safe(out, tmp, &conn->out_list, list) {
+ if (out->inhdr) {
+ if (verbose)
+ xprintf("Writing msg %s (%s) out to %p\n",
+ sockmsg_string(out->hdr.msg.type),
+ out->buffer, conn);
+ ret = conn->write(conn, out->hdr.raw + out->used,
+ sizeof(out->hdr) - out->used);
+ if (ret < 0)
+ return false;
+
+ out->used += ret;
+ if (out->used < sizeof(out->hdr))
+ return true;
+
+ out->inhdr = false;
+ out->used = 0;
+
+ /* Second write might block if non-zero. */
+ if (out->hdr.msg.len && !conn->domain)
+ return true;
+ }
+
+ ret = conn->write(conn, out->buffer + out->used,
+ out->hdr.msg.len - out->used);
+
if (ret < 0)
return false;

out->used += ret;
- if (out->used < sizeof(out->hdr))
+ if (out->used != out->hdr.msg.len)
return true;

- out->inhdr = false;
- out->used = 0;
-
- /* Second write might block if non-zero. */
- if (out->hdr.msg.len && !conn->domain)
- return true;
- }
-
- ret = conn->write(conn, out->buffer + out->used,
- out->hdr.msg.len - out->used);
-
- if (ret < 0)
- return false;
-
- out->used += ret;
- if (out->used != out->hdr.msg.len)
- return true;
-
- trace_io(conn, "OUT", out);
- conn->out = NULL;
- talloc_free(out);
-
- queue_next_event(conn);
-
- /* No longer busy? */
- if (!conn->out)
- conn->state = OK;
+ trace_io(conn, "OUT", out);
+
+ list_del(&out->list);
+ talloc_free(out);
+ }
+
return true;
}

@@ -298,9 +295,9 @@
FD_SET(conn->fd, &set);
none.tv_sec = none.tv_usec = 0;

- while (conn->out
+ while (!list_empty(&conn->out_list)
&& select(conn->fd+1, NULL, &set, NULL, &none) == 1)
- if (!write_message(conn))
+ if (!write_messages(conn))
break;
close(conn->fd);
}
@@ -327,9 +324,8 @@
list_for_each_entry(i, &connections, list) {
if (i->domain)
continue;
- if (i->state == OK)
- FD_SET(i->fd, inset);
- if (i->out)
+ FD_SET(i->fd, inset);
+ if (!list_empty(&i->out_list))
FD_SET(i->fd, outset);
if (i->fd > max)
max = i->fd;
@@ -595,14 +591,7 @@
bdata->hdr.msg.len = len;
memcpy(bdata->buffer, data, len);

- /* There might be an event going out now. Queue behind it. */
- if (conn->out) {
- assert(conn->out->hdr.msg.type == XS_WATCH_EVENT);
- assert(!conn->waiting_reply);
- conn->waiting_reply = bdata;
- } else
- conn->out = bdata;
- conn->state = BUSY;
+ list_add_tail(&bdata->list, &conn->out_list);
}

/* Some routines (write, mkdir, etc) just need a non-error return */
@@ -1103,10 +1092,6 @@
do_watch(conn, in);
break;

- case XS_WATCH_ACK:
- do_watch_ack(conn, onearg(in));
- break;
-
case XS_UNWATCH:
do_unwatch(conn, in);
break;
@@ -1153,8 +1138,6 @@
enum xsd_sockmsg_type volatile type = conn->in->hdr.msg.type;
jmp_buf talloc_fail;

- assert(conn->state == OK);
-
/* For simplicity, we kill the connection on OOM. */
talloc_set_fail_handler(out_of_mem, &talloc_fail);
if (setjmp(talloc_fail)) {
@@ -1168,11 +1151,6 @@
xprintf("Got message %s len %i from %p\n",
sockmsg_string(type), conn->in->hdr.msg.len, conn);

- /* We might get a command while waiting for an ack: this means
- * the other end discarded it: we will re-transmit. */
- if (type != XS_WATCH_ACK)
- conn->waiting_for_ack = NULL;
-
/* Careful: process_message may free connection. We detach
* "in" beforehand and allocate the new buffer to avoid
* touching conn after process_message.
@@ -1196,10 +1174,7 @@
static void handle_input(struct connection *conn)
{
int bytes;
- struct buffered_data *in;
-
- assert(conn->state == OK);
- in = conn->in;
+ struct buffered_data *in = conn->in;

/* Not finished header yet? */
if (in->inhdr) {
@@ -1247,7 +1222,7 @@

static void handle_output(struct connection *conn)
{
- if (!write_message(conn))
+ if (!write_messages(conn))
talloc_free(conn);
}

@@ -1264,9 +1239,6 @@
if (!new)
return NULL;

- new->state = OK;
- new->out = new->waiting_reply = NULL;
- new->waiting_for_ack = NULL;
new->fd = -1;
new->id = 0;
new->domain = NULL;
@@ -1274,6 +1246,7 @@
new->write = write;
new->read = read;
new->can_write = true;
+ INIT_LIST_HEAD(&new->out_list);
INIT_LIST_HEAD(&new->watches);

talloc_set_fail_handler(out_of_mem, &talloc_fail);
@@ -1328,23 +1301,17 @@
list_for_each_entry(i, &connections, list) {
printf("Connection %p:\n", i);
printf(" state = %s\n",
- i->state == OK ? "OK"
- : i->state == BUSY ? "BUSY"
- : "INVALID");
+ list_empty(&i->out_list) ? "OK" : "BUSY");
if (i->id)
printf(" id = %i\n", i->id);
if (!i->in->inhdr || i->in->used)
printf(" got %i bytes of %s\n",
i->in->used, i->in->inhdr ? "header" : "data");
+#if 0
if (i->out)
printf(" sending message %s (%s) out\n",
sockmsg_string(i->out->hdr.msg.type),
i->out->buffer);
- if (i->waiting_reply)
- printf(" ... and behind is queued %s (%s)\n",
- sockmsg_string(i->waiting_reply->hdr.msg.type),
- i->waiting_reply->buffer);
-#if 0
if (i->transaction)
dump_transaction(i);
if (i->domain)
@@ -1615,3 +1582,13 @@
max = initialize_set(&inset, &outset, *sock, *ro_sock);
}
}
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r 0e7c48861e95 -r 1ac39c7a0435 tools/xenstore/xenstored_core.h
--- a/tools/xenstore/xenstored_core.h Mon Oct 10 13:42:38 2005
+++ b/tools/xenstore/xenstored_core.h Mon Oct 10 13:46:53 2005
@@ -31,14 +31,19 @@

struct buffered_data
{
+ struct list_head list;
+
/* Are we still doing the header? */
bool inhdr;
+
/* How far are we? */
unsigned int used;
+
union {
struct xsd_sockmsg msg;
char raw[sizeof(struct xsd_sockmsg)];
} hdr;
+
/* The actual data. */
char *buffer;
};
@@ -47,14 +52,6 @@
typedef int connwritefn_t(struct connection *, const void *, unsigned int);
typedef int connreadfn_t(struct connection *, void *, unsigned int);

-enum state
-{
- /* Doing action, not listening */
- BUSY,
- /* Completed */
- OK,
-};
-
struct connection
{
struct list_head list;
@@ -62,26 +59,17 @@
/* The file descriptor we came in on. */
int fd;

- /* Who am I? 0 for socket connections. */
+ /* Who am I? 0 for socket connections. */
domid_t id;
-
- /* Blocked on transaction? Busy? */
- enum state state;

/* Is this a read-only connection? */
bool can_write;
-
- /* Are we waiting for a watch event ack? */
- struct watch *waiting_for_ack;

/* Buffered incoming data. */
struct buffered_data *in;

/* Buffered output data */
- struct buffered_data *out;
-
- /* If we had a watch fire outgoing when we needed to reply... */
- struct buffered_data *waiting_reply;
+ struct list_head out_list;

/* My transaction, if any. */
struct transaction *transaction;
@@ -175,3 +163,13 @@
extern int event_fd;

#endif /* _XENSTORED_CORE_H */
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r 0e7c48861e95 -r 1ac39c7a0435 tools/xenstore/xenstored_domain.c
--- a/tools/xenstore/xenstored_domain.c Mon Oct 10 13:42:38 2005
+++ b/tools/xenstore/xenstored_domain.c Mon Oct 10 13:46:53 2005
@@ -276,12 +276,13 @@

bool domain_can_read(struct connection *conn)
{
- return conn->state == OK && buffer_has_input(conn->domain->input);
+ return buffer_has_input(conn->domain->input);
}

bool domain_can_write(struct connection *conn)
{
- return conn->out && buffer_has_output_room(conn->domain->output);
+ return (!list_empty(&conn->out_list) &&
+ buffer_has_output_room(conn->domain->output));
}

static struct domain *new_domain(void *context, domid_t domid,
diff -r 0e7c48861e95 -r 1ac39c7a0435 tools/xenstore/xenstored_transaction.c
--- a/tools/xenstore/xenstored_transaction.c Mon Oct 10 13:42:38 2005
+++ b/tools/xenstore/xenstored_transaction.c Mon Oct 10 13:46:53 2005
@@ -154,9 +154,9 @@
return;
}

- /* Set to NULL so fire_watches sends events, tdb_context works. */
trans = conn->transaction;
conn->transaction = NULL;
+
/* Attach transaction to arg for auto-cleanup */
talloc_steal(arg, trans);

diff -r 0e7c48861e95 -r 1ac39c7a0435 tools/xenstore/xenstored_watch.c
--- a/tools/xenstore/xenstored_watch.c Mon Oct 10 13:42:38 2005
+++ b/tools/xenstore/xenstored_watch.c Mon Oct 10 13:46:53 2005
@@ -32,17 +32,6 @@
#include "xenstored_test.h"
#include "xenstored_domain.h"

-/* FIXME: time out unacked watches. */
-struct watch_event
-{
- /* The events on this watch. */
- struct list_head list;
-
- /* Data to send (node\0token\0). */
- unsigned int len;
- char *data;
-};
-
struct watch
{
/* Watches on this connection */
@@ -58,54 +47,17 @@
char *node;
};

-/* Look through our watches: if any of them have an event, queue it. */
-void queue_next_event(struct connection *conn)
-{
- struct watch_event *event;
- struct watch *watch;
-
- /* We had a reply queued already? Send it: other end will
- * discard watch. */
- if (conn->waiting_reply) {
- conn->out = conn->waiting_reply;
- conn->waiting_reply = NULL;
- conn->waiting_for_ack = NULL;
- return;
- }
-
- /* If we're already waiting for ack, don't queue more. */
- if (conn->waiting_for_ack)
- return;
-
- list_for_each_entry(watch, &conn->watches, list) {
- event = list_top(&watch->events, struct watch_event, list);
- if (event) {
- conn->waiting_for_ack = watch;
- send_reply(conn,XS_WATCH_EVENT,event->data,event->len);
- break;
- }
- }
-}
-
-static int destroy_watch_event(void *_event)
-{
- struct watch_event *event = _event;
-
- trace_destroy(event, "watch_event");
- return 0;
-}
-
static void add_event(struct connection *conn,
struct watch *watch,
const char *name)
{
- struct watch_event *event;
+ /* Data to send (node\0token\0). */
+ unsigned int len;
+ char *data;

if (!check_event_node(name)) {
/* Can this conn load node, or see that it doesn't exist? */
- struct node *node;
-
- node = get_node(conn, name, XS_PERM_READ);
+ struct node *node = get_node(conn, name, XS_PERM_READ);
if (!node && errno != ENOENT)
return;
}
@@ -116,14 +68,12 @@
name++;
}

- event = talloc(watch, struct watch_event);
- event->len = strlen(name) + 1 + strlen(watch->token) + 1;
- event->data = talloc_array(event, char, event->len);
- strcpy(event->data, name);
- strcpy(event->data + strlen(name) + 1, watch->token);
- talloc_set_destructor(event, destroy_watch_event);
- list_add_tail(&event->list, &watch->events);
- trace_create(event, "watch_event");
+ len = strlen(name) + 1 + strlen(watch->token) + 1;
+ data = talloc_array(watch, char, len);
+ strcpy(data, name);
+ strcpy(data + strlen(name) + 1, watch->token);
+ send_reply(conn, XS_WATCH_EVENT, data, len);
+ talloc_free(data);
}

/* FIXME: we fail to fire on out of memory. Should drop connections. */
@@ -143,11 +93,6 @@
add_event(i, watch, name);
else if (recurse && is_child(watch->node, name))
add_event(i, watch, watch->node);
- else
- continue;
- /* If connection not doing anything, queue this. */
- if (i->state == OK)
- queue_next_event(i);
}
}
}
@@ -181,6 +126,15 @@
}
}

+ /* Check for duplicates. */
+ list_for_each_entry(watch, &conn->watches, list) {
+ if (streq(watch->node, vec[0]) &&
+ streq(watch->token, vec[1])) {
+ send_error(conn, EEXIST);
+ return;
+ }
+ }
+
watch = talloc(conn, struct watch);
watch->node = talloc_strdup(watch, vec[0]);
watch->token = talloc_strdup(watch, vec[1]);
@@ -200,37 +154,6 @@
add_event(conn, watch, watch->node);
}

-void do_watch_ack(struct connection *conn, const char *token)
-{
- struct watch_event *event;
-
- if (!token) {
- send_error(conn, EINVAL);
- return;
- }
-
- if (!conn->waiting_for_ack) {
- send_error(conn, ENOENT);
- return;
- }
-
- if (!streq(conn->waiting_for_ack->token, token)) {
- /* They're confused: this will cause us to send event again */
- conn->waiting_for_ack = NULL;
- send_error(conn, EINVAL);
- return;
- }
-
- /* Remove event: after ack sent, core will call queue_next_event */
- event = list_top(&conn->waiting_for_ack->events, struct watch_event,
- list);
- list_del(&event->list);
- talloc_free(event);
-
- conn->waiting_for_ack = NULL;
- send_ack(conn, XS_WATCH_ACK);
-}
-
void do_unwatch(struct connection *conn, struct buffered_data *in)
{
struct watch *watch;
@@ -241,9 +164,6 @@
return;
}

- /* We don't need to worry if we're waiting for an ack for the
- * watch we're deleting: conn->waiting_for_ack was reset by
- * this command in consider_message anyway. */
node = canonicalize(conn, vec[0]);
list_for_each_entry(watch, &conn->watches, list) {
if (streq(watch->node, node) && streq(watch->token, vec[1])) {
@@ -260,18 +180,19 @@
void dump_watches(struct connection *conn)
{
struct watch *watch;
- struct watch_event *event;

- if (conn->waiting_for_ack)
- printf(" waiting_for_ack for watch on %s token %s\n",
- conn->waiting_for_ack->node,
- conn->waiting_for_ack->token);
-
- list_for_each_entry(watch, &conn->watches, list) {
+ list_for_each_entry(watch, &conn->watches, list)
printf(" watch on %s token %s\n",
watch->node, watch->token);
- list_for_each_entry(event, &watch->events, list)
- printf(" event: %s\n", event->data);
- }
}
#endif
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r 0e7c48861e95 -r 1ac39c7a0435 tools/xenstore/xenstored_watch.h
--- a/tools/xenstore/xenstored_watch.h Mon Oct 10 13:42:38 2005
+++ b/tools/xenstore/xenstored_watch.h Mon Oct 10 13:46:53 2005
@@ -23,17 +23,9 @@
#include "xenstored_core.h"

void do_watch(struct connection *conn, struct buffered_data *in);
-void do_watch_ack(struct connection *conn, const char *token);
void do_unwatch(struct connection *conn, struct buffered_data *in);

-/* Is this a watch event message for this connection? */
-bool is_watch_event(struct connection *conn, struct buffered_data *out);
-
-/* Look through our watches: if any of them have an event, queue it. */
-void queue_next_event(struct connection *conn);
-
-/* Fire all watches: recurse means all the children are affected (ie. rm).
- */
+/* Fire all watches: recurse means all the children are affected (ie. rm). */
void fire_watches(struct connection *conn, const char *name, bool recurse);

void dump_watches(struct connection *conn);
diff -r 0e7c48861e95 -r 1ac39c7a0435 tools/xenstore/xs.c
--- a/tools/xenstore/xs.c Mon Oct 10 13:42:38 2005
+++ b/tools/xenstore/xs.c Mon Oct 10 13:46:53 2005
@@ -78,9 +78,33 @@

/* One transaction at a time. */
pthread_mutex_t transaction_mutex;
+ pthread_t transaction_pthread;
};

+struct xs_transaction_handle {
+ int id;
+};
+
static void *read_thread(void *arg);
+
+static void request_mutex_acquire(struct xs_handle *h)
+{
+ /*
+ * We can't distinguish non-transactional from transactional
+ * requests right now. So temporarily acquire the transaction mutex
+ * if this task is outside transaction context.
+ */
+ if (h->transaction_pthread != pthread_self())
+ pthread_mutex_lock(&h->transaction_mutex);
+ pthread_mutex_lock(&h->request_mutex);
+}
+
+static void request_mutex_release(struct xs_handle *h)
+{
+ pthread_mutex_unlock(&h->request_mutex);
+ if (h->transaction_pthread != pthread_self())
+ pthread_mutex_unlock(&h->transaction_mutex);
+}

int xs_fileno(struct xs_handle *h)
{
@@ -163,6 +187,7 @@

pthread_mutex_init(&h->request_mutex, NULL);
pthread_mutex_init(&h->transaction_mutex, NULL);
+ h->transaction_pthread = -1;

if (pthread_create(&h->read_thr, NULL, read_thread, h) != 0)
goto error;
@@ -316,7 +341,7 @@
ignorepipe.sa_flags = 0;
sigaction(SIGPIPE, &ignorepipe, &oldact);

- pthread_mutex_lock(&h->request_mutex);
+ request_mutex_acquire(h);

if (!xs_write_all(h->fd, &msg, sizeof(msg)))
goto fail;
@@ -329,7 +354,7 @@
if (!ret)
goto fail;

- pthread_mutex_unlock(&h->request_mutex);
+ request_mutex_release(h);

sigaction(SIGPIPE, &oldact, NULL);
if (msg.type == XS_ERROR) {
@@ -350,7 +375,7 @@
fail:
/* We're in a bad state, so close fd. */
saved_errno = errno;
- pthread_mutex_unlock(&h->request_mutex);
+ request_mutex_release(h);
sigaction(SIGPIPE, &oldact, NULL);
close_fd:
close(h->fd);
@@ -386,7 +411,8 @@
return true;
}

-char **xs_directory(struct xs_handle *h, const char *path, unsigned int *num)
+char **xs_directory(struct xs_handle *h, struct xs_transaction_handle *t,
+ const char *path, unsigned int *num)
{
char *strings, *p, **ret;
unsigned int len;
@@ -417,7 +443,8 @@
* Returns a malloced value: call free() on it after use.
* len indicates length in bytes, not including the nul.
*/
-void *xs_read(struct xs_handle *h, const char *path, unsigned int *len)
+void *xs_read(struct xs_handle *h, struct xs_transaction_handle *t,
+ const char *path, unsigned int *len)
{
return xs_single(h, XS_READ, path, len);
}
@@ -425,8 +452,8 @@
/* Write the value of a single file.
* Returns false on failure.
*/
-bool xs_write(struct xs_handle *h, const char *path,
- const void *data, unsigned int len)
+bool xs_write(struct xs_handle *h, struct xs_transaction_handle *t,
+ const char *path, const void *data, unsigned int len)
{
struct iovec iovec[2];

@@ -441,7 +468,8 @@
/* Create a new directory.
* Returns false on failure, or success if it already exists.
*/
-bool xs_mkdir(struct xs_handle *h, const char *path)
+bool xs_mkdir(struct xs_handle *h, struct xs_transaction_handle *t,
+ const char *path)
{
return xs_bool(xs_single(h, XS_MKDIR, path, NULL));
}
@@ -449,7 +477,8 @@
/* Destroy a file or directory (directories must be empty).
* Returns false on failure, or success if it doesn't exist.
*/
-bool xs_rm(struct xs_handle *h, const char *path)
+bool xs_rm(struct xs_handle *h, struct xs_transaction_handle *t,
+ const char *path)
{
return xs_bool(xs_single(h, XS_RM, path, NULL));
}
@@ -458,6 +487,7 @@
* Returns malloced array, or NULL: call free() after use.
*/
struct xs_permissions *xs_get_permissions(struct xs_handle *h,
+ struct xs_transaction_handle *t,
const char *path, unsigned int *num)
{
char *strings;
@@ -490,7 +520,9 @@
/* Set permissions of node (must be owner).
* Returns false on failure.
*/
-bool xs_set_permissions(struct xs_handle *h, const char *path,
+bool xs_set_permissions(struct xs_handle *h,
+ struct xs_transaction_handle *t,
+ const char *path,
struct xs_permissions *perms,
unsigned int num_perms)
{
@@ -593,15 +625,6 @@
return ret;
}

-/* Acknowledge watch on node. Watches must be acknowledged before
- * any other watches can be read.
- * Returns false on failure.
- */
-bool xs_acknowledge_watch(struct xs_handle *h, const char *token)
-{
- return xs_bool(xs_single(h, XS_WATCH_ACK, token, NULL));
-}
-
/* Remove a watch on a node.
* Returns false on failure (no watch on that node).
*/
@@ -620,12 +643,22 @@
/* Start a transaction: changes by others will not be seen during this
* transaction, and changes will not be visible to others until end.
* You can only have one transaction at any time.
- * Returns false on failure.
- */
-bool xs_transaction_start(struct xs_handle *h)
-{
+ * Returns NULL on failure.
+ */
+struct xs_transaction_handle *xs_transaction_start(struct xs_handle *h)
+{
+ bool rc;
+
pthread_mutex_lock(&h->transaction_mutex);
- return xs_bool(xs_single(h, XS_TRANSACTION_START, "", NULL));
+ h->transaction_pthread = pthread_self();
+
+ rc = xs_bool(xs_single(h, XS_TRANSACTION_START, "", NULL));
+ if (!rc) {
+ h->transaction_pthread = -1;
+ pthread_mutex_unlock(&h->transaction_mutex);
+ }
+
+ return (struct xs_transaction_handle *)rc;
}

/* End a transaction.
@@ -633,10 +666,14 @@
* Returns false on failure, which indicates an error: transactions will
* not fail spuriously.
*/
-bool xs_transaction_end(struct xs_handle *h, bool abort)
+bool xs_transaction_end(struct xs_handle *h, struct xs_transaction_handle *t,
+ bool abort)
{
char abortstr[2];
bool rc;
+
+ if (t == NULL)
+ return -EINVAL;

if (abort)
strcpy(abortstr, "F");
@@ -645,6 +682,7 @@

rc = xs_bool(xs_single(h, XS_TRANSACTION_END, abortstr, NULL));

+ h->transaction_pthread = -1;
pthread_mutex_unlock(&h->transaction_mutex);

return rc;
diff -r 0e7c48861e95 -r 1ac39c7a0435 tools/xenstore/xs.h
--- a/tools/xenstore/xs.h Mon Oct 10 13:42:38 2005
+++ b/tools/xenstore/xs.h Mon Oct 10 13:46:53 2005
@@ -23,6 +23,7 @@
#include <xs_lib.h>

struct xs_handle;
+struct xs_transaction_handle;

/* On failure, these routines set errno. */

@@ -44,41 +45,47 @@
* Returns a malloced array: call free() on it after use.
* Num indicates size.
*/
-char **xs_directory(struct xs_handle *h, const char *path, unsigned int *num);
+char **xs_directory(struct xs_handle *h, struct xs_transaction_handle *t,
+ const char *path, unsigned int *num);

/* Get the value of a single file, nul terminated.
* Returns a malloced value: call free() on it after use.
* len indicates length in bytes, not including terminator.
*/
-void *xs_read(struct xs_handle *h, const char *path, unsigned int *len);
+void *xs_read(struct xs_handle *h, struct xs_transaction_handle *t,
+ const char *path, unsigned int *len);

/* Write the value of a single file.
* Returns false on failure.
*/
-bool xs_write(struct xs_handle *h, const char *path, const void *data,
- unsigned int len);
+bool xs_write(struct xs_handle *h, struct xs_transaction_handle *t,
+ const char *path, const void *data, unsigned int len);

/* Create a new directory.
* Returns false on failure, or success if it already exists.
*/
-bool xs_mkdir(struct xs_handle *h, const char *path);
+bool xs_mkdir(struct xs_handle *h, struct xs_transaction_handle *t,
+ const char *path);

/* Destroy a file or directory (and children).
* Returns false on failure, or success if it doesn't exist.
*/
-bool xs_rm(struct xs_handle *h, const char *path);
+bool xs_rm(struct xs_handle *h, struct xs_transaction_handle *t,
+ const char *path);

/* Get permissions of node (first element is owner, first perms is "other").
* Returns malloced array, or NULL: call free() after use.
*/
struct xs_permissions *xs_get_permissions(struct xs_handle *h,
+ struct xs_transaction_handle *t,
const char *path, unsigned int *num);

/* Set permissions of node (must be owner).
* Returns false on failure.
*/
-bool xs_set_permissions(struct xs_handle *h, const char *path,
- struct xs_permissions *perms, unsigned int num_perms);
+bool xs_set_permissions(struct xs_handle *h, struct xs_transaction_handle *t,
+ const char *path, struct xs_permissions *perms,
+ unsigned int num_perms);

/* Watch a node for changes (poll on fd to detect, or call read_watch()).
* When the node (or any child) changes, fd will become readable.
@@ -96,12 +103,6 @@
*/
char **xs_read_watch(struct xs_handle *h, unsigned int *num);

-/* Acknowledge watch on node. Watches must be acknowledged before
- * any other watches can be read.
- * Returns false on failure.
- */
-bool xs_acknowledge_watch(struct xs_handle *h, const char *token);
-
/* Remove a watch on a node: implicitly acks any outstanding watch.
* Returns false on failure (no watch on that node).
*/
@@ -110,16 +111,17 @@
/* Start a transaction: changes by others will not be seen during this
* transaction, and changes will not be visible to others until end.
* You can only have one transaction at any time.
- * Returns false on failure.
+ * Returns NULL on failure.
*/
-bool xs_transaction_start(struct xs_handle *h);
+struct xs_transaction_handle *xs_transaction_start(struct xs_handle *h);

/* End a transaction.
* If abandon is true, transaction is discarded instead of committed.
* Returns false on failure: if errno == EAGAIN, you have to restart
* transaction.
*/
-bool xs_transaction_end(struct xs_handle *h, bool abort);
+bool xs_transaction_end(struct xs_handle *h, struct xs_transaction_handle *t,
+ bool abort);

/* Introduce a new domain.
* This tells the store daemon about a shared memory page, event channel
@@ -142,3 +144,13 @@
void *data, unsigned int len);

#endif /* _XS_H */
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r 0e7c48861e95 -r 1ac39c7a0435 tools/xenstore/xs_test.c
--- a/tools/xenstore/xs_test.c Mon Oct 10 13:42:38 2005
+++ b/tools/xenstore/xs_test.c Mon Oct 10 13:46:53 2005
@@ -42,6 +42,7 @@
#define XSTEST

static struct xs_handle *handles[10] = { NULL };
+static struct xs_transaction_handle *txh[10] = { NULL };

static unsigned int timeout_ms = 500;
static bool timeout_suppressed = true;
@@ -201,7 +202,6 @@
" watch <path> <token>\n"
" watchnoack <path> <token>\n"
" waitwatch\n"
- " ackwatch <token>\n"
" unwatch <path> <token>\n"
" close\n"
" start <node>\n"
@@ -313,7 +313,7 @@
char **entries;
unsigned int i, num;

- entries = xs_directory(handles[handle], path, &num);
+ entries = xs_directory(handles[handle], txh[handle], path, &num);
if (!entries) {
failed(handle);
return;
@@ -332,7 +332,7 @@
char *value;
unsigned int len;

- value = xs_read(handles[handle], path, &len);
+ value = xs_read(handles[handle], txh[handle], path, &len);
if (!value) {
failed(handle);
return;
@@ -348,7 +348,7 @@

static void do_write(unsigned int handle, char *path, char *data)
{
- if (!xs_write(handles[handle], path, data, strlen(data)))
+ if (!xs_write(handles[handle], txh[handle], path, data, strlen(data)))
failed(handle);
}

@@ -361,13 +361,13 @@

static void do_mkdir(unsigned int handle, char *path)
{
- if (!xs_mkdir(handles[handle], path))
+ if (!xs_mkdir(handles[handle], txh[handle], path))
failed(handle);
}

static void do_rm(unsigned int handle, char *path)
{
- if (!xs_rm(handles[handle], path))
+ if (!xs_rm(handles[handle], txh[handle], path))
failed(handle);
}

@@ -376,7 +376,7 @@
unsigned int i, num;
struct xs_permissions *perms;

- perms = xs_get_permissions(handles[handle], path, &num);
+ perms = xs_get_permissions(handles[handle], txh[handle], path, &num);
if (!perms) {
failed(handle);
return;
@@ -437,7 +437,7 @@
barf("bad flags %s\n", arg);
}

- if (!xs_set_permissions(handles[handle], path, perms, i))
+ if (!xs_set_permissions(handles[handle], txh[handle], path, perms, i))
failed(handle);
}

@@ -454,8 +454,6 @@
if (!vec ||
!streq(vec[XS_WATCH_PATH], node) ||
!streq(vec[XS_WATCH_TOKEN], token))
- failed(handle);
- if (!xs_acknowledge_watch(handles[handle], token))
failed(handle);
}
}
@@ -515,12 +513,6 @@
free(vec);
}

-static void do_ackwatch(unsigned int handle, const char *token)
-{
- if (!xs_acknowledge_watch(handles[handle], token))
- failed(handle);
-}
-
static void do_unwatch(unsigned int handle, const char *node, const char *token)
{
if (!xs_unwatch(handles[handle], node, token))
@@ -529,14 +521,16 @@

static void do_start(unsigned int handle)
{
- if (!xs_transaction_start(handles[handle]))
+ txh[handle] = xs_transaction_start(handles[handle]);
+ if (txh[handle] == NULL)
failed(handle);
}

static void do_end(unsigned int handle, bool abort)
{
- if (!xs_transaction_end(handles[handle], abort))
- failed(handle);
+ if (!xs_transaction_end(handles[handle], txh[handle], abort))
+ failed(handle);
+ txh[handle] = NULL;
}

static void do_introduce(unsigned int handle,
@@ -626,7 +620,8 @@

sprintf(subnode, "%s/%s", node, dir[i]);

- perms = xs_get_permissions(handles[handle], subnode,&numperms);
+ perms = xs_get_permissions(handles[handle], txh[handle],
+ subnode,&numperms);
if (!perms) {
failed(handle);
return;
@@ -643,7 +638,8 @@
output("\n");

/* Even directories can have contents. */
- contents = xs_read(handles[handle], subnode, &len);
+ contents = xs_read(handles[handle], txh[handle],
+ subnode, &len);
if (!contents) {
if (errno != EISDIR)
failed(handle);
@@ -653,7 +649,8 @@
}

/* Every node is a directory. */
- subdirs = xs_directory(handles[handle], subnode, &subnum);
+ subdirs = xs_directory(handles[handle], txh[handle],
+ subnode, &subnum);
if (!subdirs) {
failed(handle);
return;
@@ -668,7 +665,7 @@
char **subdirs;
unsigned int subnum;

- subdirs = xs_directory(handles[handle], "/", &subnum);
+ subdirs = xs_directory(handles[handle], txh[handle], "/", &subnum);
if (!subdirs) {
failed(handle);
return;
@@ -746,13 +743,12 @@
do_watch(handle, arg(line, 1), arg(line, 2), false);
else if (streq(command, "waitwatch"))
do_waitwatch(handle);
- else if (streq(command, "ackwatch"))
- do_ackwatch(handle, arg(line, 1));
else if (streq(command, "unwatch"))
do_unwatch(handle, arg(line, 1), arg(line, 2));
else if (streq(command, "close")) {
xs_daemon_close(handles[handle]);
handles[handle] = NULL;
+ txh[handle] = NULL;
} else if (streq(command, "start"))
do_start(handle);
else if (streq(command, "commit"))
@@ -836,3 +832,13 @@

return 0;
}
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r 0e7c48861e95 -r 1ac39c7a0435 xen/include/public/io/xs_wire.h
--- a/xen/include/public/io/xs_wire.h Mon Oct 10 13:42:38 2005
+++ b/xen/include/public/io/xs_wire.h Mon Oct 10 13:46:53 2005
@@ -30,25 +30,23 @@

enum xsd_sockmsg_type
{
- XS_DEBUG,
- XS_DIRECTORY,
- XS_READ,
- XS_GET_PERMS,
- XS_WATCH,
- XS_WATCH_ACK,
- XS_UNWATCH,
- XS_TRANSACTION_START,
- XS_TRANSACTION_END,
- XS_OP_READ_ONLY = XS_TRANSACTION_END,
- XS_INTRODUCE,
- XS_RELEASE,
- XS_GET_DOMAIN_PATH,
- XS_WRITE,
- XS_MKDIR,
- XS_RM,
- XS_SET_PERMS,
- XS_WATCH_EVENT,
- XS_ERROR,
+ XS_DEBUG,
+ XS_DIRECTORY,
+ XS_READ,
+ XS_GET_PERMS,
+ XS_WATCH,
+ XS_UNWATCH,
+ XS_TRANSACTION_START,
+ XS_TRANSACTION_END,
+ XS_INTRODUCE,
+ XS_RELEASE,
+ XS_GET_DOMAIN_PATH,
+ XS_WRITE,
+ XS_MKDIR,
+ XS_RM,
+ XS_SET_PERMS,
+ XS_WATCH_EVENT,
+ XS_ERROR,
};

#define XS_WRITE_NONE "NONE"
@@ -58,38 +56,40 @@
/* We hand errors as strings, for portability. */
struct xsd_errors
{
- int errnum;
- const char *errstring;
+ int errnum;
+ const char *errstring;
};
#define XSD_ERROR(x) { x, #x }
static struct xsd_errors xsd_errors[] __attribute__((unused)) = {
- XSD_ERROR(EINVAL),
- XSD_ERROR(EACCES),
- XSD_ERROR(EEXIST),
- XSD_ERROR(EISDIR),
- XSD_ERROR(ENOENT),
- XSD_ERROR(ENOMEM),
- XSD_ERROR(ENOSPC),
- XSD_ERROR(EIO),
- XSD_ERROR(ENOTEMPTY),
- XSD_ERROR(ENOSYS),
- XSD_ERROR(EROFS),
- XSD_ERROR(EBUSY),
- XSD_ERROR(EAGAIN),
- XSD_ERROR(EISCONN),
+ XSD_ERROR(EINVAL),
+ XSD_ERROR(EACCES),
+ XSD_ERROR(EEXIST),
+ XSD_ERROR(EISDIR),
+ XSD_ERROR(ENOENT),
+ XSD_ERROR(ENOMEM),
+ XSD_ERROR(ENOSPC),
+ XSD_ERROR(EIO),
+ XSD_ERROR(ENOTEMPTY),
+ XSD_ERROR(ENOSYS),
+ XSD_ERROR(EROFS),
+ XSD_ERROR(EBUSY),
+ XSD_ERROR(EAGAIN),
+ XSD_ERROR(EISCONN),
};
struct xsd_sockmsg
{
- u32 type;
- u32 len; /* Length of data following this. */
+ u32 type; /* XS_??? */
+ u32 req_id;/* Request identifier, echoed in daemon's response. */
+ u32 tx_id; /* Transaction id (0 if not related to a transaction). */
+ u32 len; /* Length of data following this. */

- /* Generally followed by nul-terminated string(s). */
+ /* Generally followed by nul-terminated string(s). */
};

enum xs_watch_type
{
- XS_WATCH_PATH = 0,
- XS_WATCH_TOKEN,
+ XS_WATCH_PATH = 0,
+ XS_WATCH_TOKEN,
};

#endif /* _XS_WIRE_H */

_______________________________________________
Xen-changelog mailing list
Xen-changelog@lists.xensource.com
http://lists.xensource.com/xen-changelog
Merged. [ In reply to ]
# HG changeset patch
# User emellor@ewan
# Node ID f9bd8df8a0985b353de9aa6a15cb28208e9d1048
# Parent d6d1c3cbc151299053d2fafe579ac3cdd34a2195
# Parent 015f8ae8127649f0c69904fd063ca45d304d4e0c
Merged.

diff -r d6d1c3cbc151 -r f9bd8df8a098 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c
--- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c Mon Oct 10 15:15:48 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c Mon Oct 10 15:16:41 2005
@@ -45,8 +45,14 @@
#include <asm-xen/xen_proc.h>
#include <asm/hypervisor.h>

+struct xenbus_dev_transaction {
+ struct list_head list;
+ struct xenbus_transaction *handle;
+};
+
struct xenbus_dev_data {
- int in_transaction;
+ /* In-progress transaction. */
+ struct list_head transactions;

/* Partial request. */
unsigned int len;
@@ -103,6 +109,7 @@
size_t len, loff_t *ppos)
{
struct xenbus_dev_data *u = filp->private_data;
+ struct xenbus_dev_transaction *trans;
void *reply;
int err = 0;

@@ -129,13 +136,24 @@
case XS_RM:
case XS_SET_PERMS:
reply = xenbus_dev_request_and_reply(&u->u.msg);
- if (IS_ERR(reply))
+ if (IS_ERR(reply)) {
err = PTR_ERR(reply);
- else {
- if (u->u.msg.type == XS_TRANSACTION_START)
- u->in_transaction = 1;
- if (u->u.msg.type == XS_TRANSACTION_END)
- u->in_transaction = 0;
+ } else {
+ if (u->u.msg.type == XS_TRANSACTION_START) {
+ trans = kmalloc(sizeof(*trans), GFP_KERNEL);
+ trans->handle = (struct xenbus_transaction *)
+ simple_strtoul(reply, NULL, 0);
+ list_add(&trans->list, &u->transactions);
+ } else if (u->u.msg.type == XS_TRANSACTION_END) {
+ list_for_each_entry(trans, &u->transactions,
+ list)
+ if ((unsigned long)trans->handle ==
+ (unsigned long)u->u.msg.tx_id)
+ break;
+ BUG_ON(&trans->list == &u->transactions);
+ list_del(&trans->list);
+ kfree(trans);
+ }
queue_reply(u, (char *)&u->u.msg, sizeof(u->u.msg));
queue_reply(u, (char *)reply, u->u.msg.len);
kfree(reply);
@@ -169,6 +187,7 @@
return -ENOMEM;

memset(u, 0, sizeof(*u));
+ INIT_LIST_HEAD(&u->transactions);
init_waitqueue_head(&u->read_waitq);

filp->private_data = u;
@@ -179,9 +198,13 @@
static int xenbus_dev_release(struct inode *inode, struct file *filp)
{
struct xenbus_dev_data *u = filp->private_data;
-
- if (u->in_transaction)
- xenbus_transaction_end((struct xenbus_transaction *)1, 1);
+ struct xenbus_dev_transaction *trans, *tmp;
+
+ list_for_each_entry_safe(trans, tmp, &u->transactions, list) {
+ xenbus_transaction_end(trans->handle, 1);
+ list_del(&trans->list);
+ kfree(trans);
+ }

kfree(u);

diff -r d6d1c3cbc151 -r f9bd8df8a098 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c
--- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c Mon Oct 10 15:15:48 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c Mon Oct 10 15:16:41 2005
@@ -71,38 +71,14 @@
/* One request at a time. */
struct semaphore request_mutex;

- /* One transaction at a time. */
- struct semaphore transaction_mutex;
- int transaction_pid;
+ /* Protect transactions against save/restore. */
+ struct rw_semaphore suspend_mutex;
};

static struct xs_handle xs_state;

static LIST_HEAD(watches);
static DEFINE_SPINLOCK(watches_lock);
-
-/* Can wait on !xs_resuming for suspend/resume cycle to complete. */
-static int xs_resuming;
-static DECLARE_WAIT_QUEUE_HEAD(xs_resuming_waitq);
-
-static void request_mutex_acquire(void)
-{
- /*
- * We can't distinguish non-transactional from transactional
- * requests right now. So temporarily acquire the transaction mutex
- * if this task is outside transaction context.
- */
- if (xs_state.transaction_pid != current->pid)
- down(&xs_state.transaction_mutex);
- down(&xs_state.request_mutex);
-}
-
-static void request_mutex_release(void)
-{
- up(&xs_state.request_mutex);
- if (xs_state.transaction_pid != current->pid)
- up(&xs_state.transaction_mutex);
-}

static int get_error(const char *errorstring)
{
@@ -152,17 +128,17 @@
/* Emergency write. */
void xenbus_debug_write(const char *str, unsigned int count)
{
- struct xsd_sockmsg msg;
+ struct xsd_sockmsg msg = { 0 };

msg.type = XS_DEBUG;
msg.len = sizeof("print") + count + 1;

- request_mutex_acquire();
+ down(&xs_state.request_mutex);
xb_write(&msg, sizeof(msg));
xb_write("print", sizeof("print"));
xb_write(str, count);
xb_write("", 1);
- request_mutex_release();
+ up(&xs_state.request_mutex);
}

void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg)
@@ -171,12 +147,10 @@
struct xsd_sockmsg req_msg = *msg;
int err;

- if (req_msg.type == XS_TRANSACTION_START) {
- down(&xs_state.transaction_mutex);
- xs_state.transaction_pid = current->pid;
- }
-
- request_mutex_acquire();
+ if (req_msg.type == XS_TRANSACTION_START)
+ down_read(&xs_state.suspend_mutex);
+
+ down(&xs_state.request_mutex);

err = xb_write(msg, sizeof(*msg) + msg->len);
if (err) {
@@ -186,20 +160,19 @@
ret = read_reply(&msg->type, &msg->len);
}

- request_mutex_release();
+ up(&xs_state.request_mutex);

if ((msg->type == XS_TRANSACTION_END) ||
((req_msg.type == XS_TRANSACTION_START) &&
- (msg->type == XS_ERROR))) {
- xs_state.transaction_pid = -1;
- up(&xs_state.transaction_mutex);
- }
+ (msg->type == XS_ERROR)))
+ up_read(&xs_state.suspend_mutex);

return ret;
}

/* Send message to xs, get kmalloc'ed reply. ERR_PTR() on error. */
-static void *xs_talkv(enum xsd_sockmsg_type type,
+static void *xs_talkv(struct xenbus_transaction *t,
+ enum xsd_sockmsg_type type,
const struct kvec *iovec,
unsigned int num_vecs,
unsigned int *len)
@@ -209,12 +182,13 @@
unsigned int i;
int err;

+ msg.tx_id = (u32)(unsigned long)t;
msg.type = type;
msg.len = 0;
for (i = 0; i < num_vecs; i++)
msg.len += iovec[i].iov_len;

- request_mutex_acquire();
+ down(&xs_state.request_mutex);

err = xb_write(&msg, sizeof(msg));
if (err) {
@@ -225,14 +199,14 @@
for (i = 0; i < num_vecs; i++) {
err = xb_write(iovec[i].iov_base, iovec[i].iov_len);;
if (err) {
- request_mutex_release();
+ up(&xs_state.request_mutex);
return ERR_PTR(err);
}
}

ret = read_reply(&msg.type, len);

- request_mutex_release();
+ up(&xs_state.request_mutex);

if (IS_ERR(ret))
return ret;
@@ -248,14 +222,16 @@
}

/* Simplified version of xs_talkv: single message. */
-static void *xs_single(enum xsd_sockmsg_type type,
- const char *string, unsigned int *len)
+static void *xs_single(struct xenbus_transaction *t,
+ enum xsd_sockmsg_type type,
+ const char *string,
+ unsigned int *len)
{
struct kvec iovec;

iovec.iov_base = (void *)string;
iovec.iov_len = strlen(string) + 1;
- return xs_talkv(type, &iovec, 1, len);
+ return xs_talkv(t, type, &iovec, 1, len);
}

/* Many commands only need an ack, don't care what it says. */
@@ -322,7 +298,7 @@
char *strings;
unsigned int len;

- strings = xs_single(XS_DIRECTORY, join(dir, node), &len);
+ strings = xs_single(t, XS_DIRECTORY, join(dir, node), &len);
if (IS_ERR(strings))
return (char **)strings;

@@ -352,7 +328,7 @@
void *xenbus_read(struct xenbus_transaction *t,
const char *dir, const char *node, unsigned int *len)
{
- return xs_single(XS_READ, join(dir, node), len);
+ return xs_single(t, XS_READ, join(dir, node), len);
}
EXPORT_SYMBOL(xenbus_read);

@@ -372,7 +348,7 @@
iovec[1].iov_base = (void *)string;
iovec[1].iov_len = strlen(string);

- return xs_error(xs_talkv(XS_WRITE, iovec, ARRAY_SIZE(iovec), NULL));
+ return xs_error(xs_talkv(t, XS_WRITE, iovec, ARRAY_SIZE(iovec), NULL));
}
EXPORT_SYMBOL(xenbus_write);

@@ -380,14 +356,14 @@
int xenbus_mkdir(struct xenbus_transaction *t,
const char *dir, const char *node)
{
- return xs_error(xs_single(XS_MKDIR, join(dir, node), NULL));
+ return xs_error(xs_single(t, XS_MKDIR, join(dir, node), NULL));
}
EXPORT_SYMBOL(xenbus_mkdir);

/* Destroy a file or directory (directories must be empty). */
int xenbus_rm(struct xenbus_transaction *t, const char *dir, const char *node)
{
- return xs_error(xs_single(XS_RM, join(dir, node), NULL));
+ return xs_error(xs_single(t, XS_RM, join(dir, node), NULL));
}
EXPORT_SYMBOL(xenbus_rm);

@@ -396,18 +372,21 @@
*/
struct xenbus_transaction *xenbus_transaction_start(void)
{
- int err;
-
- down(&xs_state.transaction_mutex);
- xs_state.transaction_pid = current->pid;
-
- err = xs_error(xs_single(XS_TRANSACTION_START, "", NULL));
- if (err) {
- xs_state.transaction_pid = -1;
- up(&xs_state.transaction_mutex);
- }
-
- return err ? ERR_PTR(err) : (struct xenbus_transaction *)1;
+ char *id_str;
+ unsigned long id;
+
+ down_read(&xs_state.suspend_mutex);
+
+ id_str = xs_single(NULL, XS_TRANSACTION_START, "", NULL);
+ if (IS_ERR(id_str)) {
+ up_read(&xs_state.suspend_mutex);
+ return (struct xenbus_transaction *)id_str;
+ }
+
+ id = simple_strtoul(id_str, NULL, 0);
+ kfree(id_str);
+
+ return (struct xenbus_transaction *)id;
}
EXPORT_SYMBOL(xenbus_transaction_start);

@@ -419,17 +398,14 @@
char abortstr[2];
int err;

- BUG_ON(t == NULL);
-
if (abort)
strcpy(abortstr, "F");
else
strcpy(abortstr, "T");

- err = xs_error(xs_single(XS_TRANSACTION_END, abortstr, NULL));
-
- xs_state.transaction_pid = -1;
- up(&xs_state.transaction_mutex);
+ err = xs_error(xs_single(t, XS_TRANSACTION_END, abortstr, NULL));
+
+ up_read(&xs_state.suspend_mutex);

return err;
}
@@ -567,7 +543,8 @@
iov[1].iov_base = (void *)token;
iov[1].iov_len = strlen(token) + 1;

- return xs_error(xs_talkv(XS_WATCH, iov, ARRAY_SIZE(iov), NULL));
+ return xs_error(xs_talkv(NULL, XS_WATCH, iov,
+ ARRAY_SIZE(iov), NULL));
}

static int xs_unwatch(const char *path, const char *token)
@@ -579,7 +556,8 @@
iov[1].iov_base = (char *)token;
iov[1].iov_len = strlen(token) + 1;

- return xs_error(xs_talkv(XS_UNWATCH, iov, ARRAY_SIZE(iov), NULL));
+ return xs_error(xs_talkv(NULL, XS_UNWATCH, iov,
+ ARRAY_SIZE(iov), NULL));
}

static struct xenbus_watch *find_watch(const char *token)
@@ -603,6 +581,8 @@
int err;

sprintf(token, "%lX", (long)watch);
+
+ down_read(&xs_state.suspend_mutex);

spin_lock(&watches_lock);
BUG_ON(find_watch(token));
@@ -617,6 +597,8 @@
spin_unlock(&watches_lock);
}

+ up_read(&xs_state.suspend_mutex);
+
return err;
}
EXPORT_SYMBOL(register_xenbus_watch);
@@ -627,14 +609,13 @@
int err;

sprintf(token, "%lX", (long)watch);
+
+ down_read(&xs_state.suspend_mutex);

spin_lock(&watches_lock);
BUG_ON(!find_watch(token));
list_del(&watch->list);
spin_unlock(&watches_lock);
-
- /* Ensure xs_resume() is not in progress (see comments there). */
- wait_event(xs_resuming_waitq, !xs_resuming);

err = xs_unwatch(watch->node, token);
if (err)
@@ -642,6 +623,8 @@
"XENBUS Failed to release watch %s: %i\n",
watch->node, err);

+ up_read(&xs_state.suspend_mutex);
+
/* Make sure watch is not in use. */
flush_scheduled_work();
}
@@ -649,58 +632,24 @@

void xs_suspend(void)
{
- down(&xs_state.transaction_mutex);
+ down_write(&xs_state.suspend_mutex);
down(&xs_state.request_mutex);
}

void xs_resume(void)
{
- struct list_head *ent, *prev_ent = &watches;
struct xenbus_watch *watch;
char token[sizeof(watch) * 2 + 1];

- /* Protect against concurrent unregistration and freeing of watches. */
- BUG_ON(xs_resuming);
- xs_resuming = 1;
-
up(&xs_state.request_mutex);
- up(&xs_state.transaction_mutex);
-
- /*
- * Iterate over the watch list re-registering each node. We must
- * be careful about concurrent registrations and unregistrations.
- * We search for the node immediately following the previously
- * re-registered node. If we get no match then either we are done
- * (previous node is last in list) or the node was unregistered, in
- * which case we restart from the beginning of the list.
- * register_xenbus_watch() + unregister_xenbus_watch() is safe because
- * it will only ever move a watch node earlier in the list, so it
- * cannot cause us to skip nodes.
- */
- for (;;) {
- spin_lock(&watches_lock);
- list_for_each(ent, &watches)
- if (ent->prev == prev_ent)
- break;
- spin_unlock(&watches_lock);
-
- /* No match because prev_ent is at the end of the list? */
- if ((ent == &watches) && (watches.prev == prev_ent))
- break; /* We're done! */
-
- if ((prev_ent = ent) != &watches) {
- /*
- * Safe even with watch_lock not held. We are saved by
- * (xs_resumed==1) check in unregister_xenbus_watch.
- */
- watch = list_entry(ent, struct xenbus_watch, list);
- sprintf(token, "%lX", (long)watch);
- xs_watch(watch->node, token);
- }
- }
-
- xs_resuming = 0;
- wake_up(&xs_resuming_waitq);
+
+ /* No need for watches_lock: the suspend_mutex is sufficient. */
+ list_for_each_entry(watch, &watches, list) {
+ sprintf(token, "%lX", (long)watch);
+ xs_watch(watch->node, token);
+ }
+
+ up_write(&xs_state.suspend_mutex);
}

static void xenbus_fire_watch(void *arg)
@@ -801,8 +750,7 @@
init_waitqueue_head(&xs_state.reply_waitq);

init_MUTEX(&xs_state.request_mutex);
- init_MUTEX(&xs_state.transaction_mutex);
- xs_state.transaction_pid = -1;
+ init_rwsem(&xs_state.suspend_mutex);

/* Initialize the shared memory rings to talk to xenstored */
err = xb_init_comms();
diff -r d6d1c3cbc151 -r f9bd8df8a098 tools/xenstore/utils.h
--- a/tools/xenstore/utils.h Mon Oct 10 15:15:48 2005
+++ b/tools/xenstore/utils.h Mon Oct 10 15:16:41 2005
@@ -55,4 +55,34 @@
#define dprintf(_fmt, _args...) ((void)0)
#endif

+/*
+ * Mux errno values onto returned pointers.
+ */
+
+static inline void *ERR_PTR(long error)
+{
+ return (void *)error;
+}
+
+static inline long PTR_ERR(const void *ptr)
+{
+ return (long)ptr;
+}
+
+static inline long IS_ERR(const void *ptr)
+{
+ return ((unsigned long)ptr > (unsigned long)-1000L);
+}
+
+
#endif /* _UTILS_H */
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r d6d1c3cbc151 -r f9bd8df8a098 tools/xenstore/xenstore_client.c
--- a/tools/xenstore/xenstore_client.c Mon Oct 10 15:15:48 2005
+++ b/tools/xenstore/xenstore_client.c Mon Oct 10 15:16:41 2005
@@ -34,14 +34,10 @@
struct xs_handle *xsh;
struct xs_transaction_handle *xth;
bool success;
- int ret = 0;
+ int ret = 0, socket = 0;
#if defined(CLIENT_read) || defined(CLIENT_list)
int prefix = 0;
#endif
-
- xsh = xs_domain_open();
- if (xsh == NULL)
- err(1, "xs_domain_open");

while (1) {
int c, index = 0;
@@ -50,10 +46,11 @@
#if defined(CLIENT_read) || defined(CLIENT_list)
{"prefix", 0, 0, 'p'},
#endif
+ {"socket", 0, 0, 's'},
{0, 0, 0, 0}
};

- c = getopt_long(argc, argv, "h"
+ c = getopt_long(argc, argv, "hs"
#if defined(CLIENT_read) || defined(CLIENT_list)
"p"
#endif
@@ -65,6 +62,9 @@
case 'h':
usage(argv[0]);
/* NOTREACHED */
+ case 's':
+ socket = 1;
+ break;
#if defined(CLIENT_read) || defined(CLIENT_list)
case 'p':
prefix = 1;
@@ -83,6 +83,10 @@
/* NOTREACHED */
}
#endif
+
+ xsh = socket ? xs_daemon_open() : xs_domain_open();
+ if (xsh == NULL)
+ err(1, socket ? "xs_daemon_open" : "xs_domain_open");

again:
xth = xs_transaction_start(xsh);
diff -r d6d1c3cbc151 -r f9bd8df8a098 tools/xenstore/xenstored_core.c
--- a/tools/xenstore/xenstored_core.c Mon Oct 10 15:15:48 2005
+++ b/tools/xenstore/xenstored_core.c Mon Oct 10 15:16:41 2005
@@ -238,46 +238,47 @@
static bool write_messages(struct connection *conn)
{
int ret;
- struct buffered_data *out, *tmp;
-
- list_for_each_entry_safe(out, tmp, &conn->out_list, list) {
- if (out->inhdr) {
- if (verbose)
- xprintf("Writing msg %s (%s) out to %p\n",
- sockmsg_string(out->hdr.msg.type),
- out->buffer, conn);
- ret = conn->write(conn, out->hdr.raw + out->used,
- sizeof(out->hdr) - out->used);
- if (ret < 0)
- return false;
-
- out->used += ret;
- if (out->used < sizeof(out->hdr))
- return true;
-
- out->inhdr = false;
- out->used = 0;
-
- /* Second write might block if non-zero. */
- if (out->hdr.msg.len && !conn->domain)
- return true;
- }
-
- ret = conn->write(conn, out->buffer + out->used,
- out->hdr.msg.len - out->used);
-
+ struct buffered_data *out;
+
+ out = list_top(&conn->out_list, struct buffered_data, list);
+ if (out == NULL)
+ return true;
+
+ if (out->inhdr) {
+ if (verbose)
+ xprintf("Writing msg %s (%s) out to %p\n",
+ sockmsg_string(out->hdr.msg.type),
+ out->buffer, conn);
+ ret = conn->write(conn, out->hdr.raw + out->used,
+ sizeof(out->hdr) - out->used);
if (ret < 0)
return false;

out->used += ret;
- if (out->used != out->hdr.msg.len)
+ if (out->used < sizeof(out->hdr))
return true;

- trace_io(conn, "OUT", out);
-
- list_del(&out->list);
- talloc_free(out);
- }
+ out->inhdr = false;
+ out->used = 0;
+
+ /* Second write might block if non-zero. */
+ if (out->hdr.msg.len && !conn->domain)
+ return true;
+ }
+
+ ret = conn->write(conn, out->buffer + out->used,
+ out->hdr.msg.len - out->used);
+ if (ret < 0)
+ return false;
+
+ out->used += ret;
+ if (out->used != out->hdr.msg.len)
+ return true;
+
+ trace_io(conn, "OUT", out);
+
+ list_del(&out->list);
+ talloc_free(out);

return true;
}
@@ -1042,6 +1043,17 @@
*/
static void process_message(struct connection *conn, struct buffered_data *in)
{
+ struct transaction *trans;
+
+ trans = transaction_lookup(conn, in->hdr.msg.tx_id);
+ if (IS_ERR(trans)) {
+ send_error(conn, -PTR_ERR(trans));
+ return;
+ }
+
+ assert(conn->transaction == NULL);
+ conn->transaction = trans;
+
switch (in->hdr.msg.type) {
case XS_DIRECTORY:
send_directory(conn, onearg(in));
@@ -1116,11 +1128,13 @@
do_get_domain_path(conn, onearg(in));
break;

- case XS_WATCH_EVENT:
default:
eprintf("Client unknown operation %i", in->hdr.msg.type);
send_error(conn, ENOSYS);
- }
+ break;
+ }
+
+ conn->transaction = NULL;
}

static int out_of_mem(void *data)
@@ -1239,15 +1253,14 @@
if (!new)
return NULL;

+ memset(new, 0, sizeof(*new));
new->fd = -1;
- new->id = 0;
- new->domain = NULL;
- new->transaction = NULL;
new->write = write;
new->read = read;
new->can_write = true;
INIT_LIST_HEAD(&new->out_list);
INIT_LIST_HEAD(&new->watches);
+ INIT_LIST_HEAD(&new->transaction_list);

talloc_set_fail_handler(out_of_mem, &talloc_fail);
if (setjmp(talloc_fail)) {
@@ -1410,6 +1423,7 @@


static struct option options[] = {
+ { "no-domain-init", 0, NULL, 'D' },
{ "pid-file", 1, NULL, 'F' },
{ "no-fork", 0, NULL, 'N' },
{ "output-pid", 0, NULL, 'P' },
@@ -1424,11 +1438,15 @@
fd_set inset, outset;
bool dofork = true;
bool outputpid = false;
+ bool no_domain_init = false;
const char *pidfile = NULL;

- while ((opt = getopt_long(argc, argv, "F:NPT:V", options,
+ while ((opt = getopt_long(argc, argv, "DF:NPT:V", options,
NULL)) != -1) {
switch (opt) {
+ case 'D':
+ no_domain_init = true;
+ break;
case 'F':
pidfile = optarg;
break;
@@ -1501,7 +1519,8 @@
setup_structure();

/* Listen to hypervisor. */
- event_fd = domain_init();
+ if (!no_domain_init)
+ event_fd = domain_init();

/* Restore existing connections. */
restore_existing_connections();
diff -r d6d1c3cbc151 -r f9bd8df8a098 tools/xenstore/xenstored_core.h
--- a/tools/xenstore/xenstored_core.h Mon Oct 10 15:15:48 2005
+++ b/tools/xenstore/xenstored_core.h Mon Oct 10 15:16:41 2005
@@ -71,8 +71,12 @@
/* Buffered output data */
struct list_head out_list;

- /* My transaction, if any. */
+ /* Transaction context for current request (NULL if none). */
struct transaction *transaction;
+
+ /* List of in-progress transactions. */
+ struct list_head transaction_list;
+ u32 next_transaction_id;

/* The domain I'm associated with, if any. */
struct domain *domain;
diff -r d6d1c3cbc151 -r f9bd8df8a098 tools/xenstore/xenstored_transaction.c
--- a/tools/xenstore/xenstored_transaction.c Mon Oct 10 15:15:48 2005
+++ b/tools/xenstore/xenstored_transaction.c Mon Oct 10 15:16:41 2005
@@ -37,7 +37,7 @@

struct changed_node
{
- /* The list within this transaction. */
+ /* List of all changed nodes in the context of this transaction. */
struct list_head list;

/* The name of the node. */
@@ -49,14 +49,14 @@

struct transaction
{
- /* Global list of transactions. */
+ /* List of all transactions active on this connection. */
struct list_head list;
+
+ /* Connection-local identifier for this transaction. */
+ u32 id;

/* Generation when transaction started. */
unsigned int generation;
-
- /* My owner (conn->transaction == me). */
- struct connection *conn;

/* TDB to work on, and filename */
TDB_CONTEXT *tdb;
@@ -65,7 +65,7 @@
/* List of changed nodes. */
struct list_head changes;
};
-static LIST_HEAD(transactions);
+
static unsigned int generation;

/* Return tdb context to use for this connection. */
@@ -100,7 +100,6 @@
{
struct transaction *trans = _transaction;

- list_del(&trans->list);
trace_destroy(trans, "transaction");
if (trans->tdb)
tdb_close(trans->tdb);
@@ -108,10 +107,26 @@
return 0;
}

+struct transaction *transaction_lookup(struct connection *conn, u32 id)
+{
+ struct transaction *trans;
+
+ if (id == 0)
+ return NULL;
+
+ list_for_each_entry(trans, &conn->transaction_list, list)
+ if (trans->id == id)
+ return trans;
+
+ return ERR_PTR(-ENOENT);
+}
+
void do_transaction_start(struct connection *conn, struct buffered_data *in)
{
- struct transaction *trans;
-
+ struct transaction *trans, *exists;
+ char id_str[20];
+
+ /* We don't support nested transactions. */
if (conn->transaction) {
send_error(conn, EBUSY);
return;
@@ -120,7 +135,6 @@
/* Attach transaction to input for autofree until it's complete */
trans = talloc(in, struct transaction);
INIT_LIST_HEAD(&trans->changes);
- trans->conn = conn;
trans->generation = generation;
trans->tdb_name = talloc_asprintf(trans, "%s.%p",
xs_daemon_tdb(), trans);
@@ -132,11 +146,19 @@
/* Make it close if we go away. */
talloc_steal(trans, trans->tdb);

+ /* Pick an unused transaction identifier. */
+ do {
+ trans->id = conn->next_transaction_id;
+ exists = transaction_lookup(conn, conn->next_transaction_id++);
+ } while (!IS_ERR(exists));
+
/* Now we own it. */
- conn->transaction = talloc_steal(conn, trans);
- list_add_tail(&trans->list, &transactions);
+ list_add_tail(&trans->list, &conn->transaction_list);
+ talloc_steal(conn, trans);
talloc_set_destructor(trans, destroy_transaction);
- send_ack(conn, XS_TRANSACTION_START);
+
+ sprintf(id_str, "%u", trans->id);
+ send_reply(conn, XS_TRANSACTION_START, id_str, strlen(id_str)+1);
}

void do_transaction_end(struct connection *conn, const char *arg)
@@ -149,13 +171,13 @@
return;
}

- if (!conn->transaction) {
+ if ((trans = conn->transaction) == NULL) {
send_error(conn, ENOENT);
return;
}

- trans = conn->transaction;
conn->transaction = NULL;
+ list_del(&trans->list);

/* Attach transaction to arg for auto-cleanup */
talloc_steal(arg, trans);
@@ -181,3 +203,12 @@
send_ack(conn, XS_TRANSACTION_END);
}

+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r d6d1c3cbc151 -r f9bd8df8a098 tools/xenstore/xenstored_transaction.h
--- a/tools/xenstore/xenstored_transaction.h Mon Oct 10 15:15:48 2005
+++ b/tools/xenstore/xenstored_transaction.h Mon Oct 10 15:16:41 2005
@@ -25,10 +25,11 @@
void do_transaction_start(struct connection *conn, struct buffered_data *node);
void do_transaction_end(struct connection *conn, const char *arg);

-bool transaction_block(struct connection *conn);
+struct transaction *transaction_lookup(struct connection *conn, u32 id);

/* This node was changed: can fail and longjmp. */
-void add_change_node(struct transaction *trans, const char *node, bool recurse);
+void add_change_node(struct transaction *trans, const char *node,
+ bool recurse);

/* Return tdb context to use for this connection. */
TDB_CONTEXT *tdb_transaction_context(struct transaction *trans);
diff -r d6d1c3cbc151 -r f9bd8df8a098 tools/xenstore/xs.c
--- a/tools/xenstore/xs.c Mon Oct 10 15:15:48 2005
+++ b/tools/xenstore/xs.c Mon Oct 10 15:16:41 2005
@@ -75,36 +75,9 @@

/* One request at a time. */
pthread_mutex_t request_mutex;
-
- /* One transaction at a time. */
- pthread_mutex_t transaction_mutex;
- pthread_t transaction_pthread;
};

-struct xs_transaction_handle {
- int id;
-};
-
static void *read_thread(void *arg);
-
-static void request_mutex_acquire(struct xs_handle *h)
-{
- /*
- * We can't distinguish non-transactional from transactional
- * requests right now. So temporarily acquire the transaction mutex
- * if this task is outside transaction context.
- */
- if (h->transaction_pthread != pthread_self())
- pthread_mutex_lock(&h->transaction_mutex);
- pthread_mutex_lock(&h->request_mutex);
-}
-
-static void request_mutex_release(struct xs_handle *h)
-{
- pthread_mutex_unlock(&h->request_mutex);
- if (h->transaction_pthread != pthread_self())
- pthread_mutex_unlock(&h->transaction_mutex);
-}

int xs_fileno(struct xs_handle *h)
{
@@ -186,8 +159,6 @@
pthread_cond_init(&h->reply_condvar, NULL);

pthread_mutex_init(&h->request_mutex, NULL);
- pthread_mutex_init(&h->transaction_mutex, NULL);
- h->transaction_pthread = -1;

if (pthread_create(&h->read_thr, NULL, read_thread, h) != 0)
goto error;
@@ -223,7 +194,6 @@
{
struct xs_stored_msg *msg, *tmsg;

- pthread_mutex_lock(&h->transaction_mutex);
pthread_mutex_lock(&h->request_mutex);
pthread_mutex_lock(&h->reply_mutex);
pthread_mutex_lock(&h->watch_mutex);
@@ -242,7 +212,6 @@
free(msg);
}

- pthread_mutex_unlock(&h->transaction_mutex);
pthread_mutex_unlock(&h->request_mutex);
pthread_mutex_unlock(&h->reply_mutex);
pthread_mutex_unlock(&h->watch_mutex);
@@ -321,8 +290,10 @@
}

/* Send message to xs, get malloc'ed reply. NULL and set errno on error. */
-static void *xs_talkv(struct xs_handle *h, enum xsd_sockmsg_type type,
- const struct iovec *iovec, unsigned int num_vecs,
+static void *xs_talkv(struct xs_handle *h, struct xs_transaction_handle *t,
+ enum xsd_sockmsg_type type,
+ const struct iovec *iovec,
+ unsigned int num_vecs,
unsigned int *len)
{
struct xsd_sockmsg msg;
@@ -331,6 +302,7 @@
unsigned int i;
struct sigaction ignorepipe, oldact;

+ msg.tx_id = (u32)(unsigned long)t;
msg.type = type;
msg.len = 0;
for (i = 0; i < num_vecs; i++)
@@ -341,7 +313,7 @@
ignorepipe.sa_flags = 0;
sigaction(SIGPIPE, &ignorepipe, &oldact);

- request_mutex_acquire(h);
+ pthread_mutex_lock(&h->request_mutex);

if (!xs_write_all(h->fd, &msg, sizeof(msg)))
goto fail;
@@ -354,7 +326,7 @@
if (!ret)
goto fail;

- request_mutex_release(h);
+ pthread_mutex_unlock(&h->request_mutex);

sigaction(SIGPIPE, &oldact, NULL);
if (msg.type == XS_ERROR) {
@@ -375,7 +347,7 @@
fail:
/* We're in a bad state, so close fd. */
saved_errno = errno;
- request_mutex_release(h);
+ pthread_mutex_unlock(&h->request_mutex);
sigaction(SIGPIPE, &oldact, NULL);
close_fd:
close(h->fd);
@@ -393,14 +365,16 @@
}

/* Simplified version of xs_talkv: single message. */
-static void *xs_single(struct xs_handle *h, enum xsd_sockmsg_type type,
- const char *string, unsigned int *len)
+static void *xs_single(struct xs_handle *h, struct xs_transaction_handle *t,
+ enum xsd_sockmsg_type type,
+ const char *string,
+ unsigned int *len)
{
struct iovec iovec;

iovec.iov_base = (void *)string;
iovec.iov_len = strlen(string) + 1;
- return xs_talkv(h, type, &iovec, 1, len);
+ return xs_talkv(h, t, type, &iovec, 1, len);
}

static bool xs_bool(char *reply)
@@ -417,7 +391,7 @@
char *strings, *p, **ret;
unsigned int len;

- strings = xs_single(h, XS_DIRECTORY, path, &len);
+ strings = xs_single(h, t, XS_DIRECTORY, path, &len);
if (!strings)
return NULL;

@@ -446,7 +420,7 @@
void *xs_read(struct xs_handle *h, struct xs_transaction_handle *t,
const char *path, unsigned int *len)
{
- return xs_single(h, XS_READ, path, len);
+ return xs_single(h, t, XS_READ, path, len);
}

/* Write the value of a single file.
@@ -462,7 +436,8 @@
iovec[1].iov_base = (void *)data;
iovec[1].iov_len = len;

- return xs_bool(xs_talkv(h, XS_WRITE, iovec, ARRAY_SIZE(iovec), NULL));
+ return xs_bool(xs_talkv(h, t, XS_WRITE, iovec,
+ ARRAY_SIZE(iovec), NULL));
}

/* Create a new directory.
@@ -471,7 +446,7 @@
bool xs_mkdir(struct xs_handle *h, struct xs_transaction_handle *t,
const char *path)
{
- return xs_bool(xs_single(h, XS_MKDIR, path, NULL));
+ return xs_bool(xs_single(h, t, XS_MKDIR, path, NULL));
}

/* Destroy a file or directory (directories must be empty).
@@ -480,7 +455,7 @@
bool xs_rm(struct xs_handle *h, struct xs_transaction_handle *t,
const char *path)
{
- return xs_bool(xs_single(h, XS_RM, path, NULL));
+ return xs_bool(xs_single(h, t, XS_RM, path, NULL));
}

/* Get permissions of node (first element is owner).
@@ -494,7 +469,7 @@
unsigned int len;
struct xs_permissions *ret;

- strings = xs_single(h, XS_GET_PERMS, path, &len);
+ strings = xs_single(h, t, XS_GET_PERMS, path, &len);
if (!strings)
return NULL;

@@ -544,7 +519,7 @@
goto unwind;
}

- if (!xs_bool(xs_talkv(h, XS_SET_PERMS, iov, 1+num_perms, NULL)))
+ if (!xs_bool(xs_talkv(h, t, XS_SET_PERMS, iov, 1+num_perms, NULL)))
goto unwind;
for (i = 0; i < num_perms; i++)
free(iov[i+1].iov_base);
@@ -571,7 +546,8 @@
iov[1].iov_base = (void *)token;
iov[1].iov_len = strlen(token) + 1;

- return xs_bool(xs_talkv(h, XS_WATCH, iov, ARRAY_SIZE(iov), NULL));
+ return xs_bool(xs_talkv(h, NULL, XS_WATCH, iov,
+ ARRAY_SIZE(iov), NULL));
}

/* Find out what node change was on (will block if nothing pending).
@@ -637,7 +613,8 @@
iov[1].iov_base = (char *)token;
iov[1].iov_len = strlen(token) + 1;

- return xs_bool(xs_talkv(h, XS_UNWATCH, iov, ARRAY_SIZE(iov), NULL));
+ return xs_bool(xs_talkv(h, NULL, XS_UNWATCH, iov,
+ ARRAY_SIZE(iov), NULL));
}

/* Start a transaction: changes by others will not be seen during this
@@ -647,18 +624,17 @@
*/
struct xs_transaction_handle *xs_transaction_start(struct xs_handle *h)
{
- bool rc;
-
- pthread_mutex_lock(&h->transaction_mutex);
- h->transaction_pthread = pthread_self();
-
- rc = xs_bool(xs_single(h, XS_TRANSACTION_START, "", NULL));
- if (!rc) {
- h->transaction_pthread = -1;
- pthread_mutex_unlock(&h->transaction_mutex);
- }
-
- return (struct xs_transaction_handle *)rc;
+ char *id_str;
+ unsigned long id;
+
+ id_str = xs_single(h, NULL, XS_TRANSACTION_START, "", NULL);
+ if (id_str == NULL)
+ return NULL;
+
+ id = strtoul(id_str, NULL, 0);
+ free(id_str);
+
+ return (struct xs_transaction_handle *)id;
}

/* End a transaction.
@@ -670,22 +646,13 @@
bool abort)
{
char abortstr[2];
- bool rc;
-
- if (t == NULL)
- return -EINVAL;

if (abort)
strcpy(abortstr, "F");
else
strcpy(abortstr, "T");

- rc = xs_bool(xs_single(h, XS_TRANSACTION_END, abortstr, NULL));
-
- h->transaction_pthread = -1;
- pthread_mutex_unlock(&h->transaction_mutex);
-
- return rc;
+ return xs_bool(xs_single(h, t, XS_TRANSACTION_END, abortstr, NULL));
}

/* Introduce a new domain.
@@ -713,7 +680,8 @@
iov[3].iov_base = (char *)path;
iov[3].iov_len = strlen(path) + 1;

- return xs_bool(xs_talkv(h, XS_INTRODUCE, iov, ARRAY_SIZE(iov), NULL));
+ return xs_bool(xs_talkv(h, NULL, XS_INTRODUCE, iov,
+ ARRAY_SIZE(iov), NULL));
}

bool xs_release_domain(struct xs_handle *h, domid_t domid)
@@ -722,7 +690,7 @@

sprintf(domid_str, "%u", domid);

- return xs_bool(xs_single(h, XS_RELEASE, domid_str, NULL));
+ return xs_bool(xs_single(h, NULL, XS_RELEASE, domid_str, NULL));
}

char *xs_get_domain_path(struct xs_handle *h, domid_t domid)
@@ -731,7 +699,7 @@

sprintf(domid_str, "%u", domid);

- return xs_single(h, XS_GET_DOMAIN_PATH, domid_str, NULL);
+ return xs_single(h, NULL, XS_GET_DOMAIN_PATH, domid_str, NULL);
}

/* Only useful for DEBUG versions */
@@ -745,7 +713,8 @@
iov[1].iov_base = data;
iov[1].iov_len = len;

- return xs_talkv(h, XS_DEBUG, iov, ARRAY_SIZE(iov), NULL);
+ return xs_talkv(h, NULL, XS_DEBUG, iov,
+ ARRAY_SIZE(iov), NULL);
}

static void *read_thread(void *arg)

_______________________________________________
Xen-changelog mailing list
Xen-changelog@lists.xensource.com
http://lists.xensource.com/xen-changelog
Merged. [ In reply to ]
# HG changeset patch
# User emellor@ewan
# Node ID 4e335372ace84b605cebc36a42610caadb09a4d8
# Parent 713328270fb36bb1eed7d9520626fbcb123a50f3
# Parent 959d33fbd6608de6561f80889c0f3a4b80f6d5a1
Merged.

diff -r 713328270fb3 -r 4e335372ace8 linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.c
--- a/linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.c Tue Oct 11 14:01:43 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.c Tue Oct 11 14:23:19 2005
@@ -20,69 +20,48 @@
#include <linux/sched.h>
#include <linux/err.h>
#include "xencons_ring.h"
-
-struct ring_head
-{
- u32 cons;
- u32 prod;
- char buf[0];
-} __attribute__((packed));
+#include <asm-xen/xen-public/io/console.h>

static int xencons_irq;
+static xencons_receiver_func *xencons_receiver;

-#define XENCONS_RING_SIZE (PAGE_SIZE/2 - sizeof (struct ring_head))
-#define XENCONS_IDX(cnt) ((cnt) % XENCONS_RING_SIZE)
-#define XENCONS_FULL(ring) (((ring)->prod - (ring)->cons) == XENCONS_RING_SIZE)
-
-static inline struct ring_head *outring(void)
+static inline struct xencons_interface *xencons_interface(void)
{
return mfn_to_virt(xen_start_info->console_mfn);
}

-static inline struct ring_head *inring(void)
-{
- return mfn_to_virt(xen_start_info->console_mfn) + PAGE_SIZE/2;
-}
-
-
-/* don't block - write as much as possible and return */
-static int __xencons_ring_send(
- struct ring_head *ring, const char *data, unsigned len)
-{
- int copied = 0;
-
- mb();
- while (copied < len && !XENCONS_FULL(ring)) {
- ring->buf[XENCONS_IDX(ring->prod)] = data[copied];
- ring->prod++;
- copied++;
- }
- mb();
-
- return copied;
-}
-
int xencons_ring_send(const char *data, unsigned len)
{
- int sent = __xencons_ring_send(outring(), data, len);
+ int sent = 0;
+ struct xencons_interface *intf = xencons_interface();
+
+ while ((sent < len) &&
+ (intf->out_prod - intf->out_cons) < sizeof(intf->out)) {
+ intf->out[MASK_XENCONS_IDX(intf->out_prod, intf->out)] =
+ data[sent];
+ intf->out_prod++;
+ sent++;
+ }
+
/* Use evtchn: this is called early, before irq is set up. */
notify_remote_via_evtchn(xen_start_info->console_evtchn);
+
return sent;
}

-
-static xencons_receiver_func *xencons_receiver;
-
static irqreturn_t handle_input(int irq, void *unused, struct pt_regs *regs)
{
- struct ring_head *ring = inring();
- while (ring->cons < ring->prod) {
- if (xencons_receiver != NULL) {
- xencons_receiver(ring->buf + XENCONS_IDX(ring->cons),
- 1, regs);
- }
- ring->cons++;
+ struct xencons_interface *intf = xencons_interface();
+
+ while (intf->in_cons != intf->in_prod) {
+ if (xencons_receiver != NULL)
+ xencons_receiver(
+ intf->in + MASK_XENCONS_IDX(intf->in_cons,
+ intf->in),
+ 1, regs);
+ intf->in_cons++;
}
+
return IRQ_HANDLED;
}

@@ -96,7 +75,7 @@
int err;

if (xencons_irq)
- unbind_evtchn_from_irqhandler(xencons_irq, inring());
+ unbind_evtchn_from_irqhandler(xencons_irq, NULL);
xencons_irq = 0;

if (!xen_start_info->console_evtchn)
@@ -104,7 +83,7 @@

err = bind_evtchn_to_irqhandler(
xen_start_info->console_evtchn,
- handle_input, 0, "xencons", inring());
+ handle_input, 0, "xencons", NULL);
if (err <= 0) {
xprintk("XEN console request irq failed %i\n", err);
return err;
diff -r 713328270fb3 -r 4e335372ace8 tools/console/daemon/io.c
--- a/tools/console/daemon/io.c Tue Oct 11 14:01:43 2005
+++ b/tools/console/daemon/io.c Tue Oct 11 14:23:19 2005
@@ -25,6 +25,7 @@
#include <xenctrl.h>
#include <xs.h>
#include <xen/linux/evtchn.h>
+#include <xen/io/console.h>

#include <malloc.h>
#include <stdlib.h>
@@ -62,24 +63,11 @@
char *conspath;
int ring_ref;
int local_port;
- char *page;
int evtchn_fd;
+ struct xencons_interface *interface;
};

static struct domain *dom_head;
-
-struct ring_head
-{
- u32 cons;
- u32 prod;
- char buf[0];
-} __attribute__((packed));
-
-#define PAGE_SIZE (getpagesize())
-#define XENCONS_RING_SIZE (PAGE_SIZE/2 - sizeof (struct ring_head))
-#define XENCONS_IDX(cnt) ((cnt) % XENCONS_RING_SIZE)
-#define XENCONS_FULL(ring) (((ring)->prod - (ring)->cons) == XENCONS_RING_SIZE)
-#define XENCONS_SPACE(ring) (XENCONS_RING_SIZE - ((ring)->prod - (ring)->cons))

static void evtchn_notify(struct domain *dom)
{
@@ -91,12 +79,12 @@
static void buffer_append(struct domain *dom)
{
struct buffer *buffer = &dom->buffer;
- struct ring_head *ring = (struct ring_head *)dom->page;
size_t size;
- u32 oldcons;
+ XENCONS_RING_IDX oldcons;
int notify = 0;
-
- while ((size = ring->prod - ring->cons) != 0) {
+ struct xencons_interface *intf = dom->interface;
+
+ while ((size = (intf->out_prod - intf->out_cons)) != 0) {
notify = 1;

if ((buffer->capacity - buffer->size) < size) {
@@ -108,12 +96,12 @@
}
}

- oldcons = ring->cons;
- while (ring->cons < (oldcons + size)) {
- buffer->data[buffer->size] =
- ring->buf[XENCONS_IDX(ring->cons)];
+ oldcons = intf->out_cons;
+ while ((intf->out_cons - oldcons) < size) {
+ buffer->data[buffer->size] = intf->out[
+ MASK_XENCONS_IDX(intf->out_cons, intf->out)];
buffer->size++;
- ring->cons++;
+ intf->out_cons++;
}

if (buffer->max_capacity &&
@@ -246,12 +234,13 @@
goto out;

if (ring_ref != dom->ring_ref) {
- if (dom->page)
- munmap(dom->page, getpagesize());
- dom->page = xc_map_foreign_range(xc, dom->domid, getpagesize(),
- PROT_READ|PROT_WRITE,
- (unsigned long)ring_ref);
- if (dom->page == NULL) {
+ if (dom->interface != NULL)
+ munmap(dom->interface, getpagesize());
+ dom->interface = xc_map_foreign_range(
+ xc, dom->domid, getpagesize(),
+ PROT_READ|PROT_WRITE,
+ (unsigned long)ring_ref);
+ if (dom->interface == NULL) {
err = EINVAL;
goto out;
}
@@ -334,7 +323,7 @@

dom->ring_ref = -1;
dom->local_port = -1;
- dom->page = NULL;
+ dom->interface = NULL;
dom->evtchn_fd = -1;

if (!watch_domain(dom, true))
@@ -396,9 +385,9 @@
{
d->is_dead = true;
watch_domain(d, false);
- if (d->page)
- munmap(d->page, getpagesize());
- d->page = NULL;
+ if (d->interface != NULL)
+ munmap(d->interface, getpagesize());
+ d->interface = NULL;
if (d->evtchn_fd != -1)
close(d->evtchn_fd);
d->evtchn_fd = -1;
@@ -426,13 +415,21 @@

static void handle_tty_read(struct domain *dom)
{
- ssize_t len;
+ ssize_t len = 0;
char msg[80];
- struct ring_head *inring =
- (struct ring_head *)(dom->page + PAGE_SIZE/2);
int i;
-
- len = read(dom->tty_fd, msg, MIN(XENCONS_SPACE(inring), sizeof(msg)));
+ struct xencons_interface *intf = dom->interface;
+ XENCONS_RING_IDX filled = intf->in_prod - intf->in_cons;
+
+ if (sizeof(intf->in) > filled)
+ len = sizeof(intf->in) - filled;
+ if (len > sizeof(msg))
+ len = sizeof(msg);
+
+ if (len == 0)
+ return;
+
+ len = read(dom->tty_fd, msg, len);
if (len < 1) {
close(dom->tty_fd);
dom->tty_fd = -1;
@@ -444,8 +441,9 @@
}
} else if (domain_is_valid(dom->domid)) {
for (i = 0; i < len; i++) {
- inring->buf[XENCONS_IDX(inring->prod)] = msg[i];
- inring->prod++;
+ intf->in[MASK_XENCONS_IDX(intf->in_prod, intf->in)] =
+ msg[i];
+ intf->in_prod++;
}
evtchn_notify(dom);
} else {
@@ -564,3 +562,13 @@
}
} while (ret > -1);
}
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r 713328270fb3 -r 4e335372ace8 tools/xenstore/Makefile
--- a/tools/xenstore/Makefile Tue Oct 11 14:01:43 2005
+++ b/tools/xenstore/Makefile Tue Oct 11 14:23:19 2005
@@ -129,7 +129,7 @@
tarball: clean
cd .. && tar -c -j -v -h -f xenstore.tar.bz2 xenstore/

-install: libxenstore.so xenstored $(CLIENTS)
+install: libxenstore.so xenstored xsls $(CLIENTS)
$(INSTALL_DIR) -p $(DESTDIR)/var/run/xenstored
$(INSTALL_DIR) -p $(DESTDIR)/var/lib/xenstored
$(INSTALL_DIR) -p $(DESTDIR)/usr/bin
diff -r 713328270fb3 -r 4e335372ace8 xen/include/public/io/console.h
--- /dev/null Tue Oct 11 14:01:43 2005
+++ b/xen/include/public/io/console.h Tue Oct 11 14:23:19 2005
@@ -0,0 +1,23 @@
+/******************************************************************************
+ * console.h
+ *
+ * Console I/O interface for Xen guest OSes.
+ *
+ * Copyright (c) 2005, Keir Fraser
+ */
+
+#ifndef __XEN_PUBLIC_IO_CONSOLE_H__
+#define __XEN_PUBLIC_IO_CONSOLE_H__
+
+typedef u32 XENCONS_RING_IDX;
+
+#define MASK_XENCONS_IDX(idx, ring) ((idx) & (sizeof(ring)-1))
+
+struct xencons_interface {
+ char in[1024];
+ char out[2048];
+ XENCONS_RING_IDX in_cons, in_prod;
+ XENCONS_RING_IDX out_cons, out_prod;
+};
+
+#endif /* __XEN_PUBLIC_IO_CONSOLE_H__ */

_______________________________________________
Xen-changelog mailing list
Xen-changelog@lists.xensource.com
http://lists.xensource.com/xen-changelog
Merged. [ In reply to ]
# HG changeset patch
# User emellor@ewan
# Node ID 97648825856b5685fe3493a7a41a3f61bf893fba
# Parent b938c4965a8f1cab34f27d66187a896743057c5d
# Parent 26599c5d298d128d0317a66c93332e241058ba68
Merged.

diff -r b938c4965a8f -r 97648825856b tools/firmware/acpi/acpi_gen.c
--- a/tools/firmware/acpi/acpi_gen.c Wed Oct 12 12:13:32 2005
+++ b/tools/firmware/acpi/acpi_gen.c Wed Oct 12 12:20:10 2005
@@ -16,44 +16,38 @@
*
*/
#include "acpi2_0.h"
-#include "stdio.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>

-/*
- * Generate acpi table
- * write acpi table to binary: acpitable.bin
- *
- */
-
-#define USAGE "Usage: acpi_gen filename \n" \
- " generage acpitable and write to the binary \n" \
- " filename - the binary name\n"
+#define USAGE "Usage: acpi_gen filename \n" \
+ " generage acpitable and write to the binary \n" \
+ " filename - the binary name\n"

+int main(int argc, char **argv)
+{
+ char *filename;
+ char buf[ACPI_TABLE_SIZE] = { 0 };
+ FILE *f;

-int main(int argc, char** argv){
- char* filename;
- char buf[ACPI_TABLE_SIZE];
- FILE* f=NULL;
- int i;
+ if (argc < 2) {
+ fprintf(stderr,"%s",USAGE);
+ exit(1);
+ }

- for (i=0; i<ACPI_TABLE_SIZE; i++){
- buf[i]=0;
- }
+ filename = argv[1];
+
+ if ((f = fopen(filename, "w+")) == NULL) {
+ fprintf(stderr,"Can not open %s", filename);
+ exit(1);
+ }

- if (argc<2){
- fprintf(stderr,"%s",USAGE);
- exit(1);
- }
+ AcpiBuildTable((uint8_t *)buf);

- filename = argv[1];
-
- if(!(f=fopen(filename, "w+"))){
- fprintf(stderr,"Can not open %s",filename);
- exit(1);
- }
- AcpiBuildTable(buf);
- if (fwrite(buf, ACPI_TABLE_SIZE, 1, f)<1){
- fprintf(stderr,"Can not write to %s\n",filename);
- exit(1);
- }
- return 0;
+ if (fwrite(buf, ACPI_TABLE_SIZE, 1, f) < 1) {
+ fprintf(stderr,"Can not write to %s\n", filename);
+ exit(1);
+ }
+
+ return 0;
}
diff -r b938c4965a8f -r 97648825856b tools/firmware/vmxassist/Makefile
--- a/tools/firmware/vmxassist/Makefile Wed Oct 12 12:13:32 2005
+++ b/tools/firmware/vmxassist/Makefile Wed Oct 12 12:20:10 2005
@@ -24,14 +24,14 @@
# The emulator code lives in ROM space
TEXTADDR=0x000D0000

-DEFINES=-DDEBUG -DTEXTADDR=${TEXTADDR}
+DEFINES=-DDEBUG -DTEXTADDR=$(TEXTADDR)
XENINC=-I$(XEN_ROOT)/tools/libxc

LD = ld
CC = gcc
CPP = cpp -P
OBJCOPY = objcopy -p -O binary -R .note -R .comment -R .bss -S --gap-fill=0
-CFLAGS = ${DEFINES} -I. $(XENINC) -Wall -fno-builtin -O2 -msoft-float
+CFLAGS = $(DEFINES) -I. $(XENINC) -Wall -fno-builtin -O2 -msoft-float
CFLAGS += -m32 -march=i686
LDFLAGS = -m elf_i386

@@ -40,33 +40,33 @@
all: vmxloader

vmxloader: roms.h vmxloader.c acpi.h acpi_madt.c
- ${CC} ${CFLAGS} ${DEFINES} -c vmxloader.c -c acpi_madt.c
+ $(CC) $(CFLAGS) $(DEFINES) -c vmxloader.c -c acpi_madt.c
$(CC) -o vmxloader.tmp -m32 -nostdlib -Wl,-N -Wl,-Ttext -Wl,0x100000 vmxloader.o acpi_madt.o
objcopy vmxloader.tmp vmxloader
rm -f vmxloader.tmp

-vmxassist.bin: vmxassist.ld ${OBJECTS}
- ${CPP} ${DEFINES} vmxassist.ld > vmxassist.tmp
- ${LD} -o vmxassist ${LDFLAGS} -nostdlib --fatal-warnings -N -T vmxassist.tmp ${OBJECTS}
+vmxassist.bin: vmxassist.ld $(OBJECTS)
+ $(CPP) $(DEFINES) vmxassist.ld > vmxassist.tmp
+ $(LD) -o vmxassist $(LDFLAGS) -nostdlib --fatal-warnings -N -T vmxassist.tmp $(OBJECTS)
nm -n vmxassist > vmxassist.sym
- ${OBJCOPY} vmxassist vmxassist.tmp
+ $(OBJCOPY) vmxassist vmxassist.tmp
dd if=vmxassist.tmp of=vmxassist.bin ibs=512 conv=sync
rm -f vmxassist.tmp

head.o: machine.h head.S
- ${CC} ${CFLAGS} -D__ASSEMBLY__ ${DEFINES} -c head.S
+ $(CC) $(CFLAGS) -D__ASSEMBLY__ $(DEFINES) -c head.S

trap.o: machine.h offsets.h trap.S
- ${CC} ${CFLAGS} -D__ASSEMBLY__ ${DEFINES} -c trap.S
+ $(CC) $(CFLAGS) -D__ASSEMBLY__ $(DEFINES) -c trap.S

vm86.o: machine.h vm86.c
- ${CC} ${CFLAGS} -c vm86.c
+ $(CC) $(CFLAGS) -c vm86.c

setup.o: machine.h setup.c
- ${CC} ${CFLAGS} -c setup.c
+ $(CC) $(CFLAGS) -c setup.c

util.o: machine.h util.c
- ${CC} ${CFLAGS} -c util.c
+ $(CC) $(CFLAGS) -c util.c

roms.h: ../rombios/BIOS-bochs-latest ../vgabios/VGABIOS-lgpl-latest.bin ../vgabios/VGABIOS-lgpl-latest.cirrus.bin vmxassist.bin
./mkhex rombios ../rombios/BIOS-bochs-latest > roms.h
@@ -81,10 +81,10 @@
./gen > offsets.h

gen: gen.c
- ${CC} ${CFLAGS} -o gen gen.c
+ $(HOSTCC) $(HOSTCFLAGS) -I. $(XENINC) -o gen gen.c

clean:
rm -f vmxassist vmxassist.tmp vmxassist.bin vmxassist.run vmxassist.sym head.s roms.h acpi.h
- rm -f vmxloader vmxloader.tmp vmxloader.o ${OBJECTS}
+ rm -f vmxloader vmxloader.tmp vmxloader.o $(OBJECTS)
rm -f gen gen.o offsets.h


_______________________________________________
Xen-changelog mailing list
Xen-changelog@lists.xensource.com
http://lists.xensource.com/xen-changelog

1 2 3 4 5  View All