ia64/xen-unstable

changeset 11064: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(&current->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(&current->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(&regs);
  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, &regs)) {
  62.222 +            if ( !vmx_do_page_fault(va, &regs) ) {
  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(&regs);
  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(&regs);
  62.241 +        domain_crash_synchronous();
  62.242          break;
  62.243      case EXIT_REASON_CPUID:
  62.244          vmx_vmexit_do_cpuid(&regs);
  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(&regs);
  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, &regs))
  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, &regs) )
  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(&regs);
  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(&regs);
  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(&regs);       /* 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) \