From f1a675f424ac06f0e8aecd77006f028070e0a48e Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Sat, 27 Aug 2005 09:15:17 +0000 Subject: [PATCH 01/11] Don't build pcbios.c for xen/i386. No good can come of it. Signed-off-by: Keir Fraser --- linux-2.6-xen-sparse/arch/xen/i386/Kconfig | 12 ++++++------ linux-2.6-xen-sparse/arch/xen/i386/pci/Makefile | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/linux-2.6-xen-sparse/arch/xen/i386/Kconfig b/linux-2.6-xen-sparse/arch/xen/i386/Kconfig index 5629afccc9..5a01546a50 100644 --- a/linux-2.6-xen-sparse/arch/xen/i386/Kconfig +++ b/linux-2.6-xen-sparse/arch/xen/i386/Kconfig @@ -807,8 +807,8 @@ choice direct access method and falls back to the BIOS if that doesn't work. If unsure, go with the default, which is "Any". -config PCI_GOBIOS - bool "BIOS" +#config PCI_GOBIOS +# bool "BIOS" config PCI_GOMMCONFIG bool "MMConfig" @@ -821,10 +821,10 @@ config PCI_GOANY endchoice -config PCI_BIOS - bool - depends on !X86_VISWS && PCI && (PCI_GOBIOS || PCI_GOANY) - default y +#config PCI_BIOS +# bool +# depends on !X86_VISWS && PCI && (PCI_GOBIOS || PCI_GOANY) +# default y config PCI_DIRECT bool diff --git a/linux-2.6-xen-sparse/arch/xen/i386/pci/Makefile b/linux-2.6-xen-sparse/arch/xen/i386/pci/Makefile index 898fbd428a..263411c635 100644 --- a/linux-2.6-xen-sparse/arch/xen/i386/pci/Makefile +++ b/linux-2.6-xen-sparse/arch/xen/i386/pci/Makefile @@ -4,7 +4,7 @@ CFLAGS += -Iarch/$(XENARCH)/pci c-obj-y := i386.o -c-obj-$(CONFIG_PCI_BIOS) += pcbios.o +#c-obj-$(CONFIG_PCI_BIOS) += pcbios.o c-obj-$(CONFIG_PCI_MMCONFIG) += mmconfig.o c-obj-$(CONFIG_PCI_DIRECT) += direct.o From 4eaf491a1fbc0a20a0408d9f81b5e686e57cf642 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Sat, 27 Aug 2005 11:49:35 +0000 Subject: [PATCH 02/11] CONFIG_X86_PM_TIMER is a no-op option when building Linux for Xen, but make sure it doesn't break the build. Signed-off-by: Keir Fraser --- linux-2.6-xen-sparse/arch/xen/i386/kernel/acpi/boot.c | 2 +- linux-2.6-xen-sparse/arch/xen/x86_64/kernel/Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/linux-2.6-xen-sparse/arch/xen/i386/kernel/acpi/boot.c b/linux-2.6-xen-sparse/arch/xen/i386/kernel/acpi/boot.c index 230673abb6..bce4ef7ed4 100644 --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/acpi/boot.c +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/acpi/boot.c @@ -610,7 +610,7 @@ static int __init acpi_parse_fadt(unsigned long phys, unsigned long size) acpi_fadt.force_apic_physical_destination_mode = fadt->force_apic_physical_destination_mode; #endif -#ifdef CONFIG_X86_PM_TIMER +#if defined(CONFIG_X86_PM_TIMER) && !defined(CONFIG_XEN) /* detect the location of the ACPI PM Timer */ if (fadt->revision >= FADT2_REVISION_ID) { /* FADT rev. 2 */ diff --git a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/Makefile b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/Makefile index 51be8f355f..d08ec82b83 100644 --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/Makefile +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/Makefile @@ -40,7 +40,7 @@ obj-$(CONFIG_DUMMY_IOMMU) += pci-nommu.o i386-obj-$(CONFIG_DUMMY_IOMMU) += pci-dma.o i386-obj-$(CONFIG_SWIOTLB) += swiotlb.o obj-$(CONFIG_KPROBES) += kprobes.o -obj-$(CONFIG_X86_PM_TIMER) += pmtimer.o +#obj-$(CONFIG_X86_PM_TIMER) += pmtimer.o c-obj-$(CONFIG_MODULES) += module.o From dc5fbb4fa252fa4ed6357adba988356695db468a Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Sun, 28 Aug 2005 14:21:08 +0000 Subject: [PATCH 03/11] blkfront cleanup and retab. Signed-off-by: Keir Fraser --- .../drivers/xen/blkfront/blkfront.c | 1147 ++++------------- .../drivers/xen/blkfront/block.h | 2 - 2 files changed, 279 insertions(+), 870 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c index 758159cbe2..262b72d34f 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c @@ -32,23 +32,15 @@ */ #if 1 -#define ASSERT(_p) \ - if ( !(_p) ) { printk("Assertion '%s' failed, line %d, file %s", #_p , \ - __LINE__, __FILE__); *(int*)0=0; } +#define ASSERT(p) \ + if (!(p)) { printk("Assertion '%s' failed, line %d, file %s", #p , \ + __LINE__, __FILE__); *(int*)0=0; } #else #define ASSERT(_p) #endif #include - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) #include "block.h" -#else -#include "common.h" -#include -#include -#endif - #include #include #include @@ -58,11 +50,6 @@ #include #include -typedef unsigned char byte; /* from linux/ide.h */ - -/* Control whether runtime update of vbds is enabled. */ -#define ENABLE_VBD_UPDATE 1 - #define BLKIF_STATE_DISCONNECTED 0 #define BLKIF_STATE_CONNECTED 1 @@ -75,9 +62,9 @@ static unsigned int blkif_state = BLKIF_STATE_DISCONNECTED; #define GRANTREF_INVALID (1<<15) static struct blk_shadow { - blkif_request_t req; - unsigned long request; - unsigned long frame[BLKIF_MAX_SEGMENTS_PER_REQUEST]; + blkif_request_t req; + unsigned long request; + unsigned long frame[BLKIF_MAX_SEGMENTS_PER_REQUEST]; } blk_shadow[BLK_RING_SIZE]; unsigned long blk_shadow_free; @@ -85,64 +72,42 @@ static int recovery = 0; /* Recovery in progress: protected by blkif_io_lock */ static void kick_pending_request_queues(struct blkfront_info *info); -static int __init xlblk_init(void); - static void blkif_completion(struct blk_shadow *s); static inline int GET_ID_FROM_FREELIST(void) { - unsigned long free = blk_shadow_free; - BUG_ON(free > BLK_RING_SIZE); - blk_shadow_free = blk_shadow[free].req.id; - blk_shadow[free].req.id = 0x0fffffee; /* debug */ - return free; + unsigned long free = blk_shadow_free; + BUG_ON(free > BLK_RING_SIZE); + blk_shadow_free = blk_shadow[free].req.id; + blk_shadow[free].req.id = 0x0fffffee; /* debug */ + return free; } static inline void ADD_ID_TO_FREELIST(unsigned long id) { - blk_shadow[id].req.id = blk_shadow_free; - blk_shadow[id].request = 0; - blk_shadow_free = id; + blk_shadow[id].req.id = blk_shadow_free; + blk_shadow[id].request = 0; + blk_shadow_free = id; } - -/************************ COMMON CODE (inlined) ************************/ - -/* Kernel-specific definitions used in the common code */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -#define DISABLE_SCATTERGATHER() -#else -static int sg_operation = -1; -#define DISABLE_SCATTERGATHER() (sg_operation = -1) -#endif - static inline void pickle_request(struct blk_shadow *s, blkif_request_t *r) { - s->req = *r; + s->req = *r; } static inline void unpickle_request(blkif_request_t *r, struct blk_shadow *s) { - *r = s->req; + *r = s->req; } - static inline void flush_requests(struct blkfront_info *info) { - DISABLE_SCATTERGATHER(); - RING_PUSH_REQUESTS(&info->ring); - notify_via_evtchn(info->evtchn); + RING_PUSH_REQUESTS(&info->ring); + notify_via_evtchn(info->evtchn); } - -/************************** KERNEL VERSION 2.6 **************************/ - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - -module_init(xlblk_init); - static void kick_pending_request_queues(struct blkfront_info *info) { if (!RING_FULL(&info->ring)) { @@ -169,50 +134,44 @@ static void blkif_restart_queue_callback(void *arg) int blkif_open(struct inode *inode, struct file *filep) { - // struct gendisk *gd = inode->i_bdev->bd_disk; - // struct xlbd_disk_info *di = (struct xlbd_disk_info *)gd->private_data; - - /* Update of usage count is protected by per-device semaphore. */ - // di->mi->usage++; - return 0; } int blkif_release(struct inode *inode, struct file *filep) { - /* FIXME: This is where we can actually free up majors, etc. --RR */ - return 0; + return 0; } int blkif_ioctl(struct inode *inode, struct file *filep, unsigned command, unsigned long argument) { - int i; + int i; - DPRINTK_IOCTL("command: 0x%x, argument: 0x%lx, dev: 0x%04x\n", - command, (long)argument, inode->i_rdev); + DPRINTK_IOCTL("command: 0x%x, argument: 0x%lx, dev: 0x%04x\n", + command, (long)argument, inode->i_rdev); - switch ( command ) - { - case HDIO_GETGEO: - /* return ENOSYS to use defaults */ - return -ENOSYS; + switch ( command ) + { + case HDIO_GETGEO: + /* return ENOSYS to use defaults */ + return -ENOSYS; - case CDROMMULTISESSION: - DPRINTK("FIXME: support multisession CDs later\n"); - for ( i = 0; i < sizeof(struct cdrom_multisession); i++ ) - if ( put_user(0, (byte *)(argument + i)) ) return -EFAULT; - return 0; + case CDROMMULTISESSION: + DPRINTK("FIXME: support multisession CDs later\n"); + for (i = 0; i < sizeof(struct cdrom_multisession); i++) + if (put_user(0, (char *)(argument + i))) + return -EFAULT; + return 0; - default: - /*printk(KERN_ALERT "ioctl %08x not supported by Xen blkdev\n", - command);*/ - return -EINVAL; /* same return as native Linux */ - } + default: + /*printk(KERN_ALERT "ioctl %08x not supported by Xen blkdev\n", + command);*/ + return -EINVAL; /* same return as native Linux */ + } - return 0; + return 0; } @@ -228,76 +187,77 @@ int blkif_ioctl(struct inode *inode, struct file *filep, */ static int blkif_queue_request(struct request *req) { - struct blkfront_info *info = req->rq_disk->private_data; - unsigned long buffer_ma; - blkif_request_t *ring_req; - struct bio *bio; - struct bio_vec *bvec; - int idx; - unsigned long id; - unsigned int fsect, lsect; - int ref; - grant_ref_t gref_head; + struct blkfront_info *info = req->rq_disk->private_data; + unsigned long buffer_ma; + blkif_request_t *ring_req; + struct bio *bio; + struct bio_vec *bvec; + int idx; + unsigned long id; + unsigned int fsect, lsect; + int ref; + grant_ref_t gref_head; - if (unlikely(info->connected != BLKIF_STATE_CONNECTED)) - return 1; + if (unlikely(info->connected != BLKIF_STATE_CONNECTED)) + return 1; - if (gnttab_alloc_grant_references(BLKIF_MAX_SEGMENTS_PER_REQUEST, - &gref_head) < 0) { - gnttab_request_free_callback(&info->callback, - blkif_restart_queue_callback, info, - BLKIF_MAX_SEGMENTS_PER_REQUEST); - return 1; - } + if (gnttab_alloc_grant_references( + BLKIF_MAX_SEGMENTS_PER_REQUEST, &gref_head) < 0) { + gnttab_request_free_callback( + &info->callback, + blkif_restart_queue_callback, + info, + BLKIF_MAX_SEGMENTS_PER_REQUEST); + return 1; + } - /* Fill out a communications ring structure. */ - ring_req = RING_GET_REQUEST(&info->ring, info->ring.req_prod_pvt); - id = GET_ID_FROM_FREELIST(); - blk_shadow[id].request = (unsigned long)req; + /* Fill out a communications ring structure. */ + ring_req = RING_GET_REQUEST(&info->ring, info->ring.req_prod_pvt); + id = GET_ID_FROM_FREELIST(); + blk_shadow[id].request = (unsigned long)req; - ring_req->id = id; - ring_req->operation = rq_data_dir(req) ? BLKIF_OP_WRITE : BLKIF_OP_READ; - ring_req->sector_number = (blkif_sector_t)req->sector; - ring_req->handle = info->handle; + ring_req->id = id; + ring_req->operation = rq_data_dir(req) ? + BLKIF_OP_WRITE : BLKIF_OP_READ; + ring_req->sector_number = (blkif_sector_t)req->sector; + ring_req->handle = info->handle; - ring_req->nr_segments = 0; - rq_for_each_bio(bio, req) - { - bio_for_each_segment(bvec, bio, idx) - { - if ( ring_req->nr_segments == BLKIF_MAX_SEGMENTS_PER_REQUEST ) - BUG(); - buffer_ma = page_to_phys(bvec->bv_page); - fsect = bvec->bv_offset >> 9; - lsect = fsect + (bvec->bv_len >> 9) - 1; - /* install a grant reference. */ - ref = gnttab_claim_grant_reference(&gref_head); - ASSERT( ref != -ENOSPC ); + ring_req->nr_segments = 0; + rq_for_each_bio (bio, req) { + bio_for_each_segment (bvec, bio, idx) { + BUG_ON(ring_req->nr_segments + == BLKIF_MAX_SEGMENTS_PER_REQUEST); + buffer_ma = page_to_phys(bvec->bv_page); + fsect = bvec->bv_offset >> 9; + lsect = fsect + (bvec->bv_len >> 9) - 1; + /* install a grant reference. */ + ref = gnttab_claim_grant_reference(&gref_head); + ASSERT(ref != -ENOSPC); - gnttab_grant_foreign_access_ref( - ref, - info->backend_id, - buffer_ma >> PAGE_SHIFT, - rq_data_dir(req) ); + gnttab_grant_foreign_access_ref( + ref, + info->backend_id, + buffer_ma >> PAGE_SHIFT, + rq_data_dir(req) ); - blk_shadow[id].frame[ring_req->nr_segments] = - buffer_ma >> PAGE_SHIFT; + blk_shadow[id].frame[ring_req->nr_segments] = + buffer_ma >> PAGE_SHIFT; - ring_req->frame_and_sects[ring_req->nr_segments] = - blkif_fas_from_gref(ref, fsect, lsect); + ring_req->frame_and_sects[ring_req->nr_segments] = + blkif_fas_from_gref(ref, fsect, lsect); - ring_req->nr_segments++; - } - } + ring_req->nr_segments++; + } + } - info->ring.req_prod_pvt++; + info->ring.req_prod_pvt++; - /* Keep a private copy so we can reissue requests when recovering. */ - pickle_request(&blk_shadow[id], ring_req); + /* Keep a private copy so we can reissue requests when recovering. */ + pickle_request(&blk_shadow[id], ring_req); - gnttab_free_grant_references(gref_head); + gnttab_free_grant_references(gref_head); - return 0; + return 0; } /* @@ -306,756 +266,197 @@ static int blkif_queue_request(struct request *req) */ void do_blkif_request(request_queue_t *rq) { - struct blkfront_info *info = NULL; - struct request *req; - int queued; + struct blkfront_info *info = NULL; + struct request *req; + int queued; - DPRINTK("Entered do_blkif_request\n"); + DPRINTK("Entered do_blkif_request\n"); - queued = 0; + queued = 0; - while ( (req = elv_next_request(rq)) != NULL ) - { - info = req->rq_disk->private_data; + while ((req = elv_next_request(rq)) != NULL) { + info = req->rq_disk->private_data; - if ( !blk_fs_request(req) ) - { - end_request(req, 0); - continue; - } + if (!blk_fs_request(req)) { + end_request(req, 0); + continue; + } - if (RING_FULL(&info->ring)) - goto wait; + if (RING_FULL(&info->ring)) + goto wait; - DPRINTK("do_blk_req %p: cmd %p, sec %lx, (%u/%li) buffer:%p [%s]\n", - req, req->cmd, req->sector, req->current_nr_sectors, - req->nr_sectors, req->buffer, - rq_data_dir(req) ? "write" : "read"); + DPRINTK("do_blk_req %p: cmd %p, sec %lx, " + "(%u/%li) buffer:%p [%s]\n", + req, req->cmd, req->sector, req->current_nr_sectors, + req->nr_sectors, req->buffer, + rq_data_dir(req) ? "write" : "read"); - blkdev_dequeue_request(req); - if (blkif_queue_request(req)) { - blk_requeue_request(rq, req); - wait: - /* Avoid pointless unplugs. */ - blk_stop_queue(rq); - break; - } + blkdev_dequeue_request(req); + if (blkif_queue_request(req)) { + blk_requeue_request(rq, req); + wait: + /* Avoid pointless unplugs. */ + blk_stop_queue(rq); + break; + } - queued++; - } + queued++; + } - if ( queued != 0 ) - flush_requests(info); + if (queued != 0) + flush_requests(info); } static irqreturn_t blkif_int(int irq, void *dev_id, struct pt_regs *ptregs) { - struct request *req; - blkif_response_t *bret; - RING_IDX i, rp; - unsigned long flags; - struct blkfront_info *info = (struct blkfront_info *)dev_id; + struct request *req; + blkif_response_t *bret; + RING_IDX i, rp; + unsigned long flags; + struct blkfront_info *info = (struct blkfront_info *)dev_id; - spin_lock_irqsave(&blkif_io_lock, flags); + spin_lock_irqsave(&blkif_io_lock, flags); - if (unlikely(info->connected != BLKIF_STATE_CONNECTED || recovery)) { - spin_unlock_irqrestore(&blkif_io_lock, flags); - return IRQ_HANDLED; - } + if (unlikely(info->connected != BLKIF_STATE_CONNECTED || recovery)) { + spin_unlock_irqrestore(&blkif_io_lock, flags); + return IRQ_HANDLED; + } - rp = info->ring.sring->rsp_prod; - rmb(); /* Ensure we see queued responses up to 'rp'. */ + rp = info->ring.sring->rsp_prod; + rmb(); /* Ensure we see queued responses up to 'rp'. */ - for ( i = info->ring.rsp_cons; i != rp; i++ ) - { - unsigned long id; + for (i = info->ring.rsp_cons; i != rp; i++) { + unsigned long id; - bret = RING_GET_RESPONSE(&info->ring, i); - id = bret->id; - req = (struct request *)blk_shadow[id].request; + bret = RING_GET_RESPONSE(&info->ring, i); + id = bret->id; + req = (struct request *)blk_shadow[id].request; - blkif_completion(&blk_shadow[id]); + blkif_completion(&blk_shadow[id]); - ADD_ID_TO_FREELIST(id); + ADD_ID_TO_FREELIST(id); - switch ( bret->operation ) - { - case BLKIF_OP_READ: - case BLKIF_OP_WRITE: - if ( unlikely(bret->status != BLKIF_RSP_OKAY) ) - DPRINTK("Bad return from blkdev data request: %x\n", - bret->status); + switch (bret->operation) { + case BLKIF_OP_READ: + case BLKIF_OP_WRITE: + if (unlikely(bret->status != BLKIF_RSP_OKAY)) + DPRINTK("Bad return from blkdev data " + "request: %x\n", bret->status); - if ( unlikely(end_that_request_first - (req, - (bret->status == BLKIF_RSP_OKAY), - req->hard_nr_sectors)) ) - BUG(); - end_that_request_last(req); + BUG_ON(end_that_request_first( + req, (bret->status == BLKIF_RSP_OKAY), + req->hard_nr_sectors)); + end_that_request_last(req); + break; + default: + BUG(); + } + } - break; - default: - BUG(); - } - } + info->ring.rsp_cons = i; - info->ring.rsp_cons = i; + kick_pending_request_queues(info); - kick_pending_request_queues(info); + spin_unlock_irqrestore(&blkif_io_lock, flags); - spin_unlock_irqrestore(&blkif_io_lock, flags); - - return IRQ_HANDLED; + return IRQ_HANDLED; } -#else -/************************** KERNEL VERSION 2.4 **************************/ - -static kdev_t sg_dev; -static unsigned long sg_next_sect; - -/* - * Request queues with outstanding work, but ring is currently full. - * We need no special lock here, as we always access this with the - * blkif_io_lock held. We only need a small maximum list. - */ -#define MAX_PENDING 8 -static request_queue_t *pending_queues[MAX_PENDING]; -static int nr_pending; - - -#define blkif_io_lock io_request_lock - -/*============================================================================*/ -static void kick_pending_request_queues(void) -{ - /* We kick pending request queues if the ring is reasonably empty. */ - if ( (nr_pending != 0) && - (RING_PENDING_REQUESTS(&info->ring) < (BLK_RING_SIZE >> 1)) ) - { - /* Attempt to drain the queue, but bail if the ring becomes full. */ - while ( (nr_pending != 0) && !RING_FULL(&info->ring) ) - do_blkif_request(pending_queues[--nr_pending]); - } -} - -int blkif_open(struct inode *inode, struct file *filep) -{ - short xldev = inode->i_rdev; - struct gendisk *gd = get_gendisk(xldev); - xl_disk_t *disk = xldev_to_xldisk(inode->i_rdev); - short minor = MINOR(xldev); - - if ( gd->part[minor].nr_sects == 0 ) - { - /* - * Device either doesn't exist, or has zero capacity; we use a few - * cheesy heuristics to return the relevant error code - */ - if ( (gd->sizes[minor >> gd->minor_shift] != 0) || - ((minor & (gd->max_p - 1)) != 0) ) - { - /* - * We have a real device, but no such partition, or we just have a - * partition number so guess this is the problem. - */ - return -ENXIO; /* no such device or address */ - } - else if ( gd->flags[minor >> gd->minor_shift] & GENHD_FL_REMOVABLE ) - { - /* This is a removable device => assume that media is missing. */ - return -ENOMEDIUM; /* media not present (this is a guess) */ - } - else - { - /* Just go for the general 'no such device' error. */ - return -ENODEV; /* no such device */ - } - } - - /* Update of usage count is protected by per-device semaphore. */ - disk->usage++; - - return 0; -} - - -int blkif_release(struct inode *inode, struct file *filep) -{ - xl_disk_t *disk = xldev_to_xldisk(inode->i_rdev); - - /* - * When usage drops to zero it may allow more VBD updates to occur. - * Update of usage count is protected by a per-device semaphore. - */ - if ( --disk->usage == 0 ) { - vbd_update(); - } - - return 0; -} - - -int blkif_ioctl(struct inode *inode, struct file *filep, - unsigned command, unsigned long argument) -{ - kdev_t dev = inode->i_rdev; - struct hd_geometry *geo = (struct hd_geometry *)argument; - struct gendisk *gd; - struct hd_struct *part; - int i; - unsigned short cylinders; - byte heads, sectors; - - /* NB. No need to check permissions. That is done for us. */ - - DPRINTK_IOCTL("command: 0x%x, argument: 0x%lx, dev: 0x%04x\n", - command, (long) argument, dev); - - gd = get_gendisk(dev); - part = &gd->part[MINOR(dev)]; - - switch ( command ) - { - case BLKGETSIZE: - DPRINTK_IOCTL(" BLKGETSIZE: %x %lx\n", BLKGETSIZE, part->nr_sects); - return put_user(part->nr_sects, (unsigned long *) argument); - - case BLKGETSIZE64: - DPRINTK_IOCTL(" BLKGETSIZE64: %x %llx\n", BLKGETSIZE64, - (u64)part->nr_sects * 512); - return put_user((u64)part->nr_sects * 512, (u64 *) argument); - - case BLKRRPART: /* re-read partition table */ - DPRINTK_IOCTL(" BLKRRPART: %x\n", BLKRRPART); - return blkif_revalidate(dev); - - case BLKSSZGET: - return hardsect_size[MAJOR(dev)][MINOR(dev)]; - - case BLKBSZGET: /* get block size */ - DPRINTK_IOCTL(" BLKBSZGET: %x\n", BLKBSZGET); - break; - - case BLKBSZSET: /* set block size */ - DPRINTK_IOCTL(" BLKBSZSET: %x\n", BLKBSZSET); - break; - - case BLKRASET: /* set read-ahead */ - DPRINTK_IOCTL(" BLKRASET: %x\n", BLKRASET); - break; - - case BLKRAGET: /* get read-ahead */ - DPRINTK_IOCTL(" BLKRAFET: %x\n", BLKRAGET); - break; - - case HDIO_GETGEO: - DPRINTK_IOCTL(" HDIO_GETGEO: %x\n", HDIO_GETGEO); - if (!argument) return -EINVAL; - - /* We don't have real geometry info, but let's at least return - values consistent with the size of the device */ - - heads = 0xff; - sectors = 0x3f; - cylinders = part->nr_sects / (heads * sectors); - - if (put_user(0x00, (unsigned long *) &geo->start)) return -EFAULT; - if (put_user(heads, (byte *)&geo->heads)) return -EFAULT; - if (put_user(sectors, (byte *)&geo->sectors)) return -EFAULT; - if (put_user(cylinders, (unsigned short *)&geo->cylinders)) return -EFAULT; - - return 0; - - case HDIO_GETGEO_BIG: - DPRINTK_IOCTL(" HDIO_GETGEO_BIG: %x\n", HDIO_GETGEO_BIG); - if (!argument) return -EINVAL; - - /* We don't have real geometry info, but let's at least return - values consistent with the size of the device */ - - heads = 0xff; - sectors = 0x3f; - cylinders = part->nr_sects / (heads * sectors); - - if (put_user(0x00, (unsigned long *) &geo->start)) return -EFAULT; - if (put_user(heads, (byte *)&geo->heads)) return -EFAULT; - if (put_user(sectors, (byte *)&geo->sectors)) return -EFAULT; - if (put_user(cylinders, (unsigned int *) &geo->cylinders)) return -EFAULT; - - return 0; - - case CDROMMULTISESSION: - DPRINTK("FIXME: support multisession CDs later\n"); - for ( i = 0; i < sizeof(struct cdrom_multisession); i++ ) - if ( put_user(0, (byte *)(argument + i)) ) return -EFAULT; - return 0; - - case SCSI_IOCTL_GET_BUS_NUMBER: - DPRINTK("FIXME: SCSI_IOCTL_GET_BUS_NUMBER ioctl in XL blkif"); - return -ENOSYS; - - default: - WPRINTK("ioctl %08x not supported by XL blkif\n", command); - return -ENOSYS; - } - - return 0; -} - - - -/* check media change: should probably do something here in some cases :-) */ -int blkif_check(kdev_t dev) -{ - DPRINTK("blkif_check\n"); - return 0; -} - -int blkif_revalidate(kdev_t dev) -{ - struct block_device *bd; - struct gendisk *gd; - xl_disk_t *disk; - unsigned long capacity; - int i, rc = 0; - - if ( (bd = bdget(dev)) == NULL ) - return -EINVAL; - - /* - * Update of partition info, and check of usage count, is protected - * by the per-block-device semaphore. - */ - down(&bd->bd_sem); - - if ( ((gd = get_gendisk(dev)) == NULL) || - ((disk = xldev_to_xldisk(dev)) == NULL) || - ((capacity = gd->part[MINOR(dev)].nr_sects) == 0) ) - { - rc = -EINVAL; - goto out; - } - - if ( disk->usage > 1 ) - { - rc = -EBUSY; - goto out; - } - - /* Only reread partition table if VBDs aren't mapped to partitions. */ - if ( !(gd->flags[MINOR(dev) >> gd->minor_shift] & GENHD_FL_VIRT_PARTNS) ) - { - for ( i = gd->max_p - 1; i >= 0; i-- ) - { - invalidate_device(dev+i, 1); - gd->part[MINOR(dev+i)].start_sect = 0; - gd->part[MINOR(dev+i)].nr_sects = 0; - gd->sizes[MINOR(dev+i)] = 0; - } - - grok_partitions(gd, MINOR(dev)>>gd->minor_shift, gd->max_p, capacity); - } - - out: - up(&bd->bd_sem); - bdput(bd); - return rc; -} - - -/* - * blkif_queue_request - * - * request block io - * - * id: for guest use only. - * operation: BLKIF_OP_{READ,WRITE,PROBE} - * buffer: buffer to read/write into. this should be a - * virtual address in the guest os. - */ -static int blkif_queue_request(unsigned long id, - int operation, - char * buffer, - unsigned long sector_number, - unsigned short nr_sectors, - kdev_t device, - blkif_vdev_t handle) -{ - unsigned long buffer_ma = virt_to_bus(buffer); - unsigned long xid; - struct gendisk *gd; - blkif_request_t *req; - struct buffer_head *bh; - unsigned int fsect, lsect; - int ref; - - fsect = (buffer_ma & ~PAGE_MASK) >> 9; - lsect = fsect + nr_sectors - 1; - - /* Buffer must be sector-aligned. Extent mustn't cross a page boundary. */ - if ( unlikely((buffer_ma & ((1<<9)-1)) != 0) ) - BUG(); - if ( lsect > ((PAGE_SIZE/512)-1) ) - BUG(); - - buffer_ma &= PAGE_MASK; - - if (unlikely(info->connected != BLKIF_STATE_CONNECTED)) - return 1; - - switch ( operation ) - { - - case BLKIF_OP_READ: - case BLKIF_OP_WRITE: - gd = get_gendisk(device); - - /* - * Update the sector_number we'll pass down as appropriate; note that - * we could sanity check that resulting sector will be in this - * partition, but this will happen in driver backend anyhow. - */ - sector_number += gd->part[MINOR(device)].start_sect; - - /* - * If this unit doesn't consist of virtual partitions then we clear - * the partn bits from the device number. - */ - if ( !(gd->flags[MINOR(device)>>gd->minor_shift] & - GENHD_FL_VIRT_PARTNS) ) - device &= ~(gd->max_p - 1); - - if ( (sg_operation == operation) && - (sg_dev == device) && - (sg_next_sect == sector_number) ) - { - req = RING_GET_REQUEST(&info->ring, - info->ring.req_prod_pvt - 1); - bh = (struct buffer_head *)id; - - bh->b_reqnext = (struct buffer_head *)blk_shadow[req->id].request; - blk_shadow[req->id].request = (unsigned long)id; - - /* install a grant reference. */ - ref = gnttab_claim_grant_reference(&gref_head); - ASSERT( ref != -ENOSPC ); - - gnttab_grant_foreign_access_ref( - ref, - info->backend_id, - buffer_ma >> PAGE_SHIFT, - ( operation == BLKIF_OP_WRITE ? 1 : 0 ) ); - - blk_shadow[req->id].frame[req->nr_segments] = - buffer_ma >> PAGE_SHIFT; - - req->frame_and_sects[req->nr_segments] = - blkif_fas_from_gref(ref, fsect, lsect); - if ( ++req->nr_segments < BLKIF_MAX_SEGMENTS_PER_REQUEST ) - sg_next_sect += nr_sectors; - else - DISABLE_SCATTERGATHER(); - - /* Update the copy of the request in the recovery ring. */ - pickle_request(&blk_shadow[req->id], req ); - - return 0; - } - else if ( RING_FULL(&info->ring) ) - { - return 1; - } - else - { - sg_operation = operation; - sg_dev = device; - sg_next_sect = sector_number + nr_sectors; - } - break; - - default: - panic("unknown op %d\n", operation); - } - - /* Fill out a communications ring structure. */ - req = RING_GET_REQUEST(&info->ring, info->ring.req_prod_pvt); - - xid = GET_ID_FROM_FREELIST(); - blk_shadow[xid].request = (unsigned long)id; - - req->id = xid; - req->operation = operation; - req->sector_number = (blkif_sector_t)sector_number; - req->handle = handle; - req->nr_segments = 1; - /* install a grant reference. */ - ref = gnttab_claim_grant_reference(&gref_head); - ASSERT( ref != -ENOSPC ); - - gnttab_grant_foreign_access_ref( - ref, - info->backend_id, - buffer_ma >> PAGE_SHIFT, - ( operation == BLKIF_OP_WRITE ? 1 : 0 ) ); - - blk_shadow[xid].frame[0] = buffer_ma >> PAGE_SHIFT; - - req->frame_and_sects[0] = blkif_fas_from_gref(ref, fsect, lsect); - - /* Keep a private copy so we can reissue requests when recovering. */ - pickle_request(&blk_shadow[xid], req); - - info->ring.req_prod_pvt++; - - return 0; -} - - -/* - * do_blkif_request - * read a block; request is in a request queue - */ -void do_blkif_request(request_queue_t *rq) -{ - struct request *req; - struct buffer_head *bh, *next_bh; - int rw, nsect, full, queued = 0; - - DPRINTK("Entered do_blkif_request\n"); - - while ( !rq->plugged && !list_empty(&rq->queue_head)) - { - if ( (req = blkdev_entry_next_request(&rq->queue_head)) == NULL ) - goto out; - - DPRINTK("do_blkif_request %p: cmd %i, sec %lx, (%li/%li) bh:%p\n", - req, req->cmd, req->sector, - req->current_nr_sectors, req->nr_sectors, req->bh); - - rw = req->cmd; - if ( rw == READA ) - rw = READ; - if ( unlikely((rw != READ) && (rw != WRITE)) ) - panic("XenoLinux Virtual Block Device: bad cmd: %d\n", rw); - - req->errors = 0; - - bh = req->bh; - while ( bh != NULL ) - { - next_bh = bh->b_reqnext; - bh->b_reqnext = NULL; - - full = blkif_queue_request( - (unsigned long)bh, - (rw == READ) ? BLKIF_OP_READ : BLKIF_OP_WRITE, - bh->b_data, bh->b_rsector, bh->b_size>>9, bh->b_rdev); - - if ( full ) - { - bh->b_reqnext = next_bh; - pending_queues[nr_pending++] = rq; - if ( unlikely(nr_pending >= MAX_PENDING) ) - BUG(); - goto out; - } - - queued++; - - /* Dequeue the buffer head from the request. */ - nsect = bh->b_size >> 9; - bh = req->bh = next_bh; - - if ( bh != NULL ) - { - /* There's another buffer head to do. Update the request. */ - req->hard_sector += nsect; - req->hard_nr_sectors -= nsect; - req->sector = req->hard_sector; - req->nr_sectors = req->hard_nr_sectors; - req->current_nr_sectors = bh->b_size >> 9; - req->buffer = bh->b_data; - } - else - { - /* That was the last buffer head. Finalise the request. */ - if ( unlikely(end_that_request_first(req, 1, "XenBlk")) ) - BUG(); - blkdev_dequeue_request(req); - end_that_request_last(req); - } - } - } - - out: - if ( queued != 0 ) - flush_requests(); -} - - -static void blkif_int(int irq, void *dev_id, struct pt_regs *ptregs) -{ - RING_IDX i, rp; - unsigned long flags; - struct buffer_head *bh, *next_bh; - - spin_lock_irqsave(&io_request_lock, flags); - - if ( unlikely(info->connected != BLKIF_STATE_CONNECTED || recovery) ) - { - spin_unlock_irqrestore(&io_request_lock, flags); - return; - } - - rp = info->ring.sring->rsp_prod; - rmb(); /* Ensure we see queued responses up to 'rp'. */ - - for ( i = info->ring.rsp_cons; i != rp; i++ ) - { - unsigned long id; - blkif_response_t *bret; - - bret = RING_GET_RESPONSE(&info->ring, i); - id = bret->id; - bh = (struct buffer_head *)blk_shadow[id].request; - - blkif_completion(&blk_shadow[id]); - - ADD_ID_TO_FREELIST(id); - - switch ( bret->operation ) - { - case BLKIF_OP_READ: - case BLKIF_OP_WRITE: - if ( unlikely(bret->status != BLKIF_RSP_OKAY) ) - DPRINTK("Bad return from blkdev data request: %lx\n", - bret->status); - for ( ; bh != NULL; bh = next_bh ) - { - next_bh = bh->b_reqnext; - bh->b_reqnext = NULL; - bh->b_end_io(bh, bret->status == BLKIF_RSP_OKAY); - } - - break; - case BLKIF_OP_PROBE: - memcpy(&blkif_control_rsp, bret, sizeof(*bret)); - blkif_control_rsp_valid = 1; - break; - default: - BUG(); - } - - } - info->ring.rsp_cons = i; - - kick_pending_request_queues(); - - spin_unlock_irqrestore(&io_request_lock, flags); -} - -#endif - -/***************************** COMMON CODE *******************************/ - static void blkif_free(struct blkfront_info *info) { - /* Prevent new requests being issued until we fix things up. */ - spin_lock_irq(&blkif_io_lock); - info->connected = BLKIF_STATE_DISCONNECTED; - spin_unlock_irq(&blkif_io_lock); + /* Prevent new requests being issued until we fix things up. */ + spin_lock_irq(&blkif_io_lock); + info->connected = BLKIF_STATE_DISCONNECTED; + spin_unlock_irq(&blkif_io_lock); - /* Free resources associated with old device channel. */ - if ( info->ring.sring != NULL ) - { - free_page((unsigned long)info->ring.sring); - info->ring.sring = NULL; - } - unbind_evtchn_from_irqhandler(info->evtchn, NULL); - info->evtchn = 0; + /* Free resources associated with old device channel. */ + if (info->ring.sring != NULL) { + free_page((unsigned long)info->ring.sring); + info->ring.sring = NULL; + } + unbind_evtchn_from_irqhandler(info->evtchn, NULL); + info->evtchn = 0; } static void blkif_recover(struct blkfront_info *info) { - int i; - blkif_request_t *req; - struct blk_shadow *copy; - int j; + int i; + blkif_request_t *req; + struct blk_shadow *copy; + int j; - /* Stage 1: Make a safe copy of the shadow state. */ - copy = (struct blk_shadow *)kmalloc(sizeof(blk_shadow), GFP_KERNEL); - BUG_ON(copy == NULL); - memcpy(copy, blk_shadow, sizeof(blk_shadow)); + /* Stage 1: Make a safe copy of the shadow state. */ + copy = (struct blk_shadow *)kmalloc(sizeof(blk_shadow), GFP_KERNEL); + BUG_ON(copy == NULL); + memcpy(copy, blk_shadow, sizeof(blk_shadow)); - /* Stage 2: Set up free list. */ - memset(&blk_shadow, 0, sizeof(blk_shadow)); - for ( i = 0; i < BLK_RING_SIZE; i++ ) - blk_shadow[i].req.id = i+1; - blk_shadow_free = info->ring.req_prod_pvt; - blk_shadow[BLK_RING_SIZE-1].req.id = 0x0fffffff; + /* Stage 2: Set up free list. */ + memset(&blk_shadow, 0, sizeof(blk_shadow)); + for (i = 0; i < BLK_RING_SIZE; i++) + blk_shadow[i].req.id = i+1; + blk_shadow_free = info->ring.req_prod_pvt; + blk_shadow[BLK_RING_SIZE-1].req.id = 0x0fffffff; - /* Stage 3: Find pending requests and requeue them. */ - for ( i = 0; i < BLK_RING_SIZE; i++ ) - { - /* Not in use? */ - if ( copy[i].request == 0 ) - continue; + /* Stage 3: Find pending requests and requeue them. */ + for (i = 0; i < BLK_RING_SIZE; i++) { + /* Not in use? */ + if (copy[i].request == 0) + continue; - /* Grab a request slot and unpickle shadow state into it. */ - req = RING_GET_REQUEST( - &info->ring, info->ring.req_prod_pvt); - unpickle_request(req, ©[i]); + /* Grab a request slot and unpickle shadow state into it. */ + req = RING_GET_REQUEST( + &info->ring, info->ring.req_prod_pvt); + unpickle_request(req, ©[i]); - /* We get a new request id, and must reset the shadow state. */ - req->id = GET_ID_FROM_FREELIST(); - memcpy(&blk_shadow[req->id], ©[i], sizeof(copy[i])); + /* We get a new request id, and must reset the shadow state. */ + req->id = GET_ID_FROM_FREELIST(); + memcpy(&blk_shadow[req->id], ©[i], sizeof(copy[i])); - /* Rewrite any grant references invalidated by suspend/resume. */ - for ( j = 0; j < req->nr_segments; j++ ) - { - if ( req->frame_and_sects[j] & GRANTREF_INVALID ) - gnttab_grant_foreign_access_ref( - blkif_gref_from_fas(req->frame_and_sects[j]), - info->backend_id, - blk_shadow[req->id].frame[j], - rq_data_dir((struct request *) - blk_shadow[req->id].request)); - req->frame_and_sects[j] &= ~GRANTREF_INVALID; - } - blk_shadow[req->id].req = *req; + /* Rewrite any grant references invalidated by susp/resume. */ + for (j = 0; j < req->nr_segments; j++) { + if ( req->frame_and_sects[j] & GRANTREF_INVALID ) + gnttab_grant_foreign_access_ref( + blkif_gref_from_fas( + req->frame_and_sects[j]), + info->backend_id, + blk_shadow[req->id].frame[j], + rq_data_dir( + (struct request *) + blk_shadow[req->id].request)); + req->frame_and_sects[j] &= ~GRANTREF_INVALID; + } + blk_shadow[req->id].req = *req; - info->ring.req_prod_pvt++; - } + info->ring.req_prod_pvt++; + } - kfree(copy); + kfree(copy); - recovery = 0; + recovery = 0; - /* info->ring->req_prod will be set when we flush_requests().*/ - wmb(); + /* info->ring->req_prod will be set when we flush_requests().*/ + wmb(); - /* Kicks things back into life. */ - flush_requests(info); + /* Kicks things back into life. */ + flush_requests(info); - /* Now safe to left other people use the interface. */ - info->connected = BLKIF_STATE_CONNECTED; + /* Now safe to left other people use the interface. */ + info->connected = BLKIF_STATE_CONNECTED; } static void blkif_connect(struct blkfront_info *info, u16 evtchn) { - int err = 0; + int err = 0; - info->evtchn = evtchn; + info->evtchn = evtchn; - err = bind_evtchn_to_irqhandler( - info->evtchn, blkif_int, SA_SAMPLE_RANDOM, "blkif", info); - if ( err != 0 ) - { - WPRINTK("bind_evtchn_to_irqhandler failed (err=%d)\n", err); - return; - } + err = bind_evtchn_to_irqhandler( + info->evtchn, blkif_int, SA_SAMPLE_RANDOM, "blkif", info); + if (err != 0) { + WPRINTK("bind_evtchn_to_irqhandler failed (err=%d)\n", err); + return; + } } @@ -1329,55 +730,65 @@ static void __init init_blk_xenbus(void) static int wait_for_blkif(void) { - int err = 0; - int i; + int err = 0; + int i; - /* - * We should figure out how many and which devices we need to - * proceed and only wait for those. For now, continue once the - * first device is around. - */ - for ( i=0; blkif_state != BLKIF_STATE_CONNECTED && (i < 10*HZ); i++ ) - { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); - } + /* + * We should figure out how many and which devices we need to + * proceed and only wait for those. For now, continue once the + * first device is around. + */ + for (i = 0; blkif_state != BLKIF_STATE_CONNECTED && (i < 10*HZ); i++) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(1); + } - if ( blkif_state != BLKIF_STATE_CONNECTED ) - { - WPRINTK("Timeout connecting to device!\n"); - err = -ENOSYS; - } - return err; + if (blkif_state != BLKIF_STATE_CONNECTED) { + WPRINTK("Timeout connecting to device!\n"); + err = -ENOSYS; + } + return err; } static int __init xlblk_init(void) { - int i; + int i; - 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; - IPRINTK("Initialising virtual block device driver\n"); + IPRINTK("Initialising virtual block device driver\n"); - blk_shadow_free = 0; - memset(blk_shadow, 0, sizeof(blk_shadow)); - for ( i = 0; i < BLK_RING_SIZE; i++ ) - blk_shadow[i].req.id = i+1; - blk_shadow[BLK_RING_SIZE-1].req.id = 0x0fffffff; + blk_shadow_free = 0; + memset(blk_shadow, 0, sizeof(blk_shadow)); + for (i = 0; i < BLK_RING_SIZE; i++) + blk_shadow[i].req.id = i+1; + blk_shadow[BLK_RING_SIZE-1].req.id = 0x0fffffff; - init_blk_xenbus(); + init_blk_xenbus(); - wait_for_blkif(); + wait_for_blkif(); - return 0; + return 0; } +module_init(xlblk_init); + static void blkif_completion(struct blk_shadow *s) { - int i; - for ( i = 0; i < s->req.nr_segments; i++ ) - gnttab_free_grant_reference( - blkif_gref_from_fas(s->req.frame_and_sects[i])); + int i; + for (i = 0; i < s->req.nr_segments; i++) + gnttab_free_grant_reference( + blkif_gref_from_fas(s->req.frame_and_sects[i])); } + +/* + * Local variables: + * c-file-style: "linux" + * indent-tabs-mode: t + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ diff --git a/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h b/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h index 93e9db08eb..4d3cc00773 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h @@ -116,9 +116,7 @@ struct blkfront_info blkif_front_ring_t ring; unsigned int evtchn; struct xlbd_major_info *mi; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) request_queue_t *rq; -#endif struct work_struct work; struct gnttab_free_callback callback; }; From 1f1e576a4a165e81684ed43c7878f30571e7bac2 Mon Sep 17 00:00:00 2001 From: "shand@ubuntu.eng.hq.xensource.com" Date: Sun, 28 Aug 2005 21:40:36 -0800 Subject: [PATCH 04/11] Fix nasty tools race between barking xu_autoreap() and xpopen3.wait() - save/restore now seems more robust from a tools pov at least. Signed-off-by: Steven Hand --- tools/libxc/xc_linux_save.c | 4 +-- tools/python/xen/xend/XendCheckpoint.py | 7 ++--- tools/python/xen/xend/server/SrvDaemon.py | 32 +++++++++++------------ 3 files changed, 21 insertions(+), 22 deletions(-) diff --git a/tools/libxc/xc_linux_save.c b/tools/libxc/xc_linux_save.c index f83d9a5481..a4ae0c8db7 100644 --- a/tools/libxc/xc_linux_save.c +++ b/tools/libxc/xc_linux_save.c @@ -763,8 +763,6 @@ int xc_linux_save(int xc_handle, int io_fd, u32 dom) batch++; } -// DPRINTF("batch %d:%d (n=%d)\n", iter, batch, n); - if ( batch == 0 ) goto skip; /* vanishingly unlikely... */ @@ -915,7 +913,7 @@ int xc_linux_save(int xc_handle, int io_fd, u32 dom) continue; } - if ( last_iter ) break; + if ( last_iter ) break; if ( live ) { diff --git a/tools/python/xen/xend/XendCheckpoint.py b/tools/python/xen/xend/XendCheckpoint.py index e2a7d574ed..1fdcda04e2 100644 --- a/tools/python/xen/xend/XendCheckpoint.py +++ b/tools/python/xen/xend/XendCheckpoint.py @@ -51,7 +51,7 @@ def save(xd, fd, dominfo): p = select.poll() p.register(child.fromchild.fileno()) p.register(child.childerr.fileno()) - while True: + while True: r = p.poll() for (fd, event) in r: if not event & select.POLLIN: @@ -69,8 +69,9 @@ def save(xd, fd, dominfo): try: dominfo.db.releaseDomain(dominfo.id) except Exception, ex: - log.warning("error in domain release on xenstore: %s", - ex) + log.warning( + "error in domain release on xenstore: %s", + ex) pass dominfo.state_wait("suspended") log.info("suspend %d done" % dominfo.id) diff --git a/tools/python/xen/xend/server/SrvDaemon.py b/tools/python/xen/xend/server/SrvDaemon.py index 2b0d6b3b27..0a8060fb47 100644 --- a/tools/python/xen/xend/server/SrvDaemon.py +++ b/tools/python/xen/xend/server/SrvDaemon.py @@ -42,7 +42,8 @@ class Daemon: self.traceon = 0 self.tracefile = None self.traceindent = 0 - + self.child = 0 + def daemon_pids(self): pids = [] pidex = '(?P\d+)' @@ -140,15 +141,12 @@ class Daemon: else: return 0 - def install_child_reaper(self): - #signal.signal(signal.SIGCHLD, self.onSIGCHLD) - # Ensure that zombie children are automatically reaped. - xu.autoreap() - def onSIGCHLD(self, signum, frame): - code = 1 - while code > 0: - code = os.waitpid(-1, os.WNOHANG) + if self.child > 0: + try: + pid, sts = os.waitpid(self.child, os.WNOHANG) + except os.error, ex: + pass def fork_pid(self, pidfile): """Fork and write the pid of the child to 'pidfile'. @@ -156,13 +154,16 @@ class Daemon: @param pidfile: pid file @return: pid of child in parent, 0 in child """ - pid = os.fork() - if pid: + + self.child = os.fork() + + if self.child: # Parent pidfile = open(pidfile, 'w') - pidfile.write(str(pid)) + pidfile.write(str(self.child)) pidfile.close() - return pid + + return self.child def daemonize(self): if not XEND_DAEMONIZE: return @@ -203,8 +204,7 @@ class Daemon: # Trying to run an already-running service is a success. return 0 - self.install_child_reaper() - + signal.signal(signal.SIGCHLD, self.onSIGCHLD) if self.fork_pid(XEND_PID_FILE): #Parent. Sleep to give child time to start. time.sleep(1) @@ -309,7 +309,7 @@ class Daemon: print >>sys.stderr, 'Exception starting xend:', ex if XEND_DEBUG: traceback.print_exc() - log.exception("Exception starting xend") + log.exception("Exception starting xend (%s)" % ex) self.exit(1) def createFactories(self): From cabdee2e7cd28950d66467cbc7c7f6377f9f11f9 Mon Sep 17 00:00:00 2001 From: "shand@ubuntu.eng.hq.xensource.com" Date: Sun, 28 Aug 2005 21:50:04 -0800 Subject: [PATCH 05/11] Minor (partial) build fix for 2.4. Signed-off-by: Steven Hand --- linux-2.4-xen-sparse/mkbuildtree | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/linux-2.4-xen-sparse/mkbuildtree b/linux-2.4-xen-sparse/mkbuildtree index 40381c8895..45e8b0362d 100755 --- a/linux-2.4-xen-sparse/mkbuildtree +++ b/linux-2.4-xen-sparse/mkbuildtree @@ -102,9 +102,9 @@ for i in `find . -type l`; do rm -f $i; done relative_lndir ${RS} rm -f mkbuildtree -set ${RS}/../linux-2.6-xen-sparse -[ "$1" == "${RS}/../linux-2.6-xen-sparse" ] && { echo "no Linux 2.6 sparse tree at ${RS}/../linux-2.6-xen-sparse"; exit 1; } -LINUX_26="$1" +LINUX_26=${RS}/../linux-2.6-xen-sparse +[ -d $LINUX_26 ] || { echo "no Linux 2.6 sparse tree at ${RS}/../linux-2.6-xen-sparse"; exit 1; } + # Create links to the shared definitions of the Xen interfaces. rm -rf ${AD}/include/asm-xen/xen-public From 79bcde0dd2c981a322e528d7dceafff5ab84dca9 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Mon, 29 Aug 2005 13:56:53 +0000 Subject: [PATCH 06/11] Allocate a request-id space per vbd in blkfront. This should fix the assertions people have been seeing in domU blkfront where we run out of IDs (because they were being shared by multiple vbds). Signed-off-by: Keir Fraser --- .../drivers/xen/blkfront/blkfront.c | 80 ++++++++----------- .../drivers/xen/blkfront/block.h | 10 +++ 2 files changed, 45 insertions(+), 45 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c index 262b72d34f..cd6c341d14 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c @@ -55,39 +55,32 @@ static unsigned int blkif_state = BLKIF_STATE_DISCONNECTED; -#define BLK_RING_SIZE __RING_SIZE((blkif_sring_t *)0, PAGE_SIZE) - #define MAXIMUM_OUTSTANDING_BLOCK_REQS \ (BLKIF_MAX_SEGMENTS_PER_REQUEST * BLKIF_RING_SIZE) #define GRANTREF_INVALID (1<<15) -static struct blk_shadow { - blkif_request_t req; - unsigned long request; - unsigned long frame[BLKIF_MAX_SEGMENTS_PER_REQUEST]; -} blk_shadow[BLK_RING_SIZE]; -unsigned long blk_shadow_free; - static int recovery = 0; /* Recovery in progress: protected by blkif_io_lock */ static void kick_pending_request_queues(struct blkfront_info *info); static void blkif_completion(struct blk_shadow *s); -static inline int GET_ID_FROM_FREELIST(void) +static inline int GET_ID_FROM_FREELIST( + struct blkfront_info *info) { - unsigned long free = blk_shadow_free; + unsigned long free = info->shadow_free; BUG_ON(free > BLK_RING_SIZE); - blk_shadow_free = blk_shadow[free].req.id; - blk_shadow[free].req.id = 0x0fffffee; /* debug */ + info->shadow_free = info->shadow[free].req.id; + info->shadow[free].req.id = 0x0fffffee; /* debug */ return free; } -static inline void ADD_ID_TO_FREELIST(unsigned long id) +static inline void ADD_ID_TO_FREELIST( + struct blkfront_info *info, unsigned long id) { - blk_shadow[id].req.id = blk_shadow_free; - blk_shadow[id].request = 0; - blk_shadow_free = id; + info->shadow[id].req.id = info->shadow_free; + info->shadow[id].request = 0; + info->shadow_free = id; } static inline void pickle_request(struct blk_shadow *s, blkif_request_t *r) @@ -213,8 +206,8 @@ static int blkif_queue_request(struct request *req) /* Fill out a communications ring structure. */ ring_req = RING_GET_REQUEST(&info->ring, info->ring.req_prod_pvt); - id = GET_ID_FROM_FREELIST(); - blk_shadow[id].request = (unsigned long)req; + id = GET_ID_FROM_FREELIST(info); + info->shadow[id].request = (unsigned long)req; ring_req->id = id; ring_req->operation = rq_data_dir(req) ? @@ -240,7 +233,7 @@ static int blkif_queue_request(struct request *req) buffer_ma >> PAGE_SHIFT, rq_data_dir(req) ); - blk_shadow[id].frame[ring_req->nr_segments] = + info->shadow[id].frame[ring_req->nr_segments] = buffer_ma >> PAGE_SHIFT; ring_req->frame_and_sects[ring_req->nr_segments] = @@ -253,7 +246,7 @@ static int blkif_queue_request(struct request *req) info->ring.req_prod_pvt++; /* Keep a private copy so we can reissue requests when recovering. */ - pickle_request(&blk_shadow[id], ring_req); + pickle_request(&info->shadow[id], ring_req); gnttab_free_grant_references(gref_head); @@ -331,11 +324,11 @@ static irqreturn_t blkif_int(int irq, void *dev_id, struct pt_regs *ptregs) bret = RING_GET_RESPONSE(&info->ring, i); id = bret->id; - req = (struct request *)blk_shadow[id].request; + req = (struct request *)info->shadow[id].request; - blkif_completion(&blk_shadow[id]); + blkif_completion(&info->shadow[id]); - ADD_ID_TO_FREELIST(id); + ADD_ID_TO_FREELIST(info, id); switch (bret->operation) { case BLKIF_OP_READ: @@ -387,16 +380,16 @@ static void blkif_recover(struct blkfront_info *info) int j; /* Stage 1: Make a safe copy of the shadow state. */ - copy = (struct blk_shadow *)kmalloc(sizeof(blk_shadow), GFP_KERNEL); + copy = (struct blk_shadow *)kmalloc(sizeof(info->shadow), GFP_KERNEL); BUG_ON(copy == NULL); - memcpy(copy, blk_shadow, sizeof(blk_shadow)); + memcpy(copy, info->shadow, sizeof(info->shadow)); /* Stage 2: Set up free list. */ - memset(&blk_shadow, 0, sizeof(blk_shadow)); + memset(&info->shadow, 0, sizeof(info->shadow)); for (i = 0; i < BLK_RING_SIZE; i++) - blk_shadow[i].req.id = i+1; - blk_shadow_free = info->ring.req_prod_pvt; - blk_shadow[BLK_RING_SIZE-1].req.id = 0x0fffffff; + info->shadow[i].req.id = i+1; + info->shadow_free = info->ring.req_prod_pvt; + info->shadow[BLK_RING_SIZE-1].req.id = 0x0fffffff; /* Stage 3: Find pending requests and requeue them. */ for (i = 0; i < BLK_RING_SIZE; i++) { @@ -410,8 +403,8 @@ static void blkif_recover(struct blkfront_info *info) unpickle_request(req, ©[i]); /* We get a new request id, and must reset the shadow state. */ - req->id = GET_ID_FROM_FREELIST(); - memcpy(&blk_shadow[req->id], ©[i], sizeof(copy[i])); + req->id = GET_ID_FROM_FREELIST(info); + memcpy(&info->shadow[req->id], ©[i], sizeof(copy[i])); /* Rewrite any grant references invalidated by susp/resume. */ for (j = 0; j < req->nr_segments; j++) { @@ -420,13 +413,13 @@ static void blkif_recover(struct blkfront_info *info) blkif_gref_from_fas( req->frame_and_sects[j]), info->backend_id, - blk_shadow[req->id].frame[j], + info->shadow[req->id].frame[j], rq_data_dir( (struct request *) - blk_shadow[req->id].request)); + info->shadow[req->id].request)); req->frame_and_sects[j] &= ~GRANTREF_INVALID; } - blk_shadow[req->id].req = *req; + info->shadow[req->id].req = *req; info->ring.req_prod_pvt++; } @@ -628,9 +621,8 @@ static int talk_to_backend(struct xenbus_device *dev, static int blkfront_probe(struct xenbus_device *dev, const struct xenbus_device_id *id) { - int err; + int err, vdevice, i; struct blkfront_info *info; - int vdevice; /* FIXME: Use dynamic device id if this is not set. */ err = xenbus_scanf(dev->nodename, "virtual-device", "%i", &vdevice); @@ -652,6 +644,12 @@ static int blkfront_probe(struct xenbus_device *dev, info->mi = NULL; INIT_WORK(&info->work, blkif_restart_queue, (void *)info); + info->shadow_free = 0; + memset(info->shadow, 0, sizeof(info->shadow)); + for (i = 0; i < BLK_RING_SIZE; i++) + info->shadow[i].req.id = i+1; + info->shadow[BLK_RING_SIZE-1].req.id = 0x0fffffff; + /* Front end dir is a number, which is used as the id. */ info->handle = simple_strtoul(strrchr(dev->nodename,'/')+1, NULL, 0); dev->data = info; @@ -752,20 +750,12 @@ static int wait_for_blkif(void) static int __init xlblk_init(void) { - int i; - if ((xen_start_info.flags & SIF_INITDOMAIN) || (xen_start_info.flags & SIF_BLK_BE_DOMAIN) ) return 0; IPRINTK("Initialising virtual block device driver\n"); - blk_shadow_free = 0; - memset(blk_shadow, 0, sizeof(blk_shadow)); - for (i = 0; i < BLK_RING_SIZE; i++) - blk_shadow[i].req.id = i+1; - blk_shadow[BLK_RING_SIZE-1].req.id = 0x0fffffff; - init_blk_xenbus(); wait_for_blkif(); diff --git a/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h b/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h index 4d3cc00773..8a2acd6046 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h @@ -96,6 +96,14 @@ struct xlbd_major_info struct xlbd_type_info *type; }; +struct blk_shadow { + blkif_request_t req; + unsigned long request; + unsigned long frame[BLKIF_MAX_SEGMENTS_PER_REQUEST]; +}; + +#define BLK_RING_SIZE __RING_SIZE((blkif_sring_t *)0, PAGE_SIZE) + /* * We have one of these per vbd, whether ide, scsi or 'other'. They * hang in private_data off the gendisk structure. We may end up @@ -119,6 +127,8 @@ struct blkfront_info request_queue_t *rq; struct work_struct work; struct gnttab_free_callback callback; + struct blk_shadow shadow[BLK_RING_SIZE]; + unsigned long shadow_free; }; extern spinlock_t blkif_io_lock; From 82e2e63c607c0fa29cbf6c117f4905358971e039 Mon Sep 17 00:00:00 2001 From: "cl349@firebug.cl.cam.ac.uk" Date: Mon, 29 Aug 2005 13:58:46 +0000 Subject: [PATCH 07/11] Fix "bogus" check by moving it inside the length check. Signed-off-by: Ryan Harper Signed-off-by: Christian Limpach --- tools/python/xen/xm/main.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/python/xen/xm/main.py b/tools/python/xen/xm/main.py index 5c8e4b01ff..92782d2ae9 100644 --- a/tools/python/xen/xm/main.py +++ b/tools/python/xen/xm/main.py @@ -715,9 +715,9 @@ def main(argv=sys.argv): err("Most commands need root access. Please try again as root") sys.exit(1) except XendError, ex: - if args[0] == "bogus": - args.remove("bogus") if len(args) > 0: + if args[0] == "bogus": + args.remove("bogus") handle_xend_error(argv[1], args[0], ex) else: print "Unexpected error:", sys.exc_info()[0] From 7fa8b30f7d0ba3eaf33abc898f0dd3708fd58be5 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Mon, 29 Aug 2005 14:53:38 +0000 Subject: [PATCH 08/11] Fix page_is_ram() start-of-day checks, and the watch routine inside balloon driver. Signed-off-by: Keir Fraser --- linux-2.6-xen-sparse/arch/xen/i386/mm/init.c | 9 +++++++++ linux-2.6-xen-sparse/arch/xen/x86_64/mm/init.c | 3 --- linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c | 4 ++-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/linux-2.6-xen-sparse/arch/xen/i386/mm/init.c b/linux-2.6-xen-sparse/arch/xen/i386/mm/init.c index 645eaa34d6..ba3c9a6b27 100644 --- a/linux-2.6-xen-sparse/arch/xen/i386/mm/init.c +++ b/linux-2.6-xen-sparse/arch/xen/i386/mm/init.c @@ -219,6 +219,8 @@ static void __init kernel_physical_mapping_init(pgd_t *pgd_base) } } +#ifndef CONFIG_XEN + static inline int page_kills_ppro(unsigned long pagenr) { if (pagenr >= 0x70000 && pagenr <= 0x7003F) @@ -266,6 +268,13 @@ static inline int page_is_ram(unsigned long pagenr) return 0; } +#else /* CONFIG_XEN */ + +#define page_kills_ppro(p) 0 +#define page_is_ram(p) 1 + +#endif + #ifdef CONFIG_HIGHMEM pte_t *kmap_pte; pgprot_t kmap_prot; diff --git a/linux-2.6-xen-sparse/arch/xen/x86_64/mm/init.c b/linux-2.6-xen-sparse/arch/xen/x86_64/mm/init.c index f9f7454036..22ad3dfd7d 100644 --- a/linux-2.6-xen-sparse/arch/xen/x86_64/mm/init.c +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/mm/init.c @@ -767,9 +767,6 @@ void __init clear_kernel_mapping(unsigned long address, unsigned long size) static inline int page_is_ram (unsigned long pagenr) { - if (pagenr < start_pfn || pagenr >= end_pfn) - return 0; - return 1; } diff --git a/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c b/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c index 5498e5a804..dd052e42a0 100644 --- a/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c +++ b/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c @@ -295,10 +295,10 @@ static struct xenbus_watch target_watch = /* React to a change in the target key */ static void watch_target(struct xenbus_watch *watch, const char *node) { - unsigned long new_target; + unsigned long long new_target; int err; - err = xenbus_scanf("memory", "target", "%lu", &new_target); + err = xenbus_scanf("memory", "target", "%llu", &new_target); if (err != 1) { printk(KERN_ERR "Unable to read memory/target\n"); return; From 099d84b15c9cf0147aee0d681e65115d9a54de2c Mon Sep 17 00:00:00 2001 From: "cl349@firebug.cl.cam.ac.uk" Date: Mon, 29 Aug 2005 17:14:08 +0000 Subject: [PATCH 09/11] Only hotplug cpus and save/restore vcpu context on SMP builds. The for_each_cpu_mask macro has a slightly odd behaviour in the non-CONFIG_SMP case, making the code unexpectedly incorrect. Signed-off-by: Christian Limpach --- linux-2.6-xen-sparse/arch/xen/kernel/reboot.c | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c b/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c index bacf20a78c..2018a4ac25 100644 --- a/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c +++ b/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c @@ -65,6 +65,7 @@ static int shutting_down = SHUTDOWN_INVALID; #define cpu_up(x) (-EOPNOTSUPP) #endif +#ifdef CONFIG_SMP static void save_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt) { int r; @@ -119,12 +120,12 @@ static int restore_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt) return 0; } +#endif static int __do_suspend(void *ignore) { int i, j; suspend_record_t *suspend_record; - static vcpu_guest_context_t suspended_cpu_records[NR_CPUS]; /* Hmmm... a cleaner interface to suspend/resume blkdevs would be nice. */ /* XXX SMH: yes it would :-( */ @@ -147,7 +148,11 @@ static int __do_suspend(void *ignore) extern unsigned long max_pfn; extern unsigned int *pfn_to_mfn_frame_list; +#ifdef CONFIG_SMP + static vcpu_guest_context_t suspended_cpu_records[NR_CPUS]; cpumask_t prev_online_cpus, prev_present_cpus; +#endif + int err = 0; BUG_ON(smp_processor_id() != 0); @@ -164,6 +169,8 @@ static int __do_suspend(void *ignore) if ( suspend_record == NULL ) goto out; + preempt_disable(); +#ifdef CONFIG_SMP /* Take all of the other cpus offline. We need to be careful not to get preempted between the final test for num_online_cpus() == 1 and disabling interrupts, since otherwise userspace could @@ -175,7 +182,6 @@ static int __do_suspend(void *ignore) since by the time num_online_cpus() == 1, there aren't any other cpus) */ cpus_clear(prev_online_cpus); - preempt_disable(); while (num_online_cpus() > 1) { preempt_enable(); for_each_online_cpu(i) { @@ -190,6 +196,7 @@ static int __do_suspend(void *ignore) } preempt_disable(); } +#endif suspend_record->nr_pfns = max_pfn; /* final number of pfns */ @@ -197,6 +204,7 @@ static int __do_suspend(void *ignore) preempt_enable(); +#ifdef CONFIG_SMP cpus_clear(prev_present_cpus); for_each_present_cpu(i) { if (i == 0) @@ -204,6 +212,7 @@ static int __do_suspend(void *ignore) save_vcpu_context(i, &suspended_cpu_records[i]); cpu_set(i, prev_present_cpus); } +#endif #ifdef __i386__ mm_pin_all(); @@ -269,12 +278,14 @@ static int __do_suspend(void *ignore) usbif_resume(); - for_each_cpu_mask(i, prev_present_cpus) { +#ifdef CONFIG_SMP + for_each_cpu_mask(i, prev_present_cpus) restore_vcpu_context(i, &suspended_cpu_records[i]); - } +#endif __sti(); +#ifdef CONFIG_SMP out_reenable_cpus: for_each_cpu_mask(i, prev_online_cpus) { j = cpu_up(i); @@ -284,6 +295,7 @@ static int __do_suspend(void *ignore) err = j; } } +#endif out: if ( suspend_record != NULL ) From 1b7bae227d9e2421af2c17a65f750bf118653ca3 Mon Sep 17 00:00:00 2001 From: "cl349@firebug.cl.cam.ac.uk" Date: Mon, 29 Aug 2005 17:15:56 +0000 Subject: [PATCH 10/11] Update suspend/resume functions for xenbus. Signed-off-by: Christian Limpach --- .../drivers/xen/netfront/netfront.c | 29 +++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c index 9ecf176e73..6073c6b265 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c @@ -1272,25 +1272,24 @@ static int netfront_remove(struct xenbus_device *dev) static int netfront_suspend(struct xenbus_device *dev) { - struct net_private *np = dev->data; - /* Avoid having tx/rx stuff happen until we're ready. */ - unbind_evtchn_from_irqhandler(np->evtchn, np->netdev); - return 0; + struct netfront_info *info = dev->data; + + unregister_xenbus_watch(&info->watch); + kfree(info->backend); + info->backend = NULL; + + netif_free(info); + + return 0; } static int netfront_resume(struct xenbus_device *dev) { - struct net_private *np = dev->data; - /* - * Connect regardless of whether IFF_UP flag set. - * Stop bad things from happening until we're back up. - */ - np->backend_state = BEST_DISCONNECTED; - memset(np->tx, 0, PAGE_SIZE); - memset(np->rx, 0, PAGE_SIZE); - - // send_interface_connect(np); - return 0; + struct net_private *np = dev->data; + int err; + + err = talk_to_backend(dev, np); + return err; } static struct xenbus_driver netfront = { From 0d6bfee0941d54c0f6e7d237b17598ba5fc9ca29 Mon Sep 17 00:00:00 2001 From: "cl349@firebug.cl.cam.ac.uk" Date: Mon, 29 Aug 2005 17:40:47 +0000 Subject: [PATCH 11/11] Simplify and fix SMP irq and ipi teardown/setup on suspend/resume. Signed-off-by: Christian Limpach --- .../arch/xen/i386/kernel/process.c | 17 +++-- .../arch/xen/i386/kernel/smpboot.c | 67 ++++++++++++++---- linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c | 68 ------------------- linux-2.6-xen-sparse/arch/xen/kernel/reboot.c | 64 ++--------------- .../arch/xen/x86_64/kernel/smpboot.c | 10 +-- 5 files changed, 75 insertions(+), 151 deletions(-) diff --git a/linux-2.6-xen-sparse/arch/xen/i386/kernel/process.c b/linux-2.6-xen-sparse/arch/xen/i386/kernel/process.c index cb6526d4ac..5c7c6933f0 100644 --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/process.c +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/process.c @@ -135,6 +135,10 @@ static inline void play_dead(void) * low exit latency (ie sit in a loop waiting for * somebody to say that they'd like to reschedule) */ +#ifdef CONFIG_SMP +extern void smp_suspend(void); +extern void smp_resume(void); +#endif void cpu_idle (void) { int cpu = _smp_processor_id(); @@ -149,6 +153,9 @@ void cpu_idle (void) if (cpu_is_offline(cpu)) { local_irq_disable(); +#ifdef CONFIG_SMP + smp_suspend(); +#endif #if defined(CONFIG_XEN) && defined(CONFIG_HOTPLUG_CPU) /* Ack it. From this point on until we get woken up, we're not allowed @@ -159,6 +166,9 @@ void cpu_idle (void) HYPERVISOR_vcpu_down(cpu); #endif play_dead(); +#ifdef CONFIG_SMP + smp_resume(); +#endif local_irq_enable(); } @@ -789,10 +799,3 @@ unsigned long arch_align_stack(unsigned long sp) sp -= get_random_int() % 8192; return sp & ~0xf; } - - -#ifndef CONFIG_X86_SMP -void _restore_vcpu(void) -{ -} -#endif diff --git a/linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c b/linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c index dd5eb7b100..cb28a7008f 100644 --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c @@ -1601,32 +1601,71 @@ extern void local_teardown_timer_irq(void); void smp_suspend(void) { - /* XXX todo: take down time and ipi's on all cpus */ local_teardown_timer_irq(); smp_intr_exit(); } void smp_resume(void) { - /* XXX todo: restore time and ipi's on all cpus */ smp_intr_init(); local_setup_timer_irq(); } -DECLARE_PER_CPU(int, timer_irq); +static atomic_t vcpus_rebooting; -void _restore_vcpu(void) +static void restore_vcpu_ready(void) { - int cpu = smp_processor_id(); - extern atomic_t vcpus_rebooting; - /* We are the first thing the vcpu runs when it comes back, - and we are supposed to restore the IPIs and timer - interrupts etc. When we return, the vcpu's idle loop will - start up again. */ - _bind_virq_to_irq(VIRQ_TIMER, cpu, per_cpu(timer_irq, cpu)); - _bind_virq_to_irq(VIRQ_DEBUG, cpu, per_cpu(ldebug_irq, cpu)); - _bind_ipi_to_irq(RESCHEDULE_VECTOR, cpu, per_cpu(resched_irq, cpu) ); - _bind_ipi_to_irq(CALL_FUNCTION_VECTOR, cpu, per_cpu(callfunc_irq, cpu) ); atomic_dec(&vcpus_rebooting); } + +void save_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt) +{ + int r; + int gdt_pages; + r = HYPERVISOR_vcpu_pickle(vcpu, ctxt); + if (r != 0) + panic("pickling vcpu %d -> %d!\n", vcpu, r); + + /* Translate from machine to physical addresses where necessary, + so that they can be translated to our new machine address space + after resume. libxc is responsible for doing this to vcpu0, + but we do it to the others. */ + gdt_pages = (ctxt->gdt_ents + 511) / 512; + ctxt->ctrlreg[3] = machine_to_phys(ctxt->ctrlreg[3]); + for (r = 0; r < gdt_pages; r++) + ctxt->gdt_frames[r] = mfn_to_pfn(ctxt->gdt_frames[r]); +} + +int restore_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt) +{ + int r; + int gdt_pages = (ctxt->gdt_ents + 511) / 512; + + /* This is kind of a hack, and implicitly relies on the fact that + the vcpu stops in a place where all of the call clobbered + registers are already dead. */ + ctxt->user_regs.esp -= 4; + ((unsigned long *)ctxt->user_regs.esp)[0] = ctxt->user_regs.eip; + ctxt->user_regs.eip = (unsigned long)restore_vcpu_ready; + + /* De-canonicalise. libxc handles this for vcpu 0, but we need + to do it for the other vcpus. */ + ctxt->ctrlreg[3] = phys_to_machine(ctxt->ctrlreg[3]); + for (r = 0; r < gdt_pages; r++) + ctxt->gdt_frames[r] = pfn_to_mfn(ctxt->gdt_frames[r]); + + atomic_set(&vcpus_rebooting, 1); + r = HYPERVISOR_boot_vcpu(vcpu, ctxt); + if (r != 0) { + printk(KERN_EMERG "Failed to reboot vcpu %d (%d)\n", vcpu, r); + return -1; + } + + /* Make sure we wait for the new vcpu to come up before trying to do + anything with it or starting the next one. */ + while (atomic_read(&vcpus_rebooting)) + barrier(); + + return 0; +} diff --git a/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c b/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c index 47fdcc9fdf..dd8131c943 100644 --- a/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c +++ b/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c @@ -245,74 +245,6 @@ void unbind_virq_from_irq(int virq) spin_unlock(&irq_mapping_update_lock); } -/* This is only used when a vcpu from an xm save. The ipi is expected - to have been bound before we suspended, and so all of the xenolinux - state is set up; we only need to restore the Xen side of things. - The irq number has to be the same, but the evtchn number can - change. */ -void _bind_ipi_to_irq(int ipi, int vcpu, int irq) -{ - evtchn_op_t op; - int evtchn; - - spin_lock(&irq_mapping_update_lock); - - op.cmd = EVTCHNOP_bind_ipi; - if ( HYPERVISOR_event_channel_op(&op) != 0 ) - panic("Failed to bind virtual IPI %d on cpu %d\n", ipi, vcpu); - evtchn = op.u.bind_ipi.port; - - printk("<0>IPI %d, old evtchn %d, evtchn %d.\n", - ipi, per_cpu(ipi_to_evtchn, vcpu)[ipi], - evtchn); - - evtchn_to_irq[irq_to_evtchn[irq]] = -1; - irq_to_evtchn[irq] = -1; - - evtchn_to_irq[evtchn] = irq; - irq_to_evtchn[irq] = evtchn; - - printk("<0>evtchn_to_irq[%d] = %d.\n", evtchn, - evtchn_to_irq[evtchn]); - per_cpu(ipi_to_evtchn, vcpu)[ipi] = evtchn; - - bind_evtchn_to_cpu(evtchn, vcpu); - - spin_unlock(&irq_mapping_update_lock); - - clear_bit(evtchn, (unsigned long *)HYPERVISOR_shared_info->evtchn_mask); - clear_bit(evtchn, (unsigned long *)HYPERVISOR_shared_info->evtchn_pending); -} - -void _bind_virq_to_irq(int virq, int cpu, int irq) -{ - evtchn_op_t op; - int evtchn; - - spin_lock(&irq_mapping_update_lock); - - op.cmd = EVTCHNOP_bind_virq; - op.u.bind_virq.virq = virq; - if ( HYPERVISOR_event_channel_op(&op) != 0 ) - panic("Failed to bind virtual IRQ %d\n", virq); - evtchn = op.u.bind_virq.port; - - evtchn_to_irq[irq_to_evtchn[irq]] = -1; - irq_to_evtchn[irq] = -1; - - evtchn_to_irq[evtchn] = irq; - irq_to_evtchn[irq] = evtchn; - - per_cpu(virq_to_irq, cpu)[virq] = irq; - - bind_evtchn_to_cpu(evtchn, cpu); - - spin_unlock(&irq_mapping_update_lock); - - clear_bit(evtchn, (unsigned long *)HYPERVISOR_shared_info->evtchn_mask); - clear_bit(evtchn, (unsigned long *)HYPERVISOR_shared_info->evtchn_pending); -} - int bind_ipi_to_irq(int ipi) { evtchn_op_t op; diff --git a/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c b/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c index 2018a4ac25..9085609dc0 100644 --- a/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c +++ b/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c @@ -66,60 +66,6 @@ static int shutting_down = SHUTDOWN_INVALID; #endif #ifdef CONFIG_SMP -static void save_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt) -{ - int r; - int gdt_pages; - r = HYPERVISOR_vcpu_pickle(vcpu, ctxt); - if (r != 0) - panic("pickling vcpu %d -> %d!\n", vcpu, r); - - /* Translate from machine to physical addresses where necessary, - so that they can be translated to our new machine address space - after resume. libxc is responsible for doing this to vcpu0, - but we do it to the others. */ - gdt_pages = (ctxt->gdt_ents + 511) / 512; - ctxt->ctrlreg[3] = machine_to_phys(ctxt->ctrlreg[3]); - for (r = 0; r < gdt_pages; r++) - ctxt->gdt_frames[r] = mfn_to_pfn(ctxt->gdt_frames[r]); -} - -void _restore_vcpu(int cpu); - -atomic_t vcpus_rebooting; - -static int restore_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt) -{ - int r; - int gdt_pages = (ctxt->gdt_ents + 511) / 512; - - /* This is kind of a hack, and implicitly relies on the fact that - the vcpu stops in a place where all of the call clobbered - registers are already dead. */ - ctxt->user_regs.esp -= 4; - ((unsigned long *)ctxt->user_regs.esp)[0] = ctxt->user_regs.eip; - ctxt->user_regs.eip = (unsigned long)_restore_vcpu; - - /* De-canonicalise. libxc handles this for vcpu 0, but we need - to do it for the other vcpus. */ - ctxt->ctrlreg[3] = phys_to_machine(ctxt->ctrlreg[3]); - for (r = 0; r < gdt_pages; r++) - ctxt->gdt_frames[r] = pfn_to_mfn(ctxt->gdt_frames[r]); - - atomic_set(&vcpus_rebooting, 1); - r = HYPERVISOR_boot_vcpu(vcpu, ctxt); - if (r != 0) { - printk(KERN_EMERG "Failed to reboot vcpu %d (%d)\n", vcpu, r); - return -1; - } - - /* Make sure we wait for the new vcpu to come up before trying to do - anything with it or starting the next one. */ - while (atomic_read(&vcpus_rebooting)) - barrier(); - - return 0; -} #endif static int __do_suspend(void *ignore) @@ -139,18 +85,20 @@ static int __do_suspend(void *ignore) extern int gnttab_suspend(void); extern int gnttab_resume(void); -#ifdef CONFIG_SMP - extern void smp_suspend(void); - extern void smp_resume(void); -#endif extern void time_suspend(void); extern void time_resume(void); extern unsigned long max_pfn; extern unsigned int *pfn_to_mfn_frame_list; #ifdef CONFIG_SMP + extern void smp_suspend(void); + extern void smp_resume(void); + static vcpu_guest_context_t suspended_cpu_records[NR_CPUS]; cpumask_t prev_online_cpus, prev_present_cpus; + + void save_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt); + int restore_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt); #endif int err = 0; diff --git a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/smpboot.c b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/smpboot.c index 035a358efa..fde9e7fe4a 100644 --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/smpboot.c +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/smpboot.c @@ -1277,21 +1277,23 @@ extern void local_teardown_timer_irq(void); void smp_suspend(void) { - /* XXX todo: take down time and ipi's on all cpus */ local_teardown_timer_irq(); smp_intr_exit(); } void smp_resume(void) { - /* XXX todo: restore time and ipi's on all cpus */ smp_intr_init(); local_setup_timer_irq(); } -void _restore_vcpu(void) +void save_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt) { - /* XXX need to write this */ +} + +int restore_vcpu_context(int vcpu, vcpu_guest_context_t *ctxt) +{ + return 0; } #endif