ia64/xen-unstable

changeset 8527:8af1199488d3

Merged.
author emellor@leeni.uk.xensource.com
date Mon Jan 09 11:22:17 2006 +0000 (2006-01-09)
parents 25e3c8668f1f 299d6ff8fdb2
children 0ba3b9d60da6 970cf1fff5f2 a51fcb5de470
files tools/libxc/xc_linux_save.c tools/python/xen/lowlevel/xc/xc.c xen/common/grant_table.c
line diff
     1.1 --- a/.hgignore	Mon Jan 09 11:19:55 2006 +0000
     1.2 +++ b/.hgignore	Mon Jan 09 11:22:17 2006 +0000
     1.3 @@ -181,6 +181,7 @@
     1.4  ^xen/TAGS$
     1.5  ^xen/arch/x86/asm-offsets\.s$
     1.6  ^xen/arch/x86/boot/mkelf32$
     1.7 +^xen/arch/x86/xen\.lds$
     1.8  ^xen/ddb/.*$
     1.9  ^xen/include/asm$
    1.10  ^xen/include/asm-.*/asm-offsets\.h$
     2.1 --- a/linux-2.6-xen-sparse/arch/ia64/xen/drivers/xenia64_init.c	Mon Jan 09 11:19:55 2006 +0000
     2.2 +++ b/linux-2.6-xen-sparse/arch/ia64/xen/drivers/xenia64_init.c	Mon Jan 09 11:22:17 2006 +0000
     2.3 @@ -25,8 +25,9 @@ int xen_init(void)
     2.4  
     2.5  	xen_start_info = __va(s->arch.start_info_pfn << PAGE_SHIFT);
     2.6  	xen_start_info->flags = s->arch.flags;
     2.7 -	printk("Running on Xen! start_info_pfn=0x%lx lags=0x%x\n",
     2.8 -		s->arch.start_info_pfn, xen_start_info->flags);
     2.9 +	printk("Running on Xen! start_info_pfn=0x%lx nr_pages=%d flags=0x%x\n",
    2.10 +		s->arch.start_info_pfn, xen_start_info->nr_pages,
    2.11 +		xen_start_info->flags);
    2.12  
    2.13  	evtchn_init();
    2.14  	initialized = 1;
     3.1 --- a/linux-2.6-xen-sparse/arch/xen/Makefile	Mon Jan 09 11:19:55 2006 +0000
     3.2 +++ b/linux-2.6-xen-sparse/arch/xen/Makefile	Mon Jan 09 11:22:17 2006 +0000
     3.3 @@ -77,8 +77,6 @@ install kernel_install:
     3.4  	install -m0664 .config $(INSTALL_PATH)/boot/config-$(XINSTALL_NAME)$(INSTALL_SUFFIX)
     3.5  	install -m0664 System.map $(INSTALL_PATH)/boot/System.map-$(XINSTALL_NAME)$(INSTALL_SUFFIX)
     3.6  	ln -f -s vmlinuz-$(XINSTALL_NAME)$(INSTALL_SUFFIX) $(INSTALL_PATH)/boot/vmlinuz-$(VERSION).$(PATCHLEVEL)$(XENGUEST)$(INSTALL_SUFFIX)
     3.7 -	mkdir -p $(INSTALL_PATH)/usr/include/xen/linux
     3.8 -	install -m0644 $(srctree)/include/asm-xen/linux-public/*.h $(INSTALL_PATH)/usr/include/xen/linux
     3.9  
    3.10  archclean:
    3.11  	@if [ -e arch/xen/arch ]; then $(MAKE) $(clean)=arch/xen/arch; fi;
     4.1 --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/acpi/boot.c	Mon Jan 09 11:19:55 2006 +0000
     4.2 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/acpi/boot.c	Mon Jan 09 11:22:17 2006 +0000
     4.3 @@ -40,8 +40,6 @@
     4.4  #include <asm/fixmap.h>
     4.5  #endif
     4.6  
     4.7 -void (*pm_power_off)(void) = NULL;
     4.8 -
     4.9  #ifdef	CONFIG_X86_64
    4.10  
    4.11  static inline void  acpi_madt_oem_check(char *oem_id, char *oem_table_id) { }
     5.1 --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/cpu/mtrr/main.c	Mon Jan 09 11:19:55 2006 +0000
     5.2 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/cpu/mtrr/main.c	Mon Jan 09 11:22:17 2006 +0000
     5.3 @@ -67,8 +67,11 @@ int mtrr_add_page(unsigned long base, un
     5.4  	op.u.add_memtype.pfn     = base;
     5.5  	op.u.add_memtype.nr_pfns = size;
     5.6  	op.u.add_memtype.type    = type;
     5.7 -	if ((error = HYPERVISOR_dom0_op(&op)))
     5.8 +	error = HYPERVISOR_dom0_op(&op);
     5.9 +	if (error) {
    5.10 +		BUG_ON(error > 0);
    5.11  		return error;
    5.12 +	}
    5.13  
    5.14  	if (increment)
    5.15  		++usage_table[op.u.add_memtype.reg];
    5.16 @@ -121,8 +124,12 @@ int mtrr_del_page(int reg, unsigned long
    5.17  	if (--usage_table[reg] < 1) {
    5.18  		op.cmd = DOM0_DEL_MEMTYPE;
    5.19  		op.u.del_memtype.handle = 0;
    5.20 -		op.u.add_memtype.reg    = reg;
    5.21 -		(void)HYPERVISOR_dom0_op(&op);
    5.22 +		op.u.del_memtype.reg    = reg;
    5.23 +		error = HYPERVISOR_dom0_op(&op);
    5.24 +		if (error) {
    5.25 +			BUG_ON(error > 0);
    5.26 +			goto out;
    5.27 +		}
    5.28  	}
    5.29  	error = reg;
    5.30   out:
     6.1 --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/i386_ksyms.c	Mon Jan 09 11:19:55 2006 +0000
     6.2 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/i386_ksyms.c	Mon Jan 09 11:22:17 2006 +0000
     6.3 @@ -76,9 +76,7 @@ EXPORT_SYMBOL(ioremap_nocache);
     6.4  EXPORT_SYMBOL(iounmap);
     6.5  EXPORT_SYMBOL(kernel_thread);
     6.6  EXPORT_SYMBOL(pm_idle);
     6.7 -#ifdef CONFIG_ACPI_BOOT
     6.8  EXPORT_SYMBOL(pm_power_off);
     6.9 -#endif
    6.10  EXPORT_SYMBOL(get_cmos_time);
    6.11  EXPORT_SYMBOL(cpu_khz);
    6.12  EXPORT_SYMBOL(apm_info);
     7.1 --- a/linux-2.6-xen-sparse/arch/xen/kernel/gnttab.c	Mon Jan 09 11:19:55 2006 +0000
     7.2 +++ b/linux-2.6-xen-sparse/arch/xen/kernel/gnttab.c	Mon Jan 09 11:22:17 2006 +0000
     7.3 @@ -389,6 +389,30 @@ grant_write(struct file *file, const cha
     7.4  	return -ENOSYS;
     7.5  }
     7.6  
     7.7 +static int __init
     7.8 +gnttab_proc_init(void)
     7.9 +{
    7.10 +	/*
    7.11 +	 *  /proc/xen/grant : used by libxc to access grant tables
    7.12 +	 */
    7.13 +	if ((grant_pde = create_xen_proc_entry("grant", 0600)) == NULL) {
    7.14 +		WPRINTK("Unable to create grant xen proc entry\n");
    7.15 +		return -1;
    7.16 +	}
    7.17 +
    7.18 +	grant_file_ops.read   = grant_pde->proc_fops->read;
    7.19 +	grant_file_ops.write  = grant_pde->proc_fops->write;
    7.20 +
    7.21 +	grant_pde->proc_fops  = &grant_file_ops;
    7.22 +
    7.23 +	grant_pde->read_proc  = &grant_read;
    7.24 +	grant_pde->write_proc = &grant_write;
    7.25 +
    7.26 +	return 0;
    7.27 +}
    7.28 +
    7.29 +device_initcall(gnttab_proc_init);
    7.30 +
    7.31  #endif /* CONFIG_PROC_FS */
    7.32  
    7.33  int
    7.34 @@ -446,29 +470,11 @@ gnttab_init(void)
    7.35  	gnttab_free_count = NR_GRANT_ENTRIES - NR_RESERVED_ENTRIES;
    7.36  	gnttab_free_head  = NR_RESERVED_ENTRIES;
    7.37  
    7.38 -#ifdef CONFIG_PROC_FS
    7.39 -	/*
    7.40 -	 *  /proc/xen/grant : used by libxc to access grant tables
    7.41 -	 */
    7.42 -	if ((grant_pde = create_xen_proc_entry("grant", 0600)) == NULL) {
    7.43 -		WPRINTK("Unable to create grant xen proc entry\n");
    7.44 -		return -1;
    7.45 -	}
    7.46 -
    7.47 -	grant_file_ops.read   = grant_pde->proc_fops->read;
    7.48 -	grant_file_ops.write  = grant_pde->proc_fops->write;
    7.49 -
    7.50 -	grant_pde->proc_fops  = &grant_file_ops;
    7.51 -
    7.52 -	grant_pde->read_proc  = &grant_read;
    7.53 -	grant_pde->write_proc = &grant_write;
    7.54 -#endif
    7.55 -
    7.56  	printk("Grant table initialized\n");
    7.57  	return 0;
    7.58  }
    7.59  
    7.60 -__initcall(gnttab_init);
    7.61 +core_initcall(gnttab_init);
    7.62  
    7.63  /*
    7.64   * Local variables:
     8.1 --- a/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c	Mon Jan 09 11:19:55 2006 +0000
     8.2 +++ b/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c	Mon Jan 09 11:22:17 2006 +0000
     8.3 @@ -17,6 +17,13 @@
     8.4  #include <linux/kthread.h>
     8.5  #include <asm-xen/xencons.h>
     8.6  
     8.7 +#if defined(__i386__) || defined(__x86_64__)
     8.8 +/*
     8.9 + * Power off function, if any
    8.10 + */
    8.11 +void (*pm_power_off)(void);
    8.12 +#endif
    8.13 +
    8.14  #define SHUTDOWN_INVALID  -1
    8.15  #define SHUTDOWN_POWEROFF  0
    8.16  #define SHUTDOWN_REBOOT    1
     9.1 --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/x8664_ksyms.c	Mon Jan 09 11:19:55 2006 +0000
     9.2 +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/x8664_ksyms.c	Mon Jan 09 11:22:17 2006 +0000
     9.3 @@ -59,9 +59,7 @@ EXPORT_SYMBOL(disable_irq_nosync);
     9.4  EXPORT_SYMBOL(probe_irq_mask);
     9.5  EXPORT_SYMBOL(kernel_thread);
     9.6  EXPORT_SYMBOL(pm_idle);
     9.7 -#ifdef CONFIG_ACPI_BOOT
     9.8  EXPORT_SYMBOL(pm_power_off);
     9.9 -#endif
    9.10  EXPORT_SYMBOL(get_cmos_time);
    9.11  
    9.12  EXPORT_SYMBOL(__down_failed);
    10.1 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c	Mon Jan 09 11:19:55 2006 +0000
    10.2 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c	Mon Jan 09 11:22:17 2006 +0000
    10.3 @@ -540,6 +540,9 @@ static int __init blkif_init(void)
    10.4  	pending_vaddrs        = kmalloc(sizeof(pending_vaddrs[0]) *
    10.5  					mmap_pages, GFP_KERNEL);
    10.6  	if (!pending_reqs || !pending_grant_handles || !pending_vaddrs) {
    10.7 +		kfree(pending_reqs);
    10.8 +		kfree(pending_grant_handles);
    10.9 +		kfree(pending_vaddrs);
   10.10  		printk("%s: out of memory\n", __FUNCTION__);
   10.11  		return -1;
   10.12  	}
    11.1 --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c	Mon Jan 09 11:19:55 2006 +0000
    11.2 +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c	Mon Jan 09 11:22:17 2006 +0000
    11.3 @@ -331,7 +331,12 @@ static void connect(struct blkfront_info
    11.4  		return;
    11.5  	}
    11.6  
    11.7 -        xlvbd_add(sectors, info->vdevice, binfo, sector_size, info);
    11.8 +	err = xlvbd_add(sectors, info->vdevice, binfo, sector_size, info);
    11.9 +	if (err) {
   11.10 +		xenbus_dev_fatal(info->xbdev, err, "xlvbd_add at %s",
   11.11 +		                 info->xbdev->otherend);
   11.12 +		return;
   11.13 +	}
   11.14  
   11.15  	(void)xenbus_switch_state(info->xbdev, NULL, XenbusStateConnected); 
   11.16  
    12.1 --- a/linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c	Mon Jan 09 11:19:55 2006 +0000
    12.2 +++ b/linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c	Mon Jan 09 11:22:17 2006 +0000
    12.3 @@ -208,7 +208,7 @@ static struct page *blktap_nopage(struct
    12.4  }
    12.5  
    12.6  struct vm_operations_struct blktap_vm_ops = {
    12.7 -	nopage:   blktap_nopage,
    12.8 +	.nopage = blktap_nopage,
    12.9  };
   12.10  
   12.11  /******************************************************************
   12.12 @@ -225,7 +225,7 @@ static int blktap_open(struct inode *ino
   12.13  	/* Allocate the fe ring. */
   12.14  	sring = (blkif_sring_t *)get_zeroed_page(GFP_KERNEL);
   12.15  	if (sring == NULL)
   12.16 -		goto fail_nomem;
   12.17 +		return -ENOMEM;
   12.18  
   12.19  	SetPageReserved(virt_to_page(sring));
   12.20      
   12.21 @@ -233,9 +233,6 @@ static int blktap_open(struct inode *ino
   12.22  	FRONT_RING_INIT(&blktap_ufe_ring, sring, PAGE_SIZE);
   12.23  
   12.24  	return 0;
   12.25 -
   12.26 - fail_nomem:
   12.27 -	return -ENOMEM;
   12.28  }
   12.29  
   12.30  static int blktap_release(struct inode *inode, struct file *filp)
   12.31 @@ -391,12 +388,12 @@ void blktap_kick_user(void)
   12.32  }
   12.33  
   12.34  static struct file_operations blktap_fops = {
   12.35 -	owner:    THIS_MODULE,
   12.36 -	poll:     blktap_poll,
   12.37 -	ioctl:    blktap_ioctl,
   12.38 -	open:     blktap_open,
   12.39 -	release:  blktap_release,
   12.40 -	mmap:     blktap_mmap,
   12.41 +	.owner   = THIS_MODULE,
   12.42 +	.poll    = blktap_poll,
   12.43 +	.ioctl   = blktap_ioctl,
   12.44 +	.open    = blktap_open,
   12.45 +	.release = blktap_release,
   12.46 +	.mmap    = blktap_mmap,
   12.47  };
   12.48  
   12.49  
    13.1 --- a/linux-2.6-xen-sparse/drivers/xen/console/console.c	Mon Jan 09 11:19:55 2006 +0000
    13.2 +++ b/linux-2.6-xen-sparse/drivers/xen/console/console.c	Mon Jan 09 11:22:17 2006 +0000
    13.3 @@ -314,39 +314,31 @@ static void __xencons_tx_flush(void)
    13.4  {
    13.5  	int sent, sz, work_done = 0;
    13.6  
    13.7 -	if (xen_start_info->flags & SIF_INITDOMAIN) {
    13.8 -		if (x_char) {
    13.9 +	if (x_char) {
   13.10 +		if (xen_start_info->flags & SIF_INITDOMAIN)
   13.11  			kcons_write_dom0(NULL, &x_char, 1);
   13.12 -			x_char = 0;
   13.13 -			work_done = 1;
   13.14 -		}
   13.15 +		else
   13.16 +			while (x_char)
   13.17 +				if (xencons_ring_send(&x_char, 1) == 1)
   13.18 +					break;
   13.19 +		x_char = 0;
   13.20 +		work_done = 1;
   13.21 +	}
   13.22  
   13.23 -		while (wc != wp) {
   13.24 -			sz = wp - wc;
   13.25 -			if (sz > (wbuf_size - WBUF_MASK(wc)))
   13.26 -				sz = wbuf_size - WBUF_MASK(wc);
   13.27 +	while (wc != wp) {
   13.28 +		sz = wp - wc;
   13.29 +		if (sz > (wbuf_size - WBUF_MASK(wc)))
   13.30 +			sz = wbuf_size - WBUF_MASK(wc);
   13.31 +		if (xen_start_info->flags & SIF_INITDOMAIN) {
   13.32  			kcons_write_dom0(NULL, &wbuf[WBUF_MASK(wc)], sz);
   13.33  			wc += sz;
   13.34 -			work_done = 1;
   13.35 -		}
   13.36 -	} else {
   13.37 -		while (x_char) {
   13.38 -			if (xencons_ring_send(&x_char, 1) == 1) {
   13.39 -				x_char = 0;
   13.40 -				work_done = 1;
   13.41 -			}
   13.42 -		}
   13.43 -
   13.44 -		while (wc != wp) {
   13.45 -			sz = wp - wc;
   13.46 -			if (sz > (wbuf_size - WBUF_MASK(wc)))
   13.47 -				sz = wbuf_size - WBUF_MASK(wc);
   13.48 +		} else {
   13.49  			sent = xencons_ring_send(&wbuf[WBUF_MASK(wc)], sz);
   13.50  			if (sent == 0)
   13.51  				break;
   13.52  			wc += sent;
   13.53 -			work_done = 1;
   13.54  		}
   13.55 +		work_done = 1;
   13.56  	}
   13.57  
   13.58  	if (work_done && (xencons_tty != NULL)) {
    14.1 --- a/linux-2.6-xen-sparse/drivers/xen/netback/common.h	Mon Jan 09 11:19:55 2006 +0000
    14.2 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/common.h	Mon Jan 09 11:22:17 2006 +0000
    14.3 @@ -82,7 +82,7 @@ typedef struct netif_st {
    14.4  #define NET_RX_RING_SIZE __RING_SIZE((netif_rx_sring_t *)0, PAGE_SIZE)
    14.5  
    14.6  void netif_creditlimit(netif_t *netif);
    14.7 -int  netif_disconnect(netif_t *netif);
    14.8 +void netif_disconnect(netif_t *netif);
    14.9  
   14.10  netif_t *alloc_netif(domid_t domid, unsigned int handle, u8 be_mac[ETH_ALEN]);
   14.11  void free_netif(netif_t *netif);
    15.1 --- a/linux-2.6-xen-sparse/drivers/xen/netback/interface.c	Mon Jan 09 11:19:55 2006 +0000
    15.2 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/interface.c	Mon Jan 09 11:22:17 2006 +0000
    15.3 @@ -183,7 +183,7 @@ static void unmap_frontend_pages(netif_t
    15.4  int netif_map(netif_t *netif, unsigned long tx_ring_ref,
    15.5  	      unsigned long rx_ring_ref, unsigned int evtchn)
    15.6  {
    15.7 -	int err;
    15.8 +	int err = -ENOMEM;
    15.9  	netif_tx_sring_t *txs;
   15.10  	netif_rx_sring_t *rxs;
   15.11  	evtchn_op_t op = {
   15.12 @@ -196,24 +196,19 @@ int netif_map(netif_t *netif, unsigned l
   15.13  		return 0;
   15.14  
   15.15  	netif->tx_comms_area = alloc_vm_area(PAGE_SIZE);
   15.16 +	if (netif->tx_comms_area == NULL)
   15.17 +		return -ENOMEM;
   15.18  	netif->rx_comms_area = alloc_vm_area(PAGE_SIZE);
   15.19 -	if (netif->tx_comms_area == NULL || netif->rx_comms_area == NULL)
   15.20 -		return -ENOMEM;
   15.21 +	if (netif->rx_comms_area == NULL)
   15.22 +		goto err_rx;
   15.23  
   15.24  	err = map_frontend_pages(netif, tx_ring_ref, rx_ring_ref);
   15.25 -	if (err) {
   15.26 -		free_vm_area(netif->tx_comms_area);
   15.27 -		free_vm_area(netif->rx_comms_area);
   15.28 -		return err;
   15.29 -	}
   15.30 +	if (err)
   15.31 +		goto err_map;
   15.32  
   15.33  	err = HYPERVISOR_event_channel_op(&op);
   15.34 -	if (err) {
   15.35 -		unmap_frontend_pages(netif);
   15.36 -		free_vm_area(netif->tx_comms_area);
   15.37 -		free_vm_area(netif->rx_comms_area);
   15.38 -		return err;
   15.39 -	}
   15.40 +	if (err)
   15.41 +		goto err_hypervisor;
   15.42  
   15.43  	netif->evtchn = op.u.bind_interdomain.local_port;
   15.44  
   15.45 @@ -241,19 +236,22 @@ int netif_map(netif_t *netif, unsigned l
   15.46  	rtnl_unlock();
   15.47  
   15.48  	return 0;
   15.49 +err_hypervisor:
   15.50 +	unmap_frontend_pages(netif);
   15.51 +err_map:
   15.52 +	free_vm_area(netif->rx_comms_area);
   15.53 +err_rx:
   15.54 +	free_vm_area(netif->tx_comms_area);
   15.55 +	return err;
   15.56  }
   15.57  
   15.58  static void free_netif_callback(void *arg)
   15.59  {
   15.60  	netif_t *netif = (netif_t *)arg;
   15.61  
   15.62 -	/* Already disconnected? */
   15.63 -	if (!netif->irq)
   15.64 -		return;
   15.65 -
   15.66 -	unbind_from_irqhandler(netif->irq, netif);
   15.67 -	netif->irq = 0;
   15.68 -
   15.69 +	if (netif->irq)
   15.70 +		unbind_from_irqhandler(netif->irq, netif);
   15.71 +	
   15.72  	unregister_netdev(netif->dev);
   15.73  
   15.74  	if (netif->tx.sring) {
   15.75 @@ -290,10 +288,10 @@ void netif_creditlimit(netif_t *netif)
   15.76  #endif
   15.77  }
   15.78  
   15.79 -int netif_disconnect(netif_t *netif)
   15.80 +void netif_disconnect(netif_t *netif)
   15.81  {
   15.82 -
   15.83 -	if (netif->status == CONNECTED) {
   15.84 +	switch (netif->status) {
   15.85 +	case CONNECTED:
   15.86  		rtnl_lock();
   15.87  		netif->status = DISCONNECTING;
   15.88  		wmb();
   15.89 @@ -301,10 +299,14 @@ int netif_disconnect(netif_t *netif)
   15.90  			__netif_down(netif);
   15.91  		rtnl_unlock();
   15.92  		netif_put(netif);
   15.93 -		return 0; /* Caller should not send response message. */
   15.94 +		break;
   15.95 +	case DISCONNECTED:
   15.96 +		BUG_ON(atomic_read(&netif->refcnt) != 0);
   15.97 +		free_netif(netif);
   15.98 +		break;
   15.99 +	default:
  15.100 +		BUG();
  15.101  	}
  15.102 -
  15.103 -	return 1;
  15.104  }
  15.105  
  15.106  /*
    16.1 --- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c	Mon Jan 09 11:19:55 2006 +0000
    16.2 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c	Mon Jan 09 11:22:17 2006 +0000
    16.3 @@ -14,6 +14,7 @@
    16.4  #include <asm-xen/balloon.h>
    16.5  #include <asm-xen/xen-public/memory.h>
    16.6  
    16.7 +/*#define NETBE_DEBUG_INTERRUPT*/
    16.8  
    16.9  static void netif_idx_release(u16 pending_idx);
   16.10  static void netif_page_release(struct page *page);
   16.11 @@ -727,6 +728,7 @@ static int make_rx_response(netif_t *net
   16.12  	return notify;
   16.13  }
   16.14  
   16.15 +#ifdef NETBE_DEBUG_INTERRUPT
   16.16  static irqreturn_t netif_be_dbg(int irq, void *dev_id, struct pt_regs *regs)
   16.17  {
   16.18  	struct list_head *ent;
   16.19 @@ -758,6 +760,7 @@ static irqreturn_t netif_be_dbg(int irq,
   16.20  
   16.21  	return IRQ_HANDLED;
   16.22  }
   16.23 +#endif
   16.24  
   16.25  static int __init netback_init(void)
   16.26  {
   16.27 @@ -794,6 +797,7 @@ static int __init netback_init(void)
   16.28  
   16.29  	netif_xenbus_init();
   16.30  
   16.31 +#ifdef NETBE_DEBUG_INTERRUPT
   16.32  	(void)bind_virq_to_irqhandler(
   16.33  		VIRQ_DEBUG,
   16.34  		0,
   16.35 @@ -801,6 +805,7 @@ static int __init netback_init(void)
   16.36  		SA_SHIRQ, 
   16.37  		"net-be-dbg",
   16.38  		&netif_be_dbg);
   16.39 +#endif
   16.40  
   16.41  	return 0;
   16.42  }
    17.1 --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c	Mon Jan 09 11:19:55 2006 +0000
    17.2 +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c	Mon Jan 09 11:22:17 2006 +0000
    17.3 @@ -117,6 +117,8 @@ struct netfront_info
    17.4  	int rx_min_target, rx_max_target, rx_target;
    17.5  	struct sk_buff_head rx_batch;
    17.6  
    17.7 +	struct timer_list rx_refill_timer;
    17.8 +
    17.9  	/*
   17.10  	 * {tx,rx}_skbs store outstanding skbuffs. The first entry in each
   17.11  	 * array is an index into a chain of free entries.
   17.12 @@ -517,6 +519,13 @@ static void network_tx_buf_gc(struct net
   17.13  }
   17.14  
   17.15  
   17.16 +static void rx_refill_timeout(unsigned long data)
   17.17 +{
   17.18 +	struct net_device *dev = (struct net_device *)data;
   17.19 +	netif_rx_schedule(dev);
   17.20 +}
   17.21 +
   17.22 +
   17.23  static void network_alloc_rx_buffers(struct net_device *dev)
   17.24  {
   17.25  	unsigned short id;
   17.26 @@ -534,7 +543,7 @@ static void network_alloc_rx_buffers(str
   17.27  	 * Allocate skbuffs greedily, even though we batch updates to the
   17.28  	 * receive ring. This creates a less bursty demand on the memory
   17.29  	 * allocator, so should reduce the chance of failed allocation requests
   17.30 -	 *  both for ourself and for other kernel subsystems.
   17.31 +	 * both for ourself and for other kernel subsystems.
   17.32  	 */
   17.33  	batch_target = np->rx_target - (req_prod - np->rx.rsp_cons);
   17.34  	for (i = skb_queue_len(&np->rx_batch); i < batch_target; i++) {
   17.35 @@ -545,8 +554,15 @@ static void network_alloc_rx_buffers(str
   17.36  		skb = alloc_xen_skb(
   17.37  			((PAGE_SIZE - sizeof(struct skb_shared_info)) &
   17.38  			 (-SKB_DATA_ALIGN(1))) - 16);
   17.39 -		if (skb == NULL)
   17.40 -			break;
   17.41 +		if (skb == NULL) {
   17.42 +			/* Any skbuffs queued for refill? Force them out. */
   17.43 +			if (i != 0)
   17.44 +				goto refill;
   17.45 +			/* Could not allocate any skbuffs. Try again later. */
   17.46 +			mod_timer(&np->rx_refill_timer,
   17.47 +				  jiffies + (HZ/10));
   17.48 +			return;
   17.49 +		}
   17.50  		__skb_queue_tail(&np->rx_batch, skb);
   17.51  	}
   17.52  
   17.53 @@ -554,6 +570,12 @@ static void network_alloc_rx_buffers(str
   17.54  	if (i < (np->rx_target/2))
   17.55  		return;
   17.56  
   17.57 +	/* Adjust our fill target if we risked running out of buffers. */
   17.58 +	if (((req_prod - np->rx.sring->rsp_prod) < (np->rx_target / 4)) &&
   17.59 +	    ((np->rx_target *= 2) > np->rx_max_target))
   17.60 +		np->rx_target = np->rx_max_target;
   17.61 +
   17.62 + refill:
   17.63  	for (i = 0; ; i++) {
   17.64  		if ((skb = __skb_dequeue(&np->rx_batch)) == NULL)
   17.65  			break;
   17.66 @@ -608,11 +630,6 @@ static void network_alloc_rx_buffers(str
   17.67  	/* Above is a suitable barrier to ensure backend will see requests. */
   17.68  	np->rx.req_prod_pvt = req_prod + i;
   17.69  	RING_PUSH_REQUESTS(&np->rx);
   17.70 -
   17.71 -	/* Adjust our fill target if we risked running out of buffers. */
   17.72 -	if (((req_prod - np->rx.sring->rsp_prod) < (np->rx_target / 4)) &&
   17.73 -	    ((np->rx_target *= 2) > np->rx_max_target))
   17.74 -		np->rx_target = np->rx_max_target;
   17.75  }
   17.76  
   17.77  
   17.78 @@ -1077,6 +1094,10 @@ static int create_netdev(int handle, str
   17.79  	np->rx_min_target = RX_MIN_TARGET;
   17.80  	np->rx_max_target = RX_MAX_TARGET;
   17.81  
   17.82 +	init_timer(&np->rx_refill_timer);
   17.83 +	np->rx_refill_timer.data = (unsigned long)netdev;
   17.84 +	np->rx_refill_timer.function = rx_refill_timeout;
   17.85 +
   17.86  	/* Initialise {tx,rx}_skbs as a free chain containing every entry. */
   17.87  	for (i = 0; i <= NET_TX_RING_SIZE; i++) {
   17.88  		np->tx_skbs[i] = (void *)((unsigned long) i+1);
   17.89 @@ -1188,29 +1209,26 @@ static int netfront_remove(struct xenbus
   17.90  
   17.91  	DPRINTK("%s\n", dev->nodename);
   17.92  
   17.93 -	netif_free(info);
   17.94 -	kfree(info);
   17.95 +	netif_disconnect_backend(info);
   17.96 +	free_netdev(info->netdev);
   17.97  
   17.98  	return 0;
   17.99  }
  17.100  
  17.101  
  17.102 -static void netif_free(struct netfront_info *info)
  17.103 -{
  17.104 -	netif_disconnect_backend(info);
  17.105 -	close_netdev(info);
  17.106 -}
  17.107 -
  17.108 -
  17.109  static void close_netdev(struct netfront_info *info)
  17.110  {
  17.111 -	if (info->netdev) {
  17.112 +	spin_lock_irq(&info->netdev->xmit_lock);
  17.113 +	netif_stop_queue(info->netdev);
  17.114 +	spin_unlock_irq(&info->netdev->xmit_lock);
  17.115 +
  17.116  #ifdef CONFIG_PROC_FS
  17.117 -		xennet_proc_delif(info->netdev);
  17.118 +	xennet_proc_delif(info->netdev);
  17.119  #endif
  17.120 -		unregister_netdev(info->netdev);
  17.121 -		info->netdev = NULL;
  17.122 -	}
  17.123 +
  17.124 +	del_timer_sync(&info->rx_refill_timer);
  17.125 +
  17.126 +	unregister_netdev(info->netdev);
  17.127  }
  17.128  
  17.129  
  17.130 @@ -1219,21 +1237,28 @@ static void netif_disconnect_backend(str
  17.131  	/* Stop old i/f to prevent errors whilst we rebuild the state. */
  17.132  	spin_lock_irq(&info->tx_lock);
  17.133  	spin_lock(&info->rx_lock);
  17.134 -	netif_stop_queue(info->netdev);
  17.135 -	/* info->backend_state = BEST_DISCONNECTED; */
  17.136 +	info->backend_state = BEST_DISCONNECTED;
  17.137  	spin_unlock(&info->rx_lock);
  17.138  	spin_unlock_irq(&info->tx_lock);
  17.139 -    
  17.140 +
  17.141 +	if (info->irq)
  17.142 +		unbind_from_irqhandler(info->irq, info->netdev);
  17.143 +	info->evtchn = info->irq = 0;
  17.144 +
  17.145  	end_access(info->tx_ring_ref, info->tx.sring);
  17.146  	end_access(info->rx_ring_ref, info->rx.sring);
  17.147  	info->tx_ring_ref = GRANT_INVALID_REF;
  17.148  	info->rx_ring_ref = GRANT_INVALID_REF;
  17.149  	info->tx.sring = NULL;
  17.150  	info->rx.sring = NULL;
  17.151 +}
  17.152  
  17.153 -	if (info->irq)
  17.154 -		unbind_from_irqhandler(info->irq, info->netdev);
  17.155 -	info->evtchn = info->irq = 0;
  17.156 +
  17.157 +static void netif_free(struct netfront_info *info)
  17.158 +{
  17.159 +	close_netdev(info);
  17.160 +	netif_disconnect_backend(info);
  17.161 +	free_netdev(info->netdev);
  17.162  }
  17.163  
  17.164  
    18.1 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c	Mon Jan 09 11:19:55 2006 +0000
    18.2 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c	Mon Jan 09 11:22:17 2006 +0000
    18.3 @@ -111,7 +111,6 @@ static ssize_t xenbus_dev_write(struct f
    18.4  	struct xenbus_dev_data *u = filp->private_data;
    18.5  	struct xenbus_dev_transaction *trans;
    18.6  	void *reply;
    18.7 -	int err = 0;
    18.8  
    18.9  	if ((len + u->len) > sizeof(u->u.buffer))
   18.10  		return -EINVAL;
   18.11 @@ -136,41 +135,36 @@ static ssize_t xenbus_dev_write(struct f
   18.12  	case XS_RM:
   18.13  	case XS_SET_PERMS:
   18.14  		reply = xenbus_dev_request_and_reply(&u->u.msg);
   18.15 -		if (IS_ERR(reply)) {
   18.16 -			err = PTR_ERR(reply);
   18.17 -		} else {
   18.18 -			if (u->u.msg.type == XS_TRANSACTION_START) {
   18.19 -				trans = kmalloc(sizeof(*trans), GFP_KERNEL);
   18.20 -				trans->handle = (struct xenbus_transaction *)
   18.21 -					simple_strtoul(reply, NULL, 0);
   18.22 -				list_add(&trans->list, &u->transactions);
   18.23 -			} else if (u->u.msg.type == XS_TRANSACTION_END) {
   18.24 -				list_for_each_entry(trans, &u->transactions,
   18.25 -						    list)
   18.26 -					if ((unsigned long)trans->handle ==
   18.27 -					    (unsigned long)u->u.msg.tx_id)
   18.28 -						break;
   18.29 -				BUG_ON(&trans->list == &u->transactions);
   18.30 -				list_del(&trans->list);
   18.31 -				kfree(trans);
   18.32 -			}
   18.33 -			queue_reply(u, (char *)&u->u.msg, sizeof(u->u.msg));
   18.34 -			queue_reply(u, (char *)reply, u->u.msg.len);
   18.35 -			kfree(reply);
   18.36 +		if (IS_ERR(reply))
   18.37 +			return PTR_ERR(reply);
   18.38 +
   18.39 +		if (u->u.msg.type == XS_TRANSACTION_START) {
   18.40 +			trans = kmalloc(sizeof(*trans), GFP_KERNEL);
   18.41 +			if (!trans)
   18.42 +				return -ENOMEM;
   18.43 +			trans->handle = (struct xenbus_transaction *)
   18.44 +				simple_strtoul(reply, NULL, 0);
   18.45 +			list_add(&trans->list, &u->transactions);
   18.46 +		} else if (u->u.msg.type == XS_TRANSACTION_END) {
   18.47 +			list_for_each_entry(trans, &u->transactions, list)
   18.48 +				if ((unsigned long)trans->handle ==
   18.49 +				    (unsigned long)u->u.msg.tx_id)
   18.50 +					break;
   18.51 +			BUG_ON(&trans->list == &u->transactions);
   18.52 +			list_del(&trans->list);
   18.53 +			kfree(trans);
   18.54  		}
   18.55 +		queue_reply(u, (char *)&u->u.msg, sizeof(u->u.msg));
   18.56 +		queue_reply(u, (char *)reply, u->u.msg.len);
   18.57 +		kfree(reply);
   18.58  		break;
   18.59  
   18.60  	default:
   18.61 -		err = -EINVAL;
   18.62 -		break;
   18.63 +		return -EINVAL;
   18.64  	}
   18.65  
   18.66 -	if (err == 0) {
   18.67 -		u->len = 0;
   18.68 -		err = len;
   18.69 -	}
   18.70 -
   18.71 -	return err;
   18.72 +	u->len = 0;
   18.73 +	return len;
   18.74  }
   18.75  
   18.76  static int xenbus_dev_open(struct inode *inode, struct file *filp)
    19.1 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c	Mon Jan 09 11:19:55 2006 +0000
    19.2 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c	Mon Jan 09 11:22:17 2006 +0000
    19.3 @@ -542,14 +542,6 @@ static int xenbus_probe_node(struct xen_
    19.4  			     const char *type,
    19.5  			     const char *nodename)
    19.6  {
    19.7 -#define CHECK_FAIL				\
    19.8 -	do {					\
    19.9 -		if (err)			\
   19.10 -			goto fail;		\
   19.11 -	}					\
   19.12 -	while (0)				\
   19.13 -
   19.14 -
   19.15  	int err;
   19.16  	struct xenbus_device *xendev;
   19.17  	size_t stringlen;
   19.18 @@ -584,19 +576,18 @@ static int xenbus_probe_node(struct xen_
   19.19  	xendev->dev.release = xenbus_dev_release;
   19.20  
   19.21  	err = bus->get_bus_id(xendev->dev.bus_id, xendev->nodename);
   19.22 -	CHECK_FAIL;
   19.23 +	if (err)
   19.24 +		goto fail;
   19.25  
   19.26  	/* Register with generic device framework. */
   19.27  	err = device_register(&xendev->dev);
   19.28 -	CHECK_FAIL;
   19.29 +	if (err)
   19.30 +		goto fail;
   19.31  
   19.32  	device_create_file(&xendev->dev, &dev_attr_nodename);
   19.33  	device_create_file(&xendev->dev, &dev_attr_devtype);
   19.34  
   19.35  	return 0;
   19.36 -
   19.37 -#undef CHECK_FAIL
   19.38 -
   19.39  fail:
   19.40  	xenbus_dev_free(xendev);
   19.41  	return err;
    20.1 --- a/linux-2.6-xen-sparse/include/asm-xen/asm-ia64/hypercall.h	Mon Jan 09 11:19:55 2006 +0000
    20.2 +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-ia64/hypercall.h	Mon Jan 09 11:22:17 2006 +0000
    20.3 @@ -372,7 +372,7 @@ HYPERVISOR_memory_op(
    20.4      int ret;
    20.5      __asm__ __volatile__ ( ";; mov r14=%2 ; mov r15=%3 ; mov r2=%1 ; break 0x1000 ;; mov %0=r8 ;;"
    20.6          : "=r" (ret)
    20.7 -        : "i" (__HYPERVISOR_console_io), "r"(cmd), "r"(arg)
    20.8 +        : "i" (__HYPERVISOR_memory_op), "r"(cmd), "r"(arg)
    20.9          : "r14","r15","r2","r8","memory" );
   20.10      return ret;
   20.11  }
    21.1 --- a/tools/Makefile	Mon Jan 09 11:19:55 2006 +0000
    21.2 +++ b/tools/Makefile	Mon Jan 09 11:22:17 2006 +0000
    21.3 @@ -12,6 +12,7 @@ SUBDIRS += firmware
    21.4  SUBDIRS += security
    21.5  SUBDIRS += console
    21.6  SUBDIRS += xenmon
    21.7 +SUBDIRS += guest-headers
    21.8  ifeq ($(VTPM_TOOLS),y)
    21.9  SUBDIRS += vtpm_manager
   21.10  SUBDIRS += vtpm
    22.1 --- a/tools/Rules.mk	Mon Jan 09 11:19:55 2006 +0000
    22.2 +++ b/tools/Rules.mk	Mon Jan 09 11:22:17 2006 +0000
    22.3 @@ -35,6 +35,8 @@ mk-symlinks: LINUX_ROOT=$(XEN_ROOT)/linu
    22.4  mk-symlinks:
    22.5  	mkdir -p xen
    22.6  	( cd xen && ln -sf ../$(XEN_ROOT)/xen/include/public/*.h . )
    22.7 +	mkdir -p xen/hvm
    22.8 +	( cd xen/hvm && ln -sf ../../$(XEN_ROOT)/xen/include/public/hvm/*.h . )
    22.9  	mkdir -p xen/io
   22.10  	( cd xen/io && ln -sf ../../$(XEN_ROOT)/xen/include/public/io/*.h . )
   22.11  	mkdir -p xen/linux
    23.1 --- a/tools/debugger/libxendebug/xendebug.c	Mon Jan 09 11:19:55 2006 +0000
    23.2 +++ b/tools/debugger/libxendebug/xendebug.c	Mon Jan 09 11:22:17 2006 +0000
    23.3 @@ -119,8 +119,8 @@ xendebug_get_context (int xc_handle, uin
    23.4  
    23.5      if ( !ctxt->valid[vcpu] )
    23.6      {
    23.7 -        if ( (rc = xc_domain_get_vcpu_context(xc_handle, domid, vcpu, 
    23.8 -                                              &ctxt->context[vcpu])) )
    23.9 +        if ( (rc = xc_vcpu_getcontext(xc_handle, domid, vcpu, 
   23.10 +                                      &ctxt->context[vcpu])) )
   23.11              return NULL;
   23.12  
   23.13          ctxt->valid[vcpu] = true;
   23.14 @@ -139,10 +139,10 @@ xendebug_set_context (int xc_handle, dom
   23.15          return -EINVAL;
   23.16  
   23.17      op.interface_version = DOM0_INTERFACE_VERSION;
   23.18 -    op.cmd = DOM0_SETDOMAININFO;
   23.19 -    op.u.setdomaininfo.domain = ctxt->domid;
   23.20 -    op.u.setdomaininfo.vcpu = vcpu;
   23.21 -    op.u.setdomaininfo.ctxt = &ctxt->context[vcpu];
   23.22 +    op.cmd = DOM0_SETVCPUCONTEXT;
   23.23 +    op.u.setvcpucontext.domain = ctxt->domid;
   23.24 +    op.u.setvcpucontext.vcpu = vcpu;
   23.25 +    op.u.setvcpucontext.ctxt = &ctxt->context[vcpu];
   23.26  
   23.27      if ( (rc = mlock(&ctxt->context[vcpu], sizeof(vcpu_guest_context_t))) )
   23.28          return rc;
    24.1 --- a/tools/examples/xmexample.vmx	Mon Jan 09 11:19:55 2006 +0000
    24.2 +++ b/tools/examples/xmexample.vmx	Mon Jan 09 11:22:17 2006 +0000
    24.3 @@ -28,7 +28,13 @@ name = "ExampleVMXDomain"
    24.4  
    24.5  #-----------------------------------------------------------------------------
    24.6  # the number of cpus guest platform has, default=1
    24.7 -vcpus=1
    24.8 +#vcpus=1
    24.9 +
   24.10 +# enable/disalbe vmx guest ACPI, default=0 (disabled)
   24.11 +#acpi=0
   24.12 +
   24.13 +# enable/disalbe vmx guest APIC, default=0 (disabled)
   24.14 +#apic=0
   24.15  
   24.16  # List of which CPUS this domain is allowed to use, default Xen picks
   24.17  #cpus = ""         # leave to Xen to pick
    25.1 --- a/tools/firmware/vmxassist/Makefile	Mon Jan 09 11:19:55 2006 +0000
    25.2 +++ b/tools/firmware/vmxassist/Makefile	Mon Jan 09 11:22:17 2006 +0000
    25.3 @@ -24,7 +24,7 @@ include $(XEN_ROOT)/tools/Rules.mk
    25.4  # The emulator code lives in ROM space
    25.5  TEXTADDR=0x000D0000
    25.6  
    25.7 -DEFINES=-DDEBUG -D_ACPI_ -DTEXTADDR=$(TEXTADDR)
    25.8 +DEFINES=-DDEBUG -DTEXTADDR=$(TEXTADDR)
    25.9  XENINC=-I$(XEN_ROOT)/tools/libxc
   25.10  
   25.11  LD       = ld
    26.1 --- a/tools/firmware/vmxassist/acpi_madt.c	Mon Jan 09 11:19:55 2006 +0000
    26.2 +++ b/tools/firmware/vmxassist/acpi_madt.c	Mon Jan 09 11:22:17 2006 +0000
    26.3 @@ -17,30 +17,73 @@
    26.4   * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
    26.5   * Place - Suite 330, Boston, MA 02111-1307 USA.
    26.6   */
    26.7 +
    26.8  #include "../acpi/acpi2_0.h"
    26.9  #include "../acpi/acpi_madt.h"
   26.10  
   26.11 +#include <xen/hvm/hvm_info_table.h>
   26.12 +
   26.13  #define NULL ((void*)0)
   26.14  
   26.15  extern int puts(const char *s);
   26.16  
   26.17 -#define VCPU_NR_PAGE        0x0009F000
   26.18 -#define VCPU_NR_OFFSET      0x00000800
   26.19 -#define VCPU_MAGIC          0x76637075  /* "vcpu" */
   26.20 +static struct hvm_info_table *table = NULL;
   26.21 +
   26.22 +static int validate_hvm_info(struct hvm_info_table *t)
   26.23 +{
   26.24 +	char signature[] = "HVM INFO";
   26.25 +	uint8_t *ptr = (uint8_t *)t;
   26.26 +	uint8_t sum = 0;
   26.27 +	int i;
   26.28 +
   26.29 +	/* strncmp(t->signature, "HVM INFO", 8) */
   26.30 +	for (i = 0; i < 8; i++) {
   26.31 +		if (signature[i] != t->signature[i]) {
   26.32 +			puts("Bad hvm info signature\n");
   26.33 +			return 0;
   26.34 +		}
   26.35 +	}
   26.36 +
   26.37 +	for (i = 0; i < t->length; i++)
   26.38 +		sum += ptr[i];
   26.39 +
   26.40 +	return (sum == 0);
   26.41 +}
   26.42  
   26.43 -/* xc_vmx_builder wrote vcpu block at 0x9F800. Return it. */
   26.44 -static int
   26.45 +/* xc_vmx_builder wrote hvm info at 0x9F800. Return it. */
   26.46 +static struct hvm_info_table *
   26.47 +get_hvm_info_table(void)
   26.48 +{
   26.49 +	struct hvm_info_table *t;
   26.50 +	int i;
   26.51 +
   26.52 +	if (table != NULL)
   26.53 +		return table;
   26.54 +
   26.55 +	t = (struct hvm_info_table *)HVM_INFO_PADDR;
   26.56 +
   26.57 +	if (!validate_hvm_info(t)) {
   26.58 +		puts("Bad hvm info table\n");
   26.59 +		return NULL;
   26.60 +	}
   26.61 +
   26.62 +	table = t;
   26.63 +
   26.64 +	return table;
   26.65 +}
   26.66 +
   26.67 +int
   26.68  get_vcpu_nr(void)
   26.69  {
   26.70 -	unsigned int *vcpus;
   26.71 +	struct hvm_info_table *t = get_hvm_info_table();
   26.72 +	return (t ? t->nr_vcpus : 1); /* default 1 vcpu */
   26.73 +}
   26.74  
   26.75 -	vcpus = (unsigned int *)(VCPU_NR_PAGE + VCPU_NR_OFFSET);
   26.76 -	if (vcpus[0] != VCPU_MAGIC) {
   26.77 -		puts("Bad vcpus magic, set vcpu number to 1 by default.\n");
   26.78 -		return 1;
   26.79 -	}
   26.80 -
   26.81 -	return vcpus[1];
   26.82 +int
   26.83 +get_acpi_enabled(void)
   26.84 +{
   26.85 +	struct hvm_info_table *t = get_hvm_info_table();
   26.86 +	return (t ? t->acpi_enabled : 0); /* default no acpi */
   26.87  }
   26.88  
   26.89  static void *
   26.90 @@ -74,10 +117,10 @@ acpi_madt_get_madt(unsigned char *acpi_s
   26.91  	return madt;
   26.92  }
   26.93  
   26.94 -static void 
   26.95 +static void
   26.96  set_checksum(void *start, int checksum_offset, int len)
   26.97  {
   26.98 -	unsigned char sum = 0;  
   26.99 +	unsigned char sum = 0;
  26.100  	unsigned char *ptr;
  26.101  
  26.102  	ptr = start;
  26.103 @@ -89,9 +132,9 @@ set_checksum(void *start, int checksum_o
  26.104  	ptr[checksum_offset] = -sum;
  26.105  }
  26.106  
  26.107 -static int 
  26.108 +static int
  26.109  acpi_madt_set_local_apics(
  26.110 -	int nr_vcpu, 
  26.111 +	int nr_vcpu,
  26.112  	ACPI_MULTIPLE_APIC_DESCRIPTION_TABLE *madt)
  26.113  {
  26.114  	int i;
  26.115 @@ -104,14 +147,14 @@ acpi_madt_set_local_apics(
  26.116  		madt->LocalApic[i].Length          = sizeof (ACPI_LOCAL_APIC_STRUCTURE);
  26.117  		madt->LocalApic[i].AcpiProcessorId = i;
  26.118  		madt->LocalApic[i].ApicId          = i;
  26.119 -		madt->LocalApic[i].Flags           = 1; 
  26.120 +		madt->LocalApic[i].Flags           = 1;
  26.121  	}
  26.122  
  26.123  	madt->Header.Header.Length =
  26.124 -		sizeof(ACPI_MULTIPLE_APIC_DESCRIPTION_TABLE) - 
  26.125 +		sizeof(ACPI_MULTIPLE_APIC_DESCRIPTION_TABLE) -
  26.126  		(MAX_VIRT_CPUS - nr_vcpu)* sizeof(ACPI_LOCAL_APIC_STRUCTURE);
  26.127  
  26.128 -	return 0;                            
  26.129 +	return 0;
  26.130  }
  26.131  
  26.132  #define FIELD_OFFSET(TYPE,Field) ((unsigned int)(&(((TYPE *) 0)->Field)))
  26.133 @@ -133,7 +176,7 @@ int acpi_madt_update(unsigned char *acpi
  26.134  		madt, FIELD_OFFSET(ACPI_TABLE_HEADER, Checksum),
  26.135  		madt->Header.Header.Length);
  26.136  
  26.137 -	return 0;              
  26.138 +	return 0;
  26.139  }
  26.140  
  26.141  /*
    27.1 --- a/tools/firmware/vmxassist/vm86.h	Mon Jan 09 11:19:55 2006 +0000
    27.2 +++ b/tools/firmware/vmxassist/vm86.h	Mon Jan 09 11:22:17 2006 +0000
    27.3 @@ -24,7 +24,7 @@
    27.4  #include <stdint.h>
    27.5  #endif
    27.6  
    27.7 -#include <xen/vmx_assist.h>
    27.8 +#include <xen/hvm/vmx_assist.h>
    27.9  
   27.10  #define	NR_EXCEPTION_HANDLER	32
   27.11  #define	NR_INTERRUPT_HANDLERS	16
    28.1 --- a/tools/firmware/vmxassist/vmxloader.c	Mon Jan 09 11:19:55 2006 +0000
    28.2 +++ b/tools/firmware/vmxassist/vmxloader.c	Mon Jan 09 11:22:17 2006 +0000
    28.3 @@ -24,12 +24,10 @@
    28.4  #include "machine.h"
    28.5  #include "roms.h"
    28.6  
    28.7 -#ifdef _ACPI_
    28.8  #include "acpi.h"
    28.9  #include "../acpi/acpi2_0.h"  // for ACPI_PHYSICAL_ADDRESS
   28.10  int acpi_madt_update(unsigned char* acpi_start);
   28.11 -#endif
   28.12 -
   28.13 +int get_acpi_enabled(void);
   28.14  
   28.15  /*
   28.16   * C runtime start off
   28.17 @@ -120,18 +118,17 @@ main(void)
   28.18  		memcpy((void *)0xC0000,
   28.19  			vgabios_stdvga, sizeof(vgabios_stdvga));
   28.20  	}
   28.21 -#ifdef _ACPI_
   28.22 -	puts("Loading ACPI ...\n");
   28.23  
   28.24 -	acpi_madt_update(acpi);
   28.25 -
   28.26 -	if (ACPI_PHYSICAL_ADDRESS+sizeof(acpi) <= 0xF0000) {
   28.27 -		/* make sure acpi table does not overlap rombios
   28.28 - 		 * currently acpi less than 8K will be OK.
   28.29 -		 */
   28.30 -		 memcpy((void *)ACPI_PHYSICAL_ADDRESS, acpi, sizeof(acpi));
   28.31 +	if (get_acpi_enabled() != 0) {
   28.32 +		puts("Loading ACPI ...\n");
   28.33 +		acpi_madt_update((unsigned char*)acpi);
   28.34 +		if (ACPI_PHYSICAL_ADDRESS+sizeof(acpi) <= 0xF0000) {
   28.35 +			/* make sure acpi table does not overlap rombios
   28.36 +			 * currently acpi less than 8K will be OK.
   28.37 +			 */
   28.38 +			memcpy((void *)ACPI_PHYSICAL_ADDRESS, acpi, sizeof(acpi));
   28.39 +		}
   28.40  	}
   28.41 -#endif
   28.42  
   28.43  	puts("Loading VMXAssist ...\n");
   28.44  	memcpy((void *)TEXTADDR, vmxassist, sizeof(vmxassist));
    29.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.2 +++ b/tools/guest-headers/Makefile	Mon Jan 09 11:22:17 2006 +0000
    29.3 @@ -0,0 +1,11 @@
    29.4 +
    29.5 +XEN_ROOT=../..
    29.6 +linuxsparsetree = $(XEN_ROOT)/linux-2.6-xen-sparse
    29.7 +
    29.8 +check:
    29.9 +
   29.10 +install:
   29.11 +	mkdir -p $(DESTDIR)/usr/include/xen/linux
   29.12 +	install -m0644 $(linuxsparsetree)/include/asm-xen/linux-public/*.h $(DESTDIR)/usr/include/xen/linux
   29.13 +
   29.14 +clean:
    30.1 --- a/tools/ioemu/hw/i8254.c	Mon Jan 09 11:19:55 2006 +0000
    30.2 +++ b/tools/ioemu/hw/i8254.c	Mon Jan 09 11:22:17 2006 +0000
    30.3 @@ -23,7 +23,7 @@
    30.4   */
    30.5  #include "vl.h"
    30.6  #include <xenctrl.h>
    30.7 -#include <xen/io/ioreq.h>
    30.8 +#include <xen/hvm/ioreq.h>
    30.9  
   30.10  //#define DEBUG_PIT
   30.11  
    31.1 --- a/tools/ioemu/hw/i8259.c	Mon Jan 09 11:19:55 2006 +0000
    31.2 +++ b/tools/ioemu/hw/i8259.c	Mon Jan 09 11:22:17 2006 +0000
    31.3 @@ -23,7 +23,7 @@
    31.4   */
    31.5  #include "vl.h"
    31.6  #include <xenctrl.h>
    31.7 -#include <xen/io/ioreq.h>
    31.8 +#include <xen/hvm/ioreq.h>
    31.9  
   31.10  /* debug PIC */
   31.11  //#define DEBUG_PIC
    32.1 --- a/tools/ioemu/hw/i8259_stub.c	Mon Jan 09 11:19:55 2006 +0000
    32.2 +++ b/tools/ioemu/hw/i8259_stub.c	Mon Jan 09 11:22:17 2006 +0000
    32.3 @@ -22,7 +22,7 @@
    32.4   * THE SOFTWARE.
    32.5   */
    32.6  #include "xenctrl.h"
    32.7 -#include <xen/io/ioreq.h>
    32.8 +#include <xen/hvm/ioreq.h>
    32.9  #include <stdio.h>
   32.10  #include "cpu.h"
   32.11  #include "cpu-all.h"
    33.1 --- a/tools/ioemu/target-i386-dm/helper2.c	Mon Jan 09 11:19:55 2006 +0000
    33.2 +++ b/tools/ioemu/target-i386-dm/helper2.c	Mon Jan 09 11:22:17 2006 +0000
    33.3 @@ -48,7 +48,7 @@
    33.4  #include <sys/ioctl.h>
    33.5  
    33.6  #include <xenctrl.h>
    33.7 -#include <xen/io/ioreq.h>
    33.8 +#include <xen/hvm/ioreq.h>
    33.9  #include <xen/linux/evtchn.h>
   33.10  
   33.11  #include "cpu.h"
    34.1 --- a/tools/ioemu/vl.c	Mon Jan 09 11:19:55 2006 +0000
    34.2 +++ b/tools/ioemu/vl.c	Mon Jan 09 11:22:17 2006 +0000
    34.3 @@ -2948,6 +2948,7 @@ int main(int argc, char **argv)
    34.4              case QEMU_OPTION_vcpus:
    34.5                  vcpus = atoi(optarg);
    34.6                  fprintf(logfile, "qemu: the number of cpus is %d\n", vcpus);
    34.7 +                break;
    34.8              case QEMU_OPTION_pci:
    34.9                  pci_enabled = 1;
   34.10                  break;
    35.1 --- a/tools/libxc/xc_core.c	Mon Jan 09 11:19:55 2006 +0000
    35.2 +++ b/tools/libxc/xc_core.c	Mon Jan 09 11:22:17 2006 +0000
    35.3 @@ -55,7 +55,7 @@ xc_domain_dumpcore(int xc_handle,
    35.4      }
    35.5   
    35.6      for (i = 0; i < info.max_vcpu_id; i++)
    35.7 -        if (xc_domain_get_vcpu_context(xc_handle, domid,
    35.8 +        if (xc_vcpu_getcontext(xc_handle, domid,
    35.9                                         i, &ctxt[nr_vcpus]) == 0)
   35.10              nr_vcpus++;
   35.11   
    36.1 --- a/tools/libxc/xc_domain.c	Mon Jan 09 11:19:55 2006 +0000
    36.2 +++ b/tools/libxc/xc_domain.c	Mon Jan 09 11:22:17 2006 +0000
    36.3 @@ -58,16 +58,16 @@ int xc_domain_destroy(int xc_handle,
    36.4      return do_dom0_op(xc_handle, &op);
    36.5  }
    36.6  
    36.7 -int xc_domain_pincpu(int xc_handle,
    36.8 -                     uint32_t domid, 
    36.9 -                     int vcpu,
   36.10 -                     cpumap_t cpumap)
   36.11 +int xc_vcpu_setaffinity(int xc_handle,
   36.12 +                        uint32_t domid, 
   36.13 +                        int vcpu,
   36.14 +                        cpumap_t cpumap)
   36.15  {
   36.16      DECLARE_DOM0_OP;
   36.17 -    op.cmd = DOM0_PINCPUDOMAIN;
   36.18 -    op.u.pincpudomain.domain  = (domid_t)domid;
   36.19 -    op.u.pincpudomain.vcpu    = vcpu;
   36.20 -    op.u.pincpudomain.cpumap  = cpumap;
   36.21 +    op.cmd = DOM0_SETVCPUAFFINITY;
   36.22 +    op.u.setvcpuaffinity.domain  = (domid_t)domid;
   36.23 +    op.u.setvcpuaffinity.vcpu    = vcpu;
   36.24 +    op.u.setvcpuaffinity.cpumap  = cpumap;
   36.25      return do_dom0_op(xc_handle, &op);
   36.26  }
   36.27  
   36.28 @@ -155,7 +155,7 @@ int xc_domain_getinfolist(int xc_handle,
   36.29      return ret;
   36.30  }
   36.31  
   36.32 -int xc_domain_get_vcpu_context(int xc_handle,
   36.33 +int xc_vcpu_getcontext(int xc_handle,
   36.34                                 uint32_t domid,
   36.35                                 uint32_t vcpu,
   36.36                                 vcpu_guest_context_t *ctxt)
   36.37 @@ -345,10 +345,10 @@ int xc_domain_sethandle(int xc_handle, u
   36.38      return do_dom0_op(xc_handle, &op);
   36.39  }
   36.40  
   36.41 -int xc_domain_get_vcpu_info(int xc_handle,
   36.42 -                            uint32_t domid,
   36.43 -                            uint32_t vcpu,
   36.44 -                            xc_vcpuinfo_t *info)
   36.45 +int xc_vcpu_getinfo(int xc_handle,
   36.46 +                    uint32_t domid,
   36.47 +                    uint32_t vcpu,
   36.48 +                    xc_vcpuinfo_t *info)
   36.49  {
   36.50      int rc;
   36.51      DECLARE_DOM0_OP;
   36.52 @@ -380,18 +380,18 @@ int xc_domain_ioport_permission(int xc_h
   36.53      return do_dom0_op(xc_handle, &op);
   36.54  }
   36.55  
   36.56 -int xc_domain_setinfo(int xc_handle,
   36.57 -                      uint32_t domid,
   36.58 -                      uint32_t vcpu,
   36.59 -                      vcpu_guest_context_t *ctxt)
   36.60 +int xc_vcpu_setcontext(int xc_handle,
   36.61 +                       uint32_t domid,
   36.62 +                       uint32_t vcpu,
   36.63 +                       vcpu_guest_context_t *ctxt)
   36.64  {
   36.65      dom0_op_t op;
   36.66      int rc;
   36.67  
   36.68 -    op.cmd = DOM0_SETDOMAININFO;
   36.69 -    op.u.setdomaininfo.domain = domid;
   36.70 -    op.u.setdomaininfo.vcpu = vcpu;
   36.71 -    op.u.setdomaininfo.ctxt = ctxt;
   36.72 +    op.cmd = DOM0_SETVCPUCONTEXT;
   36.73 +    op.u.setvcpucontext.domain = domid;
   36.74 +    op.u.setvcpucontext.vcpu = vcpu;
   36.75 +    op.u.setvcpucontext.ctxt = ctxt;
   36.76  
   36.77      if ( (rc = mlock(ctxt, sizeof(*ctxt))) != 0 )
   36.78          return rc;
   36.79 @@ -404,6 +404,38 @@ int xc_domain_setinfo(int xc_handle,
   36.80  
   36.81  }
   36.82  
   36.83 +int xc_domain_irq_permission(int xc_handle,
   36.84 +                             uint32_t domid,
   36.85 +                             uint8_t pirq,
   36.86 +                             uint8_t allow_access)
   36.87 +{
   36.88 +    dom0_op_t op;
   36.89 +
   36.90 +    op.cmd = DOM0_IRQ_PERMISSION;
   36.91 +    op.u.irq_permission.domain = domid;
   36.92 +    op.u.irq_permission.pirq = pirq;
   36.93 +    op.u.irq_permission.allow_access = allow_access;
   36.94 +
   36.95 +    return do_dom0_op(xc_handle, &op);
   36.96 +}
   36.97 +
   36.98 +int xc_domain_iomem_permission(int xc_handle,
   36.99 +                               uint32_t domid,
  36.100 +                               unsigned long first_pfn,
  36.101 +                               unsigned long nr_pfns,
  36.102 +                               uint8_t allow_access)
  36.103 +{
  36.104 +    dom0_op_t op;
  36.105 +
  36.106 +    op.cmd = DOM0_IOMEM_PERMISSION;
  36.107 +    op.u.iomem_permission.domain = domid;
  36.108 +    op.u.iomem_permission.first_pfn = first_pfn;
  36.109 +	op.u.iomem_permission.nr_pfns = nr_pfns;
  36.110 +    op.u.iomem_permission.allow_access = allow_access;
  36.111 +
  36.112 +    return do_dom0_op(xc_handle, &op);
  36.113 +}
  36.114 +
  36.115  /*
  36.116   * Local variables:
  36.117   * mode: C
    37.1 --- a/tools/libxc/xc_ia64_stubs.c	Mon Jan 09 11:19:55 2006 +0000
    37.2 +++ b/tools/libxc/xc_ia64_stubs.c	Mon Jan 09 11:22:17 2006 +0000
    37.3 @@ -5,7 +5,7 @@
    37.4  #include <stdlib.h>
    37.5  #include <zlib.h>
    37.6  #include "xen/arch-ia64.h"
    37.7 -#include <xen/io/ioreq.h>
    37.8 +#include <xen/hvm/ioreq.h>
    37.9  
   37.10  /* this is a very ugly way of getting FPSR_DEFAULT.  struct ia64_fpreg is
   37.11   * mysteriously declared in two places: /usr/include/asm/fpu.h and
   37.12 @@ -627,6 +627,7 @@ int xc_vmx_build(int xc_handle,
   37.13                   unsigned int control_evtchn,
   37.14                   unsigned int lapic,
   37.15                   unsigned int vcpus,
   37.16 +                 unsigned int acpi,
   37.17                   unsigned int store_evtchn,
   37.18                   unsigned long *store_mfn)
   37.19  {
   37.20 @@ -663,7 +664,7 @@ int xc_vmx_build(int xc_handle,
   37.21          goto error_out;
   37.22      }
   37.23  
   37.24 -    if ( xc_domain_get_vcpu_context(xc_handle, domid, 0, ctxt) ){
   37.25 +    if ( xc_vcpu_getcontext(xc_handle, domid, 0, ctxt) ){
   37.26          PERROR("Could not get vcpu context");
   37.27          goto error_out;
   37.28      }
   37.29 @@ -687,11 +688,11 @@ int xc_vmx_build(int xc_handle,
   37.30  
   37.31      memset( &launch_op, 0, sizeof(launch_op) );
   37.32  
   37.33 -    launch_op.u.setdomaininfo.domain = (domid_t)domid;
   37.34 -    launch_op.u.setdomaininfo.vcpu   = 0;
   37.35 -    launch_op.u.setdomaininfo.ctxt   = ctxt;
   37.36 +    launch_op.u.setvcpucontext.domain = (domid_t)domid;
   37.37 +    launch_op.u.setvcpucontext.vcpu   = 0;
   37.38 +    launch_op.u.setvcpucontext.ctxt   = ctxt;
   37.39  
   37.40 -    launch_op.cmd = DOM0_SETDOMAININFO;
   37.41 +    launch_op.cmd = DOM0_SETVCPUCONTEXT;
   37.42      rc = do_dom0_op(xc_handle, &launch_op);
   37.43      return rc;
   37.44  
    38.1 --- a/tools/libxc/xc_linux_build.c	Mon Jan 09 11:19:55 2006 +0000
    38.2 +++ b/tools/libxc/xc_linux_build.c	Mon Jan 09 11:22:17 2006 +0000
    38.3 @@ -393,10 +393,14 @@ static int setup_guest(int xc_handle,
    38.4      start_info->store_evtchn = store_evtchn;
    38.5      start_info->console_mfn   = nr_pages - 1;
    38.6      start_info->console_evtchn = console_evtchn;
    38.7 +    start_info->nr_pages       = nr_pages;	// FIXME?: nr_pages - 2 ????
    38.8      if ( initrd_len != 0 )
    38.9      {
   38.10          ctxt->initrd.start    = vinitrd_start;
   38.11          ctxt->initrd.size     = initrd_len;
   38.12 +    } else {
   38.13 +        ctxt->initrd.start    = 0;
   38.14 +        ctxt->initrd.size     = 0;
   38.15      }
   38.16      strncpy((char *)ctxt->cmdline, cmdline, IA64_COMMAND_LINE_SIZE);
   38.17      ctxt->cmdline[IA64_COMMAND_LINE_SIZE-1] = '\0';
   38.18 @@ -790,7 +794,7 @@ int xc_linux_build(int xc_handle,
   38.19          goto error_out;
   38.20      }
   38.21  
   38.22 -    if ( xc_domain_get_vcpu_context(xc_handle, domid, 0, ctxt) )
   38.23 +    if ( xc_vcpu_getcontext(xc_handle, domid, 0, ctxt) )
   38.24      {
   38.25          PERROR("Could not get vcpu context");
   38.26          goto error_out;
   38.27 @@ -893,11 +897,11 @@ int xc_linux_build(int xc_handle,
   38.28  
   38.29      memset( &launch_op, 0, sizeof(launch_op) );
   38.30  
   38.31 -    launch_op.u.setdomaininfo.domain = (domid_t)domid;
   38.32 -    launch_op.u.setdomaininfo.vcpu   = 0;
   38.33 -    launch_op.u.setdomaininfo.ctxt   = ctxt;
   38.34 +    launch_op.u.setvcpucontext.domain = (domid_t)domid;
   38.35 +    launch_op.u.setvcpucontext.vcpu   = 0;
   38.36 +    launch_op.u.setvcpucontext.ctxt   = ctxt;
   38.37  
   38.38 -    launch_op.cmd = DOM0_SETDOMAININFO;
   38.39 +    launch_op.cmd = DOM0_SETVCPUCONTEXT;
   38.40      rc = xc_dom0_op(xc_handle, &launch_op);
   38.41      
   38.42      return rc;
    39.1 --- a/tools/libxc/xc_linux_restore.c	Mon Jan 09 11:19:55 2006 +0000
    39.2 +++ b/tools/libxc/xc_linux_restore.c	Mon Jan 09 11:22:17 2006 +0000
    39.3 @@ -171,7 +171,7 @@ int xc_linux_restore(int xc_handle, int 
    39.4  
    39.5  
    39.6      /* Only have to worry about vcpu 0 even for SMP */
    39.7 -    if (xc_domain_get_vcpu_context( xc_handle, dom, 0, &ctxt)) {
    39.8 +    if (xc_vcpu_getcontext( xc_handle, dom, 0, &ctxt)) {
    39.9          ERR("Could not get vcpu context");
   39.10          goto out;
   39.11      }
   39.12 @@ -735,10 +735,10 @@ int xc_linux_restore(int xc_handle, int 
   39.13  
   39.14      DPRINTF("Domain ready to be built.\n");
   39.15  
   39.16 -    op.cmd = DOM0_SETDOMAININFO;
   39.17 -    op.u.setdomaininfo.domain = (domid_t)dom;
   39.18 -    op.u.setdomaininfo.vcpu   = 0;
   39.19 -    op.u.setdomaininfo.ctxt   = &ctxt;
   39.20 +    op.cmd = DOM0_SETVCPUCONTEXT;
   39.21 +    op.u.setvcpucontext.domain = (domid_t)dom;
   39.22 +    op.u.setvcpucontext.vcpu   = 0;
   39.23 +    op.u.setvcpucontext.ctxt   = &ctxt;
   39.24      rc = xc_dom0_op(xc_handle, &op);
   39.25  
   39.26      if (rc != 0) {
    40.1 --- a/tools/libxc/xc_linux_save.c	Mon Jan 09 11:19:55 2006 +0000
    40.2 +++ b/tools/libxc/xc_linux_save.c	Mon Jan 09 11:22:17 2006 +0000
    40.3 @@ -382,7 +382,7 @@ static int suspend_and_state(int xc_hand
    40.4          return -1;
    40.5      }
    40.6  
    40.7 -    if ( xc_domain_get_vcpu_context(xc_handle, dom, 0 /* XXX */, ctxt)) 
    40.8 +    if ( xc_vcpu_getcontext(xc_handle, dom, 0 /* XXX */, ctxt)) 
    40.9          ERR("Could not get vcpu context");
   40.10  
   40.11  
   40.12 @@ -643,7 +643,7 @@ int xc_linux_save(int xc_handle, int io_
   40.13      }
   40.14      
   40.15      /* Only have to worry about vcpu 0 even for SMP */
   40.16 -    if (xc_domain_get_vcpu_context(xc_handle, dom, 0, &ctxt)) {
   40.17 +    if (xc_vcpu_getcontext(xc_handle, dom, 0, &ctxt)) {
   40.18          ERR("Could not get vcpu context");
   40.19          goto out;
   40.20      }
    41.1 --- a/tools/libxc/xc_pagetab.c	Mon Jan 09 11:19:55 2006 +0000
    41.2 +++ b/tools/libxc/xc_pagetab.c	Mon Jan 09 11:22:17 2006 +0000
    41.3 @@ -74,7 +74,7 @@ unsigned long xc_translate_foreign_addre
    41.4  #define pt_levels 4
    41.5  #endif
    41.6  
    41.7 -    if (xc_domain_get_vcpu_context(xc_handle, dom, vcpu, &ctx) != 0) {
    41.8 +    if (xc_vcpu_getcontext(xc_handle, dom, vcpu, &ctx) != 0) {
    41.9          fprintf(stderr, "failed to retreive vcpu context\n");
   41.10          goto out;
   41.11      }
    42.1 --- a/tools/libxc/xc_ptrace.c	Mon Jan 09 11:19:55 2006 +0000
    42.2 +++ b/tools/libxc/xc_ptrace.c	Mon Jan 09 11:22:17 2006 +0000
    42.3 @@ -33,7 +33,7 @@ fetch_regs(int xc_handle, int cpu, int *
    42.4      if (online)
    42.5          *online = 0;
    42.6      if ( !(regs_valid & (1 << cpu)) ) { 
    42.7 -        retval = xc_domain_get_vcpu_context(xc_handle, current_domid, 
    42.8 +        retval = xc_vcpu_getcontext(xc_handle, current_domid, 
    42.9  						cpu, &ctxt[cpu]);
   42.10          if ( retval ) 
   42.11              goto done;
   42.12 @@ -43,8 +43,7 @@ fetch_regs(int xc_handle, int cpu, int *
   42.13  	if ( online == NULL )
   42.14  	    goto done;
   42.15  
   42.16 -	retval = xc_domain_get_vcpu_info(xc_handle, current_domid,
   42.17 -					 cpu, &info);
   42.18 +	retval = xc_vcpu_getinfo(xc_handle, current_domid, cpu, &info);
   42.19  	*online = info.online;
   42.20      
   42.21   done:
   42.22 @@ -395,7 +394,7 @@ xc_ptrace(
   42.23  
   42.24      case PTRACE_SETREGS:
   42.25          SET_XC_REGS(((struct gdb_regs *)data), ctxt[cpu].user_regs);
   42.26 -        retval = xc_domain_setinfo(xc_handle, current_domid, cpu, &ctxt[cpu]);
   42.27 +        retval = xc_vcpu_setcontext(xc_handle, current_domid, cpu, &ctxt[cpu]);
   42.28          if (retval)
   42.29              goto error_out;
   42.30          break;
   42.31 @@ -405,7 +404,7 @@ xc_ptrace(
   42.32           *  during single-stepping - but that just seems retarded
   42.33           */
   42.34          ctxt[cpu].user_regs.eflags |= PSL_T; 
   42.35 -        retval = xc_domain_setinfo(xc_handle, current_domid, cpu, &ctxt[cpu]);
   42.36 +        retval = xc_vcpu_setcontext(xc_handle, current_domid, cpu, &ctxt[cpu]);
   42.37          if ( retval )
   42.38          {
   42.39              perror("dom0 op failed");
   42.40 @@ -423,8 +422,8 @@ xc_ptrace(
   42.41                  /* Clear trace flag */
   42.42                  if ( ctxt[cpu].user_regs.eflags & PSL_T ) {
   42.43                      ctxt[cpu].user_regs.eflags &= ~PSL_T;
   42.44 -                    retval = xc_domain_setinfo(xc_handle, current_domid, 
   42.45 -                                               cpu, &ctxt[cpu]);
   42.46 +                    retval = xc_vcpu_setcontext(xc_handle, current_domid, 
   42.47 +                                                cpu, &ctxt[cpu]);
   42.48                      if ( retval ) {
   42.49                          perror("dom0 op failed");
   42.50                          goto error_out;
    43.1 --- a/tools/libxc/xc_vmx_build.c	Mon Jan 09 11:19:55 2006 +0000
    43.2 +++ b/tools/libxc/xc_vmx_build.c	Mon Jan 09 11:22:17 2006 +0000
    43.3 @@ -9,7 +9,8 @@
    43.4  #include <stdlib.h>
    43.5  #include <unistd.h>
    43.6  #include <zlib.h>
    43.7 -#include <xen/io/ioreq.h>
    43.8 +#include <xen/hvm/hvm_info_table.h>
    43.9 +#include <xen/hvm/ioreq.h>
   43.10  
   43.11  #define VMX_LOADER_ENTR_ADDR  0x00100000
   43.12  
   43.13 @@ -33,9 +34,6 @@
   43.14  #define E820_MAP_NR_OFFSET  0x000001E8
   43.15  #define E820_MAP_OFFSET     0x000002D0
   43.16  
   43.17 -#define VCPU_NR_PAGE        0x0009F000
   43.18 -#define VCPU_NR_OFFSET      0x00000800
   43.19 -
   43.20  struct e820entry {
   43.21      uint64_t addr;
   43.22      uint64_t size;
   43.23 @@ -119,26 +117,50 @@ static unsigned char build_e820map(void 
   43.24      return (*(((unsigned char *)e820_page) + E820_MAP_NR_OFFSET) = nr_map);
   43.25  }
   43.26  
   43.27 +static void
   43.28 +set_hvm_info_checksum(struct hvm_info_table *t)
   43.29 +{
   43.30 +    uint8_t *ptr = (uint8_t *)t, sum = 0;
   43.31 +    unsigned int i;
   43.32 +
   43.33 +    t->checksum = 0;
   43.34 +
   43.35 +    for (i = 0; i < t->length; i++)
   43.36 +        sum += *ptr++;
   43.37 +
   43.38 +    t->checksum = -sum;
   43.39 +}
   43.40 +
   43.41  /*
   43.42 - * Use E820 reserved memory 0x9F800 to pass number of vcpus to vmxloader
   43.43 - * vmxloader will use it to config ACPI MADT table
   43.44 + * Use E820 reserved memory 0x9F800 to pass HVM info to vmxloader
   43.45 + * vmxloader will use this info to set BIOS accordingly
   43.46   */
   43.47 -#define VCPU_MAGIC      0x76637075  /* "vcpu" */
   43.48 -static int set_vcpu_nr(int xc_handle, uint32_t dom,
   43.49 -                        unsigned long *pfn_list, unsigned int vcpus)
   43.50 +static int set_hvm_info(int xc_handle, uint32_t dom,
   43.51 +                        unsigned long *pfn_list, unsigned int vcpus,
   43.52 +                        unsigned int acpi, unsigned int apic)
   43.53  {
   43.54 -    char         *va_map;
   43.55 -    unsigned int *va_vcpus;
   43.56 +    char *va_map;
   43.57 +    struct hvm_info_table *va_hvm;
   43.58  
   43.59 -    va_map = xc_map_foreign_range(xc_handle, dom,
   43.60 -                                  PAGE_SIZE, PROT_READ|PROT_WRITE,
   43.61 -                                  pfn_list[VCPU_NR_PAGE >> PAGE_SHIFT]);
   43.62 +    va_map = xc_map_foreign_range(
   43.63 +        xc_handle,
   43.64 +        dom,
   43.65 +        PAGE_SIZE,
   43.66 +        PROT_READ|PROT_WRITE,
   43.67 +        pfn_list[HVM_INFO_PFN]);
   43.68 +    
   43.69      if ( va_map == NULL )
   43.70          return -1;
   43.71  
   43.72 -    va_vcpus = (unsigned int *)(va_map + VCPU_NR_OFFSET);
   43.73 -    va_vcpus[0] = VCPU_MAGIC;
   43.74 -    va_vcpus[1] = vcpus;
   43.75 +    va_hvm = (struct hvm_info_table *)(va_map + HVM_INFO_OFFSET);
   43.76 +    memset(va_hvm, 0, sizeof(*va_hvm));
   43.77 +    strncpy(va_hvm->signature, "HVM INFO", 8);
   43.78 +    va_hvm->length       = sizeof(struct hvm_info_table);
   43.79 +    va_hvm->acpi_enabled = acpi;
   43.80 +    va_hvm->apic_enabled = apic;
   43.81 +    va_hvm->nr_vcpus     = vcpus;
   43.82 +
   43.83 +    set_hvm_info_checksum(va_hvm);
   43.84  
   43.85      munmap(va_map, PAGE_SIZE);
   43.86  
   43.87 @@ -279,8 +301,9 @@ static int setup_guest(int xc_handle,
   43.88                         vcpu_guest_context_t *ctxt,
   43.89                         unsigned long shared_info_frame,
   43.90                         unsigned int control_evtchn,
   43.91 -                       unsigned int lapic,
   43.92                         unsigned int vcpus,
   43.93 +                       unsigned int acpi,
   43.94 +                       unsigned int apic,
   43.95                         unsigned int store_evtchn,
   43.96                         unsigned long *store_mfn)
   43.97  {
   43.98 @@ -490,20 +513,14 @@ static int setup_guest(int xc_handle,
   43.99              goto error_out;
  43.100      }
  43.101  
  43.102 -    if (set_vcpu_nr(xc_handle, dom, page_array, vcpus)) {
  43.103 -        fprintf(stderr, "Couldn't set vcpu number for VMX guest.\n");
  43.104 +    if ( set_hvm_info(xc_handle, dom, page_array, vcpus, acpi, apic) ) {
  43.105 +        fprintf(stderr, "Couldn't set hvm info for VMX guest.\n");
  43.106          goto error_out;
  43.107      }
  43.108  
  43.109 -    *store_mfn = page_array[(v_end-2) >> PAGE_SHIFT];
  43.110 -    if ( xc_clear_domain_page(xc_handle, dom, *store_mfn) )
  43.111 -        goto error_out;
  43.112 -
  43.113 -    shared_page_frame = (v_end - PAGE_SIZE) >> PAGE_SHIFT;
  43.114 -
  43.115 -    if ((e820_page = xc_map_foreign_range(
  43.116 -        xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
  43.117 -        page_array[E820_MAP_PAGE >> PAGE_SHIFT])) == 0)
  43.118 +    if ( (e820_page = xc_map_foreign_range(
  43.119 +         xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
  43.120 +         page_array[E820_MAP_PAGE >> PAGE_SHIFT])) == 0 )
  43.121          goto error_out;
  43.122      memset(e820_page, 0, PAGE_SIZE);
  43.123      e820_map_nr = build_e820map(e820_page, v_end);
  43.124 @@ -518,26 +535,30 @@ static int setup_guest(int xc_handle,
  43.125      munmap(e820_page, PAGE_SIZE);
  43.126  
  43.127      /* shared_info page starts its life empty. */
  43.128 -    if ((shared_info = xc_map_foreign_range(
  43.129 -        xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
  43.130 -        shared_info_frame)) == 0)
  43.131 +    if ( (shared_info = xc_map_foreign_range(
  43.132 +         xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
  43.133 +         shared_info_frame)) == 0 )
  43.134          goto error_out;
  43.135      memset(shared_info, 0, sizeof(shared_info_t));
  43.136      /* Mask all upcalls... */
  43.137      for ( i = 0; i < MAX_VIRT_CPUS; i++ )
  43.138          shared_info->vcpu_info[i].evtchn_upcall_mask = 1;
  43.139 -
  43.140      munmap(shared_info, PAGE_SIZE);
  43.141  
  43.142      /* Populate the event channel port in the shared page */
  43.143 -    if ((sp = (shared_iopage_t *) xc_map_foreign_range(
  43.144 -        xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
  43.145 -        page_array[shared_page_frame])) == 0)
  43.146 +    shared_page_frame = page_array[(v_end >> PAGE_SHIFT) - 1];
  43.147 +    if ( (sp = (shared_iopage_t *) xc_map_foreign_range(
  43.148 +         xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
  43.149 +         shared_page_frame)) == 0 )
  43.150          goto error_out;
  43.151      memset(sp, 0, PAGE_SIZE);
  43.152      sp->sp_global.eport = control_evtchn;
  43.153      munmap(sp, PAGE_SIZE);
  43.154  
  43.155 +    *store_mfn = page_array[(v_end >> PAGE_SHIFT) - 2];
  43.156 +    if ( xc_clear_domain_page(xc_handle, dom, *store_mfn) )
  43.157 +        goto error_out;
  43.158 +
  43.159      /* Send the page update requests down to the hypervisor. */
  43.160      if ( xc_finish_mmu_updates(xc_handle, mmu) )
  43.161          goto error_out;
  43.162 @@ -559,7 +580,7 @@ static int setup_guest(int xc_handle,
  43.163      ctxt->user_regs.eax = 0;
  43.164      ctxt->user_regs.esp = 0;
  43.165      ctxt->user_regs.ebx = 0; /* startup_32 expects this to be 0 to signal boot cpu */
  43.166 -    ctxt->user_regs.ecx = lapic;
  43.167 +    ctxt->user_regs.ecx = 0;
  43.168      ctxt->user_regs.esi = 0;
  43.169      ctxt->user_regs.edi = 0;
  43.170      ctxt->user_regs.ebp = 0;
  43.171 @@ -574,36 +595,14 @@ static int setup_guest(int xc_handle,
  43.172      return -1;
  43.173  }
  43.174  
  43.175 -#define VMX_FEATURE_FLAG 0x20
  43.176 -
  43.177 -static int vmx_identify(void)
  43.178 -{
  43.179 -    int eax, ecx;
  43.180 -
  43.181 -    __asm__ __volatile__ (
  43.182 -#if defined(__i386__)
  43.183 -                          "push %%ebx; cpuid; pop %%ebx"
  43.184 -#elif defined(__x86_64__)
  43.185 -                          "push %%rbx; cpuid; pop %%rbx"
  43.186 -#endif
  43.187 -                          : "=a" (eax), "=c" (ecx)
  43.188 -                          : "0" (1)
  43.189 -                          : "dx");
  43.190 -
  43.191 -    if (!(ecx & VMX_FEATURE_FLAG)) {
  43.192 -        return -1;
  43.193 -    }
  43.194 -
  43.195 -    return 0;
  43.196 -}
  43.197 -
  43.198  int xc_vmx_build(int xc_handle,
  43.199                   uint32_t domid,
  43.200                   int memsize,
  43.201                   const char *image_name,
  43.202                   unsigned int control_evtchn,
  43.203 -                 unsigned int lapic,
  43.204                   unsigned int vcpus,
  43.205 +                 unsigned int acpi,
  43.206 +                 unsigned int apic,
  43.207                   unsigned int store_evtchn,
  43.208                   unsigned long *store_mfn)
  43.209  {
  43.210 @@ -613,10 +612,18 @@ int xc_vmx_build(int xc_handle,
  43.211      unsigned long nr_pages;
  43.212      char         *image = NULL;
  43.213      unsigned long image_size;
  43.214 +    xen_capabilities_info_t xen_caps;
  43.215  
  43.216 -    if ( vmx_identify() < 0 )
  43.217 +    if ( (rc = xc_version(xc_handle, XENVER_capabilities, &xen_caps)) != 0 )
  43.218      {
  43.219 -        PERROR("CPU doesn't support VMX Extensions");
  43.220 +        PERROR("Failed to get xen version info");
  43.221 +        goto error_out;
  43.222 +    }
  43.223 +
  43.224 +    if ( !strstr(xen_caps, "hvm") )
  43.225 +    {
  43.226 +        PERROR("CPU doesn't support VMX Extensions or "
  43.227 +               "CPU VMX Extensions are not turned on");
  43.228          goto error_out;
  43.229      }
  43.230  
  43.231 @@ -644,7 +651,7 @@ int xc_vmx_build(int xc_handle,
  43.232          goto error_out;
  43.233      }
  43.234  
  43.235 -    if ( xc_domain_get_vcpu_context(xc_handle, domid, 0, ctxt) )
  43.236 +    if ( xc_vcpu_getcontext(xc_handle, domid, 0, ctxt) )
  43.237      {
  43.238          PERROR("Could not get vcpu context");
  43.239          goto error_out;
  43.240 @@ -659,7 +666,7 @@ int xc_vmx_build(int xc_handle,
  43.241  
  43.242      if ( setup_guest(xc_handle, domid, memsize, image, image_size, nr_pages,
  43.243                       ctxt, op.u.getdomaininfo.shared_info_frame, control_evtchn,
  43.244 -                     lapic, vcpus, store_evtchn, store_mfn) < 0)
  43.245 +                     vcpus, acpi, apic, store_evtchn, store_mfn) < 0)
  43.246      {
  43.247          ERROR("Error constructing guest OS");
  43.248          goto error_out;
  43.249 @@ -701,11 +708,11 @@ int xc_vmx_build(int xc_handle,
  43.250  
  43.251      memset( &launch_op, 0, sizeof(launch_op) );
  43.252  
  43.253 -    launch_op.u.setdomaininfo.domain = (domid_t)domid;
  43.254 -    launch_op.u.setdomaininfo.vcpu   = 0;
  43.255 -    launch_op.u.setdomaininfo.ctxt   = ctxt;
  43.256 +    launch_op.u.setvcpucontext.domain = (domid_t)domid;
  43.257 +    launch_op.u.setvcpucontext.vcpu   = 0;
  43.258 +    launch_op.u.setvcpucontext.ctxt   = ctxt;
  43.259  
  43.260 -    launch_op.cmd = DOM0_SETDOMAININFO;
  43.261 +    launch_op.cmd = DOM0_SETVCPUCONTEXT;
  43.262      rc = xc_dom0_op(xc_handle, &launch_op);
  43.263  
  43.264      return rc;
    44.1 --- a/tools/libxc/xenctrl.h	Mon Jan 09 11:19:55 2006 +0000
    44.2 +++ b/tools/libxc/xenctrl.h	Mon Jan 09 11:22:17 2006 +0000
    44.3 @@ -181,10 +181,11 @@ int xc_domain_unpause(int xc_handle,
    44.4   */
    44.5  int xc_domain_destroy(int xc_handle, 
    44.6                        uint32_t domid);
    44.7 -int xc_domain_pincpu(int xc_handle,
    44.8 -                     uint32_t domid,
    44.9 -                     int vcpu,
   44.10 -                     cpumap_t cpumap);
   44.11 +
   44.12 +int xc_vcpu_setaffinity(int xc_handle,
   44.13 +                        uint32_t domid,
   44.14 +                        int vcpu,
   44.15 +                        cpumap_t cpumap);
   44.16  
   44.17  /**
   44.18   * This function will return information about one or more domains. It is
   44.19 @@ -208,7 +209,7 @@ int xc_domain_getinfo(int xc_handle,
   44.20  
   44.21  
   44.22  /**
   44.23 - * This function will set the vcpu context for the specified domain.
   44.24 + * This function will set the execution context for the specified vcpu.
   44.25   *
   44.26   * @parm xc_handle a handle to an open hypervisor interface
   44.27   * @parm domid the domain to set the vcpu context for
   44.28 @@ -216,10 +217,10 @@ int xc_domain_getinfo(int xc_handle,
   44.29   * @parm ctxt pointer to the the cpu context with the values to set
   44.30   * @return the number of domains enumerated or -1 on error
   44.31   */
   44.32 -int xc_domain_setinfo(int xc_handle,
   44.33 -                      uint32_t domid,
   44.34 -                      uint32_t vcpu,
   44.35 -                      vcpu_guest_context_t *ctxt);
   44.36 +int xc_vcpu_setcontext(int xc_handle,
   44.37 +                       uint32_t domid,
   44.38 +                       uint32_t vcpu,
   44.39 +                       vcpu_guest_context_t *ctxt);
   44.40  /**
   44.41   * This function will return information about one or more domains, using a
   44.42   * single hypercall.  The domain information will be stored into the supplied
   44.43 @@ -249,17 +250,16 @@ int xc_domain_getinfolist(int xc_handle,
   44.44   *            domain
   44.45   * @return 0 on success, -1 on failure
   44.46   */
   44.47 -int xc_domain_get_vcpu_context(int xc_handle,
   44.48 +int xc_vcpu_getcontext(int xc_handle,
   44.49                                 uint32_t domid,
   44.50                                 uint32_t vcpu,
   44.51                                 vcpu_guest_context_t *ctxt);
   44.52  
   44.53  typedef dom0_getvcpuinfo_t xc_vcpuinfo_t;
   44.54 -int xc_domain_get_vcpu_info(int xc_handle,
   44.55 -                            uint32_t domid,
   44.56 -                            uint32_t vcpu,
   44.57 -                            xc_vcpuinfo_t *info);
   44.58 -
   44.59 +int xc_vcpu_getinfo(int xc_handle,
   44.60 +                    uint32_t domid,
   44.61 +                    uint32_t vcpu,
   44.62 +                    xc_vcpuinfo_t *info);
   44.63  
   44.64  int xc_domain_setcpuweight(int xc_handle,
   44.65                             uint32_t domid,
   44.66 @@ -380,6 +380,17 @@ int xc_domain_ioport_permission(int xc_h
   44.67                                  uint32_t nr_ports,
   44.68                                  uint32_t allow_access);
   44.69  
   44.70 +int xc_domain_irq_permission(int xc_handle,
   44.71 +                             uint32_t domid,
   44.72 +                             uint8_t pirq,
   44.73 +                             uint8_t allow_access);
   44.74 +
   44.75 +int xc_domain_iomem_permission(int xc_handle,
   44.76 +                               uint32_t domid,
   44.77 +                               unsigned long first_pfn,
   44.78 +                               unsigned long nr_pfns,
   44.79 +                               uint8_t allow_access);
   44.80 +
   44.81  unsigned long xc_make_page_below_4G(int xc_handle, uint32_t domid, 
   44.82  				    unsigned long mfn);
   44.83  
    45.1 --- a/tools/libxc/xenguest.h	Mon Jan 09 11:19:55 2006 +0000
    45.2 +++ b/tools/libxc/xenguest.h	Mon Jan 09 11:22:17 2006 +0000
    45.3 @@ -56,8 +56,9 @@ int xc_vmx_build(int xc_handle,
    45.4                   int memsize,
    45.5                   const char *image_name,
    45.6                   unsigned int control_evtchn,
    45.7 -                 unsigned int lapic,
    45.8                   unsigned int vcpus,
    45.9 +                 unsigned int acpi,
   45.10 +                 unsigned int apic,
   45.11                   unsigned int store_evtchn,
   45.12                   unsigned long *store_mfn);
   45.13  
    46.1 --- a/tools/python/xen/lowlevel/xc/xc.c	Mon Jan 09 11:19:55 2006 +0000
    46.2 +++ b/tools/python/xen/lowlevel/xc/xc.c	Mon Jan 09 11:22:17 2006 +0000
    46.3 @@ -135,9 +135,9 @@ static PyObject *pyxc_domain_destroy(XcO
    46.4  }
    46.5  
    46.6  
    46.7 -static PyObject *pyxc_domain_pincpu(XcObject *self,
    46.8 -                                    PyObject *args,
    46.9 -                                    PyObject *kwds)
   46.10 +static PyObject *pyxc_vcpu_setaffinity(XcObject *self,
   46.11 +                                       PyObject *args,
   46.12 +                                       PyObject *kwds)
   46.13  {
   46.14      uint32_t dom;
   46.15      int vcpu = 0, i;
   46.16 @@ -157,7 +157,7 @@ static PyObject *pyxc_domain_pincpu(XcOb
   46.17              cpumap |= (cpumap_t)1 << PyInt_AsLong(PyList_GetItem(cpulist, i));
   46.18      }
   46.19    
   46.20 -    if ( xc_domain_pincpu(self->xc_handle, dom, vcpu, cpumap) != 0 )
   46.21 +    if ( xc_vcpu_setaffinity(self->xc_handle, dom, vcpu, cpumap) != 0 )
   46.22          return PyErr_SetFromErrno(xc_error);
   46.23      
   46.24      Py_INCREF(zero);
   46.25 @@ -297,7 +297,7 @@ static PyObject *pyxc_vcpu_getinfo(XcObj
   46.26                                        &dom, &vcpu) )
   46.27          return NULL;
   46.28  
   46.29 -    rc = xc_domain_get_vcpu_info(self->xc_handle, dom, vcpu, &info);
   46.30 +    rc = xc_vcpu_getinfo(self->xc_handle, dom, vcpu, &info);
   46.31      if ( rc < 0 )
   46.32          return PyErr_SetFromErrno(xc_error);
   46.33  
   46.34 @@ -362,21 +362,23 @@ static PyObject *pyxc_vmx_build(XcObject
   46.35      uint32_t dom;
   46.36      char *image;
   46.37      int control_evtchn, store_evtchn;
   46.38 +    int memsize;
   46.39      int vcpus = 1;
   46.40 -    int lapic = 0;
   46.41 -    int memsize;
   46.42 +    int acpi = 0;
   46.43 +    int apic = 0;
   46.44      unsigned long store_mfn = 0;
   46.45  
   46.46      static char *kwd_list[] = { "dom", "control_evtchn", "store_evtchn",
   46.47 -                                "memsize", "image", "lapic", "vcpus", NULL };
   46.48 +                                "memsize", "image", "vcpus", "acpi", "apic",
   46.49 +                                NULL };
   46.50  
   46.51 -    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiisii", kwd_list,
   46.52 +    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiisiii", kwd_list,
   46.53                                        &dom, &control_evtchn, &store_evtchn,
   46.54 -                                      &memsize, &image, &lapic, &vcpus) )
   46.55 +                                      &memsize, &image, &vcpus, &acpi, &apic) )
   46.56          return NULL;
   46.57  
   46.58      if ( xc_vmx_build(self->xc_handle, dom, memsize, image, control_evtchn,
   46.59 -                      lapic, vcpus, store_evtchn, &store_mfn) != 0 )
   46.60 +                      vcpus, acpi, apic, store_evtchn, &store_mfn) != 0 )
   46.61          return PyErr_SetFromErrno(xc_error);
   46.62  
   46.63      return Py_BuildValue("{s:i}", "store_mfn", store_mfn);
   46.64 @@ -774,6 +776,52 @@ static PyObject *pyxc_domain_ioport_perm
   46.65      return zero;
   46.66  }
   46.67  
   46.68 +static PyObject *pyxc_domain_irq_permission(PyObject *self,
   46.69 +                                            PyObject *args,
   46.70 +                                            PyObject *kwds)
   46.71 +{
   46.72 +    XcObject *xc = (XcObject *)self;
   46.73 +    uint32_t dom;
   46.74 +    int pirq, allow_access, ret;
   46.75 +
   46.76 +    static char *kwd_list[] = { "dom", "pirq", "allow_access", NULL };
   46.77 +
   46.78 +    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iii", kwd_list, 
   46.79 +                                      &dom, &pirq, &allow_access) )
   46.80 +        return NULL;
   46.81 +
   46.82 +    ret = xc_domain_irq_permission(
   46.83 +        xc->xc_handle, dom, pirq, allow_access);
   46.84 +    if ( ret != 0 )
   46.85 +        return PyErr_SetFromErrno(xc_error);
   46.86 +
   46.87 +    Py_INCREF(zero);
   46.88 +    return zero;
   46.89 +}
   46.90 +
   46.91 +static PyObject *pyxc_domain_iomem_permission(PyObject *self,
   46.92 +                                               PyObject *args,
   46.93 +                                               PyObject *kwds)
   46.94 +{
   46.95 +    XcObject *xc = (XcObject *)self;
   46.96 +    uint32_t dom;
   46.97 +    unsigned long first_pfn, nr_pfns, allow_access, ret;
   46.98 +
   46.99 +    static char *kwd_list[] = { "dom", "first_pfn", "nr_pfns", "allow_access", NULL };
  46.100 +
  46.101 +    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "illi", kwd_list, 
  46.102 +                                      &dom, &first_pfn, &nr_pfns, &allow_access) )
  46.103 +        return NULL;
  46.104 +
  46.105 +    ret = xc_domain_iomem_permission(
  46.106 +        xc->xc_handle, dom, first_pfn, nr_pfns, allow_access);
  46.107 +    if ( ret != 0 )
  46.108 +        return PyErr_SetFromErrno(xc_error);
  46.109 +
  46.110 +    Py_INCREF(zero);
  46.111 +    return zero;
  46.112 +}
  46.113 +
  46.114  
  46.115  static PyObject *dom_op(XcObject *self, PyObject *args,
  46.116                          int (*fn)(int, uint32_t))
  46.117 @@ -842,8 +890,8 @@ static PyMethodDef pyxc_methods[] = {
  46.118        " dom [int]:    Identifier of domain to be destroyed.\n\n"
  46.119        "Returns: [int] 0 on success; -1 on error.\n" },
  46.120  
  46.121 -    { "domain_pincpu", 
  46.122 -      (PyCFunction)pyxc_domain_pincpu, 
  46.123 +    { "vcpu_setaffinity", 
  46.124 +      (PyCFunction)pyxc_vcpu_setaffinity, 
  46.125        METH_VARARGS | METH_KEYWORDS, "\n"
  46.126        "Pin a VCPU to a specified set CPUs.\n"
  46.127        " dom [int]:     Identifier of domain to which VCPU belongs.\n"
  46.128 @@ -1070,6 +1118,25 @@ static PyMethodDef pyxc_methods[] = {
  46.129        " allow_access [int]: Non-zero means enable access; else disable access\n\n"
  46.130        "Returns: [int] 0 on success; -1 on error.\n" },
  46.131  
  46.132 +    { "domain_irq_permission",
  46.133 +      (PyCFunction)pyxc_domain_irq_permission,
  46.134 +      METH_VARARGS | METH_KEYWORDS, "\n"
  46.135 +      "Allow a domain access to a physical IRQ\n"
  46.136 +      " dom          [int]: Identifier of domain to be allowed access.\n"
  46.137 +      " pirq         [int]: The Physical IRQ\n"
  46.138 +      " allow_access [int]: Non-zero means enable access; else disable access\n\n"
  46.139 +      "Returns: [int] 0 on success; -1 on error.\n" },
  46.140 +
  46.141 +    { "domain_iomem_permission",
  46.142 +      (PyCFunction)pyxc_domain_iomem_permission,
  46.143 +      METH_VARARGS | METH_KEYWORDS, "\n"
  46.144 +      "Allow a domain access to a range of IO memory pages\n"
  46.145 +      " dom          [int]: Identifier of domain to be allowed access.\n"
  46.146 +      " first_pfn   [long]: First page of I/O Memory\n"
  46.147 +      " nr_pfns     [long]: Number of pages of I/O Memory (>0)\n"
  46.148 +      " allow_access [int]: Non-zero means enable access; else disable access\n\n"
  46.149 +      "Returns: [int] 0 on success; -1 on error.\n" },
  46.150 +
  46.151      { "pages_to_kib",
  46.152        (PyCFunction)pyxc_pages_to_kib,
  46.153        METH_VARARGS, "\n"
    47.1 --- a/tools/python/xen/xend/XendDomain.py	Mon Jan 09 11:19:55 2006 +0000
    47.2 +++ b/tools/python/xen/xend/XendDomain.py	Mon Jan 09 11:22:17 2006 +0000
    47.3 @@ -443,7 +443,7 @@ class XendDomain:
    47.4          cpumap = map(lambda x: int(x),
    47.5                       cpumap.replace("[", "").replace("]", "").split(","))
    47.6          try:
    47.7 -            return xc.domain_pincpu(dominfo.getDomid(), vcpu, cpumap)
    47.8 +            return xc.vcpu_setaffinity(dominfo.getDomid(), vcpu, cpumap)
    47.9          except Exception, ex:
   47.10              raise XendError(str(ex))
   47.11  
    48.1 --- a/tools/python/xen/xend/XendDomainInfo.py	Mon Jan 09 11:19:55 2006 +0000
    48.2 +++ b/tools/python/xen/xend/XendDomainInfo.py	Mon Jan 09 11:22:17 2006 +0000
    48.3 @@ -1179,7 +1179,7 @@ class XendDomainInfo:
    48.4                  for v in range(0, self.info['max_vcpu_id']+1):
    48.5                      # pincpu takes a list of ints
    48.6                      cpu = [ int( cpus[v % len(cpus)] ) ]
    48.7 -                    xc.domain_pincpu(self.domid, v, cpu)
    48.8 +                    xc.vcpu_setaffinity(self.domid, v, cpu)
    48.9  
   48.10              m = self.image.getDomainMemory(self.info['memory'] * 1024)
   48.11              balloon.free(m)
    49.1 --- a/tools/python/xen/xend/image.py	Mon Jan 09 11:19:55 2006 +0000
    49.2 +++ b/tools/python/xen/xend/image.py	Mon Jan 09 11:22:17 2006 +0000
    49.3 @@ -189,11 +189,16 @@ class VmxImageHandler(ImageHandler):
    49.4      def configure(self, imageConfig, deviceConfig):
    49.5          ImageHandler.configure(self, imageConfig, deviceConfig)
    49.6  
    49.7 +        info = xc.xeninfo()
    49.8 +        if not 'hvm' in info['xen_caps']:
    49.9 +            raise VmError("vmx: not an Intel VT platform, we stop creating!")
   49.10 +
   49.11          self.dmargs = self.parseDeviceModelArgs(imageConfig, deviceConfig)
   49.12          self.device_model = sxp.child_value(imageConfig, 'device_model')
   49.13          if not self.device_model:
   49.14              raise VmError("vmx: missing device model")
   49.15          self.display = sxp.child_value(imageConfig, 'display')
   49.16 +        self.xauthority = sxp.child_value(imageConfig, 'xauthority')
   49.17  
   49.18          self.vm.storeVm(("image/dmargs", " ".join(self.dmargs)),
   49.19                          ("image/device-model", self.device_model),
   49.20 @@ -204,10 +209,8 @@ class VmxImageHandler(ImageHandler):
   49.21  
   49.22          self.dmargs += self.configVNC(imageConfig)
   49.23  
   49.24 -        self.lapic = 0
   49.25 -        lapic = sxp.child_value(imageConfig, 'lapic')
   49.26 -        if not lapic is None:
   49.27 -            self.lapic = int(lapic)
   49.28 +        self.acpi = int(sxp.child_value(imageConfig, 'acpi', 0))
   49.29 +        self.apic = int(sxp.child_value(imageConfig, 'apic', 0))
   49.30  
   49.31      def buildDomain(self):
   49.32          # Create an event channel
   49.33 @@ -222,17 +225,18 @@ class VmxImageHandler(ImageHandler):
   49.34          log.debug("control_evtchn = %d", self.device_channel)
   49.35          log.debug("store_evtchn   = %d", store_evtchn)
   49.36          log.debug("memsize        = %d", self.vm.getMemoryTarget() / 1024)
   49.37 -        log.debug("lapic          = %d", self.lapic)
   49.38          log.debug("vcpus          = %d", self.vm.getVCpuCount())
   49.39 +        log.debug("acpi           = %d", self.acpi)
   49.40 +        log.debug("apic           = %d", self.apic)
   49.41  
   49.42          return xc.vmx_build(dom            = self.vm.getDomid(),
   49.43                              image          = self.kernel,
   49.44                              control_evtchn = self.device_channel,
   49.45                              store_evtchn   = store_evtchn,
   49.46                              memsize        = self.vm.getMemoryTarget() / 1024,
   49.47 -                            lapic          = self.lapic,
   49.48 -                            vcpus          = self.vm.getVCpuCount())
   49.49 -
   49.50 +                            vcpus          = self.vm.getVCpuCount(),
   49.51 +                            acpi           = self.acpi,
   49.52 +                            apic           = self.apic)
   49.53  
   49.54      # Return a list of cmd line args to the device models based on the
   49.55      # xm config file
   49.56 @@ -264,44 +268,44 @@ class VmxImageHandler(ImageHandler):
   49.57          nics = 0
   49.58          for (name, info) in deviceConfig:
   49.59              if name == 'vbd':
   49.60 -               uname = sxp.child_value(info, 'uname')
   49.61 -               typedev = sxp.child_value(info, 'dev')
   49.62 -               (_, vbdparam) = string.split(uname, ':', 1)
   49.63 -               if re.match('^ioemu:', typedev):
   49.64 -                  (emtype, vbddev) = string.split(typedev, ':', 1)
   49.65 -               else:
   49.66 -                  emtype = 'vbd'
   49.67 -                  vbddev = typedev
   49.68 -               if emtype != 'ioemu':
   49.69 -                  continue;
   49.70 -               vbddev_list = ['hda', 'hdb', 'hdc', 'hdd']
   49.71 -               if vbddev not in vbddev_list:
   49.72 -                  raise VmError("vmx: for qemu vbd type=file&dev=hda~hdd")
   49.73 -               ret.append("-%s" % vbddev)
   49.74 -               ret.append("%s" % vbdparam)
   49.75 +                uname = sxp.child_value(info, 'uname')
   49.76 +                typedev = sxp.child_value(info, 'dev')
   49.77 +                (_, vbdparam) = string.split(uname, ':', 1)
   49.78 +                if 'ioemu:' in typedev:
   49.79 +                    (emtype, vbddev) = string.split(typedev, ':', 1)
   49.80 +                else:
   49.81 +                    emtype = 'vbd'
   49.82 +                    vbddev = typedev
   49.83 +                if emtype == 'vbd':
   49.84 +                    continue;
   49.85 +                vbddev_list = ['hda', 'hdb', 'hdc', 'hdd']
   49.86 +                if vbddev not in vbddev_list:
   49.87 +                    raise VmError("vmx: for qemu vbd type=file&dev=hda~hdd")
   49.88 +                ret.append("-%s" % vbddev)
   49.89 +                ret.append("%s" % vbdparam)
   49.90              if name == 'vif':
   49.91 -               type = sxp.child_value(info, 'type')
   49.92 -               if type != 'ioemu':
   49.93 -                   continue
   49.94 -               nics += 1
   49.95 -               if mac != None:
   49.96 -                   continue
   49.97 -               mac = sxp.child_value(info, 'mac')
   49.98 -               bridge = sxp.child_value(info, 'bridge')
   49.99 -               if mac == None:
  49.100 -                   mac = randomMAC()
  49.101 -               if bridge == None:
  49.102 -                   bridge = 'xenbr0'
  49.103 -               ret.append("-macaddr")
  49.104 -               ret.append("%s" % mac)
  49.105 -               ret.append("-bridge")
  49.106 -               ret.append("%s" % bridge)
  49.107 +                type = sxp.child_value(info, 'type')
  49.108 +                if type != 'ioemu':
  49.109 +                    continue
  49.110 +                nics += 1
  49.111 +                if mac != None:
  49.112 +                    continue
  49.113 +                mac = sxp.child_value(info, 'mac')
  49.114 +                bridge = sxp.child_value(info, 'bridge')
  49.115 +                if mac == None:
  49.116 +                    mac = randomMAC()
  49.117 +                if bridge == None:
  49.118 +                    bridge = 'xenbr0'
  49.119 +                ret.append("-macaddr")
  49.120 +                ret.append("%s" % mac)
  49.121 +                ret.append("-bridge")
  49.122 +                ret.append("%s" % bridge)
  49.123              if name == 'vtpm':
  49.124 -               instance = sxp.child_value(info, 'pref_instance')
  49.125 -               ret.append("-instance")
  49.126 -               ret.append("%s" % instance)
  49.127 +                instance = sxp.child_value(info, 'pref_instance')
  49.128 +                ret.append("-instance")
  49.129 +                ret.append("%s" % instance)
  49.130          ret.append("-nics")
  49.131 -        ret.append("%d" % nics) 
  49.132 +        ret.append("%d" % nics)
  49.133          return ret
  49.134  
  49.135      def configVNC(self, config):
  49.136 @@ -340,6 +344,8 @@ class VmxImageHandler(ImageHandler):
  49.137          env = dict(os.environ)
  49.138          if self.display:
  49.139              env['DISPLAY'] = self.display
  49.140 +        if self.xauthority:
  49.141 +            env['XAUTHORITY'] = self.xauthority
  49.142          log.info("spawning device models: %s %s", self.device_model, args)
  49.143          self.pid = os.spawnve(os.P_NOWAIT, self.device_model, args, env)
  49.144          log.info("device model pid: %d", self.pid)
    50.1 --- a/tools/python/xen/xend/server/blkif.py	Mon Jan 09 11:19:55 2006 +0000
    50.2 +++ b/tools/python/xen/xend/server/blkif.py	Mon Jan 09 11:22:17 2006 +0000
    50.3 @@ -31,7 +31,7 @@ class BlkifController(DevController):
    50.4      """Block device interface controller. Handles all block devices
    50.5      for a domain.
    50.6      """
    50.7 -    
    50.8 +
    50.9      def __init__(self, vm):
   50.10          """Create a block device controller.
   50.11          """
   50.12 @@ -40,9 +40,9 @@ class BlkifController(DevController):
   50.13  
   50.14      def getDeviceDetails(self, config):
   50.15          """@see DevController.getDeviceDetails"""
   50.16 -        
   50.17 +
   50.18          dev = sxp.child_value(config, 'dev')
   50.19 -        if re.match('^ioemu:', dev):
   50.20 +        if 'ioemu:' in dev:
   50.21              return (None,{},{})
   50.22  
   50.23          devid = blkif.blkdev_name_to_number(dev)
    51.1 --- a/tools/python/xen/xm/create.py	Mon Jan 09 11:19:55 2006 +0000
    51.2 +++ b/tools/python/xen/xm/create.py	Mon Jan 09 11:22:17 2006 +0000
    51.3 @@ -160,9 +160,13 @@ gopts.var('cpus', val='CPUS',
    51.4            fn=set_int, default=None,
    51.5            use="CPUS to run the domain on.")
    51.6  
    51.7 -gopts.var('lapic', val='LAPIC',
    51.8 +gopts.var('acpi', val='ACPI',
    51.9            fn=set_int, default=0,
   51.10 -          use="Disable or enable local APIC of VMX domain.")
   51.11 +          use="Disable or enable ACPI of VMX domain.")
   51.12 +
   51.13 +gopts.var('apic', val='APIC',
   51.14 +          fn=set_int, default=0,
   51.15 +          use="Disable or enable APIC of VMX domain.")
   51.16  
   51.17  gopts.var('vcpus', val='VCPUS',
   51.18            fn=set_int, default=1,
   51.19 @@ -388,6 +392,10 @@ gopts.var('display', val='DISPLAY',
   51.20            fn=set_value, default=None,
   51.21            use="X11 display to use")
   51.22  
   51.23 +gopts.var('xauthority', val='XAUTHORITY',
   51.24 +          fn=set_value, default=None,
   51.25 +          use="X11 Authority to use")
   51.26 +
   51.27  
   51.28  def err(msg):
   51.29      """Print an error to stderr and exit.
   51.30 @@ -526,7 +534,8 @@ def configure_vmx(config_image, vals):
   51.31      """
   51.32      args = [ 'device_model', 'vcpus', 'cdrom', 'boot', 'fda', 'fdb',
   51.33               'localtime', 'serial', 'stdvga', 'isa', 'nographic', 'audio',
   51.34 -             'vnc', 'vncviewer', 'sdl', 'display', 'ne2000', 'lapic']
   51.35 +             'vnc', 'vncviewer', 'sdl', 'display', 'ne2000', 'acpi', 'apic',
   51.36 +             'xauthority' ]
   51.37      for a in args:
   51.38          if (vals.__dict__[a]):
   51.39              config_image.append([a, vals.__dict__[a]])
   51.40 @@ -801,6 +810,9 @@ def parseCommandLine(argv):
   51.41      if not gopts.vals.display:
   51.42          gopts.vals.display = os.getenv("DISPLAY")
   51.43  
   51.44 +    if not gopts.vals.xauthority:
   51.45 +        gopts.vals.xauthority = os.getenv("XAUTHORITY")
   51.46 +
   51.47      # Process remaining args as config variables.
   51.48      for arg in args:
   51.49          if '=' in arg:
    52.1 --- a/tools/python/xen/xm/main.py	Mon Jan 09 11:19:55 2006 +0000
    52.2 +++ b/tools/python/xen/xm/main.py	Mon Jan 09 11:22:17 2006 +0000
    52.3 @@ -390,7 +390,6 @@ def xm_brief_list(doms):
    52.4  
    52.5  
    52.6  def xm_vcpu_list(args):
    52.7 -    print 'Name                              ID  VCPU  CPU  State  Time(s)  CPU Affinity'
    52.8  
    52.9      from xen.xend.XendClient import server
   52.10      if args:
   52.11 @@ -401,6 +400,8 @@ def xm_vcpu_list(args):
   52.12              lambda x: server.xend_domain_vcpuinfo(sxp.child_value(x, 'name')),
   52.13              doms)
   52.14  
   52.15 +    print 'Name                              ID  VCPU  CPU  State  Time(s)  CPU Affinity'
   52.16 +
   52.17      for dom in dominfo:
   52.18          def get_info(n):
   52.19              return sxp.child_value(dom, n)
   52.20 @@ -625,6 +626,8 @@ def xm_sched_sedf(args):
   52.21      server.xend_domain_cpu_sedf_set(dom, *v)
   52.22  
   52.23  def xm_info(args):
   52.24 +    arg_check(args, "info", 0)
   52.25 +
   52.26      from xen.xend.XendClient import server
   52.27      info = server.xend_node()
   52.28      
   52.29 @@ -645,9 +648,12 @@ def xm_console(args):
   52.30  
   52.31  
   52.32  def xm_top(args):
   52.33 +    arg_check(args, "top", 0)
   52.34 +
   52.35      os.execvp('xentop', ['xentop'])
   52.36  
   52.37  def xm_dmesg(args):
   52.38 +    arg_check(args, "dmesg", 0)
   52.39      
   52.40      gopts = Opts(use="""[-c|--clear]
   52.41  
    53.1 --- a/tools/tests/test_x86_emulator.c	Mon Jan 09 11:19:55 2006 +0000
    53.2 +++ b/tools/tests/test_x86_emulator.c	Mon Jan 09 11:22:17 2006 +0000
    53.3 @@ -92,7 +92,7 @@ int main(int argc, char **argv)
    53.4      regs.ecx    = 0x12345678;
    53.5      cr2         = (unsigned long)&res;
    53.6      res         = 0x7FFFFFFF;
    53.7 -    rc = x86_emulate_memop(&regs, cr2, &emulops, 4);
    53.8 +    rc = x86_emulate_memop(&regs, cr2, &emulops, X86EMUL_MODE_PROT32);
    53.9      if ( (rc != 0) || 
   53.10           (res != 0x92345677) || 
   53.11           (regs.eflags != 0xa94) ||
   53.12 @@ -110,7 +110,7 @@ int main(int argc, char **argv)
   53.13      regs.ecx    = 0x12345678UL;
   53.14  #endif
   53.15      cr2         = (unsigned long)&res;
   53.16 -    rc = x86_emulate_memop(&regs, cr2, &emulops, 4);
   53.17 +    rc = x86_emulate_memop(&regs, cr2, &emulops, X86EMUL_MODE_PROT32);
   53.18      if ( (rc != 0) || 
   53.19           (res != 0x92345677) || 
   53.20           (regs.ecx != 0x8000000FUL) ||
   53.21 @@ -125,7 +125,7 @@ int main(int argc, char **argv)
   53.22      regs.eax    = 0x92345677UL;
   53.23      regs.ecx    = 0xAA;
   53.24      cr2         = (unsigned long)&res;
   53.25 -    rc = x86_emulate_memop(&regs, cr2, &emulops, 4);    
   53.26 +    rc = x86_emulate_memop(&regs, cr2, &emulops, X86EMUL_MODE_PROT32);    
   53.27      if ( (rc != 0) || 
   53.28           (res != 0x923456AA) || 
   53.29           (regs.eflags != 0x244) ||
   53.30 @@ -141,7 +141,7 @@ int main(int argc, char **argv)
   53.31      regs.eax    = 0xAABBCC77UL;
   53.32      regs.ecx    = 0xFF;
   53.33      cr2         = (unsigned long)&res;
   53.34 -    rc = x86_emulate_memop(&regs, cr2, &emulops, 4);    
   53.35 +    rc = x86_emulate_memop(&regs, cr2, &emulops, X86EMUL_MODE_PROT32);    
   53.36      if ( (rc != 0) || 
   53.37           (res != 0x923456AA) || 
   53.38           ((regs.eflags&0x240) != 0x200) ||
   53.39 @@ -157,7 +157,7 @@ int main(int argc, char **argv)
   53.40      regs.eip    = (unsigned long)&instr[0];
   53.41      regs.ecx    = 0x12345678;
   53.42      cr2         = (unsigned long)&res;
   53.43 -    rc = x86_emulate_memop(&regs, cr2, &emulops, 4);    
   53.44 +    rc = x86_emulate_memop(&regs, cr2, &emulops, X86EMUL_MODE_PROT32);    
   53.45      if ( (rc != 0) || 
   53.46           (res != 0x12345678) || 
   53.47           (regs.eflags != 0x200) ||
   53.48 @@ -174,7 +174,7 @@ int main(int argc, char **argv)
   53.49      regs.eax    = 0x923456AAUL;
   53.50      regs.ecx    = 0xDDEEFF00L;
   53.51      cr2         = (unsigned long)&res;
   53.52 -    rc = x86_emulate_memop(&regs, cr2, &emulops, 4);    
   53.53 +    rc = x86_emulate_memop(&regs, cr2, &emulops, X86EMUL_MODE_PROT32);    
   53.54      if ( (rc != 0) || 
   53.55           (res != 0xDDEEFF00) || 
   53.56           (regs.eflags != 0x244) ||
   53.57 @@ -193,7 +193,7 @@ int main(int argc, char **argv)
   53.58      regs.edi    = (unsigned long)&res + 2;
   53.59      regs.error_code = 0; /* read fault */
   53.60      cr2         = regs.esi;
   53.61 -    rc = x86_emulate_memop(&regs, cr2, &emulops, 4);    
   53.62 +    rc = x86_emulate_memop(&regs, cr2, &emulops, X86EMUL_MODE_PROT32);    
   53.63      if ( (rc != 0) || 
   53.64           (res != 0x44554455) ||
   53.65           (regs.eflags != 0x200) ||
   53.66 @@ -211,7 +211,7 @@ int main(int argc, char **argv)
   53.67      regs.eip    = (unsigned long)&instr[0];
   53.68      regs.edi    = (unsigned long)&res;
   53.69      cr2         = regs.edi;
   53.70 -    rc = x86_emulate_memop(&regs, cr2, &emulops, 4);    
   53.71 +    rc = x86_emulate_memop(&regs, cr2, &emulops, X86EMUL_MODE_PROT32);    
   53.72      if ( (rc != 0) || 
   53.73           (res != 0x2233445D) ||
   53.74           ((regs.eflags&0x201) != 0x201) ||
   53.75 @@ -229,7 +229,7 @@ int main(int argc, char **argv)
   53.76      regs.eip    = (unsigned long)&instr[0];
   53.77      regs.edi    = (unsigned long)cmpxchg8b_res;
   53.78      cr2         = regs.edi;
   53.79 -    rc = x86_emulate_memop(&regs, cr2, &emulops, 4);
   53.80 +    rc = x86_emulate_memop(&regs, cr2, &emulops, X86EMUL_MODE_PROT32);
   53.81      if ( (rc != 0) || 
   53.82           (cmpxchg8b_res[0] != 0x9999AAAA) ||
   53.83           (cmpxchg8b_res[1] != 0xCCCCFFFF) ||
   53.84 @@ -243,7 +243,7 @@ int main(int argc, char **argv)
   53.85      regs.eip    = (unsigned long)&instr[0];
   53.86      regs.edi    = (unsigned long)cmpxchg8b_res;
   53.87      cr2         = regs.edi;
   53.88 -    rc = x86_emulate_memop(&regs, cr2, &emulops, 4);
   53.89 +    rc = x86_emulate_memop(&regs, cr2, &emulops, X86EMUL_MODE_PROT32);
   53.90      if ( (rc != 0) || 
   53.91           (cmpxchg8b_res[0] != 0x9999AAAA) ||
   53.92           (cmpxchg8b_res[1] != 0xCCCCFFFF) ||
   53.93 @@ -260,7 +260,7 @@ int main(int argc, char **argv)
   53.94      regs.ecx    = 0x12345678;
   53.95      cr2         = (unsigned long)&res;
   53.96      res         = 0x82;
   53.97 -    rc = x86_emulate_memop(&regs, cr2, &emulops, 4);
   53.98 +    rc = x86_emulate_memop(&regs, cr2, &emulops, X86EMUL_MODE_PROT32);
   53.99      if ( (rc != 0) ||
  53.100           (res != 0x82) ||
  53.101           (regs.ecx != 0xFFFFFF82) ||
  53.102 @@ -275,7 +275,7 @@ int main(int argc, char **argv)
  53.103      regs.ecx    = 0x12345678;
  53.104      cr2         = (unsigned long)&res;
  53.105      res         = 0x1234aa82;
  53.106 -    rc = x86_emulate_memop(&regs, cr2, &emulops, 4);
  53.107 +    rc = x86_emulate_memop(&regs, cr2, &emulops, X86EMUL_MODE_PROT32);
  53.108      if ( (rc != 0) ||
  53.109           (res != 0x1234aa82) ||
  53.110           (regs.ecx != 0xaa82) ||
    54.1 --- a/tools/vtpm_manager/README	Mon Jan 09 11:19:55 2006 +0000
    54.2 +++ b/tools/vtpm_manager/README	Mon Jan 09 11:22:17 2006 +0000
    54.3 @@ -53,11 +53,6 @@ DUMMY_BACKEND                -> vtpm_man
    54.4  
    54.5  MANUAL_DM_LAUNCH             -> Must manually launch & kill VTPMs
    54.6  
    54.7 -WELL_KNOWN_SRK_AUTH          -> Rather than randomly generating the password for the SRK,
    54.8 -                                use a well known value. This is necessary for sharing use
    54.9 -                                of the SRK across applications. Such as VTPM and Dom0
   54.10 -                                measurement software.
   54.11 -
   54.12  WELL_KNOWN_OWNER_AUTH        -> Rather than randomly generating the password for the owner,
   54.13                                  use a well known value. This is useful for debugging and for
   54.14                                  poor bios which do not support clearing TPM if OwnerAuth is
    55.1 --- a/tools/vtpm_manager/Rules.mk	Mon Jan 09 11:19:55 2006 +0000
    55.2 +++ b/tools/vtpm_manager/Rules.mk	Mon Jan 09 11:22:17 2006 +0000
    55.3 @@ -56,8 +56,7 @@ CFLAGS += -DLOGGING_MODULES="(BITMASK(VT
    55.4  # Do not have manager launch DMs.
    55.5  #CFLAGS += -DMANUAL_DM_LAUNCH
    55.6  
    55.7 -# Fixed SRK
    55.8 -CFLAGS += -DWELL_KNOWN_SRK_AUTH
    55.9 +# Fixed OwnerAuth
   55.10  #CFLAGS += -DWELL_KNOWN_OWNER_AUTH
   55.11  
   55.12  # TPM Hardware Device or TPM Simulator
    56.1 --- a/tools/vtpm_manager/manager/securestorage.c	Mon Jan 09 11:19:55 2006 +0000
    56.2 +++ b/tools/vtpm_manager/manager/securestorage.c	Mon Jan 09 11:22:17 2006 +0000
    56.3 @@ -65,7 +65,7 @@ TPM_RESULT envelope_encrypt(const buffer
    56.4    UINT32 i;
    56.5    struct pack_constbuf_t symkey_cipher32, data_cipher32;
    56.6    
    56.7 -  vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Enveloping[%d]: 0x", buffer_len(inbuf));
    56.8 +  vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Enveloping Input[%d]: 0x", buffer_len(inbuf));
    56.9    for (i=0; i< buffer_len(inbuf); i++)
   56.10      vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", inbuf->bytes[i]);
   56.11    vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
   56.12 @@ -94,6 +94,12 @@ TPM_RESULT envelope_encrypt(const buffer
   56.13  	       BSG_TPM_SIZE32_DATA, &data_cipher32);
   56.14  
   56.15    vtpmloginfo(VTPM_LOG_VTPM, "Saved %d bytes of E(symkey) + %d bytes of E(data)\n", buffer_len(&symkey_cipher), buffer_len(&data_cipher));
   56.16 +
   56.17 +  vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Enveloping Output[%d]: 0x", buffer_len(sealed_data));
   56.18 +  for (i=0; i< buffer_len(sealed_data); i++)
   56.19 +    vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", sealed_data->bytes[i]);
   56.20 +  vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
   56.21 +
   56.22    goto egress;
   56.23  
   56.24   abort_egress:
   56.25 @@ -125,7 +131,7 @@ TPM_RESULT envelope_decrypt(const long  
   56.26  
   56.27    memset(&symkey, 0, sizeof(symkey_t));
   56.28  
   56.29 -  vtpmloginfo(VTPM_LOG_VTPM_DEEP, "envelope decrypting[%ld]: 0x", cipher_size);
   56.30 +  vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Envelope Decrypt Input[%ld]: 0x", cipher_size);
   56.31    for (i=0; i< cipher_size; i++)
   56.32      vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", cipher[i]);
   56.33    vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
   56.34 @@ -155,6 +161,11 @@ TPM_RESULT envelope_decrypt(const long  
   56.35    
   56.36    // Decrypt State
   56.37    TPMTRY(TPM_DECRYPT_ERROR, Crypto_symcrypto_decrypt (&symkey, &data_cipher, unsealed_data) );
   56.38 +
   56.39 +  vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Envelope Decrypte Output[%d]: 0x", buffer_len(unsealed_data));
   56.40 +  for (i=0; i< buffer_len(unsealed_data); i++)
   56.41 +    vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", unsealed_data->bytes[i]);
   56.42 +  vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
   56.43    
   56.44    goto egress;
   56.45    
   56.46 @@ -291,124 +302,175 @@ TPM_RESULT VTPM_Handle_Load_NVM(VTPM_DMI
   56.47    return status;
   56.48  }
   56.49  
   56.50 +
   56.51  TPM_RESULT VTPM_SaveService(void) {
   56.52    TPM_RESULT status=TPM_SUCCESS;
   56.53    int fh, dmis=-1;
   56.54 -  
   56.55 -  BYTE *flat_global;
   56.56 -  int flat_global_size, bytes_written;
   56.57 +
   56.58 +  BYTE *flat_boot_key, *flat_dmis, *flat_enc;
   56.59 +  buffer_t clear_flat_global, enc_flat_global;
   56.60    UINT32 storageKeySize = buffer_len(&vtpm_globals->storageKeyWrap);
   56.61 +  UINT32 bootKeySize = buffer_len(&vtpm_globals->bootKeyWrap);
   56.62    struct pack_buf_t storage_key_pack = {storageKeySize, vtpm_globals->storageKeyWrap.bytes};
   56.63 -  
   56.64 +  struct pack_buf_t boot_key_pack = {bootKeySize, vtpm_globals->bootKeyWrap.bytes};
   56.65 +
   56.66    struct hashtable_itr *dmi_itr;
   56.67    VTPM_DMI_RESOURCE *dmi_res;
   56.68 -  
   56.69 -  UINT32 flat_global_full_size;
   56.70 -  
   56.71 -  // Global Values needing to be saved
   56.72 -  flat_global_full_size = 3*sizeof(TPM_DIGEST) + // Auths
   56.73 -    sizeof(UINT32) +       // storagekeysize
   56.74 -    storageKeySize +       // storage key
   56.75 -    hashtable_count(vtpm_globals->dmi_map) * // num DMIS
   56.76 -    (sizeof(UINT32) + 2*sizeof(TPM_DIGEST)); // Per DMI info
   56.77 -  
   56.78 -  
   56.79 -  flat_global = (BYTE *) malloc( flat_global_full_size);
   56.80 -  
   56.81 -  flat_global_size = BSG_PackList(flat_global, 4,
   56.82 -				  BSG_TPM_AUTHDATA, &vtpm_globals->owner_usage_auth,
   56.83 -				  BSG_TPM_AUTHDATA, &vtpm_globals->srk_usage_auth,
   56.84 -				  BSG_TPM_SECRET,   &vtpm_globals->storage_key_usage_auth,
   56.85 -				  BSG_TPM_SIZE32_DATA, &storage_key_pack);
   56.86 -  
   56.87 +
   56.88 +  UINT32 boot_key_size, flat_dmis_size;
   56.89 +
   56.90 +  // Initially fill these with buffer sizes for each data type. Later fill
   56.91 +  // in actual size, once flattened.
   56.92 +  boot_key_size =  sizeof(UINT32) +       // bootkeysize
   56.93 +                   bootKeySize;           // boot key
   56.94 +
   56.95 +  TPMTRYRETURN(buffer_init(&clear_flat_global, 3*sizeof(TPM_DIGEST) + // Auths
   56.96 +                                              sizeof(UINT32) +// storagekeysize
   56.97 +                                              storageKeySize, NULL) ); // storage key
   56.98 +
   56.99 +  flat_dmis_size = (hashtable_count(vtpm_globals->dmi_map) - 1) * // num DMIS (-1 for Dom0)
  56.100 +                   (sizeof(UINT32) + 2*sizeof(TPM_DIGEST)); // Per DMI info
  56.101 +
  56.102 +  flat_boot_key = (BYTE *) malloc( boot_key_size );
  56.103 +  flat_enc = (BYTE *) malloc( sizeof(UINT32) );
  56.104 +  flat_dmis = (BYTE *) malloc( flat_dmis_size );
  56.105 +
  56.106 +  boot_key_size = BSG_PackList(flat_boot_key, 1,
  56.107 +                               BSG_TPM_SIZE32_DATA, &boot_key_pack);
  56.108 +
  56.109 +  BSG_PackList(clear_flat_global.bytes, 3,
  56.110 +                BSG_TPM_AUTHDATA, &vtpm_globals->owner_usage_auth,
  56.111 +                BSG_TPM_SECRET,   &vtpm_globals->storage_key_usage_auth,
  56.112 +                BSG_TPM_SIZE32_DATA, &storage_key_pack);
  56.113 +
  56.114 +  TPMTRYRETURN(envelope_encrypt(&clear_flat_global,
  56.115 +                                &vtpm_globals->bootKey,
  56.116 +                                &enc_flat_global) );
  56.117 +
  56.118 +  BSG_PackConst(buffer_len(&enc_flat_global), 4, flat_enc);
  56.119 +
  56.120    // Per DMI values to be saved
  56.121    if (hashtable_count(vtpm_globals->dmi_map) > 0) {
  56.122 -    
  56.123 +
  56.124      dmi_itr = hashtable_iterator(vtpm_globals->dmi_map);
  56.125      do {
  56.126        dmi_res = (VTPM_DMI_RESOURCE *) hashtable_iterator_value(dmi_itr);
  56.127        dmis++;
  56.128  
  56.129        // No need to save dmi0.
  56.130 -      if (dmi_res->dmi_id == 0) 	
  56.131 -	continue;
  56.132 -      
  56.133 -      
  56.134 -      flat_global_size += BSG_PackList( flat_global + flat_global_size, 3,
  56.135 -					BSG_TYPE_UINT32, &dmi_res->dmi_id,
  56.136 -					BSG_TPM_DIGEST, &dmi_res->NVM_measurement,
  56.137 -					BSG_TPM_DIGEST, &dmi_res->DMI_measurement);
  56.138 -      
  56.139 +      if (dmi_res->dmi_id == 0)
  56.140 +        continue;
  56.141 +
  56.142 +
  56.143 +      flat_dmis_size += BSG_PackList( flat_dmis + flat_dmis_size, 3,
  56.144 +                                        BSG_TYPE_UINT32, &dmi_res->dmi_id,
  56.145 +                                        BSG_TPM_DIGEST, &dmi_res->NVM_measurement,
  56.146 +                                        BSG_TPM_DIGEST, &dmi_res->DMI_measurement);
  56.147 +
  56.148      } while (hashtable_iterator_advance(dmi_itr));
  56.149    }
  56.150 -  
  56.151 -  //FIXME: Once we have a way to protect a TPM key, we should use it to 
  56.152 -  //       encrypt this blob. BUT, unless there is a way to ensure the key is
  56.153 -  //       not used by other apps, this encryption is useless.
  56.154 +
  56.155    fh = open(STATE_FILE, O_WRONLY | O_CREAT, S_IREAD | S_IWRITE);
  56.156    if (fh == -1) {
  56.157      vtpmlogerror(VTPM_LOG_VTPM, "Unable to open %s file for write.\n", STATE_FILE);
  56.158      status = TPM_IOERROR;
  56.159      goto abort_egress;
  56.160    }
  56.161 -  
  56.162 -  if ( (bytes_written = write(fh, flat_global, flat_global_size)) != flat_global_size ) {
  56.163 -    vtpmlogerror(VTPM_LOG_VTPM, "Failed to save service data. %d/%d bytes written.\n", bytes_written, flat_global_size);
  56.164 +
  56.165 +  if ( ( write(fh, flat_boot_key, boot_key_size) != boot_key_size ) ||
  56.166 +       ( write(fh, flat_enc, sizeof(UINT32)) != sizeof(UINT32) ) ||
  56.167 +       ( write(fh, enc_flat_global.bytes, buffer_len(&enc_flat_global)) != buffer_len(&enc_flat_global) ) ||
  56.168 +       ( write(fh, flat_dmis, flat_dmis_size) != flat_dmis_size ) ) {
  56.169 +    vtpmlogerror(VTPM_LOG_VTPM, "Failed to completely write service data.\n");
  56.170      status = TPM_IOERROR;
  56.171      goto abort_egress;
  56.172 -  }
  56.173 -  vtpm_globals->DMI_table_dirty = FALSE; 
  56.174 -  
  56.175 + }
  56.176 +
  56.177 +  vtpm_globals->DMI_table_dirty = FALSE;
  56.178 +
  56.179    goto egress;
  56.180 -  
  56.181 +
  56.182   abort_egress:
  56.183   egress:
  56.184 -  
  56.185 -  free(flat_global);
  56.186 +
  56.187 +  free(flat_boot_key);
  56.188 +  free(flat_enc);
  56.189 +  buffer_free(&enc_flat_global);
  56.190 +  free(flat_dmis);
  56.191    close(fh);
  56.192 -  
  56.193 +
  56.194    vtpmloginfo(VTPM_LOG_VTPM, "Saved VTPM Service state (status = %d, dmis = %d)\n", (int) status, dmis);
  56.195    return status;
  56.196  }
  56.197  
  56.198  TPM_RESULT VTPM_LoadService(void) {
  56.199 -  
  56.200 +
  56.201    TPM_RESULT status=TPM_SUCCESS;
  56.202    int fh, stat_ret, dmis=0;
  56.203    long fh_size = 0, step_size;
  56.204 -  BYTE *flat_global=NULL;
  56.205 -  struct pack_buf_t storage_key_pack;
  56.206 -  UINT32 *dmi_id_key;
  56.207 -  
  56.208 +  BYTE *flat_table=NULL;
  56.209 +  buffer_t  unsealed_data;
  56.210 +  struct pack_buf_t storage_key_pack, boot_key_pack;
  56.211 +  UINT32 *dmi_id_key, enc_size;
  56.212 +
  56.213    VTPM_DMI_RESOURCE *dmi_res;
  56.214    struct stat file_stat;
  56.215 -  
  56.216 +
  56.217 +  TPM_HANDLE boot_key_handle;
  56.218 +  TPM_AUTHDATA boot_usage_auth;
  56.219 +  memset(&boot_usage_auth, 0, sizeof(TPM_AUTHDATA));
  56.220 +
  56.221    fh = open(STATE_FILE, O_RDONLY );
  56.222    stat_ret = fstat(fh, &file_stat);
  56.223 -  if (stat_ret == 0) 
  56.224 +  if (stat_ret == 0)
  56.225      fh_size = file_stat.st_size;
  56.226    else {
  56.227      status = TPM_IOERROR;
  56.228      goto abort_egress;
  56.229    }
  56.230 -  
  56.231 -  flat_global = (BYTE *) malloc(fh_size);
  56.232 -  
  56.233 -  if ((long) read(fh, flat_global, fh_size) != fh_size ) {
  56.234 +
  56.235 +  flat_table = (BYTE *) malloc(fh_size);
  56.236 +
  56.237 +  if ((long) read(fh, flat_table, fh_size) != fh_size ) {
  56.238      status = TPM_IOERROR;
  56.239      goto abort_egress;
  56.240    }
  56.241 -  
  56.242 +
  56.243 +  // Read Boot Key
  56.244 +  step_size = BSG_UnpackList( flat_table, 2,
  56.245 +                              BSG_TPM_SIZE32_DATA, &boot_key_pack,
  56.246 +                              BSG_TYPE_UINT32, &enc_size);
  56.247 +
  56.248 +  TPMTRYRETURN(buffer_init(&vtpm_globals->bootKeyWrap, 0, 0) );
  56.249 +  TPMTRYRETURN(buffer_append_raw(&vtpm_globals->bootKeyWrap, boot_key_pack.size, boot_key_pack.data) );
  56.250 +
  56.251 +  //Load Boot Key
  56.252 +  TPMTRYRETURN( VTSP_LoadKey( vtpm_globals->manager_tcs_handle,
  56.253 +                              TPM_SRK_KEYHANDLE,
  56.254 +                              &vtpm_globals->bootKeyWrap,
  56.255 +                              &SRK_AUTH,
  56.256 +                              &boot_key_handle,
  56.257 +                              &vtpm_globals->keyAuth,
  56.258 +                              &vtpm_globals->bootKey,
  56.259 +                              FALSE) );
  56.260 +
  56.261 +  TPMTRYRETURN( envelope_decrypt(enc_size,
  56.262 +                                 flat_table + step_size,
  56.263 +                                 vtpm_globals->manager_tcs_handle,
  56.264 +                                 boot_key_handle,
  56.265 +                                 (const TPM_AUTHDATA*) &boot_usage_auth,
  56.266 +                                 &unsealed_data) );
  56.267 +  step_size += enc_size;
  56.268 +
  56.269    // Global Values needing to be saved
  56.270 -  step_size = BSG_UnpackList( flat_global, 4,
  56.271 -			      BSG_TPM_AUTHDATA, &vtpm_globals->owner_usage_auth,
  56.272 -			      BSG_TPM_AUTHDATA, &vtpm_globals->srk_usage_auth,
  56.273 -			      BSG_TPM_SECRET,   &vtpm_globals->storage_key_usage_auth,
  56.274 -			      BSG_TPM_SIZE32_DATA, &storage_key_pack);
  56.275 -  
  56.276 +  BSG_UnpackList( unsealed_data.bytes, 3,
  56.277 +                  BSG_TPM_AUTHDATA, &vtpm_globals->owner_usage_auth,
  56.278 +                  BSG_TPM_SECRET,   &vtpm_globals->storage_key_usage_auth,
  56.279 +                  BSG_TPM_SIZE32_DATA, &storage_key_pack);
  56.280 +
  56.281    TPMTRYRETURN(buffer_init(&vtpm_globals->storageKeyWrap, 0, 0) );
  56.282    TPMTRYRETURN(buffer_append_raw(&vtpm_globals->storageKeyWrap, storage_key_pack.size, storage_key_pack.data) );
  56.283 -  
  56.284 +
  56.285    // Per DMI values to be saved
  56.286    while ( step_size < fh_size ){
  56.287      if (fh_size - step_size < (long) (sizeof(UINT32) + 2*sizeof(TPM_DIGEST))) {
  56.288 @@ -417,35 +479,38 @@ TPM_RESULT VTPM_LoadService(void) {
  56.289      } else {
  56.290        dmi_res = (VTPM_DMI_RESOURCE *) malloc(sizeof(VTPM_DMI_RESOURCE));
  56.291        dmis++;
  56.292 -      
  56.293 +
  56.294        dmi_res->connected = FALSE;
  56.295 -      
  56.296 -      step_size += BSG_UnpackList(flat_global + step_size, 3,
  56.297 -				  BSG_TYPE_UINT32, &dmi_res->dmi_id, 
  56.298 -				  BSG_TPM_DIGEST, &dmi_res->NVM_measurement,
  56.299 -				  BSG_TPM_DIGEST, &dmi_res->DMI_measurement);
  56.300 -      
  56.301 +
  56.302 +      step_size += BSG_UnpackList(flat_table + step_size, 3,
  56.303 +                                 BSG_TYPE_UINT32, &dmi_res->dmi_id,
  56.304 +                                 BSG_TPM_DIGEST, &dmi_res->NVM_measurement,
  56.305 +                                 BSG_TPM_DIGEST, &dmi_res->DMI_measurement);
  56.306 +
  56.307        // install into map
  56.308        dmi_id_key = (UINT32 *) malloc (sizeof(UINT32));
  56.309        *dmi_id_key = dmi_res->dmi_id;
  56.310        if (!hashtable_insert(vtpm_globals->dmi_map, dmi_id_key, dmi_res)) {
  56.311 -	status = TPM_FAIL;
  56.312 -	goto abort_egress;
  56.313 +        status = TPM_FAIL;
  56.314 +        goto abort_egress;
  56.315        }
  56.316 -      
  56.317 +
  56.318      }
  56.319 -    
  56.320 +
  56.321    }
  56.322 -  
  56.323 +
  56.324    vtpmloginfo(VTPM_LOG_VTPM, "Loaded saved state (dmis = %d).\n", dmis);
  56.325    goto egress;
  56.326 -  
  56.327 +
  56.328   abort_egress:
  56.329    vtpmlogerror(VTPM_LOG_VTPM, "Failed to load service data with error = %s\n", tpm_get_error_name(status));
  56.330   egress:
  56.331 -  
  56.332 -  free(flat_global);
  56.333 +
  56.334 +  free(flat_table);
  56.335    close(fh);
  56.336 -  
  56.337 +
  56.338 +  // TODO: Could be nice and evict BootKey. (Need to add EvictKey to VTSP.
  56.339 +
  56.340    return status;
  56.341  }
  56.342 +
    57.1 --- a/tools/vtpm_manager/manager/vtpm_manager.c	Mon Jan 09 11:19:55 2006 +0000
    57.2 +++ b/tools/vtpm_manager/manager/vtpm_manager.c	Mon Jan 09 11:22:17 2006 +0000
    57.3 @@ -74,16 +74,15 @@ VTPM_GLOBALS *vtpm_globals=NULL;
    57.4  #endif
    57.5  
    57.6  // --------------------------- Well Known Auths --------------------------
    57.7 -#ifdef WELL_KNOWN_SRK_AUTH
    57.8 -static BYTE FIXED_SRK_AUTH[20] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    57.9 +const TPM_AUTHDATA SRK_AUTH = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   57.10                                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
   57.11 -#endif
   57.12  
   57.13  #ifdef WELL_KNOWN_OWNER_AUTH
   57.14  static BYTE FIXED_OWNER_AUTH[20] =  {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   57.15                                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
   57.16  #endif
   57.17 -                                  
   57.18 +
   57.19 +
   57.20  // -------------------------- Hash table functions --------------------
   57.21  
   57.22  static unsigned int hashfunc32(void *ky) {
   57.23 @@ -100,13 +99,7 @@ TPM_RESULT VTPM_Create_Service(){
   57.24    
   57.25    TPM_RESULT status = TPM_SUCCESS;
   57.26    
   57.27 -  // Generate Auth's for SRK & Owner
   57.28 -#ifdef WELL_KNOWN_SRK_AUTH 
   57.29 -  memcpy(vtpm_globals->srk_usage_auth, FIXED_SRK_AUTH, sizeof(TPM_AUTHDATA));
   57.30 -#else    
   57.31 -  Crypto_GetRandom(vtpm_globals->srk_usage_auth, sizeof(TPM_AUTHDATA) );  
   57.32 -#endif
   57.33 -  
   57.34 +  // Generate Auth for Owner
   57.35  #ifdef WELL_KNOWN_OWNER_AUTH 
   57.36    memcpy(vtpm_globals->owner_usage_auth, FIXED_OWNER_AUTH, sizeof(TPM_AUTHDATA));
   57.37  #else    
   57.38 @@ -116,14 +109,14 @@ TPM_RESULT VTPM_Create_Service(){
   57.39    // Take Owership of TPM
   57.40    CRYPTO_INFO ek_cryptoInfo;
   57.41    
   57.42 -  vtpmloginfo(VTPM_LOG_VTPM, "Attempting Pubek Read. NOTE: Failure is ok.\n");
   57.43    status = VTSP_ReadPubek(vtpm_globals->manager_tcs_handle, &ek_cryptoInfo);
   57.44    
   57.45    // If we can read PubEK then there is no owner and we should take it.
   57.46    if (status == TPM_SUCCESS) { 
   57.47 +    vtpmloginfo(VTPM_LOG_VTPM, "Failed to readEK meaning TPM has an owner. Creating Keys off existing SRK.\n");
   57.48      TPMTRYRETURN(VTSP_TakeOwnership(vtpm_globals->manager_tcs_handle,
   57.49  				    (const TPM_AUTHDATA*)&vtpm_globals->owner_usage_auth, 
   57.50 -				    (const TPM_AUTHDATA*)&vtpm_globals->srk_usage_auth,
   57.51 +				    &SRK_AUTH,
   57.52  				    &ek_cryptoInfo,
   57.53  				    &vtpm_globals->keyAuth)); 
   57.54    
   57.55 @@ -142,7 +135,7 @@ TPM_RESULT VTPM_Create_Service(){
   57.56    TPMTRYRETURN( VTSP_OSAP(vtpm_globals->manager_tcs_handle,
   57.57  			  TPM_ET_KEYHANDLE,
   57.58  			  TPM_SRK_KEYHANDLE, 
   57.59 -			  (const TPM_AUTHDATA*)&vtpm_globals->srk_usage_auth,
   57.60 +			  &SRK_AUTH,
   57.61  			  &sharedsecret, 
   57.62  			  &osap) ); 
   57.63  
   57.64 @@ -157,8 +150,43 @@ TPM_RESULT VTPM_Create_Service(){
   57.65  				    &vtpm_globals->storageKeyWrap,
   57.66  				    &osap) );
   57.67    
   57.68 -  vtpm_globals->keyAuth.fContinueAuthSession = TRUE;
   57.69 +  // Generate boot key's auth
   57.70 +  Crypto_GetRandom(  &vtpm_globals->storage_key_usage_auth, 
   57.71 +		     sizeof(TPM_AUTHDATA) );
   57.72 +  
   57.73 +  TPM_AUTHDATA bootKeyWrapAuth;
   57.74 +  memset(&bootKeyWrapAuth, 0, sizeof(bootKeyWrapAuth));
   57.75    
   57.76 +  TPMTRYRETURN( VTSP_OSAP(vtpm_globals->manager_tcs_handle,
   57.77 +			  TPM_ET_KEYHANDLE,
   57.78 +			  TPM_SRK_KEYHANDLE, 
   57.79 +			  &SRK_AUTH,
   57.80 +			  &sharedsecret, 
   57.81 +			  &osap) ); 
   57.82 +
   57.83 +  osap.fContinueAuthSession = FALSE;
   57.84 + 
   57.85 +  // FIXME: This key protects the global secrets on disk. It should use TPM
   57.86 +  //        PCR bindings to limit its use to legit configurations.
   57.87 +  //        Current binds are open, implying a Trusted VM contains this code.
   57.88 +  //        If this VM is not Trusted, use measurement and PCR bindings.
   57.89 +  TPMTRYRETURN( VTSP_CreateWrapKey( vtpm_globals->manager_tcs_handle,
   57.90 +				    TPM_KEY_BIND,
   57.91 +				    (const TPM_AUTHDATA*)&bootKeyWrapAuth,
   57.92 +				    TPM_SRK_KEYHANDLE, 
   57.93 +				    (const TPM_AUTHDATA*)&sharedsecret,
   57.94 +				    &vtpm_globals->bootKeyWrap,
   57.95 +				    &osap) );
   57.96 +
   57.97 +  // Populate CRYPTO_INFO vtpm_globals->bootKey. This does not load it into the TPM
   57.98 +  TPMTRYRETURN( VTSP_LoadKey( vtpm_globals->manager_tcs_handle,
   57.99 +                              TPM_SRK_KEYHANDLE,
  57.100 +                              &vtpm_globals->bootKeyWrap,
  57.101 +                              NULL,
  57.102 +                              NULL,
  57.103 +                              NULL,
  57.104 +                              &vtpm_globals->bootKey,
  57.105 +                              TRUE ) );
  57.106    goto egress;
  57.107    
  57.108   abort_egress:
  57.109 @@ -278,24 +306,26 @@ void *VTPM_Service_Handler(void *threadT
  57.110  #endif
  57.111  
  57.112      // Check status of rx_fh. If necessary attempt to re-open it.    
  57.113 +    char* s = NULL;
  57.114      if (*rx_fh < 0) {
  57.115  #ifdef VTPM_MULTI_VM
  57.116 -      *rx_fh = open(VTPM_BE_DEV, O_RDWR);
  57.117 +      s = VTPM_BE_DEV;
  57.118  #else
  57.119        if (threadType == BE_LISTENER_THREAD) 
  57.120    #ifdef DUMMY_BACKEND
  57.121 -	*rx_fh = open("/tmp/in.fifo", O_RDWR);
  57.122 +	s = "/tmp/in.fifo";
  57.123    #else
  57.124 -        *rx_fh = open(VTPM_BE_DEV, O_RDWR);
  57.125 +      s = VTPM_BE_DEV;
  57.126    #endif
  57.127        else  // DMI Listener   
  57.128 -	*rx_fh = open(VTPM_RX_FIFO, O_RDWR);
  57.129 +	s = VTPM_RX_FIFO;
  57.130 +      *rx_fh = open(s, O_RDWR);
  57.131  #endif    
  57.132      }
  57.133      
  57.134      // Respond to failures to open rx_fh
  57.135      if (*rx_fh < 0) {
  57.136 -      vtpmhandlerlogerror(VTPM_LOG_VTPM, "Can't open inbound fh.\n");
  57.137 +      vtpmhandlerlogerror(VTPM_LOG_VTPM, "Can't open inbound fh for %s.\n", s);
  57.138  #ifdef VTPM_MULTI_VM
  57.139        return TPM_IOERROR; 
  57.140  #else
  57.141 @@ -713,7 +743,7 @@ void *VTPM_Service_Handler(void *threadT
  57.142  
  57.143  ///////////////////////////////////////////////////////////////////////////////
  57.144  TPM_RESULT VTPM_Init_Service() {
  57.145 -  TPM_RESULT status = TPM_FAIL;   
  57.146 +  TPM_RESULT status = TPM_FAIL, serviceStatus;   
  57.147    BYTE *randomsead;
  57.148    UINT32 randomsize;
  57.149  
  57.150 @@ -737,7 +767,7 @@ TPM_RESULT VTPM_Init_Service() {
  57.151    
  57.152    // Create new TCS Object
  57.153    vtpm_globals->manager_tcs_handle = 0;
  57.154 -  
  57.155 + 
  57.156    TPMTRYRETURN(TCS_create());
  57.157    
  57.158    // Create TCS Context for service
  57.159 @@ -756,17 +786,24 @@ TPM_RESULT VTPM_Init_Service() {
  57.160    vtpm_globals->keyAuth.fContinueAuthSession = TRUE;
  57.161  
  57.162  	// If failed, create new Service.
  57.163 -  if (VTPM_LoadService() != TPM_SUCCESS)
  57.164 +  serviceStatus = VTPM_LoadService();
  57.165 +  if (serviceStatus == TPM_IOERROR) {
  57.166 +    vtpmloginfo(VTPM_LOG_VTPM, "Failed to read service file. Assuming first time initialization.\n");
  57.167      TPMTRYRETURN( VTPM_Create_Service() );    
  57.168 +  } else if (serviceStatus != TPM_SUCCESS) {
  57.169 +    vtpmlogerror(VTPM_LOG_VTPM, "Failed to read existing service file");
  57.170 +    exit(1);
  57.171 +  }
  57.172  
  57.173    //Load Storage Key 
  57.174    TPMTRYRETURN( VTSP_LoadKey( vtpm_globals->manager_tcs_handle,
  57.175  			      TPM_SRK_KEYHANDLE,
  57.176  			      &vtpm_globals->storageKeyWrap,
  57.177 -			      (const TPM_AUTHDATA*)&vtpm_globals->srk_usage_auth,
  57.178 +			      &SRK_AUTH,
  57.179  			      &vtpm_globals->storageKeyHandle,
  57.180  			      &vtpm_globals->keyAuth,
  57.181 -			      &vtpm_globals->storageKey) );
  57.182 +			      &vtpm_globals->storageKey,
  57.183 +                              FALSE ) );
  57.184  
  57.185    // Create entry for Dom0 for control messages
  57.186    TPMTRYRETURN( VTPM_Handle_New_DMI(NULL) );
  57.187 @@ -797,12 +834,11 @@ void VTPM_Stop_Service() {
  57.188  		free (dmi_itr);
  57.189    }
  57.190    
  57.191 -	
  57.192 +  if ( (vtpm_globals->DMI_table_dirty) && (VTPM_SaveService() != TPM_SUCCESS) )
  57.193 +    vtpmlogerror(VTPM_LOG_VTPM, "Unable to save manager data.\n");
  57.194 +
  57.195    TCS_CloseContext(vtpm_globals->manager_tcs_handle);
  57.196 -  
  57.197 -  if ( (vtpm_globals->DMI_table_dirty) &&
  57.198 -       (VTPM_SaveService() != TPM_SUCCESS) )
  57.199 -    vtpmlogerror(VTPM_LOG_VTPM, "Unable to save manager data.\n");
  57.200 +  TCS_destroy();
  57.201    
  57.202    hashtable_destroy(vtpm_globals->dmi_map, 1);
  57.203    free(vtpm_globals);
    58.1 --- a/tools/vtpm_manager/manager/vtpmpriv.h	Mon Jan 09 11:19:55 2006 +0000
    58.2 +++ b/tools/vtpm_manager/manager/vtpmpriv.h	Mon Jan 09 11:22:17 2006 +0000
    58.3 @@ -108,6 +108,7 @@ typedef struct tdVTPM_GLOBALS {
    58.4    TCS_CONTEXT_HANDLE  manager_tcs_handle;     // TCS Handle used by manager
    58.5    TPM_HANDLE          storageKeyHandle;       // Key used by persistent store
    58.6    CRYPTO_INFO         storageKey;             // For software encryption
    58.7 +  CRYPTO_INFO         bootKey;                // For saving table
    58.8    TCS_AUTH            keyAuth;                // OIAP session for storageKey 
    58.9    BOOL                DMI_table_dirty;        // Indicates that a command
   58.10                                                // has updated the DMI table
   58.11 @@ -115,15 +116,17 @@ typedef struct tdVTPM_GLOBALS {
   58.12      
   58.13    // Persistent Data
   58.14    TPM_AUTHDATA        owner_usage_auth;       // OwnerAuth of real TPM
   58.15 -  TPM_AUTHDATA        srk_usage_auth;         // SRK Auth of real TPM    
   58.16    buffer_t            storageKeyWrap;         // Wrapped copy of storageKey
   58.17 +  TPM_AUTHDATA        srk_usage_auth;
   58.18 +  TPM_AUTHDATA        storage_key_usage_auth; 
   58.19  
   58.20 -  TPM_AUTHDATA        storage_key_usage_auth; 
   58.21 -    
   58.22 +  buffer_t            bootKeyWrap;            // Wrapped copy of boot key 
   58.23 +
   58.24  }VTPM_GLOBALS;
   58.25  
   58.26 -//Global dmi map
   58.27 -extern VTPM_GLOBALS *vtpm_globals;
   58.28 +// --------------------------- Global Values --------------------------
   58.29 +extern VTPM_GLOBALS *vtpm_globals;   // Key info and DMI states
   58.30 +extern const TPM_AUTHDATA SRK_AUTH;  // SRK Well Known Auth Value
   58.31  
   58.32  // ********************** Command Handler Prototypes ***********************
   58.33  TPM_RESULT VTPM_Handle_Load_NVM(       VTPM_DMI_RESOURCE *myDMI, 
    59.1 --- a/tools/vtpm_manager/manager/vtsp.c	Mon Jan 09 11:19:55 2006 +0000
    59.2 +++ b/tools/vtpm_manager/manager/vtsp.c	Mon Jan 09 11:22:17 2006 +0000
    59.3 @@ -144,7 +144,10 @@ TPM_RESULT VerifyAuth( /*[IN]*/ const BY
    59.4    if (memcmp (&hm, &(auth->HMAC), sizeof(TPM_DIGEST)) == 0)  // 0 indicates equality
    59.5      return (TPM_SUCCESS);
    59.6    else {
    59.7 -    VTSP_OIAP( hContext, auth);
    59.8 +    // If specified, reconnect the OIAP session.
    59.9 +    // NOTE: This only works for TCS's that never have a 0 context. 
   59.10 +    if (hContext) 
   59.11 +      VTSP_OIAP( hContext, auth);
   59.12      return (TPM_AUTHFAIL);
   59.13    }
   59.14  }
   59.15 @@ -157,6 +160,10 @@ TPM_RESULT VTSP_OIAP(const TCS_CONTEXT_H
   59.16    TPMTRYRETURN( TCSP_OIAP(hContext,
   59.17  			  &auth->AuthHandle,
   59.18  			  &auth->NonceEven) );
   59.19 +
   59.20 +  memset(&auth->HMAC, 0, sizeof(TPM_DIGEST));
   59.21 +  auth->fContinueAuthSession = FALSE;
   59.22 +
   59.23    goto egress;
   59.24    
   59.25   abort_egress:
   59.26 @@ -195,6 +202,9 @@ TPM_RESULT VTSP_OSAP(const TCS_CONTEXT_H
   59.27  		 BSG_TPM_NONCE, &nonceOddOSAP);
   59.28    
   59.29    Crypto_HMAC(sharedSecretText, sizeof(sharedSecretText), (BYTE *) usageAuth, TPM_DIGEST_SIZE, (BYTE *) sharedSecret);       
   59.30 +
   59.31 +  memset(&auth->HMAC, 0, sizeof(TPM_DIGEST));
   59.32 +  auth->fContinueAuthSession = FALSE;
   59.33      
   59.34    goto egress;
   59.35    
   59.36 @@ -288,9 +298,6 @@ TPM_RESULT VTSP_TakeOwnership(   const T
   59.37    
   59.38    struct pack_buf_t srkText;
   59.39    
   59.40 -  // GenerateAuth new nonceOdd    
   59.41 -  Crypto_GetRandom(&auth->NonceOdd, sizeof(TPM_NONCE) );
   59.42 -  
   59.43    //These values are accurate for an enc(AuthData).
   59.44    struct pack_buf_t encOwnerAuth, encSrkAuth;
   59.45    
   59.46 @@ -383,9 +390,6 @@ TPM_RESULT VTSP_DisablePubekRead( const 
   59.47    BYTE *paramText;        // Digest to make Auth.
   59.48    UINT32 paramTextSize;
   59.49      
   59.50 -  // Generate HMAC   
   59.51 -  Crypto_GetRandom(&auth->NonceOdd, sizeof(TPM_NONCE) );
   59.52 -  
   59.53    paramText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);
   59.54    
   59.55    paramTextSize = BSG_PackList(paramText, 1,
   59.56 @@ -504,9 +508,6 @@ TPM_RESULT VTSP_CreateWrapKey(  const TC
   59.57    newKeyText.data = flatKey;
   59.58    newKeyText.size = flatKeySize;
   59.59    
   59.60 -  // GenerateAuth new nonceOdd    
   59.61 -  Crypto_GetRandom(&auth->NonceOdd, sizeof(TPM_NONCE) );
   59.62 -  
   59.63    // Generate HMAC
   59.64    paramText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);
   59.65    
   59.66 @@ -563,63 +564,66 @@ TPM_RESULT VTSP_LoadKey(const TCS_CONTEX
   59.67                          const TPM_AUTHDATA          *parentAuth,
   59.68                          TPM_HANDLE                  *newKeyHandle,
   59.69                          TCS_AUTH                    *auth,
   59.70 -                        CRYPTO_INFO                 *cryptoinfo /*= NULL*/) {
   59.71 +                        CRYPTO_INFO                 *cryptoinfo,
   59.72 +                        const BOOL                  skipTPMLoad) { 
   59.73    
   59.74    
   59.75 -  vtpmloginfo(VTPM_LOG_VTSP, "Loading Key.\n%s","");
   59.76 +  vtpmloginfo(VTPM_LOG_VTSP, "Loading Key %s.\n", (!skipTPMLoad ? "into TPM" : "only into memory"));
   59.77    
   59.78    TPM_RESULT status = TPM_SUCCESS;
   59.79    TPM_COMMAND_CODE command = TPM_ORD_LoadKey;
   59.80 -  
   59.81 -  BYTE *paramText;        // Digest to make Auth.
   59.82 +
   59.83 +  BYTE *paramText=NULL;        // Digest to make Auth.
   59.84    UINT32 paramTextSize;
   59.85 +
   59.86 +  // SkipTPMLoad stops key from being loaded into TPM, but still generates CRYPTO_INFO for it
   59.87 +  if (! skipTPMLoad) { 
   59.88    
   59.89 -  if ((rgbWrappedKeyBlob == NULL) || (parentAuth == NULL) || 
   59.90 -      (newKeyHandle==NULL) || (auth==NULL)) {
   59.91 -    status = TPM_BAD_PARAMETER;
   59.92 -    goto abort_egress;
   59.93 -  }
   59.94 -  
   59.95 -  // Generate Extra TCS Parameters
   59.96 -  TPM_HANDLE phKeyHMAC;
   59.97 +    if ((rgbWrappedKeyBlob == NULL) || (parentAuth == NULL) || 
   59.98 +        (newKeyHandle==NULL) || (auth==NULL)) {
   59.99 +      status = TPM_BAD_PARAMETER;
  59.100 +      goto abort_egress;
  59.101 +    }
  59.102    
  59.103 -  // Generate HMAC
  59.104 -  Crypto_GetRandom(&auth->NonceOdd, sizeof(TPM_NONCE) );
  59.105 +    // Generate Extra TCS Parameters
  59.106 +    TPM_HANDLE phKeyHMAC;
  59.107    
  59.108 -  paramText = (BYTE *) malloc(sizeof(BYTE) *  TCPA_MAX_BUFFER_LENGTH);
  59.109 +    paramText = (BYTE *) malloc(sizeof(BYTE) *  TCPA_MAX_BUFFER_LENGTH);
  59.110    
  59.111 -  paramTextSize = BSG_PackList(paramText, 1,
  59.112 -			       BSG_TPM_COMMAND_CODE, &command);
  59.113 +    paramTextSize = BSG_PackList(paramText, 1,
  59.114 +  			         BSG_TPM_COMMAND_CODE, &command);
  59.115    
  59.116 -  memcpy(paramText + paramTextSize, rgbWrappedKeyBlob->bytes, buffer_len(rgbWrappedKeyBlob));
  59.117 -  paramTextSize += buffer_len(rgbWrappedKeyBlob);
  59.118 +    memcpy(paramText + paramTextSize, rgbWrappedKeyBlob->bytes, buffer_len(rgbWrappedKeyBlob));
  59.119 +    paramTextSize += buffer_len(rgbWrappedKeyBlob);
  59.120    
  59.121 -  TPMTRYRETURN( GenerateAuth( paramText, paramTextSize,
  59.122 +    TPMTRYRETURN( GenerateAuth( paramText, paramTextSize,
  59.123  			      parentAuth, auth) );
  59.124    
  59.125 -  // Call TCS
  59.126 -  TPMTRYRETURN( TCSP_LoadKeyByBlob(  hContext,
  59.127 -				     hUnwrappingKey,
  59.128 -				     buffer_len(rgbWrappedKeyBlob),
  59.129 -				     rgbWrappedKeyBlob->bytes,
  59.130 -				     auth,
  59.131 -				     newKeyHandle,
  59.132 -				     &phKeyHMAC) );
  59.133 +    // Call TCS
  59.134 +    TPMTRYRETURN( TCSP_LoadKeyByBlob(  hContext,
  59.135 +				       hUnwrappingKey,
  59.136 +				       buffer_len(rgbWrappedKeyBlob),
  59.137 +				       rgbWrappedKeyBlob->bytes,
  59.138 +				       auth,
  59.139 +				       newKeyHandle,
  59.140 +				       &phKeyHMAC) );
  59.141    
  59.142 -  // Verify Auth
  59.143 -  paramTextSize = BSG_PackList(paramText, 3,
  59.144 -			       BSG_TPM_RESULT, &status,
  59.145 -			       BSG_TPM_COMMAND_CODE, &command,
  59.146 -			       BSG_TPM_HANDLE, newKeyHandle);
  59.147 +    // Verify Auth
  59.148 +    paramTextSize = BSG_PackList(paramText, 3,
  59.149 +			         BSG_TPM_RESULT, &status,
  59.150 +			         BSG_TPM_COMMAND_CODE, &command,
  59.151 +			         BSG_TPM_HANDLE, newKeyHandle);
  59.152    
  59.153 -  TPMTRYRETURN( VerifyAuth( paramText, paramTextSize,
  59.154 -			    parentAuth, auth, 
  59.155 -			    hContext) );
  59.156 +    TPMTRYRETURN( VerifyAuth( paramText, paramTextSize,
  59.157 +			      parentAuth, auth, 
  59.158 +			      hContext) );
  59.159 +  } 
  59.160    
  59.161 -  // Unpack/return key structure
  59.162 +  // Build cryptoinfo structure for software crypto function. 
  59.163    if (cryptoinfo != NULL) {
  59.164      TPM_KEY newKey;
  59.165      
  59.166 +    // Unpack/return key structure
  59.167      BSG_Unpack(BSG_TPM_KEY, rgbWrappedKeyBlob->bytes , &newKey);
  59.168      TPM_RSA_KEY_PARMS rsaKeyParms;
  59.169      
  59.170 @@ -670,9 +674,6 @@ TPM_RESULT VTSP_Unbind( const TCS_CONTEX
  59.171    BYTE *clear_data_text;
  59.172    UINT32 clear_data_size;
  59.173    
  59.174 -  // Generate HMAC   
  59.175 -  Crypto_GetRandom(&auth->NonceOdd, sizeof(TPM_NONCE) );
  59.176 -  
  59.177    struct pack_buf_t bound_data32 = {bound_data->size, bound_data->bytes};
  59.178    
  59.179    paramText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);
  59.180 @@ -781,6 +782,196 @@ TPM_RESULT VTSP_Bind(   CRYPTO_INFO *cry
  59.181    return TPM_SUCCESS;
  59.182  }
  59.183  
  59.184 +TPM_RESULT VTSP_Seal(const TCS_CONTEXT_HANDLE    hContext,
  59.185 +                     const TPM_KEY_HANDLE        keyHandle,
  59.186 +                     const TPM_AUTHDATA          *sealDataAuth,
  59.187 +                     const TPM_PCR_COMPOSITE     *pcrComp,
  59.188 +                     const buffer_t              *inData,
  59.189 +                     TPM_STORED_DATA             *sealedData,                                   
  59.190 +                     const TPM_SECRET            *osapSharedSecret,
  59.191 +                     TCS_AUTH                    *auth) {
  59.192 +
  59.193 +  TPM_RESULT status = TPM_SUCCESS;
  59.194 +  TPM_COMMAND_CODE command = TPM_ORD_Seal;
  59.195 +
  59.196 +  BYTE *paramText;        // Digest to make Auth.
  59.197 +  UINT32 paramTextSize;
  59.198 +
  59.199 +  // Generate PCR_Info Struct from Comp
  59.200 +  TPM_PCR_INFO pcrInfo;
  59.201 +  UINT32 pcrInfoSize, flatpcrSize;
  59.202 +  BYTE flatpcr[3 +                          // PCR_Select = 3 1 byte banks
  59.203 +               sizeof(UINT16) +             //              2 byte UINT16
  59.204 +               sizeof(UINT32) +             // PCR_Comp   = 4 byte UINT32
  59.205 +               24 * sizeof(TPM_PCRVALUE) ]; //              up to 24 PCRs
  59.206 +
  59.207 +  if (pcrComp != NULL) {
  59.208 +      //printf("\n\tBinding to PCRs: ");
  59.209 +      //for(int i = 0 ; i < pcrComp->select.sizeOfSelect ; i++)
  59.210 +      //printf("%2.2x", pcrComp->select.pcrSelect[i]);
  59.211 +
  59.212 +      memcpy(&pcrInfo.pcrSelection, &pcrComp->select, sizeof(TPM_PCR_SELECTION));
  59.213 +
  59.214 +      flatpcrSize = BSG_Pack(BSG_TPM_PCR_COMPOSITE, (BYTE *) pcrComp, flatpcr);
  59.215 +      Crypto_SHA1Full((BYTE *) flatpcr, flatpcrSize, (BYTE *) &(pcrInfo.digestAtRelease));
  59.216 +      memset(&(pcrInfo.digestAtCreation), 0, sizeof(TPM_DIGEST));
  59.217 +      pcrInfoSize = BSG_Pack(BSG_TPM_PCR_INFO, (BYTE *) &pcrInfo, flatpcr);
  59.218 +  } else {
  59.219 +      //printf("\n\tBinding to no PCRS.");
  59.220 +      pcrInfoSize = 0;
  59.221 +  }
  59.222 +
  59.223 +  // Calculate encUsageAuth
  59.224 +  BYTE XORbuffer[sizeof(TPM_SECRET) + sizeof(TPM_NONCE)];
  59.225 +  UINT32 XORbufferSize = sizeof(XORbuffer);
  59.226 +  TPM_DIGEST XORKey;
  59.227 +  TPM_ENCAUTH encAuth;
  59.228 +
  59.229 +  BSG_PackList( XORbuffer, 2,
  59.230 +                BSG_TPM_SECRET, osapSharedSecret,
  59.231 +                BSG_TPM_NONCE, &auth->NonceEven );
  59.232 +
  59.233 +  Crypto_SHA1Full(XORbuffer, XORbufferSize, (BYTE *) &XORKey);
  59.234 +
  59.235 +  int i;
  59.236 +  for (i=0; i < TPM_DIGEST_SIZE; i++)
  59.237 +    ((BYTE *) &encAuth)[i] = ((BYTE *) &XORKey)[i] ^ ((BYTE *) sealDataAuth)[i];
  59.238 +
  59.239 +  // Generate Extra TCS Parameters
  59.240 +  UINT32 inDataSize = buffer_len(inData);
  59.241 +  struct pack_buf_t inData_pack = {inDataSize, inData->bytes};
  59.242 +  struct pack_buf_t pcrInfo_pack = {pcrInfoSize, flatpcr};
  59.243 +
  59.244 +  UINT32 sealedDataSize;
  59.245 +  BYTE *flatSealedData=NULL;
  59.246 +
  59.247 +  paramText = (BYTE *) malloc(sizeof(BYTE) *  TCPA_MAX_BUFFER_LENGTH);
  59.248 +
  59.249 +  paramTextSize = BSG_PackList(paramText, 4,
  59.250 +                               BSG_TPM_COMMAND_CODE, &command,
  59.251 +                               BSG_TPM_ENCAUTH, &encAuth,
  59.252 +                               BSG_TPM_SIZE32_DATA, &pcrInfo_pack,
  59.253 +                               BSG_TPM_SIZE32_DATA, &inData_pack);
  59.254 +
  59.255 +  TPMTRYRETURN( GenerateAuth( paramText, paramTextSize,
  59.256 +                              osapSharedSecret, auth) );
  59.257 +
  59.258 +  // Call TCS
  59.259 +  TPMTRYRETURN( TCSP_Seal( hContext,
  59.260 +                           keyHandle,
  59.261 +                           encAuth,
  59.262 +                           pcrInfoSize,
  59.263 +                           flatpcr,
  59.264 +                           inDataSize,
  59.265 +                           inData->bytes,
  59.266 +                           auth,
  59.267 +                           &sealedDataSize,
  59.268 +                           &flatSealedData) );
  59.269 +
  59.270 +  // Unpack/return key structure
  59.271 +  BSG_Unpack( BSG_TPM_STORED_DATA, flatSealedData, sealedData );
  59.272 +
  59.273 +  paramTextSize = BSG_PackList(paramText, 3,
  59.274 +                               BSG_TPM_RESULT, &status,
  59.275 +                               BSG_TPM_COMMAND_CODE, &command,
  59.276 +                               BSG_TPM_STORED_DATA, sealedData);
  59.277 +
  59.278 +  TPMTRYRETURN( VerifyAuth( paramText, paramTextSize,
  59.279 +                            osapSharedSecret, auth,
  59.280 +                            0) );
  59.281 +
  59.282 +
  59.283 +  goto egress;
  59.284 +
  59.285 + abort_egress:
  59.286 + egress:
  59.287 +
  59.288 +  if (flatSealedData)
  59.289 +    TCS_FreeMemory( hContext, flatSealedData);
  59.290 +
  59.291 +  free(paramText);
  59.292 +  return status;
  59.293 +}
  59.294 +
  59.295 +
  59.296 +TPM_RESULT VTSP_Unseal(const TCS_CONTEXT_HANDLE    hContext,
  59.297 +                       const TPM_KEY_HANDLE        keyHandle,
  59.298 +                       const TPM_STORED_DATA       *sealedData,
  59.299 +                       const TPM_AUTHDATA          *key_usage_auth,
  59.300 +                       const TPM_AUTHDATA          *data_usage_auth,
  59.301 +                       buffer_t                    *outData,
  59.302 +                       TCS_AUTH                    *auth,
  59.303 +                       TCS_AUTH                    *dataAuth) {
  59.304 +
  59.305 +  TPM_RESULT status = TPM_SUCCESS;
  59.306 +  TPM_COMMAND_CODE command = TPM_ORD_Unseal;
  59.307 +
  59.308 +  BYTE *paramText;        // Digest to make Auth.
  59.309 +  UINT32 paramTextSize;
  59.310 +
  59.311 +  // Generate Extra TCS Parameters
  59.312 +  UINT32 sealDataSize, clearDataSize;
  59.313 +  BYTE *flatSealedData= (BYTE *) malloc(sizeof(TPM_VERSION) +
  59.314 +                                        2 * sizeof(UINT32) +
  59.315 +                                        sealedData->sealInfoSize +
  59.316 +                                        sealedData->encDataSize),
  59.317 +       *clearData=NULL;
  59.318 +
  59.319 +  sealDataSize = BSG_Pack(BSG_TPM_STORED_DATA, sealedData, flatSealedData );
  59.320 +
  59.321 +  paramText = (BYTE *) malloc(sizeof(BYTE) *  TCPA_MAX_BUFFER_LENGTH);
  59.322 +
  59.323 +  paramTextSize = BSG_PackList(paramText, 2,
  59.324 +                               BSG_TPM_COMMAND_CODE, &command,
  59.325 +                               BSG_TPM_STORED_DATA, sealedData);
  59.326 +
  59.327 +  TPMTRYRETURN( GenerateAuth( paramText, paramTextSize,
  59.328 +                              key_usage_auth, auth) );
  59.329 +
  59.330 +  TPMTRYRETURN( GenerateAuth( paramText, paramTextSize,
  59.331 +                              data_usage_auth, dataAuth) );
  59.332 +  // Call TCS
  59.333 +  TPMTRYRETURN( TCSP_Unseal(  hContext,
  59.334 +                              keyHandle,
  59.335 +                              sealDataSize,
  59.336 +                              flatSealedData,
  59.337 +                              auth,
  59.338 +                              dataAuth,
  59.339 +                              &clearDataSize,
  59.340 +                              &clearData) );
  59.341 +
  59.342 +  // Verify Auth
  59.343 +  struct pack_buf_t clearData_pack = {clearDataSize, clearData};
  59.344 +
  59.345 +  paramTextSize = BSG_PackList(paramText, 3,
  59.346 +                               BSG_TPM_RESULT, &status,
  59.347 +                               BSG_TPM_COMMAND_CODE, &command,
  59.348 +                               BSG_TPM_SIZE32_DATA, &clearData_pack);
  59.349 +
  59.350 +  TPMTRYRETURN( VerifyAuth( paramText, paramTextSize,
  59.351 +                            key_usage_auth, auth,
  59.352 +                            hContext) );
  59.353 +
  59.354 +  TPMTRYRETURN( VerifyAuth( paramText, paramTextSize,
  59.355 +                            data_usage_auth, dataAuth,
  59.356 +                            hContext) );
  59.357 +
  59.358 +  // Unpack/return key structure
  59.359 +  TPMTRYRETURN( buffer_init(outData, clearDataSize, clearData) );
  59.360 +
  59.361 +  goto egress;
  59.362 +
  59.363 + abort_egress:
  59.364 + egress:
  59.365 +
  59.366 +  if (flatSealedData)
  59.367 +    TCS_FreeMemory( hContext, clearData);
  59.368 +
  59.369 +  free(paramText);
  59.370 +  return status;
  59.371 +}
  59.372 +
  59.373 +
  59.374  // Function Reaches into unsupported TCS command, beware.
  59.375  TPM_RESULT VTSP_RawTransmit(const TCS_CONTEXT_HANDLE    hContext,
  59.376                              const buffer_t *inbuf,
    60.1 --- a/tools/vtpm_manager/manager/vtsp.h	Mon Jan 09 11:19:55 2006 +0000
    60.2 +++ b/tools/vtpm_manager/manager/vtsp.h	Mon Jan 09 11:22:17 2006 +0000
    60.3 @@ -86,7 +86,8 @@ TPM_RESULT VTSP_LoadKey(const TCS_CONTEX
    60.4                          const TPM_AUTHDATA          *parentAuth,
    60.5                          TPM_HANDLE                  *newKeyHandle,
    60.6                          TCS_AUTH                    *pAuth,
    60.7 -                        CRYPTO_INFO                 *cryptoinfo);
    60.8 +                        CRYPTO_INFO                 *cryptoinfo,
    60.9 +                        const BOOL                  skipTPMLoad);
   60.10  
   60.11  TPM_RESULT VTSP_Unbind( const TCS_CONTEXT_HANDLE    hContext,
   60.12                          const TPM_KEY_HANDLE        key_handle,
   60.13 @@ -99,4 +100,22 @@ TPM_RESULT VTSP_Bind(   CRYPTO_INFO *cry
   60.14              const buffer_t *inData, 
   60.15              buffer_t *outData);
   60.16                          
   60.17 +TPM_RESULT VTSP_Seal(const TCS_CONTEXT_HANDLE    hContext,
   60.18 +                     const TPM_KEY_HANDLE        keyHandle,
   60.19 +                     const TPM_AUTHDATA          *sealDataAuth,
   60.20 +                     const TPM_PCR_COMPOSITE     *pcrComp,
   60.21 +                     const buffer_t              *inData,
   60.22 +                     TPM_STORED_DATA             *sealedData,                                   
   60.23 +                     const TPM_SECRET            *osapSharedSecret,
   60.24 +                     TCS_AUTH                    *auth);
   60.25 +
   60.26 +TPM_RESULT VTSP_Unseal(const TCS_CONTEXT_HANDLE    hContext,
   60.27 +                       const TPM_KEY_HANDLE        keyHandle,
   60.28 +                       const TPM_STORED_DATA       *sealedData,
   60.29 +                       const TPM_AUTHDATA          *key_usage_auth,
   60.30 +                       const TPM_AUTHDATA          *data_usage_auth,
   60.31 +                       buffer_t                    *outData,
   60.32 +                       TCS_AUTH                    *auth,
   60.33 +                       TCS_AUTH                    *dataAuth);
   60.34 +
   60.35  #endif //_VTSP_H_
    61.1 --- a/tools/vtpm_manager/tcs/tcs.c	Mon Jan 09 11:19:55 2006 +0000
    61.2 +++ b/tools/vtpm_manager/tcs/tcs.c	Mon Jan 09 11:22:17 2006 +0000
    61.3 @@ -636,7 +636,7 @@ TPM_RESULT TCSP_Seal(   TCS_CONTEXT_HAND
    61.4    TDDL_UINT32  OutLength = TCPA_MAX_BUFFER_LENGTH;
    61.5    
    61.6    // check input params
    61.7 -  if (inData == NULL || pubAuth == NULL || SealedDataSize == NULL || *SealedData == NULL)
    61.8 +  if (inData == NULL || pubAuth == NULL || SealedDataSize == NULL || SealedData == NULL)
    61.9      return TPM_BAD_PARAMETER;
   61.10    
   61.11    // Convert Byte Input parameter in the input byte stream InBuf
    62.1 --- a/tools/xentrace/Makefile	Mon Jan 09 11:19:55 2006 +0000
    62.2 +++ b/tools/xentrace/Makefile	Mon Jan 09 11:22:17 2006 +0000
    62.3 @@ -15,24 +15,32 @@ HDRS     = $(wildcard *.h)
    62.4  OBJS     = $(patsubst %.c,%.o,$(wildcard *.c))
    62.5  
    62.6  BIN      = xentrace tbctl setsize
    62.7 -LIBBIN   = xenctx
    62.8 +LIBBIN   = 
    62.9  SCRIPTS  = xentrace_format
   62.10  MAN1     = $(wildcard *.1)
   62.11  MAN8     = $(wildcard *.8)
   62.12  
   62.13 +ifeq ($(XEN_TARGET_ARCH),x86_32)
   62.14 +LIBBIN  += xenctx
   62.15 +endif
   62.16 +
   62.17 +ifeq ($(XEN_TARGET_ARCH),x86_64)
   62.18 +LIBBIN  += xenctx
   62.19 +endif
   62.20 +
   62.21  all: build
   62.22  build: $(BIN) $(LIBBIN)
   62.23  
   62.24  install: build
   62.25  	[ -d $(DESTDIR)/usr/bin ] || $(INSTALL_DIR) $(DESTDIR)/usr/bin
   62.26 -	[ -d $(DESTDIR)/usr/$(LIBDIR)/xen/bin ] || \
   62.27 +	[ -z "$(LIBBIN)"] || [ -d $(DESTDIR)/usr/$(LIBDIR)/xen/bin ] || \
   62.28  		$(INSTALL_DIR) $(DESTDIR)/usr/$(LIBDIR)/xen/bin
   62.29  	[ -d $(DESTDIR)/usr/share/man/man1 ] || \
   62.30  		$(INSTALL_DIR) $(DESTDIR)/usr/share/man/man1
   62.31  	[ -d $(DESTDIR)/usr/share/man/man8 ] || \
   62.32  		$(INSTALL_DIR) $(DESTDIR)/usr/share/man/man8
   62.33  	$(INSTALL_PROG) $(BIN) $(SCRIPTS) $(DESTDIR)/usr/bin
   62.34 -	$(INSTALL_PROG) $(LIBBIN) $(DESTDIR)/usr/$(LIBDIR)/xen/bin
   62.35 +	[ -z "$(LIBBIN)"] || $(INSTALL_PROG) $(LIBBIN) $(DESTDIR)/usr/$(LIBDIR)/xen/bin
   62.36  	$(INSTALL_DATA) $(MAN1) $(DESTDIR)/usr/share/man/man1
   62.37  	$(INSTALL_DATA) $(MAN8) $(DESTDIR)/usr/share/man/man8
   62.38  
    63.1 --- a/tools/xentrace/xenctx.c	Mon Jan 09 11:19:55 2006 +0000
    63.2 +++ b/tools/xentrace/xenctx.c	Mon Jan 09 11:22:17 2006 +0000
    63.3 @@ -380,10 +380,10 @@ void dump_ctx(int vcpu)
    63.4          exit(-1);
    63.5      }
    63.6  
    63.7 -    ret = xc_domain_get_vcpu_context(xc_handle, domid, vcpu, &ctx);
    63.8 +    ret = xc_vcpu_getcontext(xc_handle, domid, vcpu, &ctx);
    63.9      if (ret < 0) {
   63.10          xc_domain_unpause(xc_handle, domid);
   63.11 -        perror("xc_domain_get_vcpu_context");
   63.12 +        perror("xc_vcpu_getcontext");
   63.13          exit(-1);
   63.14      }
   63.15  
    64.1 --- a/tools/xm-test/tests/network-attach/Makefile.am	Mon Jan 09 11:19:55 2006 +0000
    64.2 +++ b/tools/xm-test/tests/network-attach/Makefile.am	Mon Jan 09 11:22:17 2006 +0000
    64.3 @@ -6,7 +6,7 @@ TESTS = 01_network_attach_pos.test \
    64.4  	03_network_attach_detach_multiple_pos.test  \
    64.5  	04_network_attach_baddomain_neg.test
    64.6  
    64.7 -XFAIL_TESTS = 03_network_attach_detach_multiple_pos.test
    64.8 +XFAIL_TESTS = 
    64.9  
   64.10  EXTRA_DIST = $(TESTS) $(XFAIL_TESTS) network_utils.py
   64.11  
    65.1 --- a/xen/arch/ia64/Makefile	Mon Jan 09 11:19:55 2006 +0000
    65.2 +++ b/xen/arch/ia64/Makefile	Mon Jan 09 11:22:17 2006 +0000
    65.3 @@ -23,6 +23,13 @@ OBJS +=	bitop.o clear_page.o flush.o cop
    65.4  	__divsi3.o __udivsi3.o __modsi3.o __umodsi3.o			\
    65.5  	__divdi3.o __udivdi3.o __moddi3.o __umoddi3.o
    65.6  
    65.7 +# xen stack unwinder
    65.8 +# unwind_decoder.c is included in unwind.c
    65.9 +OBJS += unwind.o
   65.10 +#unwind.o: CFLAGS += -DUNW_DEBUG=4
   65.11 +
   65.12 +OBJS += process-linux-xen.o
   65.13 +
   65.14  # perfmon.o
   65.15  # unwind.o needed for kernel unwinding (rare)
   65.16  
   65.17 @@ -31,11 +38,26 @@ OBJS := $(subst $(TARGET_ARCH)/asm-offse
   65.18  # remove following line if not privifying in memory
   65.19  # OBJS += privify.o
   65.20  
   65.21 -default: $(OBJS) head.o xen.lds.s
   65.22 -	$(LD) -r -o arch.o $(OBJS)
   65.23 +default: $(TARGET)
   65.24 +
   65.25 +$(CURDIR)/arch.o: $(OBJS)
   65.26 +	$(LD) -r -o $@ $(OBJS)
   65.27 +
   65.28 +$(TARGET)-syms: $(ALL_OBJS) head.o xen.lds.s
   65.29  	$(LD) $(LDFLAGS) -T $(BASEDIR)/arch/$(TARGET_ARCH)/xen.lds.s -N \
   65.30 -		-Map map.out head.o $(ALL_OBJS) -o $(TARGET)-syms
   65.31 -	$(OBJCOPY) -R .note -R .comment -S $(TARGET)-syms $(TARGET)
   65.32 +		-Map map.out head.o $(ALL_OBJS) -o $@
   65.33 +	$(NM) -n $@ | $(BASEDIR)/tools/symbols > $(BASEDIR)/xen-syms.S
   65.34 +	$(MAKE) $(BASEDIR)/xen-syms.o
   65.35 +	$(LD) $(LDFLAGS) -T $(BASEDIR)/arch/$(TARGET_ARCH)/xen.lds.s -N \
   65.36 +		-Map map.out head.o $(ALL_OBJS) $(BASEDIR)/xen-syms.o -o $@
   65.37 +	$(NM) -n $@ | $(BASEDIR)/tools/symbols >$(BASEDIR)/xen-syms.S
   65.38 +	$(MAKE) $(BASEDIR)/xen-syms.o
   65.39 +	$(LD) $(LDFLAGS) -T $(BASEDIR)/arch/$(TARGET_ARCH)/xen.lds.s -N \
   65.40 +		-Map map.out head.o $(ALL_OBJS) $(BASEDIR)/xen-syms.o -o $@
   65.41 +	rm -f $(BASEDIR)/xen-syms.S $(BASEDIR)/xen-syms.o
   65.42 +
   65.43 +$(TARGET): $(TARGET)-syms
   65.44 +	$(OBJCOPY) -R .note -R .comment -S $(TARGET)-syms $@
   65.45  	$(NM) -n $(TARGET)-syms | grep -v '\( [aUw] \)\|\(__crc_\)\|\( \$[adt]\)'\
   65.46  		 > $(BASEDIR)/System.map
   65.47  
    66.1 --- a/xen/arch/ia64/linux-xen/entry.S	Mon Jan 09 11:19:55 2006 +0000
    66.2 +++ b/xen/arch/ia64/linux-xen/entry.S	Mon Jan 09 11:22:17 2006 +0000
    66.3 @@ -1417,7 +1417,6 @@ GLOBAL_ENTRY(ia64_prepare_handle_unalign
    66.4  	br.cond.sptk.many rp				// goes to ia64_leave_kernel
    66.5  END(ia64_prepare_handle_unaligned)
    66.6  
    66.7 -#ifndef XEN
    66.8  	//
    66.9  	// unw_init_running(void (*callback)(info, arg), void *arg)
   66.10  	//
   66.11 @@ -1463,6 +1462,7 @@ 1:	mov gp=loc2				// restore gp
   66.12  	br.ret.sptk.many rp
   66.13  END(unw_init_running)
   66.14  
   66.15 +#ifndef XEN
   66.16  	.rodata
   66.17  	.align 8
   66.18  	.globl sys_call_table
    67.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    67.2 +++ b/xen/arch/ia64/linux-xen/process-linux-xen.c	Mon Jan 09 11:22:17 2006 +0000
    67.3 @@ -0,0 +1,848 @@
    67.4 +/*
    67.5 + * Architecture-specific setup.
    67.6 + *
    67.7 + * Copyright (C) 1998-2003 Hewlett-Packard Co
    67.8 + *	David Mosberger-Tang <davidm@hpl.hp.com>
    67.9 + * 04/11/17 Ashok Raj	<ashok.raj@intel.com> Added CPU Hotplug Support
   67.10 + */
   67.11 +#ifdef XEN
   67.12 +#include <xen/types.h>
   67.13 +#include <xen/lib.h>
   67.14 +#include <xen/symbols.h>
   67.15 +#include <xen/smp.h>
   67.16 +#include <asm/uaccess.h>
   67.17 +#include <asm/processor.h>
   67.18 +#include <asm/ptrace.h>
   67.19 +#include <asm/unwind.h>
   67.20 +#else
   67.21 +#define __KERNEL_SYSCALLS__	/* see <asm/unistd.h> */
   67.22 +#include <linux/config.h>
   67.23 +
   67.24 +#include <linux/cpu.h>
   67.25 +#include <linux/pm.h>
   67.26 +#include <linux/elf.h>
   67.27 +#include <linux/errno.h>
   67.28 +#include <linux/kallsyms.h>
   67.29 +#include <linux/kernel.h>
   67.30 +#include <linux/mm.h>
   67.31 +#include <linux/module.h>
   67.32 +#include <linux/notifier.h>
   67.33 +#include <linux/personality.h>
   67.34 +#include <linux/sched.h>
   67.35 +#include <linux/slab.h>
   67.36 +#include <linux/smp_lock.h>
   67.37 +#include <linux/stddef.h>
   67.38 +#include <linux/thread_info.h>
   67.39 +#include <linux/unistd.h>
   67.40 +#include <linux/efi.h>
   67.41 +#include <linux/interrupt.h>
   67.42 +#include <linux/delay.h>
   67.43 +#include <linux/kprobes.h>
   67.44 +
   67.45 +#include <asm/cpu.h>
   67.46 +#include <asm/delay.h>
   67.47 +#include <asm/elf.h>
   67.48 +#include <asm/ia32.h>
   67.49 +#include <asm/irq.h>
   67.50 +#include <asm/pgalloc.h>
   67.51 +#include <asm/processor.h>
   67.52 +#include <asm/sal.h>
   67.53 +#include <asm/tlbflush.h>
   67.54 +#include <asm/uaccess.h>
   67.55 +#include <asm/unwind.h>
   67.56 +#include <asm/user.h>
   67.57 +
   67.58 +#include "entry.h"
   67.59 +
   67.60 +#ifdef CONFIG_PERFMON
   67.61 +# include <asm/perfmon.h>
   67.62 +#endif
   67.63 +
   67.64 +#include "sigframe.h"
   67.65 +
   67.66 +void (*ia64_mark_idle)(int);
   67.67 +static DEFINE_PER_CPU(unsigned int, cpu_idle_state);
   67.68 +
   67.69 +unsigned long boot_option_idle_override = 0;
   67.70 +EXPORT_SYMBOL(boot_option_idle_override);
   67.71 +#endif
   67.72 +
   67.73 +void
   67.74 +ia64_do_show_stack (struct unw_frame_info *info, void *arg)
   67.75 +{
   67.76 +	unsigned long ip, sp, bsp;
   67.77 +	char buf[128];			/* don't make it so big that it overflows the stack! */
   67.78 +
   67.79 +	printk("\nCall Trace:\n");
   67.80 +	do {
   67.81 +		unw_get_ip(info, &ip);
   67.82 +		if (ip == 0)
   67.83 +			break;
   67.84 +
   67.85 +		unw_get_sp(info, &sp);
   67.86 +		unw_get_bsp(info, &bsp);
   67.87 +		snprintf(buf, sizeof(buf),
   67.88 +			 " [<%016lx>] %%s\n"
   67.89 +			 "                                sp=%016lx bsp=%016lx\n",
   67.90 +			 ip, sp, bsp);
   67.91 +		print_symbol(buf, ip);
   67.92 +	} while (unw_unwind(info) >= 0);
   67.93 +}
   67.94 +
   67.95 +void
   67.96 +show_stack (struct task_struct *task, unsigned long *sp)
   67.97 +{
   67.98 +	if (!task)
   67.99 +		unw_init_running(ia64_do_show_stack, NULL);
  67.100 +	else {
  67.101 +		struct unw_frame_info info;
  67.102 +
  67.103 +		unw_init_from_blocked_task(&info, task);
  67.104 +		ia64_do_show_stack(&info, NULL);
  67.105 +	}
  67.106 +}
  67.107 +
  67.108 +#ifndef XEN
  67.109 +void
  67.110 +dump_stack (void)
  67.111 +{
  67.112 +	show_stack(NULL, NULL);
  67.113 +}
  67.114 +
  67.115 +EXPORT_SYMBOL(dump_stack);
  67.116 +#endif
  67.117 +
  67.118 +#ifdef XEN
  67.119 +void
  67.120 +show_registers(struct pt_regs *regs)
  67.121 +#else
  67.122 +void
  67.123 +show_regs (struct pt_regs *regs)
  67.124 +#endif
  67.125 +{
  67.126 +	unsigned long ip = regs->cr_iip + ia64_psr(regs)->ri;
  67.127 +
  67.128 +#ifndef XEN
  67.129 +	print_modules();
  67.130 +	printk("\nPid: %d, CPU %d, comm: %20s\n", current->pid, smp_processor_id(), current->comm);
  67.131 +	printk("psr : %016lx ifs : %016lx ip  : [<%016lx>]    %s\n",
  67.132 +	       regs->cr_ipsr, regs->cr_ifs, ip, print_tainted());
  67.133 +#else
  67.134 +	printk("\nCPU %d\n", smp_processor_id());
  67.135 +	printk("psr : %016lx ifs : %016lx ip  : [<%016lx>]\n",
  67.136 +	       regs->cr_ipsr, regs->cr_ifs, ip);
  67.137 +#endif
  67.138 +	print_symbol("ip is at %s\n", ip);
  67.139 +	printk("unat: %016lx pfs : %016lx rsc : %016lx\n",
  67.140 +	       regs->ar_unat, regs->ar_pfs, regs->ar_rsc);
  67.141 +	printk("rnat: %016lx bsps: %016lx pr  : %016lx\n",
  67.142 +	       regs->ar_rnat, regs->ar_bspstore, regs->pr);
  67.143 +	printk("ldrs: %016lx ccv : %016lx fpsr: %016lx\n",
  67.144 +	       regs->loadrs, regs->ar_ccv, regs->ar_fpsr);
  67.145 +	printk("csd : %016lx ssd : %016lx\n", regs->ar_csd, regs->ar_ssd);
  67.146 +	printk("b0  : %016lx b6  : %016lx b7  : %016lx\n", regs->b0, regs->b6, regs->b7);
  67.147 +	printk("f6  : %05lx%016lx f7  : %05lx%016lx\n",
  67.148 +	       regs->f6.u.bits[1], regs->f6.u.bits[0],
  67.149 +	       regs->f7.u.bits[1], regs->f7.u.bits[0]);
  67.150 +	printk("f8  : %05lx%016lx f9  : %05lx%016lx\n",
  67.151 +	       regs->f8.u.bits[1], regs->f8.u.bits[0],
  67.152 +	       regs->f9.u.bits[1], regs->f9.u.bits[0]);
  67.153 +	printk("f10 : %05lx%016lx f11 : %05lx%016lx\n",
  67.154 +	       regs->f10.u.bits[1], regs->f10.u.bits[0],
  67.155 +	       regs->f11.u.bits[1], regs->f11.u.bits[0]);
  67.156 +
  67.157 +	printk("r1  : %016lx r2  : %016lx r3  : %016lx\n", regs->r1, regs->r2, regs->r3);
  67.158 +	printk("r8  : %016lx r9  : %016lx r10 : %016lx\n", regs->r8, regs->r9, regs->r10);
  67.159 +	printk("r11 : %016lx r12 : %016lx r13 : %016lx\n", regs->r11, regs->r12, regs->r13);
  67.160 +	printk("r14 : %016lx r15 : %016lx r16 : %016lx\n", regs->r14, regs->r15, regs->r16);
  67.161 +	printk("r17 : %016lx r18 : %016lx r19 : %016lx\n", regs->r17, regs->r18, regs->r19);
  67.162 +	printk("r20 : %016lx r21 : %016lx r22 : %016lx\n", regs->r20, regs->r21, regs->r22);
  67.163 +	printk("r23 : %016lx r24 : %016lx r25 : %016lx\n", regs->r23, regs->r24, regs->r25);
  67.164 +	printk("r26 : %016lx r27 : %016lx r28 : %016lx\n", regs->r26, regs->r27, regs->r28);
  67.165 +	printk("r29 : %016lx r30 : %016lx r31 : %016lx\n", regs->r29, regs->r30, regs->r31);
  67.166 +
  67.167 +	if (user_mode(regs)) {
  67.168 +		/* print the stacked registers */
  67.169 +		unsigned long val, *bsp, ndirty;
  67.170 +		int i, sof, is_nat = 0;
  67.171 +
  67.172 +		sof = regs->cr_ifs & 0x7f;	/* size of frame */
  67.173 +		ndirty = (regs->loadrs >> 19);
  67.174 +		bsp = ia64_rse_skip_regs((unsigned long *) regs->ar_bspstore, ndirty);
  67.175 +		for (i = 0; i < sof; ++i) {
  67.176 +			get_user(val, (unsigned long __user *) ia64_rse_skip_regs(bsp, i));
  67.177 +			printk("r%-3u:%c%016lx%s", 32 + i, is_nat ? '*' : ' ', val,
  67.178 +			       ((i == sof - 1) || (i % 3) == 2) ? "\n" : " ");
  67.179 +		}
  67.180 +	} else
  67.181 +		show_stack(NULL, NULL);
  67.182 +}
  67.183 +
  67.184 +#ifndef XEN
  67.185 +void
  67.186 +do_notify_resume_user (sigset_t *oldset, struct sigscratch *scr, long in_syscall)
  67.187 +{
  67.188 +	if (fsys_mode(current, &scr->pt)) {
  67.189 +		/* defer signal-handling etc. until we return to privilege-level 0.  */
  67.190 +		if (!ia64_psr(&scr->pt)->lp)
  67.191 +			ia64_psr(&scr->pt)->lp = 1;
  67.192 +		return;
  67.193 +	}
  67.194 +
  67.195 +#ifdef CONFIG_PERFMON
  67.196 +	if (current->thread.pfm_needs_checking)
  67.197 +		pfm_handle_work();
  67.198 +#endif
  67.199 +
  67.200 +	/* deal with pending signal delivery */
  67.201 +	if (test_thread_flag(TIF_SIGPENDING))
  67.202 +		ia64_do_signal(oldset, scr, in_syscall);
  67.203 +}
  67.204 +
  67.205 +static int pal_halt        = 1;
  67.206 +static int can_do_pal_halt = 1;
  67.207 +
  67.208 +static int __init nohalt_setup(char * str)
  67.209 +{
  67.210 +	pal_halt = can_do_pal_halt = 0;
  67.211 +	return 1;
  67.212 +}
  67.213 +__setup("nohalt", nohalt_setup);
  67.214 +
  67.215 +void
  67.216 +update_pal_halt_status(int status)
  67.217 +{
  67.218 +	can_do_pal_halt = pal_halt && status;
  67.219 +}
  67.220 +
  67.221 +/*
  67.222 + * We use this if we don't have any better idle routine..
  67.223 + */
  67.224 +void
  67.225 +default_idle (void)
  67.226 +{
  67.227 +	local_irq_enable();
  67.228 +	while (!need_resched())
  67.229 +		if (can_do_pal_halt)
  67.230 +			safe_halt();
  67.231 +		else
  67.232 +			cpu_relax();
  67.233 +}
  67.234 +
  67.235 +#ifdef CONFIG_HOTPLUG_CPU
  67.236 +/* We don't actually take CPU down, just spin without interrupts. */
  67.237 +static inline void play_dead(void)
  67.238 +{
  67.239 +	extern void ia64_cpu_local_tick (void);
  67.240 +	unsigned int this_cpu = smp_processor_id();
  67.241 +
  67.242 +	/* Ack it */
  67.243 +	__get_cpu_var(cpu_state) = CPU_DEAD;
  67.244 +
  67.245 +	max_xtp();
  67.246 +	local_irq_disable();
  67.247 +	idle_domain_exit();
  67.248 +	ia64_jump_to_sal(&sal_boot_rendez_state[this_cpu]);
  67.249 +	/*
  67.250 +	 * The above is a point of no-return, the processor is
  67.251 +	 * expected to be in SAL loop now.
  67.252 +	 */
  67.253 +	BUG();
  67.254 +}
  67.255 +#else
  67.256 +static inline void play_dead(void)
  67.257 +{
  67.258 +	BUG();
  67.259 +}
  67.260 +#endif /* CONFIG_HOTPLUG_CPU */
  67.261 +
  67.262 +void cpu_idle_wait(void)
  67.263 +{
  67.264 +	unsigned int cpu, this_cpu = get_cpu();
  67.265 +	cpumask_t map;
  67.266 +
  67.267 +	set_cpus_allowed(current, cpumask_of_cpu(this_cpu));
  67.268 +	put_cpu();
  67.269 +
  67.270 +	cpus_clear(map);
  67.271 +	for_each_online_cpu(cpu) {
  67.272 +		per_cpu(cpu_idle_state, cpu) = 1;
  67.273 +		cpu_set(cpu, map);
  67.274 +	}
  67.275 +
  67.276 +	__get_cpu_var(cpu_idle_state) = 0;
  67.277 +
  67.278 +	wmb();
  67.279 +	do {
  67.280 +		ssleep(1);
  67.281 +		for_each_online_cpu(cpu) {
  67.282 +			if (cpu_isset(cpu, map) && !per_cpu(cpu_idle_state, cpu))
  67.283 +				cpu_clear(cpu, map);
  67.284 +		}
  67.285 +		cpus_and(map, map, cpu_online_map);
  67.286 +	} while (!cpus_empty(map));
  67.287 +}
  67.288 +EXPORT_SYMBOL_GPL(cpu_idle_wait);
  67.289 +
  67.290 +void __attribute__((noreturn))
  67.291 +cpu_idle (void)
  67.292 +{
  67.293 +	void (*mark_idle)(int) = ia64_mark_idle;
  67.294 +
  67.295 +	/* endless idle loop with no priority at all */
  67.296 +	while (1) {
  67.297 +#ifdef CONFIG_SMP
  67.298 +		if (!need_resched())
  67.299 +			min_xtp();
  67.300 +#endif
  67.301 +		while (!need_resched()) {
  67.302 +			void (*idle)(void);
  67.303 +
  67.304 +			if (__get_cpu_var(cpu_idle_state))
  67.305 +				__get_cpu_var(cpu_idle_state) = 0;
  67.306 +
  67.307 +			rmb();
  67.308 +			if (mark_idle)
  67.309 +				(*mark_idle)(1);
  67.310 +
  67.311 +			idle = pm_idle;
  67.312 +			if (!idle)
  67.313 +				idle = default_idle;
  67.314 +			(*idle)();
  67.315 +		}
  67.316 +
  67.317 +		if (mark_idle)
  67.318 +			(*mark_idle)(0);
  67.319 +
  67.320 +#ifdef CONFIG_SMP
  67.321 +		normal_xtp();
  67.322 +#endif
  67.323 +		schedule();
  67.324 +		check_pgt_cache();
  67.325 +		if (cpu_is_offline(smp_processor_id()))
  67.326 +			play_dead();
  67.327 +	}
  67.328 +}
  67.329 +
  67.330 +void
  67.331 +ia64_save_extra (struct task_struct *task)
  67.332 +{
  67.333 +#ifdef CONFIG_PERFMON
  67.334 +	unsigned long info;
  67.335 +#endif
  67.336 +
  67.337 +	if ((task->thread.flags & IA64_THREAD_DBG_VALID) != 0)
  67.338 +		ia64_save_debug_regs(&task->thread.dbr[0]);
  67.339 +
  67.340 +#ifdef CONFIG_PERFMON
  67.341 +	if ((task->thread.flags & IA64_THREAD_PM_VALID) != 0)
  67.342 +		pfm_save_regs(task);
  67.343 +
  67.344 +	info = __get_cpu_var(pfm_syst_info);
  67.345 +	if (info & PFM_CPUINFO_SYST_WIDE)
  67.346 +		pfm_syst_wide_update_task(task, info, 0);
  67.347 +#endif
  67.348 +
  67.349 +#ifdef CONFIG_IA32_SUPPORT
  67.350 +	if (IS_IA32_PROCESS(ia64_task_regs(task)))
  67.351 +		ia32_save_state(task);
  67.352 +#endif
  67.353 +}
  67.354 +
  67.355 +void
  67.356 +ia64_load_extra (struct task_struct *task)
  67.357 +{
  67.358 +#ifdef CONFIG_PERFMON
  67.359 +	unsigned long info;
  67.360 +#endif
  67.361 +
  67.362 +	if ((task->thread.flags & IA64_THREAD_DBG_VALID) != 0)
  67.363 +		ia64_load_debug_regs(&task->thread.dbr[0]);
  67.364 +
  67.365 +#ifdef CONFIG_PERFMON
  67.366 +	if ((task->thread.flags & IA64_THREAD_PM_VALID) != 0)
  67.367 +		pfm_load_regs(task);
  67.368 +
  67.369 +	info = __get_cpu_var(pfm_syst_info);
  67.370 +	if (info & PFM_CPUINFO_SYST_WIDE) 
  67.371 +		pfm_syst_wide_update_task(task, info, 1);
  67.372 +#endif
  67.373 +
  67.374 +#ifdef CONFIG_IA32_SUPPORT
  67.375 +	if (IS_IA32_PROCESS(ia64_task_regs(task)))
  67.376 +		ia32_load_state(task);
  67.377 +#endif
  67.378 +}
  67.379 +
  67.380 +/*
  67.381 + * Copy the state of an ia-64 thread.
  67.382 + *
  67.383 + * We get here through the following  call chain:
  67.384 + *
  67.385 + *	from user-level:	from kernel:
  67.386 + *
  67.387 + *	<clone syscall>	        <some kernel call frames>
  67.388 + *	sys_clone		   :
  67.389 + *	do_fork			do_fork
  67.390 + *	copy_thread		copy_thread
  67.391 + *
  67.392 + * This means that the stack layout is as follows:
  67.393 + *
  67.394 + *	+---------------------+ (highest addr)
  67.395 + *	|   struct pt_regs    |
  67.396 + *	+---------------------+
  67.397 + *	| struct switch_stack |
  67.398 + *	+---------------------+
  67.399 + *	|                     |
  67.400 + *	|    memory stack     |
  67.401 + *	|                     | <-- sp (lowest addr)
  67.402 + *	+---------------------+
  67.403 + *
  67.404 + * Observe that we copy the unat values that are in pt_regs and switch_stack.  Spilling an
  67.405 + * integer to address X causes bit N in ar.unat to be set to the NaT bit of the register,
  67.406 + * with N=(X & 0x1ff)/8.  Thus, copying the unat value preserves the NaT bits ONLY if the
  67.407 + * pt_regs structure in the parent is congruent to that of the child, modulo 512.  Since
  67.408 + * the stack is page aligned and the page size is at least 4KB, this is always the case,
  67.409 + * so there is nothing to worry about.
  67.410 + */
  67.411 +int
  67.412 +copy_thread (int nr, unsigned long clone_flags,
  67.413 +	     unsigned long user_stack_base, unsigned long user_stack_size,
  67.414 +	     struct task_struct *p, struct pt_regs *regs)
  67.415 +{
  67.416 +	extern char ia64_ret_from_clone, ia32_ret_from_clone;
  67.417 +	struct switch_stack *child_stack, *stack;
  67.418 +	unsigned long rbs, child_rbs, rbs_size;
  67.419 +	struct pt_regs *child_ptregs;
  67.420 +	int retval = 0;
  67.421 +
  67.422 +#ifdef CONFIG_SMP
  67.423 +	/*
  67.424 +	 * For SMP idle threads, fork_by_hand() calls do_fork with
  67.425 +	 * NULL regs.
  67.426 +	 */
  67.427 +	if (!regs)
  67.428 +		return 0;
  67.429 +#endif
  67.430 +
  67.431 +	stack = ((struct switch_stack *) regs) - 1;
  67.432 +
  67.433 +	child_ptregs = (struct pt_regs *) ((unsigned long) p + IA64_STK_OFFSET) - 1;
  67.434 +	child_stack = (struct switch_stack *) child_ptregs - 1;
  67.435 +
  67.436 +	/* copy parent's switch_stack & pt_regs to child: */
  67.437 +	memcpy(child_stack, stack, sizeof(*child_ptregs) + sizeof(*child_stack));
  67.438 +
  67.439 +	rbs = (unsigned long) current + IA64_RBS_OFFSET;
  67.440 +	child_rbs = (unsigned long) p + IA64_RBS_OFFSET;
  67.441 +	rbs_size = stack->ar_bspstore - rbs;
  67.442 +
  67.443 +	/* copy the parent's register backing store to the child: */
  67.444 +	memcpy((void *) child_rbs, (void *) rbs, rbs_size);
  67.445 +
  67.446 +	if (likely(user_mode(child_ptregs))) {
  67.447 +		if ((clone_flags & CLONE_SETTLS) && !IS_IA32_PROCESS(regs))
  67.448 +			child_ptregs->r13 = regs->r16;	/* see sys_clone2() in entry.S */
  67.449 +		if (user_stack_base) {
  67.450 +			child_ptregs->r12 = user_stack_base + user_stack_size - 16;
  67.451 +			child_ptregs->ar_bspstore = user_stack_base;
  67.452 +			child_ptregs->ar_rnat = 0;
  67.453 +			child_ptregs->loadrs = 0;
  67.454 +		}
  67.455 +	} else {
  67.456 +		/*
  67.457 +		 * Note: we simply preserve the relative position of
  67.458 +		 * the stack pointer here.  There is no need to
  67.459 +		 * allocate a scratch area here, since that will have
  67.460 +		 * been taken care of by the caller of sys_clone()
  67.461 +		 * already.
  67.462 +		 */
  67.463 +		child_ptregs->r12 = (unsigned long) child_ptregs - 16; /* kernel sp */
  67.464 +		child_ptregs->r13 = (unsigned long) p;		/* set `current' pointer */
  67.465 +	}
  67.466 +	child_stack->ar_bspstore = child_rbs + rbs_size;
  67.467 +	if (IS_IA32_PROCESS(regs))
  67.468 +		child_stack->b0 = (unsigned long) &ia32_ret_from_clone;
  67.469 +	else
  67.470 +		child_stack->b0 = (unsigned long) &ia64_ret_from_clone;
  67.471 +
  67.472 +	/* copy parts of thread_struct: */
  67.473 +	p->thread.ksp = (unsigned long) child_stack - 16;
  67.474 +
  67.475 +	/* stop some PSR bits from being inherited.
  67.476 +	 * the psr.up/psr.pp bits must be cleared on fork but inherited on execve()
  67.477 +	 * therefore we must specify them explicitly here and not include them in
  67.478 +	 * IA64_PSR_BITS_TO_CLEAR.
  67.479 +	 */
  67.480 +	child_ptregs->cr_ipsr = ((child_ptregs->cr_ipsr | IA64_PSR_BITS_TO_SET)
  67.481 +				 & ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_PP | IA64_PSR_UP));
  67.482 +
  67.483 +	/*
  67.484 +	 * NOTE: The calling convention considers all floating point
  67.485 +	 * registers in the high partition (fph) to be scratch.  Since
  67.486 +	 * the only way to get to this point is through a system call,
  67.487 +	 * we know that the values in fph are all dead.  Hence, there
  67.488 +	 * is no need to inherit the fph state from the parent to the
  67.489 +	 * child and all we have to do is to make sure that
  67.490 +	 * IA64_THREAD_FPH_VALID is cleared in the child.
  67.491 +	 *
  67.492 +	 * XXX We could push this optimization a bit further by
  67.493 +	 * clearing IA64_THREAD_FPH_VALID on ANY system call.
  67.494 +	 * However, it's not clear this is worth doing.  Also, it
  67.495 +	 * would be a slight deviation from the normal Linux system
  67.496 +	 * call behavior where scratch registers are preserved across
  67.497 +	 * system calls (unless used by the system call itself).
  67.498 +	 */
  67.499 +#	define THREAD_FLAGS_TO_CLEAR	(IA64_THREAD_FPH_VALID | IA64_THREAD_DBG_VALID \
  67.500 +					 | IA64_THREAD_PM_VALID)
  67.501 +#	define THREAD_FLAGS_TO_SET	0
  67.502 +	p->thread.flags = ((current->thread.flags & ~THREAD_FLAGS_TO_CLEAR)
  67.503 +			   | THREAD_FLAGS_TO_SET);
  67.504 +	ia64_drop_fpu(p);	/* don't pick up stale state from a CPU's fph */
  67.505 +#ifdef CONFIG_IA32_SUPPORT
  67.506 +	/*
  67.507 +	 * If we're cloning an IA32 task then save the IA32 extra
  67.508 +	 * state from the current task to the new task
  67.509 +	 */
  67.510 +	if (IS_IA32_PROCESS(ia64_task_regs(current))) {
  67.511 +		ia32_save_state(p);
  67.512 +		if (clone_flags & CLONE_SETTLS)
  67.513 +			retval = ia32_clone_tls(p, child_ptregs);
  67.514 +
  67.515 +		/* Copy partially mapped page list */
  67.516 +		if (!retval)
  67.517 +			retval = ia32_copy_partial_page_list(p, clone_flags);
  67.518 +	}
  67.519 +#endif
  67.520 +
  67.521 +#ifdef CONFIG_PERFMON
  67.522 +	if (current->thread.pfm_context)
  67.523 +		pfm_inherit(p, child_ptregs);
  67.524 +#endif
  67.525 +	return retval;
  67.526 +}
  67.527 +
  67.528 +static void
  67.529 +do_copy_task_regs (struct task_struct *task, struct unw_frame_info *info, void *arg)
  67.530 +{
  67.531 +	unsigned long mask, sp, nat_bits = 0, ip, ar_rnat, urbs_end, cfm;
  67.532 +	elf_greg_t *dst = arg;
  67.533 +	struct pt_regs *pt;
  67.534 +	char nat;
  67.535 +	int i;
  67.536 +
  67.537 +	memset(dst, 0, sizeof(elf_gregset_t));	/* don't leak any kernel bits to user-level */
  67.538 +
  67.539 +	if (unw_unwind_to_user(info) < 0)
  67.540 +		return;
  67.541 +
  67.542 +	unw_get_sp(info, &sp);
  67.543 +	pt = (struct pt_regs *) (sp + 16);
  67.544 +
  67.545 +	urbs_end = ia64_get_user_rbs_end(task, pt, &cfm);
  67.546 +
  67.547 +	if (ia64_sync_user_rbs(task, info->sw, pt->ar_bspstore, urbs_end) < 0)
  67.548 +		return;
  67.549 +
  67.550 +	ia64_peek(task, info->sw, urbs_end, (long) ia64_rse_rnat_addr((long *) urbs_end),
  67.551 +		  &ar_rnat);
  67.552 +
  67.553 +	/*
  67.554 +	 * coredump format:
  67.555 +	 *	r0-r31
  67.556 +	 *	NaT bits (for r0-r31; bit N == 1 iff rN is a NaT)
  67.557 +	 *	predicate registers (p0-p63)
  67.558 +	 *	b0-b7
  67.559 +	 *	ip cfm user-mask
  67.560 +	 *	ar.rsc ar.bsp ar.bspstore ar.rnat
  67.561 +	 *	ar.ccv ar.unat ar.fpsr ar.pfs ar.lc ar.ec
  67.562 +	 */
  67.563 +
  67.564 +	/* r0 is zero */
  67.565 +	for (i = 1, mask = (1UL << i); i < 32; ++i) {
  67.566 +		unw_get_gr(info, i, &dst[i], &nat);
  67.567 +		if (nat)
  67.568 +			nat_bits |= mask;
  67.569 +		mask <<= 1;
  67.570 +	}
  67.571 +	dst[32] = nat_bits;
  67.572 +	unw_get_pr(info, &dst[33]);
  67.573 +
  67.574 +	for (i = 0; i < 8; ++i)
  67.575 +		unw_get_br(info, i, &dst[34 + i]);
  67.576 +
  67.577 +	unw_get_rp(info, &ip);
  67.578 +	dst[42] = ip + ia64_psr(pt)->ri;
  67.579 +	dst[43] = cfm;
  67.580 +	dst[44] = pt->cr_ipsr & IA64_PSR_UM;
  67.581 +
  67.582 +	unw_get_ar(info, UNW_AR_RSC, &dst[45]);
  67.583 +	/*
  67.584 +	 * For bsp and bspstore, unw_get_ar() would return the kernel
  67.585 +	 * addresses, but we need the user-level addresses instead:
  67.586 +	 */
  67.587 +	dst[46] = urbs_end;	/* note: by convention PT_AR_BSP points to the end of the urbs! */
  67.588 +	dst[47] = pt->ar_bspstore;
  67.589 +	dst[48] = ar_rnat;
  67.590 +	unw_get_ar(info, UNW_AR_CCV, &dst[49]);
  67.591 +	unw_get_ar(info, UNW_AR_UNAT, &dst[50]);
  67.592 +	unw_get_ar(info, UNW_AR_FPSR, &dst[51]);
  67.593 +	dst[52] = pt->ar_pfs;	/* UNW_AR_PFS is == to pt->cr_ifs for interrupt frames */
  67.594 +	unw_get_ar(info, UNW_AR_LC, &dst[53]);
  67.595 +	unw_get_ar(info, UNW_AR_EC, &dst[54]);
  67.596 +	unw_get_ar(info, UNW_AR_CSD, &dst[55]);
  67.597 +	unw_get_ar(info, UNW_AR_SSD, &dst[56]);
  67.598 +}
  67.599 +
  67.600 +void
  67.601 +do_dump_task_fpu (struct task_struct *task, struct unw_frame_info *info, void *arg)
  67.602 +{
  67.603 +	elf_fpreg_t *dst = arg;
  67.604 +	int i;
  67.605 +
  67.606 +	memset(dst, 0, sizeof(elf_fpregset_t));	/* don't leak any "random" bits */
  67.607 +
  67.608 +	if (unw_unwind_to_user(info) < 0)
  67.609 +		return;
  67.610 +
  67.611 +	/* f0 is 0.0, f1 is 1.0 */
  67.612 +
  67.613 +	for (i = 2; i < 32; ++i)
  67.614 +		unw_get_fr(info, i, dst + i);
  67.615 +
  67.616 +	ia64_flush_fph(task);
  67.617 +	if ((task->thread.flags & IA64_THREAD_FPH_VALID) != 0)
  67.618 +		memcpy(dst + 32, task->thread.fph, 96*16);
  67.619 +}
  67.620 +
  67.621 +void
  67.622 +do_copy_regs (struct unw_frame_info *info, void *arg)
  67.623 +{
  67.624 +	do_copy_task_regs(current, info, arg);
  67.625 +}
  67.626 +
  67.627 +void
  67.628 +do_dump_fpu (struct unw_frame_info *info, void *arg)
  67.629 +{
  67.630 +	do_dump_task_fpu(current, info, arg);
  67.631 +}
  67.632 +
  67.633 +int
  67.634 +dump_task_regs(struct task_struct *task, elf_gregset_t *regs)
  67.635 +{
  67.636 +	struct unw_frame_info tcore_info;
  67.637 +
  67.638 +	if (current == task) {
  67.639 +		unw_init_running(do_copy_regs, regs);
  67.640 +	} else {
  67.641 +		memset(&tcore_info, 0, sizeof(tcore_info));
  67.642 +		unw_init_from_blocked_task(&tcore_info, task);
  67.643 +		do_copy_task_regs(task, &tcore_info, regs);
  67.644 +	}
  67.645 +	return 1;
  67.646 +}
  67.647 +
  67.648 +void
  67.649 +ia64_elf_core_copy_regs (struct pt_regs *pt, elf_gregset_t dst)
  67.650 +{
  67.651 +	unw_init_running(do_copy_regs, dst);
  67.652 +}
  67.653 +
  67.654 +int
  67.655 +dump_task_fpu (struct task_struct *task, elf_fpregset_t *dst)
  67.656 +{
  67.657 +	struct unw_frame_info tcore_info;
  67.658 +
  67.659 +	if (current == task) {
  67.660 +		unw_init_running(do_dump_fpu, dst);
  67.661 +	} else {
  67.662 +		memset(&tcore_info, 0, sizeof(tcore_info));
  67.663 +		unw_init_from_blocked_task(&tcore_info, task);
  67.664 +		do_dump_task_fpu(task, &tcore_info, dst);
  67.665 +	}
  67.666 +	return 1;
  67.667 +}
  67.668 +
  67.669 +int
  67.670 +dump_fpu (struct pt_regs *pt, elf_fpregset_t dst)
  67.671 +{
  67.672 +	unw_init_running(do_dump_fpu, dst);
  67.673 +	return 1;	/* f0-f31 are always valid so we always return 1 */
  67.674 +}
  67.675 +
  67.676 +long
  67.677 +sys_execve (char __user *filename, char __user * __user *argv, char __user * __user *envp,
  67.678 +	    struct pt_regs *regs)
  67.679 +{
  67.680 +	char *fname;
  67.681 +	int error;
  67.682 +
  67.683 +	fname = getname(filename);
  67.684 +	error = PTR_ERR(fname);
  67.685 +	if (IS_ERR(fname))
  67.686 +		goto out;
  67.687 +	error = do_execve(fname, argv, envp, regs);
  67.688 +	putname(fname);
  67.689 +out:
  67.690 +	return error;
  67.691 +}
  67.692 +
  67.693 +pid_t
  67.694 +kernel_thread (int (*fn)(void *), void *arg, unsigned long flags)
  67.695 +{
  67.696 +	extern void start_kernel_thread (void);
  67.697 +	unsigned long *helper_fptr = (unsigned long *) &start_kernel_thread;
  67.698 +	struct {
  67.699 +		struct switch_stack sw;
  67.700 +		struct pt_regs pt;
  67.701 +	} regs;
  67.702 +
  67.703 +	memset(&regs, 0, sizeof(regs));
  67.704 +	regs.pt.cr_iip = helper_fptr[0];	/* set entry point (IP) */
  67.705 +	regs.pt.r1 = helper_fptr[1];		/* set GP */
  67.706 +	regs.pt.r9 = (unsigned long) fn;	/* 1st argument */
  67.707 +	regs.pt.r11 = (unsigned long) arg;	/* 2nd argument */
  67.708 +	/* Preserve PSR bits, except for bits 32-34 and 37-45, which we can't read.  */
  67.709 +	regs.pt.cr_ipsr = ia64_getreg(_IA64_REG_PSR) | IA64_PSR_BN;
  67.710 +	regs.pt.cr_ifs = 1UL << 63;		/* mark as valid, empty frame */
  67.711 +	regs.sw.ar_fpsr = regs.pt.ar_fpsr = ia64_getreg(_IA64_REG_AR_FPSR);
  67.712 +	regs.sw.ar_bspstore = (unsigned long) current + IA64_RBS_OFFSET;
  67.713 +	regs.sw.pr = (1 << PRED_KERNEL_STACK);
  67.714 +	return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs.pt, 0, NULL, NULL);
  67.715 +}
  67.716 +EXPORT_SYMBOL(kernel_thread);
  67.717 +
  67.718 +/* This gets called from kernel_thread() via ia64_invoke_thread_helper().  */
  67.719 +int
  67.720 +kernel_thread_helper (int (*fn)(void *), void *arg)
  67.721 +{
  67.722 +#ifdef CONFIG_IA32_SUPPORT
  67.723 +	if (IS_IA32_PROCESS(ia64_task_regs(current))) {
  67.724 +		/* A kernel thread is always a 64-bit process. */
  67.725 +		current->thread.map_base  = DEFAULT_MAP_BASE;
  67.726 +		current->thread.task_size = DEFAULT_TASK_SIZE;
  67.727 +		ia64_set_kr(IA64_KR_IO_BASE, current->thread.old_iob);
  67.728 +		ia64_set_kr(IA64_KR_TSSD, current->thread.old_k1);
  67.729 +	}
  67.730 +#endif
  67.731 +	return (*fn)(arg);
  67.732 +}
  67.733 +
  67.734 +/*
  67.735 + * Flush thread state.  This is called when a thread does an execve().
  67.736 + */
  67.737 +void
  67.738 +flush_thread (void)
  67.739 +{
  67.740 +	/*
  67.741 +	 * Remove function-return probe instances associated with this task
  67.742 +	 * and put them back on the free list. Do not insert an exit probe for
  67.743 +	 * this function, it will be disabled by kprobe_flush_task if you do.
  67.744 +	 */
  67.745 +	kprobe_flush_task(current);
  67.746 +
  67.747 +	/* drop floating-point and debug-register state if it exists: */
  67.748 +	current->thread.flags &= ~(IA64_THREAD_FPH_VALID | IA64_THREAD_DBG_VALID);
  67.749 +	ia64_drop_fpu(current);
  67.750 +	if (IS_IA32_PROCESS(ia64_task_regs(current)))
  67.751 +		ia32_drop_partial_page_list(current);
  67.752 +}
  67.753 +
  67.754 +/*
  67.755 + * Clean up state associated with current thread.  This is called when
  67.756 + * the thread calls exit().
  67.757 + */
  67.758 +void
  67.759 +exit_thread (void)
  67.760 +{
  67.761 +
  67.762 +	/*
  67.763 +	 * Remove function-return probe instances associated with this task
  67.764 +	 * and put them back on the free list. Do not insert an exit probe for
  67.765 +	 * this function, it will be disabled by kprobe_flush_task if you do.
  67.766 +	 */
  67.767 +	kprobe_flush_task(current);
  67.768 +
  67.769 +	ia64_drop_fpu(current);
  67.770 +#ifdef CONFIG_PERFMON
  67.771 +       /* if needed, stop monitoring and flush state to perfmon context */
  67.772 +	if (current->thread.pfm_context)
  67.773 +		pfm_exit_thread(current);
  67.774 +
  67.775 +	/* free debug register resources */
  67.776 +	if (current->thread.flags & IA64_THREAD_DBG_VALID)
  67.777 +		pfm_release_debug_registers(current);
  67.778 +#endif
  67.779 +	if (IS_IA32_PROCESS(ia64_task_regs(current)))
  67.780 +		ia32_drop_partial_page_list(current);
  67.781 +}
  67.782 +
  67.783 +unsigned long
  67.784 +get_wchan (struct task_struct *p)
  67.785 +{
  67.786 +	struct unw_frame_info info;
  67.787 +	unsigned long ip;
  67.788 +	int count = 0;
  67.789 +
  67.790 +	/*
  67.791 +	 * Note: p may not be a blocked task (it could be current or
  67.792 +	 * another process running on some other CPU.  Rather than
  67.793 +	 * trying to determine if p is really blocked, we just assume
  67.794 +	 * it's blocked and rely on the unwind routines to fail
  67.795 +	 * gracefully if the process wasn't really blocked after all.
  67.796 +	 * --davidm 99/12/15
  67.797 +	 */
  67.798 +	unw_init_from_blocked_task(&info, p);
  67.799 +	do {
  67.800 +		if (unw_unwind(&info) < 0)
  67.801 +			return 0;
  67.802 +		unw_get_ip(&info, &ip);
  67.803 +		if (!in_sched_functions(ip))
  67.804 +			return ip;
  67.805 +	} while (count++ < 16);
  67.806 +	return 0;
  67.807 +}
  67.808 +
  67.809 +void
  67.810 +cpu_halt (void)
  67.811 +{
  67.812 +	pal_power_mgmt_info_u_t power_info[8];
  67.813 +	unsigned long min_power;
  67.814 +	int i, min_power_state;
  67.815 +
  67.816 +	if (ia64_pal_halt_info(power_info) != 0)
  67.817 +		return;
  67.818 +
  67.819 +	min_power_state = 0;
  67.820 +	min_power = power_info[0].pal_power_mgmt_info_s.power_consumption;
  67.821 +	for (i = 1; i < 8; ++i)
  67.822 +		if (power_info[i].pal_power_mgmt_info_s.im
  67.823 +		    && power_info[i].pal_power_mgmt_info_s.power_consumption < min_power) {
  67.824 +			min_power = power_info[i].pal_power_mgmt_info_s.power_consumption;
  67.825 +			min_power_state = i;
  67.826 +		}
  67.827 +
  67.828 +	while (1)
  67.829 +		ia64_pal_halt(min_power_state);
  67.830 +}
  67.831 +
  67.832 +void
  67.833 +machine_restart (char *restart_cmd)
  67.834 +{
  67.835 +	(*efi.reset_system)(EFI_RESET_WARM, 0, 0, NULL);
  67.836 +}
  67.837 +
  67.838 +void
  67.839 +machine_halt (void)
  67.840 +{
  67.841 +	cpu_halt();
  67.842 +}
  67.843 +
  67.844 +void
  67.845 +machine_power_off (void)
  67.846 +{
  67.847 +	if (pm_power_off)
  67.848 +		pm_power_off();
  67.849 +	machine_halt();
  67.850 +}
  67.851 +#endif // !XEN
    68.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    68.2 +++ b/xen/arch/ia64/linux-xen/unwind.c	Mon Jan 09 11:22:17 2006 +0000
    68.3 @@ -0,0 +1,2332 @@
    68.4 +/*
    68.5 + * Copyright (C) 1999-2004 Hewlett-Packard Co
    68.6 + *	David Mosberger-Tang <davidm@hpl.hp.com>
    68.7 + * Copyright (C) 2003 Fenghua Yu <fenghua.yu@intel.com>
    68.8 + * 	- Change pt_regs_off() to make it less dependant on pt_regs structure.
    68.9 + */
   68.10 +/*
   68.11 + * This file implements call frame unwind support for the Linux
   68.12 + * kernel.  Parsing and processing the unwind information is
   68.13 + * time-consuming, so this implementation translates the unwind
   68.14 + * descriptors into unwind scripts.  These scripts are very simple
   68.15 + * (basically a sequence of assignments) and efficient to execute.
   68.16 + * They are cached for later re-use.  Each script is specific for a
   68.17 + * given instruction pointer address and the set of predicate values
   68.18 + * that the script depends on (most unwind descriptors are
   68.19 + * unconditional and scripts often do not depend on predicates at
   68.20 + * all).  This code is based on the unwind conventions described in
   68.21 + * the "IA-64 Software Conventions and Runtime Architecture" manual.
   68.22 + *
   68.23 + * SMP conventions:
   68.24 + *	o updates to the global unwind data (in structure "unw") are serialized
   68.25 + *	  by the unw.lock spinlock
   68.26 + *	o each unwind script has its own read-write lock; a thread must acquire
   68.27 + *	  a read lock before executing a script and must acquire a write lock
   68.28 + *	  before modifying a script
   68.29 + *	o if both the unw.lock spinlock and a script's read-write lock must be
   68.30 + *	  acquired, then the read-write lock must be acquired first.
   68.31 + */
   68.32 +#ifdef XEN
   68.33 +#include <xen/types.h>
   68.34 +#include <xen/elf.h>
   68.35 +#include <xen/kernel.h>
   68.36 +#include <xen/sched.h>
   68.37 +#include <xen/xmalloc.h>
   68.38 +#include <xen/spinlock.h>
   68.39 +
   68.40 +// work around
   68.41 +#ifdef CONFIG_SMP
   68.42 +#define write_trylock(lock)	_raw_write_trylock(lock)
   68.43 +#else
   68.44 +#define write_trylock(lock)	({1;})
   68.45 +#endif
   68.46 +
   68.47 +#else
   68.48 +#include <linux/module.h>
   68.49 +#include <linux/bootmem.h>
   68.50 +#include <linux/elf.h>
   68.51 +#include <linux/kernel.h>
   68.52 +#include <linux/sched.h>
   68.53 +#include <linux/slab.h>
   68.54 +#endif
   68.55 +
   68.56 +#include <asm/unwind.h>
   68.57 +
   68.58 +#include <asm/delay.h>
   68.59 +#include <asm/page.h>
   68.60 +#include <asm/ptrace.h>
   68.61 +#include <asm/ptrace_offsets.h>
   68.62 +#include <asm/rse.h>
   68.63 +#include <asm/sections.h>
   68.64 +#include <asm/system.h>
   68.65 +#include <asm/uaccess.h>
   68.66 +
   68.67 +#include "entry.h"
   68.68 +#include "unwind_i.h"
   68.69 +
   68.70 +#define UNW_LOG_CACHE_SIZE	7	/* each unw_script is ~256 bytes in size */
   68.71 +#define UNW_CACHE_SIZE		(1 << UNW_LOG_CACHE_SIZE)
   68.72 +
   68.73 +#define UNW_LOG_HASH_SIZE	(UNW_LOG_CACHE_SIZE + 1)
   68.74 +#define UNW_HASH_SIZE		(1 << UNW_LOG_HASH_SIZE)
   68.75 +
   68.76 +#define UNW_STATS	0	/* WARNING: this disabled interrupts for long time-spans!! */
   68.77 +
   68.78 +#ifdef UNW_DEBUG
   68.79 +  static unsigned int unw_debug_level = UNW_DEBUG;
   68.80 +#  define UNW_DEBUG_ON(n)	unw_debug_level >= n
   68.81 +   /* Do not code a printk level, not all debug lines end in newline */
   68.82 +#  define UNW_DPRINT(n, ...)  if (UNW_DEBUG_ON(n)) printk(__VA_ARGS__)
   68.83 +#  define inline
   68.84 +#else /* !UNW_DEBUG */
   68.85 +#  define UNW_DEBUG_ON(n)  0
   68.86 +#  define UNW_DPRINT(n, ...)
   68.87 +#endif /* UNW_DEBUG */
   68.88 +
   68.89 +#if UNW_STATS
   68.90 +# define STAT(x...)	x
   68.91 +#else
   68.92 +# define STAT(x...)
   68.93 +#endif
   68.94 +
   68.95 +#ifdef XEN
   68.96 +#define alloc_reg_state()	xmalloc(struct unw_reg_state)
   68.97 +#define free_reg_state(usr)	xfree(usr)
   68.98 +#define alloc_labeled_state()	xmalloc(struct unw_labeled_state)
   68.99 +#define free_labeled_state(usr)	xfree(usr)
  68.100 +#else
  68.101 +#define alloc_reg_state()	kmalloc(sizeof(struct unw_reg_state), GFP_ATOMIC)
  68.102 +#define free_reg_state(usr)	kfree(usr)
  68.103 +#define alloc_labeled_state()	kmalloc(sizeof(struct unw_labeled_state), GFP_ATOMIC)
  68.104 +#define free_labeled_state(usr)	kfree(usr)
  68.105 +#endif
  68.106 +
  68.107 +typedef unsigned long unw_word;
  68.108 +typedef unsigned char unw_hash_index_t;
  68.109 +
  68.110 +static struct {
  68.111 +	spinlock_t lock;			/* spinlock for unwind data */
  68.112 +
  68.113 +	/* list of unwind tables (one per load-module) */
  68.114 +	struct unw_table *tables;
  68.115 +
  68.116 +	unsigned long r0;			/* constant 0 for r0 */
  68.117 +
  68.118 +	/* table of registers that prologues can save (and order in which they're saved): */
  68.119 +	const unsigned char save_order[8];
  68.120 +
  68.121 +	/* maps a preserved register index (preg_index) to corresponding switch_stack offset: */
  68.122 +	unsigned short sw_off[sizeof(struct unw_frame_info) / 8];
  68.123 +
  68.124 +	unsigned short lru_head;		/* index of lead-recently used script */
  68.125 +	unsigned short lru_tail;		/* index of most-recently used script */
  68.126 +
  68.127 +	/* index into unw_frame_info for preserved register i */
  68.128 +	unsigned short preg_index[UNW_NUM_REGS];
  68.129 +
  68.130 +	short pt_regs_offsets[32];
  68.131 +
  68.132 +	/* unwind table for the kernel: */
  68.133 +	struct unw_table kernel_table;
  68.134 +
  68.135 +	/* unwind table describing the gate page (kernel code that is mapped into user space): */
  68.136 +	size_t gate_table_size;
  68.137 +	unsigned long *gate_table;
  68.138 +
  68.139 +	/* hash table that maps instruction pointer to script index: */
  68.140 +	unsigned short hash[UNW_HASH_SIZE];
  68.141 +
  68.142 +	/* script cache: */
  68.143 +	struct unw_script cache[UNW_CACHE_SIZE];
  68.144 +
  68.145 +# ifdef UNW_DEBUG
  68.146 +	const char *preg_name[UNW_NUM_REGS];
  68.147 +# endif
  68.148 +# if UNW_STATS
  68.149 +	struct {
  68.150 +		struct {
  68.151 +			int lookups;
  68.152 +			int hinted_hits;
  68.153 +			int normal_hits;
  68.154 +			int collision_chain_traversals;
  68.155 +		} cache;
  68.156 +		struct {
  68.157 +			unsigned long build_time;
  68.158 +			unsigned long run_time;
  68.159 +			unsigned long parse_time;
  68.160 +			int builds;
  68.161 +			int news;
  68.162 +			int collisions;
  68.163 +			int runs;
  68.164 +		} script;
  68.165 +		struct {
  68.166 +			unsigned long init_time;
  68.167 +			unsigned long unwind_time;
  68.168 +			int inits;
  68.169 +			int unwinds;
  68.170 +		} api;
  68.171 +	} stat;
  68.172 +# endif
  68.173 +} unw = {
  68.174 +	.tables = &unw.kernel_table,
  68.175 +	.lock = SPIN_LOCK_UNLOCKED,
  68.176 +	.save_order = {
  68.177 +		UNW_REG_RP, UNW_REG_PFS, UNW_REG_PSP, UNW_REG_PR,
  68.178 +		UNW_REG_UNAT, UNW_REG_LC, UNW_REG_FPSR, UNW_REG_PRI_UNAT_GR
  68.179 +	},
  68.180 +	.preg_index = {
  68.181 +		offsetof(struct unw_frame_info, pri_unat_loc)/8,	/* PRI_UNAT_GR */
  68.182 +		offsetof(struct unw_frame_info, pri_unat_loc)/8,	/* PRI_UNAT_MEM */
  68.183 +		offsetof(struct unw_frame_info, bsp_loc)/8,
  68.184 +		offsetof(struct unw_frame_info, bspstore_loc)/8,
  68.185 +		offsetof(struct unw_frame_info, pfs_loc)/8,
  68.186 +		offsetof(struct unw_frame_info, rnat_loc)/8,
  68.187 +		offsetof(struct unw_frame_info, psp)/8,
  68.188 +		offsetof(struct unw_frame_info, rp_loc)/8,
  68.189 +		offsetof(struct unw_frame_info, r4)/8,
  68.190 +		offsetof(struct unw_frame_info, r5)/8,
  68.191 +		offsetof(struct unw_frame_info, r6)/8,
  68.192 +		offsetof(struct unw_frame_info, r7)/8,
  68.193 +		offsetof(struct unw_frame_info, unat_loc)/8,
  68.194 +		offsetof(struct unw_frame_info, pr_loc)/8,
  68.195 +		offsetof(struct unw_frame_info, lc_loc)/8,
  68.196 +		offsetof(struct unw_frame_info, fpsr_loc)/8,
  68.197 +		offsetof(struct unw_frame_info, b1_loc)/8,
  68.198 +		offsetof(struct unw_frame_info, b2_loc)/8,
  68.199 +		offsetof(struct unw_frame_info, b3_loc)/8,
  68.200 +		offsetof(struct unw_frame_info, b4_loc)/8,
  68.201 +		offsetof(struct unw_frame_info, b5_loc)/8,
  68.202 +		offsetof(struct unw_frame_info, f2_loc)/8,
  68.203 +		offsetof(struct unw_frame_info, f3_loc)/8,
  68.204 +		offsetof(struct unw_frame_info, f4_loc)/8,
  68.205 +		offsetof(struct unw_frame_info, f5_loc)/8,
  68.206 +		offsetof(struct unw_frame_info, fr_loc[16 - 16])/8,
  68.207 +		offsetof(struct unw_frame_info, fr_loc[17 - 16])/8,
  68.208 +		offsetof(struct unw_frame_info, fr_loc[18 - 16])/8,
  68.209 +		offsetof(struct unw_frame_info, fr_loc[19 - 16])/8,
  68.210 +		offsetof(struct unw_frame_info, fr_loc[20 - 16])/8,
  68.211 +		offsetof(struct unw_frame_info, fr_loc[21 - 16])/8,
  68.212 +		offsetof(struct unw_frame_info, fr_loc[22 - 16])/8,
  68.213 +		offsetof(struct unw_frame_info, fr_loc[23 - 16])/8,
  68.214 +		offsetof(struct unw_frame_info, fr_loc[24 - 16])/8,
  68.215 +		offsetof(struct unw_frame_info, fr_loc[25 - 16])/8,
  68.216 +		offsetof(struct unw_frame_info, fr_loc[26 - 16])/8,
  68.217 +		offsetof(struct unw_frame_info, fr_loc[27 - 16])/8,
  68.218 +		offsetof(struct unw_frame_info, fr_loc[28 - 16])/8,
  68.219 +		offsetof(struct unw_frame_info, fr_loc[29 - 16])/8,
  68.220 +		offsetof(struct unw_frame_info, fr_loc[30 - 16])/8,
  68.221 +		offsetof(struct unw_frame_info, fr_loc[31 - 16])/8,
  68.222 +	},
  68.223 +	.pt_regs_offsets = {
  68.224 +		[0] = -1,
  68.225 +		offsetof(struct pt_regs,  r1),
  68.226 +		offsetof(struct pt_regs,  r2),
  68.227 +		offsetof(struct pt_regs,  r3),
  68.228 +		[4] = -1, [5] = -1, [6] = -1, [7] = -1,
  68.229 +		offsetof(struct pt_regs,  r8),
  68.230 +		offsetof(struct pt_regs,  r9),
  68.231 +		offsetof(struct pt_regs, r10),
  68.232 +		offsetof(struct pt_regs, r11),
  68.233 +		offsetof(struct pt_regs, r12),
  68.234 +		offsetof(struct pt_regs, r13),
  68.235 +		offsetof(struct pt_regs, r14),
  68.236 +		offsetof(struct pt_regs, r15),
  68.237 +		offsetof(struct pt_regs, r16),
  68.238 +		offsetof(struct pt_regs, r17),
  68.239 +		offsetof(struct pt_regs, r18),
  68.240 +		offsetof(struct pt_regs, r19),
  68.241 +		offsetof(struct pt_regs, r20),
  68.242 +		offsetof(struct pt_regs, r21),
  68.243 +		offsetof(struct pt_regs, r22),
  68.244 +		offsetof(struct pt_regs, r23),
  68.245 +		offsetof(struct pt_regs, r24),
  68.246 +		offsetof(struct pt_regs, r25),
  68.247 +		offsetof(struct pt_regs, r26),
  68.248 +		offsetof(struct pt_regs, r27),
  68.249 +		offsetof(struct pt_regs, r28),
  68.250 +		offsetof(struct pt_regs, r29),
  68.251 +		offsetof(struct pt_regs, r30),
  68.252 +		offsetof(struct pt_regs, r31),
  68.253 +	},
  68.254 +	.hash = { [0 ... UNW_HASH_SIZE - 1] = -1 },
  68.255 +#ifdef UNW_DEBUG
  68.256 +	.preg_name = {
  68.257 +		"pri_unat_gr", "pri_unat_mem", "bsp", "bspstore", "ar.pfs", "ar.rnat", "psp", "rp",
  68.258 +		"r4", "r5", "r6", "r7",
  68.259 +		"ar.unat", "pr", "ar.lc", "ar.fpsr",
  68.260 +		"b1", "b2", "b3", "b4", "b5",
  68.261 +		"f2", "f3", "f4", "f5",
  68.262 +		"f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
  68.263 +		"f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31"
  68.264 +	}
  68.265 +#endif
  68.266 +};
  68.267 +
  68.268 +static inline int
  68.269 +read_only (void *addr)
  68.270 +{
  68.271 +	return (unsigned long) ((char *) addr - (char *) &unw.r0) < sizeof(unw.r0);
  68.272 +}
  68.273 +
  68.274 +/*
  68.275 + * Returns offset of rREG in struct pt_regs.
  68.276 + */
  68.277 +static inline unsigned long
  68.278 +pt_regs_off (unsigned long reg)
  68.279 +{
  68.280 +	short off = -1;
  68.281 +
  68.282 +	if (reg < ARRAY_SIZE(unw.pt_regs_offsets))
  68.283 +		off = unw.pt_regs_offsets[reg];
  68.284 +
  68.285 +	if (off < 0) {
  68.286 +		UNW_DPRINT(0, "unwind.%s: bad scratch reg r%lu\n", __FUNCTION__, reg);
  68.287 +		off = 0;
  68.288 +	}
  68.289 +	return (unsigned long) off;
  68.290 +}
  68.291 +
  68.292 +static inline struct pt_regs *
  68.293 +get_scratch_regs (struct unw_frame_info *info)
  68.294 +{
  68.295 +	if (!info->pt) {
  68.296 +		/* This should not happen with valid unwind info.  */
  68.297 +		UNW_DPRINT(0, "unwind.%s: bad unwind info: resetting info->pt\n", __FUNCTION__);
  68.298 +		if (info->flags & UNW_FLAG_INTERRUPT_FRAME)
  68.299 +			info->pt = (unsigned long) ((struct pt_regs *) info->psp - 1);
  68.300 +		else
  68.301 +			info->pt = info->sp - 16;
  68.302 +	}
  68.303 +	UNW_DPRINT(3, "unwind.%s: sp 0x%lx pt 0x%lx\n", __FUNCTION__, info->sp, info->pt);
  68.304 +	return (struct pt_regs *) info->pt;
  68.305 +}
  68.306 +
  68.307 +/* Unwind accessors.  */
  68.308 +
  68.309 +int
  68.310 +unw_access_gr (struct unw_frame_info *info, int regnum, unsigned long *val, char *nat, int write)
  68.311 +{
  68.312 +	unsigned long *addr, *nat_addr, nat_mask = 0, dummy_nat;
  68.313 +	struct unw_ireg *ireg;
  68.314 +	struct pt_regs *pt;
  68.315 +
  68.316 +	if ((unsigned) regnum - 1 >= 127) {
  68.317 +		if (regnum == 0 && !write) {
  68.318 +			*val = 0;	/* read r0 always returns 0 */
  68.319 +			*nat = 0;
  68.320 +			return 0;
  68.321 +		}
  68.322 +		UNW_DPRINT(0, "unwind.%s: trying to access non-existent r%u\n",
  68.323 +			   __FUNCTION__, regnum);
  68.324 +		return -1;
  68.325 +	}
  68.326 +
  68.327 +	if (regnum < 32) {
  68.328 +		if (regnum >= 4 && regnum <= 7) {
  68.329 +			/* access a preserved register */
  68.330 +			ireg = &info->r4 + (regnum - 4);
  68.331 +			addr = ireg->loc;
  68.332 +			if (addr) {
  68.333 +				nat_addr = addr + ireg->nat.off;
  68.334 +				switch (ireg->nat.type) {
  68.335 +				      case UNW_NAT_VAL:
  68.336 +					/* simulate getf.sig/setf.sig */
  68.337 +					if (write) {
  68.338 +						if (*nat) {
  68.339 +							/* write NaTVal and be done with it */
  68.340 +							addr[0] = 0;
  68.341 +							addr[1] = 0x1fffe;
  68.342 +							return 0;
  68.343 +						}
  68.344 +						addr[1] = 0x1003e;
  68.345 +					} else {
  68.346 +						if (addr[0] == 0 && addr[1] == 0x1ffe) {
  68.347 +							/* return NaT and be done with it */
  68.348 +							*val = 0;
  68.349 +							*nat = 1;
  68.350 +							return 0;
  68.351 +						}
  68.352 +					}
  68.353 +					/* fall through */
  68.354 +				      case UNW_NAT_NONE:
  68.355 +					dummy_nat = 0;
  68.356 +					nat_addr = &dummy_nat;
  68.357 +					break;
  68.358 +
  68.359 +				      case UNW_NAT_MEMSTK:
  68.360 +					nat_mask = (1UL << ((long) addr & 0x1f8)/8);
  68.361 +					break;
  68.362 +
  68.363 +				      case UNW_NAT_REGSTK:
  68.364 +					nat_addr = ia64_rse_rnat_addr(addr);
  68.365 +					if ((unsigned long) addr < info->regstk.limit
  68.366 +					    || (unsigned long) addr >= info->regstk.top)
  68.367 +					{
  68.368 +						UNW_DPRINT(0, "unwind.%s: %p outside of regstk "
  68.369 +							"[0x%lx-0x%lx)\n",
  68.370 +							__FUNCTION__, (void *) addr,
  68.371 +							info->regstk.limit,
  68.372 +							info->regstk.top);
  68.373 +						return -1;
  68.374 +					}
  68.375 +					if ((unsigned long) nat_addr >= info->regstk.top)
  68.376 +						nat_addr = &info->sw->ar_rnat;
  68.377 +					nat_mask = (1UL << ia64_rse_slot_num(addr));
  68.378 +					break;
  68.379 +				}
  68.380 +			} else {
  68.381 +				addr = &info->sw->r4 + (regnum - 4);
  68.382 +				nat_addr = &info->sw->ar_unat;
  68.383 +				nat_mask = (1UL << ((long) addr & 0x1f8)/8);
  68.384 +			}
  68.385 +		} else {
  68.386 +			/* access a scratch register */
  68.387 +			pt = get_scratch_regs(info);
  68.388 +			addr = (unsigned long *) ((unsigned long)pt + pt_regs_off(regnum));
  68.389 +			if (info->pri_unat_loc)
  68.390 +				nat_addr = info->pri_unat_loc;
  68.391 +			else
  68.392 +				nat_addr = &info->sw->caller_unat;
  68.393 +			nat_mask = (1UL << ((long) addr & 0x1f8)/8);
  68.394 +		}
  68.395 +	} else {
  68.396 +		/* access a stacked register */
  68.397 +		addr = ia64_rse_skip_regs((unsigned long *) info->bsp, regnum - 32);
  68.398 +		nat_addr = ia64_rse_rnat_addr(addr);
  68.399 +		if ((unsigned long) addr < info->regstk.limit
  68.400 +		    || (unsigned long) addr >= info->regstk.top)
  68.401 +		{
  68.402 +			UNW_DPRINT(0, "unwind.%s: ignoring attempt to access register outside "
  68.403 +				   "of rbs\n",  __FUNCTION__);
  68.404 +			return -1;
  68.405 +		}
  68.406 +		if ((unsigned long) nat_addr >= info->regstk.top)
  68.407 +			nat_addr = &info->sw->ar_rnat;
  68.408 +		nat_mask = (1UL << ia64_rse_slot_num(addr));
  68.409 +	}
  68.410 +
  68.411 +	if (write) {
  68.412 +		if (read_only(addr)) {
  68.413 +			UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n",
  68.414 +				__FUNCTION__);
  68.415 +		} else {
  68.416 +			*addr = *val;
  68.417 +			if (*nat)
  68.418 +				*nat_addr |= nat_mask;
  68.419 +			else
  68.420 +				*nat_addr &= ~nat_mask;
  68.421 +		}
  68.422 +	} else {
  68.423 +		if ((*nat_addr & nat_mask) == 0) {
  68.424 +			*val = *addr;
  68.425 +			*nat = 0;
  68.426 +		} else {
  68.427 +			*val = 0;	/* if register is a NaT, *addr may contain kernel data! */
  68.428 +			*nat = 1;
  68.429 +		}
  68.430 +	}
  68.431 +	return 0;
  68.432 +}
  68.433 +EXPORT_SYMBOL(unw_access_gr);
  68.434 +
  68.435 +int
  68.436 +unw_access_br (struct unw_frame_info *info, int regnum, unsigned long *val, int write)
  68.437 +{
  68.438 +	unsigned long *addr;
  68.439 +	struct pt_regs *pt;
  68.440 +
  68.441 +	switch (regnum) {
  68.442 +		/* scratch: */
  68.443 +	      case 0: pt = get_scratch_regs(info); addr = &pt->b0; break;
  68.444 +	      case 6: pt = get_scratch_regs(info); addr = &pt->b6; break;
  68.445 +	      case 7: pt = get_scratch_regs(info); addr = &pt->b7; break;
  68.446 +
  68.447 +		/* preserved: */
  68.448 +	      case 1: case 2: case 3: case 4: case 5:
  68.449 +		addr = *(&info->b1_loc + (regnum - 1));
  68.450 +		if (!addr)
  68.451 +			addr = &info->sw->b1 + (regnum - 1);
  68.452 +		break;
  68.453 +
  68.454 +	      default:
  68.455 +		UNW_DPRINT(0, "unwind.%s: trying to access non-existent b%u\n",
  68.456 +			   __FUNCTION__, regnum);
  68.457 +		return -1;
  68.458 +	}
  68.459 +	if (write)
  68.460 +		if (read_only(addr)) {
  68.461 +			UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n",
  68.462 +				__FUNCTION__);
  68.463 +		} else
  68.464 +			*addr = *val;
  68.465 +	else
  68.466 +		*val = *addr;
  68.467 +	return 0;
  68.468 +}
  68.469 +EXPORT_SYMBOL(unw_access_br);
  68.470 +
  68.471 +int
  68.472 +unw_access_fr (struct unw_frame_info *info, int regnum, struct ia64_fpreg *val, int write)
  68.473 +{
  68.474 +	struct ia64_fpreg *addr = NULL;
  68.475 +	struct pt_regs *pt;
  68.476 +
  68.477 +	if ((unsigned) (regnum - 2) >= 126) {
  68.478 +		UNW_DPRINT(0, "unwind.%s: trying to access non-existent f%u\n",
  68.479 +			   __FUNCTION__, regnum);
  68.480 +		return -1;
  68.481 +	}
  68.482 +
  68.483 +	if (regnum <= 5) {
  68.484 +		addr = *(&info->f2_loc + (regnum - 2));
  68.485 +		if (!addr)
  68.486 +			addr = &info->sw->f2 + (regnum - 2);
  68.487 +	} else if (regnum <= 15) {
  68.488 +		if (regnum <= 11) {
  68.489 +			pt = get_scratch_regs(info);
  68.490 +			addr = &pt->f6  + (regnum - 6);
  68.491 +		}
  68.492 +		else
  68.493 +			addr = &info->sw->f12 + (regnum - 12);
  68.494 +	} else if (regnum <= 31) {
  68.495 +		addr = info->fr_loc[regnum - 16];
  68.496 +		if (!addr)
  68.497 +			addr = &info->sw->f16 + (regnum - 16);
  68.498 +	} else {
  68.499 +		struct task_struct *t = info->task;
  68.500 +
  68.501 +		if (write)
  68.502 +			ia64_sync_fph(t);
  68.503 +		else
  68.504 +			ia64_flush_fph(t);
  68.505 +#ifdef XEN
  68.506 +		addr = t->arch._thread.fph + (regnum - 32);
  68.507 +#else
  68.508 +		addr = t->thread.fph + (regnum - 32);
  68.509 +#endif
  68.510 +	}
  68.511 +
  68.512 +	if (write)
  68.513 +		if (read_only(addr)) {
  68.514 +			UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n",
  68.515 +				__FUNCTION__);
  68.516 +		} else
  68.517 +			*addr = *val;
  68.518 +	else
  68.519 +		*val = *addr;
  68.520 +	return 0;
  68.521 +}
  68.522 +EXPORT_SYMBOL(unw_access_fr);
  68.523 +
  68.524 +int
  68.525 +unw_access_ar (struct unw_frame_info *info, int regnum, unsigned long *val, int write)
  68.526 +{
  68.527 +	unsigned long *addr;
  68.528 +	struct pt_regs *pt;
  68.529 +
  68.530 +	switch (regnum) {
  68.531 +	      case UNW_AR_BSP:
  68.532 +		addr = info->bsp_loc;
  68.533 +		if (!addr)
  68.534 +			addr = &info->sw->ar_bspstore;
  68.535 +		break;
  68.536 +
  68.537 +	      case UNW_AR_BSPSTORE:
  68.538 +		addr = info->bspstore_loc;
  68.539 +		if (!addr)
  68.540 +			addr = &info->sw->ar_bspstore;
  68.541 +		break;
  68.542 +
  68.543 +	      case UNW_AR_PFS:
  68.544 +		addr = info->pfs_loc;
  68.545 +		if (!addr)
  68.546 +			addr = &info->sw->ar_pfs;
  68.547 +		break;
  68.548 +
  68.549 +	      case UNW_AR_RNAT:
  68.550 +		addr = info->rnat_loc;
  68.551 +		if (!addr)
  68.552 +			addr = &info->sw->ar_rnat;
  68.553 +		break;
  68.554 +
  68.555 +	      case UNW_AR_UNAT:
  68.556 +		addr = info->unat_loc;
  68.557 +		if (!addr)
  68.558 +			addr = &info->sw->caller_unat;
  68.559 +		break;
  68.560 +
  68.561 +	      case UNW_AR_LC:
  68.562 +		addr = info->lc_loc;
  68.563 +		if (!addr)
  68.564 +			addr = &info->sw->ar_lc;
  68.565 +		break;
  68.566 +
  68.567 +	      case UNW_AR_EC:
  68.568 +		if (!info->cfm_loc)
  68.569 +			return -1;
  68.570 +		if (write)
  68.571 +			*info->cfm_loc =
  68.572 +				(*info->cfm_loc & ~(0x3fUL << 52)) | ((*val & 0x3f) << 52);
  68.573 +		else
  68.574 +			*val = (*info->cfm_loc >> 52) & 0x3f;
  68.575 +		return 0;
  68.576 +
  68.577 +	      case UNW_AR_FPSR:
  68.578 +		addr = info->fpsr_loc;
  68.579 +		if (!addr)
  68.580 +			addr = &info->sw->ar_fpsr;
  68.581 +		break;
  68.582 +
  68.583 +	      case UNW_AR_RSC:
  68.584 +		pt = get_scratch_regs(info);
  68.585 +		addr = &pt->ar_rsc;
  68.586 +		break;
  68.587 +
  68.588 +	      case UNW_AR_CCV:
  68.589 +		pt = get_scratch_regs(info);
  68.590 +		addr = &pt->ar_ccv;
  68.591 +		break;
  68.592 +
  68.593 +	      case UNW_AR_CSD:
  68.594 +		pt = get_scratch_regs(info);
  68.595 +		addr = &pt->ar_csd;
  68.596 +		break;
  68.597 +
  68.598 +	      case UNW_AR_SSD:
  68.599 +		pt = get_scratch_regs(info);
  68.600 +		addr = &pt->ar_ssd;
  68.601 +		break;
  68.602 +
  68.603 +	      default:
  68.604 +		UNW_DPRINT(0, "unwind.%s: trying to access non-existent ar%u\n",
  68.605 +			   __FUNCTION__, regnum);
  68.606 +		return -1;
  68.607 +	}
  68.608 +
  68.609 +	if (write) {
  68.610 +		if (read_only(addr)) {
  68.611 +			UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n",
  68.612 +				__FUNCTION__);
  68.613 +		} else
  68.614 +			*addr = *val;
  68.615 +	} else
  68.616 +		*val = *addr;
  68.617 +	return 0;
  68.618 +}
  68.619 +EXPORT_SYMBOL(unw_access_ar);
  68.620 +
  68.621 +int
  68.622 +unw_access_pr (struct unw_frame_info *info, unsigned long *val, int write)
  68.623 +{
  68.624 +	unsigned long *addr;
  68.625 +
  68.626 +	addr = info->pr_loc;
  68.627 +	if (!addr)
  68.628 +		addr = &info->sw->pr;
  68.629 +
  68.630 +	if (write) {
  68.631 +		if (read_only(addr)) {
  68.632 +			UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n",
  68.633 +				__FUNCTION__);
  68.634 +		} else
  68.635 +			*addr = *val;
  68.636 +	} else
  68.637 +		*val = *addr;
  68.638 +	return 0;
  68.639 +}
  68.640 +EXPORT_SYMBOL(unw_access_pr);
  68.641 +
  68.642 +
  68.643 +/* Routines to manipulate the state stack.  */
  68.644 +
  68.645 +static inline void
  68.646 +push (struct unw_state_record *sr)
  68.647 +{
  68.648 +	struct unw_reg_state *rs;
  68.649 +
  68.650 +	rs = alloc_reg_state();
  68.651 +	if (!rs) {
  68.652 +		printk(KERN_ERR "unwind: cannot stack reg state!\n");
  68.653 +		return;
  68.654 +	}
  68.655 +	memcpy(rs, &sr->curr, sizeof(*rs));
  68.656 +	sr->curr.next = rs;
  68.657 +}
  68.658 +
  68.659 +static void
  68.660 +pop (struct unw_state_record *sr)
  68.661 +{
  68.662 +	struct unw_reg_state *rs = sr->curr.next;
  68.663 +
  68.664 +	if (!rs) {
  68.665 +		printk(KERN_ERR "unwind: stack underflow!\n");
  68.666 +		return;
  68.667 +	}
  68.668 +	memcpy(&sr->curr, rs, sizeof(*rs));
  68.669 +	free_reg_state(rs);
  68.670 +}
  68.671 +
  68.672 +/* Make a copy of the state stack.  Non-recursive to avoid stack overflows.  */
  68.673 +static struct unw_reg_state *
  68.674 +dup_state_stack (struct unw_reg_state *rs)
  68.675 +{
  68.676 +	struct unw_reg_state *copy, *prev = NULL, *first = NULL;
  68.677 +
  68.678 +	while (rs) {
  68.679 +		copy = alloc_reg_state();
  68.680 +		if (!copy) {
  68.681 +			printk(KERN_ERR "unwind.dup_state_stack: out of memory\n");
  68.682 +			return NULL;
  68.683 +		}
  68.684 +		memcpy(copy, rs, sizeof(*copy));
  68.685 +		if (first)
  68.686 +			prev->next = copy;
  68.687 +		else
  68.688 +			first = copy;
  68.689 +		rs = rs->next;
  68.690 +		prev = copy;
  68.691 +	}
  68.692 +	return first;
  68.693 +}
  68.694 +
  68.695 +/* Free all stacked register states (but not RS itself).  */
  68.696 +static void
  68.697 +free_state_stack (struct unw_reg_state *rs)
  68.698 +{
  68.699 +	struct unw_reg_state *p, *next;
  68.700 +
  68.701 +	for (p = rs->next; p != NULL; p = next) {
  68.702 +		next = p->next;
  68.703 +		free_reg_state(p);
  68.704 +	}
  68.705 +	rs->next = NULL;
  68.706 +}
  68.707 +
  68.708 +/* Unwind decoder routines */
  68.709 +
  68.710 +static enum unw_register_index __attribute_const__
  68.711 +decode_abreg (unsigned char abreg, int memory)
  68.712 +{
  68.713 +	switch (abreg) {
  68.714 +	      case 0x04 ... 0x07: return UNW_REG_R4 + (abreg - 0x04);
  68.715 +	      case 0x22 ... 0x25: return UNW_REG_F2 + (abreg - 0x22);
  68.716 +	      case 0x30 ... 0x3f: return UNW_REG_F16 + (abreg - 0x30);
  68.717 +	      case 0x41 ... 0x45: return UNW_REG_B1 + (abreg - 0x41);
  68.718 +	      case 0x60: return UNW_REG_PR;
  68.719 +	      case 0x61: return UNW_REG_PSP;
  68.720 +	      case 0x62: return memory ? UNW_REG_PRI_UNAT_MEM : UNW_REG_PRI_UNAT_GR;
  68.721 +	      case 0x63: return UNW_REG_RP;
  68.722 +	      case 0x64: return UNW_REG_BSP;
  68.723 +	      case 0x65: return UNW_REG_BSPSTORE;
  68.724 +	      case 0x66: return UNW_REG_RNAT;
  68.725 +	      case 0x67: return UNW_REG_UNAT;
  68.726 +	      case 0x68: return UNW_REG_FPSR;
  68.727 +	      case 0x69: return UNW_REG_PFS;
  68.728 +	      case 0x6a: return UNW_REG_LC;
  68.729 +	      default:
  68.730 +		break;
  68.731 +	}
  68.732 +	UNW_DPRINT(0, "unwind.%s: bad abreg=0x%x\n", __FUNCTION__, abreg);
  68.733 +	return UNW_REG_LC;
  68.734 +}
  68.735 +
  68.736 +static void
  68.737 +set_reg (struct unw_reg_info *reg, enum unw_where where, int when, unsigned long val)
  68.738 +{
  68.739 +	reg->val = val;
  68.740 +	reg->where = where;
  68.741 +	if (reg->when == UNW_WHEN_NEVER)
  68.742 +		reg->when = when;
  68.743 +}
  68.744 +
  68.745 +static void
  68.746 +alloc_spill_area (unsigned long *offp, unsigned long regsize,
  68.747 +		  struct unw_reg_info *lo, struct unw_reg_info *hi)
  68.748 +{
  68.749 +	struct unw_reg_info *reg;
  68.750 +
  68.751 +	for (reg = hi; reg >= lo; --reg) {
  68.752 +		if (reg->where == UNW_WHERE_SPILL_HOME) {
  68.753 +			reg->where = UNW_WHERE_PSPREL;
  68.754 +			*offp -= regsize;
  68.755 +			reg->val = *offp;
  68.756 +		}
  68.757 +	}
  68.758 +}
  68.759 +
  68.760 +static inline void
  68.761 +spill_next_when (struct unw_reg_info **regp, struct unw_reg_info *lim, unw_word t)
  68.762 +{
  68.763 +	struct unw_reg_info *reg;
  68.764 +
  68.765 +	for (reg = *regp; reg <= lim; ++reg) {
  68.766 +		if (reg->where == UNW_WHERE_SPILL_HOME) {
  68.767 +			reg->when = t;
  68.768 +			*regp = reg + 1;
  68.769 +			return;
  68.770 +		}
  68.771 +	}
  68.772 +	UNW_DPRINT(0, "unwind.%s: excess spill!\n",  __FUNCTION__);
  68.773 +}
  68.774 +
  68.775 +static inline void
  68.776 +finish_prologue (struct unw_state_record *sr)
  68.777 +{
  68.778 +	struct unw_reg_info *reg;
  68.779 +	unsigned long off;
  68.780 +	int i;
  68.781 +
  68.782 +	/*
  68.783 +	 * First, resolve implicit register save locations (see Section "11.4.2.3 Rules
  68.784 +	 * for Using Unwind Descriptors", rule 3):
  68.785 +	 */
  68.786 +	for (i = 0; i < (int) ARRAY_SIZE(unw.save_order); ++i) {
  68.787 +		reg = sr->curr.reg + unw.save_order[i];
  68.788 +		if (reg->where == UNW_WHERE_GR_SAVE) {
  68.789 +			reg->where = UNW_WHERE_GR;
  68.790 +			reg->val = sr->gr_save_loc++;
  68.791 +		}
  68.792 +	}
  68.793 +
  68.794 +	/*
  68.795 +	 * Next, compute when the fp, general, and branch registers get
  68.796 +	 * saved.  This must come before alloc_spill_area() because
  68.797 +	 * we need to know which registers are spilled to their home
  68.798 +	 * locations.
  68.799 +	 */
  68.800 +	if (sr->imask) {
  68.801 +		unsigned char kind, mask = 0, *cp = sr->imask;
  68.802 +		int t;
  68.803 +		static const unsigned char limit[3] = {
  68.804 +			UNW_REG_F31, UNW_REG_R7, UNW_REG_B5
  68.805 +		};
  68.806 +		struct unw_reg_info *(regs[3]);
  68.807 +
  68.808 +		regs[0] = sr->curr.reg + UNW_REG_F2;
  68.809 +		regs[1] = sr->curr.reg + UNW_REG_R4;
  68.810 +		regs[2] = sr->curr.reg + UNW_REG_B1;
  68.811 +
  68.812 +		for (t = 0; t < sr->region_len; ++t) {
  68.813 +			if ((t & 3) == 0)
  68.814 +				mask = *cp++;
  68.815 +			kind = (mask >> 2*(3-(t & 3))) & 3;
  68.816 +			if (kind > 0)
  68.817 +				spill_next_when(&regs[kind - 1], sr->curr.reg + limit[kind - 1],
  68.818 +						sr->region_start + t);
  68.819 +		}
  68.820 +	}
  68.821 +	/*
  68.822 +	 * Next, lay out the memory stack spill area:
  68.823 +	 */
  68.824 +	if (sr->any_spills) {
  68.825 +		off = sr->spill_offset;
  68.826 +		alloc_spill_area(&off, 16, sr->curr.reg + UNW_REG_F2, sr->curr.reg + UNW_REG_F31);
  68.827 +		alloc_spill_area(&off,  8, sr->curr.reg + UNW_REG_B1, sr->curr.reg + UNW_REG_B5);
  68.828 +		alloc_spill_area(&off,  8, sr->curr.reg + UNW_REG_R4, sr->curr.reg + UNW_REG_R7);
  68.829 +	}
  68.830 +}
  68.831 +
  68.832 +/*
  68.833 + * Region header descriptors.
  68.834 + */
  68.835 +
  68.836 +static void
  68.837 +desc_prologue (int body, unw_word rlen, unsigned char mask, unsigned char grsave,
  68.838 +	       struct unw_state_record *sr)
  68.839 +{
  68.840 +	int i, region_start;
  68.841 +
  68.842 +	if (!(sr->in_body || sr->first_region))
  68.843 +		finish_prologue(sr);
  68.844 +	sr->first_region = 0;
  68.845 +
  68.846 +	/* check if we're done: */
  68.847 +	if (sr->when_target < sr->region_start + sr->region_len) {
  68.848 +		sr->done = 1;
  68.849 +		return;
  68.850 +	}
  68.851 +
  68.852 +	region_start = sr->region_start + sr->region_len;
  68.853 +
  68.854 +	for (i = 0; i < sr->epilogue_count; ++i)
  68.855 +		pop(sr);
  68.856 +	sr->epilogue_count = 0;
  68.857 +	sr->epilogue_start = UNW_WHEN_NEVER;
  68.858 +
  68.859 +	sr->region_start = region_start;
  68.860 +	sr->region_len = rlen;
  68.861 +	sr->in_body = body;
  68.862 +
  68.863 +	if (!body) {
  68.864 +		push(sr);
  68.865 +
  68.866 +		for (i = 0; i < 4; ++i) {
  68.867 +			if (mask & 0x8)
  68.868 +				set_reg(sr->curr.reg + unw.save_order[i], UNW_WHERE_GR,
  68.869 +					sr->region_start + sr->region_len - 1, grsave++);
  68.870 +			mask <<= 1;
  68.871 +		}
  68.872 +		sr->gr_save_loc = grsave;
  68.873 +		sr->any_spills = 0;
  68.874 +		sr->imask = NULL;
  68.875 +		sr->spill_offset = 0x10;	/* default to psp+16 */
  68.876 +	}
  68.877 +}
  68.878 +
  68.879 +/*
  68.880 + * Prologue descriptors.
  68.881 + */
  68.882 +
  68.883 +static inline void
  68.884 +desc_abi (unsigned char abi, unsigned char context, struct unw_state_record *sr)
  68.885 +{
  68.886 +	if (abi == 3 && context == 'i') {
  68.887 +		sr->flags |= UNW_FLAG_INTERRUPT_FRAME;
  68.888 +		UNW_DPRINT(3, "unwind.%s: interrupt frame\n",  __FUNCTION__);
  68.889 +	}
  68.890 +	else
  68.891 +		UNW_DPRINT(0, "unwind%s: ignoring unwabi(abi=0x%x,context=0x%x)\n",
  68.892 +				__FUNCTION__, abi, context);
  68.893 +}
  68.894 +
  68.895 +static inline void
  68.896 +desc_br_gr (unsigned char brmask, unsigned char gr, struct unw_state_record *sr)
  68.897 +{
  68.898 +	int i;
  68.899 +
  68.900 +	for (i = 0; i < 5; ++i) {
  68.901 +		if (brmask & 1)
  68.902 +			set_reg(sr->curr.reg + UNW_REG_B1 + i, UNW_WHERE_GR,
  68.903 +				sr->region_start + sr->region_len - 1, gr++);
  68.904 +		brmask >>= 1;
  68.905 +	}
  68.906 +}
  68.907 +
  68.908 +static inline void
  68.909 +desc_br_mem (unsigned char brmask, struct unw_state_record *sr)
  68.910 +{
  68.911 +	int i;
  68.912 +
  68.913 +	for (i = 0; i < 5; ++i) {
  68.914 +		if (brmask & 1) {
  68.915 +			set_reg(sr->curr.reg + UNW_REG_B1 + i, UNW_WHERE_SPILL_HOME,
  68.916 +				sr->region_start + sr->region_len - 1, 0);
  68.917 +			sr->any_spills = 1;
  68.918 +		}
  68.919 +		brmask >>= 1;
  68.920 +	}
  68.921 +}
  68.922 +
  68.923 +static inline void
  68.924 +desc_frgr_mem (unsigned char grmask, unw_word frmask, struct unw_state_record *sr)
  68.925 +{
  68.926 +	int i;
  68.927 +
  68.928 +	for (i = 0; i < 4; ++i) {
  68.929 +		if ((grmask & 1) != 0) {
  68.930 +			set_reg(sr->curr.reg + UNW_REG_R4 + i, UNW_WHERE_SPILL_HOME,
  68.931 +				sr->region_start + sr->region_len - 1, 0);
  68.932 +			sr->any_spills = 1;
  68.933 +		}
  68.934 +		grmask >>= 1;
  68.935 +	}
  68.936 +	for (i = 0; i < 20; ++i) {
  68.937 +		if ((frmask & 1) != 0) {
  68.938 +			int base = (i < 4) ? UNW_REG_F2 : UNW_REG_F16 - 4;
  68.939 +			set_reg(sr->curr.reg + base + i, UNW_WHERE_SPILL_HOME,
  68.940 +				sr->region_start + sr->region_len - 1, 0);
  68.941 +			sr->any_spills = 1;
  68.942 +		}
  68.943 +		frmask >>= 1;
  68.944 +	}
  68.945 +}
  68.946 +
  68.947 +static inline void
  68.948 +desc_fr_mem (unsigned char frmask, struct unw_state_record *sr)
  68.949 +{
  68.950 +	int i;
  68.951 +
  68.952 +	for (i = 0; i < 4; ++i) {
  68.953 +		if ((frmask & 1) != 0) {
  68.954 +			set_reg(sr->curr.reg + UNW_REG_F2 + i, UNW_WHERE_SPILL_HOME,
  68.955 +				sr->region_start + sr->region_len - 1, 0);
  68.956 +			sr->any_spills = 1;
  68.957 +		}
  68.958 +		frmask >>= 1;
  68.959 +	}
  68.960 +}
  68.961 +
  68.962 +static inline void
  68.963 +desc_gr_gr (unsigned char grmask, unsigned char gr, struct unw_state_record *sr)
  68.964 +{
  68.965 +	int i;
  68.966 +
  68.967 +	for (i = 0; i < 4; ++i) {
  68.968 +		if ((grmask & 1) != 0)
  68.969 +			set_reg(sr->curr.reg + UNW_REG_R4 + i, UNW_WHERE_GR,
  68.970 +				sr->region_start + sr->region_len - 1, gr++);
  68.971 +		grmask >>= 1;
  68.972 +	}
  68.973 +}
  68.974 +
  68.975 +static inline void
  68.976 +desc_gr_mem (unsigned char grmask, struct unw_state_record *sr)
  68.977 +{
  68.978 +	int i;
  68.979 +
  68.980 +	for (i = 0; i < 4; ++i) {
  68.981 +		if ((grmask & 1) != 0) {
  68.982 +			set_reg(sr->curr.reg + UNW_REG_R4 + i, UNW_WHERE_SPILL_HOME,
  68.983 +				sr->region_start + sr->region_len - 1, 0);
  68.984 +			sr->any_spills = 1;
  68.985 +		}
  68.986 +		grmask >>= 1;
  68.987 +	}
  68.988 +}
  68.989 +
  68.990 +static inline void
  68.991 +desc_mem_stack_f (unw_word t, unw_word size, struct unw_state_record *sr)
  68.992 +{
  68.993 +	set_reg(sr->curr.reg + UNW_REG_PSP, UNW_WHERE_NONE,
  68.994 +		sr->region_start + min_t(int, t, sr->region_len - 1), 16*size);
  68.995 +}
  68.996 +
  68.997 +static inline void
  68.998 +desc_mem_stack_v (unw_word t, struct unw_state_record *sr)
  68.999 +{
 68.1000 +	sr->curr.reg[UNW_REG_PSP].when = sr->region_start + min_t(int, t, sr->region_len - 1);
 68.1001 +}
 68.1002 +
 68.1003 +static inline void
 68.1004 +desc_reg_gr (unsigned char reg, unsigned char dst, struct unw_state_record *sr)
 68.1005 +{
 68.1006 +	set_reg(sr->curr.reg + reg, UNW_WHERE_GR, sr->region_start + sr->region_len - 1, dst);
 68.1007 +}
 68.1008 +
 68.1009 +static inline void
 68.1010 +desc_reg_psprel (unsigned char reg, unw_word pspoff, struct unw_state_record *sr)
 68.1011 +{
 68.1012 +	set_reg(sr->curr.reg + reg, UNW_WHERE_PSPREL, sr->region_start + sr->region_len - 1,
 68.1013 +		0x10 - 4*pspoff);
 68.1014 +}
 68.1015 +
 68.1016 +static inline void
 68.1017 +desc_reg_sprel (unsigned char reg, unw_word spoff, struct unw_state_record *sr)
 68.1018 +{
 68.1019 +	set_reg(sr->curr.reg + reg, UNW_WHERE_SPREL, sr->region_start + sr->region_len - 1,
 68.1020 +		4*spoff);
 68.1021 +}
 68.1022 +
 68.1023 +static inline void
 68.1024 +desc_rp_br (unsigned char dst, struct unw_state_record *sr)
 68.1025 +{
 68.1026 +	sr->return_link_reg = dst;
 68.1027 +}
 68.1028 +
 68.1029 +static inline void
 68.1030 +desc_reg_when (unsigned char regnum, unw_word t, struct unw_state_record *sr)
 68.1031 +{
 68.1032 +	struct unw_reg_info *reg = sr->curr.reg + regnum;
 68.1033 +
 68.1034 +	if (reg->where == UNW_WHERE_NONE)
 68.1035 +		reg->where = UNW_WHERE_GR_SAVE;
 68.1036 +	reg->when = sr->region_start + min_t(int, t, sr->region_len - 1);
 68.1037 +}
 68.1038 +
 68.1039 +static inline void
 68.1040 +desc_spill_base (unw_word pspoff, struct unw_state_record *sr)
 68.1041 +{
 68.1042 +	sr->spill_offset = 0x10 - 4*pspoff;
 68.1043 +}
 68.1044 +
 68.1045 +static inline unsigned char *
 68.1046 +desc_spill_mask (unsigned char *imaskp, struct unw_state_record *sr)
 68.1047 +{
 68.1048 +	sr->imask = imaskp;
 68.1049 +	return imaskp + (2*sr->region_len + 7)/8;
 68.1050 +}
 68.1051 +
 68.1052 +/*
 68.1053 + * Body descriptors.
 68.1054 + */
 68.1055 +static inline void
 68.1056 +desc_epilogue (unw_word t, unw_word ecount, struct unw_state_record *sr)
 68.1057 +{
 68.1058 +	sr->epilogue_start = sr->region_start + sr->region_len - 1 - t;
 68.1059 +	sr->epilogue_count = ecount + 1;
 68.1060 +}
 68.1061 +
 68.1062 +static inline void
 68.1063 +desc_copy_state (unw_word label, struct unw_state_record *sr)
 68.1064 +{
 68.1065 +	struct unw_labeled_state *ls;
 68.1066 +
 68.1067 +	for (ls = sr->labeled_states; ls; ls = ls->next) {
 68.1068 +		if (ls->label == label) {
 68.1069 +			free_state_stack(&sr->curr);
 68.1070 +			memcpy(&sr->curr, &ls->saved_state, sizeof(sr->curr));
 68.1071 +			sr->curr.next = dup_state_stack(ls->saved_state.next);
 68.1072 +			return;
 68.1073 +		}
 68.1074 +	}
 68.1075 +	printk(KERN_ERR "unwind: failed to find state labeled 0x%lx\n", label);
 68.1076 +}
 68.1077 +
 68.1078 +static inline void
 68.1079 +desc_label_state (unw_word label, struct unw_state_record *sr)
 68.1080 +{
 68.1081 +	struct unw_labeled_state *ls;
 68.1082 +
 68.1083 +	ls = alloc_labeled_state();
 68.1084 +	if (!ls) {
 68.1085 +		printk(KERN_ERR "unwind.desc_label_state(): out of memory\n");
 68.1086 +		return;
 68.1087 +	}
 68.1088 +	ls->label = label;
 68.1089 +	memcpy(&ls->saved_state, &sr->curr, sizeof(ls->saved_state));
 68.1090 +	ls->saved_state.next = dup_state_stack(sr->curr.next);
 68.1091 +
 68.1092 +	/* insert into list of labeled states: */
 68.1093 +	ls->next = sr->labeled_states;
 68.1094 +	sr->labeled_states = ls;
 68.1095 +}
 68.1096 +
 68.1097 +/*
 68.1098 + * General descriptors.
 68.1099 + */
 68.1100 +
 68.1101 +static inline int
 68.1102 +desc_is_active (unsigned char qp, unw_word t, struct unw_state_record *sr)
 68.1103 +{
 68.1104 +	if (sr->when_target <= sr->region_start + min_t(int, t, sr->region_len - 1))
 68.1105 +		return 0;
 68.1106 +	if (qp > 0) {
 68.1107 +		if ((sr->pr_val & (1UL << qp)) == 0)
 68.1108 +			return 0;
 68.1109 +		sr->pr_mask |= (1UL << qp);
 68.1110 +	}
 68.1111 +	return 1;
 68.1112 +}
 68.1113 +
 68.1114 +static inline void
 68.1115 +desc_restore_p (unsigned char qp, unw_word t, unsigned char abreg, struct unw_state_record *sr)
 68.1116 +{
 68.1117 +	struct unw_reg_info *r;
 68.1118 +
 68.1119 +	if (!desc_is_active(qp, t, sr))
 68.1120 +		return;
 68.1121 +
 68.1122 +	r = sr->curr.reg + decode_abreg(abreg, 0);
 68.1123 +	r->where = UNW_WHERE_NONE;
 68.1124 +	r->when = UNW_WHEN_NEVER;
 68.1125 +	r->val = 0;
 68.1126 +}
 68.1127 +
 68.1128 +static inline void
 68.1129 +desc_spill_reg_p (unsigned char qp, unw_word t, unsigned char abreg, unsigned char x,
 68.1130 +		     unsigned char ytreg, struct unw_state_record *sr)
 68.1131 +{
 68.1132 +	enum unw_where where = UNW_WHERE_GR;
 68.1133 +	struct unw_reg_info *r;
 68.1134 +
 68.1135 +	if (!desc_is_active(qp, t, sr))
 68.1136 +		return;
 68.1137 +
 68.1138 +	if (x)
 68.1139 +		where = UNW_WHERE_BR;
 68.1140 +	else if (ytreg & 0x80)
 68.1141 +		where = UNW_WHERE_FR;
 68.1142 +
 68.1143 +	r = sr->curr.reg + decode_abreg(abreg, 0);
 68.1144 +	r->where = where;
 68.1145 +	r->when = sr->region_start + min_t(int, t, sr->region_len - 1);
 68.1146 +	r->val = (ytreg & 0x7f);
 68.1147 +}
 68.1148 +
 68.1149 +static inline void
 68.1150 +desc_spill_psprel_p (unsigned char qp, unw_word t, unsigned char abreg, unw_word pspoff,
 68.1151 +		     struct unw_state_record *sr)
 68.1152 +{
 68.1153 +	struct unw_reg_info *r;
 68.1154 +
 68.1155 +	if (!desc_is_active(qp, t, sr))
 68.1156 +		return;
 68.1157 +
 68.1158 +	r = sr->curr.reg + decode_abreg(abreg, 1);
 68.1159 +	r->where = UNW_WHERE_PSPREL;
 68.1160 +	r->when = sr->region_start + min_t(int, t, sr->region_len - 1);
 68.1161 +	r->val = 0x10 - 4*pspoff;
 68.1162 +}
 68.1163 +
 68.1164 +static inline void
 68.1165 +desc_spill_sprel_p (unsigned char qp, unw_word t, unsigned char abreg, unw_word spoff,
 68.1166 +		       struct unw_state_record *sr)
 68.1167 +{
 68.1168 +	struct unw_reg_info *r;
 68.1169 +
 68.1170 +	if (!desc_is_active(qp, t, sr))
 68.1171 +		return;
 68.1172 +
 68.1173 +	r = sr->curr.reg + decode_abreg(abreg, 1);
 68.1174 +	r->where = UNW_WHERE_SPREL;
 68.1175 +	r->when = sr->region_start + min_t(int, t, sr->region_len - 1);
 68.1176 +	r->val = 4*spoff;
 68.1177 +}
 68.1178 +
 68.1179 +#define UNW_DEC_BAD_CODE(code)			printk(KERN_ERR "unwind: unknown code 0x%02x\n", \
 68.1180 +						       code);
 68.1181 +
 68.1182 +/*
 68.1183 + * region headers:
 68.1184 + */
 68.1185 +#define UNW_DEC_PROLOGUE_GR(fmt,r,m,gr,arg)	desc_prologue(0,r,m,gr,arg)
 68.1186 +#define UNW_DEC_PROLOGUE(fmt,b,r,arg)		desc_prologue(b,r,0,32,arg)
 68.1187 +/*
 68.1188 + * prologue descriptors:
 68.1189 + */
 68.1190 +#define UNW_DEC_ABI(fmt,a,c,arg)		desc_abi(a,c,arg)
 68.1191 +#define UNW_DEC_BR_GR(fmt,b,g,arg)		desc_br_gr(b,g,arg)
 68.1192 +#define UNW_DEC_BR_MEM(fmt,b,arg)		desc_br_mem(b,arg)
 68.1193 +#define UNW_DEC_FRGR_MEM(fmt,g,f,arg)		desc_frgr_mem(g,f,arg)
 68.1194 +#define UNW_DEC_FR_MEM(fmt,f,arg)		desc_fr_mem(f,arg)
 68.1195 +#define UNW_DEC_GR_GR(fmt,m,g,arg)		desc_gr_gr(m,g,arg)
 68.1196 +#define UNW_DEC_GR_MEM(fmt,m,arg)		desc_gr_mem(m,arg)
 68.1197 +#define UNW_DEC_MEM_STACK_F(fmt,t,s,arg)	desc_mem_stack_f(t,s,arg)
 68.1198 +#define UNW_DEC_MEM_STACK_V(fmt,t,arg)		desc_mem_stack_v(t,arg)
 68.1199 +#define UNW_DEC_REG_GR(fmt,r,d,arg)		desc_reg_gr(r,d,arg)
 68.1200 +#define UNW_DEC_REG_PSPREL(fmt,r,o,arg)		desc_reg_psprel(r,o,arg)
 68.1201 +#define UNW_DEC_REG_SPREL(fmt,r,o,arg)		desc_reg_sprel(r,o,arg)
 68.1202 +#define UNW_DEC_REG_WHEN(fmt,r,t,arg)		desc_reg_when(r,t,arg)
 68.1203 +#define UNW_DEC_PRIUNAT_WHEN_GR(fmt,t,arg)	desc_reg_when(UNW_REG_PRI_UNAT_GR,t,arg)
 68.1204 +#define UNW_DEC_PRIUNAT_WHEN_MEM(fmt,t,arg)	desc_reg_when(UNW_REG_PRI_UNAT_MEM,t,arg)
 68.1205 +#define UNW_DEC_PRIUNAT_GR(fmt,r,arg)		desc_reg_gr(UNW_REG_PRI_UNAT_GR,r,arg)
 68.1206 +#define UNW_DEC_PRIUNAT_PSPREL(fmt,o,arg)	desc_reg_psprel(UNW_REG_PRI_UNAT_MEM,o,arg)
 68.1207 +#define UNW_DEC_PRIUNAT_SPREL(fmt,o,arg)	desc_reg_sprel(UNW_REG_PRI_UNAT_MEM,o,arg)
 68.1208 +#define UNW_DEC_RP_BR(fmt,d,arg)		desc_rp_br(d,arg)
 68.1209 +#define UNW_DEC_SPILL_BASE(fmt,o,arg)		desc_spill_base(o,arg)
 68.1210 +#define UNW_DEC_SPILL_MASK(fmt,m,arg)		(m = desc_spill_mask(m,arg))
 68.1211 +/*
 68.1212 + * body descriptors:
 68.1213 + */
 68.1214 +#define UNW_DEC_EPILOGUE(fmt,t,c,arg)		desc_epilogue(t,c,arg)
 68.1215 +#define UNW_DEC_COPY_STATE(fmt,l,arg)		desc_copy_state(l,arg)
 68.1216 +#define UNW_DEC_LABEL_STATE(fmt,l,arg)		desc_label_state(l,arg)
 68.1217 +/*
 68.1218 + * general unwind descriptors:
 68.1219 + */
 68.1220 +#define UNW_DEC_SPILL_REG_P(f,p,t,a,x,y,arg)	desc_spill_reg_p(p,t,a,x,y,arg)
 68.1221 +#define UNW_DEC_SPILL_REG(f,t,a,x,y,arg)	desc_spill_reg_p(0,t,a,x,y,arg)
 68.1222 +#define UNW_DEC_SPILL_PSPREL_P(f,p,t,a,o,arg)	desc_spill_psprel_p(p,t,a,o,arg)
 68.1223 +#define UNW_DEC_SPILL_PSPREL(f,t,a,o,arg)	desc_spill_psprel_p(0,t,a,o,arg)
 68.1224 +#define UNW_DEC_SPILL_SPREL_P(f,p,t,a,o,arg)	desc_spill_sprel_p(p,t,a,o,arg)
 68.1225 +#define UNW_DEC_SPILL_SPREL(f,t,a,o,arg)	desc_spill_sprel_p(0,t,a,o,arg)
 68.1226 +#define UNW_DEC_RESTORE_P(f,p,t,a,arg)		desc_restore_p(p,t,a,arg)
 68.1227 +#define UNW_DEC_RESTORE(f,t,a,arg)		desc_restore_p(0,t,a,arg)
 68.1228 +
 68.1229 +#include "unwind_decoder.c"
 68.1230 +
 68.1231 +
 68.1232 +/* Unwind scripts. */
 68.1233 +
 68.1234 +static inline unw_hash_index_t
 68.1235 +hash (unsigned long ip)
 68.1236 +{
 68.1237 +#	define hashmagic	0x9e3779b97f4a7c16UL	/* based on (sqrt(5)/2-1)*2^64 */
 68.1238 +
 68.1239 +	return (ip >> 4)*hashmagic >> (64 - UNW_LOG_HASH_SIZE);
 68.1240 +#undef hashmagic
 68.1241 +}
 68.1242 +
 68.1243 +static inline long
 68.1244 +cache_match (struct unw_script *script, unsigned long ip, unsigned long pr)
 68.1245 +{
 68.1246 +	read_lock(&script->lock);
 68.1247 +	if (ip == script->ip && ((pr ^ script->pr_val) & script->pr_mask) == 0)
 68.1248 +		/* keep the read lock... */
 68.1249 +		return 1;
 68.1250 +	read_unlock(&script->lock);
 68.1251 +	return 0;
 68.1252 +}
 68.1253 +
 68.1254 +static inline struct unw_script *
 68.1255 +script_lookup (struct unw_frame_info *info)
 68.1256 +{
 68.1257 +	struct unw_script *script = unw.cache + info->hint;
 68.1258 +	unsigned short index;
 68.1259 +	unsigned long ip, pr;
 68.1260 +
 68.1261 +	if (UNW_DEBUG_ON(0))
 68.1262 +		return NULL;	/* Always regenerate scripts in debug mode */
 68.1263 +
 68.1264 +	STAT(++unw.stat.cache.lookups);
 68.1265 +
 68.1266 +	ip = info->ip;
 68.1267 +	pr = info->pr;
 68.1268 +
 68.1269 +	if (cache_match(script, ip, pr)) {
 68.1270 +		STAT(++unw.stat.cache.hinted_hits);
 68.1271 +		return script;
 68.1272 +	}
 68.1273 +
 68.1274 +	index = unw.hash[hash(ip)];
 68.1275 +	if (index >= UNW_CACHE_SIZE)
 68.1276 +		return NULL;
 68.1277 +
 68.1278 +	script = unw.cache + index;
 68.1279 +	while (1) {
 68.1280 +		if (cache_match(script, ip, pr)) {
 68.1281 +			/* update hint; no locking required as single-word writes are atomic */
 68.1282 +			STAT(++unw.stat.cache.normal_hits);
 68.1283 +			unw.cache[info->prev_script].hint = script - unw.cache;
 68.1284 +			return script;
 68.1285 +		}
 68.1286 +		if (script->coll_chain >= UNW_HASH_SIZE)
 68.1287 +			return NULL;
 68.1288 +		script = unw.cache + script->coll_chain;
 68.1289 +		STAT(++unw.stat.cache.collision_chain_traversals);
 68.1290 +	}
 68.1291 +}
 68.1292 +
 68.1293 +/*
 68.1294 + * On returning, a write lock for the SCRIPT is still being held.
 68.1295 + */
 68.1296 +static inline struct unw_script *
 68.1297 +script_new (unsigned long ip)
 68.1298 +{
 68.1299 +	struct unw_script *script, *prev, *tmp;
 68.1300 +	unw_hash_index_t index;
 68.1301 +	unsigned short head;
 68.1302 +
 68.1303 +	STAT(++unw.stat.script.news);
 68.1304 +
 68.1305 +	/*
 68.1306 +	 * Can't (easily) use cmpxchg() here because of ABA problem
 68.1307 +	 * that is intrinsic in cmpxchg()...
 68.1308 +	 */
 68.1309 +	head = unw.lru_head;
 68.1310 +	script = unw.cache + head;
 68.1311 +	unw.lru_head = script->lru_chain;
 68.1312 +
 68.1313 +	/*
 68.1314 +	 * We'd deadlock here if we interrupted a thread that is holding a read lock on
 68.1315 +	 * script->lock.  Thus, if the write_trylock() fails, we simply bail out.  The
 68.1316 +	 * alternative would be to disable interrupts whenever we hold a read-lock, but
 68.1317 +	 * that seems silly.
 68.1318 +	 */
 68.1319 +	if (!write_trylock(&script->lock))
 68.1320 +		return NULL;
 68.1321 +
 68.1322 +	/* re-insert script at the tail of the LRU chain: */
 68.1323 +	unw.cache[unw.lru_tail].lru_chain = head;
 68.1324 +	unw.lru_tail = head;
 68.1325 +
 68.1326 +	/* remove the old script from the hash table (if it's there): */
 68.1327 +	if (script->ip) {
 68.1328 +		index = hash(script->ip);
 68.1329 +		tmp = unw.cache + unw.hash[index];
 68.1330 +		prev = NULL;
 68.1331 +		while (1) {
 68.1332 +			if (tmp == script) {
 68.1333 +				if (prev)
 68.1334 +					prev->coll_chain = tmp->coll_chain;
 68.1335 +				else
 68.1336 +					unw.hash[index] = tmp->coll_chain;
 68.1337 +				break;
 68.1338 +			} else
 68.1339 +				prev = tmp;
 68.1340 +			if (tmp->coll_chain >= UNW_CACHE_SIZE)
 68.1341 +			/* old script wasn't in the hash-table */
 68.1342 +				break;
 68.1343 +			tmp = unw.cache + tmp->coll_chain;
 68.1344 +		}
 68.1345 +	}
 68.1346 +
 68.1347 +	/* enter new script in the hash table */
 68.1348 +	index = hash(ip);
 68.1349 +	script->coll_chain = unw.hash[index];
 68.1350 +	unw.hash[index] = script - unw.cache;
 68.1351 +
 68.1352 +	script->ip = ip;	/* set new IP while we're holding the locks */
 68.1353 +
 68.1354 +	STAT(if (script->coll_chain < UNW_CACHE_SIZE) ++unw.stat.script.collisions);
 68.1355 +
 68.1356 +	script->flags = 0;
 68.1357 +	script->hint = 0;
 68.1358 +	script->count = 0;
 68.1359 +	return script;
 68.1360 +}
 68.1361 +
 68.1362 +static void
 68.1363 +script_finalize (struct unw_script *script, struct unw_state_record *sr)
 68.1364 +{
 68.1365 +	script->pr_mask = sr->pr_mask;
 68.1366 +	script->pr_val = sr->pr_val;
 68.1367 +	/*
 68.1368 +	 * We could down-grade our write-lock on script->lock here but
 68.1369 +	 * the rwlock API doesn't offer atomic lock downgrading, so
 68.1370 +	 * we'll just keep the write-lock and release it later when
 68.1371 +	 * we're done using the script.
 68.1372 +	 */
 68.1373 +}
 68.1374 +
 68.1375 +static inline void
 68.1376 +script_emit (struct unw_script *script, struct unw_insn insn)
 68.1377 +{
 68.1378 +	if (script->count >= UNW_MAX_SCRIPT_LEN) {
 68.1379 +		UNW_DPRINT(0, "unwind.%s: script exceeds maximum size of %u instructions!\n",
 68.1380 +			__FUNCTION__, UNW_MAX_SCRIPT_LEN);
 68.1381 +		return;
 68.1382 +	}
 68.1383 +	script->insn[script->count++] = insn;
 68.1384 +}
 68.1385 +
 68.1386 +static inline void
 68.1387 +emit_nat_info (struct unw_state_record *sr, int i, struct unw_script *script)
 68.1388 +{
 68.1389 +	struct unw_reg_info *r = sr->curr.reg + i;
 68.1390 +	enum unw_insn_opcode opc;
 68.1391 +	struct unw_insn insn;
 68.1392 +	unsigned long val = 0;
 68.1393 +
 68.1394 +	switch (r->where) {
 68.1395 +	      case UNW_WHERE_GR:
 68.1396 +		if (r->val >= 32) {
 68.1397 +			/* register got spilled to a stacked register */
 68.1398 +			opc = UNW_INSN_SETNAT_TYPE;
 68.1399 +			val = UNW_NAT_REGSTK;
 68.1400 +		} else
 68.1401 +			/* register got spilled to a scratch register */
 68.1402 +			opc = UNW_INSN_SETNAT_MEMSTK;
 68.1403 +		break;
 68.1404 +
 68.1405 +	      case UNW_WHERE_FR:
 68.1406 +		opc = UNW_INSN_SETNAT_TYPE;
 68.1407 +		val = UNW_NAT_VAL;
 68.1408 +		break;
 68.1409 +
 68.1410 +	      case UNW_WHERE_BR:
 68.1411 +		opc = UNW_INSN_SETNAT_TYPE;
 68.1412 +		val = UNW_NAT_NONE;
 68.1413 +		break;
 68.1414 +
 68.1415 +	      case UNW_WHERE_PSPREL:
 68.1416 +	      case UNW_WHERE_SPREL:
 68.1417 +		opc = UNW_INSN_SETNAT_MEMSTK;
 68.1418 +		break;
 68.1419 +
 68.1420 +	      default:
 68.1421 +		UNW_DPRINT(0, "unwind.%s: don't know how to emit nat info for where = %u\n",
 68.1422 +			   __FUNCTION__, r->where);
 68.1423 +		return;
 68.1424 +	}
 68.1425 +	insn.opc = opc;
 68.1426 +	insn.dst = unw.preg_index[i];
 68.1427 +	insn.val = val;
 68.1428 +	script_emit(script, insn);
 68.1429 +}
 68.1430 +
 68.1431 +static void
 68.1432 +compile_reg (struct unw_state_record *sr, int i, struct unw_script *script)
 68.1433 +{
 68.1434 +	struct unw_reg_info *r = sr->curr.reg + i;
 68.1435 +	enum unw_insn_opcode opc;
 68.1436 +	unsigned long val, rval;
 68.1437 +	struct unw_insn insn;
 68.1438 +	long need_nat_info;
 68.1439 +
 68.1440 +	if (r->where == UNW_WHERE_NONE || r->when >= sr->when_target)
 68.1441 +		return;
 68.1442 +
 68.1443 +	opc = UNW_INSN_MOVE;
 68.1444 +	val = rval = r->val;
 68.1445 +	need_nat_info = (i >= UNW_REG_R4 && i <= UNW_REG_R7);
 68.1446 +
 68.1447 +	switch (r->where) {
 68.1448 +	      case UNW_WHERE_GR:
 68.1449 +		if (rval >= 32) {
 68.1450 +			opc = UNW_INSN_MOVE_STACKED;
 68.1451 +			val = rval - 32;
 68.1452 +		} else if (rval >= 4 && rval <= 7) {
 68.1453 +			if (need_nat_info) {
 68.1454 +				opc = UNW_INSN_MOVE2;
 68.1455 +				need_nat_info = 0;
 68.1456 +			}
 68.1457 +			val = unw.preg_index[UNW_REG_R4 + (rval - 4)];
 68.1458 +		} else if (rval == 0) {
 68.1459 +			opc = UNW_INSN_MOVE_CONST;
 68.1460 +			val = 0;
 68.1461 +		} else {
 68.1462 +			/* register got spilled to a scratch register */
 68.1463 +			opc = UNW_INSN_MOVE_SCRATCH;
 68.1464 +			val = pt_regs_off(rval);
 68.1465 +		}
 68.1466 +		break;
 68.1467 +
 68.1468 +	      case UNW_WHERE_FR:
 68.1469 +		if (rval <= 5)
 68.1470 +			val = unw.preg_index[UNW_REG_F2  + (rval -  2)];
 68.1471 +		else if (rval >= 16 && rval <= 31)
 68.1472 +			val = unw.preg_index[UNW_REG_F16 + (rval - 16)];
 68.1473 +		else {
 68.1474 +			opc = UNW_INSN_MOVE_SCRATCH;
 68.1475 +			if (rval <= 11)
 68.1476 +				val = offsetof(struct pt_regs, f6) + 16*(rval - 6);
 68.1477 +			else
 68.1478 +				UNW_DPRINT(0, "unwind.%s: kernel may not touch f%lu\n",
 68.1479 +					   __FUNCTION__, rval);
 68.1480 +		}
 68.1481 +		break;
 68.1482 +
 68.1483 +	      case UNW_WHERE_BR:
 68.1484 +		if (rval >= 1 && rval <= 5)
 68.1485 +			val = unw.preg_index[UNW_REG_B1 + (rval - 1)];
 68.1486 +		else {
 68.1487 +			opc = UNW_INSN_MOVE_SCRATCH;
 68.1488 +			if (rval == 0)
 68.1489 +				val = offsetof(struct pt_regs, b0);
 68.1490 +			else if (rval == 6)
 68.1491 +				val = offsetof(struct pt_regs, b6);
 68.1492 +			else
 68.1493 +				val = offsetof(struct pt_regs, b7);
 68.1494 +		}
 68.1495 +		break;
 68.1496 +
 68.1497 +	      case UNW_WHERE_SPREL:
 68.1498 +		opc = UNW_INSN_ADD_SP;
 68.1499 +		break;
 68.1500 +
 68.1501 +	      case UNW_WHERE_PSPREL:
 68.1502 +		opc = UNW_INSN_ADD_PSP;
 68.1503 +		break;
 68.1504 +
 68.1505 +	      default:
 68.1506 +		UNW_DPRINT(0, "unwind%s: register %u has unexpected `where' value of %u\n",
 68.1507 +			   __FUNCTION__, i, r->where);
 68.1508 +		break;
 68.1509 +	}
 68.1510 +	insn.opc = opc;
 68.1511 +	insn.dst = unw.preg_index[i];
 68.1512 +	insn.val = val;
 68.1513 +	script_emit(script, insn);
 68.1514 +	if (need_nat_info)
 68.1515 +		emit_nat_info(sr, i, script);
 68.1516 +
 68.1517 +	if (i == UNW_REG_PSP) {
 68.1518 +		/*
 68.1519 +		 * info->psp must contain the _value_ of the previous
 68.1520 +		 * sp, not it's save location.  We get this by
 68.1521 +		 * dereferencing the value we just stored in
 68.1522 +		 * info->psp:
 68.1523 +		 */
 68.1524 +		insn.opc = UNW_INSN_LOAD;
 68.1525 +		insn.dst = insn.val = unw.preg_index[UNW_REG_PSP];
 68.1526 +		script_emit(script, insn);
 68.1527 +	}
 68.1528 +}
 68.1529 +
 68.1530 +static inline const struct unw_table_entry *
 68.1531 +lookup (struct unw_table *table, unsigned long rel_ip)
 68.1532 +{
 68.1533 +	const struct unw_table_entry *e = NULL;
 68.1534 +	unsigned long lo, hi, mid;
 68.1535 +
 68.1536 +	/* do a binary search for right entry: */
 68.1537 +	for (lo = 0, hi = table->length; lo < hi; ) {
 68.1538 +		mid = (lo + hi) / 2;
 68.1539 +		e = &table->array[mid];
 68.1540 +		if (rel_ip < e->start_offset)
 68.1541 +			hi = mid;
 68.1542 +		else if (rel_ip >= e->end_offset)
 68.1543 +			lo = mid + 1;
 68.1544 +		else
 68.1545 +			break;
 68.1546 +	}
 68.1547 +	if (rel_ip < e->start_offset || rel_ip >= e->end_offset)
 68.1548 +		return NULL;
 68.1549 +	return e;
 68.1550 +}
 68.1551 +
 68.1552 +/*
 68.1553 + * Build an unwind script that unwinds from state OLD_STATE to the
 68.1554 + * entrypoint of the function that called OLD_STATE.
 68.1555 + */
 68.1556 +static inline struct unw_script *
 68.1557 +build_script (struct unw_frame_info *info)
 68.1558 +{
 68.1559 +	const struct unw_table_entry *e = NULL;
 68.1560 +	struct unw_script *script = NULL;
 68.1561 +	struct unw_labeled_state *ls, *next;
 68.1562 +	unsigned long ip = info->ip;
 68.1563 +	struct unw_state_record sr;
 68.1564 +	struct unw_table *table;
 68.1565 +	struct unw_reg_info *r;
 68.1566 +	struct unw_insn insn;
 68.1567 +	u8 *dp, *desc_end;
 68.1568 +	u64 hdr;
 68.1569 +	int i;
 68.1570 +	STAT(unsigned long start, parse_start;)
 68.1571 +
 68.1572 +	STAT(++unw.stat.script.builds; start = ia64_get_itc());
 68.1573 +
 68.1574 +	/* build state record */
 68.1575 +	memset(&sr, 0, sizeof(sr));
 68.1576 +	for (r = sr.curr.reg; r < sr.curr.reg + UNW_NUM_REGS; ++r)
 68.1577 +		r->when = UNW_WHEN_NEVER;
 68.1578 +	sr.pr_val = info->pr;
 68.1579 +
 68.1580 +	UNW_DPRINT(3, "unwind.%s: ip 0x%lx\n", __FUNCTION__, ip);
 68.1581 +	script = script_new(ip);
 68.1582 +	if (!script) {
 68.1583 +		UNW_DPRINT(0, "unwind.%s: failed to create unwind script\n",  __FUNCTION__);
 68.1584 +		STAT(unw.stat.script.build_time += ia64_get_itc() - start);
 68.1585 +		return NULL;
 68.1586 +	}
 68.1587 +	unw.cache[info->prev_script].hint = script - unw.cache;
 68.1588 +
 68.1589 +	/* search the kernels and the modules' unwind tables for IP: */
 68.1590 +
 68.1591 +	STAT(parse_start = ia64_get_itc());
 68.1592 +
 68.1593 +	for (table = unw.tables; table; table = table->next) {
 68.1594 +		if (ip >= table->start && ip < table->end) {
 68.1595 +			e = lookup(table, ip - table->segment_base);
 68.1596 +			break;
 68.1597 +		}
 68.1598 +	}
 68.1599 +	if (!e) {
 68.1600 +		/* no info, return default unwinder (leaf proc, no mem stack, no saved regs)  */
 68.1601 +		UNW_DPRINT(1, "unwind.%s: no unwind info for ip=0x%lx (prev ip=0x%lx)\n",
 68.1602 +			__FUNCTION__, ip, unw.cache[info->prev_script].ip);
 68.1603 +		sr.curr.reg[UNW_REG_RP].where = UNW_WHERE_BR;
 68.1604 +		sr.curr.reg[UNW_REG_RP].when = -1;
 68.1605 +		sr.curr.reg[UNW_REG_RP].val = 0;
 68.1606 +		compile_reg(&sr, UNW_REG_RP, script);
 68.1607 +		script_finalize(script, &sr);
 68.1608 +		STAT(unw.stat.script.parse_time += ia64_get_itc() - parse_start);
 68.1609 +		STAT(unw.stat.script.build_time += ia64_get_itc() - start);
 68.1610 +		return script;
 68.1611 +	}
 68.1612 +
 68.1613 +	sr.when_target = (3*((ip & ~0xfUL) - (table->segment_base + e->start_offset))/16
 68.1614 +			  + (ip & 0xfUL));
 68.1615 +	hdr = *(u64 *) (table->segment_base + e->info_offset);
 68.1616 +	dp =   (u8 *)  (table->segment_base + e->info_offset + 8);
 68.1617 +	desc_end = dp + 8*UNW_LENGTH(hdr);
 68.1618 +
 68.1619 +	while (!sr.done && dp < desc_end)
 68.1620 +		dp = unw_decode(dp, sr.in_body, &sr);
 68.1621 +
 68.1622 +	if (sr.when_target > sr.epilogue_start) {
 68.1623 +		/*
 68.1624 +		 * sp has been restored and all values on the memory stack below
 68.1625 +		 * psp also have been restored.
 68.1626 +		 */
 68.1627 +		sr.curr.reg[UNW_REG_PSP].val = 0;
 68.1628 +		sr.curr.reg[UNW_REG_PSP].where = UNW_WHERE_NONE;
 68.1629 +		sr.curr.reg[UNW_REG_PSP].when = UNW_WHEN_NEVER;
 68.1630 +		for (r = sr.curr.reg; r < sr.curr.reg + UNW_NUM_REGS; ++r)
 68.1631 +			if ((r->where == UNW_WHERE_PSPREL && r->val <= 0x10)
 68.1632 +			    || r->where == UNW_WHERE_SPREL)
 68.1633 +			{
 68.1634 +				r->val = 0;
 68.1635 +				r->where = UNW_WHERE_NONE;
 68.1636 +				r->when = UNW_WHEN_NEVER;
 68.1637 +			}
 68.1638 +	}
 68.1639 +
 68.1640 +	script->flags = sr.flags;
 68.1641 +
 68.1642 +	/*
 68.1643 +	 * If RP did't get saved, generate entry for the return link
 68.1644 +	 * register.
 68.1645 +	 */
 68.1646 +	if (sr.curr.reg[UNW_REG_RP].when >= sr.when_target) {
 68.1647 +		sr.curr.reg[UNW_REG_RP].where = UNW_WHERE_BR;
 68.1648 +		sr.curr.reg[UNW_REG_RP].when = -1;
 68.1649 +		sr.curr.reg[UNW_REG_RP].val = sr.return_link_reg;
 68.1650 +		UNW_DPRINT(1, "unwind.%s: using default for rp at ip=0x%lx where=%d val=0x%lx\n",
 68.1651 +			   __FUNCTION__, ip, sr.curr.reg[UNW_REG_RP].where,
 68.1652 +			   sr.curr.reg[UNW_REG_RP].val);
 68.1653 +	}
 68.1654 +
 68.1655 +#ifdef UNW_DEBUG
 68.1656 +	UNW_DPRINT(1, "unwind.%s: state record for func 0x%lx, t=%u:\n",
 68.1657 +		__FUNCTION__, table->segment_base + e->start_offset, sr.when_target);
 68.1658 +	for (r = sr.curr.reg; r < sr.curr.reg + UNW_NUM_REGS; ++r) {
 68.1659 +		if (r->where != UNW_WHERE_NONE || r->when != UNW_WHEN_NEVER) {
 68.1660 +			UNW_DPRINT(1, "  %s <- ", unw.preg_name[r - sr.curr.reg]);
 68.1661 +			switch (r->where) {
 68.1662 +			      case UNW_WHERE_GR:     UNW_DPRINT(1, "r%lu", r->val); break;
 68.1663 +			      case UNW_WHERE_FR:     UNW_DPRINT(1, "f%lu", r->val); break;
 68.1664 +			      case UNW_WHERE_BR:     UNW_DPRINT(1, "b%lu", r->val); break;
 68.1665 +			      case UNW_WHERE_SPREL:  UNW_DPRINT(1, "[sp+0x%lx]", r->val); break;
 68.1666 +			      case UNW_WHERE_PSPREL: UNW_DPRINT(1, "[psp+0x%lx]", r->val); break;
 68.1667 +			      case UNW_WHERE_NONE:
 68.1668 +				UNW_DPRINT(1, "%s+0x%lx", unw.preg_name[r - sr.curr.reg], r->val);
 68.1669 +				break;
 68.1670 +
 68.1671 +			      default:
 68.1672 +				UNW_DPRINT(1, "BADWHERE(%d)", r->where);
 68.1673 +				break;
 68.1674 +			}
 68.1675 +			UNW_DPRINT(1, "\t\t%d\n", r->when);
 68.1676 +		}
 68.1677 +	}
 68.1678 +#endif
 68.1679 +
 68.1680 +	STAT(unw.stat.script.parse_time += ia64_get_itc() - parse_start);
 68.1681 +
 68.1682 +	/* translate state record into unwinder instructions: */
 68.1683 +
 68.1684 +	/*
 68.1685 +	 * First, set psp if we're dealing with a fixed-size frame;
 68.1686 +	 * subsequent instructions may depend on this value.
 68.1687 +	 */
 68.1688 +	if (sr.when_target > sr.curr.reg[UNW_REG_PSP].when
 68.1689 +	    && (sr.curr.reg[UNW_REG_PSP].where == UNW_WHERE_NONE)
 68.1690 +	    && sr.curr.reg[UNW_REG_PSP].val != 0) {
 68.1691 +		/* new psp is sp plus frame size */
 68.1692 +		insn.opc = UNW_INSN_ADD;
 68.1693 +		insn.dst = offsetof(struct unw_frame_info, psp)/8;
 68.1694 +		insn.val = sr.curr.reg[UNW_REG_PSP].val;	/* frame size */
 68.1695 +		script_emit(script, insn);
 68.1696 +	}
 68.1697 +
 68.1698 +	/* determine where the primary UNaT is: */
 68.1699 +	if (sr.when_target < sr.curr.reg[UNW_REG_PRI_UNAT_GR].when)
 68.1700 +		i = UNW_REG_PRI_UNAT_MEM;
 68.1701 +	else if (sr.when_target < sr.curr.reg[UNW_REG_PRI_UNAT_MEM].when)
 68.1702 +		i = UNW_REG_PRI_UNAT_GR;
 68.1703 +	else if (sr.curr.reg[UNW_REG_PRI_UNAT_MEM].when > sr.curr.reg[UNW_REG_PRI_UNAT_GR].when)
 68.1704 +		i = UNW_REG_PRI_UNAT_MEM;
 68.1705 +	else
 68.1706 +		i = UNW_REG_PRI_UNAT_GR;
 68.1707 +
 68.1708 +	compile_reg(&sr, i, script);
 68.1709 +
 68.1710 +	for (i = UNW_REG_BSP; i < UNW_NUM_REGS; ++i)
 68.1711 +		compile_reg(&sr, i, script);
 68.1712 +
 68.1713 +	/* free labeled register states & stack: */
 68.1714 +
 68.1715 +	STAT(parse_start = ia64_get_itc());
 68.1716 +	for (ls = sr.labeled_states; ls; ls = next) {
 68.1717 +		next = ls->next;
 68.1718 +		free_state_stack(&ls->saved_state);
 68.1719 +		free_labeled_state(ls);
 68.1720 +	}
 68.1721 +	free_state_stack(&sr.curr);
 68.1722 +	STAT(unw.stat.script.parse_time += ia64_get_itc() - parse_start);
 68.1723 +
 68.1724 +	script_finalize(script, &sr);
 68.1725 +	STAT(unw.stat.script.build_time += ia64_get_itc() - start);
 68.1726 +	return script;
 68.1727 +}
 68.1728 +
 68.1729 +/*
 68.1730 + * Apply the unwinding actions represented by OPS and update SR to
 68.1731 + * reflect the state that existed upon entry to the function that this
 68.1732 + * unwinder represents.
 68.1733 + */
 68.1734 +static inline void
 68.1735 +run_script (struct unw_script *script, struct unw_frame_info *state)
 68.1736 +{
 68.1737 +	struct unw_insn *ip, *limit, next_insn;
 68.1738 +	unsigned long opc, dst, val, off;
 68.1739 +	unsigned long *s = (unsigned long *) state;
 68.1740 +	STAT(unsigned long start;)
 68.1741 +
 68.1742 +	STAT(++unw.stat.script.runs; start = ia64_get_itc());
 68.1743 +	state->flags = script->flags;
 68.1744 +	ip = script->insn;
 68.1745 +	limit = script->insn + script->count;
 68.1746 +	next_insn = *ip;
 68.1747 +
 68.1748 +	while (ip++ < limit) {
 68.1749 +		opc = next_insn.opc;
 68.1750 +		dst = next_insn.dst;
 68.1751 +		val = next_insn.val;
 68.1752 +		next_insn = *ip;
 68.1753 +
 68.1754 +	  redo:
 68.1755 +		switch (opc) {
 68.1756 +		      case UNW_INSN_ADD:
 68.1757 +			s[dst] += val;
 68.1758 +			break;
 68.1759 +
 68.1760 +		      case UNW_INSN_MOVE2:
 68.1761 +			if (!s[val])
 68.1762 +				goto lazy_init;
 68.1763 +			s[dst+1] = s[val+1];
 68.1764 +			s[dst] = s[val];
 68.1765 +			break;
 68.1766 +
 68.1767 +		      case UNW_INSN_MOVE:
 68.1768 +			if (!s[val])
 68.1769 +				goto lazy_init;
 68.1770 +			s[dst] = s[val];
 68.1771 +			break;
 68.1772 +
 68.1773 +		      case UNW_INSN_MOVE_SCRATCH:
 68.1774 +			if (state->pt) {
 68.1775 +				s[dst] = (unsigned long) get_scratch_regs(state) + val;
 68.1776 +			} else {
 68.1777 +				s[dst] = 0;
 68.1778 +				UNW_DPRINT(0, "unwind.%s: no state->pt, dst=%ld, val=%ld\n",
 68.1779 +					   __FUNCTION__, dst, val);
 68.1780 +			}
 68.1781 +			break;
 68.1782 +
 68.1783 +		      case UNW_INSN_MOVE_CONST:
 68.1784 +			if (val == 0)
 68.1785 +				s[dst] = (unsigned long) &unw.r0;
 68.1786 +			else {
 68.1787 +				s[dst] = 0;
 68.1788 +				UNW_DPRINT(0, "unwind.%s: UNW_INSN_MOVE_CONST bad val=%ld\n",
 68.1789 +					   __FUNCTION__, val);
 68.1790 +			}
 68.1791 +			break;
 68.1792 +
 68.1793 +
 68.1794 +		      case UNW_INSN_MOVE_STACKED:
 68.1795 +			s[dst] = (unsigned long) ia64_rse_skip_regs((unsigned long *)state->bsp,
 68.1796 +								    val);
 68.1797 +			break;
 68.1798 +
 68.1799 +		      case UNW_INSN_ADD_PSP:
 68.1800 +			s[dst] = state->psp + val;
 68.1801 +			break;
 68.1802 +
 68.1803 +		      case UNW_INSN_ADD_SP:
 68.1804 +			s[dst] = state->sp + val;
 68.1805 +			break;
 68.1806 +
 68.1807 +		      case UNW_INSN_SETNAT_MEMSTK:
 68.1808 +			if (!state->pri_unat_loc)
 68.1809 +				state->pri_unat_loc = &state->sw->caller_unat;
 68.1810 +			/* register off. is a multiple of 8, so the least 3 bits (type) are 0 */
 68.1811 +			s[dst+1] = ((unsigned long) state->pri_unat_loc - s[dst]) | UNW_NAT_MEMSTK;
 68.1812 +			break;
 68.1813 +
 68.1814 +		      case UNW_INSN_SETNAT_TYPE:
 68.1815 +			s[dst+1] = val;
 68.1816 +			break;
 68.1817 +
 68.1818 +		      case UNW_INSN_LOAD:
 68.1819 +#ifdef UNW_DEBUG
 68.1820 +			if ((s[val] & (local_cpu_data->unimpl_va_mask | 0x7)) != 0
 68.1821 +#ifndef XEN
 68.1822 +			    || s[val] < TASK_SIZE
 68.1823 +#endif
 68.1824 +				)
 68.1825 +			{
 68.1826 +				UNW_DPRINT(0, "unwind.%s: rejecting bad psp=0x%lx\n",
 68.1827 +					   __FUNCTION__, s[val]);
 68.1828 +				break;
 68.1829 +			}
 68.1830 +#endif
 68.1831 +			s[dst] = *(unsigned long *) s[val];
 68.1832 +			break;
 68.1833 +		}
 68.1834 +	}
 68.1835 +	STAT(unw.stat.script.run_time += ia64_get_itc() - start);
 68.1836 +	return;
 68.1837 +
 68.1838 +  lazy_init:
 68.1839 +	off = unw.sw_off[val];
 68.1840 +	s[val] = (unsigned long) state->sw + off;
 68.1841 +	if (off >= offsetof(struct switch_stack, r4) && off <= offsetof(struct switch_stack, r7))
 68.1842 +		/*
 68.1843 +		 * We're initializing a general register: init NaT info, too.  Note that
 68.1844 +		 * the offset is a multiple of 8 which gives us the 3 bits needed for
 68.1845 +		 * the type field.
 68.1846 +		 */
 68.1847 +		s[val+1] = (offsetof(struct switch_stack, ar_unat) - off) | UNW_NAT_MEMSTK;
 68.1848 +	goto redo;
 68.1849 +}
 68.1850 +
 68.1851 +static int
 68.1852 +find_save_locs (struct unw_frame_info *info)
 68.1853 +{
 68.1854 +	int have_write_lock = 0;
 68.1855 +	struct unw_script *scr;
 68.1856 +	unsigned long flags = 0;
 68.1857 +
 68.1858 +	if ((info->ip & (local_cpu_data->unimpl_va_mask | 0xf))
 68.1859 +#ifndef XEN
 68.1860 +	    || info->ip < TASK_SIZE
 68.1861 +#endif
 68.1862 +		) {
 68.1863 +		/* don't let obviously bad addresses pollute the cache */
 68.1864 +		/* FIXME: should really be level 0 but it occurs too often. KAO */
 68.1865 +		UNW_DPRINT(1, "unwind.%s: rejecting bad ip=0x%lx\n", __FUNCTION__, info->ip);
 68.1866 +		info->rp_loc = NULL;
 68.1867 +		return -1;
 68.1868 +	}
 68.1869 +
 68.1870 +	scr = script_lookup(info);
 68.1871 +	if (!scr) {
 68.1872 +		spin_lock_irqsave(&unw.lock, flags);
 68.1873 +		scr = build_script(info);
 68.1874 +		if (!scr) {
 68.1875 +			spin_unlock_irqrestore(&unw.lock, flags);
 68.1876 +			UNW_DPRINT(0,
 68.1877 +				   "unwind.%s: failed to locate/build unwind script for ip %lx\n",
 68.1878 +				   __FUNCTION__, info->ip);
 68.1879 +			return -1;
 68.1880 +		}
 68.1881 +		have_write_lock = 1;
 68.1882 +	}
 68.1883 +	info->hint = scr->hint;
 68.1884 +	info->prev_script = scr - unw.cache;
 68.1885 +
 68.1886 +	run_script(scr, info);
 68.1887 +
 68.1888 +	if (have_write_lock) {
 68.1889 +		write_unlock(&scr->lock);
 68.1890 +		spin_unlock_irqrestore(&unw.lock, flags);
 68.1891 +	} else
 68.1892 +		read_unlock(&scr->lock);
 68.1893 +	return 0;
 68.1894 +}
 68.1895 +
 68.1896 +int
 68.1897 +unw_unwind (struct unw_frame_info *info)
 68.1898 +{
 68.1899 +	unsigned long prev_ip, prev_sp, prev_bsp;
 68.1900 +	unsigned long ip, pr, num_regs;
 68.1901 +	STAT(unsigned long start, flags;)
 68.1902 +	int retval;
 68.1903 +
 68.1904 +	STAT(local_irq_save(flags); ++unw.stat.api.unwinds; start = ia64_get_itc());
 68.1905 +
 68.1906 +	prev_ip = info->ip;
 68.1907 +	prev_sp = info->sp;
 68.1908 +	prev_bsp = info->bsp;
 68.1909 +
 68.1910 +	/* restore the ip */
 68.1911 +	if (!info->rp_loc) {
 68.1912 +		/* FIXME: should really be level 0 but it occurs too often. KAO */
 68.1913 +		UNW_DPRINT(1, "unwind.%s: failed to locate return link (ip=0x%lx)!\n",
 68.1914 +			   __FUNCTION__, info->ip);
 68.1915 +		STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
 68.1916 +		return -1;
 68.1917 +	}
 68.1918 +	ip = info->ip = *info->rp_loc;
 68.1919 +	if (ip < GATE_ADDR) {
 68.1920 +		UNW_DPRINT(2, "unwind.%s: reached user-space (ip=0x%lx)\n", __FUNCTION__, ip);
 68.1921 +		STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
 68.1922 +		return -1;
 68.1923 +	}
 68.1924 +
 68.1925 +	/* restore the cfm: */
 68.1926 +	if (!info->pfs_loc) {
 68.1927 +		UNW_DPRINT(0, "unwind.%s: failed to locate ar.pfs!\n", __FUNCTION__);
 68.1928 +		STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
 68.1929 +		return -1;
 68.1930 +	}
 68.1931 +	info->cfm_loc = info->pfs_loc;
 68.1932 +
 68.1933 +	/* restore the bsp: */
 68.1934 +	pr = info->pr;
 68.1935 +	num_regs = 0;
 68.1936 +	if ((info->flags & UNW_FLAG_INTERRUPT_FRAME)) {
 68.1937 +		info->pt = info->sp + 16;
 68.1938 +		if ((pr & (1UL << PRED_NON_SYSCALL)) != 0)
 68.1939 +			num_regs = *info->cfm_loc & 0x7f;		/* size of frame */
 68.1940 +		info->pfs_loc =
 68.1941 +			(unsigned long *) (info->pt + offsetof(struct pt_regs, ar_pfs));
 68.1942 +		UNW_DPRINT(3, "unwind.%s: interrupt_frame pt 0x%lx\n", __FUNCTION__, info->pt);
 68.1943 +	} else
 68.1944 +		num_regs = (*info->cfm_loc >> 7) & 0x7f;	/* size of locals */
 68.1945 +	info->bsp = (unsigned long) ia64_rse_skip_regs((unsigned long *) info->bsp, -num_regs);
 68.1946 +	if (info->bsp < info->regstk.limit || info->bsp > info->regstk.top) {
 68.1947 +		UNW_DPRINT(0, "unwind.%s: bsp (0x%lx) out of range [0x%lx-0x%lx]\n",
 68.1948 +			__FUNCTION__, info->bsp, info->regstk.limit, info->regstk.top);
 68.1949 +		STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
 68.1950 +		return -1;
 68.1951 +	}
 68.1952 +
 68.1953 +	/* restore the sp: */
 68.1954 +	info->sp = info->psp;
 68.1955 +	if (info->sp < info->memstk.top || info->sp > info->memstk.limit) {
 68.1956 +		UNW_DPRINT(0, "unwind.%s: sp (0x%lx) out of range [0x%lx-0x%lx]\n",
 68.1957 +			__FUNCTION__, info->sp, info->memstk.top, info->memstk.limit);
 68.1958 +		STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
 68.1959 +		return -1;
 68.1960 +	}
 68.1961 +
 68.1962 +	if (info->ip == prev_ip && info->sp == prev_sp && info->bsp == prev_bsp) {
 68.1963 +		UNW_DPRINT(0, "unwind.%s: ip, sp, bsp unchanged; stopping here (ip=0x%lx)\n",
 68.1964 +			   __FUNCTION__, ip);
 68.1965 +		STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
 68.1966 +		return -1;
 68.1967 +	}
 68.1968 +
 68.1969 +	/* as we unwind, the saved ar.unat becomes the primary unat: */
 68.1970 +	info->pri_unat_loc = info->unat_loc;
 68.1971 +
 68.1972 +	/* finally, restore the predicates: */
 68.1973 +	unw_get_pr(info, &info->pr);
 68.1974 +
 68.1975 +	retval = find_save_locs(info);
 68.1976 +	STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
 68.1977 +	return retval;
 68.1978 +}
 68.1979 +EXPORT_SYMBOL(unw_unwind);
 68.1980 +
 68.1981 +int
 68.1982 +unw_unwind_to_user (struct unw_frame_info *info)
 68.1983 +{
 68.1984 +	unsigned long ip, sp, pr = 0;
 68.1985 +
 68.1986 +	while (unw_unwind(info) >= 0) {
 68.1987 +		unw_get_sp(info, &sp);
 68.1988 +		if ((long)((unsigned long)info->task + IA64_STK_OFFSET - sp)
 68.1989 +		    < IA64_PT_REGS_SIZE) {
 68.1990 +			UNW_DPRINT(0, "unwind.%s: ran off the top of the kernel stack\n",
 68.1991 +				   __FUNCTION__);
 68.1992 +			break;
 68.1993 +		}
 68.1994 +		if (unw_is_intr_frame(info) &&
 68.1995 +		    (pr & (1UL << PRED_USER_STACK)))
 68.1996 +			return 0;
 68.1997 +		if (unw_get_pr (info, &pr) < 0) {
 68.1998 +			unw_get_rp(info, &ip);
 68.1999 +			UNW_DPRINT(0, "unwind.%s: failed to read "
 68.2000 +				   "predicate register (ip=0x%lx)\n",
 68.2001 +				__FUNCTION__, ip);
 68.2002 +			return -1;
 68.2003 +		}
 68.2004 +	}
 68.2005 +	unw_get_ip(info, &ip);
 68.2006 +	UNW_DPRINT(0, "unwind.%s: failed to unwind to user-level (ip=0x%lx)\n",
 68.2007 +		   __FUNCTION__, ip);
 68.2008 +	return -1;
 68.2009 +}
 68.2010 +EXPORT_SYMBOL(unw_unwind_to_user);
 68.2011 +
 68.2012 +static void
 68.2013 +init_frame_info (struct unw_frame_info *info, struct task_struct *t,
 68.2014 +		 struct switch_stack *sw, unsigned long stktop)
 68.2015 +{
 68.2016 +	unsigned long rbslimit, rbstop, stklimit;
 68.2017 +	STAT(unsigned long start, flags;)
 68.2018 +
 68.2019 +	STAT(local_irq_save(flags); ++unw.stat.api.inits; start = ia64_get_itc());
 68.2020 +
 68.2021 +	/*
 68.2022 +	 * Subtle stuff here: we _could_ unwind through the switch_stack frame but we
 68.2023 +	 * don't want to do that because it would be slow as each preserved register would
 68.2024 +	 * have to be processed.  Instead, what we do here is zero out the frame info and
 68.2025 +	 * start the unwind process at the function that created the switch_stack frame.
 68.2026 +	 * When a preserved value in switch_stack needs to be accessed, run_script() will
 68.2027 +	 * initialize the appropriate pointer on demand.
 68.2028 +	 */
 68.2029 +	memset(info, 0, sizeof(*info));
 68.2030 +
 68.2031 +	rbslimit = (unsigned long) t + IA64_RBS_OFFSET;
 68.2032 +	rbstop   = sw->ar_bspstore;
 68.2033 +	if (rbstop - (unsigned long) t >= IA64_STK_OFFSET)
 68.2034 +		rbstop = rbslimit;
 68.2035 +
 68.2036 +	stklimit = (unsigned long) t + IA64_STK_OFFSET;
 68.2037 +	if (stktop <= rbstop)
 68.2038 +		stktop = rbstop;
 68.2039 +
 68.2040 +	info->regstk.limit = rbslimit;
 68.2041 +	info->regstk.top   = rbstop;
 68.2042 +	info->memstk.limit = stklimit;
 68.2043 +	info->memstk.top   = stktop;
 68.2044 +	info->task = t;
 68.2045 +	info->sw  = sw;
 68.2046 +	info->sp = info->psp = stktop;
 68.2047 +	info->pr = sw->pr;
 68.2048 +	UNW_DPRINT(3, "unwind.%s:\n"
 68.2049 +		   "  task   0x%lx\n"
 68.2050 +		   "  rbs = [0x%lx-0x%lx)\n"
 68.2051 +		   "  stk = [0x%lx-0x%lx)\n"
 68.2052 +		   "  pr     0x%lx\n"
 68.2053 +		   "  sw     0x%lx\n"
 68.2054 +		   "  sp     0x%lx\n",
 68.2055 +		   __FUNCTION__, (unsigned long) t, rbslimit, rbstop, stktop, stklimit,
 68.2056 +		   info->pr, (unsigned long) info->sw, info->sp);
 68.2057 +	STAT(unw.stat.api.init_time += ia64_get_itc() - start; local_irq_restore(flags));
 68.2058 +}
 68.2059 +
 68.2060 +void
 68.2061 +unw_init_frame_info (struct unw_frame_info *info, struct task_struct *t, struct switch_stack *sw)
 68.2062 +{
 68.2063 +	unsigned long sol;
 68.2064 +
 68.2065 +	init_frame_info(info, t, sw, (unsigned long) (sw + 1) - 16);
 68.2066 +	info->cfm_loc = &sw->ar_pfs;
 68.2067 +	sol = (*info->cfm_loc >> 7) & 0x7f;
 68.2068 +	info->bsp = (unsigned long) ia64_rse_skip_regs((unsigned long *) info->regstk.top, -sol);
 68.2069 +	info->ip = sw->b0;
 68.2070 +	UNW_DPRINT(3, "unwind.%s:\n"
 68.2071 +		   "  bsp    0x%lx\n"
 68.2072 +		   "  sol    0x%lx\n"
 68.2073 +		   "  ip     0x%lx\n",
 68.2074 +		   __FUNCTION__, info->bsp, sol, info->ip);
 68.2075 +	find_save_locs(info);
 68.2076 +}
 68.2077 +
 68.2078 +EXPORT_SYMBOL(unw_init_frame_info);
 68.2079 +
 68.2080 +void
 68.2081 +unw_init_from_blocked_task (struct unw_frame_info *info, struct task_struct *t)
 68.2082 +{
 68.2083 +#ifdef XEN
 68.2084 +	struct switch_stack *sw = (struct switch_stack *) (t->arch._thread.ksp + 16);
 68.2085 +#else
 68.2086 +	struct switch_stack *sw = (struct switch_stack *) (t->thread.ksp + 16);
 68.2087 +#endif
 68.2088 +
 68.2089 +	UNW_DPRINT(1, "unwind.%s\n", __FUNCTION__);
 68.2090 +	unw_init_frame_info(info, t, sw);
 68.2091 +}
 68.2092 +EXPORT_SYMBOL(unw_init_from_blocked_task);
 68.2093 +
 68.2094 +static void
 68.2095 +init_unwind_table (struct unw_table *table, const char *name, unsigned long segment_base,
 68.2096 +		   unsigned long gp, const void *table_start, const void *table_end)
 68.2097 +{
 68.2098 +	const struct unw_table_entry *start = table_start, *end = table_end;
 68.2099 +
 68.2100 +	table->name = name;
 68.2101 +	table->segment_base = segment_base;
 68.2102 +	table->gp = gp;
 68.2103 +	table->start = segment_base + start[0].start_offset;
 68.2104 +	table->end = segment_base + end[-1].end_offset;
 68.2105 +	table->array = start;
 68.2106 +	table->length = end - start;
 68.2107 +}
 68.2108 +
 68.2109 +#ifndef XEN
 68.2110 +void *
 68.2111 +unw_add_unwind_table (const char *name, unsigned long segment_base, unsigned long gp,
 68.2112 +		      const void *table_start, const void *table_end)
 68.2113 +{
 68.2114 +	const struct unw_table_entry *start = table_start, *end = table_end;
 68.2115 +	struct unw_table *table;
 68.2116 +	unsigned long flags;
 68.2117 +
 68.2118 +	if (end - start <= 0) {
 68.2119 +		UNW_DPRINT(0, "unwind.%s: ignoring attempt to insert empty unwind table\n",
 68.2120 +			   __FUNCTION__);
 68.2121 +		return NULL;
 68.2122 +	}
 68.2123 +
 68.2124 +	table = kmalloc(sizeof(*table), GFP_USER);
 68.2125 +	if (!table)
 68.2126 +		return NULL;
 68.2127 +
 68.2128 +	init_unwind_table(table, name, segment_base, gp, table_start, table_end);
 68.2129 +
 68.2130 +	spin_lock_irqsave(&unw.lock, flags);
 68.2131 +	{
 68.2132 +		/* keep kernel unwind table at the front (it's searched most commonly): */
 68.2133 +		table->next = unw.tables->next;
 68.2134 +		unw.tables->next = table;
 68.2135 +	}
 68.2136 +	spin_unlock_irqrestore(&unw.lock, flags);
 68.2137 +
 68.2138 +	return table;
 68.2139 +}
 68.2140 +
 68.2141 +void
 68.2142 +unw_remove_unwind_table (void *handle)
 68.2143 +{
 68.2144 +	struct unw_table *table, *prev;
 68.2145 +	struct unw_script *tmp;
 68.2146 +	unsigned long flags;
 68.2147 +	long index;
 68.2148 +
 68.2149 +	if (!handle) {
 68.2150 +		UNW_DPRINT(0, "unwind.%s: ignoring attempt to remove non-existent unwind table\n",
 68.2151 +			   __FUNCTION__);
 68.2152 +		return;
 68.2153 +	}
 68.2154 +
 68.2155 +	table = handle;
 68.2156 +	if (table == &unw.kernel_table) {
 68.2157 +		UNW_DPRINT(0, "unwind.%s: sorry, freeing the kernel's unwind table is a "
 68.2158 +			   "no-can-do!\n", __FUNCTION__);
 68.2159 +		return;
 68.2160 +	}
 68.2161 +
 68.2162 +	spin_lock_irqsave(&unw.lock, flags);
 68.2163 +	{
 68.2164 +		/* first, delete the table: */
 68.2165 +
 68.2166 +		for (prev = (struct unw_table *) &unw.tables; prev; prev = prev->next)
 68.2167 +			if (prev->next == table)
 68.2168 +				break;
 68.2169 +		if (!prev) {
 68.2170 +			UNW_DPRINT(0, "unwind.%s: failed to find unwind table %p\n",
 68.2171 +				   __FUNCTION__, (void *) table);
 68.2172 +			spin_unlock_irqrestore(&unw.lock, flags);
 68.2173 +			return;
 68.2174 +		}
 68.2175 +		prev->next = table->next;
 68.2176 +	}
 68.2177 +	spin_unlock_irqrestore(&unw.lock, flags);
 68.2178 +
 68.2179 +	/* next, remove hash table entries for this table */
 68.2180 +
 68.2181 +	for (index = 0; index <= UNW_HASH_SIZE; ++index) {
 68.2182 +		tmp = unw.cache + unw.hash[index];
 68.2183 +		if (unw.hash[index] >= UNW_CACHE_SIZE
 68.2184 +		    || tmp->ip < table->start || tmp->ip >= table->end)
 68.2185 +			continue;
 68.2186 +
 68.2187 +		write_lock(&tmp->lock);
 68.2188 +		{
 68.2189 +			if (tmp->ip >= table->start && tmp->ip < table->end) {
 68.2190 +				unw.hash[index] = tmp->coll_chain;
 68.2191 +				tmp->ip = 0;
 68.2192 +			}
 68.2193 +		}
 68.2194 +		write_unlock(&tmp->lock);
 68.2195 +	}
 68.2196 +
 68.2197 +	kfree(table);
 68.2198 +}
 68.2199 +
 68.2200 +static int __init
 68.2201 +create_gate_table (void)
 68.2202 +{
 68.2203 +	const struct unw_table_entry *entry, *start, *end;
 68.2204 +	unsigned long *lp, segbase = GATE_ADDR;
 68.2205 +	size_t info_size, size;
 68.2206 +	char *info;
 68.2207 +	Elf64_Phdr *punw = NULL, *phdr = (Elf64_Phdr *) (GATE_ADDR + GATE_EHDR->e_phoff);
 68.2208 +	int i;
 68.2209 +
 68.2210 +	for (i = 0; i < GATE_EHDR->e_phnum; ++i, ++phdr)
 68.2211 +		if (phdr->p_type == PT_IA_64_UNWIND) {
 68.2212 +			punw = phdr;
 68.2213 +			break;
 68.2214 +		}
 68.2215 +
 68.2216 +	if (!punw) {
 68.2217 +		printk("%s: failed to find gate DSO's unwind table!\n", __FUNCTION__);
 68.2218 +		return 0;
 68.2219 +	}
 68.2220 +
 68.2221 +	start = (const struct unw_table_entry *) punw->p_vaddr;
 68.2222 +	end = (struct unw_table_entry *) ((char *) start + punw->p_memsz);
 68.2223 +	size  = 0;
 68.2224 +
 68.2225 +	unw_add_unwind_table("linux-gate.so", segbase, 0, start, end);
 68.2226 +
 68.2227 +	for (entry = start; entry < end; ++entry)
 68.2228 +		size += 3*8 + 8 + 8*UNW_LENGTH(*(u64 *) (segbase + entry->info_offset));
 68.2229 +	size += 8;	/* reserve space for "end of table" marker */
 68.2230 +
 68.2231 +	unw.gate_table = kmalloc(size, GFP_KERNEL);
 68.2232 +	if (!unw.gate_table) {
 68.2233 +		unw.gate_table_size = 0;
 68.2234 +		printk(KERN_ERR "%s: unable to create unwind data for gate page!\n", __FUNCTION__);
 68.2235 +		return 0;
 68.2236 +	}
 68.2237 +	unw.gate_table_size = size;
 68.2238 +
 68.2239 +	lp = unw.gate_table;
 68.2240 +	info = (char *) unw.gate_table + size;
 68.2241 +
 68.2242 +	for (entry = start; entry < end; ++entry, lp += 3) {
 68.2243 +		info_size = 8 + 8*UNW_LENGTH(*(u64 *) (segbase + entry->info_offset));
 68.2244 +		info -= info_size;
 68.2245 +		memcpy(info, (char *) segbase + entry->info_offset, info_size);
 68.2246 +
 68.2247 +		lp[0] = segbase + entry->start_offset;		/* start */
 68.2248 +		lp[1] = segbase + entry->end_offset;		/* end */
 68.2249 +		lp[2] = info - (char *) unw.gate_table;		/* info */
 68.2250 +	}
 68.2251 +	*lp = 0;	/* end-of-table marker */
 68.2252 +	return 0;
 68.2253 +}
 68.2254 +
 68.2255 +__initcall(create_gate_table);
 68.2256 +#endif // !XEN
 68.2257 +
 68.2258 +void __init
 68.2259 +unw_init (void)
 68.2260 +{
 68.2261 +	extern char __gp[];
 68.2262 +	extern void unw_hash_index_t_is_too_narrow (void);
 68.2263 +	long i, off;
 68.2264 +
 68.2265 +	if (8*sizeof(unw_hash_index_t) < UNW_LOG_HASH_SIZE)
 68.2266 +		unw_hash_index_t_is_too_narrow();
 68.2267 +
 68.2268 +	unw.sw_off[unw.preg_index[UNW_REG_PRI_UNAT_GR]] = SW(CALLER_UNAT);
 68.2269 +	unw.sw_off[unw.preg_index[UNW_REG_BSPSTORE]] = SW(AR_BSPSTORE);
 68.2270 +	unw.sw_off[unw.preg_index[UNW_REG_PFS]] = SW(AR_PFS);
 68.2271 +	unw.sw_off[unw.preg_index[UNW_REG_RP]] = SW(B0);
 68.2272 +	unw.sw_off[unw.preg_index[UNW_REG_UNAT]] = SW(CALLER_UNAT);
 68.2273 +	unw.sw_off[unw.preg_index[UNW_REG_PR]] = SW(PR);
 68.2274 +	unw.sw_off[unw.preg_index[UNW_REG_LC]] = SW(AR_LC);
 68.2275 +	unw.sw_off[unw.preg_index[UNW_REG_FPSR]] = SW(AR_FPSR);
 68.2276 +	for (i = UNW_REG_R4, off = SW(R4); i <= UNW_REG_R7; ++i, off += 8)
 68.2277 +		unw.sw_off[unw.preg_index[i]] = off;
 68.2278 +	for (i = UNW_REG_B1, off = SW(B1); i <= UNW_REG_B5; ++i, off += 8)
 68.2279 +		unw.sw_off[unw.preg_index[i]] = off;
 68.2280 +	for (i = UNW_REG_F2, off = SW(F2); i <= UNW_REG_F5; ++i, off += 16)
 68.2281 +		unw.sw_off[unw.preg_index[i]] = off;
 68.2282 +	for (i = UNW_REG_F16, off = SW(F16); i <= UNW_REG_F31; ++i, off += 16)
 68.2283 +		unw.sw_off[unw.preg_index[i]] = off;
 68.2284 +
 68.2285 +	for (i = 0; i < UNW_CACHE_SIZE; ++i) {
 68.2286 +		if (i > 0)
 68.2287 +			unw.cache[i].lru_chain = (i - 1);
 68.2288 +		unw.cache[i].coll_chain = -1;
 68.2289 +		rwlock_init(&unw.cache[i].lock);
 68.2290 +	}
 68.2291 +	unw.lru_head = UNW_CACHE_SIZE - 1;
 68.2292 +	unw.lru_tail = 0;
 68.2293 +
 68.2294 +	init_unwind_table(&unw.kernel_table, "kernel", KERNEL_START, (unsigned long) __gp,
 68.2295 +			  __start_unwind, __end_unwind);
 68.2296 +}
 68.2297 +
 68.2298 +/*
 68.2299 + * DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED
 68.2300 + *
 68.2301 + *	This system call has been deprecated.  The new and improved way to get
 68.2302 + *	at the kernel's unwind info is via the gate DSO.  The address of the
 68.2303 + *	ELF header for this DSO is passed to user-level via AT_SYSINFO_EHDR.
 68.2304 + *
 68.2305 + * DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED
 68.2306 + *
 68.2307 + * This system call copies the unwind data into the buffer pointed to by BUF and returns
 68.2308 + * the size of the unwind data.  If BUF_SIZE is smaller than the size of the unwind data
 68.2309 + * or if BUF is NULL, nothing is copied, but the system call still returns the size of the
 68.2310 + * unwind data.
 68.2311 + *
 68.2312 + * The first portion of the unwind data contains an unwind table and rest contains the
 68.2313 + * associated unwind info (in no particular order).  The unwind table consists of a table
 68.2314 + * of entries of the form:
 68.2315 + *
 68.2316 + *	u64 start;	(64-bit address of start of function)
 68.2317 + *	u64 end;	(64-bit address of start of function)
 68.2318 + *	u64 info;	(BUF-relative offset to unwind info)
 68.2319 + *
 68.2320 + * The end of the unwind table is indicated by an entry with a START address of zero.
 68.2321 + *
 68.2322 + * Please see the IA-64 Software Conventions and Runtime Architecture manual for details
 68.2323 + * on the format of the unwind info.
 68.2324 + *
 68.2325 + * ERRORS
 68.2326 + *	EFAULT	BUF points outside your accessible address space.
 68.2327 + */
 68.2328 +asmlinkage long
 68.2329 +sys_getunwind (void __user *buf, size_t buf_size)
 68.2330 +{
 68.2331 +	if (buf && buf_size >= unw.gate_table_size)
 68.2332 +		if (copy_to_user(buf, unw.gate_table, unw.gate_table_size) != 0)
 68.2333 +			return -EFAULT;
 68.2334 +	return unw.gate_table_size;
 68.2335 +}
    69.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    69.2 +++ b/xen/arch/ia64/linux-xen/unwind_decoder.c	Mon Jan 09 11:22:17 2006 +0000
    69.3 @@ -0,0 +1,459 @@
    69.4 +/*
    69.5 + * Copyright (C) 2000 Hewlett-Packard Co
    69.6 + * Copyright (C) 2000 David Mosberger-Tang <davidm@hpl.hp.com>
    69.7 + *
    69.8 + * Generic IA-64 unwind info decoder.
    69.9 + *
   69.10 + * This file is used both by the Linux kernel and objdump.  Please keep
   69.11 + * the two copies of this file in sync.
   69.12 + *
   69.13 + * You need to customize the decoder by defining the following
   69.14 + * macros/constants before including this file:
   69.15 + *
   69.16 + *  Types:
   69.17 + *	unw_word	Unsigned integer type with at least 64 bits 
   69.18 + *
   69.19 + *  Register names:
   69.20 + *	UNW_REG_BSP
   69.21 + *	UNW_REG_BSPSTORE
   69.22 + *	UNW_REG_FPSR
   69.23 + *	UNW_REG_LC
   69.24 + *	UNW_REG_PFS
   69.25 + *	UNW_REG_PR
   69.26 + *	UNW_REG_RNAT
   69.27 + *	UNW_REG_PSP
   69.28 + *	UNW_REG_RP
   69.29 + *	UNW_REG_UNAT
   69.30 + *
   69.31 + *  Decoder action macros:
   69.32 + *	UNW_DEC_BAD_CODE(code)
   69.33 + *	UNW_DEC_ABI(fmt,abi,context,arg)
   69.34 + *	UNW_DEC_BR_GR(fmt,brmask,gr,arg)
   69.35 + *	UNW_DEC_BR_MEM(fmt,brmask,arg)
   69.36 + *	UNW_DEC_COPY_STATE(fmt,label,arg)
   69.37 + *	UNW_DEC_EPILOGUE(fmt,t,ecount,arg)
   69.38 + *	UNW_DEC_FRGR_MEM(fmt,grmask,frmask,arg)
   69.39 + *	UNW_DEC_FR_MEM(fmt,frmask,arg)
   69.40 + *	UNW_DEC_GR_GR(fmt,grmask,gr,arg)
   69.41 + *	UNW_DEC_GR_MEM(fmt,grmask,arg)
   69.42 + *	UNW_DEC_LABEL_STATE(fmt,label,arg)
   69.43 + *	UNW_DEC_MEM_STACK_F(fmt,t,size,arg)
   69.44 + *	UNW_DEC_MEM_STACK_V(fmt,t,arg)
   69.45 + *	UNW_DEC_PRIUNAT_GR(fmt,r,arg)
   69.46 + *	UNW_DEC_PRIUNAT_WHEN_GR(fmt,t,arg)
   69.47 + *	UNW_DEC_PRIUNAT_WHEN_MEM(fmt,t,arg)
   69.48 + *	UNW_DEC_PRIUNAT_WHEN_PSPREL(fmt,pspoff,arg)
   69.49 + *	UNW_DEC_PRIUNAT_WHEN_SPREL(fmt,spoff,arg)
   69.50 + *	UNW_DEC_PROLOGUE(fmt,body,rlen,arg)
   69.51 + *	UNW_DEC_PROLOGUE_GR(fmt,rlen,mask,grsave,arg)
   69.52 + *	UNW_DEC_REG_PSPREL(fmt,reg,pspoff,arg)
   69.53 + *	UNW_DEC_REG_REG(fmt,src,dst,arg)
   69.54 + *	UNW_DEC_REG_SPREL(fmt,reg,spoff,arg)
   69.55 + *	UNW_DEC_REG_WHEN(fmt,reg,t,arg)
   69.56 + *	UNW_DEC_RESTORE(fmt,t,abreg,arg)
   69.57 + *	UNW_DEC_RESTORE_P(fmt,qp,t,abreg,arg)
   69.58 + *	UNW_DEC_SPILL_BASE(fmt,pspoff,arg)
   69.59 + *	UNW_DEC_SPILL_MASK(fmt,imaskp,arg)
   69.60 + *	UNW_DEC_SPILL_PSPREL(fmt,t,abreg,pspoff,arg)
   69.61 + *	UNW_DEC_SPILL_PSPREL_P(fmt,qp,t,abreg,pspoff,arg)
   69.62 + *	UNW_DEC_SPILL_REG(fmt,t,abreg,x,ytreg,arg)
   69.63 + *	UNW_DEC_SPILL_REG_P(fmt,qp,t,abreg,x,ytreg,arg)
   69.64 + *	UNW_DEC_SPILL_SPREL(fmt,t,abreg,spoff,arg)
   69.65 + *	UNW_DEC_SPILL_SPREL_P(fmt,qp,t,abreg,pspoff,arg)
   69.66 + */
   69.67 +
   69.68 +static unw_word
   69.69 +unw_decode_uleb128 (unsigned char **dpp)
   69.70 +{
   69.71 +  unsigned shift = 0;
   69.72 +  unw_word byte, result = 0;
   69.73 +  unsigned char *bp = *dpp;
   69.74 +
   69.75 +  while (1)
   69.76 +    {
   69.77 +      byte = *bp++;
   69.78 +      result |= (byte & 0x7f) << shift;
   69.79 +      if ((byte & 0x80) == 0)
   69.80 +	break;
   69.81 +      shift += 7;
   69.82 +    }
   69.83 +  *dpp = bp;
   69.84 +  return result;
   69.85 +}
   69.86 +
   69.87 +static unsigned char *
   69.88 +unw_decode_x1 (unsigned char *dp, unsigned char code, void *arg)
   69.89 +{
   69.90 +  unsigned char byte1, abreg;
   69.91 +  unw_word t, off;
   69.92 +
   69.93 +  byte1 = *dp++;
   69.94 +  t = unw_decode_uleb128 (&dp);
   69.95 +  off = unw_decode_uleb128 (&dp);
   69.96 +  abreg = (byte1 & 0x7f);
   69.97 +  if (byte1 & 0x80)
   69.98 +	  UNW_DEC_SPILL_SPREL(X1, t, abreg, off, arg);
   69.99 +  else
  69.100 +	  UNW_DEC_SPILL_PSPREL(X1, t, abreg, off, arg);
  69.101 +  return dp;
  69.102 +}
  69.103 +
  69.104 +static unsigned char *
  69.105 +unw_decode_x2 (unsigned char *dp, unsigned char code, void *arg)
  69.106 +{
  69.107 +  unsigned char byte1, byte2, abreg, x, ytreg;
  69.108 +  unw_word t;
  69.109 +
  69.110 +  byte1 = *dp++; byte2 = *dp++;
  69.111 +  t = unw_decode_uleb128 (&dp);
  69.112 +  abreg = (byte1 & 0x7f);
  69.113 +  ytreg = byte2;
  69.114 +  x = (byte1 >> 7) & 1;
  69.115 +  if ((byte1 & 0x80) == 0 && ytreg == 0)
  69.116 +    UNW_DEC_RESTORE(X2, t, abreg, arg);
  69.117 +  else
  69.118 +    UNW_DEC_SPILL_REG(X2, t, abreg, x, ytreg, arg);
  69.119 +  return dp;
  69.120 +}
  69.121 +
  69.122 +static unsigned char *
  69.123 +unw_decode_x3 (unsigned char *dp, unsigned char code, void *arg)
  69.124 +{
  69.125 +  unsigned char byte1, byte2, abreg, qp;
  69.126 +  unw_word t, off;
  69.127 +
  69.128 +  byte1 = *dp++; byte2 = *dp++;
  69.129 +  t = unw_decode_uleb128 (&dp);
  69.130 +  off = unw_decode_uleb128 (&dp);
  69.131 +
  69.132 +  qp = (byte1 & 0x3f);
  69.133 +  abreg = (byte2 & 0x7f);
  69.134 +
  69.135 +  if (byte1 & 0x80)
  69.136 +    UNW_DEC_SPILL_SPREL_P(X3, qp, t, abreg, off, arg);
  69.137 +  else
  69.138 +    UNW_DEC_SPILL_PSPREL_P(X3, qp, t, abreg, off, arg);
  69.139 +  return dp;
  69.140 +}
  69.141 +
  69.142 +static unsigned char *
  69.143 +unw_decode_x4 (unsigned char *dp, unsigned char code, void *arg)
  69.144 +{
  69.145 +  unsigned char byte1, byte2, byte3, qp, abreg, x, ytreg;
  69.146 +  unw_word t;
  69.147 +
  69.148 +  byte1 = *dp++; byte2 = *dp++; byte3 = *dp++;
  69.149 +  t = unw_decode_uleb128 (&dp);
  69.150 +
  69.151 +  qp = (byte1 & 0x3f);
  69.152 +  abreg = (byte2 & 0x7f);
  69.153 +  x = (byte2 >> 7) & 1;
  69.154 +  ytreg = byte3;
  69.155 +
  69.156 +  if ((byte2 & 0x80) == 0 && byte3 == 0)
  69.157 +    UNW_DEC_RESTORE_P(X4, qp, t, abreg, arg);
  69.158 +  else
  69.159 +    UNW_DEC_SPILL_REG_P(X4, qp, t, abreg, x, ytreg, arg);
  69.160 +  return dp;
  69.161 +}
  69.162 +
  69.163 +static unsigned char *
  69.164 +unw_decode_r1 (unsigned char *dp, unsigned char code, void *arg)
  69.165 +{
  69.166 +  int body = (code & 0x20) != 0;
  69.167 +  unw_word rlen;
  69.168 +
  69.169 +  rlen = (code & 0x1f);
  69.170 +  UNW_DEC_PROLOGUE(R1, body, rlen, arg);
  69.171 +  return dp;
  69.172 +}
  69.173 +
  69.174 +static unsigned char *
  69.175 +unw_decode_r2 (unsigned char *dp, unsigned char code, void *arg)
  69.176 +{
  69.177 +  unsigned char byte1, mask, grsave;
  69.178 +  unw_word rlen;
  69.179 +
  69.180 +  byte1 = *dp++;
  69.181 +
  69.182 +  mask = ((code & 0x7) << 1) | ((byte1 >> 7) & 1);
  69.183 +  grsave = (byte1 & 0x7f);
  69.184 +  rlen = unw_decode_uleb128 (&dp);
  69.185 +  UNW_DEC_PROLOGUE_GR(R2, rlen, mask, grsave, arg);
  69.186 +  return dp;
  69.187 +}
  69.188 +
  69.189 +static unsigned char *
  69.190 +unw_decode_r3 (unsigned char *dp, unsigned char code, void *arg)
  69.191 +{
  69.192 +  unw_word rlen;
  69.193 +
  69.194 +  rlen = unw_decode_uleb128 (&dp);
  69.195 +  UNW_DEC_PROLOGUE(R3, ((code & 0x3) == 1), rlen, arg);
  69.196 +  return dp;
  69.197 +}
  69.198 +
  69.199 +static unsigned char *
  69.200 +unw_decode_p1 (unsigned char *dp, unsigned char code, void *arg)
  69.201 +{
  69.202 +  unsigned char brmask = (code & 0x1f);
  69.203 +
  69.204 +  UNW_DEC_BR_MEM(P1, brmask, arg);
  69.205 +  return dp;
  69.206 +}
  69.207 +
  69.208 +static unsigned char *
  69.209 +unw_decode_p2_p5 (unsigned char *dp, unsigned char code, void *arg)
  69.210 +{
  69.211 +  if ((code & 0x10) == 0)
  69.212 +    {
  69.213 +      unsigned char byte1 = *dp++;
  69.214 +
  69.215 +      UNW_DEC_BR_GR(P2, ((code & 0xf) << 1) | ((byte1 >> 7) & 1),
  69.216 +		    (byte1 & 0x7f), arg);
  69.217 +    }
  69.218 +  else if ((code & 0x08) == 0)
  69.219 +    {
  69.220 +      unsigned char byte1 = *dp++, r, dst;
  69.221 +
  69.222 +      r = ((code & 0x7) << 1) | ((byte1 >> 7) & 1);
  69.223 +      dst = (byte1 & 0x7f);
  69.224 +      switch (r)
  69.225 +	{
  69.226 +	case 0: UNW_DEC_REG_GR(P3, UNW_REG_PSP, dst, arg); break;
  69.227 +	case 1: UNW_DEC_REG_GR(P3, UNW_REG_RP, dst, arg); break;
  69.228 +	case 2: UNW_DEC_REG_GR(P3, UNW_REG_PFS, dst, arg); break;
  69.229 +	case 3: UNW_DEC_REG_GR(P3, UNW_REG_PR, dst, arg); break;
  69.230 +	case 4: UNW_DEC_REG_GR(P3, UNW_REG_UNAT, dst, arg); break;
  69.231 +	case 5: UNW_DEC_REG_GR(P3, UNW_REG_LC, dst, arg); break;
  69.232 +	case 6: UNW_DEC_RP_BR(P3, dst, arg); break;
  69.233 +	case 7: UNW_DEC_REG_GR(P3, UNW_REG_RNAT, dst, arg); break;
  69.234 +	case 8: UNW_DEC_REG_GR(P3, UNW_REG_BSP, dst, arg); break;
  69.235 +	case 9: UNW_DEC_REG_GR(P3, UNW_REG_BSPSTORE, dst, arg); break;
  69.236 +	case 10: UNW_DEC_REG_GR(P3, UNW_REG_FPSR, dst, arg); break;
  69.237 +	case 11: UNW_DEC_PRIUNAT_GR(P3, dst, arg); break;
  69.238 +	default: UNW_DEC_BAD_CODE(r); break;
  69.239 +	}
  69.240 +    }
  69.241 +  else if ((code & 0x7) == 0)
  69.242 +    UNW_DEC_SPILL_MASK(P4, dp, arg);
  69.243 +  else if ((code & 0x7) == 1)
  69.244 +    {
  69.245 +      unw_word grmask, frmask, byte1, byte2, byte3;
  69.246 +
  69.247 +      byte1 = *dp++; byte2 = *dp++; byte3 = *dp++;
  69.248 +      grmask = ((byte1 >> 4) & 0xf);
  69.249 +      frmask = ((byte1 & 0xf) << 16) | (byte2 << 8) | byte3;
  69.250 +      UNW_DEC_FRGR_MEM(P5, grmask, frmask, arg);
  69.251 +    }
  69.252 +  else
  69.253 +    UNW_DEC_BAD_CODE(code);
  69.254 +  return dp;
  69.255 +}
  69.256 +
  69.257 +static unsigned char *
  69.258 +unw_decode_p6 (unsigned char *dp, unsigned char code, void *arg)
  69.259 +{
  69.260 +  int gregs = (code & 0x10) != 0;
  69.261 +  unsigned char mask = (code & 0x0f);
  69.262 +
  69.263 +  if (gregs)
  69.264 +    UNW_DEC_GR_MEM(P6, mask, arg);
  69.265 +  else
  69.266 +    UNW_DEC_FR_MEM(P6, mask, arg);
  69.267 +  return dp;
  69.268 +}
  69.269 +
  69.270 +static unsigned char *
  69.271 +unw_decode_p7_p10 (unsigned char *dp, unsigned char code, void *arg)
  69.272 +{
  69.273 +  unsigned char r, byte1, byte2;
  69.274 +  unw_word t, size;
  69.275 +
  69.276 +  if ((code & 0x10) == 0)
  69.277 +    {
  69.278 +      r = (code & 0xf);
  69.279 +      t = unw_decode_uleb128 (&dp);
  69.280 +      switch (r)
  69.281 +	{
  69.282 +	case 0:
  69.283 +	  size = unw_decode_uleb128 (&dp);
  69.284 +	  UNW_DEC_MEM_STACK_F(P7, t, size, arg);
  69.285 +	  break;
  69.286 +
  69.287 +	case 1: UNW_DEC_MEM_STACK_V(P7, t, arg); break;
  69.288 +	case 2: UNW_DEC_SPILL_BASE(P7, t, arg); break;
  69.289 +	case 3: UNW_DEC_REG_SPREL(P7, UNW_REG_PSP, t, arg); break;
  69.290 +	case 4: UNW_DEC_REG_WHEN(P7, UNW_REG_RP, t, arg); break;
  69.291 +	case 5: UNW_DEC_REG_PSPREL(P7, UNW_REG_RP, t, arg); break;
  69.292 +	case 6: UNW_DEC_REG_WHEN(P7, UNW_REG_PFS, t, arg); break;
  69.293 +	case 7: UNW_DEC_REG_PSPREL(P7, UNW_REG_PFS, t, arg); break;
  69.294 +	case 8: UNW_DEC_REG_WHEN(P7, UNW_REG_PR, t, arg); break;
  69.295 +	case 9: UNW_DEC_REG_PSPREL(P7, UNW_REG_PR, t, arg); break;
  69.296 +	case 10: UNW_DEC_REG_WHEN(P7, UNW_REG_LC, t, arg); break;
  69.297 +	case 11: UNW_DEC_REG_PSPREL(P7, UNW_REG_LC, t, arg); break;
  69.298 +	case 12: UNW_DEC_REG_WHEN(P7, UNW_REG_UNAT, t, arg); break;
  69.299 +	case 13: UNW_DEC_REG_PSPREL(P7, UNW_REG_UNAT, t, arg); break;
  69.300 +	case 14: UNW_DEC_REG_WHEN(P7, UNW_REG_FPSR, t, arg); break;
  69.301 +	case 15: UNW_DEC_REG_PSPREL(P7, UNW_REG_FPSR, t, arg); break;
  69.302 +	default: UNW_DEC_BAD_CODE(r); break;
  69.303 +	}
  69.304 +    }
  69.305 +  else
  69.306 +    {
  69.307 +      switch (code & 0xf)
  69.308 +	{
  69.309 +	case 0x0: /* p8 */
  69.310 +	  {
  69.311 +	    r = *dp++;
  69.312 +	    t = unw_decode_uleb128 (&dp);
  69.313 +	    switch (r)
  69.314 +	      {
  69.315 +	      case  1: UNW_DEC_REG_SPREL(P8, UNW_REG_RP, t, arg); break;
  69.316 +	      case  2: UNW_DEC_REG_SPREL(P8, UNW_REG_PFS, t, arg); break;
  69.317 +	      case  3: UNW_DEC_REG_SPREL(P8, UNW_REG_PR, t, arg); break;
  69.318 +	      case  4: UNW_DEC_REG_SPREL(P8, UNW_REG_LC, t, arg); break;
  69.319 +	      case  5: UNW_DEC_REG_SPREL(P8, UNW_REG_UNAT, t, arg); break;
  69.320 +	      case  6: UNW_DEC_REG_SPREL(P8, UNW_REG_FPSR, t, arg); break;
  69.321 +	      case  7: UNW_DEC_REG_WHEN(P8, UNW_REG_BSP, t, arg); break;
  69.322 +	      case  8: UNW_DEC_REG_PSPREL(P8, UNW_REG_BSP, t, arg); break;
  69.323 +	      case  9: UNW_DEC_REG_SPREL(P8, UNW_REG_BSP, t, arg); break;
  69.324 +	      case 10: UNW_DEC_REG_WHEN(P8, UNW_REG_BSPSTORE, t, arg); break;
  69.325 +	      case 11: UNW_DEC_REG_PSPREL(P8, UNW_REG_BSPSTORE, t, arg); break;
  69.326 +	      case 12: UNW_DEC_REG_SPREL(P8, UNW_REG_BSPSTORE, t, arg); break;
  69.327 +	      case 13: UNW_DEC_REG_WHEN(P8, UNW_REG_RNAT, t, arg); break;
  69.328 +	      case 14: UNW_DEC_REG_PSPREL(P8, UNW_REG_RNAT, t, arg); break;
  69.329 +	      case 15: UNW_DEC_REG_SPREL(P8, UNW_REG_RNAT, t, arg); break;
  69.330 +	      case 16: UNW_DEC_PRIUNAT_WHEN_GR(P8, t, arg); break;
  69.331 +	      case 17: UNW_DEC_PRIUNAT_PSPREL(P8, t, arg); break;
  69.332 +	      case 18: UNW_DEC_PRIUNAT_SPREL(P8, t, arg); break;
  69.333 +	      case 19: UNW_DEC_PRIUNAT_WHEN_MEM(P8, t, arg); break;
  69.334 +	      default: UNW_DEC_BAD_CODE(r); break;
  69.335 +	    }
  69.336 +	  }
  69.337 +	  break;
  69.338 +
  69.339 +	case 0x1:
  69.340 +	  byte1 = *dp++; byte2 = *dp++;
  69.341 +	  UNW_DEC_GR_GR(P9, (byte1 & 0xf), (byte2 & 0x7f), arg);
  69.342 +	  break;
  69.343 +
  69.344 +	case 0xf: /* p10 */
  69.345 +	  byte1 = *dp++; byte2 = *dp++;
  69.346 +	  UNW_DEC_ABI(P10, byte1, byte2, arg);
  69.347 +	  break;
  69.348 +
  69.349 +	case 0x9:
  69.350 +	  return unw_decode_x1 (dp, code, arg);
  69.351 +
  69.352 +	case 0xa:
  69.353 +	  return unw_decode_x2 (dp, code, arg);
  69.354 +
  69.355 +	case 0xb:
  69.356 +	  return unw_decode_x3 (dp, code, arg);
  69.357 +
  69.358 +	case 0xc:
  69.359 +	  return unw_decode_x4 (dp, code, arg);
  69.360 +
  69.361 +	default:
  69.362 +	  UNW_DEC_BAD_CODE(code);
  69.363 +	  break;
  69.364 +	}
  69.365 +    }
  69.366 +  return dp;
  69.367 +}
  69.368 +
  69.369 +static unsigned char *
  69.370 +unw_decode_b1 (unsigned char *dp, unsigned char code, void *arg)
  69.371 +{
  69.372 +  unw_word label = (code & 0x1f);
  69.373 +
  69.374 +  if ((code & 0x20) != 0)
  69.375 +    UNW_DEC_COPY_STATE(B1, label, arg);
  69.376 +  else
  69.377 +    UNW_DEC_LABEL_STATE(B1, label, arg);
  69.378 +  return dp;
  69.379 +}
  69.380 +
  69.381 +static unsigned char *
  69.382 +unw_decode_b2 (unsigned char *dp, unsigned char code, void *arg)
  69.383 +{
  69.384 +  unw_word t;
  69.385 +
  69.386 +  t = unw_decode_uleb128 (&dp);
  69.387 +  UNW_DEC_EPILOGUE(B2, t, (code & 0x1f), arg);
  69.388 +  return dp;
  69.389 +}
  69.390 +
  69.391 +static unsigned char *
  69.392 +unw_decode_b3_x4 (unsigned char *dp, unsigned char code, void *arg)
  69.393 +{
  69.394 +  unw_word t, ecount, label;
  69.395 +
  69.396 +  if ((code & 0x10) == 0)
  69.397 +    {
  69.398 +      t = unw_decode_uleb128 (&dp);
  69.399 +      ecount = unw_decode_uleb128 (&dp);
  69.400 +      UNW_DEC_EPILOGUE(B3, t, ecount, arg);
  69.401 +    }
  69.402 +  else if ((code & 0x07) == 0)
  69.403 +    {
  69.404 +      label = unw_decode_uleb128 (&dp);
  69.405 +      if ((code & 0x08) != 0)
  69.406 +	UNW_DEC_COPY_STATE(B4, label, arg);
  69.407 +      else
  69.408 +	UNW_DEC_LABEL_STATE(B4, label, arg);
  69.409 +    }
  69.410 +  else
  69.411 +    switch (code & 0x7)
  69.412 +      {
  69.413 +      case 1: return unw_decode_x1 (dp, code, arg);
  69.414 +      case 2: return unw_decode_x2 (dp, code, arg);
  69.415 +      case 3: return unw_decode_x3 (dp, code, arg);
  69.416 +      case 4: return unw_decode_x4 (dp, code, arg);
  69.417 +      default: UNW_DEC_BAD_CODE(code); break;
  69.418 +      }
  69.419 +  return dp;
  69.420 +}
  69.421 +
  69.422 +typedef unsigned char *(*unw_decoder) (unsigned char *, unsigned char, void *);
  69.423 +
  69.424 +static unw_decoder unw_decode_table[2][8] =
  69.425 +{
  69.426 +  /* prologue table: */
  69.427 +  {
  69.428 +    unw_decode_r1,	/* 0 */
  69.429 +    unw_decode_r1,
  69.430 +    unw_decode_r2,
  69.431 +    unw_decode_r3,
  69.432 +    unw_decode_p1,	/* 4 */
  69.433 +    unw_decode_p2_p5,
  69.434 +    unw_decode_p6,
  69.435 +    unw_decode_p7_p10
  69.436 +  },
  69.437 +  {
  69.438 +    unw_decode_r1,	/* 0 */
  69.439 +    unw_decode_r1,
  69.440 +    unw_decode_r2,
  69.441 +    unw_decode_r3,
  69.442 +    unw_decode_b1,	/* 4 */
  69.443 +    unw_decode_b1,
  69.444 +    unw_decode_b2,
  69.445 +    unw_decode_b3_x4
  69.446 +  }
  69.447 +};
  69.448 +
  69.449 +/*
  69.450 + * Decode one descriptor and return address of next descriptor.
  69.451 + */
  69.452 +static inline unsigned char *
  69.453 +unw_decode (unsigned char *dp, int inside_body, void *arg)
  69.454 +{
  69.455 +  unw_decoder decoder;
  69.456 +  unsigned char code;
  69.457 +
  69.458 +  code = *dp++;
  69.459 +  decoder = unw_decode_table[inside_body][code >> 5];
  69.460 +  dp = (*decoder) (dp, code, arg);
  69.461 +  return dp;
  69.462 +}
    70.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    70.2 +++ b/xen/arch/ia64/linux-xen/unwind_i.h	Mon Jan 09 11:22:17 2006 +0000
    70.3 @@ -0,0 +1,164 @@
    70.4 +/*
    70.5 + * Copyright (C) 2000, 2002-2003 Hewlett-Packard Co
    70.6 + *	David Mosberger-Tang <davidm@hpl.hp.com>
    70.7 + *
    70.8 + * Kernel unwind support.
    70.9 + */
   70.10 +
   70.11 +#define UNW_VER(x)		((x) >> 48)
   70.12 +#define UNW_FLAG_MASK		0x0000ffff00000000
   70.13 +#define UNW_FLAG_OSMASK		0x0000f00000000000
   70.14 +#define UNW_FLAG_EHANDLER(x)	((x) & 0x0000000100000000L)
   70.15 +#define UNW_FLAG_UHANDLER(x)	((x) & 0x0000000200000000L)
   70.16 +#define UNW_LENGTH(x)		((x) & 0x00000000ffffffffL)
   70.17 +
   70.18 +enum unw_register_index {
   70.19 +	/* primary unat: */
   70.20 +	UNW_REG_PRI_UNAT_GR,
   70.21 +	UNW_REG_PRI_UNAT_MEM,
   70.22 +
   70.23 +	/* register stack */
   70.24 +	UNW_REG_BSP,					/* register stack pointer */
   70.25 +	UNW_REG_BSPSTORE,
   70.26 +	UNW_REG_PFS,					/* previous function state */
   70.27 +	UNW_REG_RNAT,
   70.28 +	/* memory stack */
   70.29 +	UNW_REG_PSP,					/* previous memory stack pointer */
   70.30 +	/* return pointer: */
   70.31 +	UNW_REG_RP,
   70.32 +
   70.33 +	/* preserved registers: */
   70.34 +	UNW_REG_R4, UNW_REG_R5, UNW_REG_R6, UNW_REG_R7,
   70.35 +	UNW_REG_UNAT, UNW_REG_PR, UNW_REG_LC, UNW_REG_FPSR,
   70.36 +	UNW_REG_B1, UNW_REG_B2, UNW_REG_B3, UNW_REG_B4, UNW_REG_B5,
   70.37 +	UNW_REG_F2, UNW_REG_F3, UNW_REG_F4, UNW_REG_F5,
   70.38 +	UNW_REG_F16, UNW_REG_F17, UNW_REG_F18, UNW_REG_F19,
   70.39 +	UNW_REG_F20, UNW_REG_F21, UNW_REG_F22, UNW_REG_F23,
   70.40 +	UNW_REG_F24, UNW_REG_F25, UNW_REG_F26, UNW_REG_F27,
   70.41 +	UNW_REG_F28, UNW_REG_F29, UNW_REG_F30, UNW_REG_F31,
   70.42 +	UNW_NUM_REGS
   70.43 +};
   70.44 +
   70.45 +struct unw_info_block {
   70.46 +	u64 header;
   70.47 +	u64 desc[0];		/* unwind descriptors */
   70.48 +	/* personality routine and language-specific data follow behind descriptors */
   70.49 +};
   70.50 +
   70.51 +struct unw_table {
   70.52 +	struct unw_table *next;		/* must be first member! */
   70.53 +	const char *name;
   70.54 +	unsigned long gp;		/* global pointer for this load-module */
   70.55 +	unsigned long segment_base;	/* base for offsets in the unwind table entries */
   70.56 +	unsigned long start;
   70.57 +	unsigned long end;
   70.58 +	const struct unw_table_entry *array;
   70.59 +	unsigned long length;
   70.60 +};
   70.61 +
   70.62 +enum unw_where {
   70.63 +	UNW_WHERE_NONE,			/* register isn't saved at all */
   70.64 +	UNW_WHERE_GR,			/* register is saved in a general register */
   70.65 +	UNW_WHERE_FR,			/* register is saved in a floating-point register */
   70.66 +	UNW_WHERE_BR,			/* register is saved in a branch register */
   70.67 +	UNW_WHERE_SPREL,		/* register is saved on memstack (sp-relative) */
   70.68 +	UNW_WHERE_PSPREL,		/* register is saved on memstack (psp-relative) */
   70.69 +	/*
   70.70 +	 * At the end of each prologue these locations get resolved to
   70.71 +	 * UNW_WHERE_PSPREL and UNW_WHERE_GR, respectively:
   70.72 +	 */
   70.73 +	UNW_WHERE_SPILL_HOME,		/* register is saved in its spill home */
   70.74 +	UNW_WHERE_GR_SAVE		/* register is saved in next general register */
   70.75 +};
   70.76 +
   70.77 +#define UNW_WHEN_NEVER	0x7fffffff
   70.78 +
   70.79 +struct unw_reg_info {
   70.80 +	unsigned long val;		/* save location: register number or offset */
   70.81 +	enum unw_where where;		/* where the register gets saved */
   70.82 +	int when;			/* when the register gets saved */
   70.83 +};
   70.84 +
   70.85 +struct unw_reg_state {
   70.86 +	struct unw_reg_state *next;		/* next (outer) element on state stack */
   70.87 +	struct unw_reg_info reg[UNW_NUM_REGS];	/* register save locations */
   70.88 +};
   70.89 +
   70.90 +struct unw_labeled_state {
   70.91 +	struct unw_labeled_state *next;		/* next labeled state (or NULL) */
   70.92 +	unsigned long label;			/* label for this state */
   70.93 +	struct unw_reg_state saved_state;
   70.94 +};
   70.95 +
   70.96 +struct unw_state_record {
   70.97 +	unsigned int first_region : 1;	/* is this the first region? */
   70.98 +	unsigned int done : 1;		/* are we done scanning descriptors? */
   70.99 +	unsigned int any_spills : 1;	/* got any register spills? */
  70.100 +	unsigned int in_body : 1;	/* are we inside a body (as opposed to a prologue)? */
  70.101 +	unsigned long flags;		/* see UNW_FLAG_* in unwind.h */
  70.102 +
  70.103 +	u8 *imask;			/* imask of spill_mask record or NULL */
  70.104 +	unsigned long pr_val;		/* predicate values */
  70.105 +	unsigned long pr_mask;		/* predicate mask */
  70.106 +	long spill_offset;		/* psp-relative offset for spill base */
  70.107 +	int region_start;
  70.108 +	int region_len;
  70.109 +	int epilogue_start;
  70.110 +	int epilogue_count;
  70.111 +	int when_target;
  70.112 +
  70.113 +	u8 gr_save_loc;			/* next general register to use for saving a register */
  70.114 +	u8 return_link_reg;		/* branch register in which the return link is passed */
  70.115 +
  70.116 +	struct unw_labeled_state *labeled_states;	/* list of all labeled states */
  70.117 +	struct unw_reg_state curr;	/* current state */
  70.118 +};
  70.119 +
  70.120 +enum unw_nat_type {
  70.121 +	UNW_NAT_NONE,		/* NaT not represented */
  70.122 +	UNW_NAT_VAL,		/* NaT represented by NaT value (fp reg) */
  70.123 +	UNW_NAT_MEMSTK,		/* NaT value is in unat word at offset OFF  */
  70.124 +	UNW_NAT_REGSTK		/* NaT is in rnat */
  70.125 +};
  70.126 +
  70.127 +enum unw_insn_opcode {
  70.128 +	UNW_INSN_ADD,			/* s[dst] += val */
  70.129 +	UNW_INSN_ADD_PSP,		/* s[dst] = (s.psp + val) */
  70.130 +	UNW_INSN_ADD_SP,		/* s[dst] = (s.sp + val) */
  70.131 +	UNW_INSN_MOVE,			/* s[dst] = s[val] */
  70.132 +	UNW_INSN_MOVE2,			/* s[dst] = s[val]; s[dst+1] = s[val+1] */
  70.133 +	UNW_INSN_MOVE_STACKED,		/* s[dst] = ia64_rse_skip(*s.bsp, val) */
  70.134 +	UNW_INSN_SETNAT_MEMSTK,		/* s[dst+1].nat.type = MEMSTK;
  70.135 +					   s[dst+1].nat.off = *s.pri_unat - s[dst] */
  70.136 +	UNW_INSN_SETNAT_TYPE,		/* s[dst+1].nat.type = val */
  70.137 +	UNW_INSN_LOAD,			/* s[dst] = *s[val] */
  70.138 +	UNW_INSN_MOVE_SCRATCH,		/* s[dst] = scratch reg "val" */
  70.139 +	UNW_INSN_MOVE_CONST,            /* s[dst] = constant reg "val" */
  70.140 +};
  70.141 +
  70.142 +struct unw_insn {
  70.143 +	unsigned int opc	:  4;
  70.144 +	unsigned int dst	:  9;
  70.145 +	signed int val		: 19;
  70.146 +};
  70.147 +
  70.148 +/*
  70.149 + * Preserved general static registers (r4-r7) give rise to two script
  70.150 + * instructions; everything else yields at most one instruction; at
  70.151 + * the end of the script, the psp gets popped, accounting for one more
  70.152 + * instruction.
  70.153 + */
  70.154 +#define UNW_MAX_SCRIPT_LEN	(UNW_NUM_REGS + 5)
  70.155 +
  70.156 +struct unw_script {
  70.157 +	unsigned long ip;		/* ip this script is for */
  70.158 +	unsigned long pr_mask;		/* mask of predicates script depends on */
  70.159 +	unsigned long pr_val;		/* predicate values this script is for */
  70.160 +	rwlock_t lock;
  70.161 +	unsigned int flags;		/* see UNW_FLAG_* in unwind.h */
  70.162 +	unsigned short lru_chain;	/* used for least-recently-used chain */
  70.163 +	unsigned short coll_chain;	/* used for hash collisions */
  70.164 +	unsigned short hint;		/* hint for next script to try (or -1) */
  70.165 +	unsigned short count;		/* number of instructions in script */
  70.166 +	struct unw_insn insn[UNW_MAX_SCRIPT_LEN];
  70.167 +};
    71.1 --- a/xen/arch/ia64/vmx/mmio.c	Mon Jan 09 11:19:55 2006 +0000
    71.2 +++ b/xen/arch/ia64/vmx/mmio.c	Mon Jan 09 11:22:17 2006 +0000
    71.3 @@ -29,7 +29,7 @@
    71.4  #include <asm/vmx_vcpu.h>
    71.5  #include <asm/privop.h>
    71.6  #include <asm/types.h>
    71.7 -#include <public/io/ioreq.h>
    71.8 +#include <public/hvm/ioreq.h>
    71.9  #include <asm/mm.h>
   71.10  #include <asm/vmx.h>
   71.11  
    72.1 --- a/xen/arch/ia64/vmx/vlsapic.c	Mon Jan 09 11:19:55 2006 +0000
    72.2 +++ b/xen/arch/ia64/vmx/vlsapic.c	Mon Jan 09 11:22:17 2006 +0000
    72.3 @@ -218,7 +218,7 @@ void vtm_interruption_update(VCPU *vcpu,
    72.4   */
    72.5  void vtm_domain_out(VCPU *vcpu)
    72.6  {
    72.7 -    if(!is_idle_task(vcpu->domain))
    72.8 +    if(!is_idle_domain(vcpu->domain))
    72.9  	rem_ac_timer(&vcpu->arch.arch_vmx.vtm.vtm_timer);
   72.10  }
   72.11  
   72.12 @@ -230,7 +230,7 @@ void vtm_domain_in(VCPU *vcpu)
   72.13  {
   72.14      vtime_t     *vtm;
   72.15  
   72.16 -    if(!is_idle_task(vcpu->domain)) {
   72.17 +    if(!is_idle_domain(vcpu->domain)) {
   72.18  	vtm=&(vcpu->arch.arch_vmx.vtm);
   72.19  	vtm_interruption_update(vcpu, vtm);
   72.20      }
    73.1 --- a/xen/arch/ia64/vmx/vmx_init.c	Mon Jan 09 11:19:55 2006 +0000
    73.2 +++ b/xen/arch/ia64/vmx/vmx_init.c	Mon Jan 09 11:22:17 2006 +0000
    73.3 @@ -42,7 +42,7 @@
    73.4  #include <xen/lib.h>
    73.5  #include <asm/vmmu.h>
    73.6  #include <public/arch-ia64.h>
    73.7 -#include <public/io/ioreq.h>
    73.8 +#include <public/hvm/ioreq.h>
    73.9  #include <asm/vmx_phy_mode.h>
   73.10  #include <asm/processor.h>
   73.11  #include <asm/vmx.h>
    74.1 --- a/xen/arch/ia64/vmx/vmx_process.c	Mon Jan 09 11:19:55 2006 +0000
    74.2 +++ b/xen/arch/ia64/vmx/vmx_process.c	Mon Jan 09 11:22:17 2006 +0000
    74.3 @@ -53,6 +53,7 @@
    74.4  #define INITIAL_PSR_VALUE_AT_INTERRUPTION 0x0000001808028034
    74.5  
    74.6  
    74.7 +extern void die_if_kernel(char *str, struct pt_regs *regs, long err);
    74.8  extern void rnat_consumption (VCPU *vcpu);
    74.9  #define DOMN_PAL_REQUEST    0x110000
   74.10  
   74.11 @@ -185,8 +186,11 @@ vmx_ia64_handle_break (unsigned long ifa
   74.12  	}else if(iim == DOMN_PAL_REQUEST){
   74.13          pal_emul(current);
   74.14  		vmx_vcpu_increment_iip(current);
   74.15 -    }  else
   74.16 +    } else {
   74.17 +		if (iim == 0) 
   74.18 +			die_if_kernel("bug check", regs, iim);
   74.19  		vmx_reflect_interruption(ifa,isr,iim,11,regs);
   74.20 +    }
   74.21  }
   74.22  
   74.23  
   74.24 @@ -227,7 +231,7 @@ void leave_hypervisor_tail(struct pt_reg
   74.25  	struct domain *d = current->domain;
   74.26  	struct vcpu *v = current;
   74.27  	// FIXME: Will this work properly if doing an RFI???
   74.28 -	if (!is_idle_task(d) ) {	// always comes from guest
   74.29 +	if (!is_idle_domain(d) ) {	// always comes from guest
   74.30  	        extern void vmx_dorfirfi(void);
   74.31  		struct pt_regs *user_regs = vcpu_regs(current);
   74.32   		if (local_softirq_pending())
    75.1 --- a/xen/arch/ia64/vmx/vmx_support.c	Mon Jan 09 11:19:55 2006 +0000
    75.2 +++ b/xen/arch/ia64/vmx/vmx_support.c	Mon Jan 09 11:22:17 2006 +0000
    75.3 @@ -21,7 +21,7 @@
    75.4   */
    75.5  #include <xen/config.h>
    75.6  #include <xen/sched.h>
    75.7 -#include <public/io/ioreq.h>
    75.8 +#include <public/hvm/ioreq.h>
    75.9  #include <asm/vmx.h>
   75.10  #include <asm/vmx_vcpu.h>
   75.11  
    76.1 --- a/xen/arch/ia64/xen/dom_fw.c	Mon Jan 09 11:19:55 2006 +0000
    76.2 +++ b/xen/arch/ia64/xen/dom_fw.c	Mon Jan 09 11:22:17 2006 +0000
    76.3 @@ -861,12 +861,16 @@ dom_fw_init (struct domain *d, char *arg
    76.4  	bp->console_info.orig_x = 0;
    76.5  	bp->console_info.orig_y = 24;
    76.6  	bp->fpswa = 0;
    76.7 -        bp->initrd_start = (dom0_start+dom0_size) -
    76.8 -                (PAGE_ALIGN(ia64_boot_param->initrd_size) + 4*1024*1024);
    76.9 -        bp->initrd_size = ia64_boot_param->initrd_size;
   76.10 -                printf(" initrd start %0xlx", bp->initrd_start);
   76.11 -                printf(" initrd size %0xlx", bp->initrd_size);
   76.12 -
   76.13 -
   76.14 +	if (d == dom0) {
   76.15 +		bp->initrd_start = (dom0_start+dom0_size) -
   76.16 +		  (PAGE_ALIGN(ia64_boot_param->initrd_size) + 4*1024*1024);
   76.17 +		bp->initrd_size = ia64_boot_param->initrd_size;
   76.18 +	}
   76.19 +	else {
   76.20 +		bp->initrd_start = d->arch.initrd_start;
   76.21 +		bp->initrd_size  = d->arch.initrd_len;
   76.22 +	}
   76.23 +	printf(" initrd start %0xlx", bp->initrd_start);
   76.24 +	printf(" initrd size %0xlx", bp->initrd_size);
   76.25  	return bp;
   76.26  }
    77.1 --- a/xen/arch/ia64/xen/domain.c	Mon Jan 09 11:19:55 2006 +0000
    77.2 +++ b/xen/arch/ia64/xen/domain.c	Mon Jan 09 11:22:17 2006 +0000
    77.3 @@ -19,6 +19,7 @@
    77.4  #include <xen/delay.h>
    77.5  #include <xen/softirq.h>
    77.6  #include <xen/mm.h>
    77.7 +#include <xen/iocap.h>
    77.8  #include <asm/ptrace.h>
    77.9  #include <asm/system.h>
   77.10  #include <asm/io.h>
   77.11 @@ -45,7 +46,7 @@
   77.12  #include <asm/vmx_vcpu.h>
   77.13  #include <asm/vmx_vpd.h>
   77.14  #include <asm/pal.h>
   77.15 -#include <public/io/ioreq.h>
   77.16 +#include <public/hvm/ioreq.h>
   77.17  
   77.18  #define CONFIG_DOMAIN0_CONTIGUOUS
   77.19  unsigned long dom0_start = -1L;
   77.20 @@ -181,7 +182,7 @@ static void init_switch_stack(struct vcp
   77.21  	memset(v->arch._thread.fph,0,sizeof(struct ia64_fpreg)*96);
   77.22  }
   77.23  
   77.24 -void arch_do_createdomain(struct vcpu *v)
   77.25 +int arch_do_createdomain(struct vcpu *v)
   77.26  {
   77.27  	struct domain *d = v->domain;
   77.28  	struct thread_info *ti = alloc_thread_info(v);
   77.29 @@ -248,7 +249,9 @@ void arch_do_createdomain(struct vcpu *v
   77.30  		}
   77.31  	} else
   77.32   		d->arch.mm = NULL;
   77.33 - 	printf ("arch_do_create_domain: domain=%p\n", d);
   77.34 +	printf ("arch_do_create_domain: domain=%p\n", d);
   77.35 +
   77.36 +	return 0;
   77.37  }
   77.38  
   77.39  void arch_getdomaininfo_ctxt(struct vcpu *v, struct vcpu_guest_context *c)
   77.40 @@ -291,16 +294,7 @@ int arch_set_info_guest(struct vcpu *v, 
   77.41  	d->arch.cmdline      = c->cmdline;
   77.42  	new_thread(v, regs->cr_iip, 0, 0);
   77.43  
   77.44 -#ifdef CONFIG_IA64_SPLIT_CACHE
   77.45 -    /* Sync d/i cache conservatively */
   77.46 -    if (!running_on_sim) {
   77.47 -        ret = ia64_pal_cache_flush(4, 0, &progress, NULL);
   77.48 -        if ((ret!=PAL_STATUS_SUCCESS)&& (ret!=PAL_STATUS_UNIMPLEMENTED))
   77.49 -            printk("PAL CACHE FLUSH failed for dom0.\n");
   77.50 -        else
   77.51 -            printk("Sync i/d cache for guest SUCC\n");
   77.52 -    }
   77.53 -#endif
   77.54 +	sync_split_caches();
   77.55   	v->vcpu_info->arch.evtchn_vector = c->vcpu.evtchn_vector;
   77.56  	if ( c->vcpu.privregs && copy_from_user(v->arch.privregs,
   77.57  			   c->vcpu.privregs, sizeof(mapped_regs_t))) {
   77.58 @@ -428,7 +422,7 @@ extern unsigned long vhpt_paddr, vhpt_pe
   77.59  		{
   77.60  			p = alloc_domheap_page(d);
   77.61  			// zero out pages for security reasons
   77.62 -			memset(__va(page_to_phys(p)),0,PAGE_SIZE);
   77.63 +			if (p) memset(__va(page_to_phys(p)),0,PAGE_SIZE);
   77.64  		}
   77.65  		if (unlikely(!p)) {
   77.66  printf("map_new_domain_page: Can't alloc!!!! Aaaargh!\n");
   77.67 @@ -763,7 +757,10 @@ void alloc_dom0(void)
   77.68   */
   77.69  void physdev_init_dom0(struct domain *d)
   77.70  {
   77.71 -	set_bit(_DOMF_physdev_access, &d->domain_flags);
   77.72 +	if (iomem_permit_access(d, 0UL, ~0UL))
   77.73 +		BUG();
   77.74 +	if (irqs_permit_access(d, 0, NR_PIRQS-1))
   77.75 +		BUG();
   77.76  }
   77.77  
   77.78  unsigned int vmx_dom0 = 0;
   77.79 @@ -912,9 +909,9 @@ int construct_dom0(struct domain *d,
   77.80  	memset(si, 0, PAGE_SIZE);
   77.81  	d->shared_info->arch.start_info_pfn = __pa(si) >> PAGE_SHIFT;
   77.82  	sprintf(si->magic, "xen-%i.%i-ia64", XEN_VERSION, XEN_SUBVERSION);
   77.83 +	si->nr_pages     = d->tot_pages;
   77.84  
   77.85  #if 0
   77.86 -	si->nr_pages     = d->tot_pages;
   77.87  	si->shared_info  = virt_to_phys(d->shared_info);
   77.88  	si->flags        = SIF_PRIVILEGED | SIF_INITDOMAIN;
   77.89  	//si->pt_base      = vpt_start;
   77.90 @@ -959,16 +956,7 @@ int construct_dom0(struct domain *d,
   77.91  
   77.92  	new_thread(v, pkern_entry, 0, 0);
   77.93  	physdev_init_dom0(d);
   77.94 -#ifdef CONFIG_IA64_SPLIT_CACHE
   77.95 -    /* Sync d/i cache conservatively */
   77.96 -    if (!running_on_sim) {
   77.97 -        ret = ia64_pal_cache_flush(4, 0, &progress, NULL);
   77.98 -        if ((ret!=PAL_STATUS_SUCCESS)&& (ret!=PAL_STATUS_UNIMPLEMENTED))
   77.99 -            printk("PAL CACHE FLUSH failed for dom0.\n");
  77.100 -        else
  77.101 -            printk("Sync i/d cache for guest SUCC\n");
  77.102 -    }
  77.103 -#endif
  77.104 +	sync_split_caches();
  77.105  
  77.106  	// FIXME: Hack for keyboard input
  77.107  #ifdef CLONE_DOMAIN0
  77.108 @@ -1027,16 +1015,7 @@ int construct_domU(struct domain *d,
  77.109  #endif
  77.110  	new_thread(v, pkern_entry, 0, 0);
  77.111  	printk("new_thread returns\n");
  77.112 -#ifdef CONFIG_IA64_SPLIT_CACHE
  77.113 -    /* Sync d/i cache conservatively */
  77.114 -    if (!running_on_sim) {
  77.115 -        ret = ia64_pal_cache_flush(4, 0, &progress, NULL);
  77.116 -        if ((ret!=PAL_STATUS_SUCCESS)&& (ret!=PAL_STATUS_UNIMPLEMENTED))
  77.117 -            printk("PAL CACHE FLUSH failed for dom0.\n");
  77.118 -        else
  77.119 -            printk("Sync i/d cache for guest SUCC\n");
  77.120 -    }
  77.121 -#endif
  77.122 +	sync_split_caches();
  77.123  	__set_bit(0x30, VCPU(v, delivery_mask));
  77.124  
  77.125  	return 0;
  77.126 @@ -1050,16 +1029,7 @@ void reconstruct_domU(struct vcpu *v)
  77.127  		v->domain->domain_id);
  77.128  	loaddomainelfimage(v->domain,v->domain->arch.image_start);
  77.129  	new_thread(v, v->domain->arch.entry, 0, 0);
  77.130 -#ifdef CONFIG_IA64_SPLIT_CACHE
  77.131 -    /* Sync d/i cache conservatively */
  77.132 -    if (!running_on_sim) {
  77.133 -        ret = ia64_pal_cache_flush(4, 0, &progress, NULL);
  77.134 -        if ((ret!=PAL_STATUS_SUCCESS)&& (ret!=PAL_STATUS_UNIMPLEMENTED))
  77.135 -            printk("PAL CACHE FLUSH failed for dom0.\n");
  77.136 -        else
  77.137 -            printk("Sync i/d cache for guest SUCC\n");
  77.138 -    }
  77.139 -#endif
  77.140 +	sync_split_caches();
  77.141  }
  77.142  #endif
  77.143  
  77.144 @@ -1100,15 +1070,6 @@ void domain_pend_keyboard_interrupt(int 
  77.145  	vcpu_pend_interrupt(dom0->vcpu[0],irq);
  77.146  }
  77.147  
  77.148 -void vcpu_migrate_cpu(struct vcpu *v, int newcpu)
  77.149 -{
  77.150 -	if ( v->processor == newcpu )
  77.151 -		return;
  77.152 -
  77.153 -	set_bit(_VCPUF_cpu_migrated, &v->vcpu_flags);
  77.154 -	v->processor = newcpu;
  77.155 -}
  77.156 -
  77.157  void sync_vcpu_execstate(struct vcpu *v)
  77.158  {
  77.159  	ia64_save_fpu(v->arch._thread.fph);
    78.1 --- a/xen/arch/ia64/xen/hyperprivop.S	Mon Jan 09 11:19:55 2006 +0000
    78.2 +++ b/xen/arch/ia64/xen/hyperprivop.S	Mon Jan 09 11:22:17 2006 +0000
    78.3 @@ -543,6 +543,13 @@ GLOBAL_ENTRY(fast_break_reflect)
    78.4  	extr.u r21=r30,IA64_PSR_PP_BIT,1 ;;
    78.5  	cmp.ne p7,p0=r21,r0 ;;
    78.6  (p7)	br.spnt.few dispatch_break_fault ;;
    78.7 +        movl r20=IA64_PSR_CPL ;; 
    78.8 +        and r22=r20,r30 ;;
    78.9 +        cmp.ne p7,p0=r22,r0
   78.10 +(p7)    br.spnt.many 1f ;;
   78.11 +        cmp.eq p7,p0=r17,r0
   78.12 +(p7)    br.spnt.few dispatch_break_fault ;;
   78.13 +1:
   78.14  #if 1 /* special handling in case running on simulator */
   78.15  	movl r20=first_break;;
   78.16  	ld4 r23=[r20];;
    79.1 --- a/xen/arch/ia64/xen/irq.c	Mon Jan 09 11:19:55 2006 +0000
    79.2 +++ b/xen/arch/ia64/xen/irq.c	Mon Jan 09 11:22:17 2006 +0000
    79.3 @@ -1378,9 +1378,6 @@ int pirq_guest_bind(struct vcpu *d, int 
    79.4      unsigned long       flags;
    79.5      int                 rc = 0;
    79.6  
    79.7 -    if ( !IS_CAPABLE_PHYSDEV(d->domain) )
    79.8 -        return -EPERM;
    79.9 -
   79.10      spin_lock_irqsave(&desc->lock, flags);
   79.11  
   79.12      action = (irq_guest_action_t *)desc->action;
    80.1 --- a/xen/arch/ia64/xen/ivt.S	Mon Jan 09 11:19:55 2006 +0000
    80.2 +++ b/xen/arch/ia64/xen/ivt.S	Mon Jan 09 11:22:17 2006 +0000
    80.3 @@ -839,6 +839,8 @@ ENTRY(break_fault)
    80.4  	mov r17=cr.iim
    80.5  	mov r31=pr
    80.6  	;;
    80.7 +	cmp.eq p7,p0=r17,r0
    80.8 +(p7)	br.spnt.few dispatch_break_fault ;;
    80.9  	movl r18=XSI_PSR_IC
   80.10  	;;
   80.11  	ld8 r19=[r18]
    81.1 --- a/xen/arch/ia64/xen/process.c	Mon Jan 09 11:19:55 2006 +0000
    81.2 +++ b/xen/arch/ia64/xen/process.c	Mon Jan 09 11:22:17 2006 +0000
    81.3 @@ -33,6 +33,7 @@
    81.4  #include <xen/multicall.h>
    81.5  
    81.6  extern unsigned long vcpu_get_itir_on_fault(struct vcpu *, UINT64);
    81.7 +extern void die_if_kernel(char *str, struct pt_regs *regs, long err);
    81.8  
    81.9  extern unsigned long dom0_start, dom0_size;
   81.10  
   81.11 @@ -64,26 +65,16 @@ long do_iopl(domid_t domain, unsigned in
   81.12  
   81.13  extern struct schedule_data schedule_data[NR_CPUS];
   81.14  
   81.15 -void schedule_tail(struct vcpu *next)
   81.16 +void schedule_tail(struct vcpu *prev)
   81.17  {
   81.18 -	unsigned long rr7;
   81.19 -	//printk("current=%lx,shared_info=%lx\n",current,current->vcpu_info);
   81.20 -	//printk("next=%lx,shared_info=%lx\n",next,next->vcpu_info);
   81.21 +	context_saved(prev);
   81.22  
   81.23 -    // TG: Real HACK FIXME.
   81.24 -    // This is currently necessary because when a new domain is started, 
   81.25 -    // the context_switch function of xen/common/schedule.c(__enter_scheduler)
   81.26 -    // never returns.  Therefore, the lock must be released.
   81.27 -    // schedule_tail is only called when a domain is started.
   81.28 -    spin_unlock_irq(&schedule_data[current->processor].schedule_lock);
   81.29 -
   81.30 -	/* rr7 will be postponed to last point when resuming back to guest */
   81.31 -    if(VMX_DOMAIN(current)){
   81.32 -    	vmx_load_all_rr(current);
   81.33 -    }else{
   81.34 -	    load_region_regs(current);
   81.35 -            vcpu_load_kernel_regs(current);
   81.36 -    }
   81.37 +	if (VMX_DOMAIN(current)) {
   81.38 +		vmx_load_all_rr(current);
   81.39 +	} else {
   81.40 +		load_region_regs(current);
   81.41 +		vcpu_load_kernel_regs(current);
   81.42 +	}
   81.43  }
   81.44  
   81.45  void tdpfoo(void) { }
   81.46 @@ -251,7 +242,7 @@ void deliver_pending_interrupt(struct pt
   81.47  	struct domain *d = current->domain;
   81.48  	struct vcpu *v = current;
   81.49  	// FIXME: Will this work properly if doing an RFI???
   81.50 -	if (!is_idle_task(d) && user_mode(regs)) {
   81.51 +	if (!is_idle_domain(d) && user_mode(regs)) {
   81.52  		//vcpu_poke_timer(v);
   81.53  		if (vcpu_deliverable_interrupts(v))
   81.54  			reflect_extint(regs);
   81.55 @@ -686,6 +677,8 @@ ia64_handle_break (unsigned long ifa, st
   81.56  			vcpu_increment_iip(current);
   81.57  	}
   81.58  	else {
   81.59 +		if (iim == 0) 
   81.60 +			die_if_kernel("bug check", regs, iim);
   81.61  		PSCB(v,iim) = iim;
   81.62  		reflect_interruption(isr,regs,IA64_BREAK_VECTOR);
   81.63  	}
    82.1 --- a/xen/arch/ia64/xen/vcpu.c	Mon Jan 09 11:19:55 2006 +0000
    82.2 +++ b/xen/arch/ia64/xen/vcpu.c	Mon Jan 09 11:22:17 2006 +0000
    82.3 @@ -1085,7 +1085,7 @@ void vcpu_set_next_timer(VCPU *vcpu)
    82.4  	/* gloss over the wraparound problem for now... we know it exists
    82.5  	 * but it doesn't matter right now */
    82.6  
    82.7 -	if (is_idle_task(vcpu->domain)) {
    82.8 +	if (is_idle_domain(vcpu->domain)) {
    82.9  //		printf("****** vcpu_set_next_timer called during idle!!\n");
   82.10  		vcpu_safe_set_itm(s);
   82.11  		return;
    83.1 --- a/xen/arch/ia64/xen/xenmisc.c	Mon Jan 09 11:19:55 2006 +0000
    83.2 +++ b/xen/arch/ia64/xen/xenmisc.c	Mon Jan 09 11:22:17 2006 +0000
    83.3 @@ -25,7 +25,6 @@ unsigned long wait_init_idle;
    83.4  int phys_proc_id[NR_CPUS];
    83.5  unsigned long loops_per_jiffy = (1<<12);	// from linux/init/main.c
    83.6  
    83.7 -void unw_init(void) { printf("unw_init() skipped (NEED FOR KERNEL UNWIND)\n"); }
    83.8  void ia64_mca_init(void) { printf("ia64_mca_init() skipped (Machine check abort handling)\n"); }
    83.9  void ia64_mca_cpu_init(void *x) { }
   83.10  void ia64_patch_mckinley_e9(unsigned long a, unsigned long b) { }
   83.11 @@ -180,11 +179,6 @@ void pgtable_quicklist_free(void *pgtabl
   83.12  // from arch/ia64/traps.c
   83.13  ///////////////////////////////
   83.14  
   83.15 -void show_registers(struct pt_regs *regs)
   83.16 -{
   83.17 -	printf("*** ADD REGISTER DUMP HERE FOR DEBUGGING\n");
   83.18 -}
   83.19 -
   83.20  int is_kernel_text(unsigned long addr)
   83.21  {
   83.22  	extern char _stext[], _etext[];
   83.23 @@ -236,7 +230,13 @@ void sys_exit(void)
   83.24  
   83.25  void die_if_kernel(char *str, struct pt_regs *regs, long err) /* __attribute__ ((noreturn)) */
   83.26  {
   83.27 -	printk("die_if_kernel: called, not implemented\n");
   83.28 +	if (user_mode(regs))
   83.29 +		return;
   83.30 +
   83.31 +	printk("%s: %s %ld\n", __func__, str, err);
   83.32 +	debugtrace_dump();
   83.33 +	show_registers(regs);
   83.34 +	domain_crash_synchronous();
   83.35  }
   83.36  
   83.37  long
   83.38 @@ -320,18 +320,15 @@ if (!i--) { printk("+",id); i = 1000000;
   83.39  	ia64_set_iva(&ia64_ivt);
   83.40  	ia64_set_pta(VHPT_ADDR | (1 << 8) | (VHPT_SIZE_LOG2 << 2) |
   83.41  		VHPT_ENABLED);
   83.42 -    	if (!is_idle_task(current->domain)) {
   83.43 +    	if (!is_idle_domain(current->domain)) {
   83.44  	    	load_region_regs(current);
   83.45  	    	vcpu_load_kernel_regs(current);
   83.46  		    if (vcpu_timer_expired(current)) vcpu_pend_timer(current);
   83.47      	}
   83.48  	    if (vcpu_timer_expired(current)) vcpu_pend_timer(current);
   83.49      }
   83.50 -}
   83.51  
   83.52 -void context_switch_finalise(struct vcpu *next)
   83.53 -{
   83.54 -	/* nothing to do */
   83.55 +    context_saved(prev);
   83.56  }
   83.57  
   83.58  void continue_running(struct vcpu *same)
   83.59 @@ -368,3 +365,23 @@ loop:
   83.60  		goto loop;
   83.61  	}
   83.62  }
   83.63 +
   83.64 +/* FIXME: for the forseeable future, all cpu's that enable VTi have split
   83.65 + *  caches and all cpu's that have split caches enable VTi.  This may
   83.66 + *  eventually be untrue though. */
   83.67 +#define cpu_has_split_cache	vmx_enabled
   83.68 +extern unsigned int vmx_enabled;
   83.69 +
   83.70 +void sync_split_caches(void)
   83.71 +{
   83.72 +	unsigned long ret, progress = 0;
   83.73 +
   83.74 +	if (cpu_has_split_cache) {
   83.75 +		/* Sync d/i cache conservatively */
   83.76 +		ret = ia64_pal_cache_flush(4, 0, &progress, NULL);
   83.77 +		if ((ret!=PAL_STATUS_SUCCESS)&& (ret!=PAL_STATUS_UNIMPLEMENTED))
   83.78 +			printk("PAL CACHE FLUSH failed\n");
   83.79 +		else printk("Sync i/d cache for guest SUCC\n");
   83.80 +	}
   83.81 +	else printk("sync_split_caches ignored for CPU with no split cache\n");
   83.82 +}
    84.1 --- a/xen/arch/ia64/xen/xensetup.c	Mon Jan 09 11:19:55 2006 +0000
    84.2 +++ b/xen/arch/ia64/xen/xensetup.c	Mon Jan 09 11:22:17 2006 +0000
    84.3 @@ -26,7 +26,7 @@ unsigned long xenheap_phys_end;
    84.4  
    84.5  char saved_command_line[COMMAND_LINE_SIZE];
    84.6  
    84.7 -struct vcpu *idle_task[NR_CPUS] = { &idle0_vcpu };
    84.8 +struct vcpu *idle_domain[NR_CPUS] = { &idle0_vcpu };
    84.9  
   84.10  cpumask_t cpu_present_map;
   84.11  
   84.12 @@ -382,8 +382,7 @@ printk("About to call do_createdomain()\
   84.13          panic("Could not set up DOM0 guest OS\n");
   84.14  
   84.15      /* PIN domain0 on CPU 0.  */
   84.16 -    dom0->vcpu[0]->cpumap=1;
   84.17 -    set_bit(_VCPUF_cpu_pinned, &dom0->vcpu[0]->vcpu_flags);
   84.18 +    dom0->vcpu[0]->cpu_affinity = cpumask_of_cpu(0);
   84.19  
   84.20  #ifdef CLONE_DOMAIN0
   84.21      {
    85.1 --- a/xen/arch/ia64/xen/xentime.c	Mon Jan 09 11:19:55 2006 +0000
    85.2 +++ b/xen/arch/ia64/xen/xentime.c	Mon Jan 09 11:22:17 2006 +0000
    85.3 @@ -127,7 +127,7 @@ xen_timer_interrupt (int irq, void *dev_
    85.4  			vcpu_wake(dom0->vcpu[0]);
    85.5  		}
    85.6  	}
    85.7 -	if (!is_idle_task(current->domain))  {
    85.8 +	if (!is_idle_domain(current->domain))  {
    85.9  		if (vcpu_timer_expired(current)) {
   85.10  			vcpu_pend_timer(current);
   85.11  			// ensure another timer interrupt happens even if domain doesn't
    86.1 --- a/xen/arch/x86/Makefile	Mon Jan 09 11:19:55 2006 +0000
    86.2 +++ b/xen/arch/x86/Makefile	Mon Jan 09 11:22:17 2006 +0000
    86.3 @@ -29,6 +29,7 @@ ifeq ($(TARGET_SUBARCH),x86_32)
    86.4  endif
    86.5  
    86.6  OBJS := $(subst $(TARGET_SUBARCH)/asm-offsets.o,,$(OBJS))
    86.7 +OBJS := $(subst $(TARGET_SUBARCH)/xen.lds.o,,$(OBJS))
    86.8  
    86.9  ifneq ($(crash_debug),y)
   86.10  OBJS := $(patsubst cdb%.o,,$(OBJS))
   86.11 @@ -43,22 +44,25 @@ default: $(TARGET)
   86.12  $(CURDIR)/arch.o: $(OBJS)
   86.13  	$(LD) $(LDFLAGS) -r -o $@ $(OBJS)
   86.14  
   86.15 -$(TARGET)-syms: boot/$(TARGET_SUBARCH).o $(ALL_OBJS) $(TARGET_SUBARCH)/xen.lds
   86.16 -	$(LD) $(LDFLAGS) -T $(TARGET_SUBARCH)/xen.lds -N \
   86.17 +$(TARGET)-syms: boot/$(TARGET_SUBARCH).o $(ALL_OBJS) xen.lds
   86.18 +	$(LD) $(LDFLAGS) -T xen.lds -N \
   86.19  	    boot/$(TARGET_SUBARCH).o $(ALL_OBJS) -o $@
   86.20  	$(NM) -n $@ | $(BASEDIR)/tools/symbols >$(BASEDIR)/xen-syms.S
   86.21  	$(MAKE) $(BASEDIR)/xen-syms.o
   86.22 -	$(LD) $(LDFLAGS) -T $(TARGET_SUBARCH)/xen.lds -N \
   86.23 +	$(LD) $(LDFLAGS) -T xen.lds -N \
   86.24  	    boot/$(TARGET_SUBARCH).o $(ALL_OBJS) $(BASEDIR)/xen-syms.o -o $@
   86.25  	$(NM) -n $@ | $(BASEDIR)/tools/symbols >$(BASEDIR)/xen-syms.S
   86.26  	$(MAKE) $(BASEDIR)/xen-syms.o
   86.27 -	$(LD) $(LDFLAGS) -T $(TARGET_SUBARCH)/xen.lds -N \
   86.28 +	$(LD) $(LDFLAGS) -T xen.lds -N \
   86.29  	    boot/$(TARGET_SUBARCH).o $(ALL_OBJS) $(BASEDIR)/xen-syms.o -o $@
   86.30  	rm -f $(BASEDIR)/xen-syms.S $(BASEDIR)/xen-syms.o
   86.31  
   86.32  asm-offsets.s: $(TARGET_SUBARCH)/asm-offsets.c $(HDRS)
   86.33  	$(CC) $(CFLAGS) -S -o $@ $<
   86.34  
   86.35 +xen.lds: $(TARGET_SUBARCH)/xen.lds.S $(HDRS)
   86.36 +	$(CC) $(CFLAGS) -P -E -Ui386 -D__ASSEMBLY__ -o $@ $<
   86.37 +
   86.38  boot/mkelf32: boot/mkelf32.c
   86.39  	$(HOSTCC) $(HOSTCFLAGS) -o $@ $<
   86.40  
   86.41 @@ -73,5 +77,6 @@ clean:
   86.42  	rm -f dm/*.o dm/*~ dm/core
   86.43  	rm -f genapic/*.o genapic/*~ genapic/core
   86.44  	rm -f cpu/*.o cpu/*~ cpu/core
   86.45 +	rm -f xen.lds
   86.46  
   86.47  .PHONY: default clean
    87.1 --- a/xen/arch/x86/boot/x86_32.S	Mon Jan 09 11:19:55 2006 +0000
    87.2 +++ b/xen/arch/x86/boot/x86_32.S	Mon Jan 09 11:22:17 2006 +0000
    87.3 @@ -1,5 +1,6 @@
    87.4  #include <xen/config.h>
    87.5  #include <public/xen.h>
    87.6 +#include <asm/asm_defns.h>
    87.7  #include <asm/desc.h>
    87.8  #include <asm/page.h>
    87.9  #include <asm/msr.h>
   87.10 @@ -53,6 +54,7 @@ 3:      in      %dx,%al
   87.11          mov     %ecx,%gs
   87.12          ljmp    $(__HYPERVISOR_CS),$(1f)-__PAGE_OFFSET
   87.13  1:      lss     stack_start-__PAGE_OFFSET,%esp
   87.14 +        add     $(STACK_SIZE-CPUINFO_sizeof-__PAGE_OFFSET),%esp
   87.15  
   87.16          /* Reset EFLAGS (subsumes CLI and CLD). */
   87.17  	pushl	$0
   87.18 @@ -98,7 +100,7 @@ 1:      mov     %eax,__PAGE_OFFSET>>18(%
   87.19  1:      stosl   /* low mappings cover as much physmem as possible */
   87.20          add     $4,%edi
   87.21          add     $(1<<L2_PAGETABLE_SHIFT),%eax
   87.22 -        cmp     $__HYPERVISOR_VIRT_START+0xe3,%eax
   87.23 +        cmp     $HYPERVISOR_VIRT_START+0xe3,%eax
   87.24          jne     1b
   87.25  #else
   87.26          /* Initialize low and high mappings of all memory with 4MB pages */
   87.27 @@ -111,7 +113,7 @@ 1:      mov     %eax,__PAGE_OFFSET>>20(%
   87.28          jne     1b
   87.29  1:      stosl   /* low mappings cover as much physmem as possible */
   87.30          add     $(1<<L2_PAGETABLE_SHIFT),%eax
   87.31 -        cmp     $__HYPERVISOR_VIRT_START+0xe3,%eax
   87.32 +        cmp     $HYPERVISOR_VIRT_START+0xe3,%eax
   87.33          jne     1b
   87.34  #endif
   87.35          
   87.36 @@ -189,7 +191,7 @@ 1:      jmp     1b
   87.37  /*** STACK LOCATION ***/
   87.38          
   87.39  ENTRY(stack_start)
   87.40 -        .long cpu0_stack + STACK_SIZE - 200 - __PAGE_OFFSET
   87.41 +        .long cpu0_stack
   87.42          .long __HYPERVISOR_DS
   87.43          
   87.44  /*** DESCRIPTOR TABLES ***/
   87.45 @@ -256,10 +258,6 @@ ENTRY(idle_pg_table_l2)
   87.46          .fill 1*PAGE_SIZE,1,0
   87.47  #endif
   87.48  
   87.49 -#if (STACK_ORDER == 0)
   87.50 -.section ".bss.page_aligned","w"
   87.51 -#else
   87.52 -.section ".bss.twopage_aligned","w"
   87.53 -#endif
   87.54 +.section ".bss.stack_aligned","w"
   87.55  ENTRY(cpu0_stack)
   87.56          .fill STACK_SIZE,1,0
    88.1 --- a/xen/arch/x86/boot/x86_64.S	Mon Jan 09 11:19:55 2006 +0000
    88.2 +++ b/xen/arch/x86/boot/x86_64.S	Mon Jan 09 11:22:17 2006 +0000
    88.3 @@ -1,5 +1,6 @@
    88.4  #include <xen/config.h>
    88.5  #include <public/xen.h>
    88.6 +#include <asm/asm_defns.h>
    88.7  #include <asm/desc.h>
    88.8  #include <asm/page.h>
    88.9  #include <asm/msr.h>
   88.10 @@ -121,7 +122,8 @@ 1:      /* Now in compatibility mode. Lo
   88.11          mov     %rcx,%cr4
   88.12  
   88.13          mov     stack_start(%rip),%rsp
   88.14 -        
   88.15 +        or      $(STACK_SIZE-CPUINFO_sizeof),%rsp
   88.16 +
   88.17          /* Reset EFLAGS (subsumes CLI and CLD). */
   88.18          pushq   $0
   88.19          popf
   88.20 @@ -140,7 +142,7 @@ 1:      /* Now in compatibility mode. Lo
   88.21          mov     %ecx,%ss
   88.22  
   88.23          lidt    idt_descr(%rip)
   88.24 -                
   88.25 +
   88.26          cmp     $(SECONDARY_CPU_FLAG),%ebx
   88.27          je      start_secondary
   88.28  
   88.29 @@ -219,7 +221,7 @@ idt:
   88.30          .quad   idt_table
   88.31  
   88.32  ENTRY(stack_start)
   88.33 -        .quad   cpu0_stack + STACK_SIZE - 200
   88.34 +        .quad   cpu0_stack
   88.35  
   88.36  high_start:
   88.37          .quad   __high_start
   88.38 @@ -265,10 +267,6 @@ ENTRY(idle_pg_table_l2)
   88.39          .org 0x4000 + PAGE_SIZE
   88.40          .code64
   88.41  
   88.42 -#if (STACK_ORDER == 0)
   88.43 -.section ".bss.page_aligned","w"
   88.44 -#else
   88.45 -.section ".bss.twopage_aligned","w"
   88.46 -#endif
   88.47 +.section ".bss.stack_aligned","w"
   88.48  ENTRY(cpu0_stack)
   88.49          .fill STACK_SIZE,1,0
    89.1 --- a/xen/arch/x86/dm/i8259.c	Mon Jan 09 11:19:55 2006 +0000
    89.2 +++ b/xen/arch/x86/dm/i8259.c	Mon Jan 09 11:22:17 2006 +0000
    89.3 @@ -29,7 +29,7 @@
    89.4  #include <xen/lib.h>
    89.5  #include <xen/errno.h>
    89.6  #include <xen/sched.h>
    89.7 -#include <public/io/ioreq.h>
    89.8 +#include <public/hvm/ioreq.h>
    89.9  #include <asm/vmx.h>
   89.10  #include <asm/vmx_vpic.h>
   89.11  #include <asm/current.h>
    90.1 --- a/xen/arch/x86/dm/vmx_vioapic.c	Mon Jan 09 11:19:55 2006 +0000
    90.2 +++ b/xen/arch/x86/dm/vmx_vioapic.c	Mon Jan 09 11:22:17 2006 +0000
    90.3 @@ -37,7 +37,7 @@
    90.4  #include <xen/lib.h>
    90.5  #include <xen/errno.h>
    90.6  #include <xen/sched.h>
    90.7 -#include <public/io/ioreq.h>
    90.8 +#include <public/hvm/ioreq.h>
    90.9  #include <asm/vmx.h>
   90.10  #include <asm/vmx_vpic.h>
   90.11  #include <asm/current.h>
    91.1 --- a/xen/arch/x86/dom0_ops.c	Mon Jan 09 11:19:55 2006 +0000
    91.2 +++ b/xen/arch/x86/dom0_ops.c	Mon Jan 09 11:22:17 2006 +0000
    91.3 @@ -17,6 +17,7 @@
    91.4  #include <asm/msr.h>
    91.5  #include <xen/trace.h>
    91.6  #include <xen/console.h>
    91.7 +#include <xen/iocap.h>
    91.8  #include <asm/shadow.h>
    91.9  #include <asm/irq.h>
   91.10  #include <asm/processor.h>
   91.11 @@ -35,13 +36,13 @@ static unsigned long msr_hi;
   91.12  
   91.13  static void write_msr_for(void *unused)
   91.14  {
   91.15 -    if ( ((1 << current->processor) & msr_cpu_mask) )
   91.16 +    if ( ((1 << smp_processor_id()) & msr_cpu_mask) )
   91.17          (void)wrmsr_user(msr_addr, msr_lo, msr_hi);
   91.18  }
   91.19  
   91.20  static void read_msr_for(void *unused)
   91.21  {
   91.22 -    if ( ((1 << current->processor) & msr_cpu_mask) )
   91.23 +    if ( ((1 << smp_processor_id()) & msr_cpu_mask) )
   91.24          (void)rdmsr_user(msr_addr, msr_lo, msr_hi);
   91.25  }
   91.26  
   91.27 @@ -102,12 +103,27 @@ long arch_do_dom0_op(dom0_op_t *op, dom0
   91.28              op->u.add_memtype.nr_pfns,
   91.29              op->u.add_memtype.type,
   91.30              1);
   91.31 +        if (ret > 0)
   91.32 +        {
   91.33 +            (void)__put_user(0, &u_dom0_op->u.add_memtype.handle);
   91.34 +            (void)__put_user(ret, &u_dom0_op->u.add_memtype.reg);
   91.35 +            ret = 0;
   91.36 +        }
   91.37      }
   91.38      break;
   91.39  
   91.40      case DOM0_DEL_MEMTYPE:
   91.41      {
   91.42 -        ret = mtrr_del_page(op->u.del_memtype.reg, 0, 0);
   91.43 +        if (op->u.del_memtype.handle == 0
   91.44 +            /* mtrr/main.c otherwise does a lookup */
   91.45 +            && (int)op->u.del_memtype.reg >= 0)
   91.46 +        {
   91.47 +            ret = mtrr_del_page(op->u.del_memtype.reg, 0, 0);
   91.48 +            if (ret > 0)
   91.49 +                ret = 0;
   91.50 +        }
   91.51 +        else
   91.52 +            ret = -EINVAL;
   91.53      }
   91.54      break;
   91.55  
   91.56 @@ -141,7 +157,6 @@ long arch_do_dom0_op(dom0_op_t *op, dom0
   91.57          struct domain *d;
   91.58          unsigned int fp = op->u.ioport_permission.first_port;
   91.59          unsigned int np = op->u.ioport_permission.nr_ports;
   91.60 -        unsigned int p;
   91.61  
   91.62          ret = -EINVAL;
   91.63          if ( (fp + np) > 65536 )
   91.64 @@ -152,26 +167,12 @@ long arch_do_dom0_op(dom0_op_t *op, dom0
   91.65              op->u.ioport_permission.domain)) == NULL) )
   91.66              break;
   91.67  
   91.68 -        ret = -ENOMEM;
   91.69 -        if ( d->arch.iobmp_mask != NULL )
   91.70 -        {
   91.71 -            if ( (d->arch.iobmp_mask = xmalloc_array(
   91.72 -                u8, IOBMP_BYTES)) == NULL )
   91.73 -            {
   91.74 -                put_domain(d);
   91.75 -                break;
   91.76 -            }
   91.77 -            memset(d->arch.iobmp_mask, 0xFF, IOBMP_BYTES);
   91.78 -        }
   91.79 -
   91.80 -        ret = 0;
   91.81 -        for ( p = fp; p < (fp + np); p++ )
   91.82 -        {
   91.83 -            if ( op->u.ioport_permission.allow_access )
   91.84 -                clear_bit(p, d->arch.iobmp_mask);
   91.85 -            else
   91.86 -                set_bit(p, d->arch.iobmp_mask);
   91.87 -        }
   91.88 +        if ( np == 0 )
   91.89 +            ret = 0;
   91.90 +        else if ( op->u.ioport_permission.allow_access )
   91.91 +            ret = ioports_permit_access(d, fp, fp + np - 1);
   91.92 +        else
   91.93 +            ret = ioports_deny_access(d, fp, fp + np - 1);
   91.94  
   91.95          put_domain(d);
   91.96      }
   91.97 @@ -193,7 +194,7 @@ long arch_do_dom0_op(dom0_op_t *op, dom0
   91.98          memcpy(pi->hw_cap, boot_cpu_data.x86_capability, NCAPINTS*4);
   91.99          ret = 0;
  91.100          if ( copy_to_user(u_dom0_op, op, sizeof(*op)) )
  91.101 -	    ret = -EFAULT;
  91.102 +            ret = -EFAULT;
  91.103      }
  91.104      break;
  91.105      
    92.1 --- a/xen/arch/x86/domain.c	Mon Jan 09 11:19:55 2006 +0000
    92.2 +++ b/xen/arch/x86/domain.c	Mon Jan 09 11:22:17 2006 +0000
    92.3 @@ -20,6 +20,7 @@
    92.4  #include <xen/delay.h>
    92.5  #include <xen/softirq.h>
    92.6  #include <xen/grant_table.h>
    92.7 +#include <xen/iocap.h>
    92.8  #include <asm/regs.h>
    92.9  #include <asm/mc146818rtc.h>
   92.10  #include <asm/system.h>
   92.11 @@ -35,9 +36,7 @@
   92.12  #include <xen/console.h>
   92.13  #include <xen/elf.h>
   92.14  #include <asm/vmx.h>
   92.15 -#include <asm/vmx_vmcs.h>
   92.16  #include <asm/msr.h>
   92.17 -#include <asm/physdev.h>
   92.18  #include <xen/kernel.h>
   92.19  #include <xen/multicall.h>
   92.20  
   92.21 @@ -47,17 +46,16 @@ boolean_param("noreboot", opt_noreboot);
   92.22  
   92.23  struct percpu_ctxt {
   92.24      struct vcpu *curr_vcpu;
   92.25 -    unsigned int context_not_finalised;
   92.26      unsigned int dirty_segment_mask;
   92.27  } __cacheline_aligned;
   92.28  static struct percpu_ctxt percpu_ctxt[NR_CPUS];
   92.29  
   92.30 -static void continue_idle_task(struct vcpu *v)
   92.31 +static void continue_idle_domain(struct vcpu *v)
   92.32  {
   92.33      reset_stack_and_jump(idle_loop);
   92.34  }
   92.35  
   92.36 -static void continue_nonidle_task(struct vcpu *v)
   92.37 +static void continue_nonidle_domain(struct vcpu *v)
   92.38  {
   92.39      reset_stack_and_jump(ret_from_intr);
   92.40  }
   92.41 @@ -93,12 +91,13 @@ void startup_cpu_idle_loop(void)
   92.42  {
   92.43      struct vcpu *v = current;
   92.44  
   92.45 -    ASSERT(is_idle_task(v->domain));
   92.46 +    ASSERT(is_idle_domain(v->domain));
   92.47      percpu_ctxt[smp_processor_id()].curr_vcpu = v;
   92.48 -    cpu_set(smp_processor_id(), v->domain->cpumask);
   92.49 -    v->arch.schedule_tail = continue_idle_task;
   92.50 +    cpu_set(smp_processor_id(), v->domain->domain_dirty_cpumask);
   92.51 +    cpu_set(smp_processor_id(), v->vcpu_dirty_cpumask);
   92.52 +    v->arch.schedule_tail = continue_idle_domain;
   92.53  
   92.54 -    idle_loop();
   92.55 +    reset_stack_and_jump(idle_loop);
   92.56  }
   92.57  
   92.58  static long no_idt[2];
   92.59 @@ -185,11 +184,17 @@ void dump_pageframe_info(struct domain *
   92.60  {
   92.61      struct pfn_info *page;
   92.62  
   92.63 -    if ( d->tot_pages < 10 )
   92.64 +    printk("Memory pages belonging to domain %u:\n", d->domain_id);
   92.65 +
   92.66 +    if ( d->tot_pages >= 10 )
   92.67 +    {
   92.68 +        printk("    DomPage list too long to display\n");
   92.69 +    }
   92.70 +    else
   92.71      {
   92.72          list_for_each_entry ( page, &d->page_list, list )
   92.73          {
   92.74 -            printk("Page %p: mfn=%p, caf=%08x, taf=%" PRtype_info "\n",
   92.75 +            printk("    DomPage %p: mfn=%p, caf=%08x, taf=%" PRtype_info "\n",
   92.76                     _p(page_to_phys(page)), _p(page_to_pfn(page)),
   92.77                     page->count_info, page->u.inuse.type_info);
   92.78          }
   92.79 @@ -197,15 +202,10 @@ void dump_pageframe_info(struct domain *
   92.80  
   92.81      list_for_each_entry ( page, &d->xenpage_list, list )
   92.82      {
   92.83 -        printk("XenPage %p: mfn=%p, caf=%08x, taf=%" PRtype_info "\n",
   92.84 +        printk("    XenPage %p: mfn=%p, caf=%08x, taf=%" PRtype_info "\n",
   92.85                 _p(page_to_phys(page)), _p(page_to_pfn(page)),
   92.86                 page->count_info, page->u.inuse.type_info);
   92.87      }
   92.88 -
   92.89 -    page = virt_to_page(d->shared_info);
   92.90 -    printk("Shared_info@%p: mfn=%p, caf=%08x, taf=%" PRtype_info "\n",
   92.91 -           _p(page_to_phys(page)), _p(page_to_pfn(page)), page->count_info,
   92.92 -           page->u.inuse.type_info);
   92.93  }
   92.94  
   92.95  struct vcpu *alloc_vcpu_struct(struct domain *d, unsigned int vcpu_id)
   92.96 @@ -250,24 +250,36 @@ void free_perdomain_pt(struct domain *d)
   92.97  #endif
   92.98  }
   92.99  
  92.100 -void arch_do_createdomain(struct vcpu *v)
  92.101 +int arch_do_createdomain(struct vcpu *v)
  92.102  {
  92.103      struct domain *d = v->domain;
  92.104      l1_pgentry_t gdt_l1e;
  92.105 -    int vcpuid, pdpt_order;
  92.106 +    int vcpuid, pdpt_order, rc;
  92.107  #ifdef __x86_64__
  92.108      int i;
  92.109  #endif
  92.110  
  92.111 -    if ( is_idle_task(d) )
  92.112 -        return;
  92.113 +    if ( is_idle_domain(d) )
  92.114 +        return 0;
  92.115 +
  92.116 +    d->arch.ioport_caps = 
  92.117 +        rangeset_new(d, "I/O Ports", RANGESETF_prettyprint_hex);
  92.118 +    if ( d->arch.ioport_caps == NULL )
  92.119 +        return -ENOMEM;
  92.120  
  92.121 -    v->arch.schedule_tail = continue_nonidle_task;
  92.122 +    if ( (d->shared_info = alloc_xenheap_page()) == NULL )
  92.123 +        return -ENOMEM;
  92.124  
  92.125 -    d->shared_info = alloc_xenheap_page();
  92.126 +    if ( (rc = ptwr_init(d)) != 0 )
  92.127 +    {
  92.128 +        free_xenheap_page(d->shared_info);
  92.129 +        return rc;
  92.130 +    }
  92.131 +
  92.132 +    v->arch.schedule_tail = continue_nonidle_domain;
  92.133 +
  92.134      memset(d->shared_info, 0, PAGE_SIZE);
  92.135      v->vcpu_info = &d->shared_info->vcpu_info[v->vcpu_id];
  92.136 -    v->cpumap = CPUMAP_RUNANYWHERE;
  92.137      SHARE_PFN_WITH_DOMAIN(virt_to_page(d->shared_info), d);
  92.138  
  92.139      pdpt_order = get_order_from_bytes(PDPT_L1_ENTRIES * sizeof(l1_pgentry_t));
  92.140 @@ -308,25 +320,10 @@ void arch_do_createdomain(struct vcpu *v
  92.141                              __PAGE_HYPERVISOR);
  92.142  #endif
  92.143  
  92.144 -    (void)ptwr_init(d);
  92.145 -
  92.146      shadow_lock_init(d);
  92.147      INIT_LIST_HEAD(&d->arch.free_shadow_frames);
  92.148 -}
  92.149  
  92.150 -void vcpu_migrate_cpu(struct vcpu *v, int newcpu)
  92.151 -{
  92.152 -    if ( v->processor == newcpu )
  92.153 -        return;
  92.154 -
  92.155 -    set_bit(_VCPUF_cpu_migrated, &v->vcpu_flags);
  92.156 -    v->processor = newcpu;
  92.157 -
  92.158 -    if ( VMX_DOMAIN(v) )
  92.159 -    {
  92.160 -        __vmpclear(virt_to_phys(v->arch.arch_vmx.vmcs));
  92.161 -        v->arch.schedule_tail = arch_vmx_do_relaunch;
  92.162 -    }
  92.163 +    return 0;
  92.164  }
  92.165  
  92.166  /* This is called by arch_final_setup_guest and do_boot_vcpu */
  92.167 @@ -348,6 +345,8 @@ int arch_set_info_guest(
  92.168               ((c->user_regs.ss & 3) == 0) )
  92.169              return -EINVAL;
  92.170      }
  92.171 +    else if ( !hvm_enabled )
  92.172 +        return -EINVAL;
  92.173  
  92.174      clear_bit(_VCPUF_fpu_initialised, &v->vcpu_flags);
  92.175      if ( c->flags & VGCF_I387_VALID )
  92.176 @@ -690,7 +689,7 @@ static void __context_switch(void)
  92.177      struct vcpu          *p = percpu_ctxt[cpu].curr_vcpu;
  92.178      struct vcpu          *n = current;
  92.179  
  92.180 -    if ( !is_idle_task(p->domain) )
  92.181 +    if ( !is_idle_domain(p->domain) )
  92.182      {
  92.183          memcpy(&p->arch.guest_context.user_regs,
  92.184                 stack_regs,
  92.185 @@ -699,7 +698,7 @@ static void __context_switch(void)
  92.186          save_segments(p);
  92.187      }
  92.188  
  92.189 -    if ( !is_idle_task(n->domain) )
  92.190 +    if ( !is_idle_domain(n->domain) )
  92.191      {
  92.192          memcpy(stack_regs,
  92.193                 &n->arch.guest_context.user_regs,
  92.194 @@ -725,7 +724,8 @@ static void __context_switch(void)
  92.195      }
  92.196  
  92.197      if ( p->domain != n->domain )
  92.198 -        cpu_set(cpu, n->domain->cpumask);
  92.199 +        cpu_set(cpu, n->domain->domain_dirty_cpumask);
  92.200 +    cpu_set(cpu, n->vcpu_dirty_cpumask);
  92.201  
  92.202      write_ptbase(n);
  92.203  
  92.204 @@ -738,7 +738,8 @@ static void __context_switch(void)
  92.205      }
  92.206  
  92.207      if ( p->domain != n->domain )
  92.208 -        cpu_clear(cpu, p->domain->cpumask);
  92.209 +        cpu_clear(cpu, p->domain->domain_dirty_cpumask);
  92.210 +    cpu_clear(cpu, p->vcpu_dirty_cpumask);
  92.211  
  92.212      percpu_ctxt[cpu].curr_vcpu = n;
  92.213  }
  92.214 @@ -748,28 +749,24 @@ void context_switch(struct vcpu *prev, s
  92.215  {
  92.216      unsigned int cpu = smp_processor_id();
  92.217  
  92.218 -    ASSERT(!local_irq_is_enabled());
  92.219 +    ASSERT(local_irq_is_enabled());
  92.220  
  92.221      set_current(next);
  92.222  
  92.223 -    if ( (percpu_ctxt[cpu].curr_vcpu != next) && !is_idle_task(next->domain) )
  92.224 +    if ( (percpu_ctxt[cpu].curr_vcpu != next) &&
  92.225 +         !is_idle_domain(next->domain) )
  92.226      {
  92.227 -        __context_switch();
  92.228 -        percpu_ctxt[cpu].context_not_finalised = 1;
  92.229 -    }
  92.230 -}
  92.231 +        /* This may happen if next has been migrated by the scheduler. */
  92.232 +        if ( unlikely(!cpus_empty(next->vcpu_dirty_cpumask)) )
  92.233 +        {
  92.234 +            ASSERT(!cpu_isset(cpu, next->vcpu_dirty_cpumask));
  92.235 +            sync_vcpu_execstate(next);
  92.236 +            ASSERT(cpus_empty(next->vcpu_dirty_cpumask));
  92.237 +        }
  92.238  
  92.239 -void context_switch_finalise(struct vcpu *next)
  92.240 -{
  92.241 -    unsigned int cpu = smp_processor_id();
  92.242 -
  92.243 -    ASSERT(local_irq_is_enabled());
  92.244 -
  92.245 -    if ( percpu_ctxt[cpu].context_not_finalised )
  92.246 -    {
  92.247 -        percpu_ctxt[cpu].context_not_finalised = 0;
  92.248 -
  92.249 -        BUG_ON(percpu_ctxt[cpu].curr_vcpu != next);
  92.250 +        local_irq_disable();
  92.251 +        __context_switch();
  92.252 +        local_irq_enable();
  92.253  
  92.254          if ( VMX_DOMAIN(next) )
  92.255          {
  92.256 @@ -783,6 +780,8 @@ void context_switch_finalise(struct vcpu
  92.257          }
  92.258      }
  92.259  
  92.260 +    context_saved(prev);
  92.261 +
  92.262      schedule_tail(next);
  92.263      BUG();
  92.264  }
  92.265 @@ -812,20 +811,11 @@ int __sync_lazy_execstate(void)
  92.266  
  92.267  void sync_vcpu_execstate(struct vcpu *v)
  92.268  {
  92.269 -    unsigned int cpu = v->processor;
  92.270 -
  92.271 -    if ( !cpu_isset(cpu, v->domain->cpumask) )
  92.272 -        return;
  92.273 +    if ( cpu_isset(smp_processor_id(), v->vcpu_dirty_cpumask) )
  92.274 +        (void)__sync_lazy_execstate();
  92.275  
  92.276 -    if ( cpu == smp_processor_id() )
  92.277 -    {
  92.278 -        (void)__sync_lazy_execstate();
  92.279 -    }
  92.280 -    else
  92.281 -    {
  92.282 -        /* Other cpus call __sync_lazy_execstate from flush ipi handler. */
  92.283 -        flush_tlb_mask(cpumask_of_cpu(cpu));
  92.284 -    }
  92.285 +    /* Other cpus call __sync_lazy_execstate from flush ipi handler. */
  92.286 +    flush_tlb_mask(v->vcpu_dirty_cpumask);
  92.287  }
  92.288  
  92.289  unsigned long __hypercall_create_continuation(
  92.290 @@ -951,9 +941,7 @@ void domain_relinquish_resources(struct 
  92.291      struct vcpu *v;
  92.292      unsigned long pfn;
  92.293  
  92.294 -    BUG_ON(!cpus_empty(d->cpumask));
  92.295 -
  92.296 -    physdev_destroy_state(d);
  92.297 +    BUG_ON(!cpus_empty(d->domain_dirty_cpumask));
  92.298  
  92.299      ptwr_destroy(d);
  92.300  
    93.1 --- a/xen/arch/x86/domain_build.c	Mon Jan 09 11:19:55 2006 +0000
    93.2 +++ b/xen/arch/x86/domain_build.c	Mon Jan 09 11:22:17 2006 +0000
    93.3 @@ -16,13 +16,13 @@
    93.4  #include <xen/kernel.h>
    93.5  #include <xen/domain.h>
    93.6  #include <xen/compile.h>
    93.7 +#include <xen/iocap.h>
    93.8  #include <asm/regs.h>
    93.9  #include <asm/system.h>
   93.10  #include <asm/io.h>
   93.11  #include <asm/processor.h>
   93.12  #include <asm/desc.h>
   93.13  #include <asm/i387.h>
   93.14 -#include <asm/physdev.h>
   93.15  #include <asm/shadow.h>
   93.16  
   93.17  static long dom0_nrpages;
   93.18 @@ -94,9 +94,9 @@ static struct pfn_info *alloc_chunk(stru
   93.19      return page;
   93.20  }
   93.21  
   93.22 -static void process_dom0_ioports_disable()
   93.23 +static void process_dom0_ioports_disable(void)
   93.24  {
   93.25 -    unsigned long io_from, io_to, io_nr;
   93.26 +    unsigned long io_from, io_to;
   93.27      char *t, *u, *s = opt_dom0_ioports_disable;
   93.28  
   93.29      if ( *s == '\0' )
   93.30 @@ -126,8 +126,8 @@ static void process_dom0_ioports_disable
   93.31          printk("Disabling dom0 access to ioport range %04lx-%04lx\n",
   93.32              io_from, io_to);
   93.33  
   93.34 -        io_nr = io_to - io_from + 1;
   93.35 -        physdev_modify_ioport_access_range(dom0, 0, io_from, io_nr);
   93.36 +        if ( ioports_deny_access(dom0, io_from, io_to) != 0 )
   93.37 +            BUG();
   93.38      }
   93.39  }
   93.40  
   93.41 @@ -183,7 +183,6 @@ int construct_dom0(struct domain *d,
   93.42      /* Machine address of next candidate page-table page. */
   93.43      unsigned long mpt_alloc;
   93.44  
   93.45 -    extern void physdev_init_dom0(struct domain *);
   93.46      extern void translate_l2pgtable(
   93.47          struct domain *d, l1_pgentry_t *p2m, unsigned long l2mfn);
   93.48  
   93.49 @@ -692,9 +691,6 @@ int construct_dom0(struct domain *d,
   93.50      zap_low_mappings(l2start);
   93.51      zap_low_mappings(idle_pg_table_l2);
   93.52  #endif
   93.53 -    
   93.54 -    /* DOM0 gets access to everything. */
   93.55 -    physdev_init_dom0(d);
   93.56  
   93.57      init_domain_time(d);
   93.58  
   93.59 @@ -746,20 +742,29 @@ int construct_dom0(struct domain *d,
   93.60          printk("dom0: shadow setup done\n");
   93.61      }
   93.62  
   93.63 +    i = 0;
   93.64 +
   93.65 +    /* DOM0 is permitted full I/O capabilities. */
   93.66 +    i |= ioports_permit_access(dom0, 0, 0xFFFF);
   93.67 +    i |= iomem_permit_access(dom0, 0UL, ~0UL);
   93.68 +    i |= irqs_permit_access(dom0, 0, NR_PIRQS-1);
   93.69 +
   93.70      /*
   93.71       * Modify I/O port access permissions.
   93.72       */
   93.73      /* Master Interrupt Controller (PIC). */
   93.74 -    physdev_modify_ioport_access_range(dom0, 0, 0x20, 2);
   93.75 +    i |= ioports_deny_access(dom0, 0x20, 0x21);
   93.76      /* Slave Interrupt Controller (PIC). */
   93.77 -    physdev_modify_ioport_access_range(dom0, 0, 0xA0, 2);
   93.78 +    i |= ioports_deny_access(dom0, 0xA0, 0xA1);
   93.79      /* Interval Timer (PIT). */
   93.80 -    physdev_modify_ioport_access_range(dom0, 0, 0x40, 4);
   93.81 +    i |= ioports_deny_access(dom0, 0x40, 0x43);
   93.82      /* PIT Channel 2 / PC Speaker Control. */
   93.83 -    physdev_modify_ioport_access_range(dom0, 0, 0x61, 1);
   93.84 -    /* Command-line passed i/o ranges */
   93.85 +    i |= ioports_deny_access(dom0, 0x61, 0x61);
   93.86 +    /* Command-line I/O ranges. */
   93.87      process_dom0_ioports_disable();
   93.88  
   93.89 +    BUG_ON(i != 0);
   93.90 +
   93.91      return 0;
   93.92  }
   93.93  
    94.1 --- a/xen/arch/x86/idle0_task.c	Mon Jan 09 11:19:55 2006 +0000
    94.2 +++ b/xen/arch/x86/idle0_task.c	Mon Jan 09 11:22:17 2006 +0000
    94.3 @@ -11,6 +11,7 @@ struct domain idle0_domain = {
    94.4  
    94.5  struct vcpu idle0_vcpu = {
    94.6      processor:   0,
    94.7 +    cpu_affinity:CPU_MASK_CPU0,
    94.8      domain:      &idle0_domain
    94.9  };
   94.10  
    95.1 --- a/xen/arch/x86/io_apic.c	Mon Jan 09 11:19:55 2006 +0000
    95.2 +++ b/xen/arch/x86/io_apic.c	Mon Jan 09 11:22:17 2006 +0000
    95.3 @@ -1807,3 +1807,47 @@ int ioapic_guest_write(int apicid, int a
    95.4  
    95.5      return 0;
    95.6  }
    95.7 +
    95.8 +void dump_ioapic_irq_info(void)
    95.9 +{
   95.10 +    struct irq_pin_list *entry;
   95.11 +    struct IO_APIC_route_entry rte;
   95.12 +    unsigned int irq, pin, printed = 0;
   95.13 +    unsigned long flags;
   95.14 +
   95.15 +    for ( irq = 0; irq < NR_IRQS; irq++ )
   95.16 +    {
   95.17 +        entry = &irq_2_pin[irq];
   95.18 +        if ( entry->pin == -1 )
   95.19 +            continue;
   95.20 +
   95.21 +        if ( !printed++ )
   95.22 +            printk("IO-APIC interrupt information:\n");
   95.23 +
   95.24 +        printk("    IRQ%3d Vec%3d:\n", irq, irq_to_vector(irq));
   95.25 +
   95.26 +        for ( ; ; )
   95.27 +        {
   95.28 +            pin = entry->pin;
   95.29 +
   95.30 +            printk("      Apic 0x%02x, Pin %2d: ", entry->apic, pin);
   95.31 +
   95.32 +            spin_lock_irqsave(&ioapic_lock, flags);
   95.33 +            *(((int *)&rte) + 0) = io_apic_read(entry->apic, 0x10 + 2 * pin);
   95.34 +            *(((int *)&rte) + 1) = io_apic_read(entry->apic, 0x11 + 2 * pin);
   95.35 +            spin_unlock_irqrestore(&ioapic_lock, flags);
   95.36 +
   95.37 +            printk("vector=%u, delivery_mode=%u, dest_mode=%s, "
   95.38 +                   "delivery_status=%d, polarity=%d, irr=%d, "
   95.39 +                   "trigger=%s, mask=%d\n",
   95.40 +                   rte.vector, rte.delivery_mode,
   95.41 +                   rte.dest_mode ? "logical" : "physical",
   95.42 +                   rte.delivery_status, rte.polarity, rte.irr,
   95.43 +                   rte.trigger ? "level" : "edge", rte.mask);
   95.44 +
   95.45 +            if ( entry->next == 0 )
   95.46 +                break;
   95.47 +            entry = &irq_2_pin[entry->next];
   95.48 +        }
   95.49 +    }
   95.50 +}
    96.1 --- a/xen/arch/x86/irq.c	Mon Jan 09 11:19:55 2006 +0000
    96.2 +++ b/xen/arch/x86/irq.c	Mon Jan 09 11:22:17 2006 +0000
    96.3 @@ -12,6 +12,7 @@
    96.4  #include <xen/irq.h>
    96.5  #include <xen/perfc.h>
    96.6  #include <xen/sched.h>
    96.7 +#include <xen/keyhandler.h>
    96.8  #include <asm/current.h>
    96.9  #include <asm/smpboot.h>
   96.10  
   96.11 @@ -198,19 +199,21 @@ int pirq_guest_unmask(struct domain *d)
   96.12  
   96.13  int pirq_guest_bind(struct vcpu *v, int irq, int will_share)
   96.14  {
   96.15 -    unsigned int        vector = irq_to_vector(irq);
   96.16 -    struct domain      *d = v->domain;
   96.17 -    irq_desc_t         *desc = &irq_desc[vector];
   96.18 +    unsigned int        vector;
   96.19 +    irq_desc_t         *desc;
   96.20      irq_guest_action_t *action;
   96.21      unsigned long       flags;
   96.22      int                 rc = 0;
   96.23      cpumask_t           cpumask = CPU_MASK_NONE;
   96.24  
   96.25 -    if ( !IS_CAPABLE_PHYSDEV(d) )
   96.26 -        return -EPERM;
   96.27 +    if ( (irq < 0) || (irq >= NR_IRQS) )
   96.28 +        return -EINVAL;
   96.29  
   96.30 +    vector = irq_to_vector(irq);
   96.31      if ( vector == 0 )
   96.32 -        return -EBUSY;
   96.33 +        return -EINVAL;
   96.34 +
   96.35 +    desc = &irq_desc[vector];
   96.36  
   96.37      spin_lock_irqsave(&desc->lock, flags);
   96.38  
   96.39 @@ -309,3 +312,71 @@ int pirq_guest_unbind(struct domain *d, 
   96.40      spin_unlock_irqrestore(&desc->lock, flags);    
   96.41      return 0;
   96.42  }
   96.43 +
   96.44 +extern void dump_ioapic_irq_info(void);
   96.45 +
   96.46 +static void dump_irqs(unsigned char key)
   96.47 +{
   96.48 +    int i, irq, vector;
   96.49 +    irq_desc_t *desc;
   96.50 +    irq_guest_action_t *action;
   96.51 +    struct domain *d;
   96.52 +    unsigned long flags;
   96.53 +
   96.54 +    printk("Guest interrupt information:\n");
   96.55 +
   96.56 +    for ( irq = 0; irq < NR_IRQS; irq++ )
   96.57 +    {
   96.58 +        vector = irq_to_vector(irq);
   96.59 +        if ( vector == 0 )
   96.60 +            continue;
   96.61 +
   96.62 +        desc = &irq_desc[vector];
   96.63 +
   96.64 +        spin_lock_irqsave(&desc->lock, flags);
   96.65 +
   96.66 +        if ( desc->status & IRQ_GUEST )
   96.67 +        {
   96.68 +            action = (irq_guest_action_t *)desc->action;
   96.69 +
   96.70 +            printk("    IRQ%3d Vec%3d: type=%-15s status=%08x "
   96.71 +                   "in-flight=%d domain-list=",
   96.72 +                   irq, vector, desc->handler->typename,
   96.73 +                   desc->status, action->in_flight);
   96.74 +
   96.75 +            for ( i = 0; i < action->nr_guests; i++ )
   96.76 +            {
   96.77 +                d = action->guest[i];
   96.78 +                printk("%u(%c%c%c%c)",
   96.79 +                       d->domain_id,
   96.80 +                       (test_bit(d->pirq_to_evtchn[irq],
   96.81 +                                 &d->shared_info->evtchn_pending[0]) ?
   96.82 +                        'P' : '-'),
   96.83 +                       (test_bit(d->pirq_to_evtchn[irq]/BITS_PER_LONG,
   96.84 +                                 &d->shared_info->vcpu_info[0].
   96.85 +                                 evtchn_pending_sel) ?
   96.86 +                        'S' : '-'),
   96.87 +                       (test_bit(d->pirq_to_evtchn[irq],
   96.88 +                                 &d->shared_info->evtchn_mask[0]) ?
   96.89 +                        'M' : '-'),
   96.90 +                       (test_bit(irq, &d->pirq_mask) ?
   96.91 +                        'M' : '-'));
   96.92 +                if ( i != action->nr_guests )
   96.93 +                    printk(",");
   96.94 +            }
   96.95 +
   96.96 +            printk("\n");
   96.97 +        }
   96.98 +
   96.99 +        spin_unlock_irqrestore(&desc->lock, flags);
  96.100 +    }
  96.101 +
  96.102 +    dump_ioapic_irq_info();
  96.103 +}
  96.104 +
  96.105 +static int __init setup_dump_irqs(void)
  96.106 +{
  96.107 +    register_keyhandler('i', dump_irqs, "dump interrupt bindings");
  96.108 +    return 0;
  96.109 +}
  96.110 +__initcall(setup_dump_irqs);
    97.1 --- a/xen/arch/x86/mm.c	Mon Jan 09 11:19:55 2006 +0000
    97.2 +++ b/xen/arch/x86/mm.c	Mon Jan 09 11:22:17 2006 +0000
    97.3 @@ -96,6 +96,7 @@
    97.4  #include <xen/softirq.h>
    97.5  #include <xen/domain_page.h>
    97.6  #include <xen/event.h>
    97.7 +#include <xen/iocap.h>
    97.8  #include <asm/shadow.h>
    97.9  #include <asm/page.h>
   97.10  #include <asm/flushtlb.h>
   97.11 @@ -437,7 +438,6 @@ get_page_from_l1e(
   97.12      unsigned long mfn = l1e_get_pfn(l1e);
   97.13      struct pfn_info *page = pfn_to_page(mfn);
   97.14      int okay;
   97.15 -    extern int domain_iomem_in_pfn(struct domain *d, unsigned long pfn);
   97.16  
   97.17      if ( !(l1e_get_flags(l1e) & _PAGE_PRESENT) )
   97.18          return 1;
   97.19 @@ -455,8 +455,7 @@ get_page_from_l1e(
   97.20          if ( d == dom_io )
   97.21              d = current->domain;
   97.22  
   97.23 -        if ( (!IS_PRIV(d)) &&
   97.24 -             (!IS_CAPABLE_PHYSDEV(d) || !domain_iomem_in_pfn(d, mfn)) )
   97.25 +        if ( !iomem_access_permitted(d, mfn, mfn) )
   97.26          {
   97.27              MEM_LOG("Non-privileged attempt to map I/O space %08lx", mfn);
   97.28              return 0;
   97.29 @@ -1458,7 +1457,8 @@ int get_page_type(struct pfn_info *page,
   97.30                       * was GDT/LDT) but those circumstances should be
   97.31                       * very rare.
   97.32                       */
   97.33 -                    cpumask_t mask = page_get_owner(page)->cpumask;
   97.34 +                    cpumask_t mask =
   97.35 +                        page_get_owner(page)->domain_dirty_cpumask;
   97.36                      tlbflush_filter(mask, page->tlbflush_timestamp);
   97.37  
   97.38                      if ( unlikely(!cpus_empty(mask)) )
   97.39 @@ -1620,7 +1620,7 @@ static void process_deferred_ops(unsigne
   97.40          if ( shadow_mode_enabled(d) )
   97.41              shadow_sync_all(d);
   97.42          if ( deferred_ops & DOP_FLUSH_ALL_TLBS )
   97.43 -            flush_tlb_mask(d->cpumask);
   97.44 +            flush_tlb_mask(d->domain_dirty_cpumask);
   97.45          else
   97.46              local_flush_tlb();
   97.47      }
   97.48 @@ -1692,7 +1692,7 @@ static inline cpumask_t vcpumask_to_pcpu
   97.49      struct domain *d, unsigned long vmask)
   97.50  {
   97.51      unsigned int vcpu_id;
   97.52 -    cpumask_t    pmask;
   97.53 +    cpumask_t    pmask = CPU_MASK_NONE;
   97.54      struct vcpu *v;
   97.55  
   97.56      while ( vmask != 0 )
   97.57 @@ -1701,7 +1701,7 @@ static inline cpumask_t vcpumask_to_pcpu
   97.58          vmask &= ~(1UL << vcpu_id);
   97.59          if ( (vcpu_id < MAX_VIRT_CPUS) &&
   97.60               ((v = d->vcpu[vcpu_id]) != NULL) )
   97.61 -            cpu_set(v->processor, pmask);
   97.62 +            cpus_or(pmask, pmask, v->vcpu_dirty_cpumask);
   97.63      }
   97.64  
   97.65      return pmask;
   97.66 @@ -1870,7 +1870,6 @@ int do_mmuext_op(
   97.67                  break;
   97.68              }
   97.69              pmask = vcpumask_to_pcpumask(d, vmask);
   97.70 -            cpus_and(pmask, pmask, d->cpumask);
   97.71              if ( op.cmd == MMUEXT_TLB_FLUSH_MULTI )
   97.72                  flush_tlb_mask(pmask);
   97.73              else
   97.74 @@ -1879,15 +1878,15 @@ int do_mmuext_op(
   97.75          }
   97.76  
   97.77          case MMUEXT_TLB_FLUSH_ALL:
   97.78 -            flush_tlb_mask(d->cpumask);
   97.79 +            flush_tlb_mask(d->domain_dirty_cpumask);
   97.80              break;
   97.81      
   97.82          case MMUEXT_INVLPG_ALL:
   97.83 -            flush_tlb_one_mask(d->cpumask, op.arg1.linear_addr);
   97.84 +            flush_tlb_one_mask(d->domain_dirty_cpumask, op.arg1.linear_addr);
   97.85              break;
   97.86  
   97.87          case MMUEXT_FLUSH_CACHE:
   97.88 -            if ( unlikely(!IS_CAPABLE_PHYSDEV(d)) )
   97.89 +            if ( unlikely(!cache_flush_permitted(d)) )
   97.90              {
   97.91                  MEM_LOG("Non-physdev domain tried to FLUSH_CACHE.");
   97.92                  okay = 0;
   97.93 @@ -2498,7 +2497,7 @@ int do_update_va_mapping(unsigned long v
   97.94      l1_pgentry_t   val = l1e_from_intpte(val64);
   97.95      struct vcpu   *v   = current;
   97.96      struct domain *d   = v->domain;
   97.97 -    unsigned int   cpu = v->processor;
   97.98 +    unsigned int   cpu = smp_processor_id();
   97.99      unsigned long  vmask, bmap_ptr;
  97.100      cpumask_t      pmask;
  97.101      int            rc  = 0;
  97.102 @@ -2549,13 +2548,12 @@ int do_update_va_mapping(unsigned long v
  97.103              local_flush_tlb();
  97.104              break;
  97.105          case UVMF_ALL:
  97.106 -            flush_tlb_mask(d->cpumask);
  97.107 +            flush_tlb_mask(d->domain_dirty_cpumask);
  97.108              break;
  97.109          default:
  97.110              if ( unlikely(get_user(vmask, (unsigned long *)bmap_ptr)) )
  97.111                  rc = -EFAULT;
  97.112              pmask = vcpumask_to_pcpumask(d, vmask);
  97.113 -            cpus_and(pmask, pmask, d->cpumask);
  97.114              flush_tlb_mask(pmask);
  97.115              break;
  97.116          }
  97.117 @@ -2570,13 +2568,12 @@ int do_update_va_mapping(unsigned long v
  97.118              local_flush_tlb_one(va);
  97.119              break;
  97.120          case UVMF_ALL:
  97.121 -            flush_tlb_one_mask(d->cpumask, va);
  97.122 +            flush_tlb_one_mask(d->domain_dirty_cpumask, va);
  97.123              break;
  97.124          default:
  97.125              if ( unlikely(get_user(vmask, (unsigned long *)bmap_ptr)) )
  97.126                  rc = -EFAULT;
  97.127              pmask = vcpumask_to_pcpumask(d, vmask);
  97.128 -            cpus_and(pmask, pmask, d->cpumask);
  97.129              flush_tlb_one_mask(pmask, va);
  97.130              break;
  97.131          }
  97.132 @@ -3019,7 +3016,7 @@ void ptwr_flush(struct domain *d, const 
  97.133  
  97.134      /* Ensure that there are no stale writable mappings in any TLB. */
  97.135      /* NB. INVLPG is a serialising instruction: flushes pending updates. */
  97.136 -    flush_tlb_one_mask(d->cpumask, l1va);
  97.137 +    flush_tlb_one_mask(d->domain_dirty_cpumask, l1va);
  97.138      PTWR_PRINTK("[%c] disconnected_l1va at %p now %"PRIpte"\n",
  97.139                  PTWR_PRINT_WHICH, ptep, pte.l1);
  97.140  
  97.141 @@ -3343,7 +3340,7 @@ int ptwr_do_page_fault(struct domain *d,
  97.142      if ( which == PTWR_PT_ACTIVE )
  97.143      {
  97.144          l2e_remove_flags(*pl2e, _PAGE_PRESENT);
  97.145 -        flush_tlb_mask(d->cpumask);
  97.146 +        flush_tlb_mask(d->domain_dirty_cpumask);
  97.147      }
  97.148      
  97.149      /* Temporarily map the L1 page, and make a copy of it. */
  97.150 @@ -3370,7 +3367,7 @@ int ptwr_do_page_fault(struct domain *d,
  97.151  
  97.152   emulate:
  97.153      if ( x86_emulate_memop(guest_cpu_user_regs(), addr,
  97.154 -                           &ptwr_mem_emulator, BITS_PER_LONG/8) )
  97.155 +                           &ptwr_mem_emulator, X86EMUL_MODE_HOST) )
  97.156          return 0;
  97.157      perfc_incrc(ptwr_emulations);
  97.158      return EXCRET_fault_fixed;
    98.1 --- a/xen/arch/x86/physdev.c	Mon Jan 09 11:19:55 2006 +0000
    98.2 +++ b/xen/arch/x86/physdev.c	Mon Jan 09 11:22:17 2006 +0000
    98.3 @@ -14,27 +14,6 @@
    98.4  extern int ioapic_guest_read(int apicid, int address, u32 *pval);
    98.5  extern int ioapic_guest_write(int apicid, int address, u32 pval);
    98.6  
    98.7 -void physdev_modify_ioport_access_range(
    98.8 -    struct domain *d, int enable, int port, int num)
    98.9 -{
   98.10 -    int i;
   98.11 -    for ( i = port; i < (port + num); i++ )
   98.12 -        (enable ? clear_bit : set_bit)(i, d->arch.iobmp_mask);
   98.13 -}
   98.14 -
   98.15 -void physdev_destroy_state(struct domain *d)
   98.16 -{
   98.17 -    xfree(d->arch.iobmp_mask);
   98.18 -    d->arch.iobmp_mask = NULL;
   98.19 -}
   98.20 -
   98.21 -/* Check if a domain controls a device with IO memory within frame @pfn.
   98.22 - * Returns: 1 if the domain should be allowed to map @pfn, 0 otherwise.  */
   98.23 -int domain_iomem_in_pfn(struct domain *p, unsigned long pfn)
   98.24 -{
   98.25 -    return 0;
   98.26 -}
   98.27 -
   98.28  /*
   98.29   * Demuxing hypercall.
   98.30   */
   98.31 @@ -120,18 +99,6 @@ long do_physdev_op(physdev_op_t *uop)
   98.32      return ret;
   98.33  }
   98.34  
   98.35 -/* Domain 0 has read access to all devices. */
   98.36 -void physdev_init_dom0(struct domain *d)
   98.37 -{
   98.38 -    /* Access to all I/O ports. */
   98.39 -    d->arch.iobmp_mask = xmalloc_array(u8, IOBMP_BYTES);
   98.40 -    BUG_ON(d->arch.iobmp_mask == NULL);
   98.41 -    memset(d->arch.iobmp_mask, 0, IOBMP_BYTES);
   98.42 -
   98.43 -    set_bit(_DOMF_physdev_access, &d->domain_flags);
   98.44 -}
   98.45 -
   98.46 -
   98.47  /*
   98.48   * Local variables:
   98.49   * mode: C
    99.1 --- a/xen/arch/x86/setup.c	Mon Jan 09 11:19:55 2006 +0000
    99.2 +++ b/xen/arch/x86/setup.c	Mon Jan 09 11:22:17 2006 +0000
    99.3 @@ -92,7 +92,7 @@ unsigned long mmu_cr4_features = X86_CR4
    99.4  #endif
    99.5  EXPORT_SYMBOL(mmu_cr4_features);
    99.6  
    99.7 -struct vcpu *idle_task[NR_CPUS] = { &idle0_vcpu };
    99.8 +struct vcpu *idle_domain[NR_CPUS] = { &idle0_vcpu };
    99.9  
   99.10  int acpi_disabled;
   99.11  
   99.12 @@ -138,131 +138,19 @@ static void __init do_initcalls(void)
   99.13          (*call)();
   99.14  }
   99.15  
   99.16 -static void __init start_of_day(void)
   99.17 -{
   99.18 -    int i;
   99.19 -    unsigned long vgdt, gdt_pfn;
   99.20 -
   99.21 -    early_cpu_init();
   99.22 -
   99.23 -    paging_init();
   99.24 -
   99.25 -    /* Unmap the first page of CPU0's stack. */
   99.26 -    memguard_guard_stack(cpu0_stack);
   99.27 -
   99.28 -    open_softirq(NEW_TLBFLUSH_CLOCK_PERIOD_SOFTIRQ, new_tlbflush_clock_period);
   99.29 -
   99.30 -    if ( opt_watchdog ) 
   99.31 -        nmi_watchdog = NMI_LOCAL_APIC;
   99.32 -
   99.33 -    sort_exception_tables();
   99.34 -
   99.35 -    arch_do_createdomain(current);
   99.36 -    
   99.37 -    /*
   99.38 -     * Map default GDT into its final positions in the idle page table. As
   99.39 -     * noted in arch_do_createdomain(), we must map for every possible VCPU#.
   99.40 -     */
   99.41 -    vgdt = GDT_VIRT_START(current) + FIRST_RESERVED_GDT_BYTE;
   99.42 -    gdt_pfn = virt_to_phys(gdt_table) >> PAGE_SHIFT;
   99.43 -    for ( i = 0; i < MAX_VIRT_CPUS; i++ )
   99.44 -    {
   99.45 -        map_pages_to_xen(vgdt, gdt_pfn, 1, PAGE_HYPERVISOR);
   99.46 -        vgdt += 1 << PDPT_VCPU_VA_SHIFT;
   99.47 -    }
   99.48 -
   99.49 -    find_smp_config();
   99.50 -
   99.51 -    smp_alloc_memory();
   99.52 -
   99.53 -    dmi_scan_machine();
   99.54 -
   99.55 -    generic_apic_probe();
   99.56 -
   99.57 -    acpi_boot_table_init();
   99.58 -    acpi_boot_init();
   99.59 -
   99.60 -    if ( smp_found_config ) 
   99.61 -        get_smp_config();
   99.62 -
   99.63 -    init_apic_mappings();
   99.64 -
   99.65 -    init_IRQ();
   99.66 -
   99.67 -    trap_init();
   99.68 -
   99.69 -    ac_timer_init();
   99.70 -
   99.71 -    early_time_init();
   99.72 -
   99.73 -    arch_init_memory();
   99.74 -
   99.75 -    scheduler_init();
   99.76 -
   99.77 -    identify_cpu(&boot_cpu_data);
   99.78 -    if ( cpu_has_fxsr )
   99.79 -        set_in_cr4(X86_CR4_OSFXSR);
   99.80 -    if ( cpu_has_xmm )
   99.81 -        set_in_cr4(X86_CR4_OSXMMEXCPT);
   99.82 -
   99.83 -    if ( opt_nosmp )
   99.84 -    {
   99.85 -        max_cpus = 0;
   99.86 -        smp_num_siblings = 1;
   99.87 -        boot_cpu_data.x86_num_cores = 1;
   99.88 -    }
   99.89 -
   99.90 -    smp_prepare_cpus(max_cpus);
   99.91 -
   99.92 -    /* We aren't hotplug-capable yet. */
   99.93 -    BUG_ON(!cpus_empty(cpu_present_map));
   99.94 -    for_each_cpu ( i )
   99.95 -        cpu_set(i, cpu_present_map);
   99.96 -
   99.97 -    /*
   99.98 -     * Initialise higher-level timer functions. We do this fairly late
   99.99 -     * (post-SMP) because the time bases and scale factors need to be updated 
  99.100 -     * regularly, and SMP initialisation can cause a long delay with 
  99.101 -     * interrupts not yet enabled.
  99.102 -     */
  99.103 -    init_xen_time();
  99.104 -
  99.105 -    initialize_keytable();
  99.106 -
  99.107 -    serial_init_postirq();
  99.108 -
  99.109 -    BUG_ON(!local_irq_is_enabled());
  99.110 -
  99.111 -    for_each_present_cpu ( i )
  99.112 -    {
  99.113 -        if ( num_online_cpus() >= max_cpus )
  99.114 -            break;
  99.115 -        if ( !cpu_online(i) )
  99.116 -            __cpu_up(i);
  99.117 -    }
  99.118 -
  99.119 -    printk("Brought up %ld CPUs\n", (long)num_online_cpus());
  99.120 -    smp_cpus_done(max_cpus);
  99.121 -
  99.122 -    do_initcalls();
  99.123 -
  99.124 -    schedulers_start();
  99.125 -
  99.126 -    watchdog_enable();
  99.127 -}
  99.128 -
  99.129  #define EARLY_FAIL() for ( ; ; ) __asm__ __volatile__ ( "hlt" )
  99.130  
  99.131  static struct e820entry e820_raw[E820MAX];
  99.132  
  99.133  void __init __start_xen(multiboot_info_t *mbi)
  99.134  {
  99.135 +    unsigned long vgdt, gdt_pfn;
  99.136      char *cmdline;
  99.137 +    unsigned long _initrd_start = 0, _initrd_len = 0;
  99.138 +    unsigned int initrdidx = 1;
  99.139      module_t *mod = (module_t *)__va(mbi->mods_addr);
  99.140      unsigned long nr_pages, modules_length;
  99.141      unsigned long initial_images_start, initial_images_end;
  99.142 -    unsigned long _initrd_start = 0, _initrd_len = 0;
  99.143 -    unsigned int initrdidx = 1;
  99.144      physaddr_t s, e;
  99.145      int i, e820_warn = 0, e820_raw_nr = 0, bytes = 0;
  99.146      struct ns16550_defaults ns16550 = {
  99.147 @@ -455,6 +343,12 @@ void __init __start_xen(multiboot_info_t
  99.148      BUG_ON(sizeof(shared_info_t) > PAGE_SIZE);
  99.149      BUG_ON(sizeof(vcpu_info_t) != 64);
  99.150  
  99.151 +    /* __foo are defined in public headers. Check they match internal defs. */
  99.152 +    BUG_ON(__HYPERVISOR_VIRT_START != HYPERVISOR_VIRT_START);
  99.153 +#ifdef HYPERVISOR_VIRT_END
  99.154 +    BUG_ON(__HYPERVISOR_VIRT_END   != HYPERVISOR_VIRT_END);
  99.155 +#endif
  99.156 +
  99.157      init_frametable();
  99.158  
  99.159      end_boot_allocator();
  99.160 @@ -486,7 +380,113 @@ void __init __start_xen(multiboot_info_t
  99.161  
  99.162      early_boot = 0;
  99.163  
  99.164 -    start_of_day();
  99.165 +    early_cpu_init();
  99.166 +
  99.167 +    paging_init();
  99.168 +
  99.169 +    /* Unmap the first page of CPU0's stack. */
  99.170 +    memguard_guard_stack(cpu0_stack);
  99.171 +
  99.172 +    open_softirq(NEW_TLBFLUSH_CLOCK_PERIOD_SOFTIRQ, new_tlbflush_clock_period);
  99.173 +
  99.174 +    if ( opt_watchdog ) 
  99.175 +        nmi_watchdog = NMI_LOCAL_APIC;
  99.176 +
  99.177 +    sort_exception_tables();
  99.178 +
  99.179 +    if ( arch_do_createdomain(current) != 0 )
  99.180 +        BUG();
  99.181 +
  99.182 +    /*
  99.183 +     * Map default GDT into its final positions in the idle page table. As
  99.184 +     * noted in arch_do_createdomain(), we must map for every possible VCPU#.
  99.185 +     */
  99.186 +    vgdt = GDT_VIRT_START(current) + FIRST_RESERVED_GDT_BYTE;
  99.187 +    gdt_pfn = virt_to_phys(gdt_table) >> PAGE_SHIFT;
  99.188 +    for ( i = 0; i < MAX_VIRT_CPUS; i++ )
  99.189 +    {
  99.190 +        map_pages_to_xen(vgdt, gdt_pfn, 1, PAGE_HYPERVISOR);
  99.191 +        vgdt += 1 << PDPT_VCPU_VA_SHIFT;
  99.192 +    }
  99.193 +
  99.194 +    find_smp_config();
  99.195 +
  99.196 +    smp_alloc_memory();
  99.197 +
  99.198 +    dmi_scan_machine();
  99.199 +
  99.200 +    generic_apic_probe();
  99.201 +
  99.202 +    acpi_boot_table_init();
  99.203 +    acpi_boot_init();
  99.204 +
  99.205 +    if ( smp_found_config ) 
  99.206 +        get_smp_config();
  99.207 +
  99.208 +    init_apic_mappings();
  99.209 +
  99.210 +    init_IRQ();
  99.211 +
  99.212 +    trap_init();
  99.213 +
  99.214 +    ac_timer_init();
  99.215 +
  99.216 +    early_time_init();
  99.217 +
  99.218 +    arch_init_memory();
  99.219 +
  99.220 +    scheduler_init();
  99.221 +
  99.222 +    identify_cpu(&boot_cpu_data);
  99.223 +    if ( cpu_has_fxsr )
  99.224 +        set_in_cr4(X86_CR4_OSFXSR);
  99.225 +    if ( cpu_has_xmm )
  99.226 +        set_in_cr4(X86_CR4_OSXMMEXCPT);
  99.227 +
  99.228 +    if ( opt_nosmp )
  99.229 +    {
  99.230 +        max_cpus = 0;
  99.231 +        smp_num_siblings = 1;
  99.232 +        boot_cpu_data.x86_num_cores = 1;
  99.233 +    }
  99.234 +
  99.235 +    smp_prepare_cpus(max_cpus);
  99.236 +
  99.237 +    /* We aren't hotplug-capable yet. */
  99.238 +    BUG_ON(!cpus_empty(cpu_present_map));
  99.239 +    for_each_cpu ( i )
  99.240 +        cpu_set(i, cpu_present_map);
  99.241 +
  99.242 +    /*
  99.243 +     * Initialise higher-level timer functions. We do this fairly late
  99.244 +     * (post-SMP) because the time bases and scale factors need to be updated 
  99.245 +     * regularly, and SMP initialisation can cause a long delay with 
  99.246 +     * interrupts not yet enabled.
  99.247 +     */
  99.248 +    init_xen_time();
  99.249 +
  99.250 +    initialize_keytable();
  99.251 +
  99.252 +    serial_init_postirq();
  99.253 +
  99.254 +    BUG_ON(!local_irq_is_enabled());
  99.255 +
  99.256 +    for_each_present_cpu ( i )
  99.257 +    {
  99.258 +        if ( num_online_cpus() >= max_cpus )
  99.259 +            break;
  99.260 +        if ( !cpu_online(i) )
  99.261 +            __cpu_up(i);
  99.262 +    }
  99.263 +
  99.264 +    printk("Brought up %ld CPUs\n", (long)num_online_cpus());
  99.265 +    smp_cpus_done(max_cpus);
  99.266 +
  99.267 +    do_initcalls();
  99.268 +
  99.269 +    schedulers_start();
  99.270 +
  99.271 +    watchdog_enable();
  99.272  
  99.273      shadow_mode_init();
  99.274  
   100.1 --- a/xen/arch/x86/shadow.c	Mon Jan 09 11:19:55 2006 +0000
   100.2 +++ b/xen/arch/x86/shadow.c	Mon Jan 09 11:22:17 2006 +0000
   100.3 @@ -1800,7 +1800,7 @@ static void sync_all(struct domain *d)
   100.4      }
   100.5  
   100.6      /* Other VCPUs mustn't use the revoked writable mappings. */
   100.7 -    other_vcpus_mask = d->cpumask;
   100.8 +    other_vcpus_mask = d->domain_dirty_cpumask;
   100.9      cpu_clear(smp_processor_id(), other_vcpus_mask);
  100.10      flush_tlb_mask(other_vcpus_mask);
  100.11  
   101.1 --- a/xen/arch/x86/shadow32.c	Mon Jan 09 11:19:55 2006 +0000
   101.2 +++ b/xen/arch/x86/shadow32.c	Mon Jan 09 11:22:17 2006 +0000
   101.3 @@ -2586,7 +2586,7 @@ void __shadow_sync_all(struct domain *d)
   101.4      }
   101.5  
   101.6      /* Other VCPUs mustn't use the revoked writable mappings. */
   101.7 -    other_vcpus_mask = d->cpumask;
   101.8 +    other_vcpus_mask = d->domain_dirty_cpumask;
   101.9      cpu_clear(smp_processor_id(), other_vcpus_mask);
  101.10      flush_tlb_mask(other_vcpus_mask);
  101.11  
   102.1 --- a/xen/arch/x86/smpboot.c	Mon Jan 09 11:19:55 2006 +0000
   102.2 +++ b/xen/arch/x86/smpboot.c	Mon Jan 09 11:22:17 2006 +0000
   102.3 @@ -435,7 +435,7 @@ void __init start_secondary(void *unused
   102.4  
   102.5  	extern void percpu_traps_init(void);
   102.6  
   102.7 -	set_current(idle_task[cpu]);
   102.8 +	set_current(idle_domain[cpu]);
   102.9  	set_processor_id(cpu);
  102.10  
  102.11  	percpu_traps_init();
  102.12 @@ -763,7 +763,6 @@ static int __init do_boot_cpu(int apicid
  102.13  {
  102.14  	struct domain *idle;
  102.15  	struct vcpu *v;
  102.16 -	void *stack;
  102.17  	unsigned long boot_error;
  102.18  	int timeout, cpu;
  102.19  	unsigned long start_eip;
  102.20 @@ -774,7 +773,7 @@ static int __init do_boot_cpu(int apicid
  102.21  	if ( (idle = do_createdomain(IDLE_DOMAIN_ID, cpu)) == NULL )
  102.22  		panic("failed 'createdomain' for CPU %d", cpu);
  102.23  
  102.24 -	v = idle_task[cpu] = idle->vcpu[0];
  102.25 +	v = idle_domain[cpu] = idle->vcpu[0];
  102.26  
  102.27  	set_bit(_DOMF_idle_domain, &idle->domain_flags);
  102.28  
  102.29 @@ -786,16 +785,10 @@ static int __init do_boot_cpu(int apicid
  102.30  	/* So we see what's up   */
  102.31  	printk("Booting processor %d/%d eip %lx\n", cpu, apicid, start_eip);
  102.32  
  102.33 -	stack = alloc_xenheap_pages(STACK_ORDER);
  102.34 -#if defined(__i386__)
  102.35 -	stack_start.esp = (void *)__pa(stack);
  102.36 -#elif defined(__x86_64__)
  102.37 -	stack_start.esp = stack;
  102.38 -#endif
  102.39 -	stack_start.esp += STACK_SIZE - sizeof(struct cpu_info);
  102.40 +	stack_start.esp = alloc_xenheap_pages(STACK_ORDER);
  102.41  
  102.42  	/* Debug build: detect stack overflow by setting up a guard page. */
  102.43 -	memguard_guard_stack(stack);
  102.44 +	memguard_guard_stack(stack_start.esp);
  102.45  
  102.46  	/*
  102.47  	 * This grunge runs the startup process for
   103.1 --- a/xen/arch/x86/traps.c	Mon Jan 09 11:19:55 2006 +0000
   103.2 +++ b/xen/arch/x86/traps.c	Mon Jan 09 11:22:17 2006 +0000
   103.3 @@ -41,6 +41,7 @@
   103.4  #include <xen/softirq.h>
   103.5  #include <xen/domain_page.h>
   103.6  #include <xen/symbols.h>
   103.7 +#include <xen/iocap.h>
   103.8  #include <asm/shadow.h>
   103.9  #include <asm/system.h>
  103.10  #include <asm/io.h>
  103.11 @@ -192,7 +193,8 @@ static void show_trace(struct cpu_user_r
  103.12  
  103.13      /* Bounds for range of valid frame pointer. */
  103.14      low  = (unsigned long)(ESP_BEFORE_EXCEPTION(regs) - 2);
  103.15 -    high = (low & ~(STACK_SIZE - 1)) + (STACK_SIZE - sizeof(struct cpu_info));
  103.16 +    high = (low & ~(STACK_SIZE - 1)) + 
  103.17 +        (STACK_SIZE - sizeof(struct cpu_info) - 2*sizeof(unsigned long));
  103.18  
  103.19      /* The initial frame pointer. */
  103.20      next = regs->ebp;
  103.21 @@ -200,14 +202,14 @@ static void show_trace(struct cpu_user_r
  103.22      for ( ; ; )
  103.23      {
  103.24          /* Valid frame pointer? */
  103.25 -        if ( (next < low) || (next > high) )
  103.26 +        if ( (next < low) || (next >= high) )
  103.27          {
  103.28              /*
  103.29               * Exception stack frames have a different layout, denoted by an
  103.30               * inverted frame pointer.
  103.31               */
  103.32              next = ~next;
  103.33 -            if ( (next < low) || (next > high) )
  103.34 +            if ( (next < low) || (next >= high) )
  103.35                  break;
  103.36              frame = (unsigned long *)next;
  103.37              next  = frame[0];
  103.38 @@ -621,17 +623,7 @@ static inline int admin_io_okay(
  103.39      unsigned int port, unsigned int bytes,
  103.40      struct vcpu *v, struct cpu_user_regs *regs)
  103.41  {
  103.42 -    struct domain *d = v->domain;
  103.43 -    u16 x;
  103.44 -
  103.45 -    if ( d->arch.iobmp_mask != NULL )
  103.46 -    {
  103.47 -        x = *(u16 *)(d->arch.iobmp_mask + (port >> 3));
  103.48 -        if ( (x & (((1<<bytes)-1) << (port&7))) == 0 )
  103.49 -            return 1;
  103.50 -    }
  103.51 -
  103.52 -    return 0;
  103.53 +    return ioports_access_permitted(v->domain, port, port + bytes - 1);
  103.54  }
  103.55  
  103.56  /* Check admin limits. Silently fail the access if it is disallowed. */
  103.57 @@ -871,7 +863,7 @@ static int emulate_privileged_op(struct 
  103.58  
  103.59      case 0x09: /* WBINVD */
  103.60          /* Ignore the instruction if unprivileged. */
  103.61 -        if ( !IS_CAPABLE_PHYSDEV(v->domain) )
  103.62 +        if ( !cache_flush_permitted(v->domain) )
  103.63              DPRINTK("Non-physdev domain attempted WBINVD.\n");
  103.64          else
  103.65              wbinvd();
  103.66 @@ -885,7 +877,8 @@ static int emulate_privileged_op(struct 
  103.67          switch ( modrm_reg )
  103.68          {
  103.69          case 0: /* Read CR0 */
  103.70 -            *reg = v->arch.guest_context.ctrlreg[0];
  103.71 +            *reg = (read_cr0() & ~X86_CR0_TS) |
  103.72 +                v->arch.guest_context.ctrlreg[0];
  103.73              break;
  103.74  
  103.75          case 2: /* Read CR2 */
  103.76 @@ -927,6 +920,11 @@ static int emulate_privileged_op(struct 
  103.77          switch ( modrm_reg )
  103.78          {
  103.79          case 0: /* Write CR0 */
  103.80 +            if ( (*reg ^ read_cr0()) & ~X86_CR0_TS )
  103.81 +            {
  103.82 +                DPRINTK("Attempt to change unmodifiable CR0 flags.\n");
  103.83 +                goto fail;
  103.84 +            }
  103.85              (void)do_fpu_taskswitch(!!(*reg & X86_CR0_TS));
  103.86              break;
  103.87  
  103.88 @@ -941,6 +939,14 @@ static int emulate_privileged_op(struct 
  103.89              UNLOCK_BIGLOCK(v->domain);
  103.90              break;
  103.91  
  103.92 +        case 4:
  103.93 +            if ( *reg != (read_cr4() & ~(X86_CR4_PGE|X86_CR4_PSE)) )
  103.94 +            {
  103.95 +                DPRINTK("Attempt to change CR4 flags.\n");
  103.96 +                goto fail;
  103.97 +            }
  103.98 +            break;
  103.99 +
 103.100          default:
 103.101              goto fail;
 103.102          }
   104.1 --- a/xen/arch/x86/vmx.c	Mon Jan 09 11:19:55 2006 +0000
   104.2 +++ b/xen/arch/x86/vmx.c	Mon Jan 09 11:22:17 2006 +0000
   104.3 @@ -42,7 +42,7 @@
   104.4  #include <asm/shadow_64.h>
   104.5  #endif
   104.6  #include <public/sched.h>
   104.7 -#include <public/io/ioreq.h>
   104.8 +#include <public/hvm/ioreq.h>
   104.9  #include <asm/vmx_vpic.h>
  104.10  #include <asm/vmx_vlapic.h>
  104.11  
  104.12 @@ -53,7 +53,7 @@ unsigned int opt_vmx_debug_level = 0;
  104.13  integer_param("vmx_debug", opt_vmx_debug_level);
  104.14  
  104.15  static unsigned long trace_values[NR_CPUS][4];
  104.16 -#define TRACE_VMEXIT(index,value) trace_values[current->processor][index]=value
  104.17 +#define TRACE_VMEXIT(index,value) trace_values[smp_processor_id()][index]=value
  104.18  
  104.19  static int vmx_switch_on;
  104.20  
  104.21 @@ -66,11 +66,6 @@ void vmx_final_setup_guest(struct vcpu *
  104.22          struct domain *d = v->domain;
  104.23          struct vcpu *vc;
  104.24  
  104.25 -        d->arch.vmx_platform.lapic_enable = v->arch.guest_context.user_regs.ecx;
  104.26 -        v->arch.guest_context.user_regs.ecx = 0;
  104.27 -        VMX_DBG_LOG(DBG_LEVEL_VLAPIC, "lapic enable is %d.\n",
  104.28 -                    d->arch.vmx_platform.lapic_enable);
  104.29 -
  104.30          /* Initialize monitor page table */
  104.31          for_each_vcpu(d, vc)
  104.32              vc->arch.monitor_table = mk_pagetable(0);
  104.33 @@ -95,7 +90,7 @@ void vmx_final_setup_guest(struct vcpu *
  104.34  void vmx_relinquish_resources(struct vcpu *v)
  104.35  {
  104.36      struct vmx_virpit *vpit;
  104.37 -    
  104.38 +
  104.39      if ( !VMX_DOMAIN(v) )
  104.40          return;
  104.41  
  104.42 @@ -1955,9 +1950,12 @@ asmlinkage void load_cr2(void)
  104.43  
  104.44  asmlinkage void trace_vmentry (void)
  104.45  {
  104.46 -    TRACE_5D(TRC_VMENTRY,trace_values[current->processor][0],
  104.47 -             trace_values[current->processor][1],trace_values[current->processor][2],
  104.48 -             trace_values[current->processor][3],trace_values[current->processor][4]);
  104.49 +    TRACE_5D(TRC_VMENTRY,
  104.50 +             trace_values[smp_processor_id()][0],
  104.51 +             trace_values[smp_processor_id()][1],
  104.52 +             trace_values[smp_processor_id()][2],
  104.53 +             trace_values[smp_processor_id()][3],
  104.54 +             trace_values[smp_processor_id()][4]);
  104.55      TRACE_VMEXIT(0,9);
  104.56      TRACE_VMEXIT(1,9);
  104.57      TRACE_VMEXIT(2,9);
   105.1 --- a/xen/arch/x86/vmx_intercept.c	Mon Jan 09 11:19:55 2006 +0000
   105.2 +++ b/xen/arch/x86/vmx_intercept.c	Mon Jan 09 11:22:17 2006 +0000
   105.3 @@ -24,7 +24,7 @@
   105.4  #include <asm/vmx_vpit.h>
   105.5  #include <asm/vmx_intercept.h>
   105.6  #include <asm/vmx_vlapic.h>
   105.7 -#include <public/io/ioreq.h>
   105.8 +#include <public/hvm/ioreq.h>
   105.9  #include <xen/lib.h>
  105.10  #include <xen/sched.h>
  105.11  #include <asm/current.h>
   106.1 --- a/xen/arch/x86/vmx_io.c	Mon Jan 09 11:19:55 2006 +0000
   106.2 +++ b/xen/arch/x86/vmx_io.c	Mon Jan 09 11:22:17 2006 +0000
   106.3 @@ -37,7 +37,7 @@
   106.4  #include <asm/shadow.h>
   106.5  #include <asm/vmx_vpic.h>
   106.6  #include <asm/vmx_vlapic.h>
   106.7 -#include <public/io/ioreq.h>
   106.8 +#include <public/hvm/ioreq.h>
   106.9  
  106.10  #ifdef CONFIG_VMX
  106.11  #if defined (__i386__)
   107.1 --- a/xen/arch/x86/vmx_platform.c	Mon Jan 09 11:19:55 2006 +0000
   107.2 +++ b/xen/arch/x86/vmx_platform.c	Mon Jan 09 11:22:17 2006 +0000
   107.3 @@ -27,7 +27,7 @@
   107.4  #include <xen/trace.h>
   107.5  #include <asm/vmx.h>
   107.6  #include <asm/vmx_platform.h>
   107.7 -#include <public/io/ioreq.h>
   107.8 +#include <public/hvm/ioreq.h>
   107.9  
  107.10  #include <xen/lib.h>
  107.11  #include <xen/sched.h>
   108.1 --- a/xen/arch/x86/vmx_vlapic.c	Mon Jan 09 11:19:55 2006 +0000
   108.2 +++ b/xen/arch/x86/vmx_vlapic.c	Mon Jan 09 11:22:17 2006 +0000
   108.3 @@ -32,7 +32,7 @@
   108.4  #include <xen/lib.h>
   108.5  #include <xen/sched.h>
   108.6  #include <asm/current.h>
   108.7 -#include <public/io/ioreq.h>
   108.8 +#include <public/hvm/ioreq.h>
   108.9  
  108.10  #ifdef CONFIG_VMX
  108.11  
  108.12 @@ -62,7 +62,7 @@ int vlapic_find_highest_irr(struct vlapi
  108.13  
  108.14  int vmx_apic_support(struct domain *d)
  108.15  {
  108.16 -    return d->arch.vmx_platform.lapic_enable;
  108.17 +    return d->arch.vmx_platform.apic_enabled;
  108.18  }
  108.19  
  108.20  s_time_t get_apictime_scheduled(struct vcpu *v)
   109.1 --- a/xen/arch/x86/vmx_vmcs.c	Mon Jan 09 11:19:55 2006 +0000
   109.2 +++ b/xen/arch/x86/vmx_vmcs.c	Mon Jan 09 11:22:17 2006 +0000
   109.3 @@ -32,7 +32,7 @@
   109.4  #include <asm/flushtlb.h>
   109.5  #include <xen/event.h>
   109.6  #include <xen/kernel.h>
   109.7 -#include <public/io/ioreq.h>
   109.8 +#include <public/hvm/hvm_info_table.h>
   109.9  #if CONFIG_PAGING_LEVELS >= 4
  109.10  #include <asm/shadow_64.h>
  109.11  #endif
  109.12 @@ -206,36 +206,56 @@ static void vmx_map_io_shared_page(struc
  109.13                &d->shared_info->evtchn_mask[0]);
  109.14  }
  109.15  
  109.16 -#define VCPU_NR_PAGE        0x0009F000
  109.17 -#define VCPU_NR_OFFSET      0x00000800
  109.18 -#define VCPU_MAGIC          0x76637075  /* "vcpu" */
  109.19 +static int validate_hvm_info(struct hvm_info_table *t)
  109.20 +{
  109.21 +    char signature[] = "HVM INFO";
  109.22 +    uint8_t *ptr = (uint8_t *)t;
  109.23 +    uint8_t sum = 0;
  109.24 +    int i;
  109.25  
  109.26 -static void vmx_set_vcpu_nr(struct domain *d)
  109.27 +    /* strncmp(t->signature, "HVM INFO", 8) */
  109.28 +    for ( i = 0; i < 8; i++ ) {
  109.29 +        if ( signature[i] != t->signature[i] ) {
  109.30 +            printk("Bad hvm info signature\n");
  109.31 +            return 0;
  109.32 +        }
  109.33 +    }
  109.34 +
  109.35 +    for ( i = 0; i < t->length; i++ )
  109.36 +        sum += ptr[i];
  109.37 +
  109.38 +    return (sum == 0);
  109.39 +}
  109.40 +
  109.41 +static void vmx_get_hvm_info(struct domain *d)
  109.42  {
  109.43      unsigned char *p;
  109.44      unsigned long mpfn;
  109.45 -    unsigned int *vcpus;
  109.46 +    struct hvm_info_table *t;
  109.47  
  109.48 -    mpfn = get_mfn_from_pfn(VCPU_NR_PAGE >> PAGE_SHIFT);
  109.49 -    if (mpfn == INVALID_MFN) {
  109.50 -        printk("Can not get vcpu number page mfn for VMX domain.\n");
  109.51 +    mpfn = get_mfn_from_pfn(HVM_INFO_PFN);
  109.52 +    if ( mpfn == INVALID_MFN ) {
  109.53 +        printk("Can not get hvm info page mfn for VMX domain.\n");
  109.54          domain_crash_synchronous();
  109.55      }
  109.56  
  109.57      p = map_domain_page(mpfn);
  109.58 -    if (p == NULL) {
  109.59 -        printk("Can not map vcpu number page for VMX domain.\n");
  109.60 +    if ( p == NULL ) {
  109.61 +        printk("Can not map hvm info page for VMX domain.\n");
  109.62          domain_crash_synchronous();
  109.63      }
  109.64  
  109.65 -    vcpus = (unsigned int *)(p + VCPU_NR_OFFSET);
  109.66 -    if (vcpus[0] != VCPU_MAGIC) {
  109.67 -        printk("Bad vcpus magic, set vcpu number to 1 by default.\n");
  109.68 -        d->arch.vmx_platform.nr_vcpu = 1;
  109.69 +    t = (struct hvm_info_table *)(p + HVM_INFO_OFFSET);
  109.70 +
  109.71 +    if ( validate_hvm_info(t) ) {
  109.72 +        d->arch.vmx_platform.nr_vcpus = t->nr_vcpus;
  109.73 +        d->arch.vmx_platform.apic_enabled = t->apic_enabled;
  109.74 +    } else {
  109.75 +        printk("Bad hvm info table\n");
  109.76 +        d->arch.vmx_platform.nr_vcpus = 1;
  109.77 +        d->arch.vmx_platform.apic_enabled = 0;
  109.78      }
  109.79  
  109.80 -    d->arch.vmx_platform.nr_vcpu = vcpus[1];
  109.81 -
  109.82      unmap_domain_page(p);
  109.83  }
  109.84  
  109.85 @@ -244,10 +264,10 @@ static void vmx_setup_platform(struct do
  109.86      struct vmx_platform *platform;
  109.87  
  109.88      vmx_map_io_shared_page(d);
  109.89 -    vmx_set_vcpu_nr(d);
  109.90 +    vmx_get_hvm_info(d);
  109.91  
  109.92      platform = &d->arch.vmx_platform;
  109.93 -    pic_init(&platform->vmx_pic,  pic_irq_request, 
  109.94 +    pic_init(&platform->vmx_pic,  pic_irq_request,
  109.95               &platform->interrupt_request);
  109.96      register_pic_io_hook();
  109.97  
  109.98 @@ -335,6 +355,8 @@ static void vmx_do_launch(struct vcpu *v
  109.99      __vmwrite(HOST_RSP, (unsigned long)get_stack_bottom());
 109.100  
 109.101      v->arch.schedule_tail = arch_vmx_do_resume;
 109.102 +    v->arch.arch_vmx.launch_cpu = smp_processor_id();
 109.103 +
 109.104      /* init guest tsc to start from 0 */
 109.105      rdtscll(host_tsc);
 109.106      v->arch.arch_vmx.tsc_offset = 0 - host_tsc;
 109.107 @@ -617,11 +639,21 @@ void vm_resume_fail(unsigned long eflags
 109.108  
 109.109  void arch_vmx_do_resume(struct vcpu *v)
 109.110  {
 109.111 -    u64 vmcs_phys_ptr = (u64) virt_to_phys(v->arch.arch_vmx.vmcs);
 109.112 -
 109.113 -    load_vmcs(&v->arch.arch_vmx, vmcs_phys_ptr);
 109.114 -    vmx_do_resume(v);
 109.115 -    reset_stack_and_jump(vmx_asm_do_resume);
 109.116 +    if ( v->arch.arch_vmx.launch_cpu == smp_processor_id() )
 109.117 +    {
 109.118 +        load_vmcs(&v->arch.arch_vmx, virt_to_phys(v->arch.arch_vmx.vmcs));
 109.119 +        vmx_do_resume(v);
 109.120 +        reset_stack_and_jump(vmx_asm_do_resume);
 109.121 +    }
 109.122 +    else
 109.123 +    {
 109.124 +        __vmpclear(virt_to_phys(v->arch.arch_vmx.vmcs));
 109.125 +        load_vmcs(&v->arch.arch_vmx, virt_to_phys(v->arch.arch_vmx.vmcs));
 109.126 +        vmx_do_resume(v);
 109.127 +        vmx_set_host_env(v);
 109.128 +        v->arch.arch_vmx.launch_cpu = smp_processor_id();
 109.129 +        reset_stack_and_jump(vmx_asm_do_relaunch);
 109.130 +    }
 109.131  }
 109.132  
 109.133  void arch_vmx_do_launch(struct vcpu *v)
 109.134 @@ -643,18 +675,6 @@ void arch_vmx_do_launch(struct vcpu *v)
 109.135      reset_stack_and_jump(vmx_asm_do_launch);
 109.136  }
 109.137  
 109.138 -void arch_vmx_do_relaunch(struct vcpu *v)
 109.139 -{
 109.140 -    u64 vmcs_phys_ptr = (u64) virt_to_phys(v->arch.arch_vmx.vmcs);
 109.141 -
 109.142 -    load_vmcs(&v->arch.arch_vmx, vmcs_phys_ptr);
 109.143 -    vmx_do_resume(v);
 109.144 -    vmx_set_host_env(v);
 109.145 -    v->arch.schedule_tail = arch_vmx_do_resume;
 109.146 -
 109.147 -    reset_stack_and_jump(vmx_asm_do_relaunch);
 109.148 -}
 109.149 -
 109.150  #endif /* CONFIG_VMX */
 109.151  
 109.152  /*
   110.1 --- a/xen/arch/x86/x86_32/xen.lds	Mon Jan 09 11:19:55 2006 +0000
   110.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   110.3 @@ -1,79 +0,0 @@
   110.4 -/* ld script to make i386 Linux kernel
   110.5 - * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>
   110.6 - * Modified for i386 Xen by Keir Fraser
   110.7 - */
   110.8 -OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
   110.9 -OUTPUT_ARCH(i386)
  110.10 -ENTRY(start)
  110.11 -PHDRS
  110.12 -{
  110.13 -  text PT_LOAD ;
  110.14 -}
  110.15 -SECTIONS
  110.16 -{
  110.17 -  . = 0xFF000000 + 0x100000;
  110.18 -  _text = .;			/* Text and read-only data */
  110.19 -  .text : {
  110.20 -	*(.text)
  110.21 -	*(.fixup)
  110.22 -	*(.gnu.warning)
  110.23 -	} :text =0x9090
  110.24 -  .text.lock : { *(.text.lock) } :text	/* out-of-line lock text */
  110.25 -
  110.26 -  _etext = .;			/* End of text section */
  110.27 -
  110.28 -  .rodata : { *(.rodata) *(.rodata.*) } :text
  110.29 -
  110.30 -  . = ALIGN(32);		/* Exception table */
  110.31 -  __start___ex_table = .;
  110.32 -  __ex_table : { *(__ex_table) } :text
  110.33 -  __stop___ex_table = .;
  110.34 -
  110.35 -  . = ALIGN(32);		/* Pre-exception table */
  110.36 -  __start___pre_ex_table = .;
  110.37 -  __pre_ex_table : { *(__pre_ex_table) } :text
  110.38 -  __stop___pre_ex_table = .;
  110.39 -
  110.40 -  .data : {			/* Data */
  110.41 -	*(.data)
  110.42 -	CONSTRUCTORS
  110.43 -	} :text
  110.44 -
  110.45 -  . = ALIGN(4096);		/* Init code and data */
  110.46 -  __init_begin = .;
  110.47 -  .text.init : { *(.text.init) } :text
  110.48 -  .data.init : { *(.data.init) } :text
  110.49 -  . = ALIGN(32);
  110.50 -  __setup_start = .;
  110.51 -  .setup.init : { *(.setup.init) } :text
  110.52 -  __setup_end = .;
  110.53 -  __initcall_start = .;
  110.54 -  .initcall.init : { *(.initcall.init) } :text
  110.55 -  __initcall_end = .;
  110.56 -  . = ALIGN(8192);
  110.57 -  __init_end = .;
  110.58 -
  110.59 -  __bss_start = .;		/* BSS */
  110.60 -  .bss : {
  110.61 -	*(.bss.twopage_aligned)
  110.62 -	*(.bss.page_aligned)
  110.63 -	*(.bss)
  110.64 -	} :text
  110.65 -  _end = . ;
  110.66 -
  110.67 -  /* Sections to be discarded */
  110.68 -  /DISCARD/ : {
  110.69 -	*(.text.exit)
  110.70 -	*(.data.exit)
  110.71 -	*(.exitcall.exit)
  110.72 -	}
  110.73 -
  110.74 -  /* Stabs debugging sections.  */
  110.75 -  .stab 0 : { *(.stab) }
  110.76 -  .stabstr 0 : { *(.stabstr) }
  110.77 -  .stab.excl 0 : { *(.stab.excl) }
  110.78 -  .stab.exclstr 0 : { *(.stab.exclstr) }
  110.79 -  .stab.index 0 : { *(.stab.index) }
  110.80 -  .stab.indexstr 0 : { *(.stab.indexstr) }
  110.81 -  .comment 0 : { *(.comment) }
  110.82 -}
   111.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   111.2 +++ b/xen/arch/x86/x86_32/xen.lds.S	Mon Jan 09 11:22:17 2006 +0000
   111.3 @@ -0,0 +1,85 @@
   111.4 +/* ld script to make i386 Linux kernel
   111.5 + * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>
   111.6 + * Modified for i386 Xen by Keir Fraser
   111.7 + */
   111.8 +
   111.9 +#include <xen/config.h>
  111.10 +#include <asm/page.h>
  111.11 +#undef ENTRY
  111.12 +#undef ALIGN
  111.13 +
  111.14 +OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
  111.15 +OUTPUT_ARCH(i386)
  111.16 +ENTRY(start)
  111.17 +PHDRS
  111.18 +{
  111.19 +  text PT_LOAD ;
  111.20 +}
  111.21 +SECTIONS
  111.22 +{
  111.23 +  . = 0xFF000000 + 0x100000;
  111.24 +  _text = .;			/* Text and read-only data */
  111.25 +  .text : {
  111.26 +	*(.text)
  111.27 +	*(.fixup)
  111.28 +	*(.gnu.warning)
  111.29 +	} :text =0x9090
  111.30 +  .text.lock : { *(.text.lock) } :text	/* out-of-line lock text */
  111.31 +
  111.32 +  _etext = .;			/* End of text section */
  111.33 +
  111.34 +  .rodata : { *(.rodata) *(.rodata.*) } :text
  111.35 +
  111.36 +  . = ALIGN(32);		/* Exception table */
  111.37 +  __start___ex_table = .;
  111.38 +  __ex_table : { *(__ex_table) } :text
  111.39 +  __stop___ex_table = .;
  111.40 +
  111.41 +  . = ALIGN(32);		/* Pre-exception table */
  111.42 +  __start___pre_ex_table = .;
  111.43 +  __pre_ex_table : { *(__pre_ex_table) } :text
  111.44 +  __stop___pre_ex_table = .;
  111.45 +
  111.46 +  .data : {			/* Data */
  111.47 +	*(.data)
  111.48 +	CONSTRUCTORS
  111.49 +	} :text
  111.50 +
  111.51 +  . = ALIGN(4096);		/* Init code and data */
  111.52 +  __init_begin = .;
  111.53 +  .text.init : { *(.text.init) } :text
  111.54 +  .data.init : { *(.data.init) } :text
  111.55 +  . = ALIGN(32);
  111.56 +  __setup_start = .;
  111.57 +  .setup.init : { *(.setup.init) } :text
  111.58 +  __setup_end = .;
  111.59 +  __initcall_start = .;
  111.60 +  .initcall.init : { *(.initcall.init) } :text
  111.61 +  __initcall_end = .;
  111.62 +  . = ALIGN(STACK_SIZE);
  111.63 +  __init_end = .;
  111.64 +
  111.65 +  __bss_start = .;		/* BSS */
  111.66 +  .bss : {
  111.67 +	*(.bss.stack_aligned)
  111.68 +	*(.bss.page_aligned)
  111.69 +	*(.bss)
  111.70 +	} :text
  111.71 +  _end = . ;
  111.72 +
  111.73 +  /* Sections to be discarded */
  111.74 +  /DISCARD/ : {
  111.75 +	*(.text.exit)
  111.76 +	*(.data.exit)
  111.77 +	*(.exitcall.exit)
  111.78 +	}
  111.79 +
  111.80 +  /* Stabs debugging sections.  */
  111.81 +  .stab 0 : { *(.stab) }
  111.82 +  .stabstr 0 : { *(.stabstr) }
  111.83 +  .stab.excl 0 : { *(.stab.excl) }
  111.84 +  .stab.exclstr 0 : { *(.stab.exclstr) }
  111.85 +  .stab.index 0 : { *(.stab.index) }
  111.86 +  .stab.indexstr 0 : { *(.stab.indexstr) }
  111.87 +  .comment 0 : { *(.comment) }
  111.88 +}
   112.1 --- a/xen/arch/x86/x86_64/xen.lds	Mon Jan 09 11:19:55 2006 +0000
   112.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   112.3 @@ -1,77 +0,0 @@
   112.4 -/* Excerpts written by Martin Mares <mj@atrey.karlin.mff.cuni.cz> */
   112.5 -/* Modified for x86-64 Xen by Keir Fraser */
   112.6 -OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
   112.7 -OUTPUT_ARCH(i386:x86-64)
   112.8 -ENTRY(start)
   112.9 -PHDRS
  112.10 -{
  112.11 -  text PT_LOAD ;
  112.12 -}
  112.13 -SECTIONS
  112.14 -{
  112.15 -  . = 0xFFFF830000100000;
  112.16 -  _text = .;			/* Text and read-only data */
  112.17 -  .text : {
  112.18 -	*(.text)
  112.19 -	*(.fixup)
  112.20 -	*(.gnu.warning)
  112.21 -	} :text = 0x9090
  112.22 -  .text.lock : { *(.text.lock) } :text	/* out-of-line lock text */
  112.23 -
  112.24 -  _etext = .;			/* End of text section */
  112.25 -
  112.26 -  .rodata : { *(.rodata) *(.rodata.*) } :text
  112.27 -
  112.28 -  . = ALIGN(32);		/* Exception table */
  112.29 -  __start___ex_table = .;
  112.30 -  __ex_table : { *(__ex_table) } :text
  112.31 -  __stop___ex_table = .;
  112.32 -
  112.33 -  . = ALIGN(32);                /* Pre-exception table */
  112.34 -  __start___pre_ex_table = .;
  112.35 -  __pre_ex_table : { *(__pre_ex_table) } :text
  112.36 -  __stop___pre_ex_table = .;
  112.37 -
  112.38 -  .data : {			/* Data */
  112.39 -	*(.data)
  112.40 -	CONSTRUCTORS
  112.41 -	} :text
  112.42 -
  112.43 -  . = ALIGN(4096);		/* Init code and data */
  112.44 -  __init_begin = .;
  112.45 -  .text.init : { *(.text.init) } :text
  112.46 -  .data.init : { *(.data.init) } :text
  112.47 -  . = ALIGN(32);
  112.48 -  __setup_start = .;
  112.49 -  .setup.init : { *(.setup.init) } :text
  112.50 -  __setup_end = .;
  112.51 -  __initcall_start = .;
  112.52 -  .initcall.init : { *(.initcall.init) } :text
  112.53 -  __initcall_end = .;
  112.54 -  . = ALIGN(8192);
  112.55 -  __init_end = .;
  112.56 -
  112.57 -  __bss_start = .;		/* BSS */
  112.58 -  .bss : {
  112.59 -	*(.bss.twopage_aligned)
  112.60 -	*(.bss.page_aligned)
  112.61 -	*(.bss)
  112.62 -	} :text
  112.63 -  _end = . ;
  112.64 -
  112.65 -  /* Sections to be discarded */
  112.66 -  /DISCARD/ : {
  112.67 -	*(.text.exit)
  112.68 -	*(.data.exit)
  112.69 -	*(.exitcall.exit)
  112.70 -	}
  112.71 -
  112.72 -  /* Stabs debugging sections.  */
  112.73 -  .stab 0 : { *(.stab) }
  112.74 -  .stabstr 0 : { *(.stabstr) }
  112.75 -  .stab.excl 0 : { *(.stab.excl) }
  112.76 -  .stab.exclstr 0 : { *(.stab.exclstr) }
  112.77 -  .stab.index 0 : { *(.stab.index) }
  112.78 -  .stab.indexstr 0 : { *(.stab.indexstr) }
  112.79 -  .comment 0 : { *(.comment) }
  112.80 -}
   113.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   113.2 +++ b/xen/arch/x86/x86_64/xen.lds.S	Mon Jan 09 11:22:17 2006 +0000
   113.3 @@ -0,0 +1,83 @@
   113.4 +/* Excerpts written by Martin Mares <mj@atrey.karlin.mff.cuni.cz> */
   113.5 +/* Modified for x86-64 Xen by Keir Fraser */
   113.6 +
   113.7 +#include <xen/config.h>
   113.8 +#include <asm/page.h>
   113.9 +#undef ENTRY
  113.10 +#undef ALIGN
  113.11 +
  113.12 +OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
  113.13 +OUTPUT_ARCH(i386:x86-64)
  113.14 +ENTRY(start)
  113.15 +PHDRS
  113.16 +{
  113.17 +  text PT_LOAD ;
  113.18 +}
  113.19 +SECTIONS
  113.20 +{
  113.21 +  . = 0xFFFF830000100000;
  113.22 +  _text = .;			/* Text and read-only data */
  113.23 +  .text : {
  113.24 +	*(.text)
  113.25 +	*(.fixup)
  113.26 +	*(.gnu.warning)
  113.27 +	} :text = 0x9090
  113.28 +  .text.lock : { *(.text.lock) } :text	/* out-of-line lock text */
  113.29 +
  113.30 +  _etext = .;			/* End of text section */
  113.31 +
  113.32 +  .rodata : { *(.rodata) *(.rodata.*) } :text
  113.33 +
  113.34 +  . = ALIGN(32);		/* Exception table */
  113.35 +  __start___ex_table = .;
  113.36 +  __ex_table : { *(__ex_table) } :text
  113.37 +  __stop___ex_table = .;
  113.38 +
  113.39 +  . = ALIGN(32);                /* Pre-exception table */
  113.40 +  __start___pre_ex_table = .;
  113.41 +  __pre_ex_table : { *(__pre_ex_table) } :text
  113.42 +  __stop___pre_ex_table = .;
  113.43 +
  113.44 +  .data : {			/* Data */
  113.45 +	*(.data)
  113.46 +	CONSTRUCTORS
  113.47 +	} :text
  113.48 +
  113.49 +  . = ALIGN(4096);		/* Init code and data */
  113.50 +  __init_begin = .;
  113.51 +  .text.init : { *(.text.init) } :text
  113.52 +  .data.init : { *(.data.init) } :text
  113.53 +  . = ALIGN(32);
  113.54 +  __setup_start = .;
  113.55 +  .setup.init : { *(.setup.init) } :text
  113.56 +  __setup_end = .;
  113.57 +  __initcall_start = .;
  113.58 +  .initcall.init : { *(.initcall.init) } :text
  113.59 +  __initcall_end = .;
  113.60 +  . = ALIGN(STACK_SIZE);
  113.61 +  __init_end = .;
  113.62 +
  113.63 +  __bss_start = .;		/* BSS */
  113.64 +  .bss : {
  113.65 +	*(.bss.stack_aligned)
  113.66 +	*(.bss.page_aligned)
  113.67 +	*(.bss)
  113.68 +	} :text
  113.69 +  _end = . ;
  113.70 +
  113.71 +  /* Sections to be discarded */
  113.72 +  /DISCARD/ : {
  113.73 +	*(.text.exit)
  113.74 +	*(.data.exit)
  113.75 +	*(.exitcall.exit)
  113.76 +	}
  113.77 +
  113.78 +  /* Stabs debugging sections.  */
  113.79 +  .stab 0 : { *(.stab) }
  113.80 +  .stabstr 0 : { *(.stabstr) }
  113.81 +  .stab.excl 0 : { *(.stab.excl) }
  113.82 +  .stab.exclstr 0 : { *(.stab.exclstr) }
  113.83 +  .stab.index 0 : { *(.stab.index) }
  113.84 +  .stab.indexstr 0 : { *(.stab.indexstr) }
  113.85 +  .comment 0 : { *(.comment) }
  113.86 +}
   114.1 --- a/xen/arch/x86/x86_emulate.c	Mon Jan 09 11:19:55 2006 +0000
   114.2 +++ b/xen/arch/x86/x86_emulate.c	Mon Jan 09 11:22:17 2006 +0000
   114.3 @@ -371,6 +371,21 @@ do{ __asm__ __volatile__ (              
   114.4     (_type)_x; \
   114.5  })
   114.6  
   114.7 +/* Access/update address held in a register, based on addressing mode. */
   114.8 +#define register_address(sel, reg)                                      \
   114.9 +    ((ad_bytes == sizeof(unsigned long)) ? (reg) :                      \
  114.10 +     ((mode == X86EMUL_MODE_REAL) ? /* implies ad_bytes == 2 */         \
  114.11 +      (((unsigned long)(sel) << 4) + ((reg) & 0xffff)) :                \
  114.12 +      ((reg) & ((1UL << (ad_bytes << 3)) - 1))))
  114.13 +#define register_address_increment(reg, inc)                            \
  114.14 +do {                                                                    \
  114.15 +    if ( ad_bytes == sizeof(unsigned long) )                            \
  114.16 +        (reg) += (inc);                                                 \
  114.17 +    else                                                                \
  114.18 +        (reg) = ((reg) & ~((1UL << (ad_bytes << 3)) - 1)) |             \
  114.19 +                (((reg) + (inc)) & ((1UL << (ad_bytes << 3)) - 1));     \
  114.20 +} while (0)
  114.21 +
  114.22  void *
  114.23  decode_register(
  114.24      uint8_t modrm_reg, struct cpu_user_regs *regs, int highbyte_regs)
  114.25 @@ -420,32 +435,64 @@ x86_emulate_memop(
  114.26  {
  114.27      uint8_t b, d, sib, twobyte = 0, rex_prefix = 0;
  114.28      uint8_t modrm, modrm_mod = 0, modrm_reg = 0, modrm_rm = 0;
  114.29 -    unsigned int op_bytes = (mode == 8) ? 4 : mode, ad_bytes = mode;
  114.30 -    unsigned int lock_prefix = 0, rep_prefix = 0, i;
  114.31 +    uint16_t *seg = NULL; /* override segment */
  114.32 +    unsigned int op_bytes, ad_bytes, lock_prefix = 0, rep_prefix = 0, i;
  114.33      int rc = 0;
  114.34      struct operand src, dst;
  114.35  
  114.36      /* Shadow copy of register state. Committed on successful emulation. */
  114.37      struct cpu_user_regs _regs = *regs;
  114.38  
  114.39 +    switch ( mode )
  114.40 +    {
  114.41 +    case X86EMUL_MODE_REAL:
  114.42 +    case X86EMUL_MODE_PROT16:
  114.43 +        op_bytes = ad_bytes = 2;
  114.44 +        break;
  114.45 +    case X86EMUL_MODE_PROT32:
  114.46 +        op_bytes = ad_bytes = 4;
  114.47 +        break;
  114.48 +#ifdef __x86_64__
  114.49 +    case X86EMUL_MODE_PROT64:
  114.50 +        op_bytes = 4;
  114.51 +        ad_bytes = 8;
  114.52 +        break;
  114.53 +#endif
  114.54 +    default:
  114.55 +        return -1;
  114.56 +    }
  114.57 +
  114.58      /* Legacy prefixes. */
  114.59      for ( i = 0; i < 8; i++ )
  114.60      {
  114.61          switch ( b = insn_fetch(uint8_t, 1, _regs.eip) )
  114.62          {
  114.63          case 0x66: /* operand-size override */
  114.64 -            op_bytes ^= 6;                    /* switch between 2/4 bytes */
  114.65 +            op_bytes ^= 6;      /* switch between 2/4 bytes */
  114.66              break;
  114.67          case 0x67: /* address-size override */
  114.68 -            ad_bytes ^= (mode == 8) ? 12 : 6; /* switch between 2/4/8 bytes */
  114.69 +            if ( mode == X86EMUL_MODE_PROT64 )
  114.70 +                ad_bytes ^= 12; /* switch between 4/8 bytes */
  114.71 +            else
  114.72 +                ad_bytes ^= 6;  /* switch between 2/4 bytes */
  114.73              break;
  114.74          case 0x2e: /* CS override */
  114.75 +            seg = &_regs.cs;
  114.76 +            break;
  114.77          case 0x3e: /* DS override */
  114.78 +            seg = &_regs.ds;
  114.79 +            break;
  114.80          case 0x26: /* ES override */
  114.81 +            seg = &_regs.es;
  114.82 +            break;
  114.83          case 0x64: /* FS override */
  114.84 +            seg = &_regs.fs;
  114.85 +            break;
  114.86          case 0x65: /* GS override */
  114.87 +            seg = &_regs.gs;
  114.88 +            break;
  114.89          case 0x36: /* SS override */
  114.90 -            DPRINTF("Warning: ignoring a segment override.\n");
  114.91 +            seg = &_regs.ss;
  114.92              break;
  114.93          case 0xf0: /* LOCK */
  114.94              lock_prefix = 1;
  114.95 @@ -461,8 +508,12 @@ x86_emulate_memop(
  114.96      }
  114.97   done_prefixes:
  114.98  
  114.99 +    /* Note quite the same as 80386 real mode, but hopefully good enough. */
 114.100 +    if ( (mode == X86EMUL_MODE_REAL) && (ad_bytes != 2) )
 114.101 +        goto cannot_emulate;
 114.102 +
 114.103      /* REX prefix. */
 114.104 -    if ( (mode == 8) && ((b & 0xf0) == 0x40) )
 114.105 +    if ( (mode == X86EMUL_MODE_PROT64) && ((b & 0xf0) == 0x40) )
 114.106      {
 114.107          rex_prefix = b;
 114.108          if ( b & 8 )
 114.109 @@ -674,7 +725,7 @@ x86_emulate_memop(
 114.110          emulate_2op_SrcV("cmp", src, dst, _regs.eflags);
 114.111          break;
 114.112      case 0x63: /* movsxd */
 114.113 -        if ( mode != 8 ) /* x86/64 long mode only */
 114.114 +        if ( mode != X86EMUL_MODE_PROT64 )
 114.115              goto cannot_emulate;
 114.116          dst.val = (int32_t)src.val;
 114.117          break;
 114.118 @@ -721,12 +772,13 @@ x86_emulate_memop(
 114.119          dst.val = src.val;
 114.120          break;
 114.121      case 0x8f: /* pop (sole member of Grp1a) */
 114.122 -        /* 64-bit mode: POP defaults to 64-bit operands. */
 114.123 -        if ( (mode == 8) && (dst.bytes == 4) )
 114.124 +        /* 64-bit mode: POP always pops a 64-bit operand. */
 114.125 +        if ( mode == X86EMUL_MODE_PROT64 )
 114.126              dst.bytes = 8;
 114.127 -        if ( (rc = ops->read_std(_regs.esp, &dst.val, dst.bytes)) != 0 )
 114.128 +        if ( (rc = ops->read_std(register_address(_regs.ss, _regs.esp),
 114.129 +                                 &dst.val, dst.bytes)) != 0 )
 114.130              goto done;
 114.131 -        _regs.esp += dst.bytes;
 114.132 +        register_address_increment(_regs.esp, dst.bytes);
 114.133          break;
 114.134      case 0xc0 ... 0xc1: grp2: /* Grp2 */
 114.135          switch ( modrm_reg )
 114.136 @@ -797,16 +849,17 @@ x86_emulate_memop(
 114.137              emulate_1op("dec", dst, _regs.eflags);
 114.138              break;
 114.139          case 6: /* push */
 114.140 -            /* 64-bit mode: PUSH defaults to 64-bit operands. */
 114.141 -            if ( (mode == 8) && (dst.bytes == 4) )
 114.142 +            /* 64-bit mode: PUSH always pushes a 64-bit operand. */
 114.143 +            if ( mode == X86EMUL_MODE_PROT64 )
 114.144              {
 114.145                  dst.bytes = 8;
 114.146                  if ( (rc = ops->read_std((unsigned long)dst.ptr,
 114.147                                           &dst.val, 8)) != 0 )
 114.148                      goto done;
 114.149              }
 114.150 -            _regs.esp -= dst.bytes;
 114.151 -            if ( (rc = ops->write_std(_regs.esp, dst.val, dst.bytes)) != 0 )
 114.152 +            register_address_increment(_regs.esp, -dst.bytes);
 114.153 +            if ( (rc = ops->write_std(register_address(_regs.ss, _regs.esp),
 114.154 +                                      dst.val, dst.bytes)) != 0 )
 114.155                  goto done;
 114.156              dst.val = dst.orig_val; /* skanky: disable writeback */
 114.157              break;
 114.158 @@ -873,19 +926,22 @@ x86_emulate_memop(
 114.159          {
 114.160              /* Write fault: destination is special memory. */
 114.161              dst.ptr = (unsigned long *)cr2;
 114.162 -            if ( (rc = ops->read_std(_regs.esi - _regs.edi + cr2, 
 114.163 +            if ( (rc = ops->read_std(register_address(seg ? *seg : _regs.ds,
 114.164 +                                                      _regs.esi),
 114.165                                       &dst.val, dst.bytes)) != 0 )
 114.166                  goto done;
 114.167          }
 114.168          else
 114.169          {
 114.170              /* Read fault: source is special memory. */
 114.171 -            dst.ptr = (unsigned long *)(_regs.edi - _regs.esi + cr2);
 114.172 +            dst.ptr = (unsigned long *)register_address(_regs.es, _regs.edi);
 114.173              if ( (rc = ops->read_emulated(cr2, &dst.val, dst.bytes)) != 0 )
 114.174                  goto done;
 114.175          }
 114.176 -        _regs.esi += (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes;
 114.177 -        _regs.edi += (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes;
 114.178 +        register_address_increment(
 114.179 +            _regs.esi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
 114.180 +        register_address_increment(
 114.181 +            _regs.edi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
 114.182          break;
 114.183      case 0xa6 ... 0xa7: /* cmps */
 114.184          DPRINTF("Urk! I don't handle CMPS.\n");
 114.185 @@ -895,7 +951,8 @@ x86_emulate_memop(
 114.186          dst.bytes = (d & ByteOp) ? 1 : op_bytes;
 114.187          dst.ptr   = (unsigned long *)cr2;
 114.188          dst.val   = _regs.eax;
 114.189 -        _regs.edi += (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes;
 114.190 +        register_address_increment(
 114.191 +            _regs.edi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
 114.192          break;
 114.193      case 0xac ... 0xad: /* lods */
 114.194          dst.type  = OP_REG;
 114.195 @@ -903,7 +960,8 @@ x86_emulate_memop(
 114.196          dst.ptr   = (unsigned long *)&_regs.eax;
 114.197          if ( (rc = ops->read_emulated(cr2, &dst.val, dst.bytes)) != 0 )
 114.198              goto done;
 114.199 -        _regs.esi += (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes;
 114.200 +        register_address_increment(
 114.201 +            _regs.esi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
 114.202          break;
 114.203      case 0xae ... 0xaf: /* scas */
 114.204          DPRINTF("Urk! I don't handle SCAS.\n");
   115.1 --- a/xen/common/bitmap.c	Mon Jan 09 11:19:55 2006 +0000
   115.2 +++ b/xen/common/bitmap.c	Mon Jan 09 11:22:17 2006 +0000
   115.3 @@ -282,6 +282,111 @@ int __bitmap_weight(const unsigned long 
   115.4  #endif
   115.5  EXPORT_SYMBOL(__bitmap_weight);
   115.6  
   115.7 +/*
   115.8 + * Bitmap printing & parsing functions: first version by Bill Irwin,
   115.9 + * second version by Paul Jackson, third by Joe Korty.
  115.10 + */
  115.11 +
  115.12 +#define CHUNKSZ				32
  115.13 +#define nbits_to_hold_value(val)	fls(val)
  115.14 +#define roundup_power2(val,modulus)	(((val) + (modulus) - 1) & ~((modulus) - 1))
  115.15 +#define unhex(c)			(isdigit(c) ? (c - '0') : (toupper(c) - 'A' + 10))
  115.16 +#define BASEDEC 10		/* fancier cpuset lists input in decimal */
  115.17 +
  115.18 +/**
  115.19 + * bitmap_scnprintf - convert bitmap to an ASCII hex string.
  115.20 + * @buf: byte buffer into which string is placed
  115.21 + * @buflen: reserved size of @buf, in bytes
  115.22 + * @maskp: pointer to bitmap to convert
  115.23 + * @nmaskbits: size of bitmap, in bits
  115.24 + *
  115.25 + * Exactly @nmaskbits bits are displayed.  Hex digits are grouped into
  115.26 + * comma-separated sets of eight digits per set.
  115.27 + */
  115.28 +int bitmap_scnprintf(char *buf, unsigned int buflen,
  115.29 +	const unsigned long *maskp, int nmaskbits)
  115.30 +{
  115.31 +	int i, word, bit, len = 0;
  115.32 +	unsigned long val;
  115.33 +	const char *sep = "";
  115.34 +	int chunksz;
  115.35 +	u32 chunkmask;
  115.36 +
  115.37 +	chunksz = nmaskbits & (CHUNKSZ - 1);
  115.38 +	if (chunksz == 0)
  115.39 +		chunksz = CHUNKSZ;
  115.40 +
  115.41 +	i = roundup_power2(nmaskbits, CHUNKSZ) - CHUNKSZ;
  115.42 +	for (; i >= 0; i -= CHUNKSZ) {
  115.43 +		chunkmask = ((1ULL << chunksz) - 1);
  115.44 +		word = i / BITS_PER_LONG;
  115.45 +		bit = i % BITS_PER_LONG;
  115.46 +		val = (maskp[word] >> bit) & chunkmask;
  115.47 +		len += scnprintf(buf+len, buflen-len, "%s%0*lx", sep,
  115.48 +			(chunksz+3)/4, val);
  115.49 +		chunksz = CHUNKSZ;
  115.50 +		sep = ",";
  115.51 +	}
  115.52 +	return len;
  115.53 +}
  115.54 +EXPORT_SYMBOL(bitmap_scnprintf);
  115.55 +
  115.56 +/*
  115.57 + * bscnl_emit(buf, buflen, rbot, rtop, bp)
  115.58 + *
  115.59 + * Helper routine for bitmap_scnlistprintf().  Write decimal number
  115.60 + * or range to buf, suppressing output past buf+buflen, with optional
  115.61 + * comma-prefix.  Return len of what would be written to buf, if it
  115.62 + * all fit.
  115.63 + */
  115.64 +static inline int bscnl_emit(char *buf, int buflen, int rbot, int rtop, int len)
  115.65 +{
  115.66 +	if (len > 0)
  115.67 +		len += scnprintf(buf + len, buflen - len, ",");
  115.68 +	if (rbot == rtop)
  115.69 +		len += scnprintf(buf + len, buflen - len, "%d", rbot);
  115.70 +	else
  115.71 +		len += scnprintf(buf + len, buflen - len, "%d-%d", rbot, rtop);
  115.72 +	return len;
  115.73 +}
  115.74 +
  115.75 +/**
  115.76 + * bitmap_scnlistprintf - convert bitmap to list format ASCII string
  115.77 + * @buf: byte buffer into which string is placed
  115.78 + * @buflen: reserved size of @buf, in bytes
  115.79 + * @maskp: pointer to bitmap to convert
  115.80 + * @nmaskbits: size of bitmap, in bits
  115.81 + *
  115.82 + * Output format is a comma-separated list of decimal numbers and
  115.83 + * ranges.  Consecutively set bits are shown as two hyphen-separated
  115.84 + * decimal numbers, the smallest and largest bit numbers set in
  115.85 + * the range.  Output format is compatible with the format
  115.86 + * accepted as input by bitmap_parselist().
  115.87 + *
  115.88 + * The return value is the number of characters which would be
  115.89 + * generated for the given input, excluding the trailing '\0', as
  115.90 + * per ISO C99.
  115.91 + */
  115.92 +int bitmap_scnlistprintf(char *buf, unsigned int buflen,
  115.93 +	const unsigned long *maskp, int nmaskbits)
  115.94 +{
  115.95 +	int len = 0;
  115.96 +	/* current bit is 'cur', most recently seen range is [rbot, rtop] */
  115.97 +	int cur, rbot, rtop;
  115.98 +
  115.99 +	rbot = cur = find_first_bit(maskp, nmaskbits);
 115.100 +	while (cur < nmaskbits) {
 115.101 +		rtop = cur;
 115.102 +		cur = find_next_bit(maskp, nmaskbits, cur+1);
 115.103 +		if (cur >= nmaskbits || cur > rtop + 1) {
 115.104 +			len = bscnl_emit(buf, buflen, rbot, rtop, len);
 115.105 +			rbot = cur;
 115.106 +		}
 115.107 +	}
 115.108 +	return len;
 115.109 +}
 115.110 +EXPORT_SYMBOL(bitmap_scnlistprintf);
 115.111 +
 115.112  /**
 115.113   *	bitmap_find_free_region - find a contiguous aligned mem region
 115.114   *	@bitmap: an array of unsigned longs corresponding to the bitmap
   116.1 --- a/xen/common/dom0_ops.c	Mon Jan 09 11:19:55 2006 +0000
   116.2 +++ b/xen/common/dom0_ops.c	Mon Jan 09 11:22:17 2006 +0000
   116.3 @@ -16,6 +16,7 @@
   116.4  #include <xen/domain_page.h>
   116.5  #include <xen/trace.h>
   116.6  #include <xen/console.h>
   116.7 +#include <xen/iocap.h>
   116.8  #include <asm/current.h>
   116.9  #include <public/dom0_ops.h>
  116.10  #include <public/sched_ctl.h>
  116.11 @@ -109,13 +110,13 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
  116.12      switch ( op->cmd )
  116.13      {
  116.14  
  116.15 -    case DOM0_SETDOMAININFO:
  116.16 +    case DOM0_SETVCPUCONTEXT:
  116.17      {
  116.18 -        struct domain *d = find_domain_by_id(op->u.setdomaininfo.domain);
  116.19 +        struct domain *d = find_domain_by_id(op->u.setvcpucontext.domain);
  116.20          ret = -ESRCH;
  116.21          if ( d != NULL )
  116.22          {
  116.23 -            ret = set_info_guest(d, &op->u.setdomaininfo);
  116.24 +            ret = set_info_guest(d, &op->u.setvcpucontext);
  116.25              put_domain(d);
  116.26          }
  116.27      }
  116.28 @@ -283,11 +284,12 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
  116.29      }
  116.30      break;
  116.31  
  116.32 -    case DOM0_PINCPUDOMAIN:
  116.33 +    case DOM0_SETVCPUAFFINITY:
  116.34      {
  116.35 -        domid_t dom = op->u.pincpudomain.domain;
  116.36 +        domid_t dom = op->u.setvcpuaffinity.domain;
  116.37          struct domain *d = find_domain_by_id(dom);
  116.38          struct vcpu *v;
  116.39 +        cpumask_t new_affinity;
  116.40  
  116.41          if ( d == NULL )
  116.42          {
  116.43 @@ -295,15 +297,15 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
  116.44              break;
  116.45          }
  116.46          
  116.47 -        if ( (op->u.pincpudomain.vcpu >= MAX_VIRT_CPUS) ||
  116.48 -             !d->vcpu[op->u.pincpudomain.vcpu] )
  116.49 +        if ( (op->u.setvcpuaffinity.vcpu >= MAX_VIRT_CPUS) ||
  116.50 +             !d->vcpu[op->u.setvcpuaffinity.vcpu] )
  116.51          {
  116.52              ret = -EINVAL;
  116.53              put_domain(d);
  116.54              break;
  116.55          }
  116.56  
  116.57 -        v = d->vcpu[op->u.pincpudomain.vcpu];
  116.58 +        v = d->vcpu[op->u.setvcpuaffinity.vcpu];
  116.59          if ( v == NULL )
  116.60          {
  116.61              ret = -ESRCH;
  116.62 @@ -318,22 +320,13 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
  116.63              break;
  116.64          }
  116.65  
  116.66 -        v->cpumap = op->u.pincpudomain.cpumap;
  116.67 +        new_affinity = v->cpu_affinity;
  116.68 +        memcpy(cpus_addr(new_affinity),
  116.69 +               &op->u.setvcpuaffinity.cpumap,
  116.70 +               min((int)BITS_TO_LONGS(NR_CPUS),
  116.71 +                   (int)sizeof(op->u.setvcpuaffinity.cpumap)));
  116.72  
  116.73 -        if ( v->cpumap == CPUMAP_RUNANYWHERE )
  116.74 -        {
  116.75 -            clear_bit(_VCPUF_cpu_pinned, &v->vcpu_flags);
  116.76 -        }
  116.77 -        else
  116.78 -        {
  116.79 -            /* pick a new cpu from the usable map */
  116.80 -            int new_cpu;
  116.81 -            new_cpu = (int)find_first_set_bit(v->cpumap) % num_online_cpus();
  116.82 -            vcpu_pause(v);
  116.83 -            vcpu_migrate_cpu(v, new_cpu);
  116.84 -            set_bit(_VCPUF_cpu_pinned, &v->vcpu_flags);
  116.85 -            vcpu_unpause(v);
  116.86 -        }
  116.87 +        ret = vcpu_set_affinity(v, &new_affinity);
  116.88  
  116.89          put_domain(d);
  116.90      }
  116.91 @@ -505,7 +498,11 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
  116.92          op->u.getvcpuinfo.running  = test_bit(_VCPUF_running, &v->vcpu_flags);
  116.93          op->u.getvcpuinfo.cpu_time = v->cpu_time;
  116.94          op->u.getvcpuinfo.cpu      = v->processor;
  116.95 -        op->u.getvcpuinfo.cpumap   = v->cpumap;
  116.96 +        op->u.getvcpuinfo.cpumap   = 0;
  116.97 +        memcpy(&op->u.getvcpuinfo.cpumap,
  116.98 +               cpus_addr(v->cpu_affinity),
  116.99 +               min((int)BITS_TO_LONGS(NR_CPUS),
 116.100 +                   (int)sizeof(op->u.getvcpuinfo.cpumap)));
 116.101          ret = 0;
 116.102  
 116.103          if ( copy_to_user(u_dom0_op, op, sizeof(*op)) )     
 116.104 @@ -582,6 +579,7 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
 116.105          }
 116.106      }
 116.107      break;
 116.108 +
 116.109      case DOM0_SETDEBUGGING:
 116.110      {
 116.111          struct domain *d; 
 116.112 @@ -599,6 +597,53 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
 116.113      }
 116.114      break;
 116.115  
 116.116 +    case DOM0_IRQ_PERMISSION:
 116.117 +    {
 116.118 +        struct domain *d;
 116.119 +        unsigned int pirq = op->u.irq_permission.pirq;
 116.120 +
 116.121 +        ret = -EINVAL;
 116.122 +        if ( pirq >= NR_PIRQS )
 116.123 +            break;
 116.124 +
 116.125 +        ret = -ESRCH;
 116.126 +        d = find_domain_by_id(op->u.irq_permission.domain);
 116.127 +        if ( d == NULL )
 116.128 +            break;
 116.129 +
 116.130 +        if ( op->u.irq_permission.allow_access )
 116.131 +            ret = irq_permit_access(d, pirq);
 116.132 +        else
 116.133 +            ret = irq_deny_access(d, pirq);
 116.134 +
 116.135 +        put_domain(d);
 116.136 +    }
 116.137 +    break;
 116.138 +
 116.139 +    case DOM0_IOMEM_PERMISSION:
 116.140 +    {
 116.141 +        struct domain *d;
 116.142 +        unsigned long pfn = op->u.iomem_permission.first_pfn;
 116.143 +        unsigned long nr_pfns = op->u.iomem_permission.nr_pfns;
 116.144 +
 116.145 +        ret = -EINVAL;
 116.146 +        if ( (pfn + nr_pfns - 1) < pfn ) /* wrap? */
 116.147 +            break;
 116.148 +
 116.149 +        ret = -ESRCH;
 116.150 +        d = find_domain_by_id(op->u.iomem_permission.domain);
 116.151 +        if ( d == NULL )
 116.152 +            break;
 116.153 +
 116.154 +        if ( op->u.iomem_permission.allow_access )
 116.155 +            ret = iomem_permit_access(d, pfn, pfn + nr_pfns - 1);
 116.156 +        else
 116.157 +            ret = iomem_deny_access(d, pfn, pfn + nr_pfns - 1);
 116.158 +
 116.159 +        put_domain(d);
 116.160 +    }
 116.161 +    break;
 116.162 +
 116.163  #ifdef PERF_COUNTERS
 116.164      case DOM0_PERFCCONTROL:
 116.165      {
   117.1 --- a/xen/common/domain.c	Mon Jan 09 11:19:55 2006 +0000
   117.2 +++ b/xen/common/domain.c	Mon Jan 09 11:22:17 2006 +0000
   117.3 @@ -16,6 +16,7 @@
   117.4  #include <xen/console.h>
   117.5  #include <xen/softirq.h>
   117.6  #include <xen/domain_page.h>
   117.7 +#include <xen/rangeset.h>
   117.8  #include <asm/debugger.h>
   117.9  #include <public/dom0_ops.h>
  117.10  #include <public/sched.h>
  117.11 @@ -50,25 +51,24 @@ struct domain *do_createdomain(domid_t d
  117.12      else
  117.13          set_bit(_DOMF_ctrl_pause, &d->domain_flags);
  117.14  
  117.15 -    if ( !is_idle_task(d) &&
  117.16 +    if ( !is_idle_domain(d) &&
  117.17           ((evtchn_init(d) != 0) || (grant_table_create(d) != 0)) )
  117.18 -    {
  117.19 -        evtchn_destroy(d);
  117.20 -        free_domain(d);
  117.21 -        return NULL;
  117.22 -    }
  117.23 +        goto fail1;