debuggers.hg
changeset 11049:b60ea69932b1
Merge with xenppc-unstable.
author | kfraser@localhost.localdomain |
---|---|
date | Wed Aug 09 18:04:20 2006 +0100 (2006-08-09) |
parents | e4f1519b473f 15304ad81c50 |
children | 9fc1979e9b00 |
files |
line diff
1.1 --- a/buildconfigs/linux-defconfig_xen0_ia64 Tue Aug 08 19:07:32 2006 -0500 1.2 +++ b/buildconfigs/linux-defconfig_xen0_ia64 Wed Aug 09 18:04:20 2006 +0100 1.3 @@ -1533,8 +1533,9 @@ CONFIG_XEN_BLKDEV_BACKEND=y 1.4 # CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set 1.5 CONFIG_XEN_NETDEV_LOOPBACK=y 1.6 CONFIG_XEN_PCIDEV_BACKEND=y 1.7 -CONFIG_XEN_PCIDEV_BACKEND_VPCI=y 1.8 +# CONFIG_XEN_PCIDEV_BACKEND_VPCI is not set 1.9 # CONFIG_XEN_PCIDEV_BACKEND_PASS is not set 1.10 +CONFIG_XEN_PCIDEV_BACKEND_SLOT=y 1.11 # CONFIG_XEN_PCIDEV_BE_DEBUG is not set 1.12 # CONFIG_XEN_TPMDEV_BACKEND is not set 1.13 CONFIG_XEN_BLKDEV_FRONTEND=y
2.1 --- a/buildconfigs/linux-defconfig_xen0_x86_32 Tue Aug 08 19:07:32 2006 -0500 2.2 +++ b/buildconfigs/linux-defconfig_xen0_x86_32 Wed Aug 09 18:04:20 2006 +0100 2.3 @@ -1320,6 +1320,7 @@ CONFIG_XEN_BACKEND=y 2.4 CONFIG_XEN_PCIDEV_BACKEND=y 2.5 # CONFIG_XEN_PCIDEV_BACKEND_VPCI is not set 2.6 CONFIG_XEN_PCIDEV_BACKEND_PASS=y 2.7 +# CONFIG_XEN_PCIDEV_BACKEND_SLOT is not set 2.8 # CONFIG_XEN_PCIDEV_BE_DEBUG is not set 2.9 CONFIG_XEN_BLKDEV_BACKEND=y 2.10 CONFIG_XEN_BLKDEV_TAP=y
3.1 --- a/buildconfigs/linux-defconfig_xen0_x86_64 Tue Aug 08 19:07:32 2006 -0500 3.2 +++ b/buildconfigs/linux-defconfig_xen0_x86_64 Wed Aug 09 18:04:20 2006 +0100 3.3 @@ -1261,6 +1261,7 @@ CONFIG_XEN_BACKEND=y 3.4 CONFIG_XEN_PCIDEV_BACKEND=y 3.5 # CONFIG_XEN_PCIDEV_BACKEND_VPCI is not set 3.6 CONFIG_XEN_PCIDEV_BACKEND_PASS=y 3.7 +# CONFIG_XEN_PCIDEV_BACKEND_SLOT is not set 3.8 # CONFIG_XEN_PCIDEV_BE_DEBUG is not set 3.9 CONFIG_XEN_BLKDEV_BACKEND=y 3.10 CONFIG_XEN_BLKDEV_TAP=y
4.1 --- a/buildconfigs/linux-defconfig_xen_ia64 Tue Aug 08 19:07:32 2006 -0500 4.2 +++ b/buildconfigs/linux-defconfig_xen_ia64 Wed Aug 09 18:04:20 2006 +0100 4.3 @@ -1539,8 +1539,9 @@ CONFIG_XEN_BLKDEV_BACKEND=y 4.4 # CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set 4.5 CONFIG_XEN_NETDEV_LOOPBACK=y 4.6 CONFIG_XEN_PCIDEV_BACKEND=y 4.7 -CONFIG_XEN_PCIDEV_BACKEND_VPCI=y 4.8 +# CONFIG_XEN_PCIDEV_BACKEND_VPCI is not set 4.9 # CONFIG_XEN_PCIDEV_BACKEND_PASS is not set 4.10 +CONFIG_XEN_PCIDEV_BACKEND_SLOT=y 4.11 # CONFIG_XEN_PCIDEV_BE_DEBUG is not set 4.12 # CONFIG_XEN_TPMDEV_BACKEND is not set 4.13 CONFIG_XEN_BLKDEV_FRONTEND=y
5.1 --- a/buildconfigs/linux-defconfig_xen_x86_32 Tue Aug 08 19:07:32 2006 -0500 5.2 +++ b/buildconfigs/linux-defconfig_xen_x86_32 Wed Aug 09 18:04:20 2006 +0100 5.3 @@ -3021,6 +3021,7 @@ CONFIG_XEN_BACKEND=y 5.4 CONFIG_XEN_PCIDEV_BACKEND=m 5.5 CONFIG_XEN_PCIDEV_BACKEND_VPCI=y 5.6 # CONFIG_XEN_PCIDEV_BACKEND_PASS is not set 5.7 +# CONFIG_XEN_PCIDEV_BACKEND_SLOT is not set 5.8 # CONFIG_XEN_PCIDEV_BE_DEBUG is not set 5.9 CONFIG_XEN_BLKDEV_BACKEND=y 5.10 CONFIG_XEN_BLKDEV_TAP=y
6.1 --- a/buildconfigs/linux-defconfig_xen_x86_64 Tue Aug 08 19:07:32 2006 -0500 6.2 +++ b/buildconfigs/linux-defconfig_xen_x86_64 Wed Aug 09 18:04:20 2006 +0100 6.3 @@ -2853,6 +2853,7 @@ CONFIG_XEN_BACKEND=y 6.4 CONFIG_XEN_PCIDEV_BACKEND=m 6.5 # CONFIG_XEN_PCIDEV_BACKEND_VPCI is not set 6.6 CONFIG_XEN_PCIDEV_BACKEND_PASS=y 6.7 +# CONFIG_XEN_PCIDEV_BACKEND_SLOT is not set 6.8 # CONFIG_XEN_PCIDEV_BE_DEBUG is not set 6.9 CONFIG_XEN_BLKDEV_BACKEND=y 6.10 CONFIG_XEN_BLKDEV_TAP=y
7.1 --- a/linux-2.6-xen-sparse/drivers/xen/Kconfig Tue Aug 08 19:07:32 2006 -0500 7.2 +++ b/linux-2.6-xen-sparse/drivers/xen/Kconfig Wed Aug 09 18:04:20 2006 +0100 7.3 @@ -117,7 +117,7 @@ config XEN_PCIDEV_BACKEND_VPCI 7.4 This PCI Backend hides the true PCI topology and makes the frontend 7.5 think there is a single PCI bus with only the exported devices on it. 7.6 For example, a device at 03:05.0 will be re-assigned to 00:00.0. A 7.7 - second device at 02:1a.0 will be re-assigned to 00:01.0. 7.8 + second device at 02:1a.1 will be re-assigned to 00:01.1. 7.9 7.10 config XEN_PCIDEV_BACKEND_PASS 7.11 bool "Passthrough" 7.12 @@ -129,6 +129,15 @@ config XEN_PCIDEV_BACKEND_PASS 7.13 which depend on finding their hardward in certain bus/slot 7.14 locations. 7.15 7.16 +config XEN_PCIDEV_BACKEND_SLOT 7.17 + bool "Slot" 7.18 + ---help--- 7.19 + This PCI Backend hides the true PCI topology and makes the frontend 7.20 + think there is a single PCI bus with only the exported devices on it. 7.21 + Contrary to the virtual PCI backend, a function becomes a new slot. 7.22 + For example, a device at 03:05.2 will be re-assigned to 00:00.0. A 7.23 + second device at 02:1a.1 will be re-assigned to 00:01.0. 7.24 + 7.25 endchoice 7.26 7.27 config XEN_PCIDEV_BE_DEBUG
8.1 --- a/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c Tue Aug 08 19:07:32 2006 -0500 8.2 +++ b/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c Wed Aug 09 18:04:20 2006 +0100 8.3 @@ -563,10 +563,14 @@ struct page *balloon_alloc_empty_page_ra 8.4 set_xen_guest_handle(reservation.extent_start, &gmfn); 8.5 ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation, 8.6 &reservation); 8.7 + if (ret == -ENOSYS) 8.8 + goto err; 8.9 BUG_ON(ret != 1); 8.10 } else { 8.11 ret = apply_to_page_range(&init_mm, vstart, PAGE_SIZE << order, 8.12 dealloc_pte_fn, NULL); 8.13 + if (ret == -ENOSYS) 8.14 + goto err; 8.15 BUG_ON(ret); 8.16 } 8.17 current_pages -= 1UL << order; 8.18 @@ -583,6 +587,11 @@ struct page *balloon_alloc_empty_page_ra 8.19 set_page_count(page + i, 1); 8.20 8.21 return page; 8.22 + 8.23 + err: 8.24 + free_pages(vstart, order); 8.25 + balloon_unlock(flags); 8.26 + return NULL; 8.27 } 8.28 8.29 void balloon_dealloc_empty_page_range(
9.1 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c Tue Aug 08 19:07:32 2006 -0500 9.2 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c Wed Aug 09 18:04:20 2006 +0100 9.3 @@ -518,6 +518,19 @@ static int __init blkif_init(void) 9.4 return -ENODEV; 9.5 9.6 mmap_pages = blkif_reqs * BLKIF_MAX_SEGMENTS_PER_REQUEST; 9.7 + 9.8 +#ifdef CONFIG_XEN_IA64_DOM0_NON_VP 9.9 + extern unsigned long alloc_empty_foreign_map_page_range( 9.10 + unsigned long pages); 9.11 + mmap_vstart = (unsigned long) 9.12 + alloc_empty_foreign_map_page_range(mmap_pages); 9.13 +#else /* ! ia64 */ 9.14 + page = balloon_alloc_empty_page_range(mmap_pages); 9.15 + if (page == NULL) 9.16 + return -ENOMEM; 9.17 + mmap_vstart = (unsigned long)pfn_to_kaddr(page_to_pfn(page)); 9.18 +#endif 9.19 + 9.20 pending_reqs = kmalloc(sizeof(pending_reqs[0]) * 9.21 blkif_reqs, GFP_KERNEL); 9.22 pending_grant_handles = kmalloc(sizeof(pending_grant_handles[0]) * 9.23 @@ -534,16 +547,6 @@ static int __init blkif_init(void) 9.24 9.25 blkif_interface_init(); 9.26 9.27 -#ifdef CONFIG_XEN_IA64_DOM0_NON_VP 9.28 - extern unsigned long alloc_empty_foreign_map_page_range( 9.29 - unsigned long pages); 9.30 - mmap_vstart = (unsigned long) 9.31 - alloc_empty_foreign_map_page_range(mmap_pages); 9.32 -#else /* ! ia64 */ 9.33 - page = balloon_alloc_empty_page_range(mmap_pages); 9.34 - BUG_ON(page == NULL); 9.35 - mmap_vstart = (unsigned long)pfn_to_kaddr(page_to_pfn(page)); 9.36 -#endif 9.37 printk("%s: reqs=%d, pages=%d, mmap_vstart=0x%lx\n", 9.38 __FUNCTION__, blkif_reqs, mmap_pages, mmap_vstart); 9.39 BUG_ON(mmap_vstart == 0);
10.1 --- a/linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c Tue Aug 08 19:07:32 2006 -0500 10.2 +++ b/linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c Wed Aug 09 18:04:20 2006 +0100 10.3 @@ -709,30 +709,19 @@ static void make_response(blkif_t *blkif 10.4 /****************************************************************** 10.5 * misc small helpers 10.6 */ 10.7 -/* FIXME: Return ENOMEM properly on failure to allocate additional reqs. */ 10.8 -static void req_increase(void) 10.9 +static int req_increase(void) 10.10 { 10.11 int i, j; 10.12 struct page *page; 10.13 unsigned long flags; 10.14 + int ret; 10.15 10.16 spin_lock_irqsave(&pending_free_lock, flags); 10.17 10.18 + ret = -EINVAL; 10.19 if (mmap_alloc >= MAX_PENDING_REQS || mmap_lock) 10.20 goto done; 10.21 10.22 - pending_reqs[mmap_alloc] = kzalloc(sizeof(pending_req_t) * 10.23 - blkif_reqs, GFP_KERNEL); 10.24 - pending_addrs[mmap_alloc] = kzalloc(sizeof(unsigned long) * 10.25 - mmap_pages, GFP_KERNEL); 10.26 - 10.27 - if (!pending_reqs[mmap_alloc] || !pending_addrs[mmap_alloc]) { 10.28 - kfree(pending_reqs[mmap_alloc]); 10.29 - kfree(pending_addrs[mmap_alloc]); 10.30 - WPRINTK("%s: out of memory\n", __FUNCTION__); 10.31 - goto done; 10.32 - } 10.33 - 10.34 #ifdef __ia64__ 10.35 extern unsigned long alloc_empty_foreign_map_page_range( 10.36 unsigned long pages); 10.37 @@ -740,7 +729,11 @@ static void req_increase(void) 10.38 alloc_empty_foreign_map_page_range(mmap_pages); 10.39 #else /* ! ia64 */ 10.40 page = balloon_alloc_empty_page_range(mmap_pages); 10.41 - BUG_ON(page == NULL); 10.42 + ret = -ENOMEM; 10.43 + if (page == NULL) { 10.44 + printk("%s balloon_alloc_empty_page_range gave NULL\n", __FUNCTION__); 10.45 + goto done; 10.46 + } 10.47 10.48 /* Pin all of the pages. */ 10.49 for (i=0; i<mmap_pages; i++) 10.50 @@ -751,6 +744,23 @@ static void req_increase(void) 10.51 mmap_start[mmap_alloc].mpage = page; 10.52 10.53 #endif 10.54 + 10.55 + pending_reqs[mmap_alloc] = kzalloc(sizeof(pending_req_t) * 10.56 + blkif_reqs, GFP_KERNEL); 10.57 + pending_addrs[mmap_alloc] = kzalloc(sizeof(unsigned long) * 10.58 + mmap_pages, GFP_KERNEL); 10.59 + 10.60 + ret = -ENOMEM; 10.61 + if (!pending_reqs[mmap_alloc] || !pending_addrs[mmap_alloc]) { 10.62 + kfree(pending_reqs[mmap_alloc]); 10.63 + kfree(pending_addrs[mmap_alloc]); 10.64 + WPRINTK("%s: out of memory\n", __FUNCTION__); 10.65 + ret = -ENOMEM; 10.66 + goto done; 10.67 + } 10.68 + 10.69 + ret = 0; 10.70 + 10.71 DPRINTK("%s: reqs=%d, pages=%d, mmap_vstart=0x%lx\n", 10.72 __FUNCTION__, blkif_reqs, mmap_pages, 10.73 mmap_start[mmap_alloc].start); 10.74 @@ -774,7 +784,7 @@ static void req_increase(void) 10.75 DPRINTK("# MMAPs increased to %d\n",mmap_alloc); 10.76 done: 10.77 spin_unlock_irqrestore(&pending_free_lock, flags); 10.78 - 10.79 + return ret; 10.80 } 10.81 10.82 static void mmap_req_del(int mmap) 10.83 @@ -1394,7 +1404,13 @@ static int __init blkif_init(void) 10.84 return -ENODEV; 10.85 10.86 INIT_LIST_HEAD(&pending_free); 10.87 - for(i = 0; i < 2; i++) req_increase(); 10.88 + for(i = 0; i < 2; i++) { 10.89 + ret = req_increase(); 10.90 + if (ret) 10.91 + break; 10.92 + } 10.93 + if (i == 0) 10.94 + return ret; 10.95 10.96 tap_blkif_interface_init(); 10.97
11.1 --- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Tue Aug 08 19:07:32 2006 -0500 11.2 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Wed Aug 09 18:04:20 2006 +0100 11.3 @@ -1306,7 +1306,9 @@ static int __init netback_init(void) 11.4 net_timer.function = net_alarm; 11.5 11.6 page = balloon_alloc_empty_page_range(MAX_PENDING_REQS); 11.7 - BUG_ON(page == NULL); 11.8 + if (page == NULL) 11.9 + return -ENOMEM; 11.10 + 11.11 mmap_vstart = (unsigned long)pfn_to_kaddr(page_to_pfn(page)); 11.12 11.13 for (i = 0; i < MAX_PENDING_REQS; i++) {
12.1 --- a/linux-2.6-xen-sparse/drivers/xen/pciback/Makefile Tue Aug 08 19:07:32 2006 -0500 12.2 +++ b/linux-2.6-xen-sparse/drivers/xen/pciback/Makefile Wed Aug 09 18:04:20 2006 +0100 12.3 @@ -7,6 +7,7 @@ pciback-y += conf_space.o conf_space_hea 12.4 conf_space_capability_pm.o \ 12.5 conf_space_quirks.o 12.6 pciback-$(CONFIG_XEN_PCIDEV_BACKEND_VPCI) += vpci.o 12.7 +pciback-$(CONFIG_XEN_PCIDEV_BACKEND_SLOT) += slot.o 12.8 pciback-$(CONFIG_XEN_PCIDEV_BACKEND_PASS) += passthrough.o 12.9 12.10 ifeq ($(CONFIG_XEN_PCIDEV_BE_DEBUG),y)
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 13.2 +++ b/linux-2.6-xen-sparse/drivers/xen/pciback/slot.c Wed Aug 09 18:04:20 2006 +0100 13.3 @@ -0,0 +1,151 @@ 13.4 +/* 13.5 + * PCI Backend - Provides a Virtual PCI bus (with real devices) 13.6 + * to the frontend 13.7 + * 13.8 + * Author: Ryan Wilson <hap9@epoch.ncsc.mil> (vpci.c) 13.9 + * Author: Tristan Gingold <tristan.gingold@bull.net>, from vpci.c 13.10 + */ 13.11 + 13.12 +#include <linux/list.h> 13.13 +#include <linux/slab.h> 13.14 +#include <linux/pci.h> 13.15 +#include <linux/spinlock.h> 13.16 +#include "pciback.h" 13.17 + 13.18 +/* There are at most 32 slots in a pci bus. */ 13.19 +#define PCI_SLOT_MAX 32 13.20 + 13.21 +#define PCI_BUS_NBR 2 13.22 + 13.23 +struct slot_dev_data { 13.24 + /* Access to dev_list must be protected by lock */ 13.25 + struct pci_dev *slots[PCI_BUS_NBR][PCI_SLOT_MAX]; 13.26 + spinlock_t lock; 13.27 +}; 13.28 + 13.29 +struct pci_dev *pciback_get_pci_dev(struct pciback_device *pdev, 13.30 + unsigned int domain, unsigned int bus, 13.31 + unsigned int devfn) 13.32 +{ 13.33 + struct pci_dev *dev = NULL; 13.34 + struct slot_dev_data *slot_dev = pdev->pci_dev_data; 13.35 + unsigned long flags; 13.36 + 13.37 + if (domain != 0 || PCI_FUNC(devfn) != 0) 13.38 + return NULL; 13.39 + 13.40 + if (PCI_SLOT(devfn) >= PCI_SLOT_MAX || bus >= PCI_BUS_NBR) 13.41 + return NULL; 13.42 + 13.43 + spin_lock_irqsave(&slot_dev->lock, flags); 13.44 + dev = slot_dev->slots[bus][PCI_SLOT(devfn)]; 13.45 + spin_unlock_irqrestore(&slot_dev->lock, flags); 13.46 + 13.47 + return dev; 13.48 +} 13.49 + 13.50 +int pciback_add_pci_dev(struct pciback_device *pdev, struct pci_dev *dev) 13.51 +{ 13.52 + int err = 0, slot, bus; 13.53 + struct slot_dev_data *slot_dev = pdev->pci_dev_data; 13.54 + unsigned long flags; 13.55 + 13.56 + if ((dev->class >> 24) == PCI_BASE_CLASS_BRIDGE) { 13.57 + err = -EFAULT; 13.58 + xenbus_dev_fatal(pdev->xdev, err, 13.59 + "Can't export bridges on the virtual PCI bus"); 13.60 + goto out; 13.61 + } 13.62 + 13.63 + spin_lock_irqsave(&slot_dev->lock, flags); 13.64 + 13.65 + /* Assign to a new slot on the virtual PCI bus */ 13.66 + for (bus = 0; bus < PCI_BUS_NBR; bus++) 13.67 + for (slot = 0; slot < PCI_SLOT_MAX; slot++) { 13.68 + if (slot_dev->slots[bus][slot] == NULL) { 13.69 + printk(KERN_INFO 13.70 + "pciback: slot: %s: assign to virtual slot %d, bus %d\n", 13.71 + pci_name(dev), slot, bus); 13.72 + slot_dev->slots[bus][slot] = dev; 13.73 + goto unlock; 13.74 + } 13.75 + } 13.76 + 13.77 + err = -ENOMEM; 13.78 + xenbus_dev_fatal(pdev->xdev, err, 13.79 + "No more space on root virtual PCI bus"); 13.80 + 13.81 + unlock: 13.82 + spin_unlock_irqrestore(&slot_dev->lock, flags); 13.83 + out: 13.84 + return err; 13.85 +} 13.86 + 13.87 +void pciback_release_pci_dev(struct pciback_device *pdev, struct pci_dev *dev) 13.88 +{ 13.89 + int slot, bus; 13.90 + struct slot_dev_data *slot_dev = pdev->pci_dev_data; 13.91 + struct pci_dev *found_dev = NULL; 13.92 + unsigned long flags; 13.93 + 13.94 + spin_lock_irqsave(&slot_dev->lock, flags); 13.95 + 13.96 + for (bus = 0; bus < PCI_BUS_NBR; bus++) 13.97 + for (slot = 0; slot < PCI_SLOT_MAX; slot++) { 13.98 + if (slot_dev->slots[bus][slot] == dev) { 13.99 + slot_dev->slots[bus][slot] = NULL; 13.100 + found_dev = dev; 13.101 + goto out; 13.102 + } 13.103 + } 13.104 + 13.105 + out: 13.106 + spin_unlock_irqrestore(&slot_dev->lock, flags); 13.107 + 13.108 + if (found_dev) 13.109 + pcistub_put_pci_dev(found_dev); 13.110 +} 13.111 + 13.112 +int pciback_init_devices(struct pciback_device *pdev) 13.113 +{ 13.114 + int slot, bus; 13.115 + struct slot_dev_data *slot_dev; 13.116 + 13.117 + slot_dev = kmalloc(sizeof(*slot_dev), GFP_KERNEL); 13.118 + if (!slot_dev) 13.119 + return -ENOMEM; 13.120 + 13.121 + spin_lock_init(&slot_dev->lock); 13.122 + 13.123 + for (bus = 0; bus < PCI_BUS_NBR; bus++) 13.124 + for (slot = 0; slot < PCI_SLOT_MAX; slot++) 13.125 + slot_dev->slots[bus][slot] = NULL; 13.126 + 13.127 + pdev->pci_dev_data = slot_dev; 13.128 + 13.129 + return 0; 13.130 +} 13.131 + 13.132 +int pciback_publish_pci_roots(struct pciback_device *pdev, 13.133 + publish_pci_root_cb publish_cb) 13.134 +{ 13.135 + /* The Virtual PCI bus has only one root */ 13.136 + return publish_cb(pdev, 0, 0); 13.137 +} 13.138 + 13.139 +void pciback_release_devices(struct pciback_device *pdev) 13.140 +{ 13.141 + int slot, bus; 13.142 + struct slot_dev_data *slot_dev = pdev->pci_dev_data; 13.143 + struct pci_dev *dev; 13.144 + 13.145 + for (bus = 0; bus < PCI_BUS_NBR; bus++) 13.146 + for (slot = 0; slot < PCI_SLOT_MAX; slot++) { 13.147 + dev = slot_dev->slots[bus][slot]; 13.148 + if (dev != NULL) 13.149 + pcistub_put_pci_dev(dev); 13.150 + } 13.151 + 13.152 + kfree(slot_dev); 13.153 + pdev->pci_dev_data = NULL; 13.154 +}
14.1 --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/mmu_context.h Tue Aug 08 19:07:32 2006 -0500 14.2 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/mmu_context.h Wed Aug 09 18:04:20 2006 +0100 14.3 @@ -51,7 +51,8 @@ static inline void switch_mm(struct mm_s 14.4 struct mmuext_op _op[2], *op = _op; 14.5 14.6 if (likely(prev != next)) { 14.7 - BUG_ON(!test_bit(PG_pinned, &virt_to_page(next->pgd)->flags)); 14.8 + BUG_ON(!xen_feature(XENFEAT_writable_page_tables) && 14.9 + !test_bit(PG_pinned, &virt_to_page(next->pgd)->flags)); 14.10 14.11 /* stop flush ipis for the previous mm */ 14.12 cpu_clear(cpu, prev->cpu_vm_mask);
15.1 --- a/tools/Makefile Tue Aug 08 19:07:32 2006 -0500 15.2 +++ b/tools/Makefile Wed Aug 09 18:04:20 2006 +0100 15.3 @@ -8,7 +8,7 @@ SUBDIRS-y += misc 15.4 SUBDIRS-y += examples 15.5 SUBDIRS-y += xentrace 15.6 SUBDIRS-$(CONFIG_XCUTILS) += xcutils 15.7 -SUBDIRS-y += firmware 15.8 +SUBDIRS-$(CONFIG_X86) += firmware 15.9 SUBDIRS-y += security 15.10 SUBDIRS-y += console 15.11 SUBDIRS-y += xenmon
16.1 --- a/tools/examples/xend-config.sxp Tue Aug 08 19:07:32 2006 -0500 16.2 +++ b/tools/examples/xend-config.sxp Wed Aug 09 18:04:20 2006 +0100 16.3 @@ -54,7 +54,7 @@ 16.4 # (xend-relocation-hosts-allow '^localhost$ ^.*\.example\.org$') 16.5 # 16.6 #(xend-relocation-hosts-allow '') 16.7 -(xend-relocation-hosts-allow '^localhost$') 16.8 +(xend-relocation-hosts-allow '^localhost$ ^localhost\.localdomain$') 16.9 16.10 # The limit (in kilobytes) on the size of the console buffer 16.11 #(console-limit 1024)
17.1 --- a/tools/examples/xmexample.hvm Tue Aug 08 19:07:32 2006 -0500 17.2 +++ b/tools/examples/xmexample.hvm Wed Aug 09 18:04:20 2006 +0100 17.3 @@ -130,6 +130,10 @@ vnc=1 17.4 #vncdisplay=1 17.5 17.6 #---------------------------------------------------------------------------- 17.7 +# try to find an unused port for the VNC server, default = 1 17.8 +#vncunused=1 17.9 + 17.10 +#---------------------------------------------------------------------------- 17.11 # enable spawning vncviewer for domain's console 17.12 # (only valid when vnc=1), default = 0 17.13 #vncconsole=0
18.1 --- a/tools/firmware/Makefile Tue Aug 08 19:07:32 2006 -0500 18.2 +++ b/tools/firmware/Makefile Wed Aug 09 18:04:20 2006 +0100 18.3 @@ -30,7 +30,7 @@ all: 18.4 .PHONY: install 18.5 install: all 18.6 [ -d $(INSTALL_DIR) ] || install -d -m0755 $(INSTALL_DIR) 18.7 - install -m0644 $(TARGET) $(INSTALL_DIR) 18.8 + [ ! -e $(TARGET) ] || install -m0644 $(TARGET) $(INSTALL_DIR) 18.9 18.10 .PHONY: clean 18.11 clean:
19.1 --- a/tools/ioemu/patches/domain-destroy Tue Aug 08 19:07:32 2006 -0500 19.2 +++ b/tools/ioemu/patches/domain-destroy Wed Aug 09 18:04:20 2006 +0100 19.3 @@ -1,7 +1,7 @@ 19.4 Index: ioemu/monitor.c 19.5 =================================================================== 19.6 ---- ioemu.orig/monitor.c 2006-08-06 02:22:01.487319736 +0100 19.7 -+++ ioemu/monitor.c 2006-08-06 02:23:02.269544103 +0100 19.8 +--- ioemu.orig/monitor.c 2006-08-08 11:27:48.555190337 +0100 19.9 ++++ ioemu/monitor.c 2006-08-08 11:27:53.984584612 +0100 19.10 @@ -308,6 +308,7 @@ 19.11 19.12 static void do_quit(void) 19.13 @@ -12,10 +12,10 @@ Index: ioemu/monitor.c 19.14 19.15 Index: ioemu/target-i386-dm/helper2.c 19.16 =================================================================== 19.17 ---- ioemu.orig/target-i386-dm/helper2.c 2006-08-06 02:22:59.251880493 +0100 19.18 -+++ ioemu/target-i386-dm/helper2.c 2006-08-06 02:23:02.270543991 +0100 19.19 -@@ -483,5 +483,25 @@ 19.20 - shared_page->vcpu_iodata[send_vcpu].dm_eport); 19.21 +--- ioemu.orig/target-i386-dm/helper2.c 2006-08-08 11:27:53.063687351 +0100 19.22 ++++ ioemu/target-i386-dm/helper2.c 2006-08-08 11:27:54.011581601 +0100 19.23 +@@ -488,5 +488,25 @@ 19.24 + xc_evtchn_notify(xce_handle, ioreq_local_port[send_vcpu]); 19.25 } 19.26 } 19.27 + destroy_hvm_domain(); 19.28 @@ -42,8 +42,8 @@ Index: ioemu/target-i386-dm/helper2.c 19.29 +} 19.30 Index: ioemu/vl.h 19.31 =================================================================== 19.32 ---- ioemu.orig/vl.h 2006-08-06 02:22:59.255880047 +0100 19.33 -+++ ioemu/vl.h 2006-08-06 02:23:02.271543880 +0100 19.34 +--- ioemu.orig/vl.h 2006-08-08 11:27:53.067686905 +0100 19.35 ++++ ioemu/vl.h 2006-08-08 11:27:54.061576023 +0100 19.36 @@ -1189,4 +1189,7 @@ 19.37 void kqemu_record_dump(void); 19.38
20.1 --- a/tools/ioemu/patches/domain-reset Tue Aug 08 19:07:32 2006 -0500 20.2 +++ b/tools/ioemu/patches/domain-reset Wed Aug 09 18:04:20 2006 +0100 20.3 @@ -1,8 +1,8 @@ 20.4 Index: ioemu/target-i386-dm/helper2.c 20.5 =================================================================== 20.6 ---- ioemu.orig/target-i386-dm/helper2.c 2006-08-06 02:21:15.779415007 +0100 20.7 -+++ ioemu/target-i386-dm/helper2.c 2006-08-06 02:22:59.251880493 +0100 20.8 -@@ -123,6 +123,25 @@ 20.9 +--- ioemu.orig/target-i386-dm/helper2.c 2006-08-08 11:27:45.566523765 +0100 20.10 ++++ ioemu/target-i386-dm/helper2.c 2006-08-08 11:27:53.063687351 +0100 20.11 +@@ -127,6 +127,25 @@ 20.12 /* called from main_cpu_reset */ 20.13 void cpu_reset(CPUX86State *env) 20.14 { 20.15 @@ -28,7 +28,7 @@ Index: ioemu/target-i386-dm/helper2.c 20.16 } 20.17 20.18 void cpu_x86_close(CPUX86State *env) 20.19 -@@ -449,6 +468,10 @@ 20.20 +@@ -455,6 +474,10 @@ 20.21 if (vm_running) { 20.22 if (shutdown_requested) 20.23 break; 20.24 @@ -41,8 +41,8 @@ Index: ioemu/target-i386-dm/helper2.c 20.25 /* Wait up to 10 msec. */ 20.26 Index: ioemu/vl.c 20.27 =================================================================== 20.28 ---- ioemu.orig/vl.c 2006-08-06 02:22:56.618174081 +0100 20.29 -+++ ioemu/vl.c 2006-08-06 02:22:59.254880158 +0100 20.30 +--- ioemu.orig/vl.c 2006-08-08 11:27:52.994695048 +0100 20.31 ++++ ioemu/vl.c 2006-08-08 11:27:53.066687017 +0100 20.32 @@ -4948,7 +4948,7 @@ 20.33 } QEMUResetEntry; 20.34 20.35 @@ -54,8 +54,8 @@ Index: ioemu/vl.c 20.36 20.37 Index: ioemu/vl.h 20.38 =================================================================== 20.39 ---- ioemu.orig/vl.h 2006-08-06 02:22:01.501318175 +0100 20.40 -+++ ioemu/vl.h 2006-08-06 02:22:59.255880047 +0100 20.41 +--- ioemu.orig/vl.h 2006-08-08 11:27:48.757167803 +0100 20.42 ++++ ioemu/vl.h 2006-08-08 11:27:53.067686905 +0100 20.43 @@ -130,6 +130,7 @@ 20.44 20.45 void qemu_register_reset(QEMUResetHandler *func, void *opaque);
21.1 --- a/tools/ioemu/patches/domain-timeoffset Tue Aug 08 19:07:32 2006 -0500 21.2 +++ b/tools/ioemu/patches/domain-timeoffset Wed Aug 09 18:04:20 2006 +0100 21.3 @@ -1,7 +1,7 @@ 21.4 Index: ioemu/hw/mc146818rtc.c 21.5 =================================================================== 21.6 ---- ioemu.orig/hw/mc146818rtc.c 2006-08-07 17:44:43.593604340 +0100 21.7 -+++ ioemu/hw/mc146818rtc.c 2006-08-07 17:44:47.594168708 +0100 21.8 +--- ioemu.orig/hw/mc146818rtc.c 2006-08-09 15:04:17.857242121 +0100 21.9 ++++ ioemu/hw/mc146818rtc.c 2006-08-09 15:04:24.588603423 +0100 21.10 @@ -178,10 +178,27 @@ 21.11 } 21.12 } 21.13 @@ -46,8 +46,8 @@ Index: ioemu/hw/mc146818rtc.c 21.14 static void rtc_copy_date(RTCState *s) 21.15 Index: ioemu/hw/pc.c 21.16 =================================================================== 21.17 ---- ioemu.orig/hw/pc.c 2006-08-07 17:44:47.324198106 +0100 21.18 -+++ ioemu/hw/pc.c 2006-08-07 17:44:54.830380715 +0100 21.19 +--- ioemu.orig/hw/pc.c 2006-08-09 15:04:24.316629266 +0100 21.20 ++++ ioemu/hw/pc.c 2006-08-09 15:04:24.589603328 +0100 21.21 @@ -159,7 +159,7 @@ 21.22 } 21.23 21.24 @@ -117,8 +117,8 @@ Index: ioemu/hw/pc.c 21.25 QEMUMachine pc_machine = { 21.26 Index: ioemu/vl.c 21.27 =================================================================== 21.28 ---- ioemu.orig/vl.c 2006-08-07 17:44:47.464182863 +0100 21.29 -+++ ioemu/vl.c 2006-08-07 17:44:54.830380715 +0100 21.30 +--- ioemu.orig/vl.c 2006-08-09 15:04:24.457615869 +0100 21.31 ++++ ioemu/vl.c 2006-08-09 15:04:24.592603043 +0100 21.32 @@ -163,6 +163,8 @@ 21.33 21.34 int xc_handle; 21.35 @@ -174,8 +174,8 @@ Index: ioemu/vl.c 21.36 if (usb_enabled) { 21.37 Index: ioemu/vl.h 21.38 =================================================================== 21.39 ---- ioemu.orig/vl.h 2006-08-07 17:44:47.329197562 +0100 21.40 -+++ ioemu/vl.h 2006-08-07 17:44:54.830380715 +0100 21.41 +--- ioemu.orig/vl.h 2006-08-09 15:04:24.321628791 +0100 21.42 ++++ ioemu/vl.h 2006-08-09 15:04:24.593602948 +0100 21.43 @@ -575,7 +575,7 @@ 21.44 int boot_device, 21.45 DisplayState *ds, const char **fd_filename, int snapshot,
22.1 --- a/tools/ioemu/patches/qemu-target-i386-dm Tue Aug 08 19:07:32 2006 -0500 22.2 +++ b/tools/ioemu/patches/qemu-target-i386-dm Wed Aug 09 18:04:20 2006 +0100 22.3 @@ -1,7 +1,7 @@ 22.4 Index: ioemu/Makefile.target 22.5 =================================================================== 22.6 ---- ioemu.orig/Makefile.target 2006-08-06 02:14:09.794902973 +0100 22.7 -+++ ioemu/Makefile.target 2006-08-06 02:21:42.270461924 +0100 22.8 +--- ioemu.orig/Makefile.target 2006-08-08 11:24:33.479955101 +0100 22.9 ++++ ioemu/Makefile.target 2006-08-08 11:24:39.008338255 +0100 22.10 @@ -62,6 +62,8 @@ 22.11 QEMU_SYSTEM=qemu-fast 22.12 endif 22.13 @@ -32,8 +32,8 @@ Index: ioemu/Makefile.target 22.14 DEFINES += -DHAS_AUDIO 22.15 Index: ioemu/configure 22.16 =================================================================== 22.17 ---- ioemu.orig/configure 2006-08-06 02:14:09.795902861 +0100 22.18 -+++ ioemu/configure 2006-08-06 02:15:01.771108621 +0100 22.19 +--- ioemu.orig/configure 2006-08-08 11:24:33.480954990 +0100 22.20 ++++ ioemu/configure 2006-08-08 11:24:38.122437102 +0100 22.21 @@ -373,6 +373,8 @@ 22.22 if [ "$user" = "yes" ] ; then 22.23 target_list="i386-user arm-user armeb-user sparc-user ppc-user mips-user mipsel-user $target_list" 22.24 @@ -45,8 +45,8 @@ Index: ioemu/configure 22.25 fi 22.26 Index: ioemu/monitor.c 22.27 =================================================================== 22.28 ---- ioemu.orig/monitor.c 2006-08-06 02:14:49.574468309 +0100 22.29 -+++ ioemu/monitor.c 2006-08-06 02:21:16.172371202 +0100 22.30 +--- ioemu.orig/monitor.c 2006-08-08 11:24:33.484954543 +0100 22.31 ++++ ioemu/monitor.c 2006-08-08 11:24:39.253310921 +0100 22.32 @@ -1262,6 +1262,10 @@ 22.33 "", "show profiling information", }, 22.34 { "capture", "", do_info_capture, 22.35 @@ -60,8 +60,8 @@ Index: ioemu/monitor.c 22.36 22.37 Index: ioemu/vl.c 22.38 =================================================================== 22.39 ---- ioemu.orig/vl.c 2006-08-06 02:14:09.802902081 +0100 22.40 -+++ ioemu/vl.c 2006-08-06 02:21:16.369349244 +0100 22.41 +--- ioemu.orig/vl.c 2006-08-08 11:24:33.486954320 +0100 22.42 ++++ ioemu/vl.c 2006-08-08 11:24:39.454288496 +0100 22.43 @@ -87,7 +87,7 @@ 22.44 22.45 #include "exec-all.h" 22.46 @@ -98,8 +98,8 @@ Index: ioemu/vl.c 22.47 { 22.48 Index: ioemu/vl.h 22.49 =================================================================== 22.50 ---- ioemu.orig/vl.h 2006-08-06 02:13:56.733359091 +0100 22.51 -+++ ioemu/vl.h 2006-08-06 02:21:16.369349244 +0100 22.52 +--- ioemu.orig/vl.h 2006-08-08 11:24:31.082222636 +0100 22.53 ++++ ioemu/vl.h 2006-08-08 11:24:39.454288496 +0100 22.54 @@ -37,6 +37,8 @@ 22.55 #include <unistd.h> 22.56 #include <fcntl.h> 22.57 @@ -132,7 +132,7 @@ Index: ioemu/vl.h 22.58 Index: ioemu/target-i386-dm/cpu.h 22.59 =================================================================== 22.60 --- /dev/null 1970-01-01 00:00:00.000000000 +0000 22.61 -+++ ioemu/target-i386-dm/cpu.h 2006-08-06 02:21:16.023387810 +0100 22.62 ++++ ioemu/target-i386-dm/cpu.h 2006-08-08 11:24:39.099328102 +0100 22.63 @@ -0,0 +1,86 @@ 22.64 +/* 22.65 + * i386 virtual CPU header 22.66 @@ -223,7 +223,7 @@ Index: ioemu/target-i386-dm/cpu.h 22.67 Index: ioemu/target-i386-dm/exec-dm.c 22.68 =================================================================== 22.69 --- /dev/null 1970-01-01 00:00:00.000000000 +0000 22.70 -+++ ioemu/target-i386-dm/exec-dm.c 2006-08-06 02:21:16.024387698 +0100 22.71 ++++ ioemu/target-i386-dm/exec-dm.c 2006-08-08 11:24:39.099328102 +0100 22.72 @@ -0,0 +1,516 @@ 22.73 +/* 22.74 + * virtual page mapping and translated block handling 22.75 @@ -744,8 +744,8 @@ Index: ioemu/target-i386-dm/exec-dm.c 22.76 Index: ioemu/target-i386-dm/helper2.c 22.77 =================================================================== 22.78 --- /dev/null 1970-01-01 00:00:00.000000000 +0000 22.79 -+++ ioemu/target-i386-dm/helper2.c 2006-08-06 02:21:15.779415007 +0100 22.80 -@@ -0,0 +1,464 @@ 22.81 ++++ ioemu/target-i386-dm/helper2.c 2006-08-08 11:24:44.888682140 +0100 22.82 +@@ -0,0 +1,469 @@ 22.83 +/* 22.84 + * i386 helpers (without register variable usage) 22.85 + * 22.86 @@ -830,6 +830,10 @@ Index: ioemu/target-i386-dm/helper2.c 22.87 +/* which vcpu we are serving */ 22.88 +int send_vcpu = 0; 22.89 + 22.90 ++//the evtchn port for polling the notification, 22.91 ++#define NR_CPUS 32 22.92 ++evtchn_port_t ioreq_local_port[NR_CPUS]; 22.93 ++ 22.94 +CPUX86State *cpu_x86_init(void) 22.95 +{ 22.96 + CPUX86State *env; 22.97 @@ -861,7 +865,7 @@ Index: ioemu/target-i386-dm/helper2.c 22.98 + fprintf(logfile, "bind interdomain ioctl error %d\n", errno); 22.99 + return NULL; 22.100 + } 22.101 -+ shared_page->vcpu_iodata[i].dm_eport = rc; 22.102 ++ ioreq_local_port[i] = rc; 22.103 + } 22.104 + } 22.105 + 22.106 @@ -913,8 +917,7 @@ Index: ioemu/target-i386-dm/helper2.c 22.107 + 22.108 + for (i = 0; i < vcpus; i++) { 22.109 + req = &(shared_page->vcpu_iodata[i].vp_ioreq); 22.110 -+ term_printf("vcpu %d: event port %d\n", i, 22.111 -+ shared_page->vcpu_iodata[i].vp_eport); 22.112 ++ term_printf("vcpu %d: event port %d\n", i, ioreq_local_port[i]); 22.113 + term_printf(" req state: %x, pvalid: %x, addr: %"PRIx64", " 22.114 + "data: %"PRIx64", count: %"PRIx64", size: %"PRIx64"\n", 22.115 + req->state, req->pdata_valid, req->addr, 22.116 @@ -933,6 +936,7 @@ Index: ioemu/target-i386-dm/helper2.c 22.117 + 22.118 + if (req->state == STATE_IOREQ_READY) { 22.119 + req->state = STATE_IOREQ_INPROCESS; 22.120 ++ rmb(); 22.121 + return req; 22.122 + } 22.123 + 22.124 @@ -955,7 +959,7 @@ Index: ioemu/target-i386-dm/helper2.c 22.125 + port = xc_evtchn_pending(xce_handle); 22.126 + if (port != -1) { 22.127 + for ( i = 0; i < vcpus; i++ ) 22.128 -+ if ( shared_page->vcpu_iodata[i].dm_eport == port ) 22.129 ++ if ( ioreq_local_port[i] == port ) 22.130 + break; 22.131 + 22.132 + if ( i == vcpus ) { 22.133 @@ -1176,8 +1180,10 @@ Index: ioemu/target-i386-dm/helper2.c 22.134 + } 22.135 + 22.136 + /* No state change if state = STATE_IORESP_HOOK */ 22.137 -+ if (req->state == STATE_IOREQ_INPROCESS) 22.138 ++ if (req->state == STATE_IOREQ_INPROCESS) { 22.139 ++ mb(); 22.140 + req->state = STATE_IORESP_READY; 22.141 ++ } 22.142 + env->send_event = 1; 22.143 + } 22.144 +} 22.145 @@ -1204,8 +1210,7 @@ Index: ioemu/target-i386-dm/helper2.c 22.146 + 22.147 + if (env->send_event) { 22.148 + env->send_event = 0; 22.149 -+ xc_evtchn_notify(xce_handle, 22.150 -+ shared_page->vcpu_iodata[send_vcpu].dm_eport); 22.151 ++ xc_evtchn_notify(xce_handle, ioreq_local_port[send_vcpu]); 22.152 + } 22.153 + } 22.154 + return 0; 22.155 @@ -1213,7 +1218,7 @@ Index: ioemu/target-i386-dm/helper2.c 22.156 Index: ioemu/target-i386-dm/i8259-dm.c 22.157 =================================================================== 22.158 --- /dev/null 1970-01-01 00:00:00.000000000 +0000 22.159 -+++ ioemu/target-i386-dm/i8259-dm.c 2006-08-06 02:15:01.777107952 +0100 22.160 ++++ ioemu/target-i386-dm/i8259-dm.c 2006-08-08 11:24:33.505952200 +0100 22.161 @@ -0,0 +1,107 @@ 22.162 +/* Xen 8259 stub for interrupt controller emulation 22.163 + * 22.164 @@ -1325,7 +1330,7 @@ Index: ioemu/target-i386-dm/i8259-dm.c 22.165 Index: ioemu/target-i386-dm/qemu-dm.debug 22.166 =================================================================== 22.167 --- /dev/null 1970-01-01 00:00:00.000000000 +0000 22.168 -+++ ioemu/target-i386-dm/qemu-dm.debug 2006-08-06 02:15:01.778107841 +0100 22.169 ++++ ioemu/target-i386-dm/qemu-dm.debug 2006-08-08 11:24:33.505952200 +0100 22.170 @@ -0,0 +1,5 @@ 22.171 +#!/bin/sh 22.172 + 22.173 @@ -1335,7 +1340,7 @@ Index: ioemu/target-i386-dm/qemu-dm.debu 22.174 Index: ioemu/target-i386-dm/qemu-ifup 22.175 =================================================================== 22.176 --- /dev/null 1970-01-01 00:00:00.000000000 +0000 22.177 -+++ ioemu/target-i386-dm/qemu-ifup 2006-08-06 02:15:01.778107841 +0100 22.178 ++++ ioemu/target-i386-dm/qemu-ifup 2006-08-08 11:24:33.505952200 +0100 22.179 @@ -0,0 +1,10 @@ 22.180 +#!/bin/sh 22.181 +
23.1 --- a/tools/ioemu/patches/series Tue Aug 08 19:07:32 2006 -0500 23.2 +++ b/tools/ioemu/patches/series Wed Aug 09 18:04:20 2006 +0100 23.3 @@ -34,8 +34,10 @@ vnc-fixes 23.4 vnc-start-vncviewer 23.5 vnc-title-domain-name 23.6 vnc-access-monitor-vt 23.7 +vnc-display-find-unused 23.8 xenstore-block-device-config 23.9 xenstore-write-vnc-port 23.10 qemu-allow-disable-sdl 23.11 qemu-fix-memset-args 23.12 qemu-fix-write-to-disk-synchronous 23.13 +xen-support-buffered-ioreqs
24.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 24.2 +++ b/tools/ioemu/patches/vnc-display-find-unused Wed Aug 09 18:04:20 2006 +0100 24.3 @@ -0,0 +1,128 @@ 24.4 +Index: ioemu/vnc.c 24.5 +=================================================================== 24.6 +--- ioemu.orig/vnc.c 2006-08-09 14:44:44.721942535 +0100 24.7 ++++ ioemu/vnc.c 2006-08-09 14:52:37.262165292 +0100 24.8 +@@ -1183,7 +1183,7 @@ 24.9 + } 24.10 + } 24.11 + 24.12 +-void vnc_display_init(DisplayState *ds, int display) 24.13 ++int vnc_display_init(DisplayState *ds, int display, int find_unused) 24.14 + { 24.15 + struct sockaddr_in addr; 24.16 + int reuse_addr, ret; 24.17 +@@ -1214,10 +1214,6 @@ 24.18 + exit(1); 24.19 + } 24.20 + 24.21 +- addr.sin_family = AF_INET; 24.22 +- addr.sin_port = htons(5900 + display); 24.23 +- memset(&addr.sin_addr, 0, sizeof(addr.sin_addr)); 24.24 +- 24.25 + reuse_addr = 1; 24.26 + ret = setsockopt(vs->lsock, SOL_SOCKET, SO_REUSEADDR, 24.27 + (const char *)&reuse_addr, sizeof(reuse_addr)); 24.28 +@@ -1226,7 +1222,16 @@ 24.29 + exit(1); 24.30 + } 24.31 + 24.32 ++ retry: 24.33 ++ addr.sin_family = AF_INET; 24.34 ++ addr.sin_port = htons(5900 + display); 24.35 ++ memset(&addr.sin_addr, 0, sizeof(addr.sin_addr)); 24.36 ++ 24.37 + if (bind(vs->lsock, (struct sockaddr *)&addr, sizeof(addr)) == -1) { 24.38 ++ if (find_unused && errno == EADDRINUSE) { 24.39 ++ display++; 24.40 ++ goto retry; 24.41 ++ } 24.42 + fprintf(stderr, "bind() failed\n"); 24.43 + exit(1); 24.44 + } 24.45 +@@ -1247,6 +1252,8 @@ 24.46 + vs->ds->dpy_refresh = vnc_dpy_refresh; 24.47 + 24.48 + vnc_dpy_resize(vs->ds, 640, 400); 24.49 ++ 24.50 ++ return display; 24.51 + } 24.52 + 24.53 + int vnc_start_viewer(int port) 24.54 +Index: ioemu/vl.c 24.55 +=================================================================== 24.56 +--- ioemu.orig/vl.c 2006-08-09 14:44:44.721942535 +0100 24.57 ++++ ioemu/vl.c 2006-08-09 14:52:06.783905832 +0100 24.58 +@@ -121,6 +121,7 @@ 24.59 + static DisplayState display_state; 24.60 + int nographic; 24.61 + int vncviewer; 24.62 ++int vncunused; 24.63 + const char* keyboard_layout = NULL; 24.64 + int64_t ticks_per_sec; 24.65 + int boot_device = 'c'; 24.66 +@@ -5342,6 +5343,7 @@ 24.67 + "-loadvm file start right away with a saved state (loadvm in monitor)\n" 24.68 + "-vnc display start a VNC server on display\n" 24.69 + "-vncviewer start a vncviewer process for this domain\n" 24.70 ++ "-vncunused bind the VNC server to an unused port\n" 24.71 + "-timeoffset time offset (in seconds) from local time\n" 24.72 + "-acpi disable or enable ACPI of HVM domain \n" 24.73 + "\n" 24.74 +@@ -5431,6 +5433,7 @@ 24.75 + QEMU_OPTION_timeoffset, 24.76 + QEMU_OPTION_acpi, 24.77 + QEMU_OPTION_vncviewer, 24.78 ++ QEMU_OPTION_vncunused, 24.79 + }; 24.80 + 24.81 + typedef struct QEMUOption { 24.82 +@@ -5506,6 +5509,7 @@ 24.83 + { "smp", HAS_ARG, QEMU_OPTION_smp }, 24.84 + { "vnc", HAS_ARG, QEMU_OPTION_vnc }, 24.85 + { "vncviewer", 0, QEMU_OPTION_vncviewer }, 24.86 ++ { "vncunused", 0, QEMU_OPTION_vncunused }, 24.87 + 24.88 + /* temporary options */ 24.89 + { "usb", 0, QEMU_OPTION_usb }, 24.90 +@@ -5873,6 +5877,7 @@ 24.91 + snapshot = 0; 24.92 + nographic = 0; 24.93 + vncviewer = 0; 24.94 ++ vncunused = 0; 24.95 + kernel_filename = NULL; 24.96 + kernel_cmdline = ""; 24.97 + #ifdef TARGET_PPC 24.98 +@@ -6270,6 +6275,11 @@ 24.99 + case QEMU_OPTION_vncviewer: 24.100 + vncviewer++; 24.101 + break; 24.102 ++ case QEMU_OPTION_vncunused: 24.103 ++ vncunused++; 24.104 ++ if (vnc_display == -1) 24.105 ++ vnc_display = -2; 24.106 ++ break; 24.107 + } 24.108 + } 24.109 + } 24.110 +@@ -6465,7 +6475,7 @@ 24.111 + if (nographic) { 24.112 + dumb_display_init(ds); 24.113 + } else if (vnc_display != -1) { 24.114 +- vnc_display_init(ds, vnc_display); 24.115 ++ vnc_display = vnc_display_init(ds, vnc_display, vncunused); 24.116 + if (vncviewer) 24.117 + vnc_start_viewer(vnc_display); 24.118 + } else { 24.119 +Index: ioemu/vl.h 24.120 +=================================================================== 24.121 +--- ioemu.orig/vl.h 2006-08-09 14:44:44.721942535 +0100 24.122 ++++ ioemu/vl.h 2006-08-09 14:52:06.783905832 +0100 24.123 +@@ -784,7 +784,7 @@ 24.124 + void cocoa_display_init(DisplayState *ds, int full_screen); 24.125 + 24.126 + /* vnc.c */ 24.127 +-void vnc_display_init(DisplayState *ds, int display); 24.128 ++int vnc_display_init(DisplayState *ds, int display, int find_unused); 24.129 + int vnc_start_viewer(int port); 24.130 + 24.131 + /* ide.c */
25.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 25.2 +++ b/tools/ioemu/patches/xen-support-buffered-ioreqs Wed Aug 09 18:04:20 2006 +0100 25.3 @@ -0,0 +1,150 @@ 25.4 +Index: ioemu/vl.c 25.5 +=================================================================== 25.6 +--- ioemu.orig/vl.c 2006-08-09 15:04:25.583508863 +0100 25.7 ++++ ioemu/vl.c 2006-08-09 15:04:26.034465993 +0100 25.8 +@@ -5838,6 +5838,7 @@ 25.9 + unsigned long nr_pages; 25.10 + xen_pfn_t *page_array; 25.11 + extern void *shared_page; 25.12 ++ extern void *buffered_io_page; 25.13 + 25.14 + char qemu_dm_logfilename[64]; 25.15 + 25.16 +@@ -6388,12 +6389,17 @@ 25.17 + 25.18 + phys_ram_base = xc_map_foreign_batch(xc_handle, domid, 25.19 + PROT_READ|PROT_WRITE, page_array, 25.20 +- nr_pages - 1); 25.21 ++ nr_pages - 3); 25.22 + if (phys_ram_base == 0) { 25.23 + fprintf(logfile, "xc_map_foreign_batch returned error %d\n", errno); 25.24 + exit(-1); 25.25 + } 25.26 + 25.27 ++ /* not yet add for IA64 */ 25.28 ++ buffered_io_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE, 25.29 ++ PROT_READ|PROT_WRITE, 25.30 ++ page_array[nr_pages - 3]); 25.31 ++ 25.32 + shared_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE, 25.33 + PROT_READ|PROT_WRITE, 25.34 + page_array[nr_pages - 1]); 25.35 +Index: ioemu/target-i386-dm/helper2.c 25.36 +=================================================================== 25.37 +--- ioemu.orig/target-i386-dm/helper2.c 2006-08-09 15:04:24.105649313 +0100 25.38 ++++ ioemu/target-i386-dm/helper2.c 2006-08-09 15:04:26.040465422 +0100 25.39 +@@ -76,6 +76,10 @@ 25.40 + 25.41 + shared_iopage_t *shared_page = NULL; 25.42 + 25.43 ++#define BUFFER_IO_MAX_DELAY 100 25.44 ++buffered_iopage_t *buffered_io_page = NULL; 25.45 ++QEMUTimer *buffered_io_timer; 25.46 ++ 25.47 + /* the evtchn fd for polling */ 25.48 + int xce_handle = -1; 25.49 + 25.50 +@@ -419,36 +423,68 @@ 25.51 + req->u.data = tmp1; 25.52 + } 25.53 + 25.54 ++void __handle_ioreq(CPUState *env, ioreq_t *req) 25.55 ++{ 25.56 ++ if (!req->pdata_valid && req->dir == IOREQ_WRITE && req->size != 4) 25.57 ++ req->u.data &= (1UL << (8 * req->size)) - 1; 25.58 ++ 25.59 ++ switch (req->type) { 25.60 ++ case IOREQ_TYPE_PIO: 25.61 ++ cpu_ioreq_pio(env, req); 25.62 ++ break; 25.63 ++ case IOREQ_TYPE_COPY: 25.64 ++ cpu_ioreq_move(env, req); 25.65 ++ break; 25.66 ++ case IOREQ_TYPE_AND: 25.67 ++ cpu_ioreq_and(env, req); 25.68 ++ break; 25.69 ++ case IOREQ_TYPE_OR: 25.70 ++ cpu_ioreq_or(env, req); 25.71 ++ break; 25.72 ++ case IOREQ_TYPE_XOR: 25.73 ++ cpu_ioreq_xor(env, req); 25.74 ++ break; 25.75 ++ default: 25.76 ++ hw_error("Invalid ioreq type 0x%x\n", req->type); 25.77 ++ } 25.78 ++} 25.79 ++ 25.80 ++void __handle_buffered_iopage(CPUState *env) 25.81 ++{ 25.82 ++ ioreq_t *req = NULL; 25.83 ++ 25.84 ++ if (!buffered_io_page) 25.85 ++ return; 25.86 ++ 25.87 ++ while (buffered_io_page->read_pointer != 25.88 ++ buffered_io_page->write_pointer) { 25.89 ++ req = &buffered_io_page->ioreq[buffered_io_page->read_pointer % 25.90 ++ IOREQ_BUFFER_SLOT_NUM]; 25.91 ++ 25.92 ++ __handle_ioreq(env, req); 25.93 ++ 25.94 ++ mb(); 25.95 ++ buffered_io_page->read_pointer++; 25.96 ++ } 25.97 ++} 25.98 ++ 25.99 ++void handle_buffered_io(void *opaque) 25.100 ++{ 25.101 ++ CPUState *env = opaque; 25.102 ++ 25.103 ++ __handle_buffered_iopage(env); 25.104 ++ qemu_mod_timer(buffered_io_timer, BUFFER_IO_MAX_DELAY + 25.105 ++ qemu_get_clock(rt_clock)); 25.106 ++} 25.107 ++ 25.108 + void cpu_handle_ioreq(void *opaque) 25.109 + { 25.110 + CPUState *env = opaque; 25.111 + ioreq_t *req = cpu_get_ioreq(); 25.112 + 25.113 ++ handle_buffered_io(env); 25.114 + if (req) { 25.115 +- if ((!req->pdata_valid) && (req->dir == IOREQ_WRITE)) { 25.116 +- if (req->size != 4) 25.117 +- req->u.data &= (1UL << (8 * req->size))-1; 25.118 +- } 25.119 +- 25.120 +- switch (req->type) { 25.121 +- case IOREQ_TYPE_PIO: 25.122 +- cpu_ioreq_pio(env, req); 25.123 +- break; 25.124 +- case IOREQ_TYPE_COPY: 25.125 +- cpu_ioreq_move(env, req); 25.126 +- break; 25.127 +- case IOREQ_TYPE_AND: 25.128 +- cpu_ioreq_and(env, req); 25.129 +- break; 25.130 +- case IOREQ_TYPE_OR: 25.131 +- cpu_ioreq_or(env, req); 25.132 +- break; 25.133 +- case IOREQ_TYPE_XOR: 25.134 +- cpu_ioreq_xor(env, req); 25.135 +- break; 25.136 +- default: 25.137 +- hw_error("Invalid ioreq type 0x%x\n", req->type); 25.138 +- } 25.139 ++ __handle_ioreq(env, req); 25.140 + 25.141 + /* No state change if state = STATE_IORESP_HOOK */ 25.142 + if (req->state == STATE_IOREQ_INPROCESS) { 25.143 +@@ -466,6 +502,10 @@ 25.144 + CPUState *env = cpu_single_env; 25.145 + int evtchn_fd = xc_evtchn_fd(xce_handle); 25.146 + 25.147 ++ buffered_io_timer = qemu_new_timer(rt_clock, handle_buffered_io, 25.148 ++ cpu_single_env); 25.149 ++ qemu_mod_timer(buffered_io_timer, qemu_get_clock(rt_clock)); 25.150 ++ 25.151 + qemu_set_fd_handler(evtchn_fd, cpu_handle_ioreq, NULL, env); 25.152 + 25.153 + env->send_event = 0;
26.1 --- a/tools/ioemu/patches/xenstore-block-device-config Tue Aug 08 19:07:32 2006 -0500 26.2 +++ b/tools/ioemu/patches/xenstore-block-device-config Wed Aug 09 18:04:20 2006 +0100 26.3 @@ -1,7 +1,7 @@ 26.4 Index: ioemu/Makefile.target 26.5 =================================================================== 26.6 ---- ioemu.orig/Makefile.target 2006-08-07 17:42:27.802386071 +0100 26.7 -+++ ioemu/Makefile.target 2006-08-07 17:42:28.683289358 +0100 26.8 +--- ioemu.orig/Makefile.target 2006-08-09 15:04:24.795583755 +0100 26.9 ++++ ioemu/Makefile.target 2006-08-09 15:04:25.373528824 +0100 26.10 @@ -358,6 +358,7 @@ 26.11 VL_OBJS+= cirrus_vga.o mixeng.o parallel.o acpi.o piix_pci.o 26.12 VL_OBJS+= usb-uhci.o 26.13 @@ -13,7 +13,7 @@ Index: ioemu/Makefile.target 26.14 Index: ioemu/xenstore.c 26.15 =================================================================== 26.16 --- /dev/null 1970-01-01 00:00:00.000000000 +0000 26.17 -+++ ioemu/xenstore.c 2006-08-07 17:42:28.684289249 +0100 26.18 ++++ ioemu/xenstore.c 2006-08-09 15:04:25.374528729 +0100 26.19 @@ -0,0 +1,187 @@ 26.20 +/* 26.21 + * This file is subject to the terms and conditions of the GNU General 26.22 @@ -204,9 +204,9 @@ Index: ioemu/xenstore.c 26.23 +} 26.24 Index: ioemu/vl.c 26.25 =================================================================== 26.26 ---- ioemu.orig/vl.c 2006-08-07 17:42:28.393320909 +0100 26.27 -+++ ioemu/vl.c 2006-08-07 17:42:28.687288922 +0100 26.28 -@@ -5242,9 +5242,11 @@ 26.29 +--- ioemu.orig/vl.c 2006-08-09 15:04:25.312534622 +0100 26.30 ++++ ioemu/vl.c 2006-08-09 15:04:25.377528443 +0100 26.31 +@@ -5243,9 +5243,11 @@ 26.32 "Standard options:\n" 26.33 "-M machine select emulated machine (-M ? for list)\n" 26.34 "-fda/-fdb file use 'file' as floppy disk 0/1 image\n" 26.35 @@ -218,7 +218,7 @@ Index: ioemu/vl.c 26.36 "-boot [a|c|d] boot on floppy (a), hard disk (c) or CD-ROM (d)\n" 26.37 "-snapshot write to temporary files instead of disk image files\n" 26.38 #ifdef TARGET_I386 26.39 -@@ -5370,11 +5372,13 @@ 26.40 +@@ -5372,11 +5374,13 @@ 26.41 QEMU_OPTION_M, 26.42 QEMU_OPTION_fda, 26.43 QEMU_OPTION_fdb, 26.44 @@ -232,7 +232,7 @@ Index: ioemu/vl.c 26.45 QEMU_OPTION_boot, 26.46 QEMU_OPTION_snapshot, 26.47 #ifdef TARGET_I386 26.48 -@@ -5445,11 +5449,13 @@ 26.49 +@@ -5448,11 +5452,13 @@ 26.50 { "M", HAS_ARG, QEMU_OPTION_M }, 26.51 { "fda", HAS_ARG, QEMU_OPTION_fda }, 26.52 { "fdb", HAS_ARG, QEMU_OPTION_fdb }, 26.53 @@ -246,7 +246,7 @@ Index: ioemu/vl.c 26.54 { "boot", HAS_ARG, QEMU_OPTION_boot }, 26.55 { "snapshot", 0, QEMU_OPTION_snapshot }, 26.56 #ifdef TARGET_I386 26.57 -@@ -5797,10 +5803,16 @@ 26.58 +@@ -5801,10 +5807,16 @@ 26.59 #ifdef CONFIG_GDBSTUB 26.60 int use_gdbstub, gdbstub_port; 26.61 #endif 26.62 @@ -265,7 +265,7 @@ Index: ioemu/vl.c 26.63 const char *kernel_filename, *kernel_cmdline; 26.64 DisplayState *ds = &display_state; 26.65 int cyls, heads, secs, translation; 26.66 -@@ -5861,8 +5873,10 @@ 26.67 +@@ -5865,8 +5877,10 @@ 26.68 initrd_filename = NULL; 26.69 for(i = 0; i < MAX_FD; i++) 26.70 fd_filename[i] = NULL; 26.71 @@ -276,8 +276,8 @@ Index: ioemu/vl.c 26.72 ram_size = DEFAULT_RAM_SIZE * 1024 * 1024; 26.73 vga_ram_size = VGA_RAM_SIZE; 26.74 bios_size = BIOS_SIZE; 26.75 -@@ -5875,11 +5889,13 @@ 26.76 - vncviewer = 0; 26.77 +@@ -5880,11 +5894,13 @@ 26.78 + vncunused = 0; 26.79 kernel_filename = NULL; 26.80 kernel_cmdline = ""; 26.81 +#ifndef CONFIG_DM 26.82 @@ -290,7 +290,7 @@ Index: ioemu/vl.c 26.83 cyls = heads = secs = 0; 26.84 translation = BIOS_ATA_TRANSLATION_AUTO; 26.85 pstrcpy(monitor_device, sizeof(monitor_device), "vc"); 26.86 -@@ -5912,7 +5928,11 @@ 26.87 +@@ -5917,7 +5933,11 @@ 26.88 break; 26.89 r = argv[optind]; 26.90 if (r[0] != '-') { 26.91 @@ -302,7 +302,7 @@ Index: ioemu/vl.c 26.92 } else { 26.93 const QEMUOption *popt; 26.94 26.95 -@@ -5956,6 +5976,7 @@ 26.96 +@@ -5961,6 +5981,7 @@ 26.97 case QEMU_OPTION_initrd: 26.98 initrd_filename = optarg; 26.99 break; 26.100 @@ -310,7 +310,7 @@ Index: ioemu/vl.c 26.101 case QEMU_OPTION_hda: 26.102 case QEMU_OPTION_hdb: 26.103 case QEMU_OPTION_hdc: 26.104 -@@ -5968,6 +5989,7 @@ 26.105 +@@ -5973,6 +5994,7 @@ 26.106 cdrom_index = -1; 26.107 } 26.108 break; 26.109 @@ -318,7 +318,7 @@ Index: ioemu/vl.c 26.110 case QEMU_OPTION_snapshot: 26.111 snapshot = 1; 26.112 break; 26.113 -@@ -6020,11 +6042,13 @@ 26.114 +@@ -6025,11 +6047,13 @@ 26.115 case QEMU_OPTION_append: 26.116 kernel_cmdline = optarg; 26.117 break; 26.118 @@ -332,7 +332,7 @@ Index: ioemu/vl.c 26.119 case QEMU_OPTION_boot: 26.120 boot_device = optarg[0]; 26.121 if (boot_device != 'a' && 26.122 -@@ -6274,12 +6298,18 @@ 26.123 +@@ -6284,12 +6308,18 @@ 26.124 } 26.125 } 26.126 26.127 @@ -351,7 +351,7 @@ Index: ioemu/vl.c 26.128 if (!linux_boot && 26.129 hd_filename[0] == '\0' && 26.130 (cdrom_index >= 0 && hd_filename[cdrom_index] == '\0') && 26.131 -@@ -6293,6 +6323,7 @@ 26.132 +@@ -6303,6 +6333,7 @@ 26.133 else 26.134 boot_device = 'd'; 26.135 } 26.136 @@ -359,7 +359,7 @@ Index: ioemu/vl.c 26.137 26.138 setvbuf(stdout, NULL, _IOLBF, 0); 26.139 26.140 -@@ -6407,6 +6438,7 @@ 26.141 +@@ -6417,6 +6448,7 @@ 26.142 26.143 #endif /* !CONFIG_DM */ 26.144 26.145 @@ -367,7 +367,7 @@ Index: ioemu/vl.c 26.146 /* we always create the cdrom drive, even if no disk is there */ 26.147 bdrv_init(); 26.148 if (cdrom_index >= 0) { 26.149 -@@ -6433,6 +6465,7 @@ 26.150 +@@ -6443,6 +6475,7 @@ 26.151 } 26.152 } 26.153 } 26.154 @@ -375,7 +375,7 @@ Index: ioemu/vl.c 26.155 26.156 /* we always create at least one floppy disk */ 26.157 fd_table[0] = bdrv_new("fda"); 26.158 -@@ -6511,6 +6544,8 @@ 26.159 +@@ -6521,6 +6554,8 @@ 26.160 } 26.161 } 26.162 26.163 @@ -386,8 +386,8 @@ Index: ioemu/vl.c 26.164 kernel_filename, kernel_cmdline, initrd_filename, 26.165 Index: ioemu/monitor.c 26.166 =================================================================== 26.167 ---- ioemu.orig/monitor.c 2006-08-07 17:42:27.132461888 +0100 26.168 -+++ ioemu/monitor.c 2006-08-07 17:42:28.688288814 +0100 26.169 +--- ioemu.orig/monitor.c 2006-08-09 15:04:24.105649313 +0100 26.170 ++++ ioemu/monitor.c 2006-08-09 15:04:25.379528253 +0100 26.171 @@ -24,6 +24,7 @@ 26.172 #include "vl.h" 26.173 #include "disas.h" 26.174 @@ -416,8 +416,8 @@ Index: ioemu/monitor.c 26.175 int i; 26.176 Index: ioemu/block.c 26.177 =================================================================== 26.178 ---- ioemu.orig/block.c 2006-08-07 17:42:21.704076241 +0100 26.179 -+++ ioemu/block.c 2006-08-07 17:42:28.689288705 +0100 26.180 +--- ioemu.orig/block.c 2006-08-09 15:04:17.487277167 +0100 26.181 ++++ ioemu/block.c 2006-08-09 15:04:25.379528253 +0100 26.182 @@ -758,6 +758,7 @@ 26.183 static void raw_close(BlockDriverState *bs) 26.184 { 26.185 @@ -428,8 +428,8 @@ Index: ioemu/block.c 26.186 26.187 Index: ioemu/vl.h 26.188 =================================================================== 26.189 ---- ioemu.orig/vl.h 2006-08-07 17:42:28.394320800 +0100 26.190 -+++ ioemu/vl.h 2006-08-07 17:42:28.689288705 +0100 26.191 +--- ioemu.orig/vl.h 2006-08-09 15:04:25.313534527 +0100 26.192 ++++ ioemu/vl.h 2006-08-09 15:04:25.380528158 +0100 26.193 @@ -1184,6 +1184,8 @@ 26.194 void term_print_help(void); 26.195 void monitor_readline(const char *prompt, int is_password, 26.196 @@ -455,8 +455,8 @@ Index: ioemu/vl.h 26.197 extern char domain_name[]; 26.198 Index: ioemu/hw/ide.c 26.199 =================================================================== 26.200 ---- ioemu.orig/hw/ide.c 2006-08-07 17:42:27.552414361 +0100 26.201 -+++ ioemu/hw/ide.c 2006-08-07 17:42:28.691288487 +0100 26.202 +--- ioemu.orig/hw/ide.c 2006-08-09 15:04:24.524609503 +0100 26.203 ++++ ioemu/hw/ide.c 2006-08-09 15:04:25.381528063 +0100 26.204 @@ -1158,6 +1158,7 @@ 26.205 } else { 26.206 ide_atapi_cmd_error(s, SENSE_NOT_READY,
27.1 --- a/tools/ioemu/patches/xenstore-write-vnc-port Tue Aug 08 19:07:32 2006 -0500 27.2 +++ b/tools/ioemu/patches/xenstore-write-vnc-port Wed Aug 09 18:04:20 2006 +0100 27.3 @@ -1,7 +1,7 @@ 27.4 Index: ioemu/xenstore.c 27.5 =================================================================== 27.6 ---- ioemu.orig/xenstore.c 2006-08-07 17:42:28.684289249 +0100 27.7 -+++ ioemu/xenstore.c 2006-08-07 17:42:28.891266728 +0100 27.8 +--- ioemu.orig/xenstore.c 2006-08-09 15:04:25.374528729 +0100 27.9 ++++ ioemu/xenstore.c 2006-08-09 15:04:25.579509243 +0100 27.10 @@ -185,3 +185,31 @@ 27.11 free(image); 27.12 free(vec); 27.13 @@ -36,10 +36,10 @@ Index: ioemu/xenstore.c 27.14 +} 27.15 Index: ioemu/vl.c 27.16 =================================================================== 27.17 ---- ioemu.orig/vl.c 2006-08-07 17:42:28.687288922 +0100 27.18 -+++ ioemu/vl.c 2006-08-07 17:42:28.894266401 +0100 27.19 -@@ -6501,6 +6501,7 @@ 27.20 - vnc_display_init(ds, vnc_display); 27.21 +--- ioemu.orig/vl.c 2006-08-09 15:04:25.377528443 +0100 27.22 ++++ ioemu/vl.c 2006-08-09 15:04:25.583508863 +0100 27.23 +@@ -6511,6 +6511,7 @@ 27.24 + vnc_display = vnc_display_init(ds, vnc_display, vncunused); 27.25 if (vncviewer) 27.26 vnc_start_viewer(vnc_display); 27.27 + xenstore_write_vncport(vnc_display); 27.28 @@ -48,8 +48,8 @@ Index: ioemu/vl.c 27.29 sdl_display_init(ds, full_screen); 27.30 Index: ioemu/vl.h 27.31 =================================================================== 27.32 ---- ioemu.orig/vl.h 2006-08-07 17:42:28.689288705 +0100 27.33 -+++ ioemu/vl.h 2006-08-07 17:42:28.895266293 +0100 27.34 +--- ioemu.orig/vl.h 2006-08-09 15:04:25.380528158 +0100 27.35 ++++ ioemu/vl.h 2006-08-09 15:04:25.584508768 +0100 27.36 @@ -1203,6 +1203,7 @@ 27.37 int xenstore_fd(void); 27.38 void xenstore_process_event(void *opaque);
28.1 --- a/tools/ioemu/target-i386-dm/helper2.c Tue Aug 08 19:07:32 2006 -0500 28.2 +++ b/tools/ioemu/target-i386-dm/helper2.c Wed Aug 09 18:04:20 2006 +0100 28.3 @@ -76,12 +76,20 @@ int xc_handle; 28.4 28.5 shared_iopage_t *shared_page = NULL; 28.6 28.7 +#define BUFFER_IO_MAX_DELAY 100 28.8 +buffered_iopage_t *buffered_io_page = NULL; 28.9 +QEMUTimer *buffered_io_timer; 28.10 + 28.11 /* the evtchn fd for polling */ 28.12 int xce_handle = -1; 28.13 28.14 /* which vcpu we are serving */ 28.15 int send_vcpu = 0; 28.16 28.17 +//the evtchn port for polling the notification, 28.18 +#define NR_CPUS 32 28.19 +evtchn_port_t ioreq_local_port[NR_CPUS]; 28.20 + 28.21 CPUX86State *cpu_x86_init(void) 28.22 { 28.23 CPUX86State *env; 28.24 @@ -113,7 +121,7 @@ CPUX86State *cpu_x86_init(void) 28.25 fprintf(logfile, "bind interdomain ioctl error %d\n", errno); 28.26 return NULL; 28.27 } 28.28 - shared_page->vcpu_iodata[i].dm_eport = rc; 28.29 + ioreq_local_port[i] = rc; 28.30 } 28.31 } 28.32 28.33 @@ -184,8 +192,7 @@ void sp_info() 28.34 28.35 for (i = 0; i < vcpus; i++) { 28.36 req = &(shared_page->vcpu_iodata[i].vp_ioreq); 28.37 - term_printf("vcpu %d: event port %d\n", i, 28.38 - shared_page->vcpu_iodata[i].vp_eport); 28.39 + term_printf("vcpu %d: event port %d\n", i, ioreq_local_port[i]); 28.40 term_printf(" req state: %x, pvalid: %x, addr: %"PRIx64", " 28.41 "data: %"PRIx64", count: %"PRIx64", size: %"PRIx64"\n", 28.42 req->state, req->pdata_valid, req->addr, 28.43 @@ -204,6 +211,7 @@ static ioreq_t *__cpu_get_ioreq(int vcpu 28.44 28.45 if (req->state == STATE_IOREQ_READY) { 28.46 req->state = STATE_IOREQ_INPROCESS; 28.47 + rmb(); 28.48 return req; 28.49 } 28.50 28.51 @@ -226,7 +234,7 @@ static ioreq_t *cpu_get_ioreq(void) 28.52 port = xc_evtchn_pending(xce_handle); 28.53 if (port != -1) { 28.54 for ( i = 0; i < vcpus; i++ ) 28.55 - if ( shared_page->vcpu_iodata[i].dm_eport == port ) 28.56 + if ( ioreq_local_port[i] == port ) 28.57 break; 28.58 28.59 if ( i == vcpus ) { 28.60 @@ -415,40 +423,74 @@ void cpu_ioreq_xor(CPUState *env, ioreq_ 28.61 req->u.data = tmp1; 28.62 } 28.63 28.64 +void __handle_ioreq(CPUState *env, ioreq_t *req) 28.65 +{ 28.66 + if (!req->pdata_valid && req->dir == IOREQ_WRITE && req->size != 4) 28.67 + req->u.data &= (1UL << (8 * req->size)) - 1; 28.68 + 28.69 + switch (req->type) { 28.70 + case IOREQ_TYPE_PIO: 28.71 + cpu_ioreq_pio(env, req); 28.72 + break; 28.73 + case IOREQ_TYPE_COPY: 28.74 + cpu_ioreq_move(env, req); 28.75 + break; 28.76 + case IOREQ_TYPE_AND: 28.77 + cpu_ioreq_and(env, req); 28.78 + break; 28.79 + case IOREQ_TYPE_OR: 28.80 + cpu_ioreq_or(env, req); 28.81 + break; 28.82 + case IOREQ_TYPE_XOR: 28.83 + cpu_ioreq_xor(env, req); 28.84 + break; 28.85 + default: 28.86 + hw_error("Invalid ioreq type 0x%x\n", req->type); 28.87 + } 28.88 +} 28.89 + 28.90 +void __handle_buffered_iopage(CPUState *env) 28.91 +{ 28.92 + ioreq_t *req = NULL; 28.93 + 28.94 + if (!buffered_io_page) 28.95 + return; 28.96 + 28.97 + while (buffered_io_page->read_pointer != 28.98 + buffered_io_page->write_pointer) { 28.99 + req = &buffered_io_page->ioreq[buffered_io_page->read_pointer % 28.100 + IOREQ_BUFFER_SLOT_NUM]; 28.101 + 28.102 + __handle_ioreq(env, req); 28.103 + 28.104 + mb(); 28.105 + buffered_io_page->read_pointer++; 28.106 + } 28.107 +} 28.108 + 28.109 +void handle_buffered_io(void *opaque) 28.110 +{ 28.111 + CPUState *env = opaque; 28.112 + 28.113 + __handle_buffered_iopage(env); 28.114 + qemu_mod_timer(buffered_io_timer, BUFFER_IO_MAX_DELAY + 28.115 + qemu_get_clock(rt_clock)); 28.116 +} 28.117 + 28.118 void cpu_handle_ioreq(void *opaque) 28.119 { 28.120 CPUState *env = opaque; 28.121 ioreq_t *req = cpu_get_ioreq(); 28.122 28.123 + handle_buffered_io(env); 28.124 if (req) { 28.125 - if ((!req->pdata_valid) && (req->dir == IOREQ_WRITE)) { 28.126 - if (req->size != 4) 28.127 - req->u.data &= (1UL << (8 * req->size))-1; 28.128 - } 28.129 - 28.130 - switch (req->type) { 28.131 - case IOREQ_TYPE_PIO: 28.132 - cpu_ioreq_pio(env, req); 28.133 - break; 28.134 - case IOREQ_TYPE_COPY: 28.135 - cpu_ioreq_move(env, req); 28.136 - break; 28.137 - case IOREQ_TYPE_AND: 28.138 - cpu_ioreq_and(env, req); 28.139 - break; 28.140 - case IOREQ_TYPE_OR: 28.141 - cpu_ioreq_or(env, req); 28.142 - break; 28.143 - case IOREQ_TYPE_XOR: 28.144 - cpu_ioreq_xor(env, req); 28.145 - break; 28.146 - default: 28.147 - hw_error("Invalid ioreq type 0x%x\n", req->type); 28.148 - } 28.149 + __handle_ioreq(env, req); 28.150 28.151 /* No state change if state = STATE_IORESP_HOOK */ 28.152 - if (req->state == STATE_IOREQ_INPROCESS) 28.153 + if (req->state == STATE_IOREQ_INPROCESS) { 28.154 + mb(); 28.155 req->state = STATE_IORESP_READY; 28.156 + } 28.157 env->send_event = 1; 28.158 } 28.159 } 28.160 @@ -460,6 +502,10 @@ int main_loop(void) 28.161 CPUState *env = cpu_single_env; 28.162 int evtchn_fd = xc_evtchn_fd(xce_handle); 28.163 28.164 + buffered_io_timer = qemu_new_timer(rt_clock, handle_buffered_io, 28.165 + cpu_single_env); 28.166 + qemu_mod_timer(buffered_io_timer, qemu_get_clock(rt_clock)); 28.167 + 28.168 qemu_set_fd_handler(evtchn_fd, cpu_handle_ioreq, NULL, env); 28.169 28.170 env->send_event = 0; 28.171 @@ -479,8 +525,7 @@ int main_loop(void) 28.172 28.173 if (env->send_event) { 28.174 env->send_event = 0; 28.175 - xc_evtchn_notify(xce_handle, 28.176 - shared_page->vcpu_iodata[send_vcpu].dm_eport); 28.177 + xc_evtchn_notify(xce_handle, ioreq_local_port[send_vcpu]); 28.178 } 28.179 } 28.180 destroy_hvm_domain();
29.1 --- a/tools/ioemu/vl.c Tue Aug 08 19:07:32 2006 -0500 29.2 +++ b/tools/ioemu/vl.c Wed Aug 09 18:04:20 2006 +0100 29.3 @@ -121,6 +121,7 @@ int bios_size; 29.4 static DisplayState display_state; 29.5 int nographic; 29.6 int vncviewer; 29.7 +int vncunused; 29.8 const char* keyboard_layout = NULL; 29.9 int64_t ticks_per_sec; 29.10 int boot_device = 'c'; 29.11 @@ -5344,6 +5345,7 @@ void help(void) 29.12 "-loadvm file start right away with a saved state (loadvm in monitor)\n" 29.13 "-vnc display start a VNC server on display\n" 29.14 "-vncviewer start a vncviewer process for this domain\n" 29.15 + "-vncunused bind the VNC server to an unused port\n" 29.16 "-timeoffset time offset (in seconds) from local time\n" 29.17 "-acpi disable or enable ACPI of HVM domain \n" 29.18 "\n" 29.19 @@ -5435,6 +5437,7 @@ enum { 29.20 QEMU_OPTION_timeoffset, 29.21 QEMU_OPTION_acpi, 29.22 QEMU_OPTION_vncviewer, 29.23 + QEMU_OPTION_vncunused, 29.24 }; 29.25 29.26 typedef struct QEMUOption { 29.27 @@ -5512,6 +5515,7 @@ const QEMUOption qemu_options[] = { 29.28 { "smp", HAS_ARG, QEMU_OPTION_smp }, 29.29 { "vnc", HAS_ARG, QEMU_OPTION_vnc }, 29.30 { "vncviewer", 0, QEMU_OPTION_vncviewer }, 29.31 + { "vncunused", 0, QEMU_OPTION_vncunused }, 29.32 29.33 /* temporary options */ 29.34 { "usb", 0, QEMU_OPTION_usb }, 29.35 @@ -5834,6 +5838,7 @@ int main(int argc, char **argv) 29.36 unsigned long nr_pages; 29.37 xen_pfn_t *page_array; 29.38 extern void *shared_page; 29.39 + extern void *buffered_io_page; 29.40 29.41 char qemu_dm_logfilename[64]; 29.42 29.43 @@ -5887,6 +5892,7 @@ int main(int argc, char **argv) 29.44 snapshot = 0; 29.45 nographic = 0; 29.46 vncviewer = 0; 29.47 + vncunused = 0; 29.48 kernel_filename = NULL; 29.49 kernel_cmdline = ""; 29.50 #ifndef CONFIG_DM 29.51 @@ -6294,6 +6300,11 @@ int main(int argc, char **argv) 29.52 case QEMU_OPTION_vncviewer: 29.53 vncviewer++; 29.54 break; 29.55 + case QEMU_OPTION_vncunused: 29.56 + vncunused++; 29.57 + if (vnc_display == -1) 29.58 + vnc_display = -2; 29.59 + break; 29.60 } 29.61 } 29.62 } 29.63 @@ -6378,12 +6389,17 @@ int main(int argc, char **argv) 29.64 29.65 phys_ram_base = xc_map_foreign_batch(xc_handle, domid, 29.66 PROT_READ|PROT_WRITE, page_array, 29.67 - nr_pages - 1); 29.68 + nr_pages - 3); 29.69 if (phys_ram_base == 0) { 29.70 fprintf(logfile, "xc_map_foreign_batch returned error %d\n", errno); 29.71 exit(-1); 29.72 } 29.73 29.74 + /* not yet add for IA64 */ 29.75 + buffered_io_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE, 29.76 + PROT_READ|PROT_WRITE, 29.77 + page_array[nr_pages - 3]); 29.78 + 29.79 shared_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE, 29.80 PROT_READ|PROT_WRITE, 29.81 page_array[nr_pages - 1]); 29.82 @@ -6498,7 +6514,7 @@ int main(int argc, char **argv) 29.83 if (nographic) { 29.84 dumb_display_init(ds); 29.85 } else if (vnc_display != -1) { 29.86 - vnc_display_init(ds, vnc_display); 29.87 + vnc_display = vnc_display_init(ds, vnc_display, vncunused); 29.88 if (vncviewer) 29.89 vnc_start_viewer(vnc_display); 29.90 xenstore_write_vncport(vnc_display);
30.1 --- a/tools/ioemu/vl.h Tue Aug 08 19:07:32 2006 -0500 30.2 +++ b/tools/ioemu/vl.h Wed Aug 09 18:04:20 2006 +0100 30.3 @@ -784,7 +784,7 @@ void sdl_display_init(DisplayState *ds, 30.4 void cocoa_display_init(DisplayState *ds, int full_screen); 30.5 30.6 /* vnc.c */ 30.7 -void vnc_display_init(DisplayState *ds, int display); 30.8 +int vnc_display_init(DisplayState *ds, int display, int find_unused); 30.9 int vnc_start_viewer(int port); 30.10 30.11 /* ide.c */
31.1 --- a/tools/ioemu/vnc.c Tue Aug 08 19:07:32 2006 -0500 31.2 +++ b/tools/ioemu/vnc.c Wed Aug 09 18:04:20 2006 +0100 31.3 @@ -1183,7 +1183,7 @@ static void vnc_listen_read(void *opaque 31.4 } 31.5 } 31.6 31.7 -void vnc_display_init(DisplayState *ds, int display) 31.8 +int vnc_display_init(DisplayState *ds, int display, int find_unused) 31.9 { 31.10 struct sockaddr_in addr; 31.11 int reuse_addr, ret; 31.12 @@ -1214,10 +1214,6 @@ void vnc_display_init(DisplayState *ds, 31.13 exit(1); 31.14 } 31.15 31.16 - addr.sin_family = AF_INET; 31.17 - addr.sin_port = htons(5900 + display); 31.18 - memset(&addr.sin_addr, 0, sizeof(addr.sin_addr)); 31.19 - 31.20 reuse_addr = 1; 31.21 ret = setsockopt(vs->lsock, SOL_SOCKET, SO_REUSEADDR, 31.22 (const char *)&reuse_addr, sizeof(reuse_addr)); 31.23 @@ -1226,7 +1222,16 @@ void vnc_display_init(DisplayState *ds, 31.24 exit(1); 31.25 } 31.26 31.27 + retry: 31.28 + addr.sin_family = AF_INET; 31.29 + addr.sin_port = htons(5900 + display); 31.30 + memset(&addr.sin_addr, 0, sizeof(addr.sin_addr)); 31.31 + 31.32 if (bind(vs->lsock, (struct sockaddr *)&addr, sizeof(addr)) == -1) { 31.33 + if (find_unused && errno == EADDRINUSE) { 31.34 + display++; 31.35 + goto retry; 31.36 + } 31.37 fprintf(stderr, "bind() failed\n"); 31.38 exit(1); 31.39 } 31.40 @@ -1247,6 +1252,8 @@ void vnc_display_init(DisplayState *ds, 31.41 vs->ds->dpy_refresh = vnc_dpy_refresh; 31.42 31.43 vnc_dpy_resize(vs->ds, 640, 400); 31.44 + 31.45 + return display; 31.46 } 31.47 31.48 int vnc_start_viewer(int port)
32.1 --- a/tools/libxc/xc_hvm_build.c Tue Aug 08 19:07:32 2006 -0500 32.2 +++ b/tools/libxc/xc_hvm_build.c Wed Aug 09 18:04:20 2006 +0100 32.3 @@ -26,6 +26,7 @@ 32.4 #define E820_IO 16 32.5 #define E820_SHARED_PAGE 17 32.6 #define E820_XENSTORE 18 32.7 +#define E820_BUFFERED_IO 19 32.8 32.9 #define E820_MAP_PAGE 0x00090000 32.10 #define E820_MAP_NR_OFFSET 0x000001E8 32.11 @@ -96,7 +97,13 @@ static void build_e820map(void *e820_pag 32.12 e820entry[nr_map].type = E820_RESERVED; 32.13 nr_map++; 32.14 32.15 -#define STATIC_PAGES 2 /* for ioreq_t and store_mfn */ 32.16 +#define STATIC_PAGES 3 32.17 + /* 3 static pages: 32.18 + * - ioreq buffer. 32.19 + * - xenstore. 32.20 + * - shared_page. 32.21 + */ 32.22 + 32.23 /* Most of the ram goes here */ 32.24 e820entry[nr_map].addr = 0x100000; 32.25 e820entry[nr_map].size = mem_size - 0x100000 - STATIC_PAGES * PAGE_SIZE; 32.26 @@ -105,6 +112,12 @@ static void build_e820map(void *e820_pag 32.27 32.28 /* Statically allocated special pages */ 32.29 32.30 + /* For buffered IO requests */ 32.31 + e820entry[nr_map].addr = mem_size - 3 * PAGE_SIZE; 32.32 + e820entry[nr_map].size = PAGE_SIZE; 32.33 + e820entry[nr_map].type = E820_BUFFERED_IO; 32.34 + nr_map++; 32.35 + 32.36 /* For xenstore */ 32.37 e820entry[nr_map].addr = mem_size - 2 * PAGE_SIZE; 32.38 e820entry[nr_map].size = PAGE_SIZE; 32.39 @@ -213,6 +226,9 @@ static int setup_guest(int xc_handle, 32.40 unsigned long shared_page_frame = 0; 32.41 shared_iopage_t *sp; 32.42 32.43 + unsigned long ioreq_buffer_frame = 0; 32.44 + void *ioreq_buffer_page; 32.45 + 32.46 memset(&dsi, 0, sizeof(struct domain_setup_info)); 32.47 32.48 if ( (parseelfimage(image, image_size, &dsi)) != 0 ) 32.49 @@ -294,27 +310,27 @@ static int setup_guest(int xc_handle, 32.50 shared_info->vcpu_info[i].evtchn_upcall_mask = 1; 32.51 munmap(shared_info, PAGE_SIZE); 32.52 32.53 - /* Populate the event channel port in the shared page */ 32.54 + /* Paranoia */ 32.55 shared_page_frame = page_array[(v_end >> PAGE_SHIFT) - 1]; 32.56 if ( (sp = (shared_iopage_t *) xc_map_foreign_range( 32.57 xc_handle, dom, PAGE_SIZE, PROT_READ | PROT_WRITE, 32.58 shared_page_frame)) == 0 ) 32.59 goto error_out; 32.60 memset(sp, 0, PAGE_SIZE); 32.61 - 32.62 - /* FIXME: how about if we overflow the page here? */ 32.63 - for ( i = 0; i < vcpus; i++ ) { 32.64 - unsigned int vp_eport; 32.65 + munmap(sp, PAGE_SIZE); 32.66 32.67 - vp_eport = xc_evtchn_alloc_unbound(xc_handle, dom, 0); 32.68 - if ( vp_eport < 0 ) { 32.69 - PERROR("Couldn't get unbound port from VMX guest.\n"); 32.70 - goto error_out; 32.71 - } 32.72 - sp->vcpu_iodata[i].vp_eport = vp_eport; 32.73 - } 32.74 + /* clean the buffered IO requests page */ 32.75 + ioreq_buffer_frame = page_array[(v_end >> PAGE_SHIFT) - 3]; 32.76 + ioreq_buffer_page = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, 32.77 + PROT_READ | PROT_WRITE, 32.78 + ioreq_buffer_frame); 32.79 32.80 - munmap(sp, PAGE_SIZE); 32.81 + if ( ioreq_buffer_page == NULL ) 32.82 + goto error_out; 32.83 + 32.84 + memset(ioreq_buffer_page, 0, PAGE_SIZE); 32.85 + 32.86 + munmap(ioreq_buffer_page, PAGE_SIZE); 32.87 32.88 xc_set_hvm_param(xc_handle, dom, HVM_PARAM_STORE_PFN, (v_end >> PAGE_SHIFT) - 2); 32.89 xc_set_hvm_param(xc_handle, dom, HVM_PARAM_STORE_EVTCHN, store_evtchn);
33.1 --- a/tools/libxc/xc_linux_build.c Tue Aug 08 19:07:32 2006 -0500 33.2 +++ b/tools/libxc/xc_linux_build.c Wed Aug 09 18:04:20 2006 +0100 33.3 @@ -1373,10 +1373,10 @@ int xc_linux_build(int xc_handle, 33.4 33.5 error_out: 33.6 free(image); 33.7 - if ( fd >= 0 ) 33.8 + if ( initrd_info.type == INITRD_file && initrd_info.u.file_handle ) 33.9 + gzclose(initrd_info.u.file_handle); 33.10 + else if ( fd >= 0 ) 33.11 close(fd); 33.12 - if ( initrd_info.u.file_handle ) 33.13 - gzclose(initrd_info.u.file_handle); 33.14 33.15 return sts; 33.16 }
34.1 --- a/tools/pygrub/src/GrubConf.py Tue Aug 08 19:07:32 2006 -0500 34.2 +++ b/tools/pygrub/src/GrubConf.py Wed Aug 09 18:04:20 2006 +0100 34.3 @@ -1,7 +1,7 @@ 34.4 # 34.5 # GrubConf.py - Simple grub.conf parsing 34.6 # 34.7 -# Copyright 2005 Red Hat, Inc. 34.8 +# Copyright 2005-2006 Red Hat, Inc. 34.9 # Jeremy Katz <katzj@redhat.com> 34.10 # 34.11 # This software may be freely redistributed under the terms of the GNU 34.12 @@ -16,7 +16,6 @@ import os, sys 34.13 import logging 34.14 34.15 def grub_split(s, maxsplit = -1): 34.16 - """Split a grub option screen separated with either '=' or whitespace.""" 34.17 eq = s.find('=') 34.18 if eq == -1: 34.19 return s.split(None, maxsplit) 34.20 @@ -32,6 +31,12 @@ def grub_split(s, maxsplit = -1): 34.21 else: 34.22 return s.split(None, maxsplit) 34.23 34.24 +def grub_exact_split(s, num): 34.25 + ret = grub_split(s, num - 1) 34.26 + if len(ret) < num: 34.27 + return ret + [""] * (num - len(ret)) 34.28 + return ret 34.29 + 34.30 def get_path(s): 34.31 """Returns a tuple of (GrubDiskPart, path) corresponding to string.""" 34.32 if not s.startswith('('): 34.33 @@ -75,26 +80,40 @@ class GrubDiskPart(object): 34.34 34.35 class GrubImage(object): 34.36 def __init__(self, lines): 34.37 - self._root = self._initrd = self._kernel = self._args = None 34.38 - for l in lines: 34.39 - (com, arg) = grub_split(l, 1) 34.40 - 34.41 - if self.commands.has_key(com): 34.42 - if self.commands[com] is not None: 34.43 - exec("%s = r\"%s\"" %(self.commands[com], arg.strip())) 34.44 - else: 34.45 - logging.info("Ignored image directive %s" %(com,)) 34.46 - else: 34.47 - logging.warning("Unknown image directive %s" %(com,)) 34.48 + self.reset(lines) 34.49 34.50 def __repr__(self): 34.51 return ("title: %s\n" 34.52 " root: %s\n" 34.53 " kernel: %s\n" 34.54 " args: %s\n" 34.55 - " initrd: %s" %(self.title, self.root, self.kernel, 34.56 + " initrd: %s\n" %(self.title, self.root, self.kernel, 34.57 self.args, self.initrd)) 34.58 34.59 + def reset(self, lines): 34.60 + self._root = self._initrd = self._kernel = self._args = None 34.61 + self.title = "" 34.62 + self.lines = [] 34.63 + map(self.set_from_line, lines) 34.64 + 34.65 + def set_from_line(self, line, replace = None): 34.66 + (com, arg) = grub_exact_split(line, 2) 34.67 + 34.68 + if self.commands.has_key(com): 34.69 + if self.commands[com] is not None: 34.70 + exec("%s = r\"%s\"" %(self.commands[com], arg.strip())) 34.71 + else: 34.72 + logging.info("Ignored image directive %s" %(com,)) 34.73 + else: 34.74 + logging.warning("Unknown image directive %s" %(com,)) 34.75 + 34.76 + # now put the line in the list of lines 34.77 + if replace is None: 34.78 + self.lines.append(line) 34.79 + else: 34.80 + self.lines.pop(replace) 34.81 + self.lines.insert(replace, line) 34.82 + 34.83 def set_root(self, val): 34.84 self._root = GrubDiskPart(val) 34.85 def get_root(self): 34.86 @@ -137,6 +156,7 @@ class GrubConfigFile(object): 34.87 self.filename = fn 34.88 self.images = [] 34.89 self.timeout = -1 34.90 + self._default = 0 34.91 34.92 if fn is not None: 34.93 self.parse() 34.94 @@ -164,7 +184,7 @@ class GrubConfigFile(object): 34.95 # new image 34.96 if l.startswith("title"): 34.97 if len(img) > 0: 34.98 - self.images.append(GrubImage(img)) 34.99 + self.add_image(GrubImage(img)) 34.100 img = [l] 34.101 continue 34.102 34.103 @@ -172,12 +192,7 @@ class GrubConfigFile(object): 34.104 img.append(l) 34.105 continue 34.106 34.107 - try: 34.108 - (com, arg) = grub_split(l, 1) 34.109 - except ValueError: 34.110 - com = l 34.111 - arg = "" 34.112 - 34.113 + (com, arg) = grub_exact_split(l, 2) 34.114 if self.commands.has_key(com): 34.115 if self.commands[com] is not None: 34.116 exec("%s = r\"%s\"" %(self.commands[com], arg.strip())) 34.117 @@ -187,7 +202,20 @@ class GrubConfigFile(object): 34.118 logging.warning("Unknown directive %s" %(com,)) 34.119 34.120 if len(img) > 0: 34.121 - self.images.append(GrubImage(img)) 34.122 + self.add_image(GrubImage(img)) 34.123 + 34.124 + def set(self, line): 34.125 + (com, arg) = grub_exact_split(line, 2) 34.126 + if self.commands.has_key(com): 34.127 + if self.commands[com] is not None: 34.128 + exec("%s = r\"%s\"" %(self.commands[com], arg.strip())) 34.129 + else: 34.130 + logging.info("Ignored directive %s" %(com,)) 34.131 + else: 34.132 + logging.warning("Unknown directive %s" %(com,)) 34.133 + 34.134 + def add_image(self, image): 34.135 + self.images.append(image) 34.136 34.137 def _get_default(self): 34.138 return self._default
35.1 --- a/tools/pygrub/src/pygrub Tue Aug 08 19:07:32 2006 -0500 35.2 +++ b/tools/pygrub/src/pygrub Wed Aug 09 18:04:20 2006 +0100 35.3 @@ -2,7 +2,7 @@ 35.4 # 35.5 # pygrub - simple python-based bootloader for Xen 35.6 # 35.7 -# Copyright 2005 Red Hat, Inc. 35.8 +# Copyright 2005-2006 Red Hat, Inc. 35.9 # Jeremy Katz <katzj@redhat.com> 35.10 # 35.11 # This software may be freely redistributed under the terms of the GNU 35.12 @@ -14,9 +14,10 @@ 35.13 # 35.14 35.15 import os, sys, string, struct, tempfile 35.16 +import copy 35.17 import logging 35.18 35.19 -import curses, _curses, curses.wrapper 35.20 +import curses, _curses, curses.wrapper, curses.textpad, curses.ascii 35.21 import getopt 35.22 35.23 sys.path = [ '/usr/lib/python' ] + sys.path 35.24 @@ -24,122 +25,387 @@ sys.path = [ '/usr/lib/python' ] + sys.p 35.25 import grub.GrubConf 35.26 import grub.fsys 35.27 35.28 -PYGRUB_VER = 0.3 35.29 - 35.30 - 35.31 -def draw_window(): 35.32 - stdscr = curses.initscr() 35.33 - if hasattr(curses, 'use_default_colors'): 35.34 - curses.use_default_colors() 35.35 - try: 35.36 - curses.curs_set(0) 35.37 - except _curses.error: 35.38 - pass 35.39 - 35.40 - stdscr.addstr(1, 4, "pyGRUB version %s" %(PYGRUB_VER,)) 35.41 - 35.42 - win = curses.newwin(10, 74, 2, 1) 35.43 - win.box() 35.44 - win.refresh() 35.45 - 35.46 - stdscr.addstr(12, 5, "Use the U and D keys to select which entry is highlighted.") 35.47 - stdscr.addstr(13, 5, "Press enter to boot the selected OS. 'e' to edit the") 35.48 - stdscr.addstr(14, 5, "commands before booting, 'a' to modify the kernel arguments ") 35.49 - stdscr.addstr(15, 5, "before booting, or 'c' for a command line.") 35.50 - stdscr.addch(12, 13, curses.ACS_UARROW) 35.51 - stdscr.addch(12, 19, curses.ACS_DARROW) 35.52 - (y, x) = stdscr.getmaxyx() 35.53 - stdscr.move(y - 1, x - 1) 35.54 - 35.55 - stdscr.refresh() 35.56 - return (stdscr, win) 35.57 - 35.58 -def fill_entries(win, cfg, selected): 35.59 - y = 0 35.60 - 35.61 - for i in cfg.images: 35.62 - if (0, y) > win.getmaxyx(): 35.63 - break 35.64 - if y == selected: 35.65 - attr = curses.A_REVERSE 35.66 - else: 35.67 - attr = 0 35.68 - win.addstr(y + 1, 2, i.title.ljust(70), attr) 35.69 - y += 1 35.70 - win.refresh() 35.71 - 35.72 -def select(win, line): 35.73 - win.attron(curses.A_REVERSE) 35.74 - win.redrawln(line + 1, 1) 35.75 - win.refresh() 35.76 +PYGRUB_VER = 0.4 35.77 35.78 def is_disk_image(file): 35.79 fd = os.open(file, os.O_RDONLY) 35.80 buf = os.read(fd, 512) 35.81 os.close(fd) 35.82 35.83 - if len(buf) >= 512 and struct.unpack("H", buf[0x1fe: 0x200]) == (0xaa55,): 35.84 + if len(buf) >= 512 and \ 35.85 + struct.unpack("H", buf[0x1fe: 0x200]) == (0xaa55,): 35.86 return True 35.87 return False 35.88 35.89 SECTOR_SIZE=512 35.90 def get_active_offset(file): 35.91 - """Find the offset for the start of the first active partition in the 35.92 - disk image file.""" 35.93 + """Find the offset for the start of the first active partition " 35.94 + "in the disk image file.""" 35.95 + 35.96 fd = os.open(file, os.O_RDONLY) 35.97 buf = os.read(fd, 512) 35.98 for poff in (446, 462, 478, 494): # partition offsets 35.99 # active partition has 0x80 as the first byte 35.100 if struct.unpack("<c", buf[poff:poff+1]) == ('\x80',): 35.101 - return struct.unpack("<L", buf[poff+8:poff+12])[0] * SECTOR_SIZE 35.102 - return -1 35.103 + return struct.unpack("<L", 35.104 + buf[poff+8:poff+12])[0] * SECTOR_SIZE 35.105 + 35.106 + # if there's not a partition marked as active, fall back to 35.107 + # the first partition 35.108 + P1 = 446 35.109 + return struct.unpack("<L", buf[P1+8:P1+12])[0] * SECTOR_SIZE 35.110 + 35.111 +class GrubLineEditor(curses.textpad.Textbox): 35.112 + def __init__(self, screen, startx, starty, line = ""): 35.113 + screen.addstr(startx, starty, "> ") 35.114 + screen.refresh() 35.115 + win = curses.newwin(1, 74, startx, starty + 2) 35.116 + curses.textpad.Textbox.__init__(self, win) 35.117 + 35.118 + self.line = list(line) 35.119 + self.pos = len(line) 35.120 + self.cancelled = False 35.121 + self.show_text() 35.122 + 35.123 + def show_text(self): 35.124 + """Show the text. One of our advantages over standard textboxes 35.125 + is that we can handle lines longer than the window.""" 35.126 + 35.127 + self.win.clear() 35.128 + if self.pos > 70: 35.129 + if self.pos > 130: 35.130 + off = 120 35.131 + else: 35.132 + off = 55 35.133 + l = [ "<" ] + self.line[off:] 35.134 + p = self.pos - off 35.135 + else: 35.136 + l = self.line[:70] 35.137 + p = self.pos 35.138 + self.win.addstr(0, 0, string.join(l, (""))) 35.139 + if self.pos > 70: 35.140 + self.win.addch(0, 0, curses.ACS_LARROW) 35.141 + 35.142 + self.win.move(0, p) 35.143 + 35.144 + def do_command(self, ch): 35.145 + # we handle escape as well as moving the line around, so have 35.146 + # to override some of the default handling 35.147 35.148 -def get_config(fn, isconfig = False): 35.149 - if not os.access(fn, os.R_OK): 35.150 - raise RuntimeError, "Unable to access %s" %(fn,) 35.151 + self.lastcmd = ch 35.152 + if ch == 27: # esc 35.153 + self.cancelled = True 35.154 + return 0 35.155 + elif curses.ascii.isprint(ch): 35.156 + self.line.insert(self.pos, chr(ch)) 35.157 + self.pos += 1 35.158 + elif ch == curses.ascii.SOH: # ^a 35.159 + self.pos = 0 35.160 + elif ch in (curses.ascii.STX,curses.KEY_LEFT): 35.161 + self.pos -= 1 35.162 + elif ch in (curses.ascii.BS,curses.KEY_BACKSPACE): 35.163 + if self.pos > 0: 35.164 + self.pos -= 1 35.165 + self.line.pop(self.pos) 35.166 + elif ch == curses.ascii.EOT: # ^d 35.167 + self.line.pop(self.pos) 35.168 + elif ch == curses.ascii.ENQ: # ^e 35.169 + self.pos = len(self.line) 35.170 + elif ch in (curses.ascii.ACK, curses.KEY_RIGHT): 35.171 + self.pos +=1 35.172 + elif ch == curses.ascii.VT: # ^k 35.173 + self.line = self.line[:self.pos] 35.174 + else: 35.175 + return curses.textpad.Textbox.do_command(self, ch) 35.176 + self.show_text() 35.177 + return 1 35.178 35.179 - cf = grub.GrubConf.GrubConfigFile() 35.180 + def edit(self): 35.181 + r = curses.textpad.Textbox.edit(self) 35.182 + if self.cancelled: 35.183 + return None 35.184 + return string.join(self.line, "") 35.185 + 35.186 + 35.187 +class Grub: 35.188 + def __init__(self, file, isconfig = False): 35.189 + self.screen = None 35.190 + self.entry_win = None 35.191 + self.text_win = None 35.192 + if file: 35.193 + self.read_config(file, isconfig) 35.194 + 35.195 + def draw_main_windows(self): 35.196 + if self.screen is None: #only init stuff once 35.197 + self.screen = curses.initscr() 35.198 + self.screen.timeout(1000) 35.199 + if hasattr(curses, 'use_default_colors'): 35.200 + curses.use_default_colors() 35.201 + try: 35.202 + curses.curs_set(0) 35.203 + except _curses.error: 35.204 + pass 35.205 + self.entry_win = curses.newwin(10, 74, 2, 1) 35.206 + self.text_win = curses.newwin(10, 70, 12, 5) 35.207 + 35.208 + self.screen.clear() 35.209 + self.screen.refresh() 35.210 + 35.211 + # create basic grub screen with a box of entries and a textbox 35.212 + self.screen.addstr(1, 4, "pyGRUB version %s" %(PYGRUB_VER,)) 35.213 + self.entry_win.box() 35.214 + self.screen.refresh() 35.215 35.216 - if isconfig: 35.217 - # set the config file and parse it 35.218 - cf.filename = fn 35.219 - cf.parse() 35.220 - return cf 35.221 + def fill_entry_list(self): 35.222 + self.entry_win.clear() 35.223 + self.entry_win.box() 35.224 + for y in range(0, len(self.cf.images)): 35.225 + i = self.cf.images[y] 35.226 + if (0, y) > self.entry_win.getmaxyx(): 35.227 + break 35.228 + if y == self.selected_image: 35.229 + attr = curses.A_REVERSE 35.230 + else: 35.231 + attr = 0 35.232 + self.entry_win.addstr(y + 1, 2, i.title.ljust(70), attr) 35.233 + self.entry_win.refresh() 35.234 + 35.235 + def edit_entry(self, origimg): 35.236 + def draw(): 35.237 + self.draw_main_windows() 35.238 + 35.239 + self.text_win.addstr(0, 0, "Use the U and D keys to select which entry is highlighted.") 35.240 + self.text_win.addstr(1, 0, "Press 'b' to boot, 'e' to edit the selected command in the") 35.241 + self.text_win.addstr(2, 0, "boot sequence, 'c' for a command-line, 'o' to open a new line") 35.242 + self.text_win.addstr(3, 0, "after ('O' for before) the selected line, 'd' to remove the") 35.243 + self.text_win.addstr(4, 0, "selected line, or escape to go back to the main menu.") 35.244 + self.text_win.addch(0, 8, curses.ACS_UARROW) 35.245 + self.text_win.addch(0, 14, curses.ACS_DARROW) 35.246 + (y, x) = self.text_win.getmaxyx() 35.247 + self.text_win.move(y - 1, x - 1) 35.248 + self.text_win.refresh() 35.249 + 35.250 + curline = 1 35.251 + img = copy.deepcopy(origimg) 35.252 + while 1: 35.253 + draw() 35.254 + self.entry_win.clear() 35.255 + self.entry_win.box() 35.256 + for idx in range(1, len(img.lines)): 35.257 + # current line should be highlighted 35.258 + attr = 0 35.259 + if idx == curline: 35.260 + attr = curses.A_REVERSE 35.261 + 35.262 + # trim the line 35.263 + l = img.lines[idx].ljust(70) 35.264 + if len(l) > 70: 35.265 + l = l[:69] + ">" 35.266 + 35.267 + self.entry_win.addstr(idx, 2, l, attr) 35.268 + self.entry_win.refresh() 35.269 35.270 - offset = 0 35.271 - if is_disk_image(fn): 35.272 - offset = get_active_offset(fn) 35.273 - if offset == -1: 35.274 - raise RuntimeError, "Unable to find active partition on disk" 35.275 + c = self.screen.getch() 35.276 + if c in (ord('q'), 27): # 27 == esc 35.277 + break 35.278 + elif c == curses.KEY_UP: 35.279 + curline -= 1 35.280 + elif c == curses.KEY_DOWN: 35.281 + curline += 1 35.282 + elif c == ord('b'): 35.283 + self.isdone = True 35.284 + break 35.285 + elif c == ord('e'): 35.286 + l = self.edit_line(img.lines[curline]) 35.287 + if l is not None: 35.288 + img.set_from_line(l, replace = curline) 35.289 + elif c == ord('d'): 35.290 + img.lines.pop(curline) 35.291 + elif c == ord('o'): 35.292 + img.lines.insert(curline+1, "") 35.293 + curline += 1 35.294 + elif c == ord('O'): 35.295 + img.lines.insert(curline, "") 35.296 + elif c == ord('c'): 35.297 + self.command_line_mode() 35.298 + if self.isdone: 35.299 + return 35.300 + 35.301 + # bound at the top and bottom 35.302 + if curline < 1: 35.303 + curline = 1 35.304 + elif curline >= len(img.lines): 35.305 + curline = len(img.lines) - 1 35.306 + 35.307 + if self.isdone: 35.308 + origimg.reset(img.lines) 35.309 35.310 - # open the image and read the grub config 35.311 - fs = None 35.312 - for fstype in grub.fsys.fstypes.values(): 35.313 - if fstype.sniff_magic(fn, offset): 35.314 - fs = fstype.open_fs(fn, offset) 35.315 + def edit_line(self, line): 35.316 + self.screen.clear() 35.317 + self.screen.addstr(1, 2, "[ Minimal BASH-like line editing is supported. ") 35.318 + self.screen.addstr(2, 2, " ESC at any time cancels. ENTER at any time accepts your changes. ]") 35.319 + self.screen.refresh() 35.320 + 35.321 + t = GrubLineEditor(self.screen, 5, 2, line) 35.322 + ret = t.edit() 35.323 + if ret: 35.324 + return ret 35.325 + return None 35.326 + 35.327 + def command_line_mode(self): 35.328 + self.screen.clear() 35.329 + self.screen.addstr(1, 2, "[ Minimal BASH-like line editing is supported. ESC at any time ") 35.330 + self.screen.addstr(2, 2, " exits. Typing 'boot' will boot with your entered commands. ] ") 35.331 + self.screen.refresh() 35.332 + 35.333 + y = 5 35.334 + lines = [] 35.335 + while 1: 35.336 + t = GrubLineEditor(self.screen, y, 2) 35.337 + ret = t.edit() 35.338 + if ret: 35.339 + if ret in ("quit", "return"): 35.340 + break 35.341 + elif ret != "boot": 35.342 + y += 1 35.343 + lines.append(ret) 35.344 + continue 35.345 + 35.346 + # if we got boot, then we want to boot the entered image 35.347 + img = grub.GrubConf.GrubImage(lines) 35.348 + self.cf.add_image(img) 35.349 + self.selected_image = len(self.cf.images) - 1 35.350 + self.isdone = True 35.351 + break 35.352 + 35.353 + # else, we cancelled and should just go back 35.354 break 35.355 35.356 - if fs is not None: 35.357 - grubfile = None 35.358 - for f in ("/boot/grub/menu.lst", "/boot/grub/grub.conf", 35.359 - "/grub/menu.lst", "/grub/grub.conf"): 35.360 - if fs.file_exist(f): 35.361 - grubfile = f 35.362 + def read_config(self, fn, isConfig = False): 35.363 + """Read the given file to parse the config. If isconfig, then 35.364 + we're being given a raw config file rather than a disk image.""" 35.365 + 35.366 + if not os.access(fn, os.R_OK): 35.367 + raise RuntimeError, "Unable to access %s" %(fn,) 35.368 + 35.369 + self.cf = grub.GrubConf.GrubConfigFile() 35.370 + 35.371 + if isConfig: 35.372 + # set the config file and parse it 35.373 + self.cf.filename = fn 35.374 + self.cf.parse() 35.375 + return 35.376 + 35.377 + offset = 0 35.378 + if is_disk_image(fn): 35.379 + offset = get_active_offset(fn) 35.380 + if offset == -1: 35.381 + raise RuntimeError, "Unable to find active partition on disk" 35.382 + 35.383 + # open the image and read the grub config 35.384 + fs = None 35.385 + for fstype in grub.fsys.fstypes.values(): 35.386 + if fstype.sniff_magic(fn, offset): 35.387 + fs = fstype.open_fs(fn, offset) 35.388 break 35.389 - if grubfile is None: 35.390 - raise RuntimeError, "we couldn't find /boot/grub{menu.lst,grub.conf} " + \ 35.391 - "in the image provided. halt!" 35.392 - f = fs.open_file(grubfile) 35.393 - buf = f.read() 35.394 - f.close() 35.395 - fs.close() 35.396 - # then parse the grub config 35.397 - cf.parse(buf) 35.398 - else: 35.399 - raise RuntimeError, "Unable to read filesystem" 35.400 - 35.401 - return cf 35.402 + 35.403 + if fs is not None: 35.404 + grubfile = None 35.405 + for f in ("/boot/grub/menu.lst", "/boot/grub/grub.conf", 35.406 + "/grub/menu.lst", "/grub/grub.conf"): 35.407 + if fs.file_exist(f): 35.408 + grubfile = f 35.409 + break 35.410 + if grubfile is None: 35.411 + raise RuntimeError, "we couldn't find grub config file in the image provided." 35.412 + f = fs.open_file(grubfile) 35.413 + buf = f.read() 35.414 + f.close() 35.415 + fs.close() 35.416 + # then parse the grub config 35.417 + self.cf.parse(buf) 35.418 + else: 35.419 + raise RuntimeError, "Unable to read filesystem" 35.420 + 35.421 + def run(self): 35.422 + timeout = int(self.cf.timeout) 35.423 + 35.424 + self.selected_image = self.cf.default 35.425 + self.isdone = False 35.426 + while not self.isdone: 35.427 + self.run_main(timeout) 35.428 + timeout = -1 35.429 + 35.430 + return self.selected_image 35.431 + 35.432 + def run_main(self, timeout = -1): 35.433 + def draw(): 35.434 + # set up the screen 35.435 + self.draw_main_windows() 35.436 + self.text_win.addstr(0, 0, "Use the U and D keys to select which entry is highlighted.") 35.437 + self.text_win.addstr(1, 0, "Press enter to boot the selected OS. 'e' to edit the") 35.438 + self.text_win.addstr(2, 0, "commands before booting, 'a' to modify the kernel arguments ") 35.439 + self.text_win.addstr(3, 0, "before booting, or 'c' for a command line.") 35.440 + self.text_win.addch(0, 8, curses.ACS_UARROW) 35.441 + self.text_win.addch(0, 14, curses.ACS_DARROW) 35.442 + (y, x) = self.text_win.getmaxyx() 35.443 + self.text_win.move(y - 1, x - 1) 35.444 + self.text_win.refresh() 35.445 35.446 + # now loop until we hit the timeout or get a go from the user 35.447 + mytime = 0 35.448 + while (timeout == -1 or mytime < int(timeout)): 35.449 + draw() 35.450 + if timeout != -1 and mytime != -1: 35.451 + self.screen.addstr(20, 5, "Will boot selected entry in %2d seconds" 35.452 + %(int(timeout) - mytime)) 35.453 + else: 35.454 + self.screen.addstr(20, 5, " " * 80) 35.455 + 35.456 + self.fill_entry_list() 35.457 + c = self.screen.getch() 35.458 + if mytime != -1: 35.459 + mytime += 1 35.460 + 35.461 + # handle keypresses 35.462 + if c == ord('c'): 35.463 + self.command_line_mode() 35.464 + break 35.465 + elif c == ord('a'): 35.466 + # find the kernel line, edit it and then boot 35.467 + img = self.cf.images[self.selected_image] 35.468 + for line in img.lines: 35.469 + if line.startswith("kernel"): 35.470 + l = self.edit_line(line) 35.471 + if l is not None: 35.472 + img.set_from_line(l, replace = True) 35.473 + self.isdone = True 35.474 + break 35.475 + break 35.476 + elif c == ord('e'): 35.477 + img = self.cf.images[self.selected_image] 35.478 + self.edit_entry(img) 35.479 + break 35.480 + elif c in (curses.KEY_ENTER, ord('\n'), ord('\r')): 35.481 + self.isdone = True 35.482 + break 35.483 + elif c == curses.KEY_UP: 35.484 + mytime = -1 35.485 + self.selected_image -= 1 35.486 + elif c == curses.KEY_DOWN: 35.487 + mytime = -1 35.488 + self.selected_image += 1 35.489 +# elif c in (ord('q'), 27): # 27 == esc 35.490 +# self.selected_image = -1 35.491 +# self.isdone = True 35.492 +# break 35.493 + 35.494 + # bound at the top and bottom 35.495 + if self.selected_image < 0: 35.496 + self.selected_image = 0 35.497 + elif self.selected_image >= len(self.cf.images): 35.498 + self.selected_image = len(self.cf.images) - 1 35.499 + 35.500 def get_entry_idx(cf, entry): 35.501 # first, see if the given entry is numeric 35.502 try: 35.503 @@ -155,63 +421,12 @@ def get_entry_idx(cf, entry): 35.504 35.505 return None 35.506 35.507 -def main(cf = None): 35.508 - mytime = 0 35.509 - timeout = int(cf.timeout) 35.510 - 35.511 - (stdscr, win) = draw_window() 35.512 - stdscr.timeout(1000) 35.513 - selected = cf.default 35.514 - 35.515 - while (timeout == -1 or mytime < int(timeout)): 35.516 - if timeout != -1 and mytime != -1: 35.517 - stdscr.addstr(20, 5, "Will boot selected entry in %2d seconds" 35.518 - %(int(timeout) - mytime)) 35.519 - else: 35.520 - stdscr.addstr(20, 5, " " * 80) 35.521 - 35.522 - fill_entries(win, cf, selected) 35.523 - c = stdscr.getch() 35.524 - if mytime != -1: 35.525 - mytime += 1 35.526 -# if c == ord('q'): 35.527 -# selected = -1 35.528 -# break 35.529 - if c == ord('c'): 35.530 - # FIXME: needs to go to command line mode 35.531 - continue 35.532 - elif c == ord('a'): 35.533 - # FIXME: needs to go to append mode 35.534 - continue 35.535 - elif c == ord('e'): 35.536 - # FIXME: needs to go to edit mode 35.537 - continue 35.538 - elif c in (curses.KEY_ENTER, ord('\n'), ord('\r')): 35.539 - break 35.540 - elif c == curses.KEY_UP: 35.541 - mytime = -1 35.542 - selected -= 1 35.543 - elif c == curses.KEY_DOWN: 35.544 - mytime = -1 35.545 - selected += 1 35.546 - else: 35.547 - pass 35.548 - 35.549 - # bound at the top and bottom 35.550 - if selected < 0: 35.551 - selected = 0 35.552 - elif selected >= len(cf.images): 35.553 - selected = len(cf.images) - 1 35.554 - 35.555 - if selected >= 0: 35.556 - return selected 35.557 - 35.558 if __name__ == "__main__": 35.559 sel = None 35.560 35.561 def run_main(scr, *args): 35.562 global sel 35.563 - sel = main(cf) 35.564 + sel = g.run() 35.565 35.566 def usage(): 35.567 print >> sys.stderr, "Usage: %s [-q|--quiet] [--output=] [--entry=] <image>" %(sys.argv[0],) 35.568 @@ -253,24 +468,32 @@ if __name__ == "__main__": 35.569 else: 35.570 fd = os.open(output, os.O_WRONLY) 35.571 35.572 - cf = get_config(file, isconfig) 35.573 + g = Grub(file, isconfig) 35.574 if interactive: 35.575 curses.wrapper(run_main) 35.576 else: 35.577 - sel = cf.default 35.578 + sel = g.cf.default 35.579 35.580 # set the entry to boot as requested 35.581 if entry is not None: 35.582 - idx = get_entry_idx(cf, entry) 35.583 - if idx is not None and idx > 0 and idx < len(cf.images): 35.584 + idx = get_entry_idx(g.cf, entry) 35.585 + if idx is not None and idx > 0 and idx < len(g.cf.images): 35.586 sel = idx 35.587 35.588 - img = cf.images[sel] 35.589 + if sel == -1: 35.590 + print "No kernel image selected!" 35.591 + sys.exit(1) 35.592 + 35.593 + img = g.cf.images[sel] 35.594 print "Going to boot %s" %(img.title) 35.595 print " kernel: %s" %(img.kernel[1],) 35.596 if img.initrd: 35.597 print " initrd: %s" %(img.initrd[1],) 35.598 35.599 + if isconfig: 35.600 + print " args: %s" %(img.args,) 35.601 + sys.exit(0) 35.602 + 35.603 offset = 0 35.604 if is_disk_image(file): 35.605 offset = get_active_offset(file) 35.606 @@ -288,14 +511,14 @@ if __name__ == "__main__": 35.607 raise RuntimeError, "Unable to open filesystem" 35.608 35.609 kernel = fs.open_file(img.kernel[1],).read() 35.610 - (tfd, fn) = tempfile.mkstemp(prefix="vmlinuz.") 35.611 + (tfd, fn) = tempfile.mkstemp(prefix="vmlinuz.", dir="/var/lib/xen") 35.612 os.write(tfd, kernel) 35.613 os.close(tfd) 35.614 sxp = "linux (kernel %s)" %(fn,) 35.615 35.616 if img.initrd: 35.617 initrd = fs.open_file(img.initrd[1],).read() 35.618 - (tfd, fn) = tempfile.mkstemp(prefix="initrd.") 35.619 + (tfd, fn) = tempfile.mkstemp(prefix="initrd.", dir="/var/lib/xen") 35.620 os.write(tfd, initrd) 35.621 os.close(tfd) 35.622 sxp += "(ramdisk %s)" %(fn,)
36.1 --- a/tools/python/xen/util/xmlrpclib2.py Tue Aug 08 19:07:32 2006 -0500 36.2 +++ b/tools/python/xen/util/xmlrpclib2.py Wed Aug 09 18:04:20 2006 +0100 36.3 @@ -138,6 +138,11 @@ class TCPXMLRPCServer(SocketServer.Threa 36.4 36.5 def _marshaled_dispatch(self, data, dispatch_method = None): 36.6 params, method = xmlrpclib.loads(data) 36.7 + if False: 36.8 + # Enable this block of code to exit immediately without sending 36.9 + # a response. This allows you to test client-side crash handling. 36.10 + import sys 36.11 + sys.exit(1) 36.12 try: 36.13 if dispatch_method is not None: 36.14 response = dispatch_method(method, params)
37.1 --- a/tools/python/xen/xend/XendDomain.py Tue Aug 08 19:07:32 2006 -0500 37.2 +++ b/tools/python/xen/xend/XendDomain.py Wed Aug 09 18:04:20 2006 +0100 37.3 @@ -402,9 +402,9 @@ class XendDomain: 37.4 val = dominfo.destroy() 37.5 else: 37.6 try: 37.7 - val = xc.domain_destroy(domid) 37.8 + val = xc.domain_destroy(int(domid)) 37.9 except Exception, ex: 37.10 - raise XendError(str(ex)) 37.11 + raise XendInvalidDomain(str(domid)) 37.12 return val 37.13 37.14 def domain_migrate(self, domid, dst, live=False, resource=0, port=0):
38.1 --- a/tools/python/xen/xend/image.py Tue Aug 08 19:07:32 2006 -0500 38.2 +++ b/tools/python/xen/xend/image.py Wed Aug 09 18:04:20 2006 +0100 38.3 @@ -260,7 +260,7 @@ class HVMImageHandler(ImageHandler): 38.4 if a == 'stdvga': a = 'std-vga' 38.5 38.6 # Handle booleans gracefully 38.7 - if a in ['localtime', 'std-vga', 'isa', 'usb']: 38.8 + if a in ['localtime', 'std-vga', 'isa', 'usb', 'acpi']: 38.9 if v != None: v = int(v) 38.10 if v: ret.append("-%s" % a) 38.11 else: 38.12 @@ -307,6 +307,7 @@ class HVMImageHandler(ImageHandler): 38.13 vnc = sxp.child_value(config, 'vnc') 38.14 vncdisplay = sxp.child_value(config, 'vncdisplay', 38.15 int(self.vm.getDomid())) 38.16 + vncunused = sxp.child_value(config, 'vncunused') 38.17 sdl = sxp.child_value(config, 'sdl') 38.18 ret = [] 38.19 nographic = sxp.child_value(config, 'nographic') 38.20 @@ -315,6 +316,8 @@ class HVMImageHandler(ImageHandler): 38.21 return ret 38.22 if vnc: 38.23 ret = ret + ['-vnc', '%d' % vncdisplay, '-k', 'en-us'] 38.24 + if vncunused: 38.25 + ret += ['-vncunused'] 38.26 return ret 38.27 38.28 def createDeviceModel(self):
39.1 --- a/tools/python/xen/xend/sxp.py Tue Aug 08 19:07:32 2006 -0500 39.2 +++ b/tools/python/xen/xend/sxp.py Wed Aug 09 18:04:20 2006 +0100 39.3 @@ -291,7 +291,7 @@ class Parser: 39.4 raise ParseError(self, "unexpected EOF") 39.5 elif '0' <= c <= '7': 39.6 octaldigit(c) 39.7 - elif len(self.buf): 39.8 + elif len(self.state.buf): 39.9 octaldone() 39.10 self.input_char(c) 39.11
40.1 --- a/tools/python/xen/xend/tests/test_sxp.py Tue Aug 08 19:07:32 2006 -0500 40.2 +++ b/tools/python/xen/xend/tests/test_sxp.py Wed Aug 09 18:04:20 2006 +0100 40.3 @@ -14,5 +14,26 @@ class test_sxp(unittest.TestCase): 40.4 t('(String) (Thing)', [['String'], ['Thing']]) 40.5 40.6 40.7 + def testParseFixed(self): 40.8 + fin = file('../xen/xend/tests/xend-config.sxp', 'rb') 40.9 + try: 40.10 + config = xen.xend.sxp.parse(fin) 40.11 + self.assertEqual( 40.12 + xen.xend.sxp.child_value( 40.13 + config, 40.14 + 'xend-relocation-hosts-allow'), 40.15 + '^localhost$ ^localhost\\.localdomain$') 40.16 + finally: 40.17 + fin.close() 40.18 + 40.19 + 40.20 + def testParseConfigExample(self): 40.21 + fin = file('../../examples/xend-config.sxp', 'rb') 40.22 + try: 40.23 + config = xen.xend.sxp.parse(fin) 40.24 + finally: 40.25 + fin.close() 40.26 + 40.27 + 40.28 def test_suite(): 40.29 return unittest.makeSuite(test_sxp)
41.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 41.2 +++ b/tools/python/xen/xend/tests/xend-config.sxp Wed Aug 09 18:04:20 2006 +0100 41.3 @@ -0,0 +1,132 @@ 41.4 +# -*- sh -*- 41.5 + 41.6 +# 41.7 +# Xend configuration file. 41.8 +# 41.9 + 41.10 +# This example configuration is appropriate for an installation that 41.11 +# utilizes a bridged network configuration. Access to xend via http 41.12 +# is disabled. 41.13 + 41.14 +# Commented out entries show the default for that entry, unless otherwise 41.15 +# specified. 41.16 + 41.17 +#(logfile /var/log/xend.log) 41.18 +#(loglevel DEBUG) 41.19 + 41.20 +#(xend-http-server no) 41.21 +#(xend-unix-server no) 41.22 +#(xend-tcp-xmlrpc-server no) 41.23 +#(xend-unix-xmlrpc-server yes) 41.24 +#(xend-relocation-server no) 41.25 +(xend-relocation-server yes) 41.26 + 41.27 +#(xend-unix-path /var/lib/xend/xend-socket) 41.28 + 41.29 +# Port xend should use for the HTTP interface, if xend-http-server is set. 41.30 +#(xend-port 8000) 41.31 + 41.32 +# Port xend should use for the relocation interface, if xend-relocation-server 41.33 +# is set. 41.34 +#(xend-relocation-port 8002) 41.35 + 41.36 +# Address xend should listen on for HTTP connections, if xend-http-server is 41.37 +# set. 41.38 +# Specifying 'localhost' prevents remote connections. 41.39 +# Specifying the empty string '' (the default) allows all connections. 41.40 +#(xend-address '') 41.41 +#(xend-address localhost) 41.42 + 41.43 +# Address xend should listen on for relocation-socket connections, if 41.44 +# xend-relocation-server is set. 41.45 +# Meaning and default as for xend-address above. 41.46 +#(xend-relocation-address '') 41.47 + 41.48 +# The hosts allowed to talk to the relocation port. If this is empty (the 41.49 +# default), then all connections are allowed (assuming that the connection 41.50 +# arrives on a port and interface on which we are listening; see 41.51 +# xend-relocation-port and xend-relocation-address above). Otherwise, this 41.52 +# should be a space-separated sequence of regular expressions. Any host with 41.53 +# a fully-qualified domain name or an IP address that matches one of these 41.54 +# regular expressions will be accepted. 41.55 +# 41.56 +# For example: 41.57 +# (xend-relocation-hosts-allow '^localhost$ ^.*\\.example\\.org$') 41.58 +# 41.59 +#(xend-relocation-hosts-allow '') 41.60 +(xend-relocation-hosts-allow '^localhost$ ^localhost\\.localdomain$') 41.61 + 41.62 +# The limit (in kilobytes) on the size of the console buffer 41.63 +#(console-limit 1024) 41.64 + 41.65 +## 41.66 +# To bridge network traffic, like this: 41.67 +# 41.68 +# dom0: fake eth0 -> vif0.0 -+ 41.69 +# | 41.70 +# bridge -> real eth0 -> the network 41.71 +# | 41.72 +# domU: fake eth0 -> vifN.0 -+ 41.73 +# 41.74 +# use 41.75 +# 41.76 +# (network-script network-bridge) 41.77 +# 41.78 +# Your default ethernet device is used as the outgoing interface, by default. 41.79 +# To use a different one (e.g. eth1) use 41.80 +# 41.81 +# (network-script 'network-bridge netdev=eth1') 41.82 +# 41.83 +# The bridge is named xenbr0, by default. To rename the bridge, use 41.84 +# 41.85 +# (network-script 'network-bridge bridge=<name>') 41.86 +# 41.87 +# It is possible to use the network-bridge script in more complicated 41.88 +# scenarios, such as having two outgoing interfaces, with two bridges, and 41.89 +# two fake interfaces per guest domain. To do things like this, write 41.90 +# yourself a wrapper script, and call network-bridge from it, as appropriate. 41.91 +# 41.92 +(network-script network-bridge) 41.93 + 41.94 +# The script used to control virtual interfaces. This can be overridden on a 41.95 +# per-vif basis when creating a domain or a configuring a new vif. The 41.96 +# vif-bridge script is designed for use with the network-bridge script, or 41.97 +# similar configurations. 41.98 +# 41.99 +# If you have overridden the bridge name using 41.100 +# (network-script 'network-bridge bridge=<name>') then you may wish to do the 41.101 +# same here. The bridge name can also be set when creating a domain or 41.102 +# configuring a new vif, but a value specified here would act as a default. 41.103 +# 41.104 +# If you are using only one bridge, the vif-bridge script will discover that, 41.105 +# so there is no need to specify it explicitly. 41.106 +# 41.107 +(vif-script vif-bridge) 41.108 + 41.109 + 41.110 +## Use the following if network traffic is routed, as an alternative to the 41.111 +# settings for bridged networking given above. 41.112 +#(network-script network-route) 41.113 +#(vif-script vif-route) 41.114 + 41.115 + 41.116 +## Use the following if network traffic is routed with NAT, as an alternative 41.117 +# to the settings for bridged networking given above. 41.118 +#(network-script network-nat) 41.119 +#(vif-script vif-nat) 41.120 + 41.121 + 41.122 +# Dom0 will balloon out when needed to free memory for domU. 41.123 +# dom0-min-mem is the lowest memory level (in MB) dom0 will get down to. 41.124 +# If dom0-min-mem=0, dom0 will never balloon out. 41.125 +(dom0-min-mem 196) 41.126 + 41.127 +# In SMP system, dom0 will use dom0-cpus # of CPUS 41.128 +# If dom0-cpus = 0, dom0 will take all cpus available 41.129 +(dom0-cpus 0) 41.130 + 41.131 +# Whether to enable core-dumps when domains crash. 41.132 +#(enable-dump no) 41.133 + 41.134 +# The tool used for initiating virtual TPM migration 41.135 +#(external-migration-tool '')
42.1 --- a/tools/python/xen/xm/create.py Tue Aug 08 19:07:32 2006 -0500 42.2 +++ b/tools/python/xen/xm/create.py Wed Aug 09 18:04:20 2006 +0100 42.3 @@ -412,6 +412,11 @@ gopts.var('vncdisplay', val='', 42.4 fn=set_value, default=None, 42.5 use="""VNC display to use""") 42.6 42.7 +gopts.var('vncunused', val='', 42.8 + fn=set_bool, default=1, 42.9 + use="""Try to find an unused port for the VNC server. 42.10 + Only valid when vnc=1.""") 42.11 + 42.12 gopts.var('sdl', val='', 42.13 fn=set_value, default=None, 42.14 use="""Should the device model use SDL?""") 42.15 @@ -627,7 +632,7 @@ def configure_hvm(config_image, vals): 42.16 """ 42.17 args = [ 'device_model', 'pae', 'vcpus', 'boot', 'fda', 'fdb', 42.18 'localtime', 'serial', 'stdvga', 'isa', 'nographic', 'soundhw', 42.19 - 'vnc', 'vncdisplay', 'vncconsole', 'sdl', 'display', 42.20 + 'vnc', 'vncdisplay', 'vncunused', 'vncconsole', 'sdl', 'display', 42.21 'acpi', 'apic', 'xauthority', 'usb', 'usbdevice' ] 42.22 for a in args: 42.23 if (vals.__dict__[a]): 42.24 @@ -844,14 +849,58 @@ def choose_vnc_display(): 42.25 42.26 vncpid = None 42.27 42.28 +def daemonize(prog, args): 42.29 + """Runs a program as a daemon with the list of arguments. Returns the PID 42.30 + of the daemonized program, or returns 0 on error. 42.31 + """ 42.32 + r, w = os.pipe() 42.33 + pid = os.fork() 42.34 + 42.35 + if pid == 0: 42.36 + os.close(r) 42.37 + w = os.fdopen(w, 'w') 42.38 + os.setsid() 42.39 + try: 42.40 + pid2 = os.fork() 42.41 + except: 42.42 + pid2 = None 42.43 + if pid2 == 0: 42.44 + os.chdir("/") 42.45 + for fd in range(0, 256): 42.46 + try: 42.47 + os.close(fd) 42.48 + except: 42.49 + pass 42.50 + os.open("/dev/null", os.O_RDWR) 42.51 + os.dup2(0, 1) 42.52 + os.dup2(0, 2) 42.53 + os.execvp(prog, args) 42.54 + os._exit(1) 42.55 + else: 42.56 + w.write(str(pid2 or 0)) 42.57 + w.close() 42.58 + os._exit(0) 42.59 + 42.60 + os.close(w) 42.61 + r = os.fdopen(r) 42.62 + daemon_pid = int(r.read()) 42.63 + r.close() 42.64 + os.waitpid(pid, 0) 42.65 + return daemon_pid 42.66 + 42.67 def spawn_vnc(display): 42.68 + """Spawns a vncviewer that listens on the specified display. On success, 42.69 + returns the port that the vncviewer is listening on and sets the global 42.70 + vncpid. On failure, returns 0. Note that vncviewer is daemonized. 42.71 + """ 42.72 vncargs = (["vncviewer", "-log", "*:stdout:0", 42.73 "-listen", "%d" % (VNC_BASE_PORT + display) ]) 42.74 - global vncpid 42.75 - vncpid = os.spawnvp(os.P_NOWAIT, "vncviewer", vncargs) 42.76 + global vncpid 42.77 + vncpid = daemonize("vncviewer", vncargs) 42.78 + if vncpid == 0: 42.79 + return 0 42.80 + return VNC_BASE_PORT + display 42.81 42.82 - return VNC_BASE_PORT + display 42.83 - 42.84 def preprocess_vnc(vals): 42.85 """If vnc was specified, spawn a vncviewer in listen mode 42.86 and pass its address to the domain on the kernel command line. 42.87 @@ -928,7 +977,7 @@ def make_domain(opts, config): 42.88 import signal 42.89 if vncpid: 42.90 os.kill(vncpid, signal.SIGKILL) 42.91 - raise ex 42.92 + raise 42.93 42.94 dom = sxp.child_value(dominfo, 'name') 42.95
43.1 --- a/tools/python/xen/xm/main.py Tue Aug 08 19:07:32 2006 -0500 43.2 +++ b/tools/python/xen/xm/main.py Wed Aug 09 18:04:20 2006 +0100 43.3 @@ -1257,6 +1257,16 @@ def main(argv=sys.argv): 43.4 else: 43.5 print >>sys.stderr, "Error: %s" % ex.faultString 43.6 sys.exit(1) 43.7 + except xmlrpclib.ProtocolError, ex: 43.8 + if ex.errcode == -1: 43.9 + print >>sys.stderr, ( 43.10 + "Xend has probably crashed! Invalid or missing HTTP " 43.11 + "status code.") 43.12 + else: 43.13 + print >>sys.stderr, ( 43.14 + "Xend has probably crashed! ProtocolError(%d, %s)." % 43.15 + (ex.errcode, ex.errmsg)) 43.16 + sys.exit(1) 43.17 except (ValueError, OverflowError): 43.18 err("Invalid argument.") 43.19 usage(argv[1])
44.1 --- a/tools/python/xen/xm/tests/test_create.py Tue Aug 08 19:07:32 2006 -0500 44.2 +++ b/tools/python/xen/xm/tests/test_create.py Wed Aug 09 18:04:20 2006 +0100 44.3 @@ -179,7 +179,8 @@ ne2000=0 44.4 44.5 'extra' : ('VNC_VIEWER=%s:%d ' % 44.6 (xen.xm.create.get_host_addr(), 44.7 - xen.xm.create.VNC_BASE_PORT + 1)), 44.8 + xen.xm.create.VNC_BASE_PORT + 44.9 + xen.xm.create.choose_vnc_display())), 44.10 'vnc' : 1, 44.11 'vncviewer' : 1, 44.12
45.1 --- a/tools/xenstat/libxenstat/src/xenstat.c Tue Aug 08 19:07:32 2006 -0500 45.2 +++ b/tools/xenstat/libxenstat/src/xenstat.c Wed Aug 09 18:04:20 2006 +0100 45.3 @@ -103,7 +103,10 @@ struct xenstat_vbd { 45.4 * Data-collection types 45.5 */ 45.6 /* Called to collect the information for the node and all the domains on 45.7 - * it. When called, the domain information has already been collected. */ 45.8 + * it. When called, the domain information has already been collected. 45.9 + * Return status is 0 if fatal error occurs, 1 for success. Collectors 45.10 + * may prune a domain from the list if it has been deleted between the 45.11 + * time the list was setup and the time the colector is called */ 45.12 typedef int (*xenstat_collect_func)(xenstat_node * node); 45.13 /* Called to free the information collected by the collect function. The free 45.14 * function will only be called on a xenstat_node if that node includes 45.15 @@ -134,6 +137,7 @@ static void xenstat_uninit_networks(xens 45.16 static void xenstat_uninit_xen_version(xenstat_handle * handle); 45.17 static void xenstat_uninit_vbds(xenstat_handle * handle); 45.18 static char *xenstat_get_domain_name(xenstat_handle * handle, unsigned int domain_id); 45.19 +static void xenstat_prune_domain(xenstat_node *node, unsigned int entry); 45.20 45.21 static xenstat_collector collectors[] = { 45.22 { XENSTAT_VCPU, xenstat_collect_vcpus, 45.23 @@ -208,7 +212,7 @@ xenstat_node *xenstat_get_node(xenstat_h 45.24 xenstat_node *node; 45.25 dom0_physinfo_t physinfo; 45.26 dom0_getdomaininfo_t domaininfo[DOMAIN_CHUNK_SIZE]; 45.27 - unsigned int num_domains, new_domains; 45.28 + unsigned int new_domains; 45.29 unsigned int i; 45.30 45.31 /* Create the node */ 45.32 @@ -242,15 +246,17 @@ xenstat_node *xenstat_get_node(xenstat_h 45.33 return NULL; 45.34 } 45.35 45.36 - num_domains = 0; 45.37 + node->num_domains = 0; 45.38 do { 45.39 xenstat_domain *domain, *tmp; 45.40 45.41 new_domains = xc_domain_getinfolist(handle->xc_handle, 45.42 - num_domains, DOMAIN_CHUNK_SIZE, domaininfo); 45.43 + node->num_domains, 45.44 + DOMAIN_CHUNK_SIZE, 45.45 + domaininfo); 45.46 45.47 tmp = realloc(node->domains, 45.48 - (num_domains + new_domains) 45.49 + (node->num_domains + new_domains) 45.50 * sizeof(xenstat_domain)); 45.51 if (tmp == NULL) { 45.52 free(node->domains); 45.53 @@ -259,12 +265,29 @@ xenstat_node *xenstat_get_node(xenstat_h 45.54 } 45.55 node->domains = tmp; 45.56 45.57 - domain = node->domains + num_domains; 45.58 + domain = node->domains + node->num_domains; 45.59 + 45.60 + /* zero out newly allocated memory in case error occurs below */ 45.61 + memset(domain, 0, new_domains * sizeof(xenstat_domain)); 45.62 45.63 for (i = 0; i < new_domains; i++) { 45.64 /* Fill in domain using domaininfo[i] */ 45.65 domain->id = domaininfo[i].domain; 45.66 - domain->name = xenstat_get_domain_name(handle, domaininfo[i].domain); 45.67 + domain->name = xenstat_get_domain_name(handle, 45.68 + domain->id); 45.69 + if (domain->name == NULL) { 45.70 + if (errno == ENOMEM) { 45.71 + /* fatal error */ 45.72 + xenstat_free_node(node); 45.73 + return NULL; 45.74 + } 45.75 + else { 45.76 + /* failed to get name -- this means the 45.77 + domain is being destroyed so simply 45.78 + ignore this entry */ 45.79 + continue; 45.80 + } 45.81 + } 45.82 domain->state = domaininfo[i].flags; 45.83 domain->cpu_ns = domaininfo[i].cpu_time; 45.84 domain->num_vcpus = (domaininfo[i].max_vcpu_id+1); 45.85 @@ -284,10 +307,9 @@ xenstat_node *xenstat_get_node(xenstat_h 45.86 domain->vbds = NULL; 45.87 45.88 domain++; 45.89 + node->num_domains++; 45.90 } 45.91 - num_domains += new_domains; 45.92 } while (new_domains == DOMAIN_CHUNK_SIZE); 45.93 - node->num_domains = num_domains; 45.94 45.95 /* Run all the extra data collectors requested */ 45.96 node->flags = 0; 45.97 @@ -495,10 +517,12 @@ xenstat_vbd *xenstat_domain_vbd(xenstat_ 45.98 /* Collect information about VCPUs */ 45.99 static int xenstat_collect_vcpus(xenstat_node * node) 45.100 { 45.101 - unsigned int i, vcpu; 45.102 + unsigned int i, vcpu, inc_index; 45.103 45.104 /* Fill in VCPU information */ 45.105 - for (i = 0; i < node->num_domains; i++) { 45.106 + for (i = 0; i < node->num_domains; i+=inc_index) { 45.107 + inc_index = 1; /* default is to increment to next domain */ 45.108 + 45.109 node->domains[i].vcpus = malloc(node->domains[i].num_vcpus 45.110 * sizeof(xenstat_vcpu)); 45.111 if (node->domains[i].vcpus == NULL) 45.112 @@ -509,11 +533,25 @@ static int xenstat_collect_vcpus(xenstat 45.113 dom0_getvcpuinfo_t info; 45.114 45.115 if (xc_vcpu_getinfo(node->handle->xc_handle, 45.116 - node->domains[i].id, vcpu, &info) != 0) 45.117 - return 0; 45.118 + node->domains[i].id, vcpu, &info) != 0) { 45.119 + if (errno == ENOMEM) { 45.120 + /* fatal error */ 45.121 + return 0; 45.122 + } 45.123 + else { 45.124 + /* domain is in transition - remove 45.125 + from list */ 45.126 + xenstat_prune_domain(node, i); 45.127 45.128 - node->domains[i].vcpus[vcpu].online = info.online; 45.129 - node->domains[i].vcpus[vcpu].ns = info.cpu_time; 45.130 + /* remember not to increment index! */ 45.131 + inc_index = 0; 45.132 + break; 45.133 + } 45.134 + } 45.135 + else { 45.136 + node->domains[i].vcpus[vcpu].online = info.online; 45.137 + node->domains[i].vcpus[vcpu].ns = info.cpu_time; 45.138 + } 45.139 } 45.140 } 45.141 return 1; 45.142 @@ -884,13 +922,30 @@ unsigned long long xenstat_vbd_wr_reqs(x 45.143 static char *xenstat_get_domain_name(xenstat_handle *handle, unsigned int domain_id) 45.144 { 45.145 char path[80]; 45.146 - char *name; 45.147 45.148 snprintf(path, sizeof(path),"/local/domain/%i/name", domain_id); 45.149 45.150 - name = xs_read(handle->xshandle, XBT_NULL, path, NULL); 45.151 - if (name == NULL) 45.152 - name = strdup(" "); 45.153 + return xs_read(handle->xshandle, XBT_NULL, path, NULL); 45.154 +} 45.155 + 45.156 +/* Remove specified entry from list of domains */ 45.157 +static void xenstat_prune_domain(xenstat_node *node, unsigned int entry) 45.158 +{ 45.159 + /* nothing to do if array is empty or entry is beyond end */ 45.160 + if (node->num_domains == 0 || entry >= node->num_domains) 45.161 + return; 45.162 45.163 - return name; 45.164 -} 45.165 + /* decrement count of domains */ 45.166 + node->num_domains--; 45.167 + 45.168 + /* shift entries following specified entry up by one */ 45.169 + if (entry < node->num_domains) { 45.170 + xenstat_domain *domain = &node->domains[entry]; 45.171 + memmove(domain,domain+1,node->num_domains-entry); 45.172 + } 45.173 + 45.174 + /* zero out original last entry from node -- not 45.175 + strictly necessary but safer! */ 45.176 + memset(&node->domains[node->num_domains], 0, sizeof(xenstat_domain)); 45.177 +} 45.178 +
46.1 --- a/xen/arch/ia64/xen/hypercall.c Tue Aug 08 19:07:32 2006 -0500 46.2 +++ b/xen/arch/ia64/xen/hypercall.c Wed Aug 09 18:04:20 2006 +0100 46.3 @@ -335,7 +335,7 @@ ia64_hypercall (struct pt_regs *regs) 46.4 unsigned long hypercall_create_continuation( 46.5 unsigned int op, const char *format, ...) 46.6 { 46.7 - struct mc_state *mcs = &mc_state[smp_processor_id()]; 46.8 + struct mc_state *mcs = &this_cpu(mc_state); 46.9 struct vcpu *v = current; 46.10 const char *p = format; 46.11 unsigned long arg;
47.1 --- a/xen/arch/ia64/xen/xensetup.c Tue Aug 08 19:07:32 2006 -0500 47.2 +++ b/xen/arch/ia64/xen/xensetup.c Wed Aug 09 18:04:20 2006 +0100 47.3 @@ -423,13 +423,14 @@ void start_kernel(void) 47.4 (xenheap_phys_end-__pa(heap_start)) >> 20, 47.5 (xenheap_phys_end-__pa(heap_start)) >> 10); 47.6 47.7 + late_setup_arch(&cmdline); 47.8 + 47.9 scheduler_init(); 47.10 idle_vcpu[0] = (struct vcpu*) ia64_r13; 47.11 idle_domain = domain_create(IDLE_DOMAIN_ID); 47.12 if ( (idle_domain == NULL) || (alloc_vcpu(idle_domain, 0, 0) == NULL) ) 47.13 BUG(); 47.14 47.15 - late_setup_arch(&cmdline); 47.16 alloc_dom_xen_and_dom_io(); 47.17 setup_per_cpu_areas(); 47.18 mem_init();
48.1 --- a/xen/arch/powerpc/setup.c Tue Aug 08 19:07:32 2006 -0500 48.2 +++ b/xen/arch/powerpc/setup.c Wed Aug 09 18:04:20 2006 +0100 48.3 @@ -55,7 +55,7 @@ int opt_earlygdb = 0; 48.4 boolean_param("earlygdb", opt_earlygdb); 48.5 48.6 u32 tlbflush_clock = 1U; 48.7 -u32 tlbflush_time[NR_CPUS]; 48.8 +DEFINE_PER_CPU(u32, tlbflush_time); 48.9 48.10 unsigned int watchdog_on; 48.11 unsigned long wait_init_idle;
49.1 --- a/xen/arch/x86/domain.c Tue Aug 08 19:07:32 2006 -0500 49.2 +++ b/xen/arch/x86/domain.c Wed Aug 09 18:04:20 2006 +0100 49.3 @@ -797,7 +797,7 @@ void sync_vcpu_execstate(struct vcpu *v) 49.4 unsigned long hypercall_create_continuation( 49.5 unsigned int op, const char *format, ...) 49.6 { 49.7 - struct mc_state *mcs = &mc_state[smp_processor_id()]; 49.8 + struct mc_state *mcs = &this_cpu(mc_state); 49.9 struct cpu_user_regs *regs; 49.10 const char *p = format; 49.11 unsigned long arg;
50.1 --- a/xen/arch/x86/flushtlb.c Tue Aug 08 19:07:32 2006 -0500 50.2 +++ b/xen/arch/x86/flushtlb.c Wed Aug 09 18:04:20 2006 +0100 50.3 @@ -20,7 +20,7 @@ 50.4 #endif 50.5 50.6 u32 tlbflush_clock = 1U; 50.7 -u32 tlbflush_time[NR_CPUS]; 50.8 +DEFINE_PER_CPU(u32, tlbflush_time); 50.9 50.10 void write_cr3(unsigned long cr3) 50.11 { 50.12 @@ -71,7 +71,7 @@ void write_cr3(unsigned long cr3) 50.13 * case, so really we are being ultra paranoid. 50.14 */ 50.15 50.16 - tlbflush_time[smp_processor_id()] = t2; 50.17 + this_cpu(tlbflush_time) = t2; 50.18 50.19 local_irq_restore(flags); 50.20 }
51.1 --- a/xen/arch/x86/hvm/hvm.c Tue Aug 08 19:07:32 2006 -0500 51.2 +++ b/xen/arch/x86/hvm/hvm.c Wed Aug 09 18:04:20 2006 +0100 51.3 @@ -29,6 +29,7 @@ 51.4 #include <xen/domain_page.h> 51.5 #include <xen/hypercall.h> 51.6 #include <xen/guest_access.h> 51.7 +#include <xen/event.h> 51.8 #include <asm/current.h> 51.9 #include <asm/io.h> 51.10 #include <asm/shadow.h> 51.11 @@ -133,15 +134,28 @@ static void e820_map_io_shared_callback( 51.12 } 51.13 } 51.14 51.15 -void hvm_map_io_shared_page(struct vcpu *v) 51.16 +static void e820_map_buffered_io_callback(struct domain *d, 51.17 + struct e820entry *e, 51.18 + void *data) 51.19 { 51.20 - unsigned long mfn = INVALID_MFN; 51.21 + unsigned long *mfn = data; 51.22 + if ( e->type == E820_BUFFERED_IO ) { 51.23 + ASSERT(*mfn == INVALID_MFN); 51.24 + *mfn = gmfn_to_mfn(d, e->addr >> PAGE_SHIFT); 51.25 + } 51.26 +} 51.27 + 51.28 +void hvm_map_io_shared_pages(struct vcpu *v) 51.29 +{ 51.30 + unsigned long mfn; 51.31 void *p; 51.32 struct domain *d = v->domain; 51.33 51.34 - if ( d->arch.hvm_domain.shared_page_va ) 51.35 + if ( d->arch.hvm_domain.shared_page_va || 51.36 + d->arch.hvm_domain.buffered_io_va ) 51.37 return; 51.38 51.39 + mfn = INVALID_MFN; 51.40 e820_foreach(d, e820_map_io_shared_callback, &mfn); 51.41 51.42 if ( mfn == INVALID_MFN ) 51.43 @@ -158,8 +172,39 @@ void hvm_map_io_shared_page(struct vcpu 51.44 } 51.45 51.46 d->arch.hvm_domain.shared_page_va = (unsigned long)p; 51.47 + 51.48 + mfn = INVALID_MFN; 51.49 + e820_foreach(d, e820_map_buffered_io_callback, &mfn); 51.50 + if ( mfn != INVALID_MFN ) { 51.51 + p = map_domain_page_global(mfn); 51.52 + if ( p ) 51.53 + d->arch.hvm_domain.buffered_io_va = (unsigned long)p; 51.54 + } 51.55 } 51.56 51.57 +void hvm_create_event_channels(struct vcpu *v) 51.58 +{ 51.59 + vcpu_iodata_t *p; 51.60 + struct vcpu *o; 51.61 + 51.62 + if ( v->vcpu_id == 0 ) { 51.63 + /* Ugly: create event channels for every vcpu when vcpu 0 51.64 + starts, so that they're available for ioemu to bind to. */ 51.65 + for_each_vcpu(v->domain, o) { 51.66 + p = get_vio(v->domain, o->vcpu_id); 51.67 + o->arch.hvm_vcpu.xen_port = p->vp_eport = 51.68 + alloc_unbound_xen_event_channel(o, 0); 51.69 + DPRINTK("Allocated port %d for hvm.\n", o->arch.hvm_vcpu.xen_port); 51.70 + } 51.71 + } 51.72 +} 51.73 + 51.74 +void hvm_release_assist_channel(struct vcpu *v) 51.75 +{ 51.76 + free_xen_event_channel(v, v->arch.hvm_vcpu.xen_port); 51.77 +} 51.78 + 51.79 + 51.80 void hvm_setup_platform(struct domain* d) 51.81 { 51.82 struct hvm_domain *platform; 51.83 @@ -175,7 +220,6 @@ void hvm_setup_platform(struct domain* d 51.84 } 51.85 51.86 hvm_zap_iommu_pages(d); 51.87 - hvm_map_io_shared_page(v); 51.88 51.89 platform = &d->arch.hvm_domain; 51.90 pic_init(&platform->vpic, pic_irq_request, &platform->interrupt_request); 51.91 @@ -187,6 +231,8 @@ void hvm_setup_platform(struct domain* d 51.92 hvm_vioapic_init(d); 51.93 } 51.94 51.95 + spin_lock_init(&d->arch.hvm_domain.buffered_io_lock); 51.96 + 51.97 init_timer(&platform->pl_time.periodic_tm.timer, 51.98 pt_timer_fn, v, v->processor); 51.99 pit_init(v, cpu_khz);
52.1 --- a/xen/arch/x86/hvm/intercept.c Tue Aug 08 19:07:32 2006 -0500 52.2 +++ b/xen/arch/x86/hvm/intercept.c Wed Aug 09 18:04:20 2006 +0100 52.3 @@ -36,12 +36,26 @@ extern struct hvm_mmio_handler vioapic_m 52.4 52.5 #define HVM_MMIO_HANDLER_NR 2 52.6 52.7 -struct hvm_mmio_handler *hvm_mmio_handlers[HVM_MMIO_HANDLER_NR] = 52.8 +static struct hvm_mmio_handler *hvm_mmio_handlers[HVM_MMIO_HANDLER_NR] = 52.9 { 52.10 &vlapic_mmio_handler, 52.11 &vioapic_mmio_handler 52.12 }; 52.13 52.14 +struct hvm_buffered_io_range { 52.15 + unsigned long start_addr; 52.16 + unsigned long length; 52.17 +}; 52.18 + 52.19 +#define HVM_BUFFERED_IO_RANGE_NR 1 52.20 + 52.21 +static struct hvm_buffered_io_range buffered_stdvga_range = {0xA0000, 0x20000}; 52.22 +static struct hvm_buffered_io_range 52.23 +*hvm_buffered_io_ranges[HVM_BUFFERED_IO_RANGE_NR] = 52.24 +{ 52.25 + &buffered_stdvga_range 52.26 +}; 52.27 + 52.28 static inline void hvm_mmio_access(struct vcpu *v, 52.29 ioreq_t *p, 52.30 hvm_mmio_read_t read_handler, 52.31 @@ -140,6 +154,56 @@ static inline void hvm_mmio_access(struc 52.32 } 52.33 } 52.34 52.35 +int hvm_buffered_io_intercept(ioreq_t *p) 52.36 +{ 52.37 + struct vcpu *v = current; 52.38 + spinlock_t *buffered_io_lock; 52.39 + buffered_iopage_t *buffered_iopage = 52.40 + (buffered_iopage_t *)(v->domain->arch.hvm_domain.buffered_io_va); 52.41 + unsigned long tmp_write_pointer = 0; 52.42 + int i; 52.43 + 52.44 + /* ignore READ ioreq_t! */ 52.45 + if ( p->dir == IOREQ_READ ) 52.46 + return 0; 52.47 + 52.48 + for ( i = 0; i < HVM_BUFFERED_IO_RANGE_NR; i++ ) { 52.49 + if ( p->addr >= hvm_buffered_io_ranges[i]->start_addr && 52.50 + p->addr + p->size - 1 < hvm_buffered_io_ranges[i]->start_addr + 52.51 + hvm_buffered_io_ranges[i]->length ) 52.52 + break; 52.53 + } 52.54 + 52.55 + if ( i == HVM_BUFFERED_IO_RANGE_NR ) 52.56 + return 0; 52.57 + 52.58 + buffered_io_lock = &v->domain->arch.hvm_domain.buffered_io_lock; 52.59 + spin_lock(buffered_io_lock); 52.60 + 52.61 + if ( buffered_iopage->write_pointer - buffered_iopage->read_pointer == 52.62 + (unsigned long)IOREQ_BUFFER_SLOT_NUM ) { 52.63 + /* the queue is full. 52.64 + * send the iopacket through the normal path. 52.65 + * NOTE: The arithimetic operation could handle the situation for 52.66 + * write_pointer overflow. 52.67 + */ 52.68 + spin_unlock(buffered_io_lock); 52.69 + return 0; 52.70 + } 52.71 + 52.72 + tmp_write_pointer = buffered_iopage->write_pointer % IOREQ_BUFFER_SLOT_NUM; 52.73 + 52.74 + memcpy(&buffered_iopage->ioreq[tmp_write_pointer], p, sizeof(ioreq_t)); 52.75 + 52.76 + /*make the ioreq_t visible before write_pointer*/ 52.77 + wmb(); 52.78 + buffered_iopage->write_pointer++; 52.79 + 52.80 + spin_unlock(buffered_io_lock); 52.81 + 52.82 + return 1; 52.83 +} 52.84 + 52.85 int hvm_mmio_intercept(ioreq_t *p) 52.86 { 52.87 struct vcpu *v = current; 52.88 @@ -211,7 +275,7 @@ void hlt_timer_fn(void *data) 52.89 { 52.90 struct vcpu *v = data; 52.91 52.92 - evtchn_set_pending(v, iopacket_port(v)); 52.93 + hvm_prod_vcpu(v); 52.94 } 52.95 52.96 static __inline__ void missed_ticks(struct periodic_time *pt)
53.1 --- a/xen/arch/x86/hvm/io.c Tue Aug 08 19:07:32 2006 -0500 53.2 +++ b/xen/arch/x86/hvm/io.c Wed Aug 09 18:04:20 2006 +0100 53.3 @@ -687,84 +687,17 @@ void hvm_io_assist(struct vcpu *v) 53.4 53.5 p = &vio->vp_ioreq; 53.6 53.7 - /* clear IO wait HVM flag */ 53.8 - if ( test_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags) ) { 53.9 - if ( p->state == STATE_IORESP_READY ) { 53.10 - p->state = STATE_INVALID; 53.11 - clear_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags); 53.12 - 53.13 - if ( p->type == IOREQ_TYPE_PIO ) 53.14 - hvm_pio_assist(regs, p, io_opp); 53.15 - else 53.16 - hvm_mmio_assist(regs, p, io_opp); 53.17 - 53.18 - /* Copy register changes back into current guest state. */ 53.19 - hvm_load_cpu_guest_regs(v, regs); 53.20 - memcpy(guest_cpu_user_regs(), regs, HVM_CONTEXT_STACK_BYTES); 53.21 - } 53.22 - /* else an interrupt send event raced us */ 53.23 - } 53.24 -} 53.25 - 53.26 -/* 53.27 - * On exit from hvm_wait_io, we're guaranteed not to be waiting on 53.28 - * I/O response from the device model. 53.29 - */ 53.30 -void hvm_wait_io(void) 53.31 -{ 53.32 - struct vcpu *v = current; 53.33 - struct domain *d = v->domain; 53.34 - int port = iopacket_port(v); 53.35 - 53.36 - for ( ; ; ) 53.37 - { 53.38 - /* Clear master flag, selector flag, event flag each in turn. */ 53.39 - v->vcpu_info->evtchn_upcall_pending = 0; 53.40 - clear_bit(port/BITS_PER_LONG, &v->vcpu_info->evtchn_pending_sel); 53.41 - smp_mb__after_clear_bit(); 53.42 - if ( test_and_clear_bit(port, &d->shared_info->evtchn_pending[0]) ) 53.43 - hvm_io_assist(v); 53.44 + if ( p->state == STATE_IORESP_READY ) { 53.45 + p->state = STATE_INVALID; 53.46 + if ( p->type == IOREQ_TYPE_PIO ) 53.47 + hvm_pio_assist(regs, p, io_opp); 53.48 + else 53.49 + hvm_mmio_assist(regs, p, io_opp); 53.50 53.51 - /* Need to wait for I/O responses? */ 53.52 - if ( !test_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags) ) 53.53 - break; 53.54 - 53.55 - do_sched_op_compat(SCHEDOP_block, 0); 53.56 + /* Copy register changes back into current guest state. */ 53.57 + hvm_load_cpu_guest_regs(v, regs); 53.58 + memcpy(guest_cpu_user_regs(), regs, HVM_CONTEXT_STACK_BYTES); 53.59 } 53.60 - 53.61 - /* 53.62 - * Re-set the selector and master flags in case any other notifications 53.63 - * are pending. 53.64 - */ 53.65 - if ( d->shared_info->evtchn_pending[port/BITS_PER_LONG] ) 53.66 - set_bit(port/BITS_PER_LONG, &v->vcpu_info->evtchn_pending_sel); 53.67 - if ( v->vcpu_info->evtchn_pending_sel ) 53.68 - v->vcpu_info->evtchn_upcall_pending = 1; 53.69 -} 53.70 - 53.71 -void hvm_safe_block(void) 53.72 -{ 53.73 - struct vcpu *v = current; 53.74 - struct domain *d = v->domain; 53.75 - int port = iopacket_port(v); 53.76 - 53.77 - for ( ; ; ) 53.78 - { 53.79 - /* Clear master flag & selector flag so we will wake from block. */ 53.80 - v->vcpu_info->evtchn_upcall_pending = 0; 53.81 - clear_bit(port/BITS_PER_LONG, &v->vcpu_info->evtchn_pending_sel); 53.82 - smp_mb__after_clear_bit(); 53.83 - 53.84 - /* Event pending already? */ 53.85 - if ( test_bit(port, &d->shared_info->evtchn_pending[0]) ) 53.86 - break; 53.87 - 53.88 - do_sched_op_compat(SCHEDOP_block, 0); 53.89 - } 53.90 - 53.91 - /* Reflect pending event in selector and master flags. */ 53.92 - set_bit(port/BITS_PER_LONG, &v->vcpu_info->evtchn_pending_sel); 53.93 - v->vcpu_info->evtchn_upcall_pending = 1; 53.94 } 53.95 53.96 /*
54.1 --- a/xen/arch/x86/hvm/platform.c Tue Aug 08 19:07:32 2006 -0500 54.2 +++ b/xen/arch/x86/hvm/platform.c Wed Aug 09 18:04:20 2006 +0100 54.3 @@ -669,6 +669,30 @@ int inst_copy_from_guest(unsigned char * 54.4 return inst_len; 54.5 } 54.6 54.7 +static void hvm_send_assist_req(struct vcpu *v) 54.8 +{ 54.9 + ioreq_t *p; 54.10 + 54.11 + p = &get_vio(v->domain, v->vcpu_id)->vp_ioreq; 54.12 + if ( unlikely(p->state != STATE_INVALID) ) { 54.13 + /* This indicates a bug in the device model. Crash the 54.14 + domain. */ 54.15 + printf("Device model set bad IO state %d.\n", p->state); 54.16 + domain_crash(v->domain); 54.17 + return; 54.18 + } 54.19 + wmb(); 54.20 + p->state = STATE_IOREQ_READY; 54.21 + notify_via_xen_event_channel(v->arch.hvm_vcpu.xen_port); 54.22 +} 54.23 + 54.24 + 54.25 +/* Wake up a vcpu whihc is waiting for interrupts to come in */ 54.26 +void hvm_prod_vcpu(struct vcpu *v) 54.27 +{ 54.28 + vcpu_unblock(v); 54.29 +} 54.30 + 54.31 void send_pio_req(struct cpu_user_regs *regs, unsigned long port, 54.32 unsigned long count, int size, long value, int dir, int pvalid) 54.33 { 54.34 @@ -682,13 +706,10 @@ void send_pio_req(struct cpu_user_regs * 54.35 domain_crash_synchronous(); 54.36 } 54.37 54.38 - if (test_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags)) { 54.39 - printf("HVM I/O has not yet completed\n"); 54.40 - domain_crash_synchronous(); 54.41 - } 54.42 - set_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags); 54.43 - 54.44 p = &vio->vp_ioreq; 54.45 + if ( p->state != STATE_INVALID ) 54.46 + printf("WARNING: send pio with something already pending (%d)?\n", 54.47 + p->state); 54.48 p->dir = dir; 54.49 p->pdata_valid = pvalid; 54.50 54.51 @@ -714,10 +735,7 @@ void send_pio_req(struct cpu_user_regs * 54.52 return; 54.53 } 54.54 54.55 - p->state = STATE_IOREQ_READY; 54.56 - 54.57 - evtchn_send(iopacket_port(v)); 54.58 - hvm_wait_io(); 54.59 + hvm_send_assist_req(v); 54.60 } 54.61 54.62 void send_mmio_req( 54.63 @@ -739,12 +757,9 @@ void send_mmio_req( 54.64 54.65 p = &vio->vp_ioreq; 54.66 54.67 - if (test_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags)) { 54.68 - printf("HVM I/O has not yet completed\n"); 54.69 - domain_crash_synchronous(); 54.70 - } 54.71 - 54.72 - set_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags); 54.73 + if ( p->state != STATE_INVALID ) 54.74 + printf("WARNING: send mmio with something already pending (%d)?\n", 54.75 + p->state); 54.76 p->dir = dir; 54.77 p->pdata_valid = pvalid; 54.78 54.79 @@ -764,16 +779,13 @@ void send_mmio_req( 54.80 } else 54.81 p->u.data = value; 54.82 54.83 - if (hvm_mmio_intercept(p)){ 54.84 + if ( hvm_mmio_intercept(p) || hvm_buffered_io_intercept(p) ) { 54.85 p->state = STATE_IORESP_READY; 54.86 hvm_io_assist(v); 54.87 return; 54.88 } 54.89 54.90 - p->state = STATE_IOREQ_READY; 54.91 - 54.92 - evtchn_send(iopacket_port(v)); 54.93 - hvm_wait_io(); 54.94 + hvm_send_assist_req(v); 54.95 } 54.96 54.97 static void mmio_operands(int type, unsigned long gpa, struct instruction *inst,
55.1 --- a/xen/arch/x86/hvm/svm/svm.c Tue Aug 08 19:07:32 2006 -0500 55.2 +++ b/xen/arch/x86/hvm/svm/svm.c Wed Aug 09 18:04:20 2006 +0100 55.3 @@ -25,6 +25,7 @@ 55.4 #include <xen/sched.h> 55.5 #include <xen/irq.h> 55.6 #include <xen/softirq.h> 55.7 +#include <xen/hypercall.h> 55.8 #include <asm/current.h> 55.9 #include <asm/io.h> 55.10 #include <asm/shadow.h> 55.11 @@ -809,6 +810,9 @@ static void svm_relinquish_guest_resourc 55.12 unmap_domain_page_global( 55.13 (void *)d->arch.hvm_domain.shared_page_va); 55.14 55.15 + if ( d->arch.hvm_domain.buffered_io_va ) 55.16 + unmap_domain_page_global((void *)d->arch.hvm_domain.buffered_io_va); 55.17 + 55.18 shadow_direct_map_clean(d); 55.19 } 55.20 55.21 @@ -2121,7 +2125,7 @@ static inline void svm_vmexit_do_hlt(str 55.22 next_wakeup = next_pit; 55.23 if ( next_wakeup != - 1 ) 55.24 set_timer(¤t->arch.hvm_svm.hlt_timer, next_wakeup); 55.25 - hvm_safe_block(); 55.26 + do_sched_op_compat(SCHEDOP_block, 0); 55.27 } 55.28 55.29
56.1 --- a/xen/arch/x86/hvm/svm/vmcb.c Tue Aug 08 19:07:32 2006 -0500 56.2 +++ b/xen/arch/x86/hvm/svm/vmcb.c Wed Aug 09 18:04:20 2006 +0100 56.3 @@ -370,18 +370,6 @@ void svm_do_launch(struct vcpu *v) 56.4 if (v->vcpu_id == 0) 56.5 hvm_setup_platform(v->domain); 56.6 56.7 - if ( evtchn_bind_vcpu(iopacket_port(v), v->vcpu_id) < 0 ) 56.8 - { 56.9 - printk("HVM domain bind port %d to vcpu %d failed!\n", 56.10 - iopacket_port(v), v->vcpu_id); 56.11 - domain_crash_synchronous(); 56.12 - } 56.13 - 56.14 - HVM_DBG_LOG(DBG_LEVEL_1, "eport: %x", iopacket_port(v)); 56.15 - 56.16 - clear_bit(iopacket_port(v), 56.17 - &v->domain->shared_info->evtchn_mask[0]); 56.18 - 56.19 if (hvm_apic_support(v->domain)) 56.20 vlapic_init(v); 56.21 init_timer(&v->arch.hvm_svm.hlt_timer, 56.22 @@ -439,10 +427,12 @@ void set_hsa_to_guest( struct arch_svm_s 56.23 /* 56.24 * Resume the guest. 56.25 */ 56.26 +/* XXX svm_do_resume and vmx_do_resume are remarkably similar; could 56.27 + they be unified? */ 56.28 void svm_do_resume(struct vcpu *v) 56.29 { 56.30 - struct domain *d = v->domain; 56.31 - struct periodic_time *pt = &d->arch.hvm_domain.pl_time.periodic_tm; 56.32 + struct periodic_time *pt = &v->domain->arch.hvm_domain.pl_time.periodic_tm; 56.33 + ioreq_t *p; 56.34 56.35 svm_stts(v); 56.36 56.37 @@ -455,12 +445,16 @@ void svm_do_resume(struct vcpu *v) 56.38 pickup_deactive_ticks(pt); 56.39 } 56.40 56.41 - if ( test_bit(iopacket_port(v), &d->shared_info->evtchn_pending[0]) || 56.42 - test_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags) ) 56.43 - hvm_wait_io(); 56.44 - 56.45 - /* We can't resume the guest if we're waiting on I/O */ 56.46 - ASSERT(!test_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags)); 56.47 + p = &get_vio(v->domain, v->vcpu_id)->vp_ioreq; 56.48 + wait_on_xen_event_channel(v->arch.hvm.xen_port, 56.49 + p->state != STATE_IOREQ_READY && 56.50 + p->state != STATE_IOREQ_INPROCESS); 56.51 + if ( p->state == STATE_IORESP_READY ) 56.52 + hvm_io_assist(v); 56.53 + if ( p->state != STATE_INVALID ) { 56.54 + printf("Weird HVM iorequest state %d.\n", p->state); 56.55 + domain_crash(v->domain); 56.56 + } 56.57 } 56.58 56.59 void svm_launch_fail(unsigned long eflags)
57.1 --- a/xen/arch/x86/hvm/svm/x86_32/exits.S Tue Aug 08 19:07:32 2006 -0500 57.2 +++ b/xen/arch/x86/hvm/svm/x86_32/exits.S Wed Aug 09 18:04:20 2006 +0100 57.3 @@ -132,6 +132,9 @@ ENTRY(svm_asm_do_launch) 57.4 ENTRY(svm_asm_do_resume) 57.5 svm_test_all_events: 57.6 GET_CURRENT(%ebx) 57.7 + pushl %ebx 57.8 + call svm_do_resume 57.9 + addl $4, %esp 57.10 /*test_all_events:*/ 57.11 xorl %ecx,%ecx 57.12 notl %ecx
58.1 --- a/xen/arch/x86/hvm/svm/x86_64/exits.S Tue Aug 08 19:07:32 2006 -0500 58.2 +++ b/xen/arch/x86/hvm/svm/x86_64/exits.S Wed Aug 09 18:04:20 2006 +0100 58.3 @@ -147,6 +147,8 @@ ENTRY(svm_asm_do_launch) 58.4 ENTRY(svm_asm_do_resume) 58.5 svm_test_all_events: 58.6 GET_CURRENT(%rbx) 58.7 + movq %rbx, %rdi 58.8 + call svm_do_resume 58.9 /*test_all_events:*/ 58.10 cli # tests must not race interrupts 58.11 /*test_softirqs:*/
59.1 --- a/xen/arch/x86/hvm/vlapic.c Tue Aug 08 19:07:32 2006 -0500 59.2 +++ b/xen/arch/x86/hvm/vlapic.c Wed Aug 09 18:04:20 2006 +0100 59.3 @@ -232,7 +232,7 @@ static int vlapic_accept_irq(struct vcpu 59.4 "level trig mode for vector %d\n", vector); 59.5 set_bit(vector, vlapic->regs + APIC_TMR); 59.6 } 59.7 - evtchn_set_pending(v, iopacket_port(v)); 59.8 + hvm_prod_vcpu(v); 59.9 59.10 result = 1; 59.11 break;
60.1 --- a/xen/arch/x86/hvm/vmx/io.c Tue Aug 08 19:07:32 2006 -0500 60.2 +++ b/xen/arch/x86/hvm/vmx/io.c Wed Aug 09 18:04:20 2006 +0100 60.3 @@ -221,7 +221,7 @@ asmlinkage void vmx_intr_assist(void) 60.4 60.5 void vmx_do_resume(struct vcpu *v) 60.6 { 60.7 - struct domain *d = v->domain; 60.8 + ioreq_t *p; 60.9 struct periodic_time *pt = &v->domain->arch.hvm_domain.pl_time.periodic_tm; 60.10 60.11 vmx_stts(); 60.12 @@ -235,12 +235,16 @@ void vmx_do_resume(struct vcpu *v) 60.13 pickup_deactive_ticks(pt); 60.14 } 60.15 60.16 - if ( test_bit(iopacket_port(v), &d->shared_info->evtchn_pending[0]) || 60.17 - test_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags) ) 60.18 - hvm_wait_io(); 60.19 - 60.20 - /* We can't resume the guest if we're waiting on I/O */ 60.21 - ASSERT(!test_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags)); 60.22 + p = &get_vio(v->domain, v->vcpu_id)->vp_ioreq; 60.23 + wait_on_xen_event_channel(v->arch.hvm.xen_port, 60.24 + p->state != STATE_IOREQ_READY && 60.25 + p->state != STATE_IOREQ_INPROCESS); 60.26 + if ( p->state == STATE_IORESP_READY ) 60.27 + hvm_io_assist(v); 60.28 + if ( p->state != STATE_INVALID ) { 60.29 + printf("Weird HVM iorequest state %d.\n", p->state); 60.30 + domain_crash(v->domain); 60.31 + } 60.32 } 60.33 60.34 /*
61.1 --- a/xen/arch/x86/hvm/vmx/vmcs.c Tue Aug 08 19:07:32 2006 -0500 61.2 +++ b/xen/arch/x86/hvm/vmx/vmcs.c Wed Aug 09 18:04:20 2006 +0100 61.3 @@ -245,18 +245,6 @@ static void vmx_do_launch(struct vcpu *v 61.4 if (v->vcpu_id == 0) 61.5 hvm_setup_platform(v->domain); 61.6 61.7 - if ( evtchn_bind_vcpu(iopacket_port(v), v->vcpu_id) < 0 ) 61.8 - { 61.9 - printk("VMX domain bind port %d to vcpu %d failed!\n", 61.10 - iopacket_port(v), v->vcpu_id); 61.11 - domain_crash_synchronous(); 61.12 - } 61.13 - 61.14 - HVM_DBG_LOG(DBG_LEVEL_1, "eport: %x", iopacket_port(v)); 61.15 - 61.16 - clear_bit(iopacket_port(v), 61.17 - &v->domain->shared_info->evtchn_mask[0]); 61.18 - 61.19 __asm__ __volatile__ ("mov %%cr0,%0" : "=r" (cr0) : ); 61.20 61.21 error |= __vmwrite(GUEST_CR0, cr0);
62.1 --- a/xen/arch/x86/hvm/vmx/vmx.c Tue Aug 08 19:07:32 2006 -0500 62.2 +++ b/xen/arch/x86/hvm/vmx/vmx.c Wed Aug 09 18:04:20 2006 +0100 62.3 @@ -25,6 +25,7 @@ 62.4 #include <xen/irq.h> 62.5 #include <xen/softirq.h> 62.6 #include <xen/domain_page.h> 62.7 +#include <xen/hypercall.h> 62.8 #include <asm/current.h> 62.9 #include <asm/io.h> 62.10 #include <asm/shadow.h> 62.11 @@ -48,8 +49,8 @@ 62.12 #include <asm/hvm/vpic.h> 62.13 #include <asm/hvm/vlapic.h> 62.14 62.15 -static unsigned long trace_values[NR_CPUS][5]; 62.16 -#define TRACE_VMEXIT(index,value) trace_values[smp_processor_id()][index]=value 62.17 +static DEFINE_PER_CPU(unsigned long, trace_values[5]); 62.18 +#define TRACE_VMEXIT(index,value) this_cpu(trace_values)[index]=value 62.19 62.20 static void vmx_ctxt_switch_from(struct vcpu *v); 62.21 static void vmx_ctxt_switch_to(struct vcpu *v); 62.22 @@ -141,6 +142,7 @@ static void vmx_relinquish_guest_resourc 62.23 free_domheap_page(VLAPIC(v)->regs_page); 62.24 xfree(VLAPIC(v)); 62.25 } 62.26 + hvm_release_assist_channel(v); 62.27 } 62.28 62.29 kill_timer(&d->arch.hvm_domain.pl_time.periodic_tm.timer); 62.30 @@ -149,12 +151,15 @@ static void vmx_relinquish_guest_resourc 62.31 unmap_domain_page_global( 62.32 (void *)d->arch.hvm_domain.shared_page_va); 62.33 62.34 + if ( d->arch.hvm_domain.buffered_io_va ) 62.35 + unmap_domain_page_global((void *)d->arch.hvm_domain.buffered_io_va); 62.36 + 62.37 shadow_direct_map_clean(d); 62.38 } 62.39 62.40 #ifdef __x86_64__ 62.41 62.42 -static struct vmx_msr_state percpu_msr[NR_CPUS]; 62.43 +static DEFINE_PER_CPU(struct vmx_msr_state, percpu_msr); 62.44 62.45 static u32 msr_data_index[VMX_MSR_COUNT] = 62.46 { 62.47 @@ -175,7 +180,7 @@ static void vmx_save_segments(struct vcp 62.48 */ 62.49 static void vmx_load_msrs(void) 62.50 { 62.51 - struct vmx_msr_state *host_state = &percpu_msr[smp_processor_id()]; 62.52 + struct vmx_msr_state *host_state = &this_cpu(percpu_msr); 62.53 int i; 62.54 62.55 while ( host_state->flags ) 62.56 @@ -188,7 +193,7 @@ static void vmx_load_msrs(void) 62.57 62.58 static void vmx_save_init_msrs(void) 62.59 { 62.60 - struct vmx_msr_state *host_state = &percpu_msr[smp_processor_id()]; 62.61 + struct vmx_msr_state *host_state = &this_cpu(percpu_msr); 62.62 int i; 62.63 62.64 for ( i = 0; i < VMX_MSR_COUNT; i++ ) 62.65 @@ -277,7 +282,7 @@ static inline int long_mode_do_msr_write 62.66 u64 msr_content = regs->eax | ((u64)regs->edx << 32); 62.67 struct vcpu *v = current; 62.68 struct vmx_msr_state *msr = &v->arch.hvm_vmx.msr_content; 62.69 - struct vmx_msr_state *host_state = &percpu_msr[smp_processor_id()]; 62.70 + struct vmx_msr_state *host_state = &this_cpu(percpu_msr); 62.71 62.72 HVM_DBG_LOG(DBG_LEVEL_1, "msr 0x%lx msr_content 0x%"PRIx64"\n", 62.73 (unsigned long)regs->ecx, msr_content); 62.74 @@ -359,7 +364,7 @@ static void vmx_restore_msrs(struct vcpu 62.75 unsigned long guest_flags ; 62.76 62.77 guest_state = &v->arch.hvm_vmx.msr_content;; 62.78 - host_state = &percpu_msr[smp_processor_id()]; 62.79 + host_state = &this_cpu(percpu_msr); 62.80 62.81 wrmsrl(MSR_SHADOW_GS_BASE, guest_state->shadow_gs); 62.82 guest_flags = guest_state->flags; 62.83 @@ -671,6 +676,28 @@ static int check_vmx_controls(u32 ctrls, 62.84 return 1; 62.85 } 62.86 62.87 +static void vmx_init_hypercall_page(struct domain *d, void *hypercall_page) 62.88 +{ 62.89 + char *p; 62.90 + int i; 62.91 + 62.92 + memset(hypercall_page, 0, PAGE_SIZE); 62.93 + 62.94 + for ( i = 0; i < (PAGE_SIZE / 32); i++ ) 62.95 + { 62.96 + p = (char *)(hypercall_page + (i * 32)); 62.97 + *(u8 *)(p + 0) = 0xb8; /* mov imm32, %eax */ 62.98 + *(u32 *)(p + 1) = i; 62.99 + *(u8 *)(p + 5) = 0x0f; /* vmcall */ 62.100 + *(u8 *)(p + 6) = 0x01; 62.101 + *(u8 *)(p + 7) = 0xc1; 62.102 + *(u8 *)(p + 8) = 0xc3; /* ret */ 62.103 + } 62.104 + 62.105 + /* Don't support HYPERVISOR_iret at the moment */ 62.106 + *(u16 *)(hypercall_page + (__HYPERVISOR_iret * 32)) = 0x0b0f; /* ud2 */ 62.107 +} 62.108 + 62.109 /* Setup HVM interfaces */ 62.110 static void vmx_setup_hvm_funcs(void) 62.111 { 62.112 @@ -691,28 +718,8 @@ static void vmx_setup_hvm_funcs(void) 62.113 hvm_funcs.get_guest_ctrl_reg = vmx_get_ctrl_reg; 62.114 62.115 hvm_funcs.init_ap_context = vmx_init_ap_context; 62.116 -} 62.117 62.118 -static void vmx_init_hypercall_page(struct domain *d, void *hypercall_page) 62.119 -{ 62.120 - char *p; 62.121 - int i; 62.122 - 62.123 - memset(hypercall_page, 0, PAGE_SIZE); 62.124 - 62.125 - for ( i = 0; i < (PAGE_SIZE / 32); i++ ) 62.126 - { 62.127 - p = (char *)(hypercall_page + (i * 32)); 62.128 - *(u8 *)(p + 0) = 0xb8; /* mov imm32, %eax */ 62.129 - *(u32 *)(p + 1) = i; 62.130 - *(u8 *)(p + 5) = 0x0f; /* vmcall */ 62.131 - *(u8 *)(p + 6) = 0x01; 62.132 - *(u8 *)(p + 7) = 0xc1; 62.133 - *(u8 *)(p + 8) = 0xc3; /* ret */ 62.134 - } 62.135 - 62.136 - /* Don't support HYPERVISOR_iret at the moment */ 62.137 - *(u16 *)(hypercall_page + (__HYPERVISOR_iret * 32)) = 0x0b0f; /* ud2 */ 62.138 + hvm_funcs.init_hypercall_page = vmx_init_hypercall_page; 62.139 } 62.140 62.141 int start_vmx(void) 62.142 @@ -781,8 +788,6 @@ int start_vmx(void) 62.143 62.144 vmx_setup_hvm_funcs(); 62.145 62.146 - hvm_funcs.init_hypercall_page = vmx_init_hypercall_page; 62.147 - 62.148 hvm_enabled = 1; 62.149 62.150 return 1; 62.151 @@ -2014,7 +2019,7 @@ void vmx_vmexit_do_hlt(void) 62.152 next_wakeup = next_pit; 62.153 if ( next_wakeup != - 1 ) 62.154 set_timer(¤t->arch.hvm_vmx.hlt_timer, next_wakeup); 62.155 - hvm_safe_block(); 62.156 + do_sched_op_compat(SCHEDOP_block, 0); 62.157 } 62.158 62.159 static inline void vmx_vmexit_do_extint(struct cpu_user_regs *regs) 62.160 @@ -2128,12 +2133,10 @@ void restore_cpu_user_regs(struct cpu_us 62.161 asmlinkage void vmx_vmexit_handler(struct cpu_user_regs regs) 62.162 { 62.163 unsigned int exit_reason; 62.164 - unsigned long exit_qualification, eip, inst_len = 0; 62.165 + unsigned long exit_qualification, rip, inst_len = 0; 62.166 struct vcpu *v = current; 62.167 - int error; 62.168 62.169 - error = __vmread(VM_EXIT_REASON, &exit_reason); 62.170 - BUG_ON(error); 62.171 + __vmread(VM_EXIT_REASON, &exit_reason); 62.172 62.173 perfc_incra(vmexits, exit_reason); 62.174 62.175 @@ -2172,11 +2175,9 @@ asmlinkage void vmx_vmexit_handler(struc 62.176 domain_crash_synchronous(); 62.177 } 62.178 62.179 - __vmread(GUEST_RIP, &eip); 62.180 TRACE_VMEXIT(0,exit_reason); 62.181 62.182 - switch ( exit_reason ) 62.183 - { 62.184 + switch ( exit_reason ) { 62.185 case EXIT_REASON_EXCEPTION_NMI: 62.186 { 62.187 /* 62.188 @@ -2187,15 +2188,15 @@ asmlinkage void vmx_vmexit_handler(struc 62.189 unsigned int vector; 62.190 unsigned long va; 62.191 62.192 - if (__vmread(VM_EXIT_INTR_INFO, &vector) 62.193 - || !(vector & INTR_INFO_VALID_MASK)) 62.194 - __hvm_bug(®s); 62.195 + if ( __vmread(VM_EXIT_INTR_INFO, &vector) || 62.196 + !(vector & INTR_INFO_VALID_MASK) ) 62.197 + domain_crash_synchronous(); 62.198 vector &= INTR_INFO_VECTOR_MASK; 62.199 62.200 TRACE_VMEXIT(1,vector); 62.201 perfc_incra(cause_vector, vector); 62.202 62.203 - switch (vector) { 62.204 + switch ( vector ) { 62.205 #ifdef XEN_DEBUGGER 62.206 case TRAP_debug: 62.207 { 62.208 @@ -2236,7 +2237,7 @@ asmlinkage void vmx_vmexit_handler(struc 62.209 { 62.210 if ( test_bit(_DOMF_debugging, &v->domain->domain_flags) ) 62.211 domain_pause_for_debugger(); 62.212 - else 62.213 + else 62.214 vmx_reflect_exception(v); 62.215 break; 62.216 } 62.217 @@ -2260,7 +2261,7 @@ asmlinkage void vmx_vmexit_handler(struc 62.218 (unsigned long)regs.ecx, (unsigned long)regs.edx, 62.219 (unsigned long)regs.esi, (unsigned long)regs.edi); 62.220 62.221 - if (!vmx_do_page_fault(va, ®s)) { 62.222 + if ( !vmx_do_page_fault(va, ®s) ) { 62.223 /* 62.224 * Inject #PG using Interruption-Information Fields 62.225 */ 62.226 @@ -2282,6 +2283,9 @@ asmlinkage void vmx_vmexit_handler(struc 62.227 case EXIT_REASON_EXTERNAL_INTERRUPT: 62.228 vmx_vmexit_do_extint(®s); 62.229 break; 62.230 + case EXIT_REASON_TRIPLE_FAULT: 62.231 + domain_crash_synchronous(); 62.232 + break; 62.233 case EXIT_REASON_PENDING_INTERRUPT: 62.234 /* 62.235 * Not sure exactly what the purpose of this is. The only bits set 62.236 @@ -2296,7 +2300,7 @@ asmlinkage void vmx_vmexit_handler(struc 62.237 v->arch.hvm_vcpu.u.vmx.exec_control); 62.238 break; 62.239 case EXIT_REASON_TASK_SWITCH: 62.240 - __hvm_bug(®s); 62.241 + domain_crash_synchronous(); 62.242 break; 62.243 case EXIT_REASON_CPUID: 62.244 vmx_vmexit_do_cpuid(®s); 62.245 @@ -2321,7 +2325,7 @@ asmlinkage void vmx_vmexit_handler(struc 62.246 case EXIT_REASON_VMCALL: 62.247 { 62.248 __get_instruction_length(inst_len); 62.249 - __vmread(GUEST_RIP, &eip); 62.250 + __vmread(GUEST_RIP, &rip); 62.251 __vmread(EXIT_QUALIFICATION, &exit_qualification); 62.252 62.253 hvm_do_hypercall(®s); 62.254 @@ -2330,13 +2334,13 @@ asmlinkage void vmx_vmexit_handler(struc 62.255 } 62.256 case EXIT_REASON_CR_ACCESS: 62.257 { 62.258 - __vmread(GUEST_RIP, &eip); 62.259 + __vmread(GUEST_RIP, &rip); 62.260 __get_instruction_length(inst_len); 62.261 __vmread(EXIT_QUALIFICATION, &exit_qualification); 62.262 62.263 - HVM_DBG_LOG(DBG_LEVEL_1, "eip = %lx, inst_len =%lx, exit_qualification = %lx", 62.264 - eip, inst_len, exit_qualification); 62.265 - if (vmx_cr_access(exit_qualification, ®s)) 62.266 + HVM_DBG_LOG(DBG_LEVEL_1, "rip = %lx, inst_len =%lx, exit_qualification = %lx", 62.267 + rip, inst_len, exit_qualification); 62.268 + if ( vmx_cr_access(exit_qualification, ®s) ) 62.269 __update_guest_eip(inst_len); 62.270 TRACE_VMEXIT(3,regs.error_code); 62.271 TRACE_VMEXIT(4,exit_qualification); 62.272 @@ -2360,13 +2364,14 @@ asmlinkage void vmx_vmexit_handler(struc 62.273 __update_guest_eip(inst_len); 62.274 break; 62.275 case EXIT_REASON_MSR_WRITE: 62.276 - __vmread(GUEST_RIP, &eip); 62.277 vmx_do_msr_write(®s); 62.278 __get_instruction_length(inst_len); 62.279 __update_guest_eip(inst_len); 62.280 break; 62.281 case EXIT_REASON_MWAIT_INSTRUCTION: 62.282 - __hvm_bug(®s); 62.283 + case EXIT_REASON_MONITOR_INSTRUCTION: 62.284 + case EXIT_REASON_PAUSE_INSTRUCTION: 62.285 + domain_crash_synchronous(); 62.286 break; 62.287 case EXIT_REASON_VMCLEAR: 62.288 case EXIT_REASON_VMLAUNCH: 62.289 @@ -2375,15 +2380,15 @@ asmlinkage void vmx_vmexit_handler(struc 62.290 case EXIT_REASON_VMREAD: 62.291 case EXIT_REASON_VMRESUME: 62.292 case EXIT_REASON_VMWRITE: 62.293 - case EXIT_REASON_VMOFF: 62.294 - case EXIT_REASON_VMON: 62.295 - /* Report invalid opcode exception when a VMX guest tries to execute 62.296 + case EXIT_REASON_VMXOFF: 62.297 + case EXIT_REASON_VMXON: 62.298 + /* Report invalid opcode exception when a VMX guest tries to execute 62.299 any of the VMX instructions */ 62.300 vmx_inject_hw_exception(v, TRAP_invalid_op, VMX_DELIVER_NO_ERROR_CODE); 62.301 break; 62.302 62.303 default: 62.304 - __hvm_bug(®s); /* should not happen */ 62.305 + domain_crash_synchronous(); /* should not happen */ 62.306 } 62.307 } 62.308 62.309 @@ -2398,11 +2403,11 @@ asmlinkage void vmx_load_cr2(void) 62.310 asmlinkage void vmx_trace_vmentry (void) 62.311 { 62.312 TRACE_5D(TRC_VMX_VMENTRY, 62.313 - trace_values[smp_processor_id()][0], 62.314 - trace_values[smp_processor_id()][1], 62.315 - trace_values[smp_processor_id()][2], 62.316 - trace_values[smp_processor_id()][3], 62.317 - trace_values[smp_processor_id()][4]); 62.318 + this_cpu(trace_values)[0], 62.319 + this_cpu(trace_values)[1], 62.320 + this_cpu(trace_values)[2], 62.321 + this_cpu(trace_values)[3], 62.322 + this_cpu(trace_values)[4]); 62.323 TRACE_VMEXIT(0,9); 62.324 TRACE_VMEXIT(1,9); 62.325 TRACE_VMEXIT(2,9);
63.1 --- a/xen/arch/x86/hvm/vmx/x86_32/exits.S Tue Aug 08 19:07:32 2006 -0500 63.2 +++ b/xen/arch/x86/hvm/vmx/x86_32/exits.S Wed Aug 09 18:04:20 2006 +0100 63.3 @@ -94,6 +94,9 @@ vmx_process_softirqs: 63.4 ALIGN 63.5 ENTRY(vmx_asm_do_vmentry) 63.6 GET_CURRENT(%ebx) 63.7 + pushl %ebx 63.8 + call vmx_do_resume 63.9 + addl $4, %esp 63.10 cli # tests must not race interrupts 63.11 63.12 movl VCPU_processor(%ebx),%eax
64.1 --- a/xen/arch/x86/hvm/vmx/x86_64/exits.S Tue Aug 08 19:07:32 2006 -0500 64.2 +++ b/xen/arch/x86/hvm/vmx/x86_64/exits.S Wed Aug 09 18:04:20 2006 +0100 64.3 @@ -105,6 +105,8 @@ vmx_process_softirqs: 64.4 ALIGN 64.5 ENTRY(vmx_asm_do_vmentry) 64.6 GET_CURRENT(%rbx) 64.7 + movq %rbx, %rdi 64.8 + call vmx_do_resume 64.9 cli # tests must not race interrupts 64.10 64.11 movl VCPU_processor(%rbx),%eax
65.1 --- a/xen/arch/x86/irq.c Tue Aug 08 19:07:32 2006 -0500 65.2 +++ b/xen/arch/x86/irq.c Wed Aug 09 18:04:20 2006 +0100 65.3 @@ -160,11 +160,12 @@ typedef struct { 65.4 * Stack of interrupts awaiting EOI on each CPU. These must be popped in 65.5 * order, as only the current highest-priority pending irq can be EOIed. 65.6 */ 65.7 -static struct { 65.8 +struct pending_eoi { 65.9 u8 vector; /* Vector awaiting EOI */ 65.10 u8 ready; /* Ready for EOI now? */ 65.11 -} pending_eoi[NR_CPUS][NR_VECTORS] __cacheline_aligned; 65.12 -#define pending_eoi_sp(cpu) (pending_eoi[cpu][NR_VECTORS-1].vector) 65.13 +}; 65.14 +static DEFINE_PER_CPU(struct pending_eoi, pending_eoi[NR_VECTORS]); 65.15 +#define pending_eoi_sp(p) ((p)[NR_VECTORS-1].vector) 65.16 65.17 static void __do_IRQ_guest(int vector) 65.18 { 65.19 @@ -172,7 +173,8 @@ static void __do_IRQ_guest(int vector) 65.20 irq_desc_t *desc = &irq_desc[vector]; 65.21 irq_guest_action_t *action = (irq_guest_action_t *)desc->action; 65.22 struct domain *d; 65.23 - int i, sp, cpu = smp_processor_id(); 65.24 + int i, sp; 65.25 + struct pending_eoi *peoi = this_cpu(pending_eoi); 65.26 65.27 if ( unlikely(action->nr_guests == 0) ) 65.28 { 65.29 @@ -185,13 +187,13 @@ static void __do_IRQ_guest(int vector) 65.30 65.31 if ( action->ack_type == ACKTYPE_EOI ) 65.32 { 65.33 - sp = pending_eoi_sp(cpu); 65.34 - ASSERT((sp == 0) || (pending_eoi[cpu][sp-1].vector < vector)); 65.35 + sp = pending_eoi_sp(peoi); 65.36 + ASSERT((sp == 0) || (peoi[sp-1].vector < vector)); 65.37 ASSERT(sp < (NR_VECTORS-1)); 65.38 - pending_eoi[cpu][sp].vector = vector; 65.39 - pending_eoi[cpu][sp].ready = 0; 65.40 - pending_eoi_sp(cpu) = sp+1; 65.41 - cpu_set(cpu, action->cpu_eoi_map); 65.42 + peoi[sp].vector = vector; 65.43 + peoi[sp].ready = 0; 65.44 + pending_eoi_sp(peoi) = sp+1; 65.45 + cpu_set(smp_processor_id(), action->cpu_eoi_map); 65.46 } 65.47 65.48 for ( i = 0; i < action->nr_guests; i++ ) 65.49 @@ -207,43 +209,45 @@ static void __do_IRQ_guest(int vector) 65.50 /* Flush all ready EOIs from the top of this CPU's pending-EOI stack. */ 65.51 static void flush_ready_eoi(void *unused) 65.52 { 65.53 - irq_desc_t *desc; 65.54 - int vector, sp, cpu = smp_processor_id(); 65.55 + struct pending_eoi *peoi = this_cpu(pending_eoi); 65.56 + irq_desc_t *desc; 65.57 + int vector, sp; 65.58 65.59 ASSERT(!local_irq_is_enabled()); 65.60 65.61 - sp = pending_eoi_sp(cpu); 65.62 + sp = pending_eoi_sp(peoi); 65.63 65.64 - while ( (--sp >= 0) && pending_eoi[cpu][sp].ready ) 65.65 + while ( (--sp >= 0) && peoi[sp].ready ) 65.66 { 65.67 - vector = pending_eoi[cpu][sp].vector; 65.68 + vector = peoi[sp].vector; 65.69 desc = &irq_desc[vector]; 65.70 spin_lock(&desc->lock); 65.71 desc->handler->end(vector); 65.72 spin_unlock(&desc->lock); 65.73 } 65.74 65.75 - pending_eoi_sp(cpu) = sp+1; 65.76 + pending_eoi_sp(peoi) = sp+1; 65.77 } 65.78 65.79 static void __set_eoi_ready(irq_desc_t *desc) 65.80 { 65.81 irq_guest_action_t *action = (irq_guest_action_t *)desc->action; 65.82 - int vector, sp, cpu = smp_processor_id(); 65.83 + struct pending_eoi *peoi = this_cpu(pending_eoi); 65.84 + int vector, sp; 65.85 65.86 vector = desc - irq_desc; 65.87 65.88 if ( !(desc->status & IRQ_GUEST) || 65.89 (action->in_flight != 0) || 65.90 - !cpu_test_and_clear(cpu, action->cpu_eoi_map) ) 65.91 + !cpu_test_and_clear(smp_processor_id(), action->cpu_eoi_map) ) 65.92 return; 65.93 65.94 - sp = pending_eoi_sp(cpu); 65.95 + sp = pending_eoi_sp(peoi); 65.96 do { 65.97 ASSERT(sp > 0); 65.98 - } while ( pending_eoi[cpu][--sp].vector != vector ); 65.99 - ASSERT(!pending_eoi[cpu][sp].ready); 65.100 - pending_eoi[cpu][sp].ready = 1; 65.101 + } while ( peoi[--sp].vector != vector ); 65.102 + ASSERT(!peoi[sp].ready); 65.103 + peoi[sp].ready = 1; 65.104 } 65.105 65.106 /* Mark specified IRQ as ready-for-EOI (if it really is) and attempt to EOI. */ 65.107 @@ -269,16 +273,17 @@ static void flush_all_pending_eoi(void * 65.108 { 65.109 irq_desc_t *desc; 65.110 irq_guest_action_t *action; 65.111 - int i, vector, sp, cpu = smp_processor_id(); 65.112 + struct pending_eoi *peoi = this_cpu(pending_eoi); 65.113 + int i, vector, sp; 65.114 65.115 ASSERT(!local_irq_is_enabled()); 65.116 65.117 - sp = pending_eoi_sp(cpu); 65.118 + sp = pending_eoi_sp(peoi); 65.119 while ( --sp >= 0 ) 65.120 { 65.121 - if ( pending_eoi[cpu][sp].ready ) 65.122 + if ( peoi[sp].ready ) 65.123 continue; 65.124 - vector = pending_eoi[cpu][sp].vector; 65.125 + vector = peoi[sp].vector; 65.126 desc = &irq_desc[vector]; 65.127 spin_lock(&desc->lock); 65.128 action = (irq_guest_action_t *)desc->action; 65.129 @@ -668,7 +673,7 @@ static int __init setup_dump_irqs(void) 65.130 } 65.131 __initcall(setup_dump_irqs); 65.132 65.133 -static struct timer end_irq_timer[NR_CPUS]; 65.134 +static DEFINE_PER_CPU(struct timer, end_irq_timer); 65.135 65.136 /* 65.137 * force_intack: Forcibly emit all pending EOIs on each CPU every second. 65.138 @@ -677,22 +682,13 @@ static struct timer end_irq_timer[NR_CPU 65.139 65.140 static void end_irq_timeout(void *unused) 65.141 { 65.142 - int cpu = smp_processor_id(); 65.143 - 65.144 local_irq_disable(); 65.145 flush_all_pending_eoi(NULL); 65.146 local_irq_enable(); 65.147 65.148 on_selected_cpus(cpu_online_map, flush_ready_eoi, NULL, 1, 0); 65.149 65.150 - set_timer(&end_irq_timer[cpu], NOW() + MILLISECS(1000)); 65.151 -} 65.152 - 65.153 -static void __init __setup_irq_timeout(void *unused) 65.154 -{ 65.155 - int cpu = smp_processor_id(); 65.156 - init_timer(&end_irq_timer[cpu], end_irq_timeout, NULL, cpu); 65.157 - set_timer(&end_irq_timer[cpu], NOW() + MILLISECS(1000)); 65.158 + set_timer(&this_cpu(end_irq_timer), NOW() + MILLISECS(1000)); 65.159 } 65.160 65.161 static int force_intack; 65.162 @@ -700,8 +696,17 @@ boolean_param("force_intack", force_inta 65.163 65.164 static int __init setup_irq_timeout(void) 65.165 { 65.166 - if ( force_intack ) 65.167 - on_each_cpu(__setup_irq_timeout, NULL, 1, 1); 65.168 + unsigned int cpu; 65.169 + 65.170 + if ( !force_intack ) 65.171 + return 0; 65.172 + 65.173 + for_each_online_cpu ( cpu ) 65.174 + { 65.175 + init_timer(&per_cpu(end_irq_timer, cpu), end_irq_timeout, NULL, cpu); 65.176 + set_timer(&per_cpu(end_irq_timer, cpu), NOW() + MILLISECS(1000)); 65.177 + } 65.178 + 65.179 return 0; 65.180 } 65.181 __initcall(setup_irq_timeout);
66.1 --- a/xen/arch/x86/mm.c Tue Aug 08 19:07:32 2006 -0500 66.2 +++ b/xen/arch/x86/mm.c Wed Aug 09 18:04:20 2006 +0100 66.3 @@ -139,20 +139,21 @@ static int mod_l2_entry(l2_pgentry_t *, 66.4 static int mod_l1_entry(l1_pgentry_t *, l1_pgentry_t); 66.5 66.6 /* Used to defer flushing of memory structures. */ 66.7 -static struct { 66.8 +struct percpu_mm_info { 66.9 #define DOP_FLUSH_TLB (1<<0) /* Flush the local TLB. */ 66.10 #define DOP_FLUSH_ALL_TLBS (1<<1) /* Flush TLBs of all VCPUs of current dom. */ 66.11 #define DOP_RELOAD_LDT (1<<2) /* Reload the LDT shadow mapping. */ 66.12 unsigned int deferred_ops; 66.13 /* If non-NULL, specifies a foreign subject domain for some operations. */ 66.14 struct domain *foreign; 66.15 -} __cacheline_aligned percpu_info[NR_CPUS]; 66.16 +}; 66.17 +static DEFINE_PER_CPU(struct percpu_mm_info, percpu_mm_info); 66.18 66.19 /* 66.20 * Returns the current foreign domain; defaults to the currently-executing 66.21 * domain if a foreign override hasn't been specified. 66.22 */ 66.23 -#define FOREIGNDOM (percpu_info[smp_processor_id()].foreign ?: current->domain) 66.24 +#define FOREIGNDOM (this_cpu(percpu_mm_info).foreign ?: current->domain) 66.25 66.26 /* Private domain structs for DOMID_XEN and DOMID_IO. */ 66.27 static struct domain *dom_xen, *dom_io; 66.28 @@ -190,8 +191,6 @@ void arch_init_memory(void) 66.29 66.30 unsigned long i, pfn, rstart_pfn, rend_pfn; 66.31 66.32 - memset(percpu_info, 0, sizeof(percpu_info)); 66.33 - 66.34 /* 66.35 * Initialise our DOMID_XEN domain. 66.36 * Any Xen-heap pages that we will allow to be mapped will have 66.37 @@ -378,7 +377,8 @@ void invalidate_shadow_ldt(struct vcpu * 66.38 } 66.39 66.40 /* Dispose of the (now possibly invalid) mappings from the TLB. */ 66.41 - percpu_info[v->processor].deferred_ops |= DOP_FLUSH_TLB | DOP_RELOAD_LDT; 66.42 + ASSERT(v->processor == smp_processor_id()); 66.43 + this_cpu(percpu_mm_info).deferred_ops |= DOP_FLUSH_TLB | DOP_RELOAD_LDT; 66.44 } 66.45 66.46 66.47 @@ -1503,7 +1503,7 @@ void free_page_type(struct page_info *pa 66.48 * (e.g., update_va_mapping()) or we could end up modifying a page 66.49 * that is no longer a page table (and hence screw up ref counts). 66.50 */ 66.51 - percpu_info[smp_processor_id()].deferred_ops |= DOP_FLUSH_ALL_TLBS; 66.52 + this_cpu(percpu_mm_info).deferred_ops |= DOP_FLUSH_ALL_TLBS; 66.53 66.54 if ( unlikely(shadow_mode_enabled(owner)) ) 66.55 { 66.56 @@ -1781,7 +1781,8 @@ int new_guest_cr3(unsigned long mfn) 66.57 /* Failure here is unrecoverable: the VCPU has no pagetable! */ 66.58 MEM_LOG("Fatal error while installing new baseptr %lx", mfn); 66.59 domain_crash(d); 66.60 - percpu_info[v->processor].deferred_ops = 0; 66.61 + ASSERT(v->processor == smp_processor_id()); 66.62 + this_cpu(percpu_mm_info).deferred_ops = 0; 66.63 return 0; 66.64 } 66.65 } 66.66 @@ -1817,13 +1818,14 @@ int new_guest_cr3(unsigned long mfn) 66.67 return 1; 66.68 } 66.69 66.70 -static void process_deferred_ops(unsigned int cpu) 66.71 +static void process_deferred_ops(void) 66.72 { 66.73 unsigned int deferred_ops; 66.74 struct domain *d = current->domain; 66.75 - 66.76 - deferred_ops = percpu_info[cpu].deferred_ops; 66.77 - percpu_info[cpu].deferred_ops = 0; 66.78 + struct percpu_mm_info *info = &this_cpu(percpu_mm_info); 66.79 + 66.80 + deferred_ops = info->deferred_ops; 66.81 + info->deferred_ops = 0; 66.82 66.83 if ( deferred_ops & (DOP_FLUSH_ALL_TLBS|DOP_FLUSH_TLB) ) 66.84 { 66.85 @@ -1838,19 +1840,20 @@ static void process_deferred_ops(unsigne 66.86 if ( deferred_ops & DOP_RELOAD_LDT ) 66.87 (void)map_ldt_shadow_page(0); 66.88 66.89 - if ( unlikely(percpu_info[cpu].foreign != NULL) ) 66.90 + if ( unlikely(info->foreign != NULL) ) 66.91 { 66.92 - put_domain(percpu_info[cpu].foreign); 66.93 - percpu_info[cpu].foreign = NULL; 66.94 + put_domain(info->foreign); 66.95 + info->foreign = NULL; 66.96 } 66.97 } 66.98 66.99 -static int set_foreigndom(unsigned int cpu, domid_t domid) 66.100 +static int set_foreigndom(domid_t domid) 66.101 { 66.102 struct domain *e, *d = current->domain; 66.103 + struct percpu_mm_info *info = &this_cpu(percpu_mm_info); 66.104 int okay = 1; 66.105 66.106 - ASSERT(percpu_info[cpu].foreign == NULL); 66.107 + ASSERT(info->foreign == NULL); 66.108 66.109 if ( likely(domid == DOMID_SELF) ) 66.110 goto out; 66.111 @@ -1867,7 +1870,7 @@ static int set_foreigndom(unsigned int c 66.112 { 66.113 case DOMID_IO: 66.114 get_knownalive_domain(dom_io); 66.115 - percpu_info[cpu].foreign = dom_io; 66.116 + info->foreign = dom_io; 66.117 break; 66.118 default: 66.119 MEM_LOG("Dom %u cannot set foreign dom", d->domain_id); 66.120 @@ -1877,18 +1880,18 @@ static int set_foreigndom(unsigned int c 66.121 } 66.122 else 66.123 { 66.124 - percpu_info[cpu].foreign = e = find_domain_by_id(domid); 66.125 + info->foreign = e = find_domain_by_id(domid); 66.126 if ( e == NULL ) 66.127 { 66.128 switch ( domid ) 66.129 { 66.130 case DOMID_XEN: 66.131 get_knownalive_domain(dom_xen); 66.132 - percpu_info[cpu].foreign = dom_xen; 66.133 + info->foreign = dom_xen; 66.134 break; 66.135 case DOMID_IO: 66.136 get_knownalive_domain(dom_io); 66.137 - percpu_info[cpu].foreign = dom_io; 66.138 + info->foreign = dom_io; 66.139 break; 66.140 default: 66.141 MEM_LOG("Unknown domain '%u'", domid); 66.142 @@ -1928,7 +1931,7 @@ int do_mmuext_op( 66.143 unsigned int foreigndom) 66.144 { 66.145 struct mmuext_op op; 66.146 - int rc = 0, i = 0, okay, cpu = smp_processor_id(); 66.147 + int rc = 0, i = 0, okay; 66.148 unsigned long mfn, type; 66.149 unsigned int done = 0; 66.150 struct page_info *page; 66.151 @@ -1946,7 +1949,7 @@ int do_mmuext_op( 66.152 (void)copy_from_guest(&done, pdone, 1); 66.153 } 66.154 66.155 - if ( !set_foreigndom(cpu, foreigndom) ) 66.156 + if ( !set_foreigndom(foreigndom) ) 66.157 { 66.158 rc = -ESRCH; 66.159 goto out; 66.160 @@ -2042,7 +2045,7 @@ int do_mmuext_op( 66.161 case MMUEXT_NEW_BASEPTR: 66.162 mfn = gmfn_to_mfn(current->domain, mfn); 66.163 okay = new_guest_cr3(mfn); 66.164 - percpu_info[cpu].deferred_ops &= ~DOP_FLUSH_TLB; 66.165 + this_cpu(percpu_mm_info).deferred_ops &= ~DOP_FLUSH_TLB; 66.166 break; 66.167 66.168 #ifdef __x86_64__ 66.169 @@ -2065,7 +2068,7 @@ int do_mmuext_op( 66.170 #endif 66.171 66.172 case MMUEXT_TLB_FLUSH_LOCAL: 66.173 - percpu_info[cpu].deferred_ops |= DOP_FLUSH_TLB; 66.174 + this_cpu(percpu_mm_info).deferred_ops |= DOP_FLUSH_TLB; 66.175 break; 66.176 66.177 case MMUEXT_INVLPG_LOCAL: 66.178 @@ -2137,9 +2140,9 @@ int do_mmuext_op( 66.179 v->arch.guest_context.ldt_base = ptr; 66.180 v->arch.guest_context.ldt_ents = ents; 66.181 load_LDT(v); 66.182 - percpu_info[cpu].deferred_ops &= ~DOP_RELOAD_LDT; 66.183 + this_cpu(percpu_mm_info).deferred_ops &= ~DOP_RELOAD_LDT; 66.184 if ( ents != 0 ) 66.185 - percpu_info[cpu].deferred_ops |= DOP_RELOAD_LDT; 66.186 + this_cpu(percpu_mm_info).deferred_ops |= DOP_RELOAD_LDT; 66.187 } 66.188 break; 66.189 } 66.190 @@ -2160,7 +2163,7 @@ int do_mmuext_op( 66.191 } 66.192 66.193 out: 66.194 - process_deferred_ops(cpu); 66.195 + process_deferred_ops(); 66.196 66.197 /* Add incremental work we have done to the @done output parameter. */ 66.198 done += i; 66.199 @@ -2181,7 +2184,7 @@ int do_mmu_update( 66.200 void *va; 66.201 unsigned long gpfn, gmfn, mfn; 66.202 struct page_info *page; 66.203 - int rc = 0, okay = 1, i = 0, cpu = smp_processor_id(); 66.204 + int rc = 0, okay = 1, i = 0; 66.205 unsigned int cmd, done = 0; 66.206 struct vcpu *v = current; 66.207 struct domain *d = v->domain; 66.208 @@ -2205,7 +2208,7 @@ int do_mmu_update( 66.209 domain_mmap_cache_init(&mapcache); 66.210 domain_mmap_cache_init(&sh_mapcache); 66.211 66.212 - if ( !set_foreigndom(cpu, foreigndom) ) 66.213 + if ( !set_foreigndom(foreigndom) ) 66.214 { 66.215 rc = -ESRCH; 66.216 goto out; 66.217 @@ -2396,7 +2399,7 @@ int do_mmu_update( 66.218 domain_mmap_cache_destroy(&mapcache); 66.219 domain_mmap_cache_destroy(&sh_mapcache); 66.220 66.221 - process_deferred_ops(cpu); 66.222 + process_deferred_ops(); 66.223 66.224 /* Add incremental work we have done to the @done output parameter. */ 66.225 done += i; 66.226 @@ -2690,7 +2693,6 @@ int do_update_va_mapping(unsigned long v 66.227 l1_pgentry_t val = l1e_from_intpte(val64); 66.228 struct vcpu *v = current; 66.229 struct domain *d = v->domain; 66.230 - unsigned int cpu = smp_processor_id(); 66.231 unsigned long vmask, bmap_ptr; 66.232 cpumask_t pmask; 66.233 int rc = 0; 66.234 @@ -2713,9 +2715,10 @@ int do_update_va_mapping(unsigned long v 66.235 66.236 if ( likely(rc == 0) && unlikely(shadow_mode_enabled(d)) ) 66.237 { 66.238 - if ( unlikely(percpu_info[cpu].foreign && 66.239 + if ( unlikely(this_cpu(percpu_mm_info).foreign && 66.240 (shadow_mode_translate(d) || 66.241 - shadow_mode_translate(percpu_info[cpu].foreign))) ) 66.242 + shadow_mode_translate( 66.243 + this_cpu(percpu_mm_info).foreign))) ) 66.244 { 66.245 /* 66.246 * The foreign domain's pfn's are in a different namespace. There's 66.247 @@ -2773,7 +2776,7 @@ int do_update_va_mapping(unsigned long v 66.248 break; 66.249 } 66.250 66.251 - process_deferred_ops(cpu); 66.252 + process_deferred_ops(); 66.253 66.254 UNLOCK_BIGLOCK(d); 66.255 66.256 @@ -2784,13 +2787,12 @@ int do_update_va_mapping_otherdomain(uns 66.257 unsigned long flags, 66.258 domid_t domid) 66.259 { 66.260 - unsigned int cpu = smp_processor_id(); 66.261 int rc; 66.262 66.263 if ( unlikely(!IS_PRIV(current->domain)) ) 66.264 return -EPERM; 66.265 66.266 - if ( !set_foreigndom(cpu, domid) ) 66.267 + if ( !set_foreigndom(domid) ) 66.268 return -ESRCH; 66.269 66.270 rc = do_update_va_mapping(va, val64, flags);
67.1 --- a/xen/arch/x86/nmi.c Tue Aug 08 19:07:32 2006 -0500 67.2 +++ b/xen/arch/x86/nmi.c Wed Aug 09 18:04:20 2006 +0100 67.3 @@ -36,8 +36,8 @@ unsigned int nmi_watchdog = NMI_NONE; 67.4 static unsigned int nmi_hz = HZ; 67.5 static unsigned int nmi_perfctr_msr; /* the MSR to reset in NMI handler */ 67.6 static unsigned int nmi_p4_cccr_val; 67.7 -static struct timer nmi_timer[NR_CPUS]; 67.8 -static unsigned int nmi_timer_ticks[NR_CPUS]; 67.9 +static DEFINE_PER_CPU(struct timer, nmi_timer); 67.10 +static DEFINE_PER_CPU(unsigned int, nmi_timer_ticks); 67.11 67.12 /* 67.13 * lapic_nmi_owner tracks the ownership of the lapic NMI hardware: 67.14 @@ -132,9 +132,8 @@ int __init check_nmi_watchdog (void) 67.15 67.16 static void nmi_timer_fn(void *unused) 67.17 { 67.18 - int cpu = smp_processor_id(); 67.19 - nmi_timer_ticks[cpu]++; 67.20 - set_timer(&nmi_timer[cpu], NOW() + MILLISECS(1000)); 67.21 + this_cpu(nmi_timer_ticks)++; 67.22 + set_timer(&this_cpu(nmi_timer), NOW() + MILLISECS(1000)); 67.23 } 67.24 67.25 static void disable_lapic_nmi_watchdog(void) 67.26 @@ -340,9 +339,8 @@ void __pminit setup_apic_nmi_watchdog(vo 67.27 nmi_active = 1; 67.28 } 67.29 67.30 -static unsigned int 67.31 -last_irq_sums [NR_CPUS], 67.32 - alert_counter [NR_CPUS]; 67.33 +static DEFINE_PER_CPU(unsigned int, last_irq_sums); 67.34 +static DEFINE_PER_CPU(unsigned int, alert_counter); 67.35 67.36 static atomic_t watchdog_disable_count = ATOMIC_INIT(1); 67.37 67.38 @@ -366,35 +364,35 @@ void watchdog_enable(void) 67.39 */ 67.40 for_each_online_cpu ( cpu ) 67.41 { 67.42 - init_timer(&nmi_timer[cpu], nmi_timer_fn, NULL, cpu); 67.43 - set_timer(&nmi_timer[cpu], NOW()); 67.44 + init_timer(&per_cpu(nmi_timer, cpu), nmi_timer_fn, NULL, cpu); 67.45 + set_timer(&per_cpu(nmi_timer, cpu), NOW()); 67.46 } 67.47 } 67.48 67.49 void nmi_watchdog_tick(struct cpu_user_regs * regs) 67.50 { 67.51 - int sum, cpu = smp_processor_id(); 67.52 + unsigned int sum = this_cpu(nmi_timer_ticks); 67.53 67.54 - sum = nmi_timer_ticks[cpu]; 67.55 - 67.56 - if ( (last_irq_sums[cpu] == sum) && !atomic_read(&watchdog_disable_count) ) 67.57 + if ( (this_cpu(last_irq_sums) == sum) && 67.58 + !atomic_read(&watchdog_disable_count) ) 67.59 { 67.60 /* 67.61 * Ayiee, looks like this CPU is stuck ... wait a few IRQs (5 seconds) 67.62 * before doing the oops ... 67.63 */ 67.64 - alert_counter[cpu]++; 67.65 - if ( alert_counter[cpu] == 5*nmi_hz ) 67.66 + this_cpu(alert_counter)++; 67.67 + if ( this_cpu(alert_counter) == 5*nmi_hz ) 67.68 { 67.69 console_force_unlock(); 67.70 - printk("Watchdog timer detects that CPU%d is stuck!\n", cpu); 67.71 + printk("Watchdog timer detects that CPU%d is stuck!\n", 67.72 + smp_processor_id()); 67.73 fatal_trap(TRAP_nmi, regs); 67.74 } 67.75 } 67.76 else 67.77 { 67.78 - last_irq_sums[cpu] = sum; 67.79 - alert_counter[cpu] = 0; 67.80 + this_cpu(last_irq_sums) = sum; 67.81 + this_cpu(alert_counter) = 0; 67.82 } 67.83 67.84 if ( nmi_perfctr_msr )
68.1 --- a/xen/arch/x86/time.c Tue Aug 08 19:07:32 2006 -0500 68.2 +++ b/xen/arch/x86/time.c Wed Aug 09 18:04:20 2006 +0100 68.3 @@ -56,9 +56,9 @@ struct cpu_time { 68.4 s_time_t stime_master_stamp; 68.5 struct time_scale tsc_scale; 68.6 struct timer calibration_timer; 68.7 -} __cacheline_aligned; 68.8 +}; 68.9 68.10 -static struct cpu_time cpu_time[NR_CPUS]; 68.11 +static DEFINE_PER_CPU(struct cpu_time, cpu_time); 68.12 68.13 /* 68.14 * Protected by platform_timer_lock, which must be acquired with interrupts 68.15 @@ -263,7 +263,7 @@ void calibrate_tsc_ap(void) 68.16 rdtscll(t2); 68.17 68.18 ticks_per_sec = (t2 - t1) * (u64)CALIBRATE_FRAC; 68.19 - set_time_scale(&cpu_time[smp_processor_id()].tsc_scale, ticks_per_sec); 68.20 + set_time_scale(&this_cpu(cpu_time).tsc_scale, ticks_per_sec); 68.21 68.22 atomic_dec(&tsc_calibrate_gang); 68.23 } 68.24 @@ -646,7 +646,7 @@ static unsigned long get_cmos_time(void) 68.25 68.26 s_time_t get_s_time(void) 68.27 { 68.28 - struct cpu_time *t = &cpu_time[smp_processor_id()]; 68.29 + struct cpu_time *t = &this_cpu(cpu_time); 68.30 u64 tsc, delta; 68.31 s_time_t now; 68.32 68.33 @@ -675,7 +675,7 @@ static inline void __update_vcpu_system_ 68.34 struct cpu_time *t; 68.35 struct vcpu_time_info *u; 68.36 68.37 - t = &cpu_time[smp_processor_id()]; 68.38 + t = &this_cpu(cpu_time); 68.39 u = &v->domain->shared_info->vcpu_info[v->vcpu_id].time; 68.40 68.41 version_update_begin(&u->version); 68.42 @@ -691,7 +691,7 @@ static inline void __update_vcpu_system_ 68.43 void update_vcpu_system_time(struct vcpu *v) 68.44 { 68.45 if ( v->domain->shared_info->vcpu_info[v->vcpu_id].time.tsc_timestamp != 68.46 - cpu_time[smp_processor_id()].local_tsc_stamp ) 68.47 + this_cpu(cpu_time).local_tsc_stamp ) 68.48 __update_vcpu_system_time(v); 68.49 } 68.50 68.51 @@ -728,7 +728,7 @@ void do_settime(unsigned long secs, unsi 68.52 68.53 static void local_time_calibration(void *unused) 68.54 { 68.55 - unsigned int cpu = smp_processor_id(); 68.56 + struct cpu_time *t = &this_cpu(cpu_time); 68.57 68.58 /* 68.59 * System timestamps, extrapolated from local and master oscillators, 68.60 @@ -759,9 +759,9 @@ static void local_time_calibration(void 68.61 /* The overall calibration scale multiplier. */ 68.62 u32 calibration_mul_frac; 68.63 68.64 - prev_tsc = cpu_time[cpu].local_tsc_stamp; 68.65 - prev_local_stime = cpu_time[cpu].stime_local_stamp; 68.66 - prev_master_stime = cpu_time[cpu].stime_master_stamp; 68.67 + prev_tsc = t->local_tsc_stamp; 68.68 + prev_local_stime = t->stime_local_stamp; 68.69 + prev_master_stime = t->stime_master_stamp; 68.70 68.71 /* Disable IRQs to get 'instantaneous' current timestamps. */ 68.72 local_irq_disable(); 68.73 @@ -772,9 +772,9 @@ static void local_time_calibration(void 68.74 68.75 #if 0 68.76 printk("PRE%d: tsc=%lld stime=%lld master=%lld\n", 68.77 - cpu, prev_tsc, prev_local_stime, prev_master_stime); 68.78 + smp_processor_id(), prev_tsc, prev_local_stime, prev_master_stime); 68.79 printk("CUR%d: tsc=%lld stime=%lld master=%lld -> %lld\n", 68.80 - cpu, curr_tsc, curr_local_stime, curr_master_stime, 68.81 + smp_processor_id(), curr_tsc, curr_local_stime, curr_master_stime, 68.82 curr_master_stime - curr_local_stime); 68.83 #endif 68.84 68.85 @@ -844,41 +844,41 @@ static void local_time_calibration(void 68.86 calibration_mul_frac = mul_frac(calibration_mul_frac, error_factor); 68.87 68.88 #if 0 68.89 - printk("---%d: %08x %08x %d\n", cpu, 68.90 + printk("---%d: %08x %08x %d\n", smp_processor_id(), 68.91 error_factor, calibration_mul_frac, tsc_shift); 68.92 #endif 68.93 68.94 /* Record new timestamp information. */ 68.95 - cpu_time[cpu].tsc_scale.mul_frac = calibration_mul_frac; 68.96 - cpu_time[cpu].tsc_scale.shift = tsc_shift; 68.97 - cpu_time[cpu].local_tsc_stamp = curr_tsc; 68.98 - cpu_time[cpu].stime_local_stamp = curr_local_stime; 68.99 - cpu_time[cpu].stime_master_stamp = curr_master_stime; 68.100 + t->tsc_scale.mul_frac = calibration_mul_frac; 68.101 + t->tsc_scale.shift = tsc_shift; 68.102 + t->local_tsc_stamp = curr_tsc; 68.103 + t->stime_local_stamp = curr_local_stime; 68.104 + t->stime_master_stamp = curr_master_stime; 68.105 68.106 out: 68.107 - set_timer(&cpu_time[cpu].calibration_timer, NOW() + EPOCH); 68.108 + set_timer(&t->calibration_timer, NOW() + EPOCH); 68.109 68.110 - if ( cpu == 0 ) 68.111 + if ( smp_processor_id() == 0 ) 68.112 platform_time_calibration(); 68.113 } 68.114 68.115 void init_percpu_time(void) 68.116 { 68.117 - unsigned int cpu = smp_processor_id(); 68.118 + struct cpu_time *t = &this_cpu(cpu_time); 68.119 unsigned long flags; 68.120 s_time_t now; 68.121 68.122 local_irq_save(flags); 68.123 - rdtscll(cpu_time[cpu].local_tsc_stamp); 68.124 - now = (cpu == 0) ? 0 : read_platform_stime(); 68.125 + rdtscll(t->local_tsc_stamp); 68.126 + now = (smp_processor_id() == 0) ? 0 : read_platform_stime(); 68.127 local_irq_restore(flags); 68.128 68.129 - cpu_time[cpu].stime_master_stamp = now; 68.130 - cpu_time[cpu].stime_local_stamp = now; 68.131 + t->stime_master_stamp = now; 68.132 + t->stime_local_stamp = now; 68.133 68.134 - init_timer(&cpu_time[cpu].calibration_timer, 68.135 - local_time_calibration, NULL, cpu); 68.136 - set_timer(&cpu_time[cpu].calibration_timer, NOW() + EPOCH); 68.137 + init_timer(&t->calibration_timer, local_time_calibration, 68.138 + NULL, smp_processor_id()); 68.139 + set_timer(&t->calibration_timer, NOW() + EPOCH); 68.140 } 68.141 68.142 /* Late init function (after all CPUs are booted). */ 68.143 @@ -904,7 +904,7 @@ void __init early_time_init(void) 68.144 { 68.145 u64 tmp = calibrate_boot_tsc(); 68.146 68.147 - set_time_scale(&cpu_time[0].tsc_scale, tmp); 68.148 + set_time_scale(&per_cpu(cpu_time, 0).tsc_scale, tmp); 68.149 68.150 do_div(tmp, 1000); 68.151 cpu_khz = (unsigned long)tmp;
69.1 --- a/xen/arch/x86/x86_32/domain_page.c Tue Aug 08 19:07:32 2006 -0500 69.2 +++ b/xen/arch/x86/x86_32/domain_page.c Wed Aug 09 18:04:20 2006 +0100 69.3 @@ -73,8 +73,7 @@ void *map_domain_page(unsigned long pfn) 69.4 if ( unlikely(cache->epoch != cache->shadow_epoch[vcpu]) ) 69.5 { 69.6 cache->shadow_epoch[vcpu] = cache->epoch; 69.7 - if ( NEED_FLUSH(tlbflush_time[smp_processor_id()], 69.8 - cache->tlbflush_timestamp) ) 69.9 + if ( NEED_FLUSH(this_cpu(tlbflush_time), cache->tlbflush_timestamp) ) 69.10 { 69.11 perfc_incrc(domain_page_tlb_flush); 69.12 local_flush_tlb();
70.1 --- a/xen/arch/x86/x86_32/traps.c Tue Aug 08 19:07:32 2006 -0500 70.2 +++ b/xen/arch/x86/x86_32/traps.c Wed Aug 09 18:04:20 2006 +0100 70.3 @@ -19,7 +19,7 @@ 70.4 #include <public/callback.h> 70.5 70.6 /* All CPUs have their own IDT to allow int80 direct trap. */ 70.7 -idt_entry_t *idt_tables[NR_CPUS] = { 0 }; 70.8 +idt_entry_t *idt_tables[NR_CPUS] __read_mostly; 70.9 70.10 void show_registers(struct cpu_user_regs *regs) 70.11 {
71.1 --- a/xen/arch/x86/x86_32/xen.lds.S Tue Aug 08 19:07:32 2006 -0500 71.2 +++ b/xen/arch/x86/x86_32/xen.lds.S Wed Aug 09 18:04:20 2006 +0100 71.3 @@ -46,6 +46,9 @@ SECTIONS 71.4 CONSTRUCTORS 71.5 } :text 71.6 71.7 + . = ALIGN(128); 71.8 + .data.read_mostly : { *(.data.read_mostly) } :text 71.9 + 71.10 . = ALIGN(4096); /* Init code and data */ 71.11 __init_begin = .; 71.12 .text.init : { *(.text.init) } :text
72.1 --- a/xen/arch/x86/x86_64/xen.lds.S Tue Aug 08 19:07:32 2006 -0500 72.2 +++ b/xen/arch/x86/x86_64/xen.lds.S Wed Aug 09 18:04:20 2006 +0100 72.3 @@ -44,6 +44,9 @@ SECTIONS 72.4 CONSTRUCTORS 72.5 } :text 72.6 72.7 + . = ALIGN(128); 72.8 + .data.read_mostly : { *(.data.read_mostly) } :text 72.9 + 72.10 . = ALIGN(4096); /* Init code and data */ 72.11 __init_begin = .; 72.12 .text.init : { *(.text.init) } :text
73.1 --- a/xen/common/domain.c Tue Aug 08 19:07:32 2006 -0500 73.2 +++ b/xen/common/domain.c Wed Aug 09 18:04:20 2006 +0100 73.3 @@ -21,6 +21,7 @@ 73.4 #include <xen/hypercall.h> 73.5 #include <xen/delay.h> 73.6 #include <xen/shutdown.h> 73.7 +#include <xen/percpu.h> 73.8 #include <asm/debugger.h> 73.9 #include <public/dom0_ops.h> 73.10 #include <public/sched.h> 73.11 @@ -33,7 +34,7 @@ struct domain *domain_list; 73.12 73.13 struct domain *dom0; 73.14 73.15 -struct vcpu *idle_vcpu[NR_CPUS]; 73.16 +struct vcpu *idle_vcpu[NR_CPUS] __read_mostly; 73.17 73.18 struct domain *alloc_domain(domid_t domid) 73.19 { 73.20 @@ -245,15 +246,15 @@ void __domain_crash_synchronous(void) 73.21 } 73.22 73.23 73.24 -static struct domain *domain_shuttingdown[NR_CPUS]; 73.25 +static DEFINE_PER_CPU(struct domain *, domain_shuttingdown); 73.26 73.27 static void domain_shutdown_finalise(void) 73.28 { 73.29 struct domain *d; 73.30 struct vcpu *v; 73.31 73.32 - d = domain_shuttingdown[smp_processor_id()]; 73.33 - domain_shuttingdown[smp_processor_id()] = NULL; 73.34 + d = this_cpu(domain_shuttingdown); 73.35 + this_cpu(domain_shuttingdown) = NULL; 73.36 73.37 BUG_ON(d == NULL); 73.38 BUG_ON(d == current->domain); 73.39 @@ -302,7 +303,7 @@ void domain_shutdown(struct domain *d, u 73.40 vcpu_sleep_nosync(v); 73.41 73.42 get_knownalive_domain(d); 73.43 - domain_shuttingdown[smp_processor_id()] = d; 73.44 + this_cpu(domain_shuttingdown) = d; 73.45 raise_softirq(DOMAIN_SHUTDOWN_FINALISE_SOFTIRQ); 73.46 } 73.47
74.1 --- a/xen/common/multicall.c Tue Aug 08 19:07:32 2006 -0500 74.2 +++ b/xen/common/multicall.c Wed Aug 09 18:04:20 2006 +0100 74.3 @@ -14,13 +14,13 @@ 74.4 #include <asm/current.h> 74.5 #include <asm/hardirq.h> 74.6 74.7 -struct mc_state mc_state[NR_CPUS]; 74.8 +DEFINE_PER_CPU(struct mc_state, mc_state); 74.9 74.10 long 74.11 do_multicall( 74.12 XEN_GUEST_HANDLE(multicall_entry_t) call_list, unsigned int nr_calls) 74.13 { 74.14 - struct mc_state *mcs = &mc_state[smp_processor_id()]; 74.15 + struct mc_state *mcs = &this_cpu(mc_state); 74.16 unsigned int i; 74.17 74.18 if ( unlikely(__test_and_set_bit(_MCSF_in_multicall, &mcs->flags)) )
75.1 --- a/xen/common/sched_bvt.c Tue Aug 08 19:07:32 2006 -0500 75.2 +++ b/xen/common/sched_bvt.c Wed Aug 09 18:04:20 2006 +0100 75.3 @@ -60,7 +60,8 @@ struct bvt_cpu_info 75.4 75.5 #define BVT_INFO(p) ((struct bvt_dom_info *)(p)->sched_priv) 75.6 #define EBVT_INFO(p) ((struct bvt_vcpu_info *)(p)->sched_priv) 75.7 -#define CPU_INFO(cpu) ((struct bvt_cpu_info *)(schedule_data[cpu]).sched_priv) 75.8 +#define CPU_INFO(cpu) \ 75.9 + ((struct bvt_cpu_info *)(per_cpu(schedule_data, cpu).sched_priv)) 75.10 #define RUNLIST(p) ((struct list_head *)&(EBVT_INFO(p)->run_list)) 75.11 #define RUNQUEUE(cpu) ((struct list_head *)&(CPU_INFO(cpu)->runqueue)) 75.12 #define CPU_SVT(cpu) (CPU_INFO(cpu)->svt) 75.13 @@ -203,7 +204,8 @@ static int bvt_init_vcpu(struct vcpu *v) 75.14 /* Allocate per-CPU context if this is the first domain to be added. */ 75.15 if ( CPU_INFO(v->processor) == NULL ) 75.16 { 75.17 - schedule_data[v->processor].sched_priv = xmalloc(struct bvt_cpu_info); 75.18 + per_cpu(schedule_data, v->processor).sched_priv = 75.19 + xmalloc(struct bvt_cpu_info); 75.20 BUG_ON(CPU_INFO(v->processor) == NULL); 75.21 INIT_LIST_HEAD(RUNQUEUE(v->processor)); 75.22 CPU_SVT(v->processor) = 0; 75.23 @@ -251,7 +253,7 @@ static void bvt_wake(struct vcpu *v) 75.24 /* Deal with warping here. */ 75.25 einf->evt = calc_evt(v, einf->avt); 75.26 75.27 - curr = schedule_data[cpu].curr; 75.28 + curr = per_cpu(schedule_data, cpu).curr; 75.29 curr_evt = calc_evt(curr, calc_avt(curr, now)); 75.30 /* Calculate the time the current domain would run assuming 75.31 the second smallest evt is of the newly woken domain */ 75.32 @@ -261,14 +263,14 @@ static void bvt_wake(struct vcpu *v) 75.33 75.34 if ( is_idle_vcpu(curr) || (einf->evt <= curr_evt) ) 75.35 cpu_raise_softirq(cpu, SCHEDULE_SOFTIRQ); 75.36 - else if ( schedule_data[cpu].s_timer.expires > r_time ) 75.37 - set_timer(&schedule_data[cpu].s_timer, r_time); 75.38 + else if ( per_cpu(schedule_data, cpu).s_timer.expires > r_time ) 75.39 + set_timer(&per_cpu(schedule_data, cpu).s_timer, r_time); 75.40 } 75.41 75.42 75.43 static void bvt_sleep(struct vcpu *v) 75.44 { 75.45 - if ( schedule_data[v->processor].curr == v ) 75.46 + if ( per_cpu(schedule_data, v->processor).curr == v ) 75.47 cpu_raise_softirq(v->processor, SCHEDULE_SOFTIRQ); 75.48 else if ( __task_on_runqueue(v) ) 75.49 __del_from_runqueue(v); 75.50 @@ -418,7 +420,7 @@ static struct task_slice bvt_do_schedule 75.51 * *and* the task the second lowest evt. 75.52 * this code is O(n) but we expect n to be small. 75.53 */ 75.54 - next_einf = EBVT_INFO(schedule_data[cpu].idle); 75.55 + next_einf = EBVT_INFO(per_cpu(schedule_data, cpu).idle); 75.56 next_prime_einf = NULL; 75.57 75.58 next_evt = ~0U;
76.1 --- a/xen/common/sched_credit.c Tue Aug 08 19:07:32 2006 -0500 76.2 +++ b/xen/common/sched_credit.c Wed Aug 09 18:04:20 2006 +0100 76.3 @@ -55,7 +55,8 @@ 76.4 /* 76.5 * Useful macros 76.6 */ 76.7 -#define CSCHED_PCPU(_c) ((struct csched_pcpu *)schedule_data[_c].sched_priv) 76.8 +#define CSCHED_PCPU(_c) \ 76.9 + ((struct csched_pcpu *)per_cpu(schedule_data, _c).sched_priv) 76.10 #define CSCHED_VCPU(_vcpu) ((struct csched_vcpu *) (_vcpu)->sched_priv) 76.11 #define CSCHED_DOM(_dom) ((struct csched_dom *) (_dom)->sched_priv) 76.12 #define RUNQ(_cpu) (&(CSCHED_PCPU(_cpu)->runq)) 76.13 @@ -253,7 +254,8 @@ static inline void 76.14 static inline void 76.15 __runq_tickle(unsigned int cpu, struct csched_vcpu *new) 76.16 { 76.17 - struct csched_vcpu * const cur = CSCHED_VCPU(schedule_data[cpu].curr); 76.18 + struct csched_vcpu * const cur = 76.19 + CSCHED_VCPU(per_cpu(schedule_data, cpu).curr); 76.20 cpumask_t mask; 76.21 76.22 ASSERT(cur); 76.23 @@ -318,10 +320,10 @@ csched_pcpu_init(int cpu) 76.24 76.25 INIT_LIST_HEAD(&spc->runq); 76.26 spc->runq_sort_last = csched_priv.runq_sort; 76.27 - schedule_data[cpu].sched_priv = spc; 76.28 + per_cpu(schedule_data, cpu).sched_priv = spc; 76.29 76.30 /* Start off idling... */ 76.31 - BUG_ON( !is_idle_vcpu(schedule_data[cpu].curr) ); 76.32 + BUG_ON( !is_idle_vcpu(per_cpu(schedule_data, cpu).curr) ); 76.33 cpu_set(cpu, csched_priv.idlers); 76.34 76.35 spin_unlock_irqrestore(&csched_priv.lock, flags); 76.36 @@ -533,7 +535,7 @@ csched_vcpu_sleep(struct vcpu *vc) 76.37 76.38 BUG_ON( is_idle_vcpu(vc) ); 76.39 76.40 - if ( schedule_data[vc->processor].curr == vc ) 76.41 + if ( per_cpu(schedule_data, vc->processor).curr == vc ) 76.42 cpu_raise_softirq(vc->processor, SCHEDULE_SOFTIRQ); 76.43 else if ( __vcpu_on_runq(svc) ) 76.44 __runq_remove(svc); 76.45 @@ -547,7 +549,7 @@ csched_vcpu_wake(struct vcpu *vc) 76.46 76.47 BUG_ON( is_idle_vcpu(vc) ); 76.48 76.49 - if ( unlikely(schedule_data[cpu].curr == vc) ) 76.50 + if ( unlikely(per_cpu(schedule_data, cpu).curr == vc) ) 76.51 { 76.52 CSCHED_STAT_CRANK(vcpu_wake_running); 76.53 return; 76.54 @@ -599,7 +601,8 @@ csched_vcpu_set_affinity(struct vcpu *vc 76.55 76.56 vc->processor = first_cpu(vc->cpu_affinity); 76.57 76.58 - spin_unlock_irqrestore(&schedule_data[lcpu].schedule_lock, flags); 76.59 + spin_unlock_irqrestore(&per_cpu(schedule_data, lcpu).schedule_lock, 76.60 + flags); 76.61 } 76.62 76.63 vcpu_unpause(vc); 76.64 @@ -685,7 +688,7 @@ csched_runq_sort(unsigned int cpu) 76.65 76.66 spc->runq_sort_last = sort_epoch; 76.67 76.68 - spin_lock_irqsave(&schedule_data[cpu].schedule_lock, flags); 76.69 + spin_lock_irqsave(&per_cpu(schedule_data, cpu).schedule_lock, flags); 76.70 76.71 runq = &spc->runq; 76.72 elem = runq->next; 76.73 @@ -710,7 +713,7 @@ csched_runq_sort(unsigned int cpu) 76.74 elem = next; 76.75 } 76.76 76.77 - spin_unlock_irqrestore(&schedule_data[cpu].schedule_lock, flags); 76.78 + spin_unlock_irqrestore(&per_cpu(schedule_data, cpu).schedule_lock, flags); 76.79 } 76.80 76.81 static void 76.82 @@ -900,7 +903,7 @@ csched_tick(unsigned int cpu) 76.83 * we could distribute or at the very least cycle the duty. 76.84 */ 76.85 if ( (csched_priv.master == cpu) && 76.86 - (schedule_data[cpu].tick % CSCHED_ACCT_NTICKS) == 0 ) 76.87 + (per_cpu(schedule_data, cpu).tick % CSCHED_ACCT_NTICKS) == 0 ) 76.88 { 76.89 csched_acct(); 76.90 } 76.91 @@ -984,7 +987,7 @@ csched_load_balance(int cpu, struct csch 76.92 * cause a deadlock if the peer CPU is also load balancing and trying 76.93 * to lock this CPU. 76.94 */ 76.95 - if ( spin_trylock(&schedule_data[peer_cpu].schedule_lock) ) 76.96 + if ( spin_trylock(&per_cpu(schedule_data, peer_cpu).schedule_lock) ) 76.97 { 76.98 76.99 spc = CSCHED_PCPU(peer_cpu); 76.100 @@ -998,7 +1001,7 @@ csched_load_balance(int cpu, struct csch 76.101 speer = csched_runq_steal(spc, cpu, snext->pri); 76.102 } 76.103 76.104 - spin_unlock(&schedule_data[peer_cpu].schedule_lock); 76.105 + spin_unlock(&per_cpu(schedule_data, peer_cpu).schedule_lock); 76.106 76.107 /* Got one! */ 76.108 if ( speer ) 76.109 @@ -1120,11 +1123,11 @@ csched_dump_pcpu(int cpu) 76.110 runq = &spc->runq; 76.111 76.112 printk(" tick=%lu, sort=%d\n", 76.113 - schedule_data[cpu].tick, 76.114 + per_cpu(schedule_data, cpu).tick, 76.115 spc->runq_sort_last); 76.116 76.117 /* current VCPU */ 76.118 - svc = CSCHED_VCPU(schedule_data[cpu].curr); 76.119 + svc = CSCHED_VCPU(per_cpu(schedule_data, cpu).curr); 76.120 if ( svc ) 76.121 { 76.122 printk("\trun: ");
77.1 --- a/xen/common/sched_sedf.c Tue Aug 08 19:07:32 2006 -0500 77.2 +++ b/xen/common/sched_sedf.c Wed Aug 09 18:04:20 2006 +0100 77.3 @@ -113,13 +113,14 @@ struct sedf_cpu_info { 77.4 }; 77.5 77.6 #define EDOM_INFO(d) ((struct sedf_vcpu_info *)((d)->sched_priv)) 77.7 -#define CPU_INFO(cpu) ((struct sedf_cpu_info *)schedule_data[cpu].sched_priv) 77.8 +#define CPU_INFO(cpu) \ 77.9 + ((struct sedf_cpu_info *)per_cpu(schedule_data, cpu).sched_priv) 77.10 #define LIST(d) (&EDOM_INFO(d)->list) 77.11 #define EXTRALIST(d,i) (&(EDOM_INFO(d)->extralist[i])) 77.12 #define RUNQ(cpu) (&CPU_INFO(cpu)->runnableq) 77.13 #define WAITQ(cpu) (&CPU_INFO(cpu)->waitq) 77.14 #define EXTRAQ(cpu,i) (&(CPU_INFO(cpu)->extraq[i])) 77.15 -#define IDLETASK(cpu) ((struct vcpu *)schedule_data[cpu].idle) 77.16 +#define IDLETASK(cpu) ((struct vcpu *)per_cpu(schedule_data, cpu).idle) 77.17 77.18 #define PERIOD_BEGIN(inf) ((inf)->deadl_abs - (inf)->period) 77.19 77.20 @@ -348,11 +349,11 @@ static int sedf_init_vcpu(struct vcpu *v 77.21 inf->vcpu = v; 77.22 77.23 /* Allocate per-CPU context if this is the first domain to be added. */ 77.24 - if ( unlikely(schedule_data[v->processor].sched_priv == NULL) ) 77.25 + if ( unlikely(per_cpu(schedule_data, v->processor).sched_priv == NULL) ) 77.26 { 77.27 - schedule_data[v->processor].sched_priv = 77.28 + per_cpu(schedule_data, v->processor).sched_priv = 77.29 xmalloc(struct sedf_cpu_info); 77.30 - BUG_ON(schedule_data[v->processor].sched_priv == NULL); 77.31 + BUG_ON(per_cpu(schedule_data, v->processor).sched_priv == NULL); 77.32 memset(CPU_INFO(v->processor), 0, sizeof(*CPU_INFO(v->processor))); 77.33 INIT_LIST_HEAD(WAITQ(v->processor)); 77.34 INIT_LIST_HEAD(RUNQ(v->processor)); 77.35 @@ -847,7 +848,7 @@ static void sedf_sleep(struct vcpu *d) 77.36 77.37 EDOM_INFO(d)->status |= SEDF_ASLEEP; 77.38 77.39 - if ( schedule_data[d->processor].curr == d ) 77.40 + if ( per_cpu(schedule_data, d->processor).curr == d ) 77.41 { 77.42 cpu_raise_softirq(d->processor, SCHEDULE_SOFTIRQ); 77.43 } 77.44 @@ -1167,9 +1168,9 @@ void sedf_wake(struct vcpu *d) 77.45 Save approximation: Always switch to scheduler!*/ 77.46 ASSERT(d->processor >= 0); 77.47 ASSERT(d->processor < NR_CPUS); 77.48 - ASSERT(schedule_data[d->processor].curr); 77.49 + ASSERT(per_cpu(schedule_data, d->processor).curr); 77.50 77.51 - if ( should_switch(schedule_data[d->processor].curr, d, now) ) 77.52 + if ( should_switch(per_cpu(schedule_data, d->processor).curr, d, now) ) 77.53 cpu_raise_softirq(d->processor, SCHEDULE_SOFTIRQ); 77.54 } 77.55
78.1 --- a/xen/common/schedule.c Tue Aug 08 19:07:32 2006 -0500 78.2 +++ b/xen/common/schedule.c Wed Aug 09 18:04:20 2006 +0100 78.3 @@ -46,7 +46,7 @@ static void vcpu_timer_fn(void *data); 78.4 static void poll_timer_fn(void *data); 78.5 78.6 /* This is global for now so that private implementations can reach it */ 78.7 -struct schedule_data schedule_data[NR_CPUS]; 78.8 +DEFINE_PER_CPU(struct schedule_data, schedule_data); 78.9 78.10 extern struct scheduler sched_bvt_def; 78.11 extern struct scheduler sched_sedf_def; 78.12 @@ -67,13 +67,13 @@ static struct scheduler ops; 78.13 : (typeof(ops.fn(__VA_ARGS__)))0 ) 78.14 78.15 /* Per-CPU periodic timer sends an event to the currently-executing domain. */ 78.16 -static struct timer t_timer[NR_CPUS]; 78.17 +static DEFINE_PER_CPU(struct timer, t_timer); 78.18 78.19 static inline void vcpu_runstate_change( 78.20 struct vcpu *v, int new_state, s_time_t new_entry_time) 78.21 { 78.22 ASSERT(v->runstate.state != new_state); 78.23 - ASSERT(spin_is_locked(&schedule_data[v->processor].schedule_lock)); 78.24 + ASSERT(spin_is_locked(&per_cpu(schedule_data,v->processor).schedule_lock)); 78.25 78.26 v->runstate.time[v->runstate.state] += 78.27 new_entry_time - v->runstate.state_entry_time; 78.28 @@ -107,8 +107,8 @@ int sched_init_vcpu(struct vcpu *v) 78.29 78.30 if ( is_idle_vcpu(v) ) 78.31 { 78.32 - schedule_data[v->processor].curr = v; 78.33 - schedule_data[v->processor].idle = v; 78.34 + per_cpu(schedule_data, v->processor).curr = v; 78.35 + per_cpu(schedule_data, v->processor).idle = v; 78.36 set_bit(_VCPUF_running, &v->vcpu_flags); 78.37 } 78.38 78.39 @@ -500,19 +500,21 @@ long sched_adjdom(struct sched_adjdom_cm 78.40 */ 78.41 static void __enter_scheduler(void) 78.42 { 78.43 - struct vcpu *prev = current, *next = NULL; 78.44 - int cpu = smp_processor_id(); 78.45 - s_time_t now = NOW(); 78.46 - struct task_slice next_slice; 78.47 - s32 r_time; /* time for new dom to run */ 78.48 + struct vcpu *prev = current, *next = NULL; 78.49 + s_time_t now = NOW(); 78.50 + struct schedule_data *sd; 78.51 + struct task_slice next_slice; 78.52 + s32 r_time; /* time for new dom to run */ 78.53 78.54 ASSERT(!in_irq()); 78.55 78.56 perfc_incrc(sched_run); 78.57 78.58 - spin_lock_irq(&schedule_data[cpu].schedule_lock); 78.59 + sd = &this_cpu(schedule_data); 78.60 78.61 - stop_timer(&schedule_data[cpu].s_timer); 78.62 + spin_lock_irq(&sd->schedule_lock); 78.63 + 78.64 + stop_timer(&sd->s_timer); 78.65 78.66 /* get policy-specific decision on scheduling... */ 78.67 next_slice = ops.do_schedule(now); 78.68 @@ -520,13 +522,13 @@ static void __enter_scheduler(void) 78.69 r_time = next_slice.time; 78.70 next = next_slice.task; 78.71 78.72 - schedule_data[cpu].curr = next; 78.73 + sd->curr = next; 78.74 78.75 - set_timer(&schedule_data[cpu].s_timer, now + r_time); 78.76 + set_timer(&sd->s_timer, now + r_time); 78.77 78.78 if ( unlikely(prev == next) ) 78.79 { 78.80 - spin_unlock_irq(&schedule_data[cpu].schedule_lock); 78.81 + spin_unlock_irq(&sd->schedule_lock); 78.82 return continue_running(prev); 78.83 } 78.84 78.85 @@ -552,17 +554,17 @@ static void __enter_scheduler(void) 78.86 ASSERT(!test_bit(_VCPUF_running, &next->vcpu_flags)); 78.87 set_bit(_VCPUF_running, &next->vcpu_flags); 78.88 78.89 - spin_unlock_irq(&schedule_data[cpu].schedule_lock); 78.90 + spin_unlock_irq(&sd->schedule_lock); 78.91 78.92 perfc_incrc(sched_ctx); 78.93 78.94 - prev->sleep_tick = schedule_data[cpu].tick; 78.95 + prev->sleep_tick = sd->tick; 78.96 78.97 /* Ensure that the domain has an up-to-date time base. */ 78.98 if ( !is_idle_vcpu(next) ) 78.99 { 78.100 update_vcpu_system_time(next); 78.101 - if ( next->sleep_tick != schedule_data[cpu].tick ) 78.102 + if ( next->sleep_tick != sd->tick ) 78.103 send_timer_event(next); 78.104 } 78.105 78.106 @@ -591,10 +593,9 @@ static void s_timer_fn(void *unused) 78.107 /* Periodic tick timer: send timer event to current domain */ 78.108 static void t_timer_fn(void *unused) 78.109 { 78.110 - struct vcpu *v = current; 78.111 - unsigned int cpu = smp_processor_id(); 78.112 + struct vcpu *v = current; 78.113 78.114 - schedule_data[cpu].tick++; 78.115 + this_cpu(schedule_data).tick++; 78.116 78.117 if ( !is_idle_vcpu(v) ) 78.118 { 78.119 @@ -604,9 +605,9 @@ static void t_timer_fn(void *unused) 78.120 78.121 page_scrub_schedule_work(); 78.122 78.123 - SCHED_OP(tick, cpu); 78.124 + SCHED_OP(tick, smp_processor_id()); 78.125 78.126 - set_timer(&t_timer[cpu], NOW() + MILLISECS(10)); 78.127 + set_timer(&this_cpu(t_timer), NOW() + MILLISECS(10)); 78.128 } 78.129 78.130 /* Per-VCPU timer function: sends a virtual timer interrupt. */ 78.131 @@ -633,9 +634,9 @@ void __init scheduler_init(void) 78.132 78.133 for ( i = 0; i < NR_CPUS; i++ ) 78.134 { 78.135 - spin_lock_init(&schedule_data[i].schedule_lock); 78.136 - init_timer(&schedule_data[i].s_timer, s_timer_fn, NULL, i); 78.137 - init_timer(&t_timer[i], t_timer_fn, NULL, i); 78.138 + spin_lock_init(&per_cpu(schedule_data, i).schedule_lock); 78.139 + init_timer(&per_cpu(schedule_data, i).s_timer, s_timer_fn, NULL, i); 78.140 + init_timer(&per_cpu(t_timer, i), t_timer_fn, NULL, i); 78.141 } 78.142 78.143 for ( i = 0; schedulers[i] != NULL; i++ ) 78.144 @@ -676,10 +677,10 @@ void dump_runq(unsigned char key) 78.145 78.146 for_each_online_cpu ( i ) 78.147 { 78.148 - spin_lock(&schedule_data[i].schedule_lock); 78.149 + spin_lock(&per_cpu(schedule_data, i).schedule_lock); 78.150 printk("CPU[%02d] ", i); 78.151 - SCHED_OP(dump_cpu_state,i); 78.152 - spin_unlock(&schedule_data[i].schedule_lock); 78.153 + SCHED_OP(dump_cpu_state, i); 78.154 + spin_unlock(&per_cpu(schedule_data, i).schedule_lock); 78.155 } 78.156 78.157 local_irq_restore(flags);
79.1 --- a/xen/common/timer.c Tue Aug 08 19:07:32 2006 -0500 79.2 +++ b/xen/common/timer.c Wed Aug 09 18:04:20 2006 +0100 79.3 @@ -17,6 +17,7 @@ 79.4 #include <xen/softirq.h> 79.5 #include <xen/timer.h> 79.6 #include <xen/keyhandler.h> 79.7 +#include <xen/percpu.h> 79.8 #include <asm/system.h> 79.9 #include <asm/desc.h> 79.10 79.11 @@ -32,7 +33,7 @@ struct timers { 79.12 struct timer *running; 79.13 } __cacheline_aligned; 79.14 79.15 -struct timers timers[NR_CPUS]; 79.16 +static DEFINE_PER_CPU(struct timers, timers); 79.17 79.18 extern int reprogram_timer(s_time_t timeout); 79.19 79.20 @@ -149,7 +150,7 @@ static int add_entry(struct timer ***phe 79.21 static inline void __add_timer(struct timer *timer) 79.22 { 79.23 int cpu = timer->cpu; 79.24 - if ( add_entry(&timers[cpu].heap, timer) ) 79.25 + if ( add_entry(&per_cpu(timers, cpu).heap, timer) ) 79.26 cpu_raise_softirq(cpu, TIMER_SOFTIRQ); 79.27 } 79.28 79.29 @@ -157,7 +158,7 @@ static inline void __add_timer(struct ti 79.30 static inline void __stop_timer(struct timer *timer) 79.31 { 79.32 int cpu = timer->cpu; 79.33 - if ( remove_entry(timers[cpu].heap, timer) ) 79.34 + if ( remove_entry(per_cpu(timers, cpu).heap, timer) ) 79.35 cpu_raise_softirq(cpu, TIMER_SOFTIRQ); 79.36 } 79.37 79.38 @@ -168,10 +169,10 @@ static inline void timer_lock(struct tim 79.39 for ( ; ; ) 79.40 { 79.41 cpu = timer->cpu; 79.42 - spin_lock(&timers[cpu].lock); 79.43 + spin_lock(&per_cpu(timers, cpu).lock); 79.44 if ( likely(timer->cpu == cpu) ) 79.45 break; 79.46 - spin_unlock(&timers[cpu].lock); 79.47 + spin_unlock(&per_cpu(timers, cpu).lock); 79.48 } 79.49 } 79.50 79.51 @@ -182,7 +183,7 @@ static inline void timer_lock(struct tim 79.52 79.53 static inline void timer_unlock(struct timer *timer) 79.54 { 79.55 - spin_unlock(&timers[timer->cpu].lock); 79.56 + spin_unlock(&per_cpu(timers, timer->cpu).lock); 79.57 } 79.58 79.59 #define timer_unlock_irq(t) \ 79.60 @@ -234,20 +235,20 @@ void migrate_timer(struct timer *timer, 79.61 79.62 if ( old_cpu < new_cpu ) 79.63 { 79.64 - spin_lock_irqsave(&timers[old_cpu].lock, flags); 79.65 - spin_lock(&timers[new_cpu].lock); 79.66 + spin_lock_irqsave(&per_cpu(timers, old_cpu).lock, flags); 79.67 + spin_lock(&per_cpu(timers, new_cpu).lock); 79.68 } 79.69 else 79.70 { 79.71 - spin_lock_irqsave(&timers[new_cpu].lock, flags); 79.72 - spin_lock(&timers[old_cpu].lock); 79.73 + spin_lock_irqsave(&per_cpu(timers, new_cpu).lock, flags); 79.74 + spin_lock(&per_cpu(timers, old_cpu).lock); 79.75 } 79.76 79.77 if ( likely(timer->cpu == old_cpu) ) 79.78 break; 79.79 79.80 - spin_unlock(&timers[old_cpu].lock); 79.81 - spin_unlock_irqrestore(&timers[new_cpu].lock, flags); 79.82 + spin_unlock(&per_cpu(timers, old_cpu).lock); 79.83 + spin_unlock_irqrestore(&per_cpu(timers, new_cpu).lock, flags); 79.84 } 79.85 79.86 if ( active_timer(timer) ) 79.87 @@ -261,8 +262,8 @@ void migrate_timer(struct timer *timer, 79.88 timer->cpu = new_cpu; 79.89 } 79.90 79.91 - spin_unlock(&timers[old_cpu].lock); 79.92 - spin_unlock_irqrestore(&timers[new_cpu].lock, flags); 79.93 + spin_unlock(&per_cpu(timers, old_cpu).lock); 79.94 + spin_unlock_irqrestore(&per_cpu(timers, new_cpu).lock, flags); 79.95 } 79.96 79.97 79.98 @@ -271,7 +272,7 @@ void kill_timer(struct timer *timer) 79.99 int cpu; 79.100 unsigned long flags; 79.101 79.102 - BUG_ON(timers[smp_processor_id()].running == timer); 79.103 + BUG_ON(this_cpu(timers).running == timer); 79.104 79.105 timer_lock_irqsave(timer, flags); 79.106 79.107 @@ -282,23 +283,25 @@ void kill_timer(struct timer *timer) 79.108 timer_unlock_irqrestore(timer, flags); 79.109 79.110 for_each_online_cpu ( cpu ) 79.111 - while ( timers[cpu].running == timer ) 79.112 + while ( per_cpu(timers, cpu).running == timer ) 79.113 cpu_relax(); 79.114 } 79.115 79.116 79.117 static void timer_softirq_action(void) 79.118 { 79.119 - int cpu = smp_processor_id(); 79.120 - struct timer *t, **heap; 79.121 - s_time_t now; 79.122 - void (*fn)(void *); 79.123 - void *data; 79.124 + struct timer *t, **heap; 79.125 + struct timers *ts; 79.126 + s_time_t now; 79.127 + void (*fn)(void *); 79.128 + void *data; 79.129 79.130 - spin_lock_irq(&timers[cpu].lock); 79.131 + ts = &this_cpu(timers); 79.132 + 79.133 + spin_lock_irq(&ts->lock); 79.134 79.135 do { 79.136 - heap = timers[cpu].heap; 79.137 + heap = ts->heap; 79.138 now = NOW(); 79.139 79.140 while ( (GET_HEAP_SIZE(heap) != 0) && 79.141 @@ -306,24 +309,24 @@ static void timer_softirq_action(void) 79.142 { 79.143 remove_entry(heap, t); 79.144 79.145 - timers[cpu].running = t; 79.146 + ts->running = t; 79.147 79.148 fn = t->function; 79.149 data = t->data; 79.150 79.151 - spin_unlock_irq(&timers[cpu].lock); 79.152 + spin_unlock_irq(&ts->lock); 79.153 (*fn)(data); 79.154 - spin_lock_irq(&timers[cpu].lock); 79.155 + spin_lock_irq(&ts->lock); 79.156 79.157 /* Heap may have grown while the lock was released. */ 79.158 - heap = timers[cpu].heap; 79.159 + heap = ts->heap; 79.160 } 79.161 79.162 - timers[cpu].running = NULL; 79.163 + ts->running = NULL; 79.164 } 79.165 while ( !reprogram_timer(GET_HEAP_SIZE(heap) ? heap[1]->expires : 0) ); 79.166 79.167 - spin_unlock_irq(&timers[cpu].lock); 79.168 + spin_unlock_irq(&ts->lock); 79.169 } 79.170 79.171 79.172 @@ -338,25 +341,28 @@ void process_pending_timers(void) 79.173 79.174 static void dump_timerq(unsigned char key) 79.175 { 79.176 - struct timer *t; 79.177 - unsigned long flags; 79.178 - s_time_t now = NOW(); 79.179 - int i, j; 79.180 + struct timer *t; 79.181 + struct timers *ts; 79.182 + unsigned long flags; 79.183 + s_time_t now = NOW(); 79.184 + int i, j; 79.185 79.186 printk("Dumping timer queues: NOW=0x%08X%08X\n", 79.187 (u32)(now>>32), (u32)now); 79.188 79.189 for_each_online_cpu( i ) 79.190 { 79.191 + ts = &per_cpu(timers, i); 79.192 + 79.193 printk("CPU[%02d] ", i); 79.194 - spin_lock_irqsave(&timers[i].lock, flags); 79.195 - for ( j = 1; j <= GET_HEAP_SIZE(timers[i].heap); j++ ) 79.196 + spin_lock_irqsave(&ts->lock, flags); 79.197 + for ( j = 1; j <= GET_HEAP_SIZE(ts->heap); j++ ) 79.198 { 79.199 - t = timers[i].heap[j]; 79.200 + t = ts->heap[j]; 79.201 printk (" %d : %p ex=0x%08X%08X %p\n", 79.202 j, t, (u32)(t->expires>>32), (u32)t->expires, t->data); 79.203 } 79.204 - spin_unlock_irqrestore(&timers[i].lock, flags); 79.205 + spin_unlock_irqrestore(&ts->lock, flags); 79.206 printk("\n"); 79.207 } 79.208 } 79.209 @@ -378,8 +384,8 @@ void __init timer_init(void) 79.210 79.211 for ( i = 0; i < NR_CPUS; i++ ) 79.212 { 79.213 - spin_lock_init(&timers[i].lock); 79.214 - timers[i].heap = &dummy_heap; 79.215 + spin_lock_init(&per_cpu(timers, i).lock); 79.216 + per_cpu(timers, i).heap = &dummy_heap; 79.217 } 79.218 79.219 register_keyhandler('a', dump_timerq, "dump timer queues");
80.1 --- a/xen/common/trace.c Tue Aug 08 19:07:32 2006 -0500 80.2 +++ b/xen/common/trace.c Wed Aug 09 18:04:20 2006 +0100 80.3 @@ -39,8 +39,8 @@ static unsigned int opt_tbuf_size = 0; 80.4 integer_param("tbuf_size", opt_tbuf_size); 80.5 80.6 /* Pointers to the meta-data objects for all system trace buffers */ 80.7 -static struct t_buf *t_bufs[NR_CPUS]; 80.8 -static struct t_rec *t_recs[NR_CPUS]; 80.9 +static DEFINE_PER_CPU(struct t_buf *, t_bufs); 80.10 +static DEFINE_PER_CPU(struct t_rec *, t_recs); 80.11 static int nr_recs; 80.12 80.13 /* High water mark for trace buffers; */ 80.14 @@ -105,9 +105,10 @@ static int alloc_trace_bufs(void) 80.15 80.16 for_each_online_cpu ( i ) 80.17 { 80.18 - buf = t_bufs[i] = (struct t_buf *)&rawbuf[i*opt_tbuf_size*PAGE_SIZE]; 80.19 + buf = per_cpu(t_bufs, i) = (struct t_buf *) 80.20 + &rawbuf[i*opt_tbuf_size*PAGE_SIZE]; 80.21 buf->cons = buf->prod = 0; 80.22 - t_recs[i] = (struct t_rec *)(buf + 1); 80.23 + per_cpu(t_recs, i) = (struct t_rec *)(buf + 1); 80.24 } 80.25 80.26 t_buf_highwater = nr_recs >> 1; /* 50% high water */ 80.27 @@ -186,7 +187,7 @@ int tb_control(dom0_tbufcontrol_t *tbc) 80.28 case DOM0_TBUF_GET_INFO: 80.29 tbc->cpu_mask = tb_cpu_mask; 80.30 tbc->evt_mask = tb_event_mask; 80.31 - tbc->buffer_mfn = opt_tbuf_size ? virt_to_mfn(t_bufs[0]) : 0UL; 80.32 + tbc->buffer_mfn = opt_tbuf_size ? virt_to_mfn(per_cpu(t_bufs, 0)) : 0; 80.33 tbc->size = opt_tbuf_size * PAGE_SIZE; 80.34 break; 80.35 case DOM0_TBUF_SET_CPU_MASK: 80.36 @@ -258,7 +259,7 @@ void trace(u32 event, unsigned long d1, 80.37 /* Read tb_init_done /before/ t_bufs. */ 80.38 rmb(); 80.39 80.40 - buf = t_bufs[smp_processor_id()]; 80.41 + buf = this_cpu(t_bufs); 80.42 80.43 local_irq_save(flags); 80.44 80.45 @@ -272,7 +273,7 @@ void trace(u32 event, unsigned long d1, 80.46 80.47 if ( unlikely(this_cpu(lost_records) != 0) ) 80.48 { 80.49 - rec = &t_recs[smp_processor_id()][buf->prod % nr_recs]; 80.50 + rec = &this_cpu(t_recs)[buf->prod % nr_recs]; 80.51 memset(rec, 0, sizeof(*rec)); 80.52 rec->cycles = (u64)get_cycles(); 80.53 rec->event = TRC_LOST_RECORDS; 80.54 @@ -283,7 +284,7 @@ void trace(u32 event, unsigned long d1, 80.55 buf->prod++; 80.56 } 80.57 80.58 - rec = &t_recs[smp_processor_id()][buf->prod % nr_recs]; 80.59 + rec = &this_cpu(t_recs)[buf->prod % nr_recs]; 80.60 rec->cycles = (u64)get_cycles(); 80.61 rec->event = event; 80.62 rec->data[0] = d1;
81.1 --- a/xen/drivers/char/console.c Tue Aug 08 19:07:32 2006 -0500 81.2 +++ b/xen/drivers/char/console.c Wed Aug 09 18:04:20 2006 +0100 81.3 @@ -716,7 +716,6 @@ void panic(const char *fmt, ...) 81.4 char buf[128]; 81.5 unsigned long flags; 81.6 static DEFINE_SPINLOCK(lock); 81.7 - extern void machine_restart(char *); 81.8 81.9 debugtrace_dump(); 81.10
82.1 --- a/xen/include/asm-ia64/linux-xen/asm/cache.h Tue Aug 08 19:07:32 2006 -0500 82.2 +++ b/xen/include/asm-ia64/linux-xen/asm/cache.h Wed Aug 09 18:04:20 2006 +0100 82.3 @@ -32,4 +32,6 @@ 82.4 #endif 82.5 #endif 82.6 82.7 +#define __read_mostly 82.8 + 82.9 #endif /* _ASM_IA64_CACHE_H */
83.1 --- a/xen/include/asm-powerpc/cache.h Tue Aug 08 19:07:32 2006 -0500 83.2 +++ b/xen/include/asm-powerpc/cache.h Wed Aug 09 18:04:20 2006 +0100 83.3 @@ -57,4 +57,6 @@ static __inline__ void synchronize_cache 83.4 isync(); 83.5 } 83.6 83.7 +#define __read_mostly 83.8 + 83.9 #endif
84.1 --- a/xen/include/asm-powerpc/flushtlb.h Tue Aug 08 19:07:32 2006 -0500 84.2 +++ b/xen/include/asm-powerpc/flushtlb.h Wed Aug 09 18:04:20 2006 +0100 84.3 @@ -22,6 +22,7 @@ 84.4 #define _ASM_FLUSHTLB_H_ 84.5 84.6 #include <xen/config.h> 84.7 +#include <xen/percpu.h> 84.8 #include <xen/types.h> 84.9 #include <asm/misc.h> 84.10 84.11 @@ -30,7 +31,7 @@ extern u32 tlbflush_clock; 84.12 #define tlbflush_current_time() tlbflush_clock 84.13 84.14 /* Time at which each CPU's TLB was last flushed. */ 84.15 -extern u32 tlbflush_time[NR_CPUS]; 84.16 +DECLARE_PER_CPU(u32, tlbflush_time); 84.17 84.18 static inline int NEED_FLUSH(u32 cpu_stamp, u32 lastuse_stamp) 84.19 { 84.20 @@ -44,12 +45,12 @@ static inline int NEED_FLUSH(u32 cpu_sta 84.21 * Filter the given set of CPUs, removing those that definitely flushed their 84.22 * TLB since @page_timestamp. 84.23 */ 84.24 -#define tlbflush_filter(mask, page_timestamp) \ 84.25 -do { \ 84.26 - unsigned int cpu; \ 84.27 - for_each_cpu_mask ( cpu, mask ) \ 84.28 - if ( !NEED_FLUSH(tlbflush_time[cpu], page_timestamp) ) \ 84.29 - cpu_clear(cpu, mask); \ 84.30 +#define tlbflush_filter(mask, page_timestamp) \ 84.31 +do { \ 84.32 + unsigned int cpu; \ 84.33 + for_each_cpu_mask ( cpu, mask ) \ 84.34 + if ( !NEED_FLUSH(per_cpu(tlbflush_time, cpu), page_timestamp) ) \ 84.35 + cpu_clear(cpu, mask); \ 84.36 } while ( 0 ) 84.37 84.38
85.1 --- a/xen/include/asm-x86/cache.h Tue Aug 08 19:07:32 2006 -0500 85.2 +++ b/xen/include/asm-x86/cache.h Wed Aug 09 18:04:20 2006 +0100 85.3 @@ -10,4 +10,6 @@ 85.4 #define L1_CACHE_SHIFT (CONFIG_X86_L1_CACHE_SHIFT) 85.5 #define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) 85.6 85.7 +#define __read_mostly __attribute__((__section__(".data.read_mostly"))) 85.8 + 85.9 #endif
86.1 --- a/xen/include/asm-x86/current.h Tue Aug 08 19:07:32 2006 -0500 86.2 +++ b/xen/include/asm-x86/current.h Wed Aug 09 18:04:20 2006 +0100 86.3 @@ -8,6 +8,7 @@ 86.4 #define __X86_CURRENT_H__ 86.5 86.6 #include <xen/config.h> 86.7 +#include <xen/percpu.h> 86.8 #include <public/xen.h> 86.9 #include <asm/page.h> 86.10 86.11 @@ -53,7 +54,6 @@ static inline struct cpu_info *get_cpu_i 86.12 86.13 #define schedule_tail(vcpu) (((vcpu)->arch.schedule_tail)(vcpu)) 86.14 86.15 -#include <xen/percpu.h> 86.16 /* 86.17 * Which VCPU's state is currently running on each CPU? 86.18 * This is not necesasrily the same as 'current' as a CPU may be
87.1 --- a/xen/include/asm-x86/e820.h Tue Aug 08 19:07:32 2006 -0500 87.2 +++ b/xen/include/asm-x86/e820.h Wed Aug 09 18:04:20 2006 +0100 87.3 @@ -12,6 +12,7 @@ 87.4 #define E820_IO 16 87.5 #define E820_SHARED_PAGE 17 87.6 #define E820_XENSTORE 18 87.7 +#define E820_BUFFERED_IO 19 87.8 87.9 #define E820_MAP_PAGE 0x00090000 87.10 #define E820_MAP_NR_OFFSET 0x000001E8
88.1 --- a/xen/include/asm-x86/flushtlb.h Tue Aug 08 19:07:32 2006 -0500 88.2 +++ b/xen/include/asm-x86/flushtlb.h Wed Aug 09 18:04:20 2006 +0100 88.3 @@ -11,13 +11,15 @@ 88.4 #define __FLUSHTLB_H__ 88.5 88.6 #include <xen/config.h> 88.7 +#include <xen/percpu.h> 88.8 #include <xen/smp.h> 88.9 +#include <xen/types.h> 88.10 88.11 /* The current time as shown by the virtual TLB clock. */ 88.12 extern u32 tlbflush_clock; 88.13 88.14 /* Time at which each CPU's TLB was last flushed. */ 88.15 -extern u32 tlbflush_time[NR_CPUS]; 88.16 +DECLARE_PER_CPU(u32, tlbflush_time); 88.17 88.18 #define tlbflush_current_time() tlbflush_clock 88.19 88.20 @@ -47,12 +49,12 @@ static inline int NEED_FLUSH(u32 cpu_sta 88.21 * Filter the given set of CPUs, removing those that definitely flushed their 88.22 * TLB since @page_timestamp. 88.23 */ 88.24 -#define tlbflush_filter(mask, page_timestamp) \ 88.25 -do { \ 88.26 - unsigned int cpu; \ 88.27 - for_each_cpu_mask ( cpu, mask ) \ 88.28 - if ( !NEED_FLUSH(tlbflush_time[cpu], page_timestamp) ) \ 88.29 - cpu_clear(cpu, mask); \ 88.30 +#define tlbflush_filter(mask, page_timestamp) \ 88.31 +do { \ 88.32 + unsigned int cpu; \ 88.33 + for_each_cpu_mask ( cpu, mask ) \ 88.34 + if ( !NEED_FLUSH(per_cpu(tlbflush_time, cpu), page_timestamp) ) \ 88.35 + cpu_clear(cpu, mask); \ 88.36 } while ( 0 ) 88.37 88.38 extern void new_tlbflush_clock_period(void);
89.1 --- a/xen/include/asm-x86/hvm/domain.h Tue Aug 08 19:07:32 2006 -0500 89.2 +++ b/xen/include/asm-x86/hvm/domain.h Wed Aug 09 18:04:20 2006 +0100 89.3 @@ -33,6 +33,8 @@ 89.4 89.5 struct hvm_domain { 89.6 unsigned long shared_page_va; 89.7 + unsigned long buffered_io_va; 89.8 + spinlock_t buffered_io_lock; 89.9 s64 tsc_frequency; 89.10 struct pl_time pl_time; 89.11
90.1 --- a/xen/include/asm-x86/hvm/hvm.h Tue Aug 08 19:07:32 2006 -0500 90.2 +++ b/xen/include/asm-x86/hvm/hvm.h Wed Aug 09 18:04:20 2006 +0100 90.3 @@ -77,12 +77,20 @@ hvm_disable(void) 90.4 hvm_funcs.disable(); 90.5 } 90.6 90.7 +void hvm_create_event_channels(struct vcpu *v); 90.8 +void hvm_map_io_shared_pages(struct vcpu *v); 90.9 + 90.10 static inline int 90.11 hvm_initialize_guest_resources(struct vcpu *v) 90.12 { 90.13 + int ret = 1; 90.14 if ( hvm_funcs.initialize_guest_resources ) 90.15 - return hvm_funcs.initialize_guest_resources(v); 90.16 - return 0; 90.17 + ret = hvm_funcs.initialize_guest_resources(v); 90.18 + if ( ret == 1 ) { 90.19 + hvm_map_io_shared_pages(v); 90.20 + hvm_create_event_channels(v); 90.21 + } 90.22 + return ret; 90.23 } 90.24 90.25 static inline void
91.1 --- a/xen/include/asm-x86/hvm/io.h Tue Aug 08 19:07:32 2006 -0500 91.2 +++ b/xen/include/asm-x86/hvm/io.h Wed Aug 09 18:04:20 2006 +0100 91.3 @@ -150,13 +150,12 @@ static inline int irq_masked(unsigned lo 91.4 #endif 91.5 91.6 extern void handle_mmio(unsigned long, unsigned long); 91.7 -extern void hvm_wait_io(void); 91.8 -extern void hvm_safe_block(void); 91.9 extern void hvm_io_assist(struct vcpu *v); 91.10 extern void pic_irq_request(void *data, int level); 91.11 extern void hvm_pic_assist(struct vcpu *v); 91.12 extern int cpu_get_interrupt(struct vcpu *v, int *type); 91.13 extern int cpu_has_pending_irq(struct vcpu *v); 91.14 +extern void hvm_release_assist_channel(struct vcpu *v); 91.15 91.16 // XXX - think about this, maybe use bit 30 of the mfn to signify an MMIO frame. 91.17 #define mmio_space(gpa) (!VALID_MFN(get_mfn_from_gpfn((gpa) >> PAGE_SHIFT)))
92.1 --- a/xen/include/asm-x86/hvm/support.h Tue Aug 08 19:07:32 2006 -0500 92.2 +++ b/xen/include/asm-x86/hvm/support.h Wed Aug 09 18:04:20 2006 +0100 92.3 @@ -44,11 +44,6 @@ static inline vcpu_iodata_t *get_vio(str 92.4 return &get_sp(d)->vcpu_iodata[cpu]; 92.5 } 92.6 92.7 -static inline int iopacket_port(struct vcpu *v) 92.8 -{ 92.9 - return get_vio(v->domain, v->vcpu_id)->vp_eport; 92.10 -} 92.11 - 92.12 /* XXX these are really VMX specific */ 92.13 #define TYPE_MOV_TO_DR (0 << 4) 92.14 #define TYPE_MOV_FROM_DR (1 << 4) 92.15 @@ -144,10 +139,13 @@ extern int hvm_copy(void *buf, unsigned 92.16 extern void hvm_setup_platform(struct domain* d); 92.17 extern int hvm_mmio_intercept(ioreq_t *p); 92.18 extern int hvm_io_intercept(ioreq_t *p, int type); 92.19 +extern int hvm_buffered_io_intercept(ioreq_t *p); 92.20 extern void hvm_hooks_assist(struct vcpu *v); 92.21 extern void hvm_print_line(struct vcpu *v, const char c); 92.22 extern void hlt_timer_fn(void *data); 92.23 92.24 void hvm_do_hypercall(struct cpu_user_regs *pregs); 92.25 92.26 +void hvm_prod_vcpu(struct vcpu *v); 92.27 + 92.28 #endif /* __ASM_X86_HVM_SUPPORT_H__ */
93.1 --- a/xen/include/asm-x86/hvm/vcpu.h Tue Aug 08 19:07:32 2006 -0500 93.2 +++ b/xen/include/asm-x86/hvm/vcpu.h Wed Aug 09 18:04:20 2006 +0100 93.3 @@ -38,6 +38,8 @@ struct hvm_vcpu { 93.4 /* For AP startup */ 93.5 unsigned long init_sipi_sipi_state; 93.6 93.7 + int xen_port; 93.8 + 93.9 /* Flags */ 93.10 int flag_dr_dirty; 93.11
94.1 --- a/xen/include/asm-x86/hvm/vmx/vmx.h Tue Aug 08 19:07:32 2006 -0500 94.2 +++ b/xen/include/asm-x86/hvm/vmx/vmx.h Wed Aug 09 18:04:20 2006 +0100 94.3 @@ -40,82 +40,91 @@ extern unsigned int cpu_rev; 94.4 * Need fill bits for SENTER 94.5 */ 94.6 94.7 -#define MONITOR_PIN_BASED_EXEC_CONTROLS_RESERVED_VALUE 0x00000016 94.8 +#define MONITOR_PIN_BASED_EXEC_CONTROLS_RESERVED_VALUE 0x00000016 94.9 94.10 -#define MONITOR_PIN_BASED_EXEC_CONTROLS \ 94.11 - ( \ 94.12 - MONITOR_PIN_BASED_EXEC_CONTROLS_RESERVED_VALUE | \ 94.13 - PIN_BASED_EXT_INTR_MASK | \ 94.14 - PIN_BASED_NMI_EXITING \ 94.15 +#define MONITOR_PIN_BASED_EXEC_CONTROLS \ 94.16 + ( \ 94.17 + MONITOR_PIN_BASED_EXEC_CONTROLS_RESERVED_VALUE | \ 94.18 + PIN_BASED_EXT_INTR_MASK | \ 94.19 + PIN_BASED_NMI_EXITING \ 94.20 ) 94.21 94.22 -#define MONITOR_CPU_BASED_EXEC_CONTROLS_RESERVED_VALUE 0x0401e172 94.23 +#define MONITOR_CPU_BASED_EXEC_CONTROLS_RESERVED_VALUE 0x0401e172 94.24 94.25 -#define _MONITOR_CPU_BASED_EXEC_CONTROLS \ 94.26 - ( \ 94.27 +#define _MONITOR_CPU_BASED_EXEC_CONTROLS \ 94.28 + ( \ 94.29 MONITOR_CPU_BASED_EXEC_CONTROLS_RESERVED_VALUE | \ 94.30 - CPU_BASED_HLT_EXITING | \ 94.31 - CPU_BASED_INVDPG_EXITING | \ 94.32 - CPU_BASED_MWAIT_EXITING | \ 94.33 - CPU_BASED_MOV_DR_EXITING | \ 94.34 - CPU_BASED_ACTIVATE_IO_BITMAP | \ 94.35 - CPU_BASED_USE_TSC_OFFSETING \ 94.36 + CPU_BASED_HLT_EXITING | \ 94.37 + CPU_BASED_INVDPG_EXITING | \ 94.38 + CPU_BASED_MWAIT_EXITING | \ 94.39 + CPU_BASED_MOV_DR_EXITING | \ 94.40 + CPU_BASED_ACTIVATE_IO_BITMAP | \ 94.41 + CPU_BASED_USE_TSC_OFFSETING \ 94.42 ) 94.43 94.44 -#define MONITOR_CPU_BASED_EXEC_CONTROLS_IA32E_MODE \ 94.45 - ( \ 94.46 - CPU_BASED_CR8_LOAD_EXITING | \ 94.47 - CPU_BASED_CR8_STORE_EXITING \ 94.48 +#define MONITOR_CPU_BASED_EXEC_CONTROLS_IA32E_MODE \ 94.49 + ( \ 94.50 + CPU_BASED_CR8_LOAD_EXITING | \ 94.51 + CPU_BASED_CR8_STORE_EXITING \ 94.52 ) 94.53 94.54 -#define MONITOR_VM_EXIT_CONTROLS_RESERVED_VALUE 0x0003edff 94.55 +#define MONITOR_VM_EXIT_CONTROLS_RESERVED_VALUE 0x0003edff 94.56 94.57 -#define MONITOR_VM_EXIT_CONTROLS_IA32E_MODE 0x00000200 94.58 +#define MONITOR_VM_EXIT_CONTROLS_IA32E_MODE 0x00000200 94.59 94.60 -#define _MONITOR_VM_EXIT_CONTROLS \ 94.61 - ( \ 94.62 - MONITOR_VM_EXIT_CONTROLS_RESERVED_VALUE |\ 94.63 - VM_EXIT_ACK_INTR_ON_EXIT \ 94.64 +#define _MONITOR_VM_EXIT_CONTROLS \ 94.65 + ( \ 94.66 + MONITOR_VM_EXIT_CONTROLS_RESERVED_VALUE | \ 94.67 + VM_EXIT_ACK_INTR_ON_EXIT \ 94.68 ) 94.69 94.70 #if defined (__x86_64__) 94.71 -#define MONITOR_CPU_BASED_EXEC_CONTROLS \ 94.72 - ( \ 94.73 - _MONITOR_CPU_BASED_EXEC_CONTROLS | \ 94.74 - MONITOR_CPU_BASED_EXEC_CONTROLS_IA32E_MODE \ 94.75 +#define MONITOR_CPU_BASED_EXEC_CONTROLS \ 94.76 + ( \ 94.77 + _MONITOR_CPU_BASED_EXEC_CONTROLS | \ 94.78 + MONITOR_CPU_BASED_EXEC_CONTROLS_IA32E_MODE \ 94.79 ) 94.80 -#define MONITOR_VM_EXIT_CONTROLS \ 94.81 - ( \ 94.82 - _MONITOR_VM_EXIT_CONTROLS | \ 94.83 - MONITOR_VM_EXIT_CONTROLS_IA32E_MODE \ 94.84 +#define MONITOR_VM_EXIT_CONTROLS \ 94.85 + ( \ 94.86 + _MONITOR_VM_EXIT_CONTROLS | \ 94.87 + MONITOR_VM_EXIT_CONTROLS_IA32E_MODE \ 94.88 ) 94.89 #else 94.90 -#define MONITOR_CPU_BASED_EXEC_CONTROLS \ 94.91 - _MONITOR_CPU_BASED_EXEC_CONTROLS 94.92 +#define MONITOR_CPU_BASED_EXEC_CONTROLS \ 94.93 + _MONITOR_CPU_BASED_EXEC_CONTROLS 94.94 94.95 -#define MONITOR_VM_EXIT_CONTROLS \ 94.96 +#define MONITOR_VM_EXIT_CONTROLS \ 94.97 _MONITOR_VM_EXIT_CONTROLS 94.98 #endif 94.99 94.100 -#define VM_ENTRY_CONTROLS_RESERVED_VALUE 0x000011ff 94.101 -#define VM_ENTRY_CONTROLS_IA32E_MODE 0x00000200 94.102 -#define MONITOR_VM_ENTRY_CONTROLS VM_ENTRY_CONTROLS_RESERVED_VALUE 94.103 +#define VM_ENTRY_CONTROLS_RESERVED_VALUE 0x000011ff 94.104 +#define VM_ENTRY_CONTROLS_IA32E_MODE 0x00000200 94.105 + 94.106 +#define MONITOR_VM_ENTRY_CONTROLS \ 94.107 + VM_ENTRY_CONTROLS_RESERVED_VALUE 94.108 + 94.109 /* 94.110 * Exit Reasons 94.111 */ 94.112 -#define VMX_EXIT_REASONS_FAILED_VMENTRY 0x80000000 94.113 +#define VMX_EXIT_REASONS_FAILED_VMENTRY 0x80000000 94.114 94.115 #define EXIT_REASON_EXCEPTION_NMI 0 94.116 #define EXIT_REASON_EXTERNAL_INTERRUPT 1 94.117 - 94.118 +#define EXIT_REASON_TRIPLE_FAULT 2 94.119 +#define EXIT_REASON_INIT 3 94.120 +#define EXIT_REASON_SIPI 4 94.121 +#define EXIT_REASON_IO_SMI 5 94.122 +#define EXIT_REASON_OTHER_SMI 6 94.123 #define EXIT_REASON_PENDING_INTERRUPT 7 94.124 94.125 #define EXIT_REASON_TASK_SWITCH 9 94.126 #define EXIT_REASON_CPUID 10 94.127 #define EXIT_REASON_HLT 12 94.128 +#define EXIT_REASON_INVD 13 94.129 #define EXIT_REASON_INVLPG 14 94.130 #define EXIT_REASON_RDPMC 15 94.131 #define EXIT_REASON_RDTSC 16 94.132 +#define EXIT_REASON_RSM 17 94.133 #define EXIT_REASON_VMCALL 18 94.134 #define EXIT_REASON_VMCLEAR 19 94.135 #define EXIT_REASON_VMLAUNCH 20 94.136 @@ -124,19 +133,24 @@ extern unsigned int cpu_rev; 94.137 #define EXIT_REASON_VMREAD 23 94.138 #define EXIT_REASON_VMRESUME 24 94.139 #define EXIT_REASON_VMWRITE 25 94.140 -#define EXIT_REASON_VMOFF 26 94.141 -#define EXIT_REASON_VMON 27 94.142 +#define EXIT_REASON_VMXOFF 26 94.143 +#define EXIT_REASON_VMXON 27 94.144 #define EXIT_REASON_CR_ACCESS 28 94.145 #define EXIT_REASON_DR_ACCESS 29 94.146 #define EXIT_REASON_IO_INSTRUCTION 30 94.147 #define EXIT_REASON_MSR_READ 31 94.148 #define EXIT_REASON_MSR_WRITE 32 94.149 -#define EXIT_REASON_MWAIT_INSTRUCTION 36 94.150 94.151 #define EXIT_REASON_INVALID_GUEST_STATE 33 94.152 #define EXIT_REASON_MSR_LOADING 34 94.153 + 94.154 +#define EXIT_REASON_MWAIT_INSTRUCTION 36 94.155 +#define EXIT_REASON_MONITOR_INSTRUCTION 39 94.156 +#define EXIT_REASON_PAUSE_INSTRUCTION 40 94.157 + 94.158 #define EXIT_REASON_MACHINE_CHECK 41 94.159 94.160 +#define EXIT_REASON_TPR_BELOW_THRESHOLD 43 94.161 94.162 /* 94.163 * Interruption-information format 94.164 @@ -146,9 +160,9 @@ extern unsigned int cpu_rev; 94.165 #define INTR_INFO_DELIVER_CODE_MASK 0x800 /* 11 */ 94.166 #define INTR_INFO_VALID_MASK 0x80000000 /* 31 */ 94.167 94.168 -#define INTR_TYPE_EXT_INTR (0 << 8) /* external interrupt */ 94.169 -#define INTR_TYPE_HW_EXCEPTION (3 << 8) /* hardware exception */ 94.170 -#define INTR_TYPE_SW_EXCEPTION (6 << 8) /* software exception */ 94.171 +#define INTR_TYPE_EXT_INTR (0 << 8) /* external interrupt */ 94.172 +#define INTR_TYPE_HW_EXCEPTION (3 << 8) /* hardware exception */ 94.173 +#define INTR_TYPE_SW_EXCEPTION (6 << 8) /* software exception */ 94.174 94.175 /* 94.176 * Exit Qualifications for MOV for Control Register Access 94.177 @@ -156,33 +170,33 @@ extern unsigned int cpu_rev; 94.178 #define CONTROL_REG_ACCESS_NUM 0xf /* 3:0, number of control register */ 94.179 #define CONTROL_REG_ACCESS_TYPE 0x30 /* 5:4, access type */ 94.180 #define CONTROL_REG_ACCESS_REG 0xf00 /* 10:8, general purpose register */ 94.181 -#define LMSW_SOURCE_DATA (0xFFFF << 16) /* 16:31 lmsw source */ 94.182 -#define REG_EAX (0 << 8) 94.183 -#define REG_ECX (1 << 8) 94.184 -#define REG_EDX (2 << 8) 94.185 -#define REG_EBX (3 << 8) 94.186 -#define REG_ESP (4 << 8) 94.187 -#define REG_EBP (5 << 8) 94.188 -#define REG_ESI (6 << 8) 94.189 -#define REG_EDI (7 << 8) 94.190 -#define REG_R8 (8 << 8) 94.191 -#define REG_R9 (9 << 8) 94.192 -#define REG_R10 (10 << 8) 94.193 -#define REG_R11 (11 << 8) 94.194 -#define REG_R12 (12 << 8) 94.195 -#define REG_R13 (13 << 8) 94.196 -#define REG_R14 (14 << 8) 94.197 -#define REG_R15 (15 << 8) 94.198 +#define LMSW_SOURCE_DATA (0xFFFF << 16) /* 16:31 lmsw source */ 94.199 +#define REG_EAX (0 << 8) 94.200 +#define REG_ECX (1 << 8) 94.201 +#define REG_EDX (2 << 8) 94.202 +#define REG_EBX (3 << 8) 94.203 +#define REG_ESP (4 << 8) 94.204 +#define REG_EBP (5 << 8) 94.205 +#define REG_ESI (6 << 8) 94.206 +#define REG_EDI (7 << 8) 94.207 +#define REG_R8 (8 << 8) 94.208 +#define REG_R9 (9 << 8) 94.209 +#define REG_R10 (10 << 8) 94.210 +#define REG_R11 (11 << 8) 94.211 +#define REG_R12 (12 << 8) 94.212 +#define REG_R13 (13 << 8) 94.213 +#define REG_R14 (14 << 8) 94.214 +#define REG_R15 (15 << 8) 94.215 94.216 /* 94.217 * Exit Qualifications for MOV for Debug Register Access 94.218 */ 94.219 #define DEBUG_REG_ACCESS_NUM 0x7 /* 2:0, number of debug register */ 94.220 #define DEBUG_REG_ACCESS_TYPE 0x10 /* 4, direction of access */ 94.221 -#define TYPE_MOV_TO_DR (0 << 4) 94.222 +#define TYPE_MOV_TO_DR (0 << 4) 94.223 #define TYPE_MOV_FROM_DR (1 << 4) 94.224 #define DEBUG_REG_ACCESS_REG 0xf00 /* 11:8, general purpose register */ 94.225 - 94.226 + 94.227 /* These bits in the CR4 are owned by the host */ 94.228 #if CONFIG_PAGING_LEVELS >= 3 94.229 #define VMX_CR4_HOST_MASK (X86_CR4_VMXE | X86_CR4_PAE) 94.230 @@ -212,7 +226,7 @@ static inline void __vmptrld(u64 addr) 94.231 /* CF==1 or ZF==1 --> crash (ud2) */ 94.232 "ja 1f ; ud2 ; 1:\n" 94.233 : 94.234 - : "a" (&addr) 94.235 + : "a" (&addr) 94.236 : "memory"); 94.237 } 94.238 94.239 @@ -221,7 +235,7 @@ static inline void __vmptrst(u64 addr) 94.240 __asm__ __volatile__ ( VMPTRST_OPCODE 94.241 MODRM_EAX_07 94.242 : 94.243 - : "a" (&addr) 94.244 + : "a" (&addr) 94.245 : "memory"); 94.246 } 94.247 94.248 @@ -232,7 +246,7 @@ static inline void __vmpclear(u64 addr) 94.249 /* CF==1 or ZF==1 --> crash (ud2) */ 94.250 "ja 1f ; ud2 ; 1:\n" 94.251 : 94.252 - : "a" (&addr) 94.253 + : "a" (&addr) 94.254 : "memory"); 94.255 } 94.256 94.257 @@ -252,7 +266,7 @@ static always_inline int ___vmread( 94.258 : "0" (0), "a" (field) 94.259 : "memory"); 94.260 94.261 - switch (size) { 94.262 + switch ( size ) { 94.263 case 1: 94.264 *((u8 *) (ptr)) = ecx; 94.265 break; 94.266 @@ -274,43 +288,45 @@ static always_inline int ___vmread( 94.267 } 94.268 94.269 94.270 -static always_inline void __vmwrite_vcpu(struct vcpu *v, unsigned long field, unsigned long value) 94.271 +static always_inline void __vmwrite_vcpu( 94.272 + struct vcpu *v, unsigned long field, unsigned long value) 94.273 { 94.274 - switch(field) { 94.275 + switch ( field ) { 94.276 case CR0_READ_SHADOW: 94.277 - v->arch.hvm_vmx.cpu_shadow_cr0 = value; 94.278 - break; 94.279 + v->arch.hvm_vmx.cpu_shadow_cr0 = value; 94.280 + break; 94.281 case GUEST_CR0: 94.282 - v->arch.hvm_vmx.cpu_cr0 = value; 94.283 - break; 94.284 + v->arch.hvm_vmx.cpu_cr0 = value; 94.285 + break; 94.286 case CPU_BASED_VM_EXEC_CONTROL: 94.287 - v->arch.hvm_vmx.cpu_based_exec_control = value; 94.288 - break; 94.289 + v->arch.hvm_vmx.cpu_based_exec_control = value; 94.290 + break; 94.291 default: 94.292 - printk("__vmwrite_cpu: invalid field %lx\n", field); 94.293 - break; 94.294 + printk("__vmwrite_cpu: invalid field %lx\n", field); 94.295 + break; 94.296 } 94.297 } 94.298 94.299 -static always_inline void __vmread_vcpu(struct vcpu *v, unsigned long field, unsigned long *value) 94.300 +static always_inline void __vmread_vcpu( 94.301 + struct vcpu *v, unsigned long field, unsigned long *value) 94.302 { 94.303 - switch(field) { 94.304 + switch ( field ) { 94.305 case CR0_READ_SHADOW: 94.306 - *value = v->arch.hvm_vmx.cpu_shadow_cr0; 94.307 - break; 94.308 + *value = v->arch.hvm_vmx.cpu_shadow_cr0; 94.309 + break; 94.310 case GUEST_CR0: 94.311 - *value = v->arch.hvm_vmx.cpu_cr0; 94.312 - break; 94.313 + *value = v->arch.hvm_vmx.cpu_cr0; 94.314 + break; 94.315 case CPU_BASED_VM_EXEC_CONTROL: 94.316 - *value = v->arch.hvm_vmx.cpu_based_exec_control; 94.317 - break; 94.318 + *value = v->arch.hvm_vmx.cpu_based_exec_control; 94.319 + break; 94.320 default: 94.321 - printk("__vmread_cpu: invalid field %lx\n", field); 94.322 - break; 94.323 + printk("__vmread_cpu: invalid field %lx\n", field); 94.324 + break; 94.325 } 94.326 } 94.327 94.328 -static inline int __vmwrite (unsigned long field, unsigned long value) 94.329 +static inline int __vmwrite(unsigned long field, unsigned long value) 94.330 { 94.331 struct vcpu *v = current; 94.332 int rc; 94.333 @@ -323,12 +339,12 @@ static inline int __vmwrite (unsigned lo 94.334 : "0" (0), "a" (field) , "c" (value) 94.335 : "memory"); 94.336 94.337 - switch(field) { 94.338 + switch ( field ) { 94.339 case CR0_READ_SHADOW: 94.340 case GUEST_CR0: 94.341 case CPU_BASED_VM_EXEC_CONTROL: 94.342 - __vmwrite_vcpu(v, field, value); 94.343 - break; 94.344 + __vmwrite_vcpu(v, field, value); 94.345 + break; 94.346 } 94.347 94.348 return rc; 94.349 @@ -336,31 +352,31 @@ static inline int __vmwrite (unsigned lo 94.350 94.351 static inline int __vm_set_bit(unsigned long field, unsigned long mask) 94.352 { 94.353 - unsigned long tmp; 94.354 - int err = 0; 94.355 + unsigned long tmp; 94.356 + int err = 0; 94.357 94.358 - err |= __vmread(field, &tmp); 94.359 - tmp |= mask; 94.360 - err |= __vmwrite(field, tmp); 94.361 + err |= __vmread(field, &tmp); 94.362 + tmp |= mask; 94.363 + err |= __vmwrite(field, tmp); 94.364 94.365 - return err; 94.366 + return err; 94.367 } 94.368 94.369 static inline int __vm_clear_bit(unsigned long field, unsigned long mask) 94.370 { 94.371 - unsigned long tmp; 94.372 - int err = 0; 94.373 + unsigned long tmp; 94.374 + int err = 0; 94.375 94.376 - err |= __vmread(field, &tmp); 94.377 - tmp &= ~mask; 94.378 - err |= __vmwrite(field, tmp); 94.379 + err |= __vmread(field, &tmp); 94.380 + tmp &= ~mask; 94.381 + err |= __vmwrite(field, tmp); 94.382 94.383 - return err; 94.384 + return err; 94.385 } 94.386 94.387 static inline void __vmxoff (void) 94.388 { 94.389 - __asm__ __volatile__ ( VMXOFF_OPCODE 94.390 + __asm__ __volatile__ ( VMXOFF_OPCODE 94.391 ::: "memory"); 94.392 } 94.393 94.394 @@ -373,7 +389,7 @@ static inline int __vmxon (u64 addr) 94.395 /* CF==1 or ZF==1 --> rc = -1 */ 94.396 "setna %b0 ; neg %0" 94.397 : "=q" (rc) 94.398 - : "0" (0), "a" (&addr) 94.399 + : "0" (0), "a" (&addr) 94.400 : "memory"); 94.401 94.402 return rc; 94.403 @@ -390,9 +406,9 @@ static inline void vmx_stts(void) 94.404 return; 94.405 94.406 /* 94.407 - * If the guest does not have TS enabled then we must cause and handle an 94.408 - * exception on first use of the FPU. If the guest *does* have TS enabled 94.409 - * then this is not necessary: no FPU activity can occur until the guest 94.410 + * If the guest does not have TS enabled then we must cause and handle an 94.411 + * exception on first use of the FPU. If the guest *does* have TS enabled 94.412 + * then this is not necessary: no FPU activity can occur until the guest 94.413 * clears CR0.TS, and we will initialise the FPU when that happens. 94.414 */ 94.415 __vmread_vcpu(v, CR0_READ_SHADOW, &cr0); 94.416 @@ -421,66 +437,64 @@ static inline int vmx_pgbit_test(struct 94.417 return (cr0 & X86_CR0_PG); 94.418 } 94.419 94.420 -static inline int __vmx_inject_exception(struct vcpu *v, int trap, int type, 94.421 +static inline void __vmx_inject_exception(struct vcpu *v, int trap, int type, 94.422 int error_code, int ilen) 94.423 { 94.424 unsigned long intr_fields; 94.425 94.426 /* Reflect it back into the guest */ 94.427 intr_fields = (INTR_INFO_VALID_MASK | type | trap); 94.428 - if (error_code != VMX_DELIVER_NO_ERROR_CODE) { 94.429 + if ( error_code != VMX_DELIVER_NO_ERROR_CODE ) { 94.430 __vmwrite(VM_ENTRY_EXCEPTION_ERROR_CODE, error_code); 94.431 intr_fields |= INTR_INFO_DELIVER_CODE_MASK; 94.432 } 94.433 94.434 - if(ilen) 94.435 + if ( ilen ) 94.436 __vmwrite(VM_ENTRY_INSTRUCTION_LEN, ilen); 94.437 94.438 __vmwrite(VM_ENTRY_INTR_INFO_FIELD, intr_fields); 94.439 - return 0; 94.440 } 94.441 94.442 -static inline int vmx_inject_hw_exception(struct vcpu *v, int trap, int error_code) 94.443 +static inline void vmx_inject_hw_exception( 94.444 + struct vcpu *v, int trap, int error_code) 94.445 { 94.446 v->arch.hvm_vmx.vector_injected = 1; 94.447 - return __vmx_inject_exception(v, trap, INTR_TYPE_HW_EXCEPTION, 94.448 - error_code, 0); 94.449 + __vmx_inject_exception(v, trap, INTR_TYPE_HW_EXCEPTION, error_code, 0); 94.450 } 94.451 94.452 -static inline int vmx_inject_sw_exception(struct vcpu *v, int trap, int instruction_len) { 94.453 - v->arch.hvm_vmx.vector_injected=1; 94.454 - return __vmx_inject_exception(v, trap, INTR_TYPE_SW_EXCEPTION, 94.455 - VMX_DELIVER_NO_ERROR_CODE, 94.456 - instruction_len); 94.457 +static inline void vmx_inject_sw_exception( 94.458 + struct vcpu *v, int trap, int instruction_len) 94.459 +{ 94.460 + v->arch.hvm_vmx.vector_injected = 1; 94.461 + __vmx_inject_exception(v, trap, INTR_TYPE_SW_EXCEPTION, 94.462 + VMX_DELIVER_NO_ERROR_CODE, 94.463 + instruction_len); 94.464 } 94.465 94.466 -static inline int vmx_inject_extint(struct vcpu *v, int trap, int error_code) 94.467 +static inline void vmx_inject_extint(struct vcpu *v, int trap, int error_code) 94.468 { 94.469 __vmx_inject_exception(v, trap, INTR_TYPE_EXT_INTR, error_code, 0); 94.470 __vmwrite(GUEST_INTERRUPTIBILITY_INFO, 0); 94.471 - 94.472 - return 0; 94.473 } 94.474 94.475 -static inline int vmx_reflect_exception(struct vcpu *v) 94.476 +static inline void vmx_reflect_exception(struct vcpu *v) 94.477 { 94.478 int error_code, intr_info, vector; 94.479 94.480 __vmread(VM_EXIT_INTR_INFO, &intr_info); 94.481 vector = intr_info & 0xff; 94.482 - if (intr_info & INTR_INFO_DELIVER_CODE_MASK) 94.483 + if ( intr_info & INTR_INFO_DELIVER_CODE_MASK ) 94.484 __vmread(VM_EXIT_INTR_ERROR_CODE, &error_code); 94.485 else 94.486 error_code = VMX_DELIVER_NO_ERROR_CODE; 94.487 94.488 #ifndef NDEBUG 94.489 { 94.490 - unsigned long eip; 94.491 + unsigned long rip; 94.492 94.493 - __vmread(GUEST_RIP, &eip); 94.494 - HVM_DBG_LOG(DBG_LEVEL_1, 94.495 - "vmx_reflect_exception: eip = %lx, error_code = %x", 94.496 - eip, error_code); 94.497 + __vmread(GUEST_RIP, &rip); 94.498 + HVM_DBG_LOG(DBG_LEVEL_1, "rip = %lx, error_code = %x", 94.499 + rip, error_code); 94.500 } 94.501 #endif /* NDEBUG */ 94.502 94.503 @@ -489,15 +503,14 @@ static inline int vmx_reflect_exception( 94.504 2.8.3, SW_EXCEPTION should be used for #BP and #OV, and 94.505 HW_EXCPEPTION used for everything else. The main difference 94.506 appears to be that for SW_EXCEPTION, the EIP/RIP is incremented 94.507 - by VM_ENTER_INSTRUCTION_LEN bytes, whereas for HW_EXCEPTION, 94.508 + by VM_ENTER_INSTRUCTION_LEN bytes, whereas for HW_EXCEPTION, 94.509 it is not. */ 94.510 - if((intr_info & INTR_INFO_INTR_TYPE_MASK) == INTR_TYPE_SW_EXCEPTION) { 94.511 - int ilen; 94.512 - __vmread(VM_EXIT_INSTRUCTION_LEN, &ilen); 94.513 - vmx_inject_sw_exception(v, vector, ilen); 94.514 + if ( (intr_info & INTR_INFO_INTR_TYPE_MASK) == INTR_TYPE_SW_EXCEPTION ) { 94.515 + int ilen; 94.516 + __vmread(VM_EXIT_INSTRUCTION_LEN, &ilen); 94.517 + vmx_inject_sw_exception(v, vector, ilen); 94.518 } else 94.519 - vmx_inject_hw_exception(v, vector, error_code); 94.520 - return 0; 94.521 + vmx_inject_hw_exception(v, vector, error_code); 94.522 } 94.523 94.524 #endif /* __ASM_X86_HVM_VMX_VMX_H__ */
95.1 --- a/xen/include/public/hvm/ioreq.h Tue Aug 08 19:07:32 2006 -0500 95.2 +++ b/xen/include/public/hvm/ioreq.h Wed Aug 09 18:04:20 2006 +0100 95.3 @@ -69,7 +69,6 @@ struct vcpu_iodata { 95.4 struct ioreq vp_ioreq; 95.5 /* Event channel port */ 95.6 unsigned int vp_eport; /* VMX vcpu uses this to notify DM */ 95.7 - unsigned int dm_eport; /* DM uses this to notify VMX vcpu */ 95.8 }; 95.9 typedef struct vcpu_iodata vcpu_iodata_t; 95.10 95.11 @@ -79,6 +78,14 @@ struct shared_iopage { 95.12 }; 95.13 typedef struct shared_iopage shared_iopage_t; 95.14 95.15 +#define IOREQ_BUFFER_SLOT_NUM 80 95.16 +struct buffered_iopage { 95.17 + unsigned long read_pointer; 95.18 + unsigned long write_pointer; 95.19 + ioreq_t ioreq[IOREQ_BUFFER_SLOT_NUM]; 95.20 +}; /* sizeof this structure must be in one page */ 95.21 +typedef struct buffered_iopage buffered_iopage_t; 95.22 + 95.23 #endif /* _IOREQ_H_ */ 95.24 95.25 /*
96.1 --- a/xen/include/xen/config.h Tue Aug 08 19:07:32 2006 -0500 96.2 +++ b/xen/include/xen/config.h Wed Aug 09 18:04:20 2006 +0100 96.3 @@ -50,6 +50,5 @@ 96.4 #endif /* !__ASSEMBLY__ */ 96.5 96.6 #define fastcall 96.7 -#define __read_mostly 96.8 96.9 #endif /* __XEN_CONFIG_H__ */
97.1 --- a/xen/include/xen/event.h Tue Aug 08 19:07:32 2006 -0500 97.2 +++ b/xen/include/xen/event.h Wed Aug 09 18:04:20 2006 +0100 97.3 @@ -12,6 +12,7 @@ 97.4 #include <xen/config.h> 97.5 #include <xen/sched.h> 97.6 #include <xen/smp.h> 97.7 +#include <xen/softirq.h> 97.8 #include <asm/bitops.h> 97.9 #include <asm/event.h> 97.10
98.1 --- a/xen/include/xen/multicall.h Tue Aug 08 19:07:32 2006 -0500 98.2 +++ b/xen/include/xen/multicall.h Wed Aug 09 18:04:20 2006 +0100 98.3 @@ -5,6 +5,7 @@ 98.4 #ifndef __XEN_MULTICALL_H__ 98.5 #define __XEN_MULTICALL_H__ 98.6 98.7 +#include <xen/percpu.h> 98.8 #include <asm/multicall.h> 98.9 98.10 #define _MCSF_in_multicall 0 98.11 @@ -14,8 +15,8 @@ 98.12 struct mc_state { 98.13 unsigned long flags; 98.14 struct multicall_entry call; 98.15 -} __cacheline_aligned; 98.16 +}; 98.17 98.18 -extern struct mc_state mc_state[NR_CPUS]; 98.19 +DECLARE_PER_CPU(struct mc_state, mc_state); 98.20 98.21 #endif /* __XEN_MULTICALL_H__ */
99.1 --- a/xen/include/xen/percpu.h Tue Aug 08 19:07:32 2006 -0500 99.2 +++ b/xen/include/xen/percpu.h Wed Aug 09 18:04:20 2006 +0100 99.3 @@ -2,7 +2,6 @@ 99.4 #define __XEN_PERCPU_H__ 99.5 99.6 #include <xen/config.h> 99.7 -#include <xen/smp.h> 99.8 #include <asm/percpu.h> 99.9 99.10 /* Preferred on Xen. Also see arch-defined per_cpu(). */
100.1 --- a/xen/include/xen/sched-if.h Tue Aug 08 19:07:32 2006 -0500 100.2 +++ b/xen/include/xen/sched-if.h Wed Aug 09 18:04:20 2006 +0100 100.3 @@ -8,6 +8,8 @@ 100.4 #ifndef __XEN_SCHED_IF_H__ 100.5 #define __XEN_SCHED_IF_H__ 100.6 100.7 +#include <xen/percpu.h> 100.8 + 100.9 struct schedule_data { 100.10 spinlock_t schedule_lock; /* spinlock protecting curr */ 100.11 struct vcpu *curr; /* current task */ 100.12 @@ -17,7 +19,7 @@ struct schedule_data { 100.13 unsigned long tick; /* current periodic 'tick' */ 100.14 } __cacheline_aligned; 100.15 100.16 -extern struct schedule_data schedule_data[]; 100.17 +DECLARE_PER_CPU(struct schedule_data, schedule_data); 100.18 100.19 static inline void vcpu_schedule_lock(struct vcpu *v) 100.20 { 100.21 @@ -26,10 +28,10 @@ static inline void vcpu_schedule_lock(st 100.22 for ( ; ; ) 100.23 { 100.24 cpu = v->processor; 100.25 - spin_lock(&schedule_data[cpu].schedule_lock); 100.26 + spin_lock(&per_cpu(schedule_data, cpu).schedule_lock); 100.27 if ( likely(v->processor == cpu) ) 100.28 break; 100.29 - spin_unlock(&schedule_data[cpu].schedule_lock); 100.30 + spin_unlock(&per_cpu(schedule_data, cpu).schedule_lock); 100.31 } 100.32 } 100.33 100.34 @@ -40,7 +42,7 @@ static inline void vcpu_schedule_lock(st 100.35 100.36 static inline void vcpu_schedule_unlock(struct vcpu *v) 100.37 { 100.38 - spin_unlock(&schedule_data[v->processor].schedule_lock); 100.39 + spin_unlock(&per_cpu(schedule_data, v->processor).schedule_lock); 100.40 } 100.41 100.42 #define vcpu_schedule_unlock_irq(v) \