From b64ef24e2f1684085b9f12aef1dc5fbd5bea5c3f Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Wed, 7 Feb 2007 16:08:47 +0000 Subject: [PATCH 01/19] hvm: Add PCI subsystem ID to emulated devices. This patch adds the PCI Subsystem ID 5853:0001 to the virtual devices emulated by qemu (ide, nic, vga). Signed-off-by: Gerd Hoffmann --- tools/ioemu/hw/cirrus_vga.c | 4 ++++ tools/ioemu/hw/ide.c | 4 ++++ tools/ioemu/hw/rtl8139.c | 6 ++++-- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/tools/ioemu/hw/cirrus_vga.c b/tools/ioemu/hw/cirrus_vga.c index 3c316d6dc9..292673ae6a 100644 --- a/tools/ioemu/hw/cirrus_vga.c +++ b/tools/ioemu/hw/cirrus_vga.c @@ -3339,6 +3339,10 @@ void pci_cirrus_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base, pci_conf[0x0a] = PCI_CLASS_SUB_VGA; pci_conf[0x0b] = PCI_CLASS_BASE_DISPLAY; pci_conf[0x0e] = PCI_CLASS_HEADERTYPE_00h; + pci_conf[0x2c] = 0x53; /* subsystem vendor: XenSource */ + pci_conf[0x2d] = 0x58; + pci_conf[0x2e] = 0x01; /* subsystem device */ + pci_conf[0x2f] = 0x00; /* setup VGA */ s = &d->cirrus_vga; diff --git a/tools/ioemu/hw/ide.c b/tools/ioemu/hw/ide.c index ef203a2f8a..3bf2c7d594 100644 --- a/tools/ioemu/hw/ide.c +++ b/tools/ioemu/hw/ide.c @@ -2502,6 +2502,10 @@ void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn) pci_conf[0x0a] = 0x01; // class_sub = PCI_IDE pci_conf[0x0b] = 0x01; // class_base = PCI_mass_storage pci_conf[0x0e] = 0x00; // header_type + pci_conf[0x2c] = 0x53; /* subsystem vendor: XenSource */ + pci_conf[0x2d] = 0x58; + pci_conf[0x2e] = 0x01; /* subsystem device */ + pci_conf[0x2f] = 0x00; pci_register_io_region((PCIDevice *)d, 4, 0x10, PCI_ADDRESS_SPACE_IO, bmdma_map); diff --git a/tools/ioemu/hw/rtl8139.c b/tools/ioemu/hw/rtl8139.c index 77e3c6d9fb..e4ba40dfe3 100644 --- a/tools/ioemu/hw/rtl8139.c +++ b/tools/ioemu/hw/rtl8139.c @@ -3423,8 +3423,10 @@ void pci_rtl8139_init(PCIBus *bus, NICInfo *nd) pci_conf[0x0e] = 0x00; /* header_type */ pci_conf[0x3d] = 1; /* interrupt pin 0 */ pci_conf[0x34] = 0xdc; - pci_conf[0x2c] = pci_conf[0x00]; // same as Vendor ID - pci_conf[0x2d] = pci_conf[0x01]; + pci_conf[0x2c] = 0x53; /* subsystem vendor: XenSource */ + pci_conf[0x2d] = 0x58; + pci_conf[0x2e] = 0x01; /* subsystem device */ + pci_conf[0x2f] = 0x00; s = &d->rtl8139; From 6b91de464c93f0c24e72de22d81a8192a39920e4 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Wed, 7 Feb 2007 16:12:40 +0000 Subject: [PATCH 02/19] pvfb: Split mouse and keyboard into separate devices. This patch creates two separate input devices for keyboard and mouse events. The reason for this is to separate them in the linux input layer and allow them being routed different ways. Use case: Configure the X-Server like this to get the mouse events directly from the linux input layer, which has the major advantage that absolute coordinates work correctly: Section "InputDevice" Driver "evdev" Identifier "Mouse" Option "Device" "/dev/input/event" EndSection This makes the keyboard stop working though in case mouse and keyboard events are coming through the same input device, at least with older Xorg (6.9) versions. Signed-off-by: Gerd Hoffmann Assign fake pci product identifiers down from 0xffff. This may help clarify that the devices are not actually PCI. Also it reduces probability of accidental conflict if further real PCI assignments occur in future (0x0002, 0x0003, ... would be obvious next identifiers to allocate). Signed-off-by: Keir Fraser --- .../drivers/xen/fbfront/xenkbd.c | 97 +++++++++++++------ 1 file changed, 67 insertions(+), 30 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/fbfront/xenkbd.c b/linux-2.6-xen-sparse/drivers/xen/fbfront/xenkbd.c index e4debd83d3..a34beafcda 100644 --- a/linux-2.6-xen-sparse/drivers/xen/fbfront/xenkbd.c +++ b/linux-2.6-xen-sparse/drivers/xen/fbfront/xenkbd.c @@ -29,10 +29,12 @@ struct xenkbd_info { - struct input_dev *dev; + struct input_dev *kbd; + struct input_dev *ptr; struct xenkbd_page *page; int irq; struct xenbus_device *xbdev; + char phys[32]; }; static int xenkbd_remove(struct xenbus_device *); @@ -56,23 +58,36 @@ static irqreturn_t input_handler(int rq, void *dev_id, struct pt_regs *regs) rmb(); /* ensure we see ring contents up to prod */ for (cons = page->in_cons; cons != prod; cons++) { union xenkbd_in_event *event; + struct input_dev *dev; event = &XENKBD_IN_RING_REF(page, cons); + dev = info->ptr; switch (event->type) { case XENKBD_TYPE_MOTION: - input_report_rel(info->dev, REL_X, event->motion.rel_x); - input_report_rel(info->dev, REL_Y, event->motion.rel_y); + input_report_rel(dev, REL_X, event->motion.rel_x); + input_report_rel(dev, REL_Y, event->motion.rel_y); break; case XENKBD_TYPE_KEY: - input_report_key(info->dev, event->key.keycode, event->key.pressed); + dev = NULL; + if (test_bit(event->key.keycode, info->kbd->keybit)) + dev = info->kbd; + if (test_bit(event->key.keycode, info->ptr->keybit)) + dev = info->ptr; + if (dev) + input_report_key(dev, event->key.keycode, + event->key.pressed); + else + printk("xenkbd: unhandled keycode 0x%x\n", + event->key.keycode); break; case XENKBD_TYPE_POS: - input_report_abs(info->dev, ABS_X, event->pos.abs_x); - input_report_abs(info->dev, ABS_Y, event->pos.abs_y); + input_report_abs(dev, ABS_X, event->pos.abs_x); + input_report_abs(dev, ABS_Y, event->pos.abs_y); break; } + if (dev) + input_sync(dev); } - input_sync(info->dev); mb(); /* ensure we got ring contents */ page->in_cons = cons; notify_remote_via_irq(info->irq); @@ -85,7 +100,7 @@ int __devinit xenkbd_probe(struct xenbus_device *dev, { int ret, i; struct xenkbd_info *info; - struct input_dev *input_dev; + struct input_dev *kbd, *ptr; info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) { @@ -94,6 +109,7 @@ int __devinit xenkbd_probe(struct xenbus_device *dev, } dev->dev.driver_data = info; info->xbdev = dev; + snprintf(info->phys, sizeof(info->phys), "xenbus/%s", dev->nodename); info->page = (void *)__get_free_page(GFP_KERNEL); if (!info->page) @@ -101,32 +117,52 @@ int __devinit xenkbd_probe(struct xenbus_device *dev, info->page->in_cons = info->page->in_prod = 0; info->page->out_cons = info->page->out_prod = 0; - input_dev = input_allocate_device(); - if (!input_dev) + /* keyboard */ + kbd = input_allocate_device(); + if (!kbd) goto error_nomem; + kbd->name = "Xen Virtual Keyboard"; + kbd->phys = info->phys; + kbd->id.bustype = BUS_PCI; + kbd->id.vendor = 0x5853; + kbd->id.product = 0xffff; + kbd->evbit[0] = BIT(EV_KEY); + for (i = KEY_ESC; i < KEY_UNKNOWN; i++) + set_bit(i, kbd->keybit); + for (i = KEY_OK; i < KEY_MAX; i++) + set_bit(i, kbd->keybit); - input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_ABS); - input_dev->keybit[LONG(BTN_MOUSE)] - = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT); - /* TODO additional buttons */ - input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y); - - /* FIXME not sure this is quite right */ - for (i = 0; i < 256; i++) - set_bit(i, input_dev->keybit); - - input_dev->name = "Xen Virtual Keyboard/Mouse"; - - input_set_abs_params(input_dev, ABS_X, 0, XENFB_WIDTH, 0, 0); - input_set_abs_params(input_dev, ABS_Y, 0, XENFB_HEIGHT, 0, 0); - - ret = input_register_device(input_dev); + ret = input_register_device(kbd); if (ret) { - input_free_device(input_dev); - xenbus_dev_fatal(dev, ret, "input_register_device"); + input_free_device(kbd); + xenbus_dev_fatal(dev, ret, "input_register_device(kbd)"); goto error; } - info->dev = input_dev; + info->kbd = kbd; + + /* pointing device */ + ptr = input_allocate_device(); + if (!ptr) + goto error_nomem; + ptr->name = "Xen Virtual Pointer"; + ptr->phys = info->phys; + ptr->id.bustype = BUS_PCI; + ptr->id.vendor = 0x5853; + ptr->id.product = 0xfffe; + ptr->evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_ABS); + for (i = BTN_LEFT; i <= BTN_TASK; i++) + set_bit(i, ptr->keybit); + ptr->relbit[0] = BIT(REL_X) | BIT(REL_Y); + input_set_abs_params(ptr, ABS_X, 0, XENFB_WIDTH, 0, 0); + input_set_abs_params(ptr, ABS_Y, 0, XENFB_HEIGHT, 0, 0); + + ret = input_register_device(ptr); + if (ret) { + input_free_device(ptr); + xenbus_dev_fatal(dev, ret, "input_register_device(ptr)"); + goto error; + } + info->ptr = ptr; ret = xenkbd_connect_backend(dev, info); if (ret < 0) @@ -155,7 +191,8 @@ static int xenkbd_remove(struct xenbus_device *dev) struct xenkbd_info *info = dev->dev.driver_data; xenkbd_disconnect_backend(info); - input_unregister_device(info->dev); + input_unregister_device(info->kbd); + input_unregister_device(info->ptr); free_page((unsigned long)info->page); kfree(info); return 0; From e7f13aefbd2e782f83d47a62bf1cf549b51ec933 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Wed, 7 Feb 2007 16:20:28 +0000 Subject: [PATCH 03/19] Dom0 VNC server should not drop any of teh 8 supported mouse button event types. Signed-off-by: Daniel P. Berrange --- tools/xenfb/vncfb.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tools/xenfb/vncfb.c b/tools/xenfb/vncfb.c index c2a7e5d02d..1ae06809fc 100644 --- a/tools/xenfb/vncfb.c +++ b/tools/xenfb/vncfb.c @@ -57,7 +57,8 @@ unsigned char keycode_table[512]; static void *kbd_layout; static int btnmap[] = { - BTN_LEFT, BTN_MIDDLE, BTN_RIGHT, BTN_FORWARD, BTN_BACK + BTN_LEFT, BTN_MIDDLE, BTN_RIGHT, BTN_SIDE, + BTN_EXTRA, BTN_FORWARD, BTN_BACK, BTN_TASK }; static void on_kbd_event(rfbBool down, rfbKeySym keycode, rfbClientPtr cl) @@ -73,11 +74,12 @@ static void on_kbd_event(rfbBool down, rfbKeySym keycode, rfbClientPtr cl) */ rfbScreenInfoPtr server = cl->screen; struct xenfb *xenfb = server->screenData; + int scancode; - if( keycode >= 'A' && keycode <= 'Z' ) + if (keycode >= 'A' && keycode <= 'Z') keycode += 'a' - 'A'; - int scancode = keycode_table[keysym2scancode(kbd_layout, keycode)]; + scancode = keycode_table[keysym2scancode(kbd_layout, keycode)]; if (scancode == 0) return; if (xenfb_send_key(xenfb, down, scancode) < 0) From a8d52901714bbef1f07df0cca60b43ad61405a07 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Wed, 7 Feb 2007 16:22:55 +0000 Subject: [PATCH 04/19] Improve hotplug script error reporting via xenstore. Use this to detect and report up-front in vif-bridge script whether the bridge device exists or not. Signed-off-by: Daniel P. Berrange --- tools/examples/vif-bridge | 7 ++++ tools/examples/xen-hotplug-common.sh | 5 ++- tools/python/xen/xend/server/DevController.py | 37 ++++++++++--------- 3 files changed, 29 insertions(+), 20 deletions(-) diff --git a/tools/examples/vif-bridge b/tools/examples/vif-bridge index 0935ad2fae..6bee562c4b 100755 --- a/tools/examples/vif-bridge +++ b/tools/examples/vif-bridge @@ -46,6 +46,13 @@ then fi fi +RET=0 +ip link show $bridge 1>/dev/null 2>&1 || RET=1 +if [ "$RET" -eq 1 ] +then + fatal "Could not find bridge device $bridge" +fi + case "$command" in online) setup_bridge_port "$vif" diff --git a/tools/examples/xen-hotplug-common.sh b/tools/examples/xen-hotplug-common.sh index c825dae593..980a62704e 100644 --- a/tools/examples/xen-hotplug-common.sh +++ b/tools/examples/xen-hotplug-common.sh @@ -28,14 +28,15 @@ export LANG="POSIX" unset $(set | grep ^LC_ | cut -d= -f1) fatal() { - xenstore_write "$XENBUS_PATH"/hotplug-status error + xenstore_write "$XENBUS_PATH/hotplug-error" "$*" \ + "$XENBUS_PATH/hotplug-status" error log err "$@" exit 1 } success() { # Tell DevController that backend is "connected" - xenstore_write "$XENBUS_PATH"/hotplug-status connected + xenstore_write "$XENBUS_PATH/hotplug-status" connected } do_or_die() { diff --git a/tools/python/xen/xend/server/DevController.py b/tools/python/xen/xend/server/DevController.py index 8256d2265f..47f03e1994 100644 --- a/tools/python/xen/xend/server/DevController.py +++ b/tools/python/xen/xend/server/DevController.py @@ -153,9 +153,9 @@ class DevController: log.debug("Waiting for %s.", devid) if not self.hotplug: - return - - status = self.waitForBackend(devid) + return + + (status, err) = self.waitForBackend(devid) if status == Timeout: self.destroyDevice(devid, False) @@ -165,25 +165,22 @@ class DevController: elif status == Error: self.destroyDevice(devid, False) - raise VmError("Device %s (%s) could not be connected. " - "Backend device not found." % - (devid, self.deviceClass)) - + if err is None: + raise VmError("Device %s (%s) could not be connected. " + "Backend device not found." % + (devid, self.deviceClass)) + else: + raise VmError("Device %s (%s) could not be connected. " + "%s" % (devid, self.deviceClass, err)) elif status == Missing: # Don't try to destroy the device; it's already gone away. raise VmError("Device %s (%s) could not be connected. " "Device not found." % (devid, self.deviceClass)) elif status == Busy: - err = None - frontpath = self.frontendPath(devid) - backpath = xstransact.Read(frontpath, "backend") - if backpath: - err = xstransact.Read(backpath, HOTPLUG_ERROR_NODE) - if not err: - err = "Busy." - self.destroyDevice(devid, False) + if err is None: + err = "Busy." raise VmError("Device %s (%s) could not be connected.\n%s" % (devid, self.deviceClass, err)) @@ -478,17 +475,21 @@ class DevController: frontpath = self.frontendPath(devid) backpath = xstransact.Read(frontpath, "backend") + if backpath: statusPath = backpath + '/' + HOTPLUG_STATUS_NODE ev = Event() result = { 'status': Timeout } - + xswatch(statusPath, hotplugStatusCallback, ev, result) ev.wait(DEVICE_CREATE_TIMEOUT) - return result['status'] + + err = xstransact.Read(backpath, HOTPLUG_ERROR_NODE) + + return (result['status'], err) else: - return Missing + return (Missing, None) def backendPath(self, backdom, devid): From 431be892ae4676cc17d7b0888567ba24b45b4149 Mon Sep 17 00:00:00 2001 From: Tim Deegan Date: Wed, 7 Feb 2007 17:29:21 +0000 Subject: [PATCH 05/19] [XEND] Open save/restore files with O_LARGEFILE if possible Signed-off-by: Tim Deegan --- tools/python/xen/xend/XendDomain.py | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/tools/python/xen/xend/XendDomain.py b/tools/python/xen/xend/XendDomain.py index 303a615ad8..0c8cddde48 100644 --- a/tools/python/xen/xend/XendDomain.py +++ b/tools/python/xen/xend/XendDomain.py @@ -800,7 +800,10 @@ class XendDomain: "support.") path = self._managed_check_point_path(dom_uuid) - fd = os.open(path, os.O_WRONLY | os.O_CREAT | os.O_TRUNC) + oflags = os.O_WRONLY | os.O_CREAT | os.O_TRUNC + if hasattr(os, "O_LARGEFILE"): + oflags |= os.O_LARGEFILE + fd = os.open(path, oflags) try: # For now we don't support 'live checkpoint' XendCheckpoint.save(fd, dominfo, False, False, path) @@ -840,8 +843,11 @@ class XendDomain: # Restore that replaces the existing XendDomainInfo try: log.debug('Current DomainInfo state: %d' % dominfo.state) + oflags = os.O_RDONLY + if hasattr(os, "O_LARGEFILE"): + oflags |= os.O_LARGEFILE XendCheckpoint.restore(self, - os.open(chkpath, os.O_RDONLY), + os.open(chkpath, oflags), dominfo, paused = start_paused) os.unlink(chkpath) @@ -1009,7 +1015,10 @@ class XendDomain: @raise XendError: Failure to restore domain """ try: - fd = os.open(src, os.O_RDONLY) + oflags = os.O_RDONLY + if hasattr(os, "O_LARGEFILE"): + oflags |= os.O_LARGEFILE + fd = os.open(src, oflags) try: return self.domain_restore_fd(fd, paused=paused) finally: @@ -1193,7 +1202,10 @@ class XendDomain: if dominfo.getDomid() == DOM0_ID: raise XendError("Cannot save privileged domain %i" % domid) - fd = os.open(dst, os.O_WRONLY | os.O_CREAT | os.O_TRUNC) + oflags = os.O_WRONLY | os.O_CREAT | os.O_TRUNC + if hasattr(os, "O_LARGEFILE"): + oflags |= os.O_LARGEFILE + fd = os.open(dst, oflags) try: # For now we don't support 'live checkpoint' XendCheckpoint.save(fd, dominfo, False, False, dst) From 2b30444fe2a045eeaa1e6d7e656ad34989350ebc Mon Sep 17 00:00:00 2001 From: Tim Deegan Date: Wed, 7 Feb 2007 17:29:52 +0000 Subject: [PATCH 06/19] [HVM] Save/restore: don't try to save the MMIO memory-hole at 4GB. Also remove two integer arrays that were set to a[i] == i. Signed-off-by: Tim Deegan --- tools/libxc/xc_hvm_save.c | 70 +++++++++++++++------------------------ 1 file changed, 27 insertions(+), 43 deletions(-) diff --git a/tools/libxc/xc_hvm_save.c b/tools/libxc/xc_hvm_save.c index e6f5ee1dde..fdd2799743 100644 --- a/tools/libxc/xc_hvm_save.c +++ b/tools/libxc/xc_hvm_save.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "xc_private.h" #include "xg_private.h" @@ -275,9 +276,8 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, /* A copy of the CPU context of the guest. */ vcpu_guest_context_t ctxt; - /* A table containg the type of each PFN (/not/ MFN!). */ - unsigned long *pfn_type = NULL; - unsigned long *pfn_batch = NULL; + /* A table containg the PFNs (/not/ MFN!) to map. */ + xen_pfn_t *pfn_batch = NULL; /* A copy of hvm domain context buffer*/ uint32_t hvm_buf_size; @@ -290,7 +290,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, unsigned char *region_base = NULL; uint32_t nr_pfns, rec_size, nr_vcpus; - unsigned long *page_array = NULL; /* power of 2 order of max_pfn */ int order_nr; @@ -361,18 +360,12 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, goto out; } - max_pfn = live_shinfo->arch.max_pfn; - DPRINTF("saved hvm domain info:max_memkb=0x%lx, max_mfn=0x%lx, nr_pages=0x%lx\n", info.max_memkb, max_mfn, info.nr_pages); - /* nr_pfns: total pages excluding vga acc mem - * max_pfn: nr_pfns + 0x20 vga hole(0xa0~0xc0) - * getdomaininfo.tot_pages: all the allocated pages for this domain - */ if (live) { ERROR("hvm domain doesn't support live migration now.\n"); goto out; - + if (xc_shadow_control(xc_handle, dom, XEN_DOMCTL_SHADOW_OP_ENABLE_LOGDIRTY, NULL, 0, NULL, 0, NULL) < 0) { @@ -381,6 +374,7 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, } /* excludes vga acc mem */ + /* XXX will need to check whether acceleration is enabled here! */ nr_pfns = info.nr_pages - 0x800; last_iter = 0; @@ -396,8 +390,8 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, ERROR("HVM Domain appears not to have suspended"); goto out; } - nr_pfns = info.nr_pages; - DPRINTF("after suspend hvm domain nr_pages=0x%x.\n", nr_pfns); + + nr_pfns = info.nr_pages; } DPRINTF("after 1st handle hvm domain nr_pfns=0x%x, nr_pages=0x%lx, max_memkb=0x%lx, live=%d.\n", @@ -406,10 +400,15 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, info.max_memkb, live); - nr_pfns = info.nr_pages; - - /*XXX: caculate the VGA hole*/ - max_pfn = nr_pfns + 0x20; + /* Calculate the highest PFN of "normal" memory: + * HVM memory is sequential except for the VGA and MMIO holes, and + * we have nr_pfns of it (which now excludes the cirrus video RAM) */ + max_pfn = nr_pfns; + /* Skip the VGA hole from 0xa0000 to 0xc0000 */ + max_pfn += 0x20; + /* Skip the MMIO hole: 256MB just below 4GB */ + if ( max_pfn >= (HVM_BELOW_4G_MMIO_START >> PAGE_SHIFT) ) + max_pfn += (HVM_BELOW_4G_MMIO_LENGTH >> PAGE_SHIFT); skip_this_iter = 0;/*XXX*/ /* pretend we sent all the pages last iteration */ @@ -424,7 +423,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, to_send = malloc(BITMAP_SIZE); to_skip = malloc(BITMAP_SIZE); - page_array = (unsigned long *) malloc( sizeof(unsigned long) * max_pfn); hvm_buf_size = xc_domain_hvm_getcontext(xc_handle, dom, 0, 0); if ( hvm_buf_size == -1 ) @@ -434,7 +432,7 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, } hvm_buf = malloc(hvm_buf_size); - if (!to_send ||!to_skip ||!page_array ||!hvm_buf) { + if (!to_send ||!to_skip ||!hvm_buf) { ERROR("Couldn't allocate memory"); goto out; } @@ -454,26 +452,16 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, analysis_phase(xc_handle, dom, max_pfn, to_skip, 0); - /* get all the HVM domain pfns */ - for ( i = 0; i < max_pfn; i++) - page_array[i] = i; - /* We want zeroed memory so use calloc rather than malloc. */ - pfn_type = calloc(MAX_BATCH_SIZE, sizeof(*pfn_type)); pfn_batch = calloc(MAX_BATCH_SIZE, sizeof(*pfn_batch)); - if ((pfn_type == NULL) || (pfn_batch == NULL)) { - ERROR("failed to alloc memory for pfn_type and/or pfn_batch arrays"); + if (pfn_batch == NULL) { + ERROR("failed to alloc memory for pfn_batch array"); errno = ENOMEM; goto out; } - if (lock_pages(pfn_type, MAX_BATCH_SIZE * sizeof(*pfn_type))) { - ERROR("Unable to lock"); - goto out; - } - /* Start writing out the saved-domain record. */ if (!write_exact(io_fd, &max_pfn, sizeof(unsigned long))) { ERROR("write: max_pfn"); @@ -511,16 +499,15 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, } - /* load pfn_type[] with the mfn of all the pages we're doing in + /* load pfn_batch[] with the mfn of all the pages we're doing in this batch. */ for (batch = 0; batch < MAX_BATCH_SIZE && N < max_pfn ; N++) { int n = permute(N, max_pfn, order_nr); if (debug) { - DPRINTF("%d pfn= %08lx mfn= %08lx %d \n", - iter, (unsigned long)n, page_array[n], - test_bit(n, to_send)); + DPRINTF("%d pfn= %08lx %d \n", + iter, (unsigned long)n, test_bit(n, to_send)); } if (!last_iter && test_bit(n, to_send)&& test_bit(n, to_skip)) @@ -530,10 +517,12 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, (test_bit(n, to_send) && last_iter))) continue; - if (n >= 0xa0 && n < 0xc0) { -/* DPRINTF("get a vga hole pfn= %x.\n", n);*/ + /* Skip PFNs that aren't really there */ + if ((n >= 0xa0 && n < 0xc0) /* VGA hole */ + || (n >= (HVM_BELOW_4G_MMIO_START >> PAGE_SHIFT) + && n < (1ULL << 32) >> PAGE_SHIFT)) /* 4G MMIO hole */ continue; - } + /* ** we get here if: ** 1. page is marked to_send & hasn't already been re-dirtied @@ -541,7 +530,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, */ pfn_batch[batch] = n; - pfn_type[batch] = page_array[n]; batch++; } @@ -573,7 +561,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, goto out; } - sent_this_iter += batch; munmap(region_base, batch*PAGE_SIZE); @@ -723,9 +710,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, } free(hvm_buf); - free(page_array); - - free(pfn_type); free(pfn_batch); free(to_send); free(to_skip); From 51efffe71249ca3250c3c4be0192525c41a7dc81 Mon Sep 17 00:00:00 2001 From: "wim@xen-wim.site" Date: Wed, 7 Feb 2007 16:53:01 -0800 Subject: [PATCH 07/19] [blktap] Allow HVM booting from blktap device(s) Signed-off-by: wim colgate --- tools/ioemu/xenstore.c | 60 +++++++++++++++++- tools/python/xen/xend/XendConfig.py | 41 ++++++++++++ tools/python/xen/xend/XendDomainInfo.py | 56 ++++++++++++++++- .../xen/xend/server/BlktapController.py | 62 +++++++++++++++++++ tools/python/xen/xend/server/DevController.py | 13 ++++ 5 files changed, 230 insertions(+), 2 deletions(-) diff --git a/tools/ioemu/xenstore.c b/tools/ioemu/xenstore.c index 21a8ed08b7..6b1036bcbf 100644 --- a/tools/ioemu/xenstore.c +++ b/tools/ioemu/xenstore.c @@ -10,6 +10,7 @@ #include "vl.h" #include "block_int.h" +#include static struct xs_handle *xsh = NULL; static char *hd_filename[MAX_DISKS]; @@ -52,11 +53,40 @@ void xenstore_check_new_media_present(int timeout) qemu_mod_timer(insert_timer, qemu_get_clock(rt_clock) + timeout); } +static int waitForDevice(char *path, char *field, char *desired) +{ + char *buf = NULL, *stat = NULL; + unsigned int len; + int val = 1; + + /* loop until we find a value in xenstore, return + * if it was what we wanted, or not + */ + while (1) { + if (pasprintf(&buf, "%s/%s", path, field) == -1) + goto done; + free(stat); + stat = xs_read(xsh, XBT_NULL, buf, &len); + if (stat == NULL) { + usleep(100000); /* 1/10th second, no path found */ + } else { + val = strcmp(stat, desired); + goto done; + } + } + +done: + free(stat); + free(buf); + return val; +} + void xenstore_parse_domain_config(int domid) { char **e = NULL; char *buf = NULL, *path; - char *bpath = NULL, *dev = NULL, *params = NULL, *type = NULL; + char *fpath = NULL, *bpath = NULL, + *dev = NULL, *params = NULL, *type = NULL; int i; unsigned int len, num, hd_index; @@ -120,7 +150,35 @@ void xenstore_parse_domain_config(int domid) hd_filename[hd_index] = params; /* strdup() */ params = NULL; /* don't free params on re-use */ } + /* + * check if device has a phantom vbd; the phantom is hooked + * to the frontend device (for ease of cleanup), so lookup + * the frontend device, and see if there is a phantom_vbd + * if there is, we will use resolution as the filename + */ + if (pasprintf(&buf, "%s/device/vbd/%s/phantom_vbd", path, e[i]) == -1) + continue; + free(fpath); + fpath = xs_read(xsh, XBT_NULL, buf, &len); + if (fpath != NULL) { + + if (waitForDevice(fpath, "hotplug-status", "connected")) { + continue; + } + + if (pasprintf(&buf, "%s/dev", fpath) == -1) + continue; + params = xs_read(xsh, XBT_NULL, buf , &len); + if (params != NULL) { + free(hd_filename[hd_index]); + hd_filename[hd_index] = params; + params = NULL; /* don't free params on re-use */ + } + } bs_table[hd_index] = bdrv_new(dev); + /* re-establish buf */ + if (pasprintf(&buf, "%s/params", bpath) == -1) + continue; /* check if it is a cdrom */ if (type && !strcmp(type, "cdrom")) { bdrv_set_type_hint(bs_table[hd_index], BDRV_TYPE_CDROM); diff --git a/tools/python/xen/xend/XendConfig.py b/tools/python/xen/xend/XendConfig.py index 223a90cf6e..fa19165e77 100644 --- a/tools/python/xen/xend/XendConfig.py +++ b/tools/python/xen/xend/XendConfig.py @@ -1148,6 +1148,47 @@ class XendConfig(dict): # no valid device to add return '' + def phantom_device_add(self, dev_type, cfg_xenapi = None, + target = None): + """Add a phantom tap device configuration in XenAPI struct format. + """ + + if target == None: + target = self + + if dev_type not in XendDevices.valid_devices() and \ + dev_type not in XendDevices.pseudo_devices(): + raise XendConfigError("XendConfig: %s not a valid device type" % + dev_type) + + if cfg_xenapi == None: + raise XendConfigError("XendConfig: device_add requires some " + "config.") + + if cfg_xenapi: + log.debug("XendConfig.phantom_device_add: %s" % str(cfg_xenapi)) + + if cfg_xenapi: + dev_info = {} + if dev_type in ('vbd', 'tap'): + if dev_type == 'vbd': + dev_info['uname'] = cfg_xenapi.get('image', '') + dev_info['dev'] = '%s:disk' % cfg_xenapi.get('device') + elif dev_type == 'tap': + if cfg_xenapi.get('image').find('tap:') == -1: + dev_info['uname'] = 'tap:qcow:%s' % cfg_xenapi.get('image') + dev_info['dev'] = '/dev/%s' % cfg_xenapi.get('device') + dev_info['uname'] = cfg_xenapi.get('image') + dev_info['mode'] = cfg_xenapi.get('mode') + dev_info['backend'] = '0' + dev_uuid = cfg_xenapi.get('uuid', uuid.createString()) + dev_info['uuid'] = dev_uuid + self['devices'][dev_uuid] = (dev_type, dev_info) + self['vbd_refs'].append(dev_uuid) + return dev_uuid + + return '' + def console_add(self, protocol, location, other_config = {}): dev_uuid = uuid.createString() if protocol == 'vt100': diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index ddc240b96b..160ee25a90 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -1565,19 +1565,54 @@ class XendDomainInfo: # VM Destroy # + def _prepare_phantom_paths(self): + # get associated devices to destroy + # build list of phantom devices to be removed after normal devices + plist = [] + from xen.xend.xenstore.xstransact import xstransact + t = xstransact("%s/device/vbd" % GetDomainPath(self.domid)) + for dev in t.list(): + backend_phantom_vbd = xstransact.Read("%s/device/vbd/%s/phantom_vbd" \ + % (self.dompath, dev)) + if backend_phantom_vbd is not None: + frontend_phantom_vbd = xstransact.Read("%s/frontend" \ + % backend_phantom_vbd) + plist.append(backend_phantom_vbd) + plist.append(frontend_phantom_vbd) + return plist + + def _cleanup_phantom_devs(self, plist): + # remove phantom devices + if not plist == []: + time.sleep(2) + for paths in plist: + if paths.find('backend') != -1: + from xen.xend.server import DevController + # Modify online status /before/ updating state (latter is watched by + # drivers, so this ordering avoids a race). + xstransact.Write(paths, 'online', "0") + xstransact.Write(paths, 'state', str(DevController.xenbusState['Closing'])) + # force + xstransact.Remove(paths) + def destroy(self): """Cleanup VM and destroy domain. Nothrow guarantee.""" log.debug("XendDomainInfo.destroy: domid=%s", str(self.domid)) + paths = self._prepare_phantom_paths() + self._cleanupVm() if self.dompath is not None: self.destroyDomain() + self._cleanup_phantom_devs(paths) def destroyDomain(self): log.debug("XendDomainInfo.destroyDomain(%s)", str(self.domid)) + paths = self._prepare_phantom_paths() + try: if self.domid is not None: xc.domain_destroy(self.domid) @@ -1591,7 +1626,7 @@ class XendDomainInfo: XendDomain.instance().remove_domain(self) self.cleanupDomain() - + self._cleanup_phantom_devs(paths) def resumeDomain(self): log.debug("XendDomainInfo.resumeDomain(%s)", str(self.domid)) @@ -2211,6 +2246,25 @@ class XendDomainInfo: return dev_uuid + def create_phantom_vbd_with_vdi(self, xenapi_vbd, vdi_image_path): + """Create a VBD using a VDI from XendStorageRepository. + + @param xenapi_vbd: vbd struct from the Xen API + @param vdi_image_path: VDI UUID + @rtype: string + @return: uuid of the device + """ + xenapi_vbd['image'] = vdi_image_path + dev_uuid = self.info.phantom_device_add('tap', cfg_xenapi = xenapi_vbd) + if not dev_uuid: + raise XendError('Failed to create device') + + if self.state == XEN_API_VM_POWER_STATE_RUNNING: + _, config = self.info['devices'][dev_uuid] + config['devid'] = self.getDeviceController('tap').createDevice(config) + + return config['devid'] + def create_vif(self, xenapi_vif): """Create VIF device from the passed struct in Xen API format. diff --git a/tools/python/xen/xend/server/BlktapController.py b/tools/python/xen/xend/server/BlktapController.py index 062769a061..420a4bdbe6 100644 --- a/tools/python/xen/xend/server/BlktapController.py +++ b/tools/python/xen/xend/server/BlktapController.py @@ -2,7 +2,10 @@ from xen.xend.server.blkif import BlkifController +from xen.xend.XendLogging import log +phantomDev = 0; +phantomId = 0; class BlktapController(BlkifController): def __init__(self, vm): @@ -12,3 +15,62 @@ class BlktapController(BlkifController): """@see DevController#frontendRoot""" return "%s/device/vbd" % self.vm.getDomainPath() + + def getDeviceDetails(self, config): + (devid, back, front) = BlkifController.getDeviceDetails(self, config) + + phantomDevid = 0 + wrapped = False + + try: + imagetype = self.vm.info['image']['type'] + except: + imagetype = "" + + if imagetype == 'hvm': + tdevname = back['dev'] + index = ['c', 'd', 'e', 'f', 'g', 'h', 'i', \ + 'j', 'l', 'm', 'n', 'o', 'p'] + while True: + global phantomDev + global phantomId + import os, stat + + phantomId = phantomId + 1 + if phantomId == 16: + if index[phantomDev] == index[-1]: + if wrapped: + raise VmError(" No loopback block \ + devices are available. ") + wrapped = True + phantomDev = 0 + else: + phantomDev = phantomDev + 1 + phantomId = 1 + devname = 'xvd%s%d' % (index[phantomDev], phantomId) + try: + info = os.stat('/dev/%s' % devname) + except: + break + + vbd = { 'mode': 'w', 'device': devname } + fn = 'tap:%s' % back['params'] + + # recurse ... by creating the vbd, then fallthrough + # and finish creating the original device + + from xen.xend import XendDomain + dom0 = XendDomain.instance().privilegedDomain() + phantomDevid = dom0.create_phantom_vbd_with_vdi(vbd, fn) + # we need to wait for this device at a higher level + # the vbd that gets created will have a link to us + # and will let them do it there + + # add a hook to point to the phantom device, + # root path is always the same (dom0 tap) + if phantomDevid != 0: + front['phantom_vbd'] = '/local/domain/0/backend/tap/0/%s' \ + % str(phantomDevid) + + return (devid, back, front) + diff --git a/tools/python/xen/xend/server/DevController.py b/tools/python/xen/xend/server/DevController.py index 47f03e1994..0016ff89a3 100644 --- a/tools/python/xen/xend/server/DevController.py +++ b/tools/python/xen/xend/server/DevController.py @@ -473,6 +473,19 @@ class DevController: def waitForBackend(self, devid): frontpath = self.frontendPath(devid) + # lookup a phantom + phantomPath = xstransact.Read(frontpath, 'phantom_vbd') + if phantomPath is not None: + log.debug("Waiting for %s's phantom %s.", devid, phantomPath) + statusPath = phantomPath + '/' + HOTPLUG_STATUS_NODE + ev = Event() + result = { 'status': Timeout } + xswatch(statusPath, hotplugStatusCallback, ev, result) + ev.wait(DEVICE_CREATE_TIMEOUT) + err = xstransact.Read(statusPath, HOTPLUG_ERROR_NODE) + if result['status'] != 'Connected': + return (result['status'], err) + backpath = xstransact.Read(frontpath, "backend") From 49d6f8401bf93c7a5ac411db31d7a84a77df66b4 Mon Sep 17 00:00:00 2001 From: Tim Deegan Date: Thu, 8 Feb 2007 10:44:53 +0000 Subject: [PATCH 08/19] [XEN] When removing pages, drop shadow refs before complaining about refcount. Signed-off-by: Tim Deegan --- xen/common/memory.c | 10 ++++++---- xen/include/asm-x86/shadow.h | 5 +++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/xen/common/memory.c b/xen/common/memory.c index 78887e19a6..fcd483818d 100644 --- a/xen/common/memory.c +++ b/xen/common/memory.c @@ -175,11 +175,13 @@ int guest_remove_page(struct domain *d, unsigned long gmfn) if ( unlikely(!page_is_removable(page)) ) { + shadow_drop_references(d, page); /* We'll make this a guest-visible error in future, so take heed! */ - gdprintk(XENLOG_INFO, "Dom%d freeing in-use page %lx (pseudophys %lx):" - " count=%lx type=%lx\n", - d->domain_id, mfn, get_gpfn_from_mfn(mfn), - (unsigned long)page->count_info, page->u.inuse.type_info); + if ( !page_is_removable(page) ) + gdprintk(XENLOG_INFO, "Dom%d freeing in-use page %lx " + "(pseudophys %lx): count=%lx type=%lx\n", + d->domain_id, mfn, get_gpfn_from_mfn(mfn), + (unsigned long)page->count_info, page->u.inuse.type_info); } guest_physmap_remove_page(d, gmfn, mfn); diff --git a/xen/include/asm-x86/shadow.h b/xen/include/asm-x86/shadow.h index 2afc0b0562..a4a489dcf5 100644 --- a/xen/include/asm-x86/shadow.h +++ b/xen/include/asm-x86/shadow.h @@ -355,8 +355,9 @@ int sh_remove_all_mappings(struct vcpu *v, mfn_t target_mfn); static inline void shadow_drop_references(struct domain *d, struct page_info *p) { - /* See the comment about locking in sh_remove_all_mappings */ - sh_remove_all_mappings(d->vcpu[0], _mfn(page_to_mfn(p))); + if ( unlikely(shadow_mode_enabled(d)) ) + /* See the comment about locking in sh_remove_all_mappings */ + sh_remove_all_mappings(d->vcpu[0], _mfn(page_to_mfn(p))); } /* Remove all shadows of the guest mfn. */ From 9c47bd3d1e8e66c787f3dbf1f475dd536ab5d184 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Thu, 8 Feb 2007 11:03:29 +0000 Subject: [PATCH 09/19] [XEN] kexec: Remove asm/kexec.h. Move the single inline function into arch specific machine_kexec.c with the other arch specific kexec functions. IA64 already had a stub in both kexec.h and machine_kexec.c. Signed-off-by: Ian Campbell --- xen/arch/powerpc/machine_kexec.c | 5 ++++ xen/arch/x86/crash.c | 1 - xen/arch/x86/machine_kexec.c | 15 +++++++++++- xen/common/kexec.c | 1 - xen/include/asm-ia64/kexec.h | 25 ------------------- xen/include/asm-powerpc/kexec.h | 25 ------------------- xen/include/asm-x86/kexec.h | 20 --------------- xen/include/asm-x86/x86_32/kexec.h | 39 ------------------------------ xen/include/asm-x86/x86_64/kexec.h | 38 ----------------------------- xen/include/xen/kexec.h | 1 + 10 files changed, 20 insertions(+), 150 deletions(-) delete mode 100644 xen/include/asm-ia64/kexec.h delete mode 100644 xen/include/asm-powerpc/kexec.h delete mode 100644 xen/include/asm-x86/kexec.h delete mode 100644 xen/include/asm-x86/x86_32/kexec.h delete mode 100644 xen/include/asm-x86/x86_64/kexec.h diff --git a/xen/arch/powerpc/machine_kexec.c b/xen/arch/powerpc/machine_kexec.c index 2debd26a7e..51ddd75890 100644 --- a/xen/arch/powerpc/machine_kexec.c +++ b/xen/arch/powerpc/machine_kexec.c @@ -19,6 +19,11 @@ void machine_reboot_kexec(xen_kexec_image_t *image) printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__); } +void machine_kexec(xen_kexec_image_t *image) +{ + printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__); +} + /* * Local variables: * mode: C diff --git a/xen/arch/x86/crash.c b/xen/arch/x86/crash.c index 73eb4724a8..cae1768633 100644 --- a/xen/arch/x86/crash.c +++ b/xen/arch/x86/crash.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include diff --git a/xen/arch/x86/machine_kexec.c b/xen/arch/x86/machine_kexec.c index 81c392a7d3..54fa466793 100644 --- a/xen/arch/x86/machine_kexec.c +++ b/xen/arch/x86/machine_kexec.c @@ -15,11 +15,15 @@ #include #include #include -#include #include #include #include +typedef void (*relocate_new_kernel_t)( + unsigned long indirection_page, + unsigned long page_list, + unsigned long start_address); + int machine_kexec_load(int type, int slot, xen_kexec_image_t *image) { unsigned long prev_ma = 0; @@ -94,6 +98,15 @@ void machine_reboot_kexec(xen_kexec_image_t *image) BUG(); } +void machine_kexec(xen_kexec_image_t *image) +{ + relocate_new_kernel_t rnk; + + rnk = (relocate_new_kernel_t) image->page_list[1]; + (*rnk)(image->indirection_page, (unsigned long)image->page_list, + image->start_address); +} + /* * Local variables: * mode: C diff --git a/xen/common/kexec.c b/xen/common/kexec.c index a9e85cad7f..80314a6673 100644 --- a/xen/common/kexec.c +++ b/xen/common/kexec.c @@ -6,7 +6,6 @@ * - Magnus Damm */ -#include #include #include #include diff --git a/xen/include/asm-ia64/kexec.h b/xen/include/asm-ia64/kexec.h deleted file mode 100644 index 45756e8f64..0000000000 --- a/xen/include/asm-ia64/kexec.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef __IA64_KEXEC_H__ -#define __IA64_KEXEC_H__ - -#include /* for printk() used in stub */ -#include -#include -#include - -static inline void machine_kexec(xen_kexec_image_t *image) -{ - printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__); -} - -#endif /* __IA64_KEXEC_H__ */ - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ - diff --git a/xen/include/asm-powerpc/kexec.h b/xen/include/asm-powerpc/kexec.h deleted file mode 100644 index f228972047..0000000000 --- a/xen/include/asm-powerpc/kexec.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef _ASM_KEXEC_H__ -#define _ASM_KEXEC_H__ - -#include /* for printk() used in stub */ -#include -#include -#include - -static inline void machine_kexec(xen_kexec_image_t *image) -{ - printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__); -} - -#endif /* _ASM_KEXEC_H__ */ - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ - diff --git a/xen/include/asm-x86/kexec.h b/xen/include/asm-x86/kexec.h deleted file mode 100644 index d137337da0..0000000000 --- a/xen/include/asm-x86/kexec.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef __X86_KEXEC_H__ -#define __X86_KEXEC_H__ - -#ifdef __x86_64__ -#include -#else -#include -#endif - -#endif /* __X86_KEXEC_H__ */ - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/xen/include/asm-x86/x86_32/kexec.h b/xen/include/asm-x86/x86_32/kexec.h deleted file mode 100644 index cb4ada715e..0000000000 --- a/xen/include/asm-x86/x86_32/kexec.h +++ /dev/null @@ -1,39 +0,0 @@ -/****************************************************************************** - * kexec.h - * - * Based heavily on machine_kexec.c and kexec.h from Linux 2.6.19-rc1 - * - */ - -#ifndef __X86_KEXEC_X86_32_H__ -#define __X86_KEXEC_X86_32_H__ - -#include -#include - -typedef asmlinkage void (*relocate_new_kernel_t)( - unsigned long indirection_page, - unsigned long page_list, - unsigned long start_address, - unsigned int has_pae); - -static inline void machine_kexec(xen_kexec_image_t *image) -{ - relocate_new_kernel_t rnk; - - rnk = (relocate_new_kernel_t) image->page_list[1]; - (*rnk)(image->indirection_page, (unsigned long)image->page_list, - image->start_address, (unsigned long)cpu_has_pae); -} - -#endif /* __X86_KEXEC_X86_32_H__ */ - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/xen/include/asm-x86/x86_64/kexec.h b/xen/include/asm-x86/x86_64/kexec.h deleted file mode 100644 index c54dbb9ba6..0000000000 --- a/xen/include/asm-x86/x86_64/kexec.h +++ /dev/null @@ -1,38 +0,0 @@ -/****************************************************************************** - * kexec.h - * - * Based heavily on machine_kexec.c and kexec.h from Linux 2.6.19-rc1 - * - */ - -#ifndef __X86_64_KEXEC_H__ -#define __X86_64_KEXEC_H__ - -#include -#include - -typedef void (*relocate_new_kernel_t)( - unsigned long indirection_page, - unsigned long page_list, - unsigned long start_address); - -static inline void machine_kexec(xen_kexec_image_t *image) -{ - relocate_new_kernel_t rnk; - - rnk = (relocate_new_kernel_t) image->page_list[1]; - (*rnk)(image->indirection_page, (unsigned long)image->page_list, - image->start_address); -} - -#endif /* __X86_64_KEXEC_H__ */ - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/xen/include/xen/kexec.h b/xen/include/xen/kexec.h index be09c0a1ab..523846af06 100644 --- a/xen/include/xen/kexec.h +++ b/xen/include/xen/kexec.h @@ -25,6 +25,7 @@ int machine_kexec_load(int type, int slot, xen_kexec_image_t *image); void machine_kexec_unload(int type, int slot, xen_kexec_image_t *image); void machine_kexec_reserved(xen_kexec_reserve_t *reservation); void machine_reboot_kexec(xen_kexec_image_t *image); +void machine_kexec(xen_kexec_image_t *image); void kexec_crash(void); void kexec_crash_save_cpu(void); crash_xen_info_t *kexec_crash_save_info(void); From cc1b02ddd4b54154944d31a82f56b84cd616362e Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Thu, 8 Feb 2007 11:03:32 +0000 Subject: [PATCH 10/19] [XEN] kexec: add compatability shim for kexec in 32on64 mode. Signed-off-by: Ian Campbell --- xen/arch/x86/machine_kexec.c | 48 +++++++++-- xen/arch/x86/x86_64/Makefile | 1 + xen/arch/x86/x86_64/compat_kexec.S | 126 +++++++++++++++++++++++++++++ 3 files changed, 168 insertions(+), 7 deletions(-) create mode 100644 xen/arch/x86/x86_64/compat_kexec.S diff --git a/xen/arch/x86/machine_kexec.c b/xen/arch/x86/machine_kexec.c index 54fa466793..5e82975366 100644 --- a/xen/arch/x86/machine_kexec.c +++ b/xen/arch/x86/machine_kexec.c @@ -21,7 +21,7 @@ typedef void (*relocate_new_kernel_t)( unsigned long indirection_page, - unsigned long page_list, + unsigned long *page_list, unsigned long start_address); int machine_kexec_load(int type, int slot, xen_kexec_image_t *image) @@ -44,8 +44,26 @@ int machine_kexec_load(int type, int slot, xen_kexec_image_t *image) else { /* Odd pages: va for previous ma. */ - set_fixmap(fix_base + (k >> 1), prev_ma); - image->page_list[k] = fix_to_virt(fix_base + (k >> 1)); + if ( IS_COMPAT(dom0) ) + { + + /* + * The compatability bounce code sets up a page table + * with a 1-1 mapping of the first 1G of memory so + * VA==PA here. + * + * This Linux purgatory code still sets up separate + * high and low mappings on the control page (entries + * 0 and 1) but it is harmless if they are equal since + * that PT is not live at the time. + */ + image->page_list[k] = prev_ma; + } + else + { + set_fixmap(fix_base + (k >> 1), prev_ma); + image->page_list[k] = fix_to_virt(fix_base + (k >> 1)); + } } } @@ -100,11 +118,27 @@ void machine_reboot_kexec(xen_kexec_image_t *image) void machine_kexec(xen_kexec_image_t *image) { - relocate_new_kernel_t rnk; +#ifdef CONFIG_COMPAT + if ( IS_COMPAT(dom0) ) + { + extern void compat_machine_kexec(unsigned long rnk, + unsigned long indirection_page, + unsigned long *page_list, + unsigned long start_address); + compat_machine_kexec(image->page_list[1], + image->indirection_page, + image->page_list, + image->start_address); + } + else +#endif + { + relocate_new_kernel_t rnk; - rnk = (relocate_new_kernel_t) image->page_list[1]; - (*rnk)(image->indirection_page, (unsigned long)image->page_list, - image->start_address); + rnk = (relocate_new_kernel_t) image->page_list[1]; + (*rnk)(image->indirection_page, image->page_list, + image->start_address); + } } /* diff --git a/xen/arch/x86/x86_64/Makefile b/xen/arch/x86/x86_64/Makefile index df5632e0a0..372cce5892 100644 --- a/xen/arch/x86/x86_64/Makefile +++ b/xen/arch/x86/x86_64/Makefile @@ -1,4 +1,5 @@ obj-y += entry.o +obj-y += compat_kexec.o obj-y += gpr_switch.o obj-y += mm.o obj-y += traps.o diff --git a/xen/arch/x86/x86_64/compat_kexec.S b/xen/arch/x86/x86_64/compat_kexec.S new file mode 100644 index 0000000000..c06db6fc7e --- /dev/null +++ b/xen/arch/x86/x86_64/compat_kexec.S @@ -0,0 +1,126 @@ +/* + * Compatibility kexec handler. + */ + +#include + +#include +#include +#include + +.text + + .code64 + +ENTRY(compat_machine_kexec) + /* x86/64 x86/32 */ + /* %rdi - relocate_new_kernel_t CALL */ + /* %rsi - indirection page 4(%esp) */ + /* %rdx - page_list 8(%esp) */ + /* %rcx - start address 12(%esp) */ + /* cpu has pae 16(%esp) */ + + /* Shim the 64 bit page_list into a 32 bit page_list. */ + mov $12,%r9 + lea compat_page_list(%rip), %rbx +1: dec %r9 + movl (%rdx,%r9,8),%eax + movl %eax,(%rbx,%r9,4) + test %r9,%r9 + jnz 1b + + movq %rbx,%rdx + mov $__PAGE_OFFSET,%rbx + sub %rbx, %rdx + + /* + * Setup an identity mapped region in PML4[0] of idle page + * table. + */ + lea idle_pg_table_l3(%rip),%rax + sub %rbx,%rax + or $0x63,%rax + mov %rax, idle_pg_table(%rip) + + /* Switch to idle page table. */ + movq $(idle_pg_table - __PAGE_OFFSET), %rax + movq %rax, %cr3 + + /* Jump to low identity mapping in compatibility mode. */ + ljmp *compatibility_mode_far(%rip) + ud2 + +compatibility_mode_far: + .long compatibility_mode - __PAGE_OFFSET + .long __HYPERVISOR_CS32 + + .code32 + +compatibility_mode: + /* Setup some sane segments. */ + movl $__HYPERVISOR_DS32, %eax + movl %eax, %ds + movl %eax, %es + movl %eax, %fs + movl %eax, %gs + movl %eax, %ss + + /* Push arguments onto stack. */ + pushl $1 /* 16(%esp) - cpu has pae */ + pushl %ecx /* 12(%esp) - start address */ + pushl %edx /* 8(%esp) - page list */ + pushl %esi /* 4(%esp) - indirection page */ + pushl %edi /* 0(%esp) - CALL */ + + /* Disable paging and therefore leave 64 bit mode. */ + movl %cr0, %eax + andl $~X86_CR0_PG, %eax + movl %eax, %cr0 + + /* Switch to 32 bit page table. */ + movl $compat_pg_table - __PAGE_OFFSET, %eax + movl %eax, %cr3 + + /* Clear MSR_EFER[LME], disabling long mode */ + movl $MSR_EFER,%ecx + rdmsr + btcl $_EFER_LME,%eax + wrmsr + + /* Re-enable paging, but only 32 bit mode now. */ + movl %cr0, %eax + orl $X86_CR0_PG, %eax + movl %eax, %cr0 + + popl %eax + call *%eax + ud2 + +compat_page_list: + .fill 12,4,0 + + .align 32,0 + + /* + * These compat page tables contain an identity mapping of the + * first 1G of the physical address space. + */ +compat_pg_table: + .long compat_pg_table_l2 + 0*PAGE_SIZE + 0x01 - __PAGE_OFFSET, 0 + .long 0, 0 + .long 0, 0 + .long 0, 0 + + .align 4096,0 + +compat_pg_table_l2: + .macro identmap from=0, count=512 + .if \count-1 + identmap "(\from+0)","(\count/2)" + identmap "(\from+(0x200000*(\count/2)))","(\count/2)" + .else + .quad 0x00000000000000e3 + \from + .endif + .endm + + identmap From 8bc62853df8dd3507ba7d5d839654afd1e164e53 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Thu, 8 Feb 2007 12:33:32 +0000 Subject: [PATCH 11/19] [XEN] Fix typos in comment describing 32on64 memory layout Signed-off-by: Ian Campbell --- xen/include/asm-x86/config.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xen/include/asm-x86/config.h b/xen/include/asm-x86/config.h index 71e3dd8e4a..34cd754186 100644 --- a/xen/include/asm-x86/config.h +++ b/xen/include/asm-x86/config.h @@ -145,9 +145,9 @@ * Compatibility guest area layout: * 0x0000000000000000 - 0x00000000f57fffff [3928MB, PML4:0] * Guest-defined use. - * 0x0000000f58000000 - 0x00000000ffffffff [168MB, PML4:0] + * 0x00000000f5800000 - 0x00000000ffffffff [168MB, PML4:0] * Read-only machine-to-phys translation table (GUEST ACCESSIBLE). - * 0x0000000000000000 - 0x00000000ffffffff [508GB, PML4:0] + * 0x0000000100000000 - 0x0000007fffffffff [508GB, PML4:0] * Unused. * 0x0000008000000000 - 0x000000ffffffffff [512GB, 2^39 bytes, PML4:1] * Hypercall argument translation area. From 8abe0e51d15e6038599fa0d631e78ab41d5aef1b Mon Sep 17 00:00:00 2001 From: Tim Deegan Date: Thu, 8 Feb 2007 13:42:49 +0000 Subject: [PATCH 12/19] [HVM] Save/restore: save pmtimer count register Also remove the repeating timer from pmtimer.c because it doesn't do anything. Signed-off-by: Tim Deegan --- xen/arch/x86/hvm/hvm.c | 2 - xen/arch/x86/hvm/pmtimer.c | 75 ++++++++++++++++++++--------------- xen/include/asm-x86/hvm/vpt.h | 14 +++---- xen/include/public/hvm/save.h | 12 +++++- 4 files changed, 58 insertions(+), 45 deletions(-) diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index 96c827d235..9147737846 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -106,7 +106,6 @@ void hvm_migrate_timers(struct vcpu *v) pit_migrate_timers(v); rtc_migrate_timers(v); hpet_migrate_timers(v); - pmtimer_migrate_timers(v); if ( vcpu_vlapic(v)->pt.enabled ) migrate_timer(&vcpu_vlapic(v)->pt.timer, v->processor); } @@ -170,7 +169,6 @@ void hvm_domain_destroy(struct domain *d) { pit_deinit(d); rtc_deinit(d); - pmtimer_deinit(d); hpet_deinit(d); if ( d->arch.hvm_domain.shared_page_va ) diff --git a/xen/arch/x86/hvm/pmtimer.c b/xen/arch/x86/hvm/pmtimer.c index 28be242f84..a396d27df4 100644 --- a/xen/arch/x86/hvm/pmtimer.c +++ b/xen/arch/x86/hvm/pmtimer.c @@ -2,17 +2,6 @@ #include #include -#define TMR_STS (1 << 0) -static void pmt_update_status(void *opaque) -{ - PMTState *s = opaque; - s->pm1_status |= TMR_STS; - - /* TODO: When TMR_EN == 1, generate a SCI event */ - - set_timer(&s->timer, NOW() + (1000000000ULL << 31) / FREQUENCE_PMTIMER); -} - static int handle_pmt_io(ioreq_t *p) { struct vcpu *v = current; @@ -30,42 +19,62 @@ static int handle_pmt_io(ioreq_t *p) /* PM_TMR_BLK is read-only */ return 1; } else if (p->dir == 1) { /* read */ + /* Set the correct value in the timer, accounting for time + * elapsed since the last time we did that. */ curr_gtime = hvm_get_guest_time(s->vcpu); - s->pm1_timer += ((curr_gtime - s->last_gtime) * s->scale) >> 32; - p->data = s->pm1_timer; + s->pm.timer += ((curr_gtime - s->last_gtime) * s->scale) >> 32; + p->data = s->pm.timer; s->last_gtime = curr_gtime; return 1; } return 0; } +static int pmtimer_save(struct domain *d, hvm_domain_context_t *h) +{ + PMTState *s = &d->arch.hvm_domain.pl_time.vpmt; + uint32_t x; + + /* Update the counter to the guest's current time. We always save + * with the domain paused, so the saved time should be after the + * last_gtime, but just in case, make sure we only go forwards */ + x = ((s->vcpu->arch.hvm_vcpu.guest_time - s->last_gtime) * s->scale) >> 32; + if ( x < 1UL<<31 ) + s->pm.timer += x; + return hvm_save_entry(PMTIMER, 0, h, &s->pm); +} + +static int pmtimer_load(struct domain *d, hvm_domain_context_t *h) +{ + PMTState *s = &d->arch.hvm_domain.pl_time.vpmt; + + /* Reload the counter */ + if ( hvm_load_entry(PMTIMER, h, &s->pm) ) + return -EINVAL; + + /* Calculate future counter values from now. */ + s->last_gtime = hvm_get_guest_time(s->vcpu); + + return 0; +} + +HVM_REGISTER_SAVE_RESTORE(PMTIMER, pmtimer_save, pmtimer_load, + 1, HVMSR_PER_DOM); + + void pmtimer_init(struct vcpu *v, int base) { PMTState *s = &v->domain->arch.hvm_domain.pl_time.vpmt; - s->pm1_timer = 0; - s->pm1_status = 0; + s->pm.timer = 0; s->scale = ((uint64_t)FREQUENCE_PMTIMER << 32) / ticks_per_sec(v); s->vcpu = v; - init_timer(&s->timer, pmt_update_status, s, v->processor); - /* ACPI supports a 32-bit power management timer */ - set_timer(&s->timer, NOW() + (1000000000ULL << 31) / FREQUENCE_PMTIMER); - + /* Not implemented: we should set TMR_STS (bit 0 of PM1a_STS) every + * time the timer's top bit flips, and generate an SCI if TMR_EN + * (bit 0 of PM1a_EN) is set. For now, those registers are in + * qemu-dm, and we just calculate the timer's value on demand. */ + register_portio_handler(v->domain, base, 4, handle_pmt_io); } -void pmtimer_migrate_timers(struct vcpu *v) -{ - struct PMTState *vpmt = &v->domain->arch.hvm_domain.pl_time.vpmt; - - if (vpmt->vcpu == v) - migrate_timer(&vpmt->timer, v->processor); -} - -void pmtimer_deinit(struct domain *d) -{ - PMTState *s = &d->arch.hvm_domain.pl_time.vpmt; - - kill_timer(&s->timer); -} diff --git a/xen/include/asm-x86/hvm/vpt.h b/xen/include/asm-x86/hvm/vpt.h index 78c7b536d4..02bc3fa05c 100644 --- a/xen/include/asm-x86/hvm/vpt.h +++ b/xen/include/asm-x86/hvm/vpt.h @@ -94,14 +94,12 @@ typedef struct RTCState { struct periodic_time pt; } RTCState; -#define FREQUENCE_PMTIMER 3579545 +#define FREQUENCE_PMTIMER 3579545 /* Timer should run at 3.579545 MHz */ typedef struct PMTState { - uint32_t pm1_timer; - uint32_t pm1_status; - uint64_t last_gtime; - struct timer timer; - uint64_t scale; - struct vcpu *vcpu; + struct hvm_hw_pmtimer pm; /* 32bit timer value */ + struct vcpu *vcpu; /* Keeps sync with this vcpu's guest-time */ + uint64_t last_gtime; /* Last (guest) time we updated the timer */ + uint64_t scale; /* Multiplier to get from tsc to timer ticks */ } PMTState; struct pl_time { /* platform time */ @@ -134,8 +132,6 @@ void rtc_migrate_timers(struct vcpu *v); void rtc_deinit(struct domain *d); int is_rtc_periodic_irq(void *opaque); void pmtimer_init(struct vcpu *v, int base); -void pmtimer_migrate_timers(struct vcpu *v); -void pmtimer_deinit(struct domain *d); void hpet_migrate_timers(struct vcpu *v); void hpet_init(struct vcpu *v); diff --git a/xen/include/public/hvm/save.h b/xen/include/public/hvm/save.h index 7ed26495c8..c6a856a558 100644 --- a/xen/include/public/hvm/save.h +++ b/xen/include/public/hvm/save.h @@ -382,10 +382,20 @@ struct hvm_hw_hpet { DECLARE_HVM_SAVE_TYPE(HPET, 12, struct hvm_hw_hpet); +/* + * PM timer + */ + +struct hvm_hw_pmtimer { + uint32_t timer; +}; + +DECLARE_HVM_SAVE_TYPE(PMTIMER, 13, struct hvm_hw_pmtimer); + /* * Largest type-code in use */ -#define HVM_SAVE_CODE_MAX 12 +#define HVM_SAVE_CODE_MAX 13 /* From de602931ef7752d469b206b21ffad7f38810cda6 Mon Sep 17 00:00:00 2001 From: Tim Deegan Date: Thu, 8 Feb 2007 15:00:33 +0000 Subject: [PATCH 13/19] [HVM] Save/restore: don't try to set the console ring MFN in a HVM restore. In particular, don't print an uninitialized stack variable, which causes XMLRPC exceptions in xend. Signed-off-by: Tim Deegan --- tools/libxc/xc_hvm_restore.c | 5 ++--- tools/libxc/xenguest.h | 3 +-- tools/libxc/xg_private.c | 3 +-- tools/python/xen/xend/XendCheckpoint.py | 7 +++++-- tools/xcutils/xc_restore.c | 5 +++-- 5 files changed, 12 insertions(+), 11 deletions(-) diff --git a/tools/libxc/xc_hvm_restore.c b/tools/libxc/xc_hvm_restore.c index 6622b49f79..4cf27fdb8b 100644 --- a/tools/libxc/xc_hvm_restore.c +++ b/tools/libxc/xc_hvm_restore.c @@ -69,7 +69,6 @@ read_exact(int fd, void *buf, size_t count) int xc_hvm_restore(int xc_handle, int io_fd, uint32_t dom, unsigned long nr_pfns, unsigned int store_evtchn, unsigned long *store_mfn, - unsigned int console_evtchn, unsigned long *console_mfn, unsigned int pae, unsigned int apic) { DECLARE_DOMCTL; @@ -104,8 +103,8 @@ int xc_hvm_restore(int xc_handle, int io_fd, memsize = (unsigned long long)*store_mfn; v_end = memsize << 20; - DPRINTF("xc_hvm_restore:dom=%d, nr_pfns=0x%lx, store_evtchn=%d, *store_mfn=%ld, console_evtchn=%d, *console_mfn=%ld, pae=%u, apic=%u.\n", - dom, nr_pfns, store_evtchn, *store_mfn, console_evtchn, *console_mfn, pae, apic); + DPRINTF("xc_hvm_restore:dom=%d, nr_pfns=0x%lx, store_evtchn=%d, *store_mfn=%ld, pae=%u, apic=%u.\n", + dom, nr_pfns, store_evtchn, *store_mfn, pae, apic); max_pfn = nr_pfns; diff --git a/tools/libxc/xenguest.h b/tools/libxc/xenguest.h index 7b5a2af0a4..3800b0cb13 100644 --- a/tools/libxc/xenguest.h +++ b/tools/libxc/xenguest.h @@ -58,8 +58,7 @@ int xc_linux_restore(int xc_handle, int io_fd, uint32_t dom, */ int xc_hvm_restore(int xc_handle, int io_fd, uint32_t dom, unsigned long nr_pfns, unsigned int store_evtchn, - unsigned long *store_mfn, unsigned int console_evtchn, - unsigned long *console_mfn, + unsigned long *store_mfn, unsigned int pae, unsigned int apic); /** diff --git a/tools/libxc/xg_private.c b/tools/libxc/xg_private.c index f45c2ebb0d..6f4f28f988 100644 --- a/tools/libxc/xg_private.c +++ b/tools/libxc/xg_private.c @@ -210,8 +210,7 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, __attribute__((weak)) int xc_hvm_restore(int xc_handle, int io_fd, uint32_t dom, unsigned long nr_pfns, unsigned int store_evtchn, - unsigned long *store_mfn, unsigned int console_evtchn, - unsigned long *console_mfn, + unsigned long *store_mfn, unsigned int pae, unsigned int apic) { errno = ENOSYS; diff --git a/tools/python/xen/xend/XendCheckpoint.py b/tools/python/xen/xend/XendCheckpoint.py index 6eda8edf76..63368bd654 100644 --- a/tools/python/xen/xend/XendCheckpoint.py +++ b/tools/python/xen/xend/XendCheckpoint.py @@ -239,8 +239,11 @@ def restore(xd, fd, dominfo = None, paused = False): forkHelper(cmd, fd, handler.handler, True) - if handler.store_mfn is None or handler.console_mfn is None: - raise XendError('Could not read store/console MFN') + if handler.store_mfn is None: + raise XendError('Could not read store MFN') + + if not is_hvm and handler.console_mfn is None: + raise XendError('Could not read console MFN') dominfo.waitForDevices() # Wait for backends to set up if not paused: diff --git a/tools/xcutils/xc_restore.c b/tools/xcutils/xc_restore.c index 8e26d9bb70..6629e33082 100644 --- a/tools/xcutils/xc_restore.c +++ b/tools/xcutils/xc_restore.c @@ -45,14 +45,15 @@ main(int argc, char **argv) /* pass the memsize to xc_hvm_restore to find the store_mfn */ store_mfn = hvm; ret = xc_hvm_restore(xc_fd, io_fd, domid, nr_pfns, store_evtchn, - &store_mfn, console_evtchn, &console_mfn, pae, apic); + &store_mfn, pae, apic); } else ret = xc_linux_restore(xc_fd, io_fd, domid, nr_pfns, store_evtchn, &store_mfn, console_evtchn, &console_mfn); if (ret == 0) { printf("store-mfn %li\n", store_mfn); - printf("console-mfn %li\n", console_mfn); + if (!hvm) + printf("console-mfn %li\n", console_mfn); fflush(stdout); } From 1f226801508c962af561b9192381bf7f68cb7ee1 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Thu, 8 Feb 2007 16:52:05 +0000 Subject: [PATCH 14/19] Fix localtime setting for PV domains. Signed-off-by: Atsushi SAKAI --- tools/python/xen/xend/XendDomainInfo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index 160ee25a90..6c4a9afcb4 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -1416,7 +1416,7 @@ class XendDomainInfo: self.info['image'], self.info['devices']) - localtime = self.info.get('localtime', False) + localtime = self.info.get('platform_localtime', False) if localtime: xc.domain_set_time_offset(self.domid) From d4a9cc151365ad63cb2100e5b768319bf498312a Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Thu, 8 Feb 2007 17:04:26 +0000 Subject: [PATCH 15/19] Add example xen-detect.c code for detecting application execution in Xen PV or HVM contexts, using the Xen CPUID extensions. Signed-off-by: Keir Fraser --- .hgignore | 1 + tools/misc/Makefile | 2 +- tools/misc/xen-detect.c | 107 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 109 insertions(+), 1 deletion(-) create mode 100644 tools/misc/xen-detect.c diff --git a/.hgignore b/.hgignore index 85ddd9d976..4a3636cab5 100644 --- a/.hgignore +++ b/.hgignore @@ -138,6 +138,7 @@ ^tools/misc/miniterm/miniterm$ ^tools/misc/xc_shadow$ ^tools/misc/xen_cpuperf$ +^tools/misc/xen-detect$ ^tools/misc/xenperf$ ^tools/pygrub/build/.*$ ^tools/python/build/.*$ diff --git a/tools/misc/Makefile b/tools/misc/Makefile index 80b52c0063..494ebc95ec 100644 --- a/tools/misc/Makefile +++ b/tools/misc/Makefile @@ -9,7 +9,7 @@ CFLAGS += $(INCLUDES) HDRS = $(wildcard *.h) -TARGETS = xenperf xc_shadow +TARGETS = xenperf xc_shadow xen-detect INSTALL_BIN = $(TARGETS) xencons INSTALL_SBIN = netfix xm xen-bugtool xen-python-path xend xenperf diff --git a/tools/misc/xen-detect.c b/tools/misc/xen-detect.c new file mode 100644 index 0000000000..6ac23f4453 --- /dev/null +++ b/tools/misc/xen-detect.c @@ -0,0 +1,107 @@ +/****************************************************************************** + * xen_detect.c + * + * Simple GNU C / POSIX application to detect execution on Xen VMM platform. + * + * Copyright (c) 2007, XenSource Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (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. + */ + +#include +#include +#include +#include +#include +#include + +static int pv_context; + +static void cpuid(uint32_t idx, + uint32_t *eax, + uint32_t *ebx, + uint32_t *ecx, + uint32_t *edx) +{ + asm volatile ( + "test %1,%1 ; jz 1f ; ud2a ; .ascii \"xen\" ; 1: cpuid" + : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx) + : "0" (idx), "1" (pv_context) ); +} + +static int check_for_xen(void) +{ + uint32_t eax, ebx, ecx, edx; + char signature[13]; + + cpuid(0x40000000, &eax, &ebx, &ecx, &edx); + *(uint32_t *)(signature + 0) = ebx; + *(uint32_t *)(signature + 4) = ecx; + *(uint32_t *)(signature + 8) = edx; + signature[12] = '\0'; + + if ( strcmp("XenVMMXenVMM", signature) || (eax < 0x40000002) ) + return 0; + + cpuid(0x40000001, &eax, &ebx, &ecx, &edx); + printf("Running in %s context on Xen v%d.%d.\n", + pv_context ? "PV" : "HVM", (uint16_t)(eax >> 16), (uint16_t)eax); + return 1; +} + +int main(void) +{ + pid_t pid; + int status; + uint32_t dummy; + + /* Check for execution in HVM context. */ + if ( check_for_xen() ) + return 0; + + /* Now we check for execution in PV context. */ + pv_context = 1; + + /* + * Fork a child to test the paravirtualised CPUID instruction. + * If executed outside Xen PV context, the extended opcode will fault. + */ + pid = fork(); + switch ( pid ) + { + case 0: + /* Child: test paravirtualised CPUID opcode and then exit cleanly. */ + cpuid(0x40000000, &dummy, &dummy, &dummy, &dummy); + exit(0); + case -1: + fprintf(stderr, "Fork failed.\n"); + return 0; + } + + /* + * Parent waits for child to terminate and checks for clean exit. + * Only if the exit is clean is it safe for us to try the extended CPUID. + */ + waitpid(pid, &status, 0); + if ( WIFEXITED(status) && check_for_xen() ) + return 0; + + printf("Not running on Xen.\n"); + return 0; +} From c68414307be76e655696398f1ed72466c1e4b869 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Thu, 8 Feb 2007 17:07:36 +0000 Subject: [PATCH 16/19] Fix xen-detect build. Signed-off-by: Keir Fraser --- tools/misc/Makefile | 2 +- tools/misc/xen-detect.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/misc/Makefile b/tools/misc/Makefile index 494ebc95ec..dce732f273 100644 --- a/tools/misc/Makefile +++ b/tools/misc/Makefile @@ -41,5 +41,5 @@ clean: %.o: %.c $(HDRS) Makefile $(CC) -c $(CFLAGS) -o $@ $< -$(TARGETS): %: %.o Makefile +xenperf xc_shadow: %: %.o Makefile $(CC) $(CFLAGS) -o $@ $< -L$(XEN_LIBXC) -lxenctrl diff --git a/tools/misc/xen-detect.c b/tools/misc/xen-detect.c index 6ac23f4453..c918945f81 100644 --- a/tools/misc/xen-detect.c +++ b/tools/misc/xen-detect.c @@ -26,6 +26,7 @@ #include #include +#include #include #include #include From 9e81ed4de392d2785759a552d74b58aa09c0fb4f Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Thu, 8 Feb 2007 17:15:38 +0000 Subject: [PATCH 17/19] Fix a typo in console_steal(). Signed-off-by: Kevin Tian --- xen/drivers/char/console.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c index 01eda8a06d..7eea5b2b4e 100644 --- a/xen/drivers/char/console.c +++ b/xen/drivers/char/console.c @@ -223,7 +223,7 @@ int console_steal(int handle, void (*fn)(const char *)) if ( (handle == -1) || (handle != sercon_handle) ) return 0; - if ( serial_steal_fn == NULL ) + if ( serial_steal_fn != NULL ) return -EBUSY; serial_steal_fn = fn; From ed293612d54a3d1626e9ac53eaf2f495a7fe6a92 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Thu, 8 Feb 2007 17:19:49 +0000 Subject: [PATCH 18/19] Move skb_pull_rcsum() to its usual place in skbuff.c --- linux-2.6-xen-sparse/net/core/skbuff.c | 46 +++++++++++++------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/linux-2.6-xen-sparse/net/core/skbuff.c b/linux-2.6-xen-sparse/net/core/skbuff.c index e7bbe91b8f..c8e7259cc0 100644 --- a/linux-2.6-xen-sparse/net/core/skbuff.c +++ b/linux-2.6-xen-sparse/net/core/skbuff.c @@ -1896,6 +1896,29 @@ int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb, return 0; } +/** + * skb_pull_rcsum - pull skb and update receive checksum + * @skb: buffer to update + * @start: start of data before pull + * @len: length of data pulled + * + * This function performs an skb_pull on the packet and updates + * update the CHECKSUM_HW checksum. It should be used on receive + * path processing instead of skb_pull unless you know that the + * checksum difference is zero (e.g., a valid IP header) or you + * are setting ip_summed to CHECKSUM_NONE. + */ +unsigned char *skb_pull_rcsum(struct sk_buff *skb, unsigned int len) +{ + BUG_ON(len > skb->len); + skb->len -= len; + BUG_ON(skb->len < skb->data_len); + skb_postpull_rcsum(skb, skb->data, len); + return skb->data += len; +} + +EXPORT_SYMBOL_GPL(skb_pull_rcsum); + /** * skb_segment - Perform protocol segmentation on skb. * @skb: buffer to segment @@ -2022,29 +2045,6 @@ err: EXPORT_SYMBOL_GPL(skb_segment); -/** - * skb_pull_rcsum - pull skb and update receive checksum - * @skb: buffer to update - * @start: start of data before pull - * @len: length of data pulled - * - * This function performs an skb_pull on the packet and updates - * update the CHECKSUM_HW checksum. It should be used on receive - * path processing instead of skb_pull unless you know that the - * checksum difference is zero (e.g., a valid IP header) or you - * are setting ip_summed to CHECKSUM_NONE. - */ -unsigned char *skb_pull_rcsum(struct sk_buff *skb, unsigned int len) -{ - BUG_ON(len > skb->len); - skb->len -= len; - BUG_ON(skb->len < skb->data_len); - skb_postpull_rcsum(skb, skb->data, len); - return skb->data += len; -} - -EXPORT_SYMBOL_GPL(skb_pull_rcsum); - void __init skb_init(void) { skbuff_head_cache = kmem_cache_create("skbuff_head_cache", From a9a8f70bdf30e1b7ae7d50f3b86788fc93329ff9 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Thu, 8 Feb 2007 17:21:04 +0000 Subject: [PATCH 19/19] Remove unnecessarily modified a.out.h. Signed-off-by: Jan Beulich --- linux-2.6-xen-sparse/include/asm-i386/a.out.h | 26 ------------------- 1 file changed, 26 deletions(-) delete mode 100644 linux-2.6-xen-sparse/include/asm-i386/a.out.h diff --git a/linux-2.6-xen-sparse/include/asm-i386/a.out.h b/linux-2.6-xen-sparse/include/asm-i386/a.out.h deleted file mode 100644 index 66db22938f..0000000000 --- a/linux-2.6-xen-sparse/include/asm-i386/a.out.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef __I386_A_OUT_H__ -#define __I386_A_OUT_H__ - -struct exec -{ - unsigned long a_info; /* Use macros N_MAGIC, etc for access */ - unsigned a_text; /* length of text, in bytes */ - unsigned a_data; /* length of data, in bytes */ - unsigned a_bss; /* length of uninitialized data area for file, in bytes */ - unsigned a_syms; /* length of symbol table data in file, in bytes */ - unsigned a_entry; /* start address */ - unsigned a_trsize; /* length of relocation info for text, in bytes */ - unsigned a_drsize; /* length of relocation info for data, in bytes */ -}; - -#define N_TRSIZE(a) ((a).a_trsize) -#define N_DRSIZE(a) ((a).a_drsize) -#define N_SYMSIZE(a) ((a).a_syms) - -#ifdef __KERNEL__ - -#define STACK_TOP (TASK_SIZE - 3*PAGE_SIZE) - -#endif - -#endif /* __A_OUT_GNU_H__ */