[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] Merge
# HG changeset patch # User djm@xxxxxxxxxxxxxxx # Node ID cd914808acf1f5a32fc6fa575432cd96f9a4ad10 # Parent 903fb46f240eeafaeefbc32e31ea9a3b00fb906f # Parent 5b30599761b3f0b85e6bb1768f0236294881e900 Merge diff -r 903fb46f240e -r cd914808acf1 .hgignore --- a/.hgignore Tue Jan 3 14:59:00 2006 +++ b/.hgignore Tue Jan 3 16:19:20 2006 @@ -181,6 +181,7 @@ ^xen/TAGS$ ^xen/arch/x86/asm-offsets\.s$ ^xen/arch/x86/boot/mkelf32$ +^xen/arch/x86/xen\.lds$ ^xen/ddb/.*$ ^xen/include/asm$ ^xen/include/asm-.*/asm-offsets\.h$ diff -r 903fb46f240e -r cd914808acf1 linux-2.6-xen-sparse/arch/xen/kernel/gnttab.c --- a/linux-2.6-xen-sparse/arch/xen/kernel/gnttab.c Tue Jan 3 14:59:00 2006 +++ b/linux-2.6-xen-sparse/arch/xen/kernel/gnttab.c Tue Jan 3 16:19:20 2006 @@ -389,6 +389,30 @@ return -ENOSYS; } +static int __init +gnttab_proc_init(void) +{ + /* + * /proc/xen/grant : used by libxc to access grant tables + */ + if ((grant_pde = create_xen_proc_entry("grant", 0600)) == NULL) { + WPRINTK("Unable to create grant xen proc entry\n"); + return -1; + } + + grant_file_ops.read = grant_pde->proc_fops->read; + grant_file_ops.write = grant_pde->proc_fops->write; + + grant_pde->proc_fops = &grant_file_ops; + + grant_pde->read_proc = &grant_read; + grant_pde->write_proc = &grant_write; + + return 0; +} + +device_initcall(gnttab_proc_init); + #endif /* CONFIG_PROC_FS */ int @@ -446,29 +470,11 @@ gnttab_free_count = NR_GRANT_ENTRIES - NR_RESERVED_ENTRIES; gnttab_free_head = NR_RESERVED_ENTRIES; -#ifdef CONFIG_PROC_FS - /* - * /proc/xen/grant : used by libxc to access grant tables - */ - if ((grant_pde = create_xen_proc_entry("grant", 0600)) == NULL) { - WPRINTK("Unable to create grant xen proc entry\n"); - return -1; - } - - grant_file_ops.read = grant_pde->proc_fops->read; - grant_file_ops.write = grant_pde->proc_fops->write; - - grant_pde->proc_fops = &grant_file_ops; - - grant_pde->read_proc = &grant_read; - grant_pde->write_proc = &grant_write; -#endif - printk("Grant table initialized\n"); return 0; } -__initcall(gnttab_init); +core_initcall(gnttab_init); /* * Local variables: diff -r 903fb46f240e -r cd914808acf1 linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c Tue Jan 3 14:59:00 2006 +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c Tue Jan 3 16:19:20 2006 @@ -331,7 +331,12 @@ return; } - xlvbd_add(sectors, info->vdevice, binfo, sector_size, info); + err = xlvbd_add(sectors, info->vdevice, binfo, sector_size, info); + if (err) { + xenbus_dev_fatal(info->xbdev, err, "xlvbd_add at %s", + info->xbdev->otherend); + return; + } (void)xenbus_switch_state(info->xbdev, NULL, XenbusStateConnected); diff -r 903fb46f240e -r cd914808acf1 linux-2.6-xen-sparse/drivers/xen/netback/common.h --- a/linux-2.6-xen-sparse/drivers/xen/netback/common.h Tue Jan 3 14:59:00 2006 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/common.h Tue Jan 3 16:19:20 2006 @@ -82,7 +82,7 @@ #define NET_RX_RING_SIZE __RING_SIZE((netif_rx_sring_t *)0, PAGE_SIZE) void netif_creditlimit(netif_t *netif); -int netif_disconnect(netif_t *netif); +void netif_disconnect(netif_t *netif); netif_t *alloc_netif(domid_t domid, unsigned int handle, u8 be_mac[ETH_ALEN]); void free_netif(netif_t *netif); diff -r 903fb46f240e -r cd914808acf1 linux-2.6-xen-sparse/drivers/xen/netback/interface.c --- a/linux-2.6-xen-sparse/drivers/xen/netback/interface.c Tue Jan 3 14:59:00 2006 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/interface.c Tue Jan 3 16:19:20 2006 @@ -196,9 +196,13 @@ return 0; netif->tx_comms_area = alloc_vm_area(PAGE_SIZE); + if (netif->tx_comms_area == NULL) + return -ENOMEM; netif->rx_comms_area = alloc_vm_area(PAGE_SIZE); - if (netif->tx_comms_area == NULL || netif->rx_comms_area == NULL) + if (netif->rx_comms_area == NULL) { + free_vm_area(netif->tx_comms_area); return -ENOMEM; + } err = map_frontend_pages(netif, tx_ring_ref, rx_ring_ref); if (err) { @@ -247,13 +251,9 @@ { netif_t *netif = (netif_t *)arg; - /* Already disconnected? */ - if (!netif->irq) - return; - - unbind_from_irqhandler(netif->irq, netif); - netif->irq = 0; - + if (netif->irq) + unbind_from_irqhandler(netif->irq, netif); + unregister_netdev(netif->dev); if (netif->tx.sring) { @@ -290,10 +290,10 @@ #endif } -int netif_disconnect(netif_t *netif) -{ - - if (netif->status == CONNECTED) { +void netif_disconnect(netif_t *netif) +{ + switch (netif->status) { + case CONNECTED: rtnl_lock(); netif->status = DISCONNECTING; wmb(); @@ -301,10 +301,14 @@ __netif_down(netif); rtnl_unlock(); netif_put(netif); - return 0; /* Caller should not send response message. */ - } - - return 1; + break; + case DISCONNECTED: + BUG_ON(atomic_read(&netif->refcnt) != 0); + free_netif(netif); + break; + default: + BUG(); + } } /* diff -r 903fb46f240e -r cd914808acf1 linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Tue Jan 3 14:59:00 2006 +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Tue Jan 3 16:19:20 2006 @@ -116,6 +116,8 @@ #define RX_MAX_TARGET NET_RX_RING_SIZE int rx_min_target, rx_max_target, rx_target; struct sk_buff_head rx_batch; + + struct timer_list rx_refill_timer; /* * {tx,rx}_skbs store outstanding skbuffs. The first entry in each @@ -517,6 +519,13 @@ } +static void rx_refill_timeout(unsigned long data) +{ + struct net_device *dev = (struct net_device *)data; + netif_rx_schedule(dev); +} + + static void network_alloc_rx_buffers(struct net_device *dev) { unsigned short id; @@ -534,7 +543,7 @@ * Allocate skbuffs greedily, even though we batch updates to the * receive ring. This creates a less bursty demand on the memory * allocator, so should reduce the chance of failed allocation requests - * both for ourself and for other kernel subsystems. + * both for ourself and for other kernel subsystems. */ batch_target = np->rx_target - (req_prod - np->rx.rsp_cons); for (i = skb_queue_len(&np->rx_batch); i < batch_target; i++) { @@ -545,8 +554,15 @@ skb = alloc_xen_skb( ((PAGE_SIZE - sizeof(struct skb_shared_info)) & (-SKB_DATA_ALIGN(1))) - 16); - if (skb == NULL) - break; + if (skb == NULL) { + /* Any skbuffs queued for refill? Force them out. */ + if (i != 0) + goto refill; + /* Could not allocate any skbuffs. Try again later. */ + mod_timer(&np->rx_refill_timer, + jiffies + (HZ/10)); + return; + } __skb_queue_tail(&np->rx_batch, skb); } @@ -554,6 +570,12 @@ if (i < (np->rx_target/2)) return; + /* Adjust our fill target if we risked running out of buffers. */ + if (((req_prod - np->rx.sring->rsp_prod) < (np->rx_target / 4)) && + ((np->rx_target *= 2) > np->rx_max_target)) + np->rx_target = np->rx_max_target; + + refill: for (i = 0; ; i++) { if ((skb = __skb_dequeue(&np->rx_batch)) == NULL) break; @@ -608,11 +630,6 @@ /* Above is a suitable barrier to ensure backend will see requests. */ np->rx.req_prod_pvt = req_prod + i; RING_PUSH_REQUESTS(&np->rx); - - /* Adjust our fill target if we risked running out of buffers. */ - if (((req_prod - np->rx.sring->rsp_prod) < (np->rx_target / 4)) && - ((np->rx_target *= 2) > np->rx_max_target)) - np->rx_target = np->rx_max_target; } @@ -1077,6 +1094,10 @@ np->rx_min_target = RX_MIN_TARGET; np->rx_max_target = RX_MAX_TARGET; + init_timer(&np->rx_refill_timer); + np->rx_refill_timer.data = (unsigned long)netdev; + np->rx_refill_timer.function = rx_refill_timeout; + /* Initialise {tx,rx}_skbs as a free chain containing every entry. */ for (i = 0; i <= NET_TX_RING_SIZE; i++) { np->tx_skbs[i] = (void *)((unsigned long) i+1); @@ -1188,33 +1209,14 @@ DPRINTK("%s\n", dev->nodename); - netif_free(info); - kfree(info); + netif_disconnect_backend(info); + free_netdev(info->netdev); return 0; } -static void netif_free(struct netfront_info *info) -{ - netif_disconnect_backend(info); - close_netdev(info); -} - - static void close_netdev(struct netfront_info *info) -{ - if (info->netdev) { -#ifdef CONFIG_PROC_FS - xennet_proc_delif(info->netdev); -#endif - unregister_netdev(info->netdev); - info->netdev = NULL; - } -} - - -static void netif_disconnect_backend(struct netfront_info *info) { /* Stop old i/f to prevent errors whilst we rebuild the state. */ spin_lock_irq(&info->tx_lock); @@ -1223,17 +1225,37 @@ /* info->backend_state = BEST_DISCONNECTED; */ spin_unlock(&info->rx_lock); spin_unlock_irq(&info->tx_lock); - + +#ifdef CONFIG_PROC_FS + xennet_proc_delif(info->netdev); +#endif + + if (info->irq) + unbind_from_irqhandler(info->irq, info->netdev); + info->evtchn = info->irq = 0; + + del_timer_sync(&info->rx_refill_timer); + + unregister_netdev(info->netdev); +} + + +static void netif_disconnect_backend(struct netfront_info *info) +{ end_access(info->tx_ring_ref, info->tx.sring); end_access(info->rx_ring_ref, info->rx.sring); info->tx_ring_ref = GRANT_INVALID_REF; info->rx_ring_ref = GRANT_INVALID_REF; info->tx.sring = NULL; info->rx.sring = NULL; - - if (info->irq) - unbind_from_irqhandler(info->irq, info->netdev); - info->evtchn = info->irq = 0; +} + + +static void netif_free(struct netfront_info *info) +{ + close_netdev(info); + netif_disconnect_backend(info); + free_netdev(info->netdev); } diff -r 903fb46f240e -r cd914808acf1 tools/examples/xmexample.vmx --- a/tools/examples/xmexample.vmx Tue Jan 3 14:59:00 2006 +++ b/tools/examples/xmexample.vmx Tue Jan 3 16:19:20 2006 @@ -29,6 +29,9 @@ #----------------------------------------------------------------------------- # the number of cpus guest platform has, default=1 vcpus=1 + +# enable/disalbe vmx guest ACPI, default=0 (disabled) +#acpi=0 # List of which CPUS this domain is allowed to use, default Xen picks #cpus = "" # leave to Xen to pick diff -r 903fb46f240e -r cd914808acf1 tools/firmware/vmxassist/Makefile --- a/tools/firmware/vmxassist/Makefile Tue Jan 3 14:59:00 2006 +++ b/tools/firmware/vmxassist/Makefile Tue Jan 3 16:19:20 2006 @@ -24,7 +24,7 @@ # The emulator code lives in ROM space TEXTADDR=0x000D0000 -DEFINES=-DDEBUG -D_ACPI_ -DTEXTADDR=$(TEXTADDR) +DEFINES=-DDEBUG -DTEXTADDR=$(TEXTADDR) XENINC=-I$(XEN_ROOT)/tools/libxc LD = ld diff -r 903fb46f240e -r cd914808acf1 tools/firmware/vmxassist/acpi_madt.c --- a/tools/firmware/vmxassist/acpi_madt.c Tue Jan 3 14:59:00 2006 +++ b/tools/firmware/vmxassist/acpi_madt.c Tue Jan 3 16:19:20 2006 @@ -24,23 +24,75 @@ extern int puts(const char *s); -#define VCPU_NR_PAGE 0x0009F000 -#define VCPU_NR_OFFSET 0x00000800 -#define VCPU_MAGIC 0x76637075 /* "vcpu" */ +#define HVM_INFO_PAGE 0x0009F000 +#define HVM_INFO_OFFSET 0x00000800 -/* xc_vmx_builder wrote vcpu block at 0x9F800. Return it. */ +struct hvm_info_table { + char signature[8]; /* "HVM INFO" */ + uint32_t length; + uint8_t checksum; + uint8_t acpi_enabled; + uint8_t pad[2]; + uint32_t nr_vcpus; +}; + +static struct hvm_info_table *table = NULL; + static int +checksum_valid(uint8_t *ptr, int len) +{ + uint8_t sum=0; + int i; + + for (i = 0; i < len; i++) + sum += ptr[i]; + + return (sum == 0); +} + +/* xc_vmx_builder wrote hvm info at 0x9F800. Return it. */ +static struct hvm_info_table * +get_hvm_info_table(void) +{ + struct hvm_info_table *t; + char signature[] = "HVM INFO"; + int i; + + if (table != NULL) + return table; + + t = (struct hvm_info_table *)(HVM_INFO_PAGE + HVM_INFO_OFFSET); + + /* strncmp(t->signature, "HVM INFO", 8) */ + for (i = 0; i < 8; i++) { + if (signature[i] != t->signature[i]) { + puts("Bad hvm info signature\n"); + return NULL; + } + } + + if (!checksum_valid((uint8_t *)t, t->length)) { + puts("Bad hvm info checksum\n"); + return NULL; + } + + table = t; + + return table; +} + +int get_vcpu_nr(void) { - unsigned int *vcpus; + struct hvm_info_table *t = get_hvm_info_table(); + return (t ? t->nr_vcpus : 1); /* default 1 vcpu */ +} - vcpus = (unsigned int *)(VCPU_NR_PAGE + VCPU_NR_OFFSET); - if (vcpus[0] != VCPU_MAGIC) { - puts("Bad vcpus magic, set vcpu number to 1 by default.\n"); - return 1; - } - - return vcpus[1]; +int +get_acpi_enabled(void) +{ + struct hvm_info_table *t = get_hvm_info_table(); + return (t ? t->acpi_enabled : 0); /* default no acpi */ } static void * diff -r 903fb46f240e -r cd914808acf1 tools/firmware/vmxassist/vmxloader.c --- a/tools/firmware/vmxassist/vmxloader.c Tue Jan 3 14:59:00 2006 +++ b/tools/firmware/vmxassist/vmxloader.c Tue Jan 3 16:19:20 2006 @@ -24,12 +24,10 @@ #include "machine.h" #include "roms.h" -#ifdef _ACPI_ #include "acpi.h" #include "../acpi/acpi2_0.h" // for ACPI_PHYSICAL_ADDRESS int acpi_madt_update(unsigned char* acpi_start); -#endif - +int get_acpi_enabled(void); /* * C runtime start off @@ -120,18 +118,17 @@ memcpy((void *)0xC0000, vgabios_stdvga, sizeof(vgabios_stdvga)); } -#ifdef _ACPI_ - puts("Loading ACPI ...\n"); - acpi_madt_update(acpi); - - if (ACPI_PHYSICAL_ADDRESS+sizeof(acpi) <= 0xF0000) { - /* make sure acpi table does not overlap rombios - * currently acpi less than 8K will be OK. - */ - memcpy((void *)ACPI_PHYSICAL_ADDRESS, acpi, sizeof(acpi)); + if (get_acpi_enabled() != 0) { + puts("Loading ACPI ...\n"); + acpi_madt_update((unsigned char*)acpi); + if (ACPI_PHYSICAL_ADDRESS+sizeof(acpi) <= 0xF0000) { + /* make sure acpi table does not overlap rombios + * currently acpi less than 8K will be OK. + */ + memcpy((void *)ACPI_PHYSICAL_ADDRESS, acpi, sizeof(acpi)); + } } -#endif puts("Loading VMXAssist ...\n"); memcpy((void *)TEXTADDR, vmxassist, sizeof(vmxassist)); diff -r 903fb46f240e -r cd914808acf1 tools/ioemu/vl.c --- a/tools/ioemu/vl.c Tue Jan 3 14:59:00 2006 +++ b/tools/ioemu/vl.c Tue Jan 3 16:19:20 2006 @@ -2948,6 +2948,7 @@ case QEMU_OPTION_vcpus: vcpus = atoi(optarg); fprintf(logfile, "qemu: the number of cpus is %d\n", vcpus); + break; case QEMU_OPTION_pci: pci_enabled = 1; break; diff -r 903fb46f240e -r cd914808acf1 tools/libxc/Makefile --- a/tools/libxc/Makefile Tue Jan 3 14:59:00 2006 +++ b/tools/libxc/Makefile Tue Jan 3 16:19:20 2006 @@ -27,6 +27,11 @@ ifeq ($(XEN_TARGET_ARCH),x86_32) SRCS += xc_ptrace.c SRCS += xc_ptrace_core.c +SRCS += xc_pagetab.c +endif + +ifeq ($(XEN_TARGET_ARCH),x86_64) +SRCS += xc_pagetab.c endif BUILD_SRCS := diff -r 903fb46f240e -r cd914808acf1 tools/libxc/xc_domain.c --- a/tools/libxc/xc_domain.c Tue Jan 3 14:59:00 2006 +++ b/tools/libxc/xc_domain.c Tue Jan 3 16:19:20 2006 @@ -404,6 +404,38 @@ } +int xc_domain_irq_permission(int xc_handle, + uint32_t domid, + uint8_t pirq, + uint8_t allow_access) +{ + dom0_op_t op; + + op.cmd = DOM0_IRQ_PERMISSION; + op.u.irq_permission.domain = domid; + op.u.irq_permission.pirq = pirq; + op.u.irq_permission.allow_access = allow_access; + + return do_dom0_op(xc_handle, &op); +} + +int xc_domain_iomem_permission(int xc_handle, + uint32_t domid, + unsigned long first_pfn, + unsigned long nr_pfns, + uint8_t allow_access) +{ + dom0_op_t op; + + op.cmd = DOM0_IOMEM_PERMISSION; + op.u.iomem_permission.domain = domid; + op.u.iomem_permission.first_pfn = first_pfn; + op.u.iomem_permission.nr_pfns = nr_pfns; + op.u.iomem_permission.allow_access = allow_access; + + return do_dom0_op(xc_handle, &op); +} + /* * Local variables: * mode: C diff -r 903fb46f240e -r cd914808acf1 tools/libxc/xc_vmx_build.c --- a/tools/libxc/xc_vmx_build.c Tue Jan 3 14:59:00 2006 +++ b/tools/libxc/xc_vmx_build.c Tue Jan 3 16:19:20 2006 @@ -33,8 +33,17 @@ #define E820_MAP_NR_OFFSET 0x000001E8 #define E820_MAP_OFFSET 0x000002D0 -#define VCPU_NR_PAGE 0x0009F000 -#define VCPU_NR_OFFSET 0x00000800 +#define HVM_INFO_PAGE 0x0009F000 +#define HVM_INFO_OFFSET 0x00000800 + +struct hvm_info_table { + char signature[8]; /* "HVM INFO" */ + uint32_t length; + uint8_t checksum; + uint8_t acpi_enabled; + uint8_t pad[2]; + uint32_t nr_vcpus; +}; struct e820entry { uint64_t addr; @@ -119,26 +128,45 @@ return (*(((unsigned char *)e820_page) + E820_MAP_NR_OFFSET) = nr_map); } +static void +set_hvm_info_checksum(struct hvm_info_table *t) +{ + uint8_t *ptr = (uint8_t *)t, sum = 0; + unsigned int i; + + t->checksum = 0; + + for (i = 0; i < t->length; i++) + sum += *ptr++; + + t->checksum = -sum; +} + /* - * Use E820 reserved memory 0x9F800 to pass number of vcpus to vmxloader - * vmxloader will use it to config ACPI MADT table + * Use E820 reserved memory 0x9F800 to pass HVM info to vmxloader + * vmxloader will use this info to set BIOS accordingly */ -#define VCPU_MAGIC 0x76637075 /* "vcpu" */ -static int set_vcpu_nr(int xc_handle, uint32_t dom, - unsigned long *pfn_list, unsigned int vcpus) -{ - char *va_map; - unsigned int *va_vcpus; +static int set_hvm_info(int xc_handle, uint32_t dom, + unsigned long *pfn_list, unsigned int vcpus, + unsigned int acpi) +{ + char *va_map; + struct hvm_info_table *va_hvm; va_map = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE, - pfn_list[VCPU_NR_PAGE >> PAGE_SHIFT]); + pfn_list[HVM_INFO_PAGE >> PAGE_SHIFT]); if ( va_map == NULL ) return -1; - va_vcpus = (unsigned int *)(va_map + VCPU_NR_OFFSET); - va_vcpus[0] = VCPU_MAGIC; - va_vcpus[1] = vcpus; + va_hvm = (struct hvm_info_table *)(va_map + HVM_INFO_OFFSET); + memset(va_hvm, 0, sizeof(*va_hvm)); + strncpy(va_hvm->signature, "HVM INFO", 8); + va_hvm->length = sizeof(struct hvm_info_table); + va_hvm->acpi_enabled = acpi; + va_hvm->nr_vcpus = vcpus; + + set_hvm_info_checksum(va_hvm); munmap(va_map, PAGE_SIZE); @@ -281,6 +309,7 @@ unsigned int control_evtchn, unsigned int lapic, unsigned int vcpus, + unsigned int acpi, unsigned int store_evtchn, unsigned long *store_mfn) { @@ -490,8 +519,8 @@ goto error_out; } - if (set_vcpu_nr(xc_handle, dom, page_array, vcpus)) { - fprintf(stderr, "Couldn't set vcpu number for VMX guest.\n"); + if (set_hvm_info(xc_handle, dom, page_array, vcpus, acpi)) { + fprintf(stderr, "Couldn't set hvm info for VMX guest.\n"); goto error_out; } @@ -574,29 +603,6 @@ return -1; } -#define VMX_FEATURE_FLAG 0x20 - -static int vmx_identify(void) -{ - int eax, ecx; - - __asm__ __volatile__ ( -#if defined(__i386__) - "push %%ebx; cpuid; pop %%ebx" -#elif defined(__x86_64__) - "push %%rbx; cpuid; pop %%rbx" -#endif - : "=a" (eax), "=c" (ecx) - : "0" (1) - : "dx"); - - if (!(ecx & VMX_FEATURE_FLAG)) { - return -1; - } - - return 0; -} - int xc_vmx_build(int xc_handle, uint32_t domid, int memsize, @@ -604,6 +610,7 @@ unsigned int control_evtchn, unsigned int lapic, unsigned int vcpus, + unsigned int acpi, unsigned int store_evtchn, unsigned long *store_mfn) { @@ -613,10 +620,18 @@ unsigned long nr_pages; char *image = NULL; unsigned long image_size; - - if ( vmx_identify() < 0 ) - { - PERROR("CPU doesn't support VMX Extensions"); + xen_capabilities_info_t xen_caps; + + if ( (rc = xc_version(xc_handle, XENVER_capabilities, &xen_caps)) != 0 ) + { + PERROR("Failed to get xen version info"); + goto error_out; + } + + if ( !strstr(xen_caps, "hvm") ) + { + PERROR("CPU doesn't support VMX Extensions or " + "CPU VMX Extensions are not turned on"); goto error_out; } @@ -659,7 +674,7 @@ if ( setup_guest(xc_handle, domid, memsize, image, image_size, nr_pages, ctxt, op.u.getdomaininfo.shared_info_frame, control_evtchn, - lapic, vcpus, store_evtchn, store_mfn) < 0) + lapic, vcpus, acpi, store_evtchn, store_mfn) < 0) { ERROR("Error constructing guest OS"); goto error_out; diff -r 903fb46f240e -r cd914808acf1 tools/libxc/xenctrl.h --- a/tools/libxc/xenctrl.h Tue Jan 3 14:59:00 2006 +++ b/tools/libxc/xenctrl.h Tue Jan 3 16:19:20 2006 @@ -380,6 +380,17 @@ uint32_t nr_ports, uint32_t allow_access); +int xc_domain_irq_permission(int xc_handle, + uint32_t domid, + uint8_t pirq, + uint8_t allow_access); + +int xc_domain_iomem_permission(int xc_handle, + uint32_t domid, + unsigned long first_pfn, + unsigned long nr_pfns, + uint8_t allow_access); + unsigned long xc_make_page_below_4G(int xc_handle, uint32_t domid, unsigned long mfn); @@ -415,6 +426,19 @@ void *xc_map_foreign_batch(int xc_handle, uint32_t dom, int prot, unsigned long *arr, int num ); + +/** + * Translates a virtual address in the context of a given domain and + * vcpu returning the machine page frame number of the associated + * page. + * + * @parm xc_handle a handle on an open hypervisor interface + * @parm dom the domain to perform the translation in + * @parm vcpu the vcpu to perform the translation on + * @parm virt the virtual address to translate + */ +unsigned long xc_translate_foreign_address(int xc_handle, uint32_t dom, + int vcpu, unsigned long long virt); int xc_get_pfn_list(int xc_handle, uint32_t domid, unsigned long *pfn_buf, unsigned long max_pfns); diff -r 903fb46f240e -r cd914808acf1 tools/libxc/xenguest.h --- a/tools/libxc/xenguest.h Tue Jan 3 14:59:00 2006 +++ b/tools/libxc/xenguest.h Tue Jan 3 16:19:20 2006 @@ -58,6 +58,7 @@ unsigned int control_evtchn, unsigned int lapic, unsigned int vcpus, + unsigned int acpi, unsigned int store_evtchn, unsigned long *store_mfn); diff -r 903fb46f240e -r cd914808acf1 tools/python/xen/lowlevel/xc/xc.c --- a/tools/python/xen/lowlevel/xc/xc.c Tue Jan 3 14:59:00 2006 +++ b/tools/python/xen/lowlevel/xc/xc.c Tue Jan 3 16:19:20 2006 @@ -364,19 +364,20 @@ int control_evtchn, store_evtchn; int vcpus = 1; int lapic = 0; + int acpi = 0; int memsize; unsigned long store_mfn = 0; static char *kwd_list[] = { "dom", "control_evtchn", "store_evtchn", - "memsize", "image", "lapic", "vcpus", NULL }; - - if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiisii", kwd_list, + "memsize", "image", "lapic", "vcpus", "acpi",NULL }; + + if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiisiii", kwd_list, &dom, &control_evtchn, &store_evtchn, - &memsize, &image, &lapic, &vcpus) ) + &memsize, &image, &lapic, &vcpus,&acpi) ) return NULL; if ( xc_vmx_build(self->xc_handle, dom, memsize, image, control_evtchn, - lapic, vcpus, store_evtchn, &store_mfn) != 0 ) + lapic, vcpus, acpi, store_evtchn, &store_mfn) != 0 ) return PyErr_SetFromErrno(xc_error); return Py_BuildValue("{s:i}", "store_mfn", store_mfn); @@ -774,6 +775,52 @@ return zero; } +static PyObject *pyxc_domain_irq_permission(PyObject *self, + PyObject *args, + PyObject *kwds) +{ + XcObject *xc = (XcObject *)self; + uint32_t dom; + int pirq, allow_access, ret; + + static char *kwd_list[] = { "dom", "pirq", "allow_access", NULL }; + + if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iii", kwd_list, + &dom, &pirq, &allow_access) ) + return NULL; + + ret = xc_domain_irq_permission( + xc->xc_handle, dom, pirq, allow_access); + if ( ret != 0 ) + return PyErr_SetFromErrno(xc_error); + + Py_INCREF(zero); + return zero; +} + +static PyObject *pyxc_domain_iomem_permission(PyObject *self, + PyObject *args, + PyObject *kwds) +{ + XcObject *xc = (XcObject *)self; + uint32_t dom; + unsigned long first_pfn, nr_pfns, allow_access, ret; + + static char *kwd_list[] = { "dom", "first_pfn", "nr_pfns", "allow_access", NULL }; + + if ( !PyArg_ParseTupleAndKeywords(args, kwds, "illi", kwd_list, + &dom, &first_pfn, &nr_pfns, &allow_access) ) + return NULL; + + ret = xc_domain_iomem_permission( + xc->xc_handle, dom, first_pfn, nr_pfns, allow_access); + if ( ret != 0 ) + return PyErr_SetFromErrno(xc_error); + + Py_INCREF(zero); + return zero; +} + static PyObject *dom_op(XcObject *self, PyObject *args, int (*fn)(int, uint32_t)) @@ -1067,6 +1114,25 @@ " dom [int]: Identifier of domain to be allowed access.\n" " first_port [int]: First IO port\n" " nr_ports [int]: Number of IO ports\n" + " allow_access [int]: Non-zero means enable access; else disable access\n\n" + "Returns: [int] 0 on success; -1 on error.\n" }, + + { "domain_irq_permission", + (PyCFunction)pyxc_domain_irq_permission, + METH_VARARGS | METH_KEYWORDS, "\n" + "Allow a domain access to a physical IRQ\n" + " dom [int]: Identifier of domain to be allowed access.\n" + " pirq [int]: The Physical IRQ\n" + " allow_access [int]: Non-zero means enable access; else disable access\n\n" + "Returns: [int] 0 on success; -1 on error.\n" }, + + { "domain_iomem_permission", + (PyCFunction)pyxc_domain_iomem_permission, + METH_VARARGS | METH_KEYWORDS, "\n" + "Allow a domain access to a range of IO memory pages\n" + " dom [int]: Identifier of domain to be allowed access.\n" + " first_pfn [long]: First page of I/O Memory\n" + " nr_pfns [long]: Number of pages of I/O Memory (>0)\n" " allow_access [int]: Non-zero means enable access; else disable access\n\n" "Returns: [int] 0 on success; -1 on error.\n" }, diff -r 903fb46f240e -r cd914808acf1 tools/python/xen/xend/image.py --- a/tools/python/xen/xend/image.py Tue Jan 3 14:59:00 2006 +++ b/tools/python/xen/xend/image.py Tue Jan 3 16:19:20 2006 @@ -189,11 +189,16 @@ def configure(self, imageConfig, deviceConfig): ImageHandler.configure(self, imageConfig, deviceConfig) + info = xc.xeninfo() + if not 'hvm' in info['xen_caps']: + raise VmError("vmx: not an Intel VT platform, we stop creating!") + self.dmargs = self.parseDeviceModelArgs(imageConfig, deviceConfig) self.device_model = sxp.child_value(imageConfig, 'device_model') if not self.device_model: raise VmError("vmx: missing device model") self.display = sxp.child_value(imageConfig, 'display') + self.xauthority = sxp.child_value(imageConfig, 'xauthority') self.vm.storeVm(("image/dmargs", " ".join(self.dmargs)), ("image/device-model", self.device_model), @@ -209,6 +214,8 @@ if not lapic is None: self.lapic = int(lapic) + self.acpi = int(sxp.child_value(imageConfig, 'acpi', 0)) + def buildDomain(self): # Create an event channel self.device_channel = xc.evtchn_alloc_unbound(dom=self.vm.getDomid(), @@ -224,6 +231,7 @@ log.debug("memsize = %d", self.vm.getMemoryTarget() / 1024) log.debug("lapic = %d", self.lapic) log.debug("vcpus = %d", self.vm.getVCpuCount()) + log.debug("acpi = %d", self.acpi) return xc.vmx_build(dom = self.vm.getDomid(), image = self.kernel, @@ -231,8 +239,8 @@ store_evtchn = store_evtchn, memsize = self.vm.getMemoryTarget() / 1024, lapic = self.lapic, + acpi = self.acpi, vcpus = self.vm.getVCpuCount()) - # Return a list of cmd line args to the device models based on the # xm config file @@ -264,44 +272,44 @@ nics = 0 for (name, info) in deviceConfig: if name == 'vbd': - uname = sxp.child_value(info, 'uname') - typedev = sxp.child_value(info, 'dev') - (_, vbdparam) = string.split(uname, ':', 1) - if re.match('^ioemu:', typedev): - (emtype, vbddev) = string.split(typedev, ':', 1) - else: - emtype = 'vbd' - vbddev = typedev - if emtype != 'ioemu': - continue; - vbddev_list = ['hda', 'hdb', 'hdc', 'hdd'] - if vbddev not in vbddev_list: - raise VmError("vmx: for qemu vbd type=file&dev=hda~hdd") - ret.append("-%s" % vbddev) - ret.append("%s" % vbdparam) + uname = sxp.child_value(info, 'uname') + typedev = sxp.child_value(info, 'dev') + (_, vbdparam) = string.split(uname, ':', 1) + if 'ioemu:' in typedev: + (emtype, vbddev) = string.split(typedev, ':', 1) + else: + emtype = 'vbd' + vbddev = typedev + if emtype == 'vbd': + continue; + vbddev_list = ['hda', 'hdb', 'hdc', 'hdd'] + if vbddev not in vbddev_list: + raise VmError("vmx: for qemu vbd type=file&dev=hda~hdd") + ret.append("-%s" % vbddev) + ret.append("%s" % vbdparam) if name == 'vif': - type = sxp.child_value(info, 'type') - if type != 'ioemu': - continue - nics += 1 - if mac != None: - continue - mac = sxp.child_value(info, 'mac') - bridge = sxp.child_value(info, 'bridge') - if mac == None: - mac = randomMAC() - if bridge == None: - bridge = 'xenbr0' - ret.append("-macaddr") - ret.append("%s" % mac) - ret.append("-bridge") - ret.append("%s" % bridge) + type = sxp.child_value(info, 'type') + if type != 'ioemu': + continue + nics += 1 + if mac != None: + continue + mac = sxp.child_value(info, 'mac') + bridge = sxp.child_value(info, 'bridge') + if mac == None: + mac = randomMAC() + if bridge == None: + bridge = 'xenbr0' + ret.append("-macaddr") + ret.append("%s" % mac) + ret.append("-bridge") + ret.append("%s" % bridge) if name == 'vtpm': - instance = sxp.child_value(info, 'pref_instance') - ret.append("-instance") - ret.append("%s" % instance) + instance = sxp.child_value(info, 'pref_instance') + ret.append("-instance") + ret.append("%s" % instance) ret.append("-nics") - ret.append("%d" % nics) + ret.append("%d" % nics) return ret def configVNC(self, config): @@ -340,6 +348,8 @@ env = dict(os.environ) if self.display: env['DISPLAY'] = self.display + if self.xauthority: + env['XAUTHORITY'] = self.xauthority log.info("spawning device models: %s %s", self.device_model, args) self.pid = os.spawnve(os.P_NOWAIT, self.device_model, args, env) log.info("device model pid: %d", self.pid) diff -r 903fb46f240e -r cd914808acf1 tools/python/xen/xend/server/blkif.py --- a/tools/python/xen/xend/server/blkif.py Tue Jan 3 14:59:00 2006 +++ b/tools/python/xen/xend/server/blkif.py Tue Jan 3 16:19:20 2006 @@ -31,7 +31,7 @@ """Block device interface controller. Handles all block devices for a domain. """ - + def __init__(self, vm): """Create a block device controller. """ @@ -40,9 +40,9 @@ def getDeviceDetails(self, config): """@see DevController.getDeviceDetails""" - + dev = sxp.child_value(config, 'dev') - if re.match('^ioemu:', dev): + if 'ioemu:' in dev: return (None,{},{}) devid = blkif.blkdev_name_to_number(dev) diff -r 903fb46f240e -r cd914808acf1 tools/python/xen/xm/create.py --- a/tools/python/xen/xm/create.py Tue Jan 3 14:59:00 2006 +++ b/tools/python/xen/xm/create.py Tue Jan 3 16:19:20 2006 @@ -164,6 +164,10 @@ fn=set_int, default=0, use="Disable or enable local APIC of VMX domain.") +gopts.var('acpi', val='ACPI', + fn=set_int, default=0, + use="Disable or enable ACPI of VMX domain.") + gopts.var('vcpus', val='VCPUS', fn=set_int, default=1, use="# of Virtual CPUS in domain.") @@ -387,6 +391,10 @@ gopts.var('display', val='DISPLAY', fn=set_value, default=None, use="X11 display to use") + +gopts.var('xauthority', val='XAUTHORITY', + fn=set_value, default=None, + use="X11 Authority to use") def err(msg): @@ -526,7 +534,8 @@ """ args = [ 'device_model', 'vcpus', 'cdrom', 'boot', 'fda', 'fdb', 'localtime', 'serial', 'stdvga', 'isa', 'nographic', 'audio', - 'vnc', 'vncviewer', 'sdl', 'display', 'ne2000', 'lapic'] + 'vnc', 'vncviewer', 'sdl', 'display', 'ne2000', 'lapic', + 'xauthority', 'acpi' ] for a in args: if (vals.__dict__[a]): config_image.append([a, vals.__dict__[a]]) @@ -801,6 +810,9 @@ if not gopts.vals.display: gopts.vals.display = os.getenv("DISPLAY") + if not gopts.vals.xauthority: + gopts.vals.xauthority = os.getenv("XAUTHORITY") + # Process remaining args as config variables. for arg in args: if '=' in arg: diff -r 903fb46f240e -r cd914808acf1 tools/python/xen/xm/main.py --- a/tools/python/xen/xm/main.py Tue Jan 3 14:59:00 2006 +++ b/tools/python/xen/xm/main.py Tue Jan 3 16:19:20 2006 @@ -75,7 +75,7 @@ vcpu_set_help = """vcpu-set <DomId> <VCPUs> Set the number of VCPUs for a domain""" vcpu_list_help = "vcpu-list <DomId> List the VCPUs for a domain (or all domains)" vcpu_pin_help = "vcpu-pin <DomId> <VCPU> <CPUs> Set which cpus a VCPU can use" -dmesg_help = "dmesg [--clear] Read or clear Xen's message buffer" +dmesg_help = "dmesg [-c|--clear] Read or clear Xen's message buffer" info_help = "info Get information about the xen host" rename_help = "rename <DomId> <New Name> Rename a domain" log_help = "log Print the xend log" @@ -672,7 +672,7 @@ server.xend_node_clear_dmesg() def xm_log(args): - arg_check(args, 'xm-log', 0) + arg_check(args, "log", 0) from xen.xend.XendClient import server print server.xend_node_log() @@ -845,8 +845,8 @@ "balloon": "mem-set", "set-vcpus": "vcpu-set", "vif-list": "network-list", - "vbd-create": "block-create", - "vbd-destroy": "block-destroy", + "vbd-create": "block-attach", + "vbd-destroy": "block-detach", "vbd-list": "block-list", } diff -r 903fb46f240e -r cd914808acf1 tools/vtpm_manager/README --- a/tools/vtpm_manager/README Tue Jan 3 14:59:00 2006 +++ b/tools/vtpm_manager/README Tue Jan 3 16:19:20 2006 @@ -53,11 +53,6 @@ MANUAL_DM_LAUNCH -> Must manually launch & kill VTPMs -WELL_KNOWN_SRK_AUTH -> Rather than randomly generating the password for the SRK, - use a well known value. This is necessary for sharing use - of the SRK across applications. Such as VTPM and Dom0 - measurement software. - WELL_KNOWN_OWNER_AUTH -> Rather than randomly generating the password for the owner, use a well known value. This is useful for debugging and for poor bios which do not support clearing TPM if OwnerAuth is diff -r 903fb46f240e -r cd914808acf1 tools/vtpm_manager/Rules.mk --- a/tools/vtpm_manager/Rules.mk Tue Jan 3 14:59:00 2006 +++ b/tools/vtpm_manager/Rules.mk Tue Jan 3 16:19:20 2006 @@ -56,8 +56,7 @@ # Do not have manager launch DMs. #CFLAGS += -DMANUAL_DM_LAUNCH -# Fixed SRK -CFLAGS += -DWELL_KNOWN_SRK_AUTH +# Fixed OwnerAuth #CFLAGS += -DWELL_KNOWN_OWNER_AUTH # TPM Hardware Device or TPM Simulator diff -r 903fb46f240e -r cd914808acf1 tools/vtpm_manager/manager/securestorage.c --- a/tools/vtpm_manager/manager/securestorage.c Tue Jan 3 14:59:00 2006 +++ b/tools/vtpm_manager/manager/securestorage.c Tue Jan 3 16:19:20 2006 @@ -65,7 +65,7 @@ UINT32 i; struct pack_constbuf_t symkey_cipher32, data_cipher32; - vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Enveloping[%d]: 0x", buffer_len(inbuf)); + vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Enveloping Input[%d]: 0x", buffer_len(inbuf)); for (i=0; i< buffer_len(inbuf); i++) vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", inbuf->bytes[i]); vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n"); @@ -94,6 +94,12 @@ BSG_TPM_SIZE32_DATA, &data_cipher32); vtpmloginfo(VTPM_LOG_VTPM, "Saved %d bytes of E(symkey) + %d bytes of E(data)\n", buffer_len(&symkey_cipher), buffer_len(&data_cipher)); + + vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Enveloping Output[%d]: 0x", buffer_len(sealed_data)); + for (i=0; i< buffer_len(sealed_data); i++) + vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", sealed_data->bytes[i]); + vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n"); + goto egress; abort_egress: @@ -125,7 +131,7 @@ memset(&symkey, 0, sizeof(symkey_t)); - vtpmloginfo(VTPM_LOG_VTPM_DEEP, "envelope decrypting[%ld]: 0x", cipher_size); + vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Envelope Decrypt Input[%ld]: 0x", cipher_size); for (i=0; i< cipher_size; i++) vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", cipher[i]); vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n"); @@ -155,6 +161,11 @@ // Decrypt State TPMTRY(TPM_DECRYPT_ERROR, Crypto_symcrypto_decrypt (&symkey, &data_cipher, unsealed_data) ); + + vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Envelope Decrypte Output[%d]: 0x", buffer_len(unsealed_data)); + for (i=0; i< buffer_len(unsealed_data); i++) + vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", unsealed_data->bytes[i]); + vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n"); goto egress; @@ -291,124 +302,175 @@ return status; } + TPM_RESULT VTPM_SaveService(void) { TPM_RESULT status=TPM_SUCCESS; int fh, dmis=-1; - - BYTE *flat_global; - int flat_global_size, bytes_written; + + BYTE *flat_boot_key, *flat_dmis, *flat_enc; + buffer_t clear_flat_global, enc_flat_global; UINT32 storageKeySize = buffer_len(&vtpm_globals->storageKeyWrap); + UINT32 bootKeySize = buffer_len(&vtpm_globals->bootKeyWrap); struct pack_buf_t storage_key_pack = {storageKeySize, vtpm_globals->storageKeyWrap.bytes}; - + struct pack_buf_t boot_key_pack = {bootKeySize, vtpm_globals->bootKeyWrap.bytes}; + struct hashtable_itr *dmi_itr; VTPM_DMI_RESOURCE *dmi_res; - - UINT32 flat_global_full_size; - - // Global Values needing to be saved - flat_global_full_size = 3*sizeof(TPM_DIGEST) + // Auths - sizeof(UINT32) + // storagekeysize - storageKeySize + // storage key - hashtable_count(vtpm_globals->dmi_map) * // num DMIS - (sizeof(UINT32) + 2*sizeof(TPM_DIGEST)); // Per DMI info - - - flat_global = (BYTE *) malloc( flat_global_full_size); - - flat_global_size = BSG_PackList(flat_global, 4, - BSG_TPM_AUTHDATA, &vtpm_globals->owner_usage_auth, - BSG_TPM_AUTHDATA, &vtpm_globals->srk_usage_auth, - BSG_TPM_SECRET, &vtpm_globals->storage_key_usage_auth, - BSG_TPM_SIZE32_DATA, &storage_key_pack); - + + UINT32 boot_key_size, flat_dmis_size; + + // Initially fill these with buffer sizes for each data type. Later fill + // in actual size, once flattened. + boot_key_size = sizeof(UINT32) + // bootkeysize + bootKeySize; // boot key + + TPMTRYRETURN(buffer_init(&clear_flat_global, 3*sizeof(TPM_DIGEST) + // Auths + sizeof(UINT32) +// storagekeysize + storageKeySize, NULL) ); // storage key + + flat_dmis_size = (hashtable_count(vtpm_globals->dmi_map) - 1) * // num DMIS (-1 for Dom0) + (sizeof(UINT32) + 2*sizeof(TPM_DIGEST)); // Per DMI info + + flat_boot_key = (BYTE *) malloc( boot_key_size ); + flat_enc = (BYTE *) malloc( sizeof(UINT32) ); + flat_dmis = (BYTE *) malloc( flat_dmis_size ); + + boot_key_size = BSG_PackList(flat_boot_key, 1, + BSG_TPM_SIZE32_DATA, &boot_key_pack); + + BSG_PackList(clear_flat_global.bytes, 3, + BSG_TPM_AUTHDATA, &vtpm_globals->owner_usage_auth, + BSG_TPM_SECRET, &vtpm_globals->storage_key_usage_auth, + BSG_TPM_SIZE32_DATA, &storage_key_pack); + + TPMTRYRETURN(envelope_encrypt(&clear_flat_global, + &vtpm_globals->bootKey, + &enc_flat_global) ); + + BSG_PackConst(buffer_len(&enc_flat_global), 4, flat_enc); + // Per DMI values to be saved if (hashtable_count(vtpm_globals->dmi_map) > 0) { - + dmi_itr = hashtable_iterator(vtpm_globals->dmi_map); do { dmi_res = (VTPM_DMI_RESOURCE *) hashtable_iterator_value(dmi_itr); dmis++; // No need to save dmi0. - if (dmi_res->dmi_id == 0) - continue; - - - flat_global_size += BSG_PackList( flat_global + flat_global_size, 3, - BSG_TYPE_UINT32, &dmi_res->dmi_id, - BSG_TPM_DIGEST, &dmi_res->NVM_measurement, - BSG_TPM_DIGEST, &dmi_res->DMI_measurement); - + if (dmi_res->dmi_id == 0) + continue; + + + flat_dmis_size += BSG_PackList( flat_dmis + flat_dmis_size, 3, + BSG_TYPE_UINT32, &dmi_res->dmi_id, + BSG_TPM_DIGEST, &dmi_res->NVM_measurement, + BSG_TPM_DIGEST, &dmi_res->DMI_measurement); + } while (hashtable_iterator_advance(dmi_itr)); } - - //FIXME: Once we have a way to protect a TPM key, we should use it to - // encrypt this blob. BUT, unless there is a way to ensure the key is - // not used by other apps, this encryption is useless. + fh = open(STATE_FILE, O_WRONLY | O_CREAT, S_IREAD | S_IWRITE); if (fh == -1) { vtpmlogerror(VTPM_LOG_VTPM, "Unable to open %s file for write.\n", STATE_FILE); status = TPM_IOERROR; goto abort_egress; } - - if ( (bytes_written = write(fh, flat_global, flat_global_size)) != flat_global_size ) { - vtpmlogerror(VTPM_LOG_VTPM, "Failed to save service data. %d/%d bytes written.\n", bytes_written, flat_global_size); - status = TPM_IOERROR; - goto abort_egress; - } - vtpm_globals->DMI_table_dirty = FALSE; - + + if ( ( write(fh, flat_boot_key, boot_key_size) != boot_key_size ) || + ( write(fh, flat_enc, sizeof(UINT32)) != sizeof(UINT32) ) || + ( write(fh, enc_flat_global.bytes, buffer_len(&enc_flat_global)) != buffer_len(&enc_flat_global) ) || + ( write(fh, flat_dmis, flat_dmis_size) != flat_dmis_size ) ) { + vtpmlogerror(VTPM_LOG_VTPM, "Failed to completely write service data.\n"); + status = TPM_IOERROR; + goto abort_egress; + } + + vtpm_globals->DMI_table_dirty = FALSE; + goto egress; - + abort_egress: egress: - - free(flat_global); + + free(flat_boot_key); + free(flat_enc); + buffer_free(&enc_flat_global); + free(flat_dmis); close(fh); - + vtpmloginfo(VTPM_LOG_VTPM, "Saved VTPM Service state (status = %d, dmis = %d)\n", (int) status, dmis); return status; } TPM_RESULT VTPM_LoadService(void) { - + TPM_RESULT status=TPM_SUCCESS; int fh, stat_ret, dmis=0; long fh_size = 0, step_size; - BYTE *flat_global=NULL; - struct pack_buf_t storage_key_pack; - UINT32 *dmi_id_key; - + BYTE *flat_table=NULL; + buffer_t unsealed_data; + struct pack_buf_t storage_key_pack, boot_key_pack; + UINT32 *dmi_id_key, enc_size; + VTPM_DMI_RESOURCE *dmi_res; struct stat file_stat; - + + TPM_HANDLE boot_key_handle; + TPM_AUTHDATA boot_usage_auth; + memset(&boot_usage_auth, 0, sizeof(TPM_AUTHDATA)); + fh = open(STATE_FILE, O_RDONLY ); stat_ret = fstat(fh, &file_stat); - if (stat_ret == 0) + if (stat_ret == 0) fh_size = file_stat.st_size; else { status = TPM_IOERROR; goto abort_egress; } - - flat_global = (BYTE *) malloc(fh_size); - - if ((long) read(fh, flat_global, fh_size) != fh_size ) { - status = TPM_IOERROR; - goto abort_egress; - } - + + flat_table = (BYTE *) malloc(fh_size); + + if ((long) read(fh, flat_table, fh_size) != fh_size ) { + status = TPM_IOERROR; + goto abort_egress; + } + + // Read Boot Key + step_size = BSG_UnpackList( flat_table, 2, + BSG_TPM_SIZE32_DATA, &boot_key_pack, + BSG_TYPE_UINT32, &enc_size); + + TPMTRYRETURN(buffer_init(&vtpm_globals->bootKeyWrap, 0, 0) ); + TPMTRYRETURN(buffer_append_raw(&vtpm_globals->bootKeyWrap, boot_key_pack.size, boot_key_pack.data) ); + + //Load Boot Key + TPMTRYRETURN( VTSP_LoadKey( vtpm_globals->manager_tcs_handle, + TPM_SRK_KEYHANDLE, + &vtpm_globals->bootKeyWrap, + &SRK_AUTH, + &boot_key_handle, + &vtpm_globals->keyAuth, + &vtpm_globals->bootKey, + FALSE) ); + + TPMTRYRETURN( envelope_decrypt(enc_size, + flat_table + step_size, + vtpm_globals->manager_tcs_handle, + boot_key_handle, + (const TPM_AUTHDATA*) &boot_usage_auth, + &unsealed_data) ); + step_size += enc_size; + // Global Values needing to be saved - step_size = BSG_UnpackList( flat_global, 4, - BSG_TPM_AUTHDATA, &vtpm_globals->owner_usage_auth, - BSG_TPM_AUTHDATA, &vtpm_globals->srk_usage_auth, - BSG_TPM_SECRET, &vtpm_globals->storage_key_usage_auth, - BSG_TPM_SIZE32_DATA, &storage_key_pack); - + BSG_UnpackList( unsealed_data.bytes, 3, + BSG_TPM_AUTHDATA, &vtpm_globals->owner_usage_auth, + BSG_TPM_SECRET, &vtpm_globals->storage_key_usage_auth, + BSG_TPM_SIZE32_DATA, &storage_key_pack); + TPMTRYRETURN(buffer_init(&vtpm_globals->storageKeyWrap, 0, 0) ); TPMTRYRETURN(buffer_append_raw(&vtpm_globals->storageKeyWrap, storage_key_pack.size, storage_key_pack.data) ); - + // Per DMI values to be saved while ( step_size < fh_size ){ if (fh_size - step_size < (long) (sizeof(UINT32) + 2*sizeof(TPM_DIGEST))) { @@ -417,35 +479,38 @@ } else { dmi_res = (VTPM_DMI_RESOURCE *) malloc(sizeof(VTPM_DMI_RESOURCE)); dmis++; - + dmi_res->connected = FALSE; - - step_size += BSG_UnpackList(flat_global + step_size, 3, - BSG_TYPE_UINT32, &dmi_res->dmi_id, - BSG_TPM_DIGEST, &dmi_res->NVM_measurement, - BSG_TPM_DIGEST, &dmi_res->DMI_measurement); - + + step_size += BSG_UnpackList(flat_table + step_size, 3, + BSG_TYPE_UINT32, &dmi_res->dmi_id, + BSG_TPM_DIGEST, &dmi_res->NVM_measurement, + BSG_TPM_DIGEST, &dmi_res->DMI_measurement); + // install into map dmi_id_key = (UINT32 *) malloc (sizeof(UINT32)); *dmi_id_key = dmi_res->dmi_id; if (!hashtable_insert(vtpm_globals->dmi_map, dmi_id_key, dmi_res)) { - status = TPM_FAIL; - goto abort_egress; + status = TPM_FAIL; + goto abort_egress; } - + } - - } - + + } + vtpmloginfo(VTPM_LOG_VTPM, "Loaded saved state (dmis = %d).\n", dmis); goto egress; - + abort_egress: vtpmlogerror(VTPM_LOG_VTPM, "Failed to load service data with error = %s\n", tpm_get_error_name(status)); egress: - - free(flat_global); + + free(flat_table); close(fh); - + + // TODO: Could be nice and evict BootKey. (Need to add EvictKey to VTSP. + return status; } + diff -r 903fb46f240e -r cd914808acf1 tools/vtpm_manager/manager/vtpm_manager.c --- a/tools/vtpm_manager/manager/vtpm_manager.c Tue Jan 3 14:59:00 2006 +++ b/tools/vtpm_manager/manager/vtpm_manager.c Tue Jan 3 16:19:20 2006 @@ -74,16 +74,15 @@ #endif // --------------------------- Well Known Auths -------------------------- -#ifdef WELL_KNOWN_SRK_AUTH -static BYTE FIXED_SRK_AUTH[20] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +const TPM_AUTHDATA SRK_AUTH = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; -#endif #ifdef WELL_KNOWN_OWNER_AUTH static BYTE FIXED_OWNER_AUTH[20] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; #endif - + + // -------------------------- Hash table functions -------------------- static unsigned int hashfunc32(void *ky) { @@ -100,13 +99,7 @@ TPM_RESULT status = TPM_SUCCESS; - // Generate Auth's for SRK & Owner -#ifdef WELL_KNOWN_SRK_AUTH - memcpy(vtpm_globals->srk_usage_auth, FIXED_SRK_AUTH, sizeof(TPM_AUTHDATA)); -#else - Crypto_GetRandom(vtpm_globals->srk_usage_auth, sizeof(TPM_AUTHDATA) ); -#endif - + // Generate Auth for Owner #ifdef WELL_KNOWN_OWNER_AUTH memcpy(vtpm_globals->owner_usage_auth, FIXED_OWNER_AUTH, sizeof(TPM_AUTHDATA)); #else @@ -116,14 +109,14 @@ // Take Owership of TPM CRYPTO_INFO ek_cryptoInfo; - vtpmloginfo(VTPM_LOG_VTPM, "Attempting Pubek Read. NOTE: Failure is ok.\n"); status = VTSP_ReadPubek(vtpm_globals->manager_tcs_handle, &ek_cryptoInfo); // If we can read PubEK then there is no owner and we should take it. if (status == TPM_SUCCESS) { + vtpmloginfo(VTPM_LOG_VTPM, "Failed to readEK meaning TPM has an owner. Creating Keys off existing SRK.\n"); TPMTRYRETURN(VTSP_TakeOwnership(vtpm_globals->manager_tcs_handle, (const TPM_AUTHDATA*)&vtpm_globals->owner_usage_auth, - (const TPM_AUTHDATA*)&vtpm_globals->srk_usage_auth, + &SRK_AUTH, &ek_cryptoInfo, &vtpm_globals->keyAuth)); @@ -142,7 +135,7 @@ TPMTRYRETURN( VTSP_OSAP(vtpm_globals->manager_tcs_handle, TPM_ET_KEYHANDLE, TPM_SRK_KEYHANDLE, - (const TPM_AUTHDATA*)&vtpm_globals->srk_usage_auth, + &SRK_AUTH, &sharedsecret, &osap) ); @@ -157,8 +150,43 @@ &vtpm_globals->storageKeyWrap, &osap) ); - vtpm_globals->keyAuth.fContinueAuthSession = TRUE; - + // Generate boot key's auth + Crypto_GetRandom( &vtpm_globals->storage_key_usage_auth, + sizeof(TPM_AUTHDATA) ); + + TPM_AUTHDATA bootKeyWrapAuth; + memset(&bootKeyWrapAuth, 0, sizeof(bootKeyWrapAuth)); + + TPMTRYRETURN( VTSP_OSAP(vtpm_globals->manager_tcs_handle, + TPM_ET_KEYHANDLE, + TPM_SRK_KEYHANDLE, + &SRK_AUTH, + &sharedsecret, + &osap) ); + + osap.fContinueAuthSession = FALSE; + + // FIXME: This key protects the global secrets on disk. It should use TPM + // PCR bindings to limit its use to legit configurations. + // Current binds are open, implying a Trusted VM contains this code. + // If this VM is not Trusted, use measurement and PCR bindings. + TPMTRYRETURN( VTSP_CreateWrapKey( vtpm_globals->manager_tcs_handle, + TPM_KEY_BIND, + (const TPM_AUTHDATA*)&bootKeyWrapAuth, + TPM_SRK_KEYHANDLE, + (const TPM_AUTHDATA*)&sharedsecret, + &vtpm_globals->bootKeyWrap, + &osap) ); + + // Populate CRYPTO_INFO vtpm_globals->bootKey. This does not load it into the TPM + TPMTRYRETURN( VTSP_LoadKey( vtpm_globals->manager_tcs_handle, + TPM_SRK_KEYHANDLE, + &vtpm_globals->bootKeyWrap, + NULL, + NULL, + NULL, + &vtpm_globals->bootKey, + TRUE ) ); goto egress; abort_egress: @@ -278,24 +306,26 @@ #endif // Check status of rx_fh. If necessary attempt to re-open it. + char* s = NULL; if (*rx_fh < 0) { #ifdef VTPM_MULTI_VM - *rx_fh = open(VTPM_BE_DEV, O_RDWR); + s = VTPM_BE_DEV; #else if (threadType == BE_LISTENER_THREAD) #ifdef DUMMY_BACKEND - *rx_fh = open("/tmp/in.fifo", O_RDWR); + s = "/tmp/in.fifo"; #else - *rx_fh = open(VTPM_BE_DEV, O_RDWR); + s = VTPM_BE_DEV; #endif else // DMI Listener - *rx_fh = open(VTPM_RX_FIFO, O_RDWR); + s = VTPM_RX_FIFO; + *rx_fh = open(s, O_RDWR); #endif } // Respond to failures to open rx_fh if (*rx_fh < 0) { - vtpmhandlerlogerror(VTPM_LOG_VTPM, "Can't open inbound fh.\n"); + vtpmhandlerlogerror(VTPM_LOG_VTPM, "Can't open inbound fh for %s.\n", s); #ifdef VTPM_MULTI_VM return TPM_IOERROR; #else @@ -713,7 +743,7 @@ /////////////////////////////////////////////////////////////////////////////// TPM_RESULT VTPM_Init_Service() { - TPM_RESULT status = TPM_FAIL; + TPM_RESULT status = TPM_FAIL, serviceStatus; BYTE *randomsead; UINT32 randomsize; @@ -737,7 +767,7 @@ // Create new TCS Object vtpm_globals->manager_tcs_handle = 0; - + TPMTRYRETURN(TCS_create()); // Create TCS Context for service @@ -756,17 +786,24 @@ vtpm_globals->keyAuth.fContinueAuthSession = TRUE; // If failed, create new Service. - if (VTPM_LoadService() != TPM_SUCCESS) + serviceStatus = VTPM_LoadService(); + if (serviceStatus == TPM_IOERROR) { + vtpmloginfo(VTPM_LOG_VTPM, "Failed to read service file. Assuming first time initialization.\n"); TPMTRYRETURN( VTPM_Create_Service() ); + } else if (serviceStatus != TPM_SUCCESS) { + vtpmlogerror(VTPM_LOG_VTPM, "Failed to read existing service file"); + exit(1); + } //Load Storage Key TPMTRYRETURN( VTSP_LoadKey( vtpm_globals->manager_tcs_handle, TPM_SRK_KEYHANDLE, &vtpm_globals->storageKeyWrap, - (const TPM_AUTHDATA*)&vtpm_globals->srk_usage_auth, + &SRK_AUTH, &vtpm_globals->storageKeyHandle, &vtpm_globals->keyAuth, - &vtpm_globals->storageKey) ); + &vtpm_globals->storageKey, + FALSE ) ); // Create entry for Dom0 for control messages TPMTRYRETURN( VTPM_Handle_New_DMI(NULL) ); @@ -797,12 +834,11 @@ free (dmi_itr); } - + if ( (vtpm_globals->DMI_table_dirty) && (VTPM_SaveService() != TPM_SUCCESS) ) + vtpmlogerror(VTPM_LOG_VTPM, "Unable to save manager data.\n"); + TCS_CloseContext(vtpm_globals->manager_tcs_handle); - - if ( (vtpm_globals->DMI_table_dirty) && - (VTPM_SaveService() != TPM_SUCCESS) ) - vtpmlogerror(VTPM_LOG_VTPM, "Unable to save manager data.\n"); + TCS_destroy(); hashtable_destroy(vtpm_globals->dmi_map, 1); free(vtpm_globals); diff -r 903fb46f240e -r cd914808acf1 tools/vtpm_manager/manager/vtpmpriv.h --- a/tools/vtpm_manager/manager/vtpmpriv.h Tue Jan 3 14:59:00 2006 +++ b/tools/vtpm_manager/manager/vtpmpriv.h Tue Jan 3 16:19:20 2006 @@ -108,6 +108,7 @@ TCS_CONTEXT_HANDLE manager_tcs_handle; // TCS Handle used by manager TPM_HANDLE storageKeyHandle; // Key used by persistent store CRYPTO_INFO storageKey; // For software encryption + CRYPTO_INFO bootKey; // For saving table TCS_AUTH keyAuth; // OIAP session for storageKey BOOL DMI_table_dirty; // Indicates that a command // has updated the DMI table @@ -115,15 +116,17 @@ // Persistent Data TPM_AUTHDATA owner_usage_auth; // OwnerAuth of real TPM - TPM_AUTHDATA srk_usage_auth; // SRK Auth of real TPM buffer_t storageKeyWrap; // Wrapped copy of storageKey + TPM_AUTHDATA srk_usage_auth; + TPM_AUTHDATA storage_key_usage_auth; - TPM_AUTHDATA storage_key_usage_auth; - + buffer_t bootKeyWrap; // Wrapped copy of boot key + }VTPM_GLOBALS; -//Global dmi map -extern VTPM_GLOBALS *vtpm_globals; +// --------------------------- Global Values -------------------------- +extern VTPM_GLOBALS *vtpm_globals; // Key info and DMI states +extern const TPM_AUTHDATA SRK_AUTH; // SRK Well Known Auth Value // ********************** Command Handler Prototypes *********************** TPM_RESULT VTPM_Handle_Load_NVM( VTPM_DMI_RESOURCE *myDMI, diff -r 903fb46f240e -r cd914808acf1 tools/vtpm_manager/manager/vtsp.c --- a/tools/vtpm_manager/manager/vtsp.c Tue Jan 3 14:59:00 2006 +++ b/tools/vtpm_manager/manager/vtsp.c Tue Jan 3 16:19:20 2006 @@ -563,63 +563,69 @@ const TPM_AUTHDATA *parentAuth, TPM_HANDLE *newKeyHandle, TCS_AUTH *auth, - CRYPTO_INFO *cryptoinfo /*= NULL*/) { - - - vtpmloginfo(VTPM_LOG_VTSP, "Loading Key.\n%s",""); + CRYPTO_INFO *cryptoinfo, + const BOOL skipTPMLoad) { + + + vtpmloginfo(VTPM_LOG_VTSP, "Loading Key %s.\n", (!skipTPMLoad ? "into TPM" : "only into memory")); TPM_RESULT status = TPM_SUCCESS; TPM_COMMAND_CODE command = TPM_ORD_LoadKey; - - BYTE *paramText; // Digest to make Auth. + + BYTE *paramText=NULL; // Digest to make Auth. UINT32 paramTextSize; - - if ((rgbWrappedKeyBlob == NULL) || (parentAuth == NULL) || - (newKeyHandle==NULL) || (auth==NULL)) { - status = TPM_BAD_PARAMETER; - goto abort_egress; - } - - // Generate Extra TCS Parameters - TPM_HANDLE phKeyHMAC; - - // Generate HMAC - Crypto_GetRandom(&auth->NonceOdd, sizeof(TPM_NONCE) ); - - paramText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH); - - paramTextSize = BSG_PackList(paramText, 1, - BSG_TPM_COMMAND_CODE, &command); - - memcpy(paramText + paramTextSize, rgbWrappedKeyBlob->bytes, buffer_len(rgbWrappedKeyBlob)); - paramTextSize += buffer_len(rgbWrappedKeyBlob); - - TPMTRYRETURN( GenerateAuth( paramText, paramTextSize, + + // SkipTPMLoad stops key from being loaded into TPM, but still generates CRYPTO_INFO for it + if (! skipTPMLoad) { + + if ((rgbWrappedKeyBlob == NULL) || (parentAuth == NULL) || + (newKeyHandle==NULL) || (auth==NULL)) { + status = TPM_BAD_PARAMETER; + goto abort_egress; + } + + // Generate Extra TCS Parameters + TPM_HANDLE phKeyHMAC; + + // Generate HMAC + Crypto_GetRandom(&auth->NonceOdd, sizeof(TPM_NONCE) ); + + paramText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH); + + paramTextSize = BSG_PackList(paramText, 1, + BSG_TPM_COMMAND_CODE, &command); + + memcpy(paramText + paramTextSize, rgbWrappedKeyBlob->bytes, buffer_len(rgbWrappedKeyBlob)); + paramTextSize += buffer_len(rgbWrappedKeyBlob); + + TPMTRYRETURN( GenerateAuth( paramText, paramTextSize, parentAuth, auth) ); - // Call TCS - TPMTRYRETURN( TCSP_LoadKeyByBlob( hContext, - hUnwrappingKey, - buffer_len(rgbWrappedKeyBlob), - rgbWrappedKeyBlob->bytes, - auth, - newKeyHandle, - &phKeyHMAC) ); - - // Verify Auth - paramTextSize = BSG_PackList(paramText, 3, - BSG_TPM_RESULT, &status, - BSG_TPM_COMMAND_CODE, &command, - BSG_TPM_HANDLE, newKeyHandle); - - TPMTRYRETURN( VerifyAuth( paramText, paramTextSize, - parentAuth, auth, - hContext) ); - - // Unpack/return key structure + // Call TCS + TPMTRYRETURN( TCSP_LoadKeyByBlob( hContext, + hUnwrappingKey, + buffer_len(rgbWrappedKeyBlob), + rgbWrappedKeyBlob->bytes, + auth, + newKeyHandle, + &phKeyHMAC) ); + + // Verify Auth + paramTextSize = BSG_PackList(paramText, 3, + BSG_TPM_RESULT, &status, + BSG_TPM_COMMAND_CODE, &command, + BSG_TPM_HANDLE, newKeyHandle); + + TPMTRYRETURN( VerifyAuth( paramText, paramTextSize, + parentAuth, auth, + hContext) ); + } + + // Build cryptoinfo structure for software crypto function. if (cryptoinfo != NULL) { TPM_KEY newKey; + // Unpack/return key structure BSG_Unpack(BSG_TPM_KEY, rgbWrappedKeyBlob->bytes , &newKey); TPM_RSA_KEY_PARMS rsaKeyParms; diff -r 903fb46f240e -r cd914808acf1 tools/vtpm_manager/manager/vtsp.h --- a/tools/vtpm_manager/manager/vtsp.h Tue Jan 3 14:59:00 2006 +++ b/tools/vtpm_manager/manager/vtsp.h Tue Jan 3 16:19:20 2006 @@ -86,7 +86,8 @@ const TPM_AUTHDATA *parentAuth, TPM_HANDLE *newKeyHandle, TCS_AUTH *pAuth, - CRYPTO_INFO *cryptoinfo); + CRYPTO_INFO *cryptoinfo, + const BOOL skipTPMLoad); TPM_RESULT VTSP_Unbind( const TCS_CONTEXT_HANDLE hContext, const TPM_KEY_HANDLE key_handle, diff -r 903fb46f240e -r cd914808acf1 tools/xentrace/Makefile --- a/tools/xentrace/Makefile Tue Jan 3 14:59:00 2006 +++ b/tools/xentrace/Makefile Tue Jan 3 16:19:20 2006 @@ -15,25 +15,37 @@ OBJS = $(patsubst %.c,%.o,$(wildcard *.c)) BIN = xentrace tbctl setsize +LIBBIN = SCRIPTS = xentrace_format MAN1 = $(wildcard *.1) MAN8 = $(wildcard *.8) +ifeq ($(XEN_TARGET_ARCH),x86_32) +LIBBIN += xenctx +endif + +ifeq ($(XEN_TARGET_ARCH),x86_64) +LIBBIN += xenctx +endif + all: build -build: $(BIN) +build: $(BIN) $(LIBBIN) install: build [ -d $(DESTDIR)/usr/bin ] || $(INSTALL_DIR) $(DESTDIR)/usr/bin + [ -z "$(LIBBIN)"] || [ -d $(DESTDIR)/usr/$(LIBDIR)/xen/bin ] || \ + $(INSTALL_DIR) $(DESTDIR)/usr/$(LIBDIR)/xen/bin [ -d $(DESTDIR)/usr/share/man/man1 ] || \ $(INSTALL_DIR) $(DESTDIR)/usr/share/man/man1 [ -d $(DESTDIR)/usr/share/man/man8 ] || \ $(INSTALL_DIR) $(DESTDIR)/usr/share/man/man8 $(INSTALL_PROG) $(BIN) $(SCRIPTS) $(DESTDIR)/usr/bin + [ -z "$(LIBBIN)"] || $(INSTALL_PROG) $(LIBBIN) $(DESTDIR)/usr/$(LIBDIR)/xen/bin $(INSTALL_DATA) $(MAN1) $(DESTDIR)/usr/share/man/man1 $(INSTALL_DATA) $(MAN8) $(DESTDIR)/usr/share/man/man8 clean: - $(RM) *.a *.so *.o *.rpm $(BIN) + $(RM) *.a *.so *.o *.rpm $(BIN) $(LIBBIN) %: %.c $(HDRS) Makefile $(CC) $(CFLAGS) -o $@ $< -L$(XEN_LIBXC) -lxenctrl diff -r 903fb46f240e -r cd914808acf1 tools/xentrace/xenctx.c --- a/tools/xentrace/xenctx.c Tue Jan 3 14:59:00 2006 +++ b/tools/xentrace/xenctx.c Tue Jan 3 16:19:20 2006 @@ -20,15 +20,184 @@ #include <errno.h> #include <argp.h> #include <signal.h> +#include <string.h> +#include <getopt.h> #include "xenctrl.h" + +int xc_handle = 0; +int domid = 0; +int frame_ptrs = 0; +int stack_trace = 0; + +#if defined (__i386__) +#define FMT_SIZE_T "%08x" +#define STACK_POINTER(regs) (regs->esp) +#define FRAME_POINTER(regs) (regs->ebp) +#define INSTR_POINTER(regs) (regs->eip) +#define STACK_ROWS 4 +#define STACK_COLS 8 +#elif defined (__x86_64__) +#define FMT_SIZE_T "%016lx" +#define STACK_POINTER(regs) (regs->rsp) +#define FRAME_POINTER(regs) (regs->rbp) +#define INSTR_POINTER(regs) (regs->rip) +#define STACK_ROWS 4 +#define STACK_COLS 4 +#endif + +struct symbol { + size_t address; + char type; + char *name; + struct symbol *next; +} *symbol_table = NULL; + +size_t kernel_stext, kernel_etext, kernel_sinittext, kernel_einittext; + +int is_kernel_text(size_t addr) +{ +#if defined (__i386__) + if (symbol_table == NULL) + return (addr > 0xc000000); +#elif defined (__x86_64__) + if (symbol_table == NULL) + return (addr > 0xffffffff80000000UL); +#endif + + if (addr >= kernel_stext && + addr <= kernel_etext) + return 1; + if (addr >= kernel_sinittext && + addr <= kernel_einittext) + return 1; + return 0; +} + +void free_symbol(struct symbol *symbol) +{ + if (symbol == NULL) + return; + if (symbol->name) + free(symbol->name); + free(symbol); +} + +void insert_symbol(struct symbol *symbol) +{ + static struct symbol *prev = NULL; + struct symbol *s = symbol_table; + + if (s == NULL) { + symbol_table = symbol; + symbol->next = NULL; + return; + } + + /* The System.map is usually already sorted... */ + if (prev + && prev->address < symbol->address + && (!prev->next || prev->next->address > symbol->address)) { + s = prev; + } else { + /* ... otherwise do crappy/slow search for the correct place */ + while(s && s->next && s->next->address < symbol->address) + s = s->next; + } + + symbol->next = s->next; + s->next = symbol; + prev = symbol; +} + +struct symbol *lookup_symbol(size_t address) +{ + struct symbol *s = symbol_table; + + while(s && s->next && s->next->address < address) + s = s->next; + + if (s && s->address < address) + return s; + + return NULL; +} + +void print_symbol(size_t addr) +{ + struct symbol *s; + + if (!is_kernel_text(addr)) + return; + + s = lookup_symbol(addr); + + if (s==NULL) + return; + + if (addr==s->address) + printf("%s", s->name); + else + printf("%s+%#x", s->name, (unsigned int)(addr - s->address)); +} + +void read_symbol_table(const char *symtab) +{ + char line[256]; + char *p; + struct symbol *symbol; + FILE *f; + + f = fopen(symtab, "r"); + if(f == NULL) { + fprintf(stderr, "failed to open symbol table %s\n", symtab); + exit(-1); + } + + while(!feof(f)) { + if(fgets(line,256,f)==NULL) + break; + + symbol = malloc(sizeof(*symbol)); + + /* need more checks for syntax here... */ + symbol->address = strtoull(line, &p, 16); + p++; + symbol->type = *p++; + p++; + + /* in the future we should handle the module name + * being appended here, this would allow us to use + * /proc/kallsyms as our symbol table + */ + if (p[strlen(p)-1] == '\n') + p[strlen(p)-1] = '\0'; + symbol->name = strdup(p); + + insert_symbol(symbol); + + if (strcmp(symbol->name, "_stext") == 0) + kernel_stext = symbol->address; + else if (strcmp(symbol->name, "_etext") == 0) + kernel_etext = symbol->address; + else if (strcmp(symbol->name, "_sinittext") == 0) + kernel_sinittext = symbol->address; + else if (strcmp(symbol->name, "_einittext") == 0) + kernel_einittext = symbol->address; + } + + fclose(f); +} #ifdef __i386__ void print_ctx(vcpu_guest_context_t *ctx1) { struct cpu_user_regs *regs = &ctx1->user_regs; - printf("eip: %08x\t", regs->eip); + printf("eip: %08x ", regs->eip); + print_symbol(regs->eip); + printf("\n"); + printf("esp: %08x\n", regs->esp); printf("eax: %08x\t", regs->eax); @@ -51,7 +220,9 @@ { struct cpu_user_regs *regs = &ctx1->user_regs; - printf("rip: %08lx\t", regs->rip); + printf("rip: %08lx ", regs->rip); + print_symbol(regs->rip); + printf("\n"); printf("rsp: %08lx\n", regs->rsp); printf("rax: %08lx\t", regs->rax); @@ -63,8 +234,8 @@ printf("rdi: %08lx\t", regs->rdi); printf("rbp: %08lx\n", regs->rbp); - printf("r8: %08lx\t", regs->r8); - printf("r9: %08lx\t", regs->r9); + printf(" r8: %08lx\t", regs->r8); + printf(" r9: %08lx\t", regs->r9); printf("r10: %08lx\t", regs->r10); printf("r11: %08lx\n", regs->r11); @@ -81,35 +252,238 @@ } #endif -void dump_ctx(uint32_t domid, uint32_t vcpu) +void *map_page(vcpu_guest_context_t *ctx, int vcpu, size_t virt) +{ + static unsigned long previous_mfn = 0; + static void *mapped = NULL; + + unsigned long mfn = xc_translate_foreign_address(xc_handle, domid, vcpu, virt); + unsigned long offset = virt & ~XC_PAGE_MASK; + + if (mapped && mfn == previous_mfn) + goto out; + + if (mapped) + munmap(mapped, XC_PAGE_SIZE); + + previous_mfn = mfn; + + mapped = xc_map_foreign_range(xc_handle, domid, XC_PAGE_SIZE, PROT_READ, mfn); + + if (mapped == NULL) { + fprintf(stderr, "failed to map page.\n"); + exit(-1); + } + + out: + return (void *)(mapped + offset); +} + +void print_stack(vcpu_guest_context_t *ctx, int vcpu) +{ + struct cpu_user_regs *regs = &ctx->user_regs; + size_t stack = STACK_POINTER(regs); + size_t stack_limit = (STACK_POINTER(regs) & XC_PAGE_MASK) + XC_PAGE_SIZE; + size_t frame; + size_t instr; + size_t *p; + int i; + + printf("\n"); + printf("Stack:\n"); + for (i=1; i<STACK_ROWS+1 && stack < stack_limit; i++) { + while(stack < stack_limit && stack < STACK_POINTER(regs) + i*STACK_COLS*sizeof(stack)) { + p = map_page(ctx, vcpu, stack); + printf(" " FMT_SIZE_T, *p); + stack += sizeof(stack); + } + printf("\n"); + } + printf("\n"); + + printf("Code:\n"); + instr = INSTR_POINTER(regs) - 21; + for(i=0; i<32; i++) { + unsigned char *c = map_page(ctx, vcpu, instr+i); + if (instr+i == INSTR_POINTER(regs)) + printf("<%02x> ", *c); + else + printf("%02x ", *c); + } + printf("\n"); + + printf("\n"); + + if(stack_trace) + printf("Stack Trace:\n"); + else + printf("Call Trace:\n"); + printf("%c [<" FMT_SIZE_T ">] ", stack_trace ? '*' : ' ', INSTR_POINTER(regs)); + + print_symbol(INSTR_POINTER(regs)); + printf(" <--\n"); + if (frame_ptrs) { + stack = STACK_POINTER(regs); + frame = FRAME_POINTER(regs); + while(frame && stack < stack_limit) { + if (stack_trace) { + while (stack < frame) { + p = map_page(ctx, vcpu, stack); + printf("| " FMT_SIZE_T " ", *p); + printf("\n"); + stack += sizeof(*p); + } + } else { + stack = frame; + } + + p = map_page(ctx, vcpu, stack); + frame = *p; + if (stack_trace) + printf("|-- " FMT_SIZE_T "\n", *p); + stack += sizeof(*p); + + if (frame) { + p = map_page(ctx, vcpu, stack); + printf("%c [<" FMT_SIZE_T ">] ", stack_trace ? '|' : ' ', *p); + print_symbol(*p); + printf("\n"); + stack += sizeof(*p); + } + } + } else { + stack = STACK_POINTER(regs); + while(stack < stack_limit) { + p = map_page(ctx, vcpu, stack); + if (is_kernel_text(*p)) { + printf(" [<" FMT_SIZE_T ">] ", *p); + print_symbol(*p); + printf("\n"); + } else if (stack_trace) { + printf(" " FMT_SIZE_T "\n", *p); + } + stack += sizeof(*p); + } + } +} + +void dump_ctx(int vcpu) { int ret; vcpu_guest_context_t ctx; - int xc_handle = xc_interface_open(); /* for accessing control interface */ + xc_handle = xc_interface_open(); /* for accessing control interface */ + + ret = xc_domain_pause(xc_handle, domid); + if (ret < 0) { + perror("xc_domain_pause"); + exit(-1); + } ret = xc_domain_get_vcpu_context(xc_handle, domid, vcpu, &ctx); - if (ret != 0) { + if (ret < 0) { + xc_domain_unpause(xc_handle, domid); perror("xc_domain_get_vcpu_context"); exit(-1); } + print_ctx(&ctx); + if (is_kernel_text(ctx.user_regs.eip)) + print_stack(&ctx, vcpu); + + ret = xc_domain_unpause(xc_handle, domid); + if (ret < 0) { + perror("xc_domain_unpause"); + exit(-1); + } + xc_interface_close(xc_handle); + if (ret < 0) { + perror("xc_interface_close"); + exit(-1); + } +} + +void usage(void) +{ + printf("usage:\n\n"); + + printf(" xenctx [options] <DOMAIN> [VCPU]\n\n"); + + printf("options:\n"); + printf(" -f, --frame-pointers\n"); + printf(" assume the kernel was compiled with\n"); + printf(" frame pointers.\n"); + printf(" -s SYMTAB, --symbol-table=SYMTAB\n"); + printf(" read symbol table from SYMTAB.\n"); + printf(" --stack-trace print a complete stack trace.\n"); } int main(int argc, char **argv) { + int ch; + const char *sopts = "fs:h"; + const struct option lopts[] = { + {"stack-trace", 0, NULL, 'S'}, + {"symbol-table", 1, NULL, 's'}, + {"frame-pointers", 0, NULL, 'f'}, + {"help", 0, NULL, 'h'}, + {0, 0, 0, 0} + }; + const char *symbol_table = NULL; + int vcpu = 0; - if (argc < 2) { - printf("usage: xenctx <domid> <optional vcpu>\n"); - exit(-1); - } - - if (argc == 3) - vcpu = atoi(argv[2]); - - dump_ctx(atoi(argv[1]), vcpu); + while ((ch = getopt_long(argc, argv, sopts, lopts, NULL)) != -1) { + switch(ch) { + case 'f': + frame_ptrs = 1; + break; + case 's': + symbol_table = optarg; + break; + case 'S': + stack_trace = 1; + break; + case 'h': + usage(); + exit(-1); + case '?': + fprintf(stderr, "%s --help for more options\n", argv[0]); + exit(-1); + } + } + + argv += optind; argc -= optind; + + if (argc < 1 || argc > 2) { + printf("usage: xenctx [options] <domid> <optional vcpu>\n"); + exit(-1); + } + + domid = atoi(argv[0]); + if (domid==0) { + fprintf(stderr, "cannot trace dom0\n"); + exit(-1); + } + + if (argc == 2) + vcpu = atoi(argv[1]); + + if (symbol_table) + read_symbol_table(symbol_table); + + dump_ctx(vcpu); return 0; } + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff -r 903fb46f240e -r cd914808acf1 xen/arch/ia64/xen/domain.c --- a/xen/arch/ia64/xen/domain.c Tue Jan 3 14:59:00 2006 +++ b/xen/arch/ia64/xen/domain.c Tue Jan 3 16:19:20 2006 @@ -181,7 +181,7 @@ memset(v->arch._thread.fph,0,sizeof(struct ia64_fpreg)*96); } -void arch_do_createdomain(struct vcpu *v) +int arch_do_createdomain(struct vcpu *v) { struct domain *d = v->domain; struct thread_info *ti = alloc_thread_info(v); @@ -248,7 +248,9 @@ } } else d->arch.mm = NULL; - printf ("arch_do_create_domain: domain=%p\n", d); + printf ("arch_do_create_domain: domain=%p\n", d); + + return 0; } void arch_getdomaininfo_ctxt(struct vcpu *v, struct vcpu_guest_context *c) @@ -754,7 +756,10 @@ */ void physdev_init_dom0(struct domain *d) { - set_bit(_DOMF_physdev_access, &d->domain_flags); + if (iomem_permit_access(d, 0UL, ~0UL)) + BUG(); + if (irqs_permit_access(d, 0, NR_PIRQS-1)) + BUG(); } unsigned int vmx_dom0 = 0; diff -r 903fb46f240e -r cd914808acf1 xen/arch/ia64/xen/irq.c --- a/xen/arch/ia64/xen/irq.c Tue Jan 3 14:59:00 2006 +++ b/xen/arch/ia64/xen/irq.c Tue Jan 3 16:19:20 2006 @@ -1377,9 +1377,6 @@ irq_guest_action_t *action; unsigned long flags; int rc = 0; - - if ( !IS_CAPABLE_PHYSDEV(d->domain) ) - return -EPERM; spin_lock_irqsave(&desc->lock, flags); diff -r 903fb46f240e -r cd914808acf1 xen/arch/x86/Makefile --- a/xen/arch/x86/Makefile Tue Jan 3 14:59:00 2006 +++ b/xen/arch/x86/Makefile Tue Jan 3 16:19:20 2006 @@ -29,6 +29,7 @@ endif OBJS := $(subst $(TARGET_SUBARCH)/asm-offsets.o,,$(OBJS)) +OBJS := $(subst $(TARGET_SUBARCH)/xen.lds.o,,$(OBJS)) ifneq ($(crash_debug),y) OBJS := $(patsubst cdb%.o,,$(OBJS)) @@ -43,21 +44,24 @@ $(CURDIR)/arch.o: $(OBJS) $(LD) $(LDFLAGS) -r -o $@ $(OBJS) -$(TARGET)-syms: boot/$(TARGET_SUBARCH).o $(ALL_OBJS) $(TARGET_SUBARCH)/xen.lds - $(LD) $(LDFLAGS) -T $(TARGET_SUBARCH)/xen.lds -N \ +$(TARGET)-syms: boot/$(TARGET_SUBARCH).o $(ALL_OBJS) xen.lds + $(LD) $(LDFLAGS) -T xen.lds -N \ boot/$(TARGET_SUBARCH).o $(ALL_OBJS) -o $@ $(NM) -n $@ | $(BASEDIR)/tools/symbols >$(BASEDIR)/xen-syms.S $(MAKE) $(BASEDIR)/xen-syms.o - $(LD) $(LDFLAGS) -T $(TARGET_SUBARCH)/xen.lds -N \ + $(LD) $(LDFLAGS) -T xen.lds -N \ boot/$(TARGET_SUBARCH).o $(ALL_OBJS) $(BASEDIR)/xen-syms.o -o $@ $(NM) -n $@ | $(BASEDIR)/tools/symbols >$(BASEDIR)/xen-syms.S $(MAKE) $(BASEDIR)/xen-syms.o - $(LD) $(LDFLAGS) -T $(TARGET_SUBARCH)/xen.lds -N \ + $(LD) $(LDFLAGS) -T xen.lds -N \ boot/$(TARGET_SUBARCH).o $(ALL_OBJS) $(BASEDIR)/xen-syms.o -o $@ rm -f $(BASEDIR)/xen-syms.S $(BASEDIR)/xen-syms.o asm-offsets.s: $(TARGET_SUBARCH)/asm-offsets.c $(HDRS) $(CC) $(CFLAGS) -S -o $@ $< + +xen.lds: $(TARGET_SUBARCH)/xen.lds.S $(HDRS) + $(CC) $(CFLAGS) -P -E -Ui386 -D__ASSEMBLY__ -o $@ $< boot/mkelf32: boot/mkelf32.c $(HOSTCC) $(HOSTCFLAGS) -o $@ $< @@ -73,5 +77,6 @@ rm -f dm/*.o dm/*~ dm/core rm -f genapic/*.o genapic/*~ genapic/core rm -f cpu/*.o cpu/*~ cpu/core + rm -f xen.lds .PHONY: default clean diff -r 903fb46f240e -r cd914808acf1 xen/arch/x86/boot/x86_32.S --- a/xen/arch/x86/boot/x86_32.S Tue Jan 3 14:59:00 2006 +++ b/xen/arch/x86/boot/x86_32.S Tue Jan 3 16:19:20 2006 @@ -1,5 +1,6 @@ #include <xen/config.h> #include <public/xen.h> +#include <asm/asm_defns.h> #include <asm/desc.h> #include <asm/page.h> #include <asm/msr.h> @@ -53,6 +54,7 @@ mov %ecx,%gs ljmp $(__HYPERVISOR_CS),$(1f)-__PAGE_OFFSET 1: lss stack_start-__PAGE_OFFSET,%esp + add $(STACK_SIZE-CPUINFO_sizeof-__PAGE_OFFSET),%esp /* Reset EFLAGS (subsumes CLI and CLD). */ pushl $0 @@ -189,7 +191,7 @@ /*** STACK LOCATION ***/ ENTRY(stack_start) - .long cpu0_stack + STACK_SIZE - 200 - __PAGE_OFFSET + .long cpu0_stack .long __HYPERVISOR_DS /*** DESCRIPTOR TABLES ***/ @@ -256,10 +258,6 @@ .fill 1*PAGE_SIZE,1,0 #endif -#if (STACK_ORDER == 0) -.section ".bss.page_aligned","w" -#else -.section ".bss.twopage_aligned","w" -#endif +.section ".bss.stack_aligned","w" ENTRY(cpu0_stack) .fill STACK_SIZE,1,0 diff -r 903fb46f240e -r cd914808acf1 xen/arch/x86/boot/x86_64.S --- a/xen/arch/x86/boot/x86_64.S Tue Jan 3 14:59:00 2006 +++ b/xen/arch/x86/boot/x86_64.S Tue Jan 3 16:19:20 2006 @@ -1,5 +1,6 @@ #include <xen/config.h> #include <public/xen.h> +#include <asm/asm_defns.h> #include <asm/desc.h> #include <asm/page.h> #include <asm/msr.h> @@ -121,7 +122,8 @@ mov %rcx,%cr4 mov stack_start(%rip),%rsp - + or $(STACK_SIZE-CPUINFO_sizeof),%rsp + /* Reset EFLAGS (subsumes CLI and CLD). */ pushq $0 popf @@ -140,7 +142,7 @@ mov %ecx,%ss lidt idt_descr(%rip) - + cmp $(SECONDARY_CPU_FLAG),%ebx je start_secondary @@ -219,7 +221,7 @@ .quad idt_table ENTRY(stack_start) - .quad cpu0_stack + STACK_SIZE - 200 + .quad cpu0_stack high_start: .quad __high_start @@ -265,10 +267,6 @@ .org 0x4000 + PAGE_SIZE .code64 -#if (STACK_ORDER == 0) -.section ".bss.page_aligned","w" -#else -.section ".bss.twopage_aligned","w" -#endif +.section ".bss.stack_aligned","w" ENTRY(cpu0_stack) .fill STACK_SIZE,1,0 diff -r 903fb46f240e -r cd914808acf1 xen/arch/x86/dom0_ops.c --- a/xen/arch/x86/dom0_ops.c Tue Jan 3 14:59:00 2006 +++ b/xen/arch/x86/dom0_ops.c Tue Jan 3 16:19:20 2006 @@ -17,6 +17,7 @@ #include <asm/msr.h> #include <xen/trace.h> #include <xen/console.h> +#include <xen/iocap.h> #include <asm/shadow.h> #include <asm/irq.h> #include <asm/processor.h> @@ -141,7 +142,6 @@ struct domain *d; unsigned int fp = op->u.ioport_permission.first_port; unsigned int np = op->u.ioport_permission.nr_ports; - unsigned int p; ret = -EINVAL; if ( (fp + np) > 65536 ) @@ -152,26 +152,12 @@ op->u.ioport_permission.domain)) == NULL) ) break; - ret = -ENOMEM; - if ( d->arch.iobmp_mask != NULL ) - { - if ( (d->arch.iobmp_mask = xmalloc_array( - u8, IOBMP_BYTES)) == NULL ) - { - put_domain(d); - break; - } - memset(d->arch.iobmp_mask, 0xFF, IOBMP_BYTES); - } - - ret = 0; - for ( p = fp; p < (fp + np); p++ ) - { - if ( op->u.ioport_permission.allow_access ) - clear_bit(p, d->arch.iobmp_mask); - else - set_bit(p, d->arch.iobmp_mask); - } + if ( np == 0 ) + ret = 0; + else if ( op->u.ioport_permission.allow_access ) + ret = ioports_permit_access(d, fp, fp + np - 1); + else + ret = ioports_deny_access(d, fp, fp + np - 1); put_domain(d); } diff -r 903fb46f240e -r cd914808acf1 xen/arch/x86/domain.c --- a/xen/arch/x86/domain.c Tue Jan 3 14:59:00 2006 +++ b/xen/arch/x86/domain.c Tue Jan 3 16:19:20 2006 @@ -20,6 +20,7 @@ #include <xen/delay.h> #include <xen/softirq.h> #include <xen/grant_table.h> +#include <xen/iocap.h> #include <asm/regs.h> #include <asm/mc146818rtc.h> #include <asm/system.h> @@ -35,9 +36,7 @@ #include <xen/console.h> #include <xen/elf.h> #include <asm/vmx.h> -#include <asm/vmx_vmcs.h> #include <asm/msr.h> -#include <asm/physdev.h> #include <xen/kernel.h> #include <xen/multicall.h> @@ -98,7 +97,7 @@ cpu_set(smp_processor_id(), v->domain->cpumask); v->arch.schedule_tail = continue_idle_task; - idle_loop(); + reset_stack_and_jump(idle_loop); } static long no_idt[2]; @@ -185,11 +184,17 @@ { struct pfn_info *page; - if ( d->tot_pages < 10 ) + printk("Memory pages belonging to domain %u:\n", d->domain_id); + + if ( d->tot_pages >= 10 ) + { + printk(" DomPage list too long to display\n"); + } + else { list_for_each_entry ( page, &d->page_list, list ) { - printk("Page %p: mfn=%p, caf=%08x, taf=%" PRtype_info "\n", + printk(" DomPage %p: mfn=%p, caf=%08x, taf=%" PRtype_info "\n", _p(page_to_phys(page)), _p(page_to_pfn(page)), page->count_info, page->u.inuse.type_info); } @@ -197,15 +202,10 @@ list_for_each_entry ( page, &d->xenpage_list, list ) { - printk("XenPage %p: mfn=%p, caf=%08x, taf=%" PRtype_info "\n", + printk(" XenPage %p: mfn=%p, caf=%08x, taf=%" PRtype_info "\n", _p(page_to_phys(page)), _p(page_to_pfn(page)), page->count_info, page->u.inuse.type_info); } - - page = virt_to_page(d->shared_info); - printk("Shared_info@%p: mfn=%p, caf=%08x, taf=%" PRtype_info "\n", - _p(page_to_phys(page)), _p(page_to_pfn(page)), page->count_info, - page->u.inuse.type_info); } struct vcpu *alloc_vcpu_struct(struct domain *d, unsigned int vcpu_id) @@ -250,21 +250,34 @@ #endif } -void arch_do_createdomain(struct vcpu *v) +int arch_do_createdomain(struct vcpu *v) { struct domain *d = v->domain; l1_pgentry_t gdt_l1e; - int vcpuid, pdpt_order; + int vcpuid, pdpt_order, rc; #ifdef __x86_64__ int i; #endif if ( is_idle_task(d) ) - return; + return 0; + + d->arch.ioport_caps = + rangeset_new(d, "I/O Ports", RANGESETF_prettyprint_hex); + if ( d->arch.ioport_caps == NULL ) + return -ENOMEM; + + if ( (d->shared_info = alloc_xenheap_page()) == NULL ) + return -ENOMEM; + + if ( (rc = ptwr_init(d)) != 0 ) + { + free_xenheap_page(d->shared_info); + return rc; + } v->arch.schedule_tail = continue_nonidle_task; - d->shared_info = alloc_xenheap_page(); memset(d->shared_info, 0, PAGE_SIZE); v->vcpu_info = &d->shared_info->vcpu_info[v->vcpu_id]; v->cpumap = CPUMAP_RUNANYWHERE; @@ -308,10 +321,10 @@ __PAGE_HYPERVISOR); #endif - (void)ptwr_init(d); - shadow_lock_init(d); INIT_LIST_HEAD(&d->arch.free_shadow_frames); + + return 0; } void vcpu_migrate_cpu(struct vcpu *v, int newcpu) @@ -348,6 +361,8 @@ ((c->user_regs.ss & 3) == 0) ) return -EINVAL; } + else if ( !hvm_enabled ) + return -EINVAL; clear_bit(_VCPUF_fpu_initialised, &v->vcpu_flags); if ( c->flags & VGCF_I387_VALID ) @@ -953,8 +968,6 @@ BUG_ON(!cpus_empty(d->cpumask)); - physdev_destroy_state(d); - ptwr_destroy(d); /* Drop the in-use references to page-table bases. */ diff -r 903fb46f240e -r cd914808acf1 xen/arch/x86/domain_build.c --- a/xen/arch/x86/domain_build.c Tue Jan 3 14:59:00 2006 +++ b/xen/arch/x86/domain_build.c Tue Jan 3 16:19:20 2006 @@ -16,13 +16,13 @@ #include <xen/kernel.h> #include <xen/domain.h> #include <xen/compile.h> +#include <xen/iocap.h> #include <asm/regs.h> #include <asm/system.h> #include <asm/io.h> #include <asm/processor.h> #include <asm/desc.h> #include <asm/i387.h> -#include <asm/physdev.h> #include <asm/shadow.h> static long dom0_nrpages; @@ -94,9 +94,9 @@ return page; } -static void process_dom0_ioports_disable() +static void process_dom0_ioports_disable(void) { - unsigned long io_from, io_to, io_nr; + unsigned long io_from, io_to; char *t, *u, *s = opt_dom0_ioports_disable; if ( *s == '\0' ) @@ -126,8 +126,8 @@ printk("Disabling dom0 access to ioport range %04lx-%04lx\n", io_from, io_to); - io_nr = io_to - io_from + 1; - physdev_modify_ioport_access_range(dom0, 0, io_from, io_nr); + if ( ioports_deny_access(dom0, io_from, io_to) != 0 ) + BUG(); } } @@ -183,7 +183,6 @@ /* Machine address of next candidate page-table page. */ unsigned long mpt_alloc; - extern void physdev_init_dom0(struct domain *); extern void translate_l2pgtable( struct domain *d, l1_pgentry_t *p2m, unsigned long l2mfn); @@ -692,9 +691,6 @@ zap_low_mappings(l2start); zap_low_mappings(idle_pg_table_l2); #endif - - /* DOM0 gets access to everything. */ - physdev_init_dom0(d); init_domain_time(d); @@ -746,19 +742,28 @@ printk("dom0: shadow setup done\n"); } + i = 0; + + /* DOM0 is permitted full I/O capabilities. */ + i |= ioports_permit_access(dom0, 0, 0xFFFF); + i |= iomem_permit_access(dom0, 0UL, ~0UL); + i |= irqs_permit_access(dom0, 0, NR_PIRQS-1); + /* * Modify I/O port access permissions. */ /* Master Interrupt Controller (PIC). */ - physdev_modify_ioport_access_range(dom0, 0, 0x20, 2); + i |= ioports_deny_access(dom0, 0x20, 0x21); /* Slave Interrupt Controller (PIC). */ - physdev_modify_ioport_access_range(dom0, 0, 0xA0, 2); + i |= ioports_deny_access(dom0, 0xA0, 0xA1); /* Interval Timer (PIT). */ - physdev_modify_ioport_access_range(dom0, 0, 0x40, 4); + i |= ioports_deny_access(dom0, 0x40, 0x43); /* PIT Channel 2 / PC Speaker Control. */ - physdev_modify_ioport_access_range(dom0, 0, 0x61, 1); - /* Command-line passed i/o ranges */ + i |= ioports_deny_access(dom0, 0x61, 0x61); + /* Command-line I/O ranges. */ process_dom0_ioports_disable(); + + BUG_ON(i != 0); return 0; } diff -r 903fb46f240e -r cd914808acf1 xen/arch/x86/irq.c --- a/xen/arch/x86/irq.c Tue Jan 3 14:59:00 2006 +++ b/xen/arch/x86/irq.c Tue Jan 3 16:19:20 2006 @@ -199,15 +199,11 @@ int pirq_guest_bind(struct vcpu *v, int irq, int will_share) { unsigned int vector = irq_to_vector(irq); - struct domain *d = v->domain; irq_desc_t *desc = &irq_desc[vector]; irq_guest_action_t *action; unsigned long flags; int rc = 0; cpumask_t cpumask = CPU_MASK_NONE; - - if ( !IS_CAPABLE_PHYSDEV(d) ) - return -EPERM; if ( vector == 0 ) return -EBUSY; diff -r 903fb46f240e -r cd914808acf1 xen/arch/x86/mm.c --- a/xen/arch/x86/mm.c Tue Jan 3 14:59:00 2006 +++ b/xen/arch/x86/mm.c Tue Jan 3 16:19:20 2006 @@ -96,6 +96,7 @@ #include <xen/softirq.h> #include <xen/domain_page.h> #include <xen/event.h> +#include <xen/iocap.h> #include <asm/shadow.h> #include <asm/page.h> #include <asm/flushtlb.h> @@ -437,7 +438,6 @@ unsigned long mfn = l1e_get_pfn(l1e); struct pfn_info *page = pfn_to_page(mfn); int okay; - extern int domain_iomem_in_pfn(struct domain *d, unsigned long pfn); if ( !(l1e_get_flags(l1e) & _PAGE_PRESENT) ) return 1; @@ -455,8 +455,7 @@ if ( d == dom_io ) d = current->domain; - if ( (!IS_PRIV(d)) && - (!IS_CAPABLE_PHYSDEV(d) || !domain_iomem_in_pfn(d, mfn)) ) + if ( !iomem_access_permitted(d, mfn, mfn) ) { MEM_LOG("Non-privileged attempt to map I/O space %08lx", mfn); return 0; @@ -1887,7 +1886,7 @@ break; case MMUEXT_FLUSH_CACHE: - if ( unlikely(!IS_CAPABLE_PHYSDEV(d)) ) + if ( unlikely(!cache_flush_permitted(d)) ) { MEM_LOG("Non-physdev domain tried to FLUSH_CACHE."); okay = 0; diff -r 903fb46f240e -r cd914808acf1 xen/arch/x86/physdev.c --- a/xen/arch/x86/physdev.c Tue Jan 3 14:59:00 2006 +++ b/xen/arch/x86/physdev.c Tue Jan 3 16:19:20 2006 @@ -13,27 +13,6 @@ extern int ioapic_guest_read(int apicid, int address, u32 *pval); extern int ioapic_guest_write(int apicid, int address, u32 pval); - -void physdev_modify_ioport_access_range( - struct domain *d, int enable, int port, int num) -{ - int i; - for ( i = port; i < (port + num); i++ ) - (enable ? clear_bit : set_bit)(i, d->arch.iobmp_mask); -} - -void physdev_destroy_state(struct domain *d) -{ - xfree(d->arch.iobmp_mask); - d->arch.iobmp_mask = NULL; -} - -/* Check if a domain controls a device with IO memory within frame @pfn. - * Returns: 1 if the domain should be allowed to map @pfn, 0 otherwise. */ -int domain_iomem_in_pfn(struct domain *p, unsigned long pfn) -{ - return 0; -} /* * Demuxing hypercall. @@ -120,18 +99,6 @@ return ret; } -/* Domain 0 has read access to all devices. */ -void physdev_init_dom0(struct domain *d) -{ - /* Access to all I/O ports. */ - d->arch.iobmp_mask = xmalloc_array(u8, IOBMP_BYTES); - BUG_ON(d->arch.iobmp_mask == NULL); - memset(d->arch.iobmp_mask, 0, IOBMP_BYTES); - - set_bit(_DOMF_physdev_access, &d->domain_flags); -} - - /* * Local variables: * mode: C diff -r 903fb46f240e -r cd914808acf1 xen/arch/x86/setup.c --- a/xen/arch/x86/setup.c Tue Jan 3 14:59:00 2006 +++ b/xen/arch/x86/setup.c Tue Jan 3 16:19:20 2006 @@ -138,131 +138,19 @@ (*call)(); } -static void __init start_of_day(void) -{ - int i; - unsigned long vgdt, gdt_pfn; - - early_cpu_init(); - - paging_init(); - - /* Unmap the first page of CPU0's stack. */ - memguard_guard_stack(cpu0_stack); - - open_softirq(NEW_TLBFLUSH_CLOCK_PERIOD_SOFTIRQ, new_tlbflush_clock_period); - - if ( opt_watchdog ) - nmi_watchdog = NMI_LOCAL_APIC; - - sort_exception_tables(); - - arch_do_createdomain(current); - - /* - * Map default GDT into its final positions in the idle page table. As - * noted in arch_do_createdomain(), we must map for every possible VCPU#. - */ - vgdt = GDT_VIRT_START(current) + FIRST_RESERVED_GDT_BYTE; - gdt_pfn = virt_to_phys(gdt_table) >> PAGE_SHIFT; - for ( i = 0; i < MAX_VIRT_CPUS; i++ ) - { - map_pages_to_xen(vgdt, gdt_pfn, 1, PAGE_HYPERVISOR); - vgdt += 1 << PDPT_VCPU_VA_SHIFT; - } - - find_smp_config(); - - smp_alloc_memory(); - - dmi_scan_machine(); - - generic_apic_probe(); - - acpi_boot_table_init(); - acpi_boot_init(); - - if ( smp_found_config ) - get_smp_config(); - - init_apic_mappings(); - - init_IRQ(); - - trap_init(); - - ac_timer_init(); - - early_time_init(); - - arch_init_memory(); - - scheduler_init(); - - identify_cpu(&boot_cpu_data); - if ( cpu_has_fxsr ) - set_in_cr4(X86_CR4_OSFXSR); - if ( cpu_has_xmm ) - set_in_cr4(X86_CR4_OSXMMEXCPT); - - if ( opt_nosmp ) - { - max_cpus = 0; - smp_num_siblings = 1; - boot_cpu_data.x86_num_cores = 1; - } - - smp_prepare_cpus(max_cpus); - - /* We aren't hotplug-capable yet. */ - BUG_ON(!cpus_empty(cpu_present_map)); - for_each_cpu ( i ) - cpu_set(i, cpu_present_map); - - /* - * Initialise higher-level timer functions. We do this fairly late - * (post-SMP) because the time bases and scale factors need to be updated - * regularly, and SMP initialisation can cause a long delay with - * interrupts not yet enabled. - */ - init_xen_time(); - - initialize_keytable(); - - serial_init_postirq(); - - BUG_ON(!local_irq_is_enabled()); - - for_each_present_cpu ( i ) - { - if ( num_online_cpus() >= max_cpus ) - break; - if ( !cpu_online(i) ) - __cpu_up(i); - } - - printk("Brought up %ld CPUs\n", (long)num_online_cpus()); - smp_cpus_done(max_cpus); - - do_initcalls(); - - schedulers_start(); - - watchdog_enable(); -} - #define EARLY_FAIL() for ( ; ; ) __asm__ __volatile__ ( "hlt" ) static struct e820entry e820_raw[E820MAX]; void __init __start_xen(multiboot_info_t *mbi) { + unsigned long vgdt, gdt_pfn; char *cmdline; + unsigned long _initrd_start = 0, _initrd_len = 0; + unsigned int initrdidx = 1; module_t *mod = (module_t *)__va(mbi->mods_addr); unsigned long nr_pages, modules_length; unsigned long initial_images_start, initial_images_end; - unsigned long _initrd_start = 0, _initrd_len = 0; - unsigned int initrdidx = 1; physaddr_t s, e; int i, e820_warn = 0, e820_raw_nr = 0, bytes = 0; struct ns16550_defaults ns16550 = { @@ -486,7 +374,113 @@ early_boot = 0; - start_of_day(); + early_cpu_init(); + + paging_init(); + + /* Unmap the first page of CPU0's stack. */ + memguard_guard_stack(cpu0_stack); + + open_softirq(NEW_TLBFLUSH_CLOCK_PERIOD_SOFTIRQ, new_tlbflush_clock_period); + + if ( opt_watchdog ) + nmi_watchdog = NMI_LOCAL_APIC; + + sort_exception_tables(); + + if ( arch_do_createdomain(current) != 0 ) + BUG(); + + /* + * Map default GDT into its final positions in the idle page table. As + * noted in arch_do_createdomain(), we must map for every possible VCPU#. + */ + vgdt = GDT_VIRT_START(current) + FIRST_RESERVED_GDT_BYTE; + gdt_pfn = virt_to_phys(gdt_table) >> PAGE_SHIFT; + for ( i = 0; i < MAX_VIRT_CPUS; i++ ) + { + map_pages_to_xen(vgdt, gdt_pfn, 1, PAGE_HYPERVISOR); + vgdt += 1 << PDPT_VCPU_VA_SHIFT; + } + + find_smp_config(); + + smp_alloc_memory(); + + dmi_scan_machine(); + + generic_apic_probe(); + + acpi_boot_table_init(); + acpi_boot_init(); + + if ( smp_found_config ) + get_smp_config(); + + init_apic_mappings(); + + init_IRQ(); + + trap_init(); + + ac_timer_init(); + + early_time_init(); + + arch_init_memory(); + + scheduler_init(); + + identify_cpu(&boot_cpu_data); + if ( cpu_has_fxsr ) + set_in_cr4(X86_CR4_OSFXSR); + if ( cpu_has_xmm ) + set_in_cr4(X86_CR4_OSXMMEXCPT); + + if ( opt_nosmp ) + { + max_cpus = 0; + smp_num_siblings = 1; + boot_cpu_data.x86_num_cores = 1; + } + + smp_prepare_cpus(max_cpus); + + /* We aren't hotplug-capable yet. */ + BUG_ON(!cpus_empty(cpu_present_map)); + for_each_cpu ( i ) + cpu_set(i, cpu_present_map); + + /* + * Initialise higher-level timer functions. We do this fairly late + * (post-SMP) because the time bases and scale factors need to be updated + * regularly, and SMP initialisation can cause a long delay with + * interrupts not yet enabled. + */ + init_xen_time(); + + initialize_keytable(); + + serial_init_postirq(); + + BUG_ON(!local_irq_is_enabled()); + + for_each_present_cpu ( i ) + { + if ( num_online_cpus() >= max_cpus ) + break; + if ( !cpu_online(i) ) + __cpu_up(i); + } + + printk("Brought up %ld CPUs\n", (long)num_online_cpus()); + smp_cpus_done(max_cpus); + + do_initcalls(); + + schedulers_start(); + + watchdog_enable(); shadow_mode_init(); diff -r 903fb46f240e -r cd914808acf1 xen/arch/x86/smpboot.c --- a/xen/arch/x86/smpboot.c Tue Jan 3 14:59:00 2006 +++ b/xen/arch/x86/smpboot.c Tue Jan 3 16:19:20 2006 @@ -763,7 +763,6 @@ { struct domain *idle; struct vcpu *v; - void *stack; unsigned long boot_error; int timeout, cpu; unsigned long start_eip; @@ -786,16 +785,10 @@ /* So we see what's up */ printk("Booting processor %d/%d eip %lx\n", cpu, apicid, start_eip); - stack = alloc_xenheap_pages(STACK_ORDER); -#if defined(__i386__) - stack_start.esp = (void *)__pa(stack); -#elif defined(__x86_64__) - stack_start.esp = stack; -#endif - stack_start.esp += STACK_SIZE - sizeof(struct cpu_info); + stack_start.esp = alloc_xenheap_pages(STACK_ORDER); /* Debug build: detect stack overflow by setting up a guard page. */ - memguard_guard_stack(stack); + memguard_guard_stack(stack_start.esp); /* * This grunge runs the startup process for diff -r 903fb46f240e -r cd914808acf1 xen/arch/x86/traps.c --- a/xen/arch/x86/traps.c Tue Jan 3 14:59:00 2006 +++ b/xen/arch/x86/traps.c Tue Jan 3 16:19:20 2006 @@ -41,6 +41,7 @@ #include <xen/softirq.h> #include <xen/domain_page.h> #include <xen/symbols.h> +#include <xen/iocap.h> #include <asm/shadow.h> #include <asm/system.h> #include <asm/io.h> @@ -192,7 +193,8 @@ /* Bounds for range of valid frame pointer. */ low = (unsigned long)(ESP_BEFORE_EXCEPTION(regs) - 2); - high = (low & ~(STACK_SIZE - 1)) + (STACK_SIZE - sizeof(struct cpu_info)); + high = (low & ~(STACK_SIZE - 1)) + + (STACK_SIZE - sizeof(struct cpu_info) - 2*sizeof(unsigned long)); /* The initial frame pointer. */ next = regs->ebp; @@ -200,14 +202,14 @@ for ( ; ; ) { /* Valid frame pointer? */ - if ( (next < low) || (next > high) ) + if ( (next < low) || (next >= high) ) { /* * Exception stack frames have a different layout, denoted by an * inverted frame pointer. */ next = ~next; - if ( (next < low) || (next > high) ) + if ( (next < low) || (next >= high) ) break; frame = (unsigned long *)next; next = frame[0]; @@ -621,17 +623,7 @@ unsigned int port, unsigned int bytes, struct vcpu *v, struct cpu_user_regs *regs) { - struct domain *d = v->domain; - u16 x; - - if ( d->arch.iobmp_mask != NULL ) - { - x = *(u16 *)(d->arch.iobmp_mask + (port >> 3)); - if ( (x & (((1<<bytes)-1) << (port&7))) == 0 ) - return 1; - } - - return 0; + return ioports_access_permitted(v->domain, port, port + bytes - 1); } /* Check admin limits. Silently fail the access if it is disallowed. */ @@ -871,7 +863,7 @@ case 0x09: /* WBINVD */ /* Ignore the instruction if unprivileged. */ - if ( !IS_CAPABLE_PHYSDEV(v->domain) ) + if ( !cache_flush_permitted(v->domain) ) DPRINTK("Non-physdev domain attempted WBINVD.\n"); else wbinvd(); @@ -885,7 +877,8 @@ switch ( modrm_reg ) { case 0: /* Read CR0 */ - *reg = v->arch.guest_context.ctrlreg[0]; + *reg = (read_cr0() & ~X86_CR0_TS) | + v->arch.guest_context.ctrlreg[0]; break; case 2: /* Read CR2 */ @@ -927,6 +920,11 @@ switch ( modrm_reg ) { case 0: /* Write CR0 */ + if ( (*reg ^ read_cr0()) & ~X86_CR0_TS ) + { + DPRINTK("Attempt to change unmodifiable CR0 flags.\n"); + goto fail; + } (void)do_fpu_taskswitch(!!(*reg & X86_CR0_TS)); break; @@ -939,6 +937,14 @@ LOCK_BIGLOCK(v->domain); (void)new_guest_cr3(*reg); UNLOCK_BIGLOCK(v->domain); + break; + + case 4: + if ( *reg != (read_cr4() & ~(X86_CR4_PGE|X86_CR4_PSE)) ) + { + DPRINTK("Attempt to change CR4 flags.\n"); + goto fail; + } break; default: diff -r 903fb46f240e -r cd914808acf1 xen/arch/x86/x86_emulate.c --- a/xen/arch/x86/x86_emulate.c Tue Jan 3 14:59:00 2006 +++ b/xen/arch/x86/x86_emulate.c Tue Jan 3 16:19:20 2006 @@ -371,6 +371,21 @@ (_type)_x; \ }) +/* Access/update address held in a register, based on addressing mode. */ +#define register_address(sel, reg) \ + ((ad_bytes == sizeof(unsigned long)) ? (reg) : \ + ((mode == X86EMUL_MODE_REAL) ? /* implies ad_bytes == 2 */ \ + (((unsigned long)(sel) << 4) + ((reg) & 0xffff)) : \ + ((reg) & ((1UL << (ad_bytes << 3)) - 1)))) +#define register_address_increment(reg, inc) \ +do { \ + if ( ad_bytes == sizeof(unsigned long) ) \ + (reg) += (inc); \ + else \ + (reg) = ((reg) & ~((1UL << (ad_bytes << 3)) - 1)) | \ + (((reg) + (inc)) & ((1UL << (ad_bytes << 3)) - 1)); \ +} while (0) + void * decode_register( uint8_t modrm_reg, struct cpu_user_regs *regs, int highbyte_regs) @@ -420,32 +435,64 @@ { uint8_t b, d, sib, twobyte = 0, rex_prefix = 0; uint8_t modrm, modrm_mod = 0, modrm_reg = 0, modrm_rm = 0; - unsigned int op_bytes = (mode == 8) ? 4 : mode, ad_bytes = mode; - unsigned int lock_prefix = 0, rep_prefix = 0, i; + uint16_t *seg = NULL; /* override segment */ + unsigned int op_bytes, ad_bytes, lock_prefix = 0, rep_prefix = 0, i; int rc = 0; struct operand src, dst; /* Shadow copy of register state. Committed on successful emulation. */ struct cpu_user_regs _regs = *regs; + switch ( mode ) + { + case X86EMUL_MODE_REAL: + case X86EMUL_MODE_PROT16: + op_bytes = ad_bytes = 2; + break; + case X86EMUL_MODE_PROT32: + op_bytes = ad_bytes = 4; + break; +#ifdef __x86_64__ + case X86EMUL_MODE_PROT64: + op_bytes = 4; + ad_bytes = 8; + break; +#endif + default: + return -1; + } + /* Legacy prefixes. */ for ( i = 0; i < 8; i++ ) { switch ( b = insn_fetch(uint8_t, 1, _regs.eip) ) { case 0x66: /* operand-size override */ - op_bytes ^= 6; /* switch between 2/4 bytes */ + op_bytes ^= 6; /* switch between 2/4 bytes */ break; case 0x67: /* address-size override */ - ad_bytes ^= (mode == 8) ? 12 : 6; /* switch between 2/4/8 bytes */ + if ( mode == X86EMUL_MODE_PROT64 ) + ad_bytes ^= 12; /* switch between 4/8 bytes */ + else + ad_bytes ^= 6; /* switch between 2/4 bytes */ break; case 0x2e: /* CS override */ + seg = &_regs.cs; + break; case 0x3e: /* DS override */ + seg = &_regs.ds; + break; case 0x26: /* ES override */ + seg = &_regs.es; + break; case 0x64: /* FS override */ + seg = &_regs.fs; + break; case 0x65: /* GS override */ + seg = &_regs.gs; + break; case 0x36: /* SS override */ - DPRINTF("Warning: ignoring a segment override.\n"); + seg = &_regs.ss; break; case 0xf0: /* LOCK */ lock_prefix = 1; @@ -461,8 +508,12 @@ } done_prefixes: + /* Note quite the same as 80386 real mode, but hopefully good enough. */ + if ( (mode == X86EMUL_MODE_REAL) && (ad_bytes != 2) ) + goto cannot_emulate; + /* REX prefix. */ - if ( (mode == 8) && ((b & 0xf0) == 0x40) ) + if ( (mode == X86EMUL_MODE_PROT64) && ((b & 0xf0) == 0x40) ) { rex_prefix = b; if ( b & 8 ) @@ -674,7 +725,7 @@ emulate_2op_SrcV("cmp", src, dst, _regs.eflags); break; case 0x63: /* movsxd */ - if ( mode != 8 ) /* x86/64 long mode only */ + if ( mode != X86EMUL_MODE_PROT64 ) goto cannot_emulate; dst.val = (int32_t)src.val; break; @@ -721,12 +772,13 @@ dst.val = src.val; break; case 0x8f: /* pop (sole member of Grp1a) */ - /* 64-bit mode: POP defaults to 64-bit operands. */ - if ( (mode == 8) && (dst.bytes == 4) ) + /* 64-bit mode: POP always pops a 64-bit operand. */ + if ( mode == X86EMUL_MODE_PROT64 ) dst.bytes = 8; - if ( (rc = ops->read_std(_regs.esp, &dst.val, dst.bytes)) != 0 ) + if ( (rc = ops->read_std(register_address(_regs.ss, _regs.esp), + &dst.val, dst.bytes)) != 0 ) goto done; - _regs.esp += dst.bytes; + register_address_increment(_regs.esp, dst.bytes); break; case 0xc0 ... 0xc1: grp2: /* Grp2 */ switch ( modrm_reg ) @@ -797,16 +849,17 @@ emulate_1op("dec", dst, _regs.eflags); break; case 6: /* push */ - /* 64-bit mode: PUSH defaults to 64-bit operands. */ - if ( (mode == 8) && (dst.bytes == 4) ) + /* 64-bit mode: PUSH always pushes a 64-bit operand. */ + if ( mode == X86EMUL_MODE_PROT64 ) { dst.bytes = 8; if ( (rc = ops->read_std((unsigned long)dst.ptr, &dst.val, 8)) != 0 ) goto done; } - _regs.esp -= dst.bytes; - if ( (rc = ops->write_std(_regs.esp, dst.val, dst.bytes)) != 0 ) + register_address_increment(_regs.esp, -dst.bytes); + if ( (rc = ops->write_std(register_address(_regs.ss, _regs.esp), + dst.val, dst.bytes)) != 0 ) goto done; dst.val = dst.orig_val; /* skanky: disable writeback */ break; @@ -873,19 +926,22 @@ { /* Write fault: destination is special memory. */ dst.ptr = (unsigned long *)cr2; - if ( (rc = ops->read_std(_regs.esi - _regs.edi + cr2, + if ( (rc = ops->read_std(register_address(seg ? *seg : _regs.ds, + _regs.esi), &dst.val, dst.bytes)) != 0 ) goto done; } else { /* Read fault: source is special memory. */ - dst.ptr = (unsigned long *)(_regs.edi - _regs.esi + cr2); + dst.ptr = (unsigned long *)register_address(_regs.es, _regs.edi); if ( (rc = ops->read_emulated(cr2, &dst.val, dst.bytes)) != 0 ) goto done; } - _regs.esi += (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes; - _regs.edi += (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes; + register_address_increment( + _regs.esi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes); + register_address_increment( + _regs.edi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes); break; case 0xa6 ... 0xa7: /* cmps */ DPRINTF("Urk! I don't handle CMPS.\n"); @@ -895,7 +951,8 @@ dst.bytes = (d & ByteOp) ? 1 : op_bytes; dst.ptr = (unsigned long *)cr2; dst.val = _regs.eax; - _regs.edi += (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes; + register_address_increment( + _regs.edi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes); break; case 0xac ... 0xad: /* lods */ dst.type = OP_REG; @@ -903,7 +960,8 @@ dst.ptr = (unsigned long *)&_regs.eax; if ( (rc = ops->read_emulated(cr2, &dst.val, dst.bytes)) != 0 ) goto done; - _regs.esi += (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes; + register_address_increment( + _regs.esi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes); break; case 0xae ... 0xaf: /* scas */ DPRINTF("Urk! I don't handle SCAS.\n"); diff -r 903fb46f240e -r cd914808acf1 xen/common/dom0_ops.c --- a/xen/common/dom0_ops.c Tue Jan 3 14:59:00 2006 +++ b/xen/common/dom0_ops.c Tue Jan 3 16:19:20 2006 @@ -16,6 +16,7 @@ #include <xen/domain_page.h> #include <xen/trace.h> #include <xen/console.h> +#include <xen/iocap.h> #include <asm/current.h> #include <public/dom0_ops.h> #include <public/sched_ctl.h> @@ -582,6 +583,7 @@ } } break; + case DOM0_SETDEBUGGING: { struct domain *d; @@ -596,6 +598,53 @@ put_domain(d); ret = 0; } + } + break; + + case DOM0_IRQ_PERMISSION: + { + struct domain *d; + unsigned int pirq = op->u.irq_permission.pirq; + + ret = -EINVAL; + if ( pirq >= NR_PIRQS ) + break; + + ret = -ESRCH; + d = find_domain_by_id(op->u.irq_permission.domain); + if ( d == NULL ) + break; + + if ( op->u.irq_permission.allow_access ) + ret = irq_permit_access(d, pirq); + else + ret = irq_deny_access(d, pirq); + + put_domain(d); + } + break; + + case DOM0_IOMEM_PERMISSION: + { + struct domain *d; + unsigned long pfn = op->u.iomem_permission.first_pfn; + unsigned long nr_pfns = op->u.iomem_permission.nr_pfns; + + ret = -EINVAL; + if ( (pfn + nr_pfns - 1) < pfn ) /* wrap? */ + break; + + ret = -ESRCH; + d = find_domain_by_id(op->u.iomem_permission.domain); + if ( d == NULL ) + break; + + if ( op->u.iomem_permission.allow_access ) + ret = iomem_permit_access(d, pfn, pfn + nr_pfns - 1); + else + ret = iomem_deny_access(d, pfn, pfn + nr_pfns - 1); + + put_domain(d); } break; diff -r 903fb46f240e -r cd914808acf1 xen/common/domain.c --- a/xen/common/domain.c Tue Jan 3 14:59:00 2006 +++ b/xen/common/domain.c Tue Jan 3 16:19:20 2006 @@ -16,6 +16,7 @@ #include <xen/console.h> #include <xen/softirq.h> #include <xen/domain_page.h> +#include <xen/rangeset.h> #include <asm/debugger.h> #include <public/dom0_ops.h> #include <public/sched.h> @@ -52,22 +53,21 @@ if ( !is_idle_task(d) && ((evtchn_init(d) != 0) || (grant_table_create(d) != 0)) ) - { - evtchn_destroy(d); - free_domain(d); - return NULL; - } + goto fail1; if ( (v = alloc_vcpu(d, 0, cpu)) == NULL ) - { - grant_table_destroy(d); - evtchn_destroy(d); - free_domain(d); - return NULL; - } - - arch_do_createdomain(v); - + goto fail2; + + rangeset_domain_initialise(d); + + d->iomem_caps = rangeset_new(d, "I/O Memory", RANGESETF_prettyprint_hex); + d->irq_caps = rangeset_new(d, "Interrupts", 0); + + if ( (d->iomem_caps == NULL) || + (d->irq_caps == NULL) || + (arch_do_createdomain(v) != 0) ) + goto fail3; + if ( !is_idle_task(d) ) { write_lock(&domlist_lock); @@ -83,6 +83,15 @@ } return d; + + fail3: + rangeset_domain_destroy(d); + fail2: + grant_table_destroy(d); + fail1: + evtchn_destroy(d); + free_domain(d); + return NULL; } @@ -271,6 +280,8 @@ *pd = d->next_in_hashbucket; write_unlock(&domlist_lock); + rangeset_domain_destroy(d); + evtchn_destroy(d); grant_table_destroy(d); diff -r 903fb46f240e -r cd914808acf1 xen/common/event_channel.c --- a/xen/common/event_channel.c Tue Jan 3 14:59:00 2006 +++ b/xen/common/event_channel.c Tue Jan 3 16:19:20 2006 @@ -22,6 +22,7 @@ #include <xen/sched.h> #include <xen/event.h> #include <xen/irq.h> +#include <xen/iocap.h> #include <asm/current.h> #include <public/xen.h> @@ -241,6 +242,9 @@ if ( pirq >= ARRAY_SIZE(d->pirq_to_evtchn) ) return -EINVAL; + + if ( !irq_access_permitted(d, pirq) ) + return -EPERM; spin_lock(&d->evtchn_lock); diff -r 903fb46f240e -r cd914808acf1 xen/common/keyhandler.c --- a/xen/common/keyhandler.c Tue Jan 3 14:59:00 2006 +++ b/xen/common/keyhandler.c Tue Jan 3 16:19:20 2006 @@ -11,6 +11,7 @@ #include <xen/sched.h> #include <xen/softirq.h> #include <xen/domain.h> +#include <xen/rangeset.h> #include <asm/debugger.h> #define KEY_MAX 256 @@ -109,31 +110,32 @@ for_each_domain ( d ) { - printk("Xen: DOM %u, flags=%lx refcnt=%d nr_pages=%d " - "xenheap_pages=%d\n", d->domain_id, d->domain_flags, - atomic_read(&d->refcnt), d->tot_pages, d->xenheap_pages); - /* The handle is printed according to the OSF DCE UUID spec., even - though it is not necessarily such a thing, for ease of use when it - _is_ one of those. */ - printk(" handle=%02x%02x%02x%02x-%02x%02x-%02x%02x-" + printk("General information for domain %u:\n", d->domain_id); + printk(" flags=%lx refcnt=%d nr_pages=%d xenheap_pages=%d\n", + d->domain_flags, atomic_read(&d->refcnt), + d->tot_pages, d->xenheap_pages); + printk(" handle=%02x%02x%02x%02x-%02x%02x-%02x%02x-" "%02x%02x-%02x%02x%02x%02x%02x%02x\n", d->handle[ 0], d->handle[ 1], d->handle[ 2], d->handle[ 3], d->handle[ 4], d->handle[ 5], d->handle[ 6], d->handle[ 7], d->handle[ 8], d->handle[ 9], d->handle[10], d->handle[11], d->handle[12], d->handle[13], d->handle[14], d->handle[15]); + rangeset_domain_printk(d); + dump_pageframe_info(d); + printk("VCPU information and callbacks for domain %u:\n", + d->domain_id); for_each_vcpu ( d, v ) { - printk("Guest: %p CPU %d [has=%c] flags=%lx " - "upcall_pend = %02x, upcall_mask = %02x\n", v, - v->processor, + printk(" VCPU%d: CPU%d [has=%c] flags=%lx " + "upcall_pend = %02x, upcall_mask = %02x\n", + v->vcpu_id, v->processor, test_bit(_VCPUF_running, &v->vcpu_flags) ? 'T':'F', v->vcpu_flags, v->vcpu_info->evtchn_upcall_pending, v->vcpu_info->evtchn_upcall_mask); - printk("Notifying guest... %d/%d\n", d->domain_id, v->vcpu_id); - printk("port %d/%d stat %d %d %d\n", + printk(" Notifying guest (virq %d, port %d, stat %d/%d/%d)\n", VIRQ_DEBUG, v->virq_to_evtchn[VIRQ_DEBUG], test_bit(v->virq_to_evtchn[VIRQ_DEBUG], &d->shared_info->evtchn_pending[0]), diff -r 903fb46f240e -r cd914808acf1 xen/common/memory.c --- a/xen/common/memory.c Tue Jan 3 14:59:00 2006 +++ b/xen/common/memory.c Tue Jan 3 16:19:20 2006 @@ -15,6 +15,7 @@ #include <xen/sched.h> #include <xen/event.h> #include <xen/shadow.h> +#include <xen/iocap.h> #include <asm/current.h> #include <asm/hardirq.h> #include <public/memory.h> @@ -35,7 +36,8 @@ !array_access_ok(extent_list, nr_extents, sizeof(*extent_list)) ) return 0; - if ( (extent_order != 0) && !IS_CAPABLE_PHYSDEV(current->domain) ) + if ( (extent_order != 0) && + !multipage_allocation_permitted(current->domain) ) { DPRINTK("Only I/O-capable domains may allocate multi-page extents.\n"); return 0; diff -r 903fb46f240e -r cd914808acf1 xen/drivers/char/ns16550.c --- a/xen/drivers/char/ns16550.c Tue Jan 3 14:59:00 2006 +++ b/xen/drivers/char/ns16550.c Tue Jan 3 16:19:20 2006 @@ -13,6 +13,7 @@ #include <xen/irq.h> #include <xen/sched.h> #include <xen/serial.h> +#include <xen/iocap.h> #include <asm/io.h> /* @@ -233,11 +234,11 @@ } #ifdef CONFIG_X86 -#include <asm/physdev.h> static void ns16550_endboot(struct serial_port *port) { struct ns16550 *uart = port->uart; - physdev_modify_ioport_access_range(dom0, 0, uart->io_base, 8); + if ( ioports_deny_access(dom0, uart->io_base, uart->io_base + 7) != 0 ) + BUG(); } #else #define ns16550_endboot NULL diff -r 903fb46f240e -r cd914808acf1 xen/include/asm-ia64/domain.h --- a/xen/include/asm-ia64/domain.h Tue Jan 3 14:59:00 2006 +++ b/xen/include/asm-ia64/domain.h Tue Jan 3 16:19:20 2006 @@ -10,7 +10,7 @@ #include <asm/vmx_platform.h> #include <xen/list.h> -extern void arch_do_createdomain(struct vcpu *); +extern int arch_do_createdomain(struct vcpu *); extern void domain_relinquish_resources(struct domain *); diff -r 903fb46f240e -r cd914808acf1 xen/include/asm-x86/current.h --- a/xen/include/asm-x86/current.h Tue Jan 3 14:59:00 2006 +++ b/xen/include/asm-x86/current.h Tue Jan 3 16:19:20 2006 @@ -49,7 +49,7 @@ #define reset_stack_and_jump(__fn) \ __asm__ __volatile__ ( \ "mov %0,%%"__OP"sp; jmp "STR(__fn) \ - : : "r" (guest_cpu_user_regs()) ) + : : "r" (guest_cpu_user_regs()) : "memory" ) #define schedule_tail(_ed) (((_ed)->arch.schedule_tail)(_ed)) diff -r 903fb46f240e -r cd914808acf1 xen/include/asm-x86/domain.h --- a/xen/include/asm-x86/domain.h Tue Jan 3 14:59:00 2006 +++ b/xen/include/asm-x86/domain.h Tue Jan 3 16:19:20 2006 @@ -24,8 +24,8 @@ /* Writable pagetables. */ struct ptwr_info ptwr[2]; - /* I/O-port access bitmap mask. */ - u8 *iobmp_mask; /* Address of IO bitmap mask, or NULL. */ + /* I/O-port admin-specified access capabilities. */ + struct rangeset *ioport_caps; /* Shadow mode status and controls. */ struct shadow_ops *ops; diff -r 903fb46f240e -r cd914808acf1 xen/include/asm-x86/msr.h --- a/xen/include/asm-x86/msr.h Tue Jan 3 14:59:00 2006 +++ b/xen/include/asm-x86/msr.h Tue Jan 3 16:19:20 2006 @@ -12,7 +12,7 @@ __asm__ __volatile__("rdmsr" \ : "=a" (a__), "=d" (b__) \ : "c" (msr)); \ - val = a__ | (b__<<32); \ + val = a__ | ((u64)b__<<32); \ } while(0); #define wrmsr(msr,val1,val2) \ diff -r 903fb46f240e -r cd914808acf1 xen/include/asm-x86/x86_emulate.h --- a/xen/include/asm-x86/x86_emulate.h Tue Jan 3 14:59:00 2006 +++ b/xen/include/asm-x86/x86_emulate.h Tue Jan 3 16:19:20 2006 @@ -141,6 +141,12 @@ struct cpu_user_regs; +/* Current execution mode, passed to the emulator. */ +#define X86EMUL_MODE_REAL 0 +#define X86EMUL_MODE_PROT16 2 +#define X86EMUL_MODE_PROT32 4 +#define X86EMUL_MODE_PROT64 8 + /* * x86_emulate_memop: Emulate an instruction that faulted attempting to * read/write a 'special' memory area. @@ -149,6 +155,8 @@ * @ops: Interface to access special memory. * @mode: Current execution mode, represented by the default size of memory * addresses, in bytes. Valid values are 2, 4 and 8 (x86/64 only). + * Alternatively use the appropriate X86EMUL_MODE value (which also + * includes a value for emulating real mode). */ extern int x86_emulate_memop( diff -r 903fb46f240e -r cd914808acf1 xen/include/public/dom0_ops.h --- a/xen/include/public/dom0_ops.h Tue Jan 3 14:59:00 2006 +++ b/xen/include/public/dom0_ops.h Tue Jan 3 16:19:20 2006 @@ -410,6 +410,21 @@ uint8_t enable; } dom0_setdebugging_t; +#define DOM0_IRQ_PERMISSION 46 +typedef struct { + domid_t domain; /* domain to be affected */ + uint8_t pirq; + uint8_t allow_access; /* flag to specify enable/disable of IRQ access */ +} dom0_irq_permission_t; + +#define DOM0_IOMEM_PERMISSION 47 +typedef struct { + domid_t domain; /* domain to be affected */ + unsigned long first_pfn; /* first page (physical page number) in range */ + unsigned long nr_pfns; /* number of pages in range (>0) */ + uint8_t allow_access; /* allow (!0) or deny (0) access to range? */ +} dom0_iomem_permission_t; + typedef struct { uint32_t cmd; uint32_t interface_version; /* DOM0_INTERFACE_VERSION */ @@ -448,6 +463,8 @@ dom0_max_vcpus_t max_vcpus; dom0_setdomainhandle_t setdomainhandle; dom0_setdebugging_t setdebugging; + dom0_irq_permission_t irq_permission; + dom0_iomem_permission_t iomem_permission; uint8_t pad[128]; } u; } dom0_op_t; diff -r 903fb46f240e -r cd914808acf1 xen/include/xen/compiler.h --- a/xen/include/xen/compiler.h Tue Jan 3 14:59:00 2006 +++ b/xen/include/xen/compiler.h Tue Jan 3 16:19:20 2006 @@ -19,4 +19,10 @@ #define __attribute_used__ __attribute__((__unused__)) #endif +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) +#define __must_check __attribute__((warn_unused_result)) +#else +#define __must_check +#endif + #endif /* __LINUX_COMPILER_H */ diff -r 903fb46f240e -r cd914808acf1 xen/include/xen/domain.h --- a/xen/include/xen/domain.h Tue Jan 3 14:59:00 2006 +++ b/xen/include/xen/domain.h Tue Jan 3 16:19:20 2006 @@ -13,9 +13,9 @@ extern void free_vcpu_struct(struct vcpu *v); -extern void arch_do_createdomain(struct vcpu *v); +extern int arch_do_createdomain(struct vcpu *v); -extern int arch_set_info_guest( +extern int arch_set_info_guest( struct vcpu *v, struct vcpu_guest_context *c); extern void vcpu_migrate_cpu(struct vcpu *v, int newcpu); diff -r 903fb46f240e -r cd914808acf1 xen/include/xen/sched.h --- a/xen/include/xen/sched.h Tue Jan 3 14:59:00 2006 +++ b/xen/include/xen/sched.h Tue Jan 3 16:19:20 2006 @@ -11,6 +11,7 @@ #include <xen/time.h> #include <xen/ac_timer.h> #include <xen/grant_table.h> +#include <xen/rangeset.h> #include <asm/domain.h> extern unsigned long volatile jiffies; @@ -110,6 +111,9 @@ struct domain *next_in_list; struct domain *next_in_hashbucket; + struct list_head rangesets; + spinlock_t rangesets_lock; + /* Event channel information. */ struct evtchn *evtchn[NR_EVTCHN_BUCKETS]; spinlock_t evtchn_lock; @@ -124,6 +128,10 @@ #define NR_PIRQS 256 /* Put this somewhere sane! */ u16 pirq_to_evtchn[NR_PIRQS]; u32 pirq_mask[NR_PIRQS/32]; + + /* I/O capabilities (access to IRQs and memory-mapped I/O). */ + struct rangeset *iomem_caps; + struct rangeset *irq_caps; unsigned long domain_flags; unsigned long vm_assist; @@ -378,23 +386,20 @@ /* Is this domain privileged? */ #define _DOMF_privileged 1 #define DOMF_privileged (1UL<<_DOMF_privileged) - /* May this domain do IO to physical devices? */ -#define _DOMF_physdev_access 2 -#define DOMF_physdev_access (1UL<<_DOMF_physdev_access) /* Guest shut itself down for some reason. */ -#define _DOMF_shutdown 3 +#define _DOMF_shutdown 2 #define DOMF_shutdown (1UL<<_DOMF_shutdown) /* Guest is in process of shutting itself down (becomes DOMF_shutdown). */ -#define _DOMF_shuttingdown 4 +#define _DOMF_shuttingdown 3 #define DOMF_shuttingdown (1UL<<_DOMF_shuttingdown) /* Death rattle. */ -#define _DOMF_dying 5 +#define _DOMF_dying 4 #define DOMF_dying (1UL<<_DOMF_dying) /* Domain is paused by controller software. */ -#define _DOMF_ctrl_pause 6 +#define _DOMF_ctrl_pause 5 #define DOMF_ctrl_pause (1UL<<_DOMF_ctrl_pause) /* Domain is being debugged by controller software. */ -#define _DOMF_debugging 7 +#define _DOMF_debugging 6 #define DOMF_debugging (1UL<<_DOMF_debugging) @@ -422,8 +427,6 @@ #define IS_PRIV(_d) \ (test_bit(_DOMF_privileged, &(_d)->domain_flags)) -#define IS_CAPABLE_PHYSDEV(_d) \ - (test_bit(_DOMF_physdev_access, &(_d)->domain_flags)) #define VM_ASSIST(_d,_t) (test_bit((_t), &(_d)->vm_assist)) diff -r 903fb46f240e -r cd914808acf1 tools/libxc/xc_pagetab.c --- /dev/null Tue Jan 3 14:59:00 2006 +++ b/tools/libxc/xc_pagetab.c Tue Jan 3 16:19:20 2006 @@ -0,0 +1,192 @@ +/****************************************************************************** + * xc_pagetab.c + * + * Function to translate virtual to physical addresses. + */ +#include "xc_private.h" + +#if defined(__i386__) + +#define L1_PAGETABLE_SHIFT_PAE 12 +#define L2_PAGETABLE_SHIFT_PAE 21 +#define L3_PAGETABLE_SHIFT_PAE 30 + +#define L1_PAGETABLE_SHIFT 12 +#define L2_PAGETABLE_SHIFT 22 + +#define L0_PAGETABLE_MASK_PAE 0x0000000ffffff000ULL +#define L1_PAGETABLE_MASK_PAE 0x1ffULL +#define L2_PAGETABLE_MASK_PAE 0x1ffULL +#define L3_PAGETABLE_MASK_PAE 0x3ULL + +#define L0_PAGETABLE_MASK 0xfffff000ULL +#define L1_PAGETABLE_MASK 0x3ffULL +#define L2_PAGETABLE_MASK 0x3ffULL + +#elif defined(__x86_64__) + +#define L1_PAGETABLE_SHIFT_PAE 12 +#define L2_PAGETABLE_SHIFT_PAE 21 +#define L3_PAGETABLE_SHIFT_PAE 30 +#define L4_PAGETABLE_SHIFT_PAE 39 + +#define L1_PAGETABLE_SHIFT L1_PAGETABLE_SHIFT_PAE +#define L2_PAGETABLE_SHIFT L2_PAGETABLE_SHIFT_PAE + +#define L0_PAGETABLE_MASK_PAE 0x000000fffffff000ULL +#define L1_PAGETABLE_MASK_PAE 0x1ffULL +#define L2_PAGETABLE_MASK_PAE 0x1ffULL +#define L3_PAGETABLE_MASK_PAE 0x1ffULL +#define L4_PAGETABLE_MASK_PAE 0x1ffULL + +#define L0_PAGETABLE_MASK L0_PAGETABLE_MASK_PAE +#define L1_PAGETABLE_MASK L1_PAGETABLE_MASK_PAE +#define L2_PAGETABLE_MASK L2_PAGETABLE_MASK_PAE + +#endif + +unsigned long xc_translate_foreign_address(int xc_handle, uint32_t dom, + int vcpu, unsigned long long virt ) +{ + vcpu_guest_context_t ctx; + unsigned long long cr3; + void *pd, *pt, *pdppage = NULL, *pdp, *pml = NULL; + unsigned long long pde, pte, pdpe, pmle; + unsigned long mfn = 0; +#if defined (__i386__) + static int pt_levels = 0; + + if (pt_levels == 0) { + xen_capabilities_info_t xen_caps = ""; + + if (xc_version(xc_handle, XENVER_capabilities, &xen_caps) != 0) + goto out; + if (strstr(xen_caps, "xen-3.0-x86_64")) + pt_levels = 4; + else if (strstr(xen_caps, "xen-3.0-x86_32p")) + pt_levels = 3; + else if (strstr(xen_caps, "xen-3.0-x86_32")) + pt_levels = 2; + else + goto out; + } +#elif defined (__x86_64__) +#define pt_levels 4 +#endif + + if (xc_domain_get_vcpu_context(xc_handle, dom, vcpu, &ctx) != 0) { + fprintf(stderr, "failed to retreive vcpu context\n"); + goto out; + } + cr3 = ctx.ctrlreg[3]; + + /* Page Map Level 4 */ + +#if defined(__i386__) + pmle = cr3; +#elif defined(__x86_64__) + pml = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, PROT_READ, cr3 >> PAGE_SHIFT); + if (pml == NULL) { + fprintf(stderr, "failed to map PML4\n"); + goto out; + } + pmle = *(unsigned long long *)(pml + 8 * ((virt >> L4_PAGETABLE_SHIFT_PAE) & L4_PAGETABLE_MASK_PAE)); + if((pmle & 1) == 0) { + fprintf(stderr, "page entry not present in PML4\n"); + goto out_unmap_pml; + } +#endif + + /* Page Directory Pointer Table */ + + if (pt_levels >= 3) { + pdppage = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, PROT_READ, pmle >> PAGE_SHIFT); + if (pdppage == NULL) { + fprintf(stderr, "failed to map PDP\n"); + goto out_unmap_pml; + } + if (pt_levels >= 4) + pdp = pdppage; + else + /* PDP is only 32 bit aligned with 3 level pts */ + pdp = pdppage + (pmle & ~(XC_PAGE_MASK | 0x1f)); + + pdpe = *(unsigned long long *)(pdp + 8 * ((virt >> L3_PAGETABLE_SHIFT_PAE) & L3_PAGETABLE_MASK_PAE)); + + if((pdpe & 1) == 0) { + fprintf(stderr, "page entry not present in PDP\n"); + goto out_unmap_pdp; + } + } else { + pdpe = pmle; + } + + /* Page Directory */ + + pd = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, PROT_READ, pdpe >> PAGE_SHIFT); + if (pd == NULL) { + fprintf(stderr, "failed to map PD\n"); + goto out_unmap_pdp; + } + + if (pt_levels >= 3) + pde = *(unsigned long long *)(pd + 8 * ((virt >> L2_PAGETABLE_SHIFT_PAE) & L2_PAGETABLE_MASK_PAE)); + else + pde = *(unsigned long long *)(pd + 4 * ((virt >> L2_PAGETABLE_SHIFT) & L2_PAGETABLE_MASK)); + + if ((pde & 1) == 0) { + fprintf(stderr, "page entry not present in PD\n"); + goto out_unmap_pd; + } + + /* Page Table */ + + if (pde & 0x00000008) { /* 4M page (or 2M in PAE mode) */ + fprintf(stderr, "Cannot currently cope with 2/4M pages\n"); + exit(-1); + } else { /* 4k page */ + pt = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, PROT_READ, + pde >> PAGE_SHIFT); + + if (pt == NULL) { + fprintf(stderr, "failed to map PT\n"); + goto out_unmap_pd; + } + + if (pt_levels >= 3) + pte = *(unsigned long long *)(pt + 8 * ((virt >> L1_PAGETABLE_SHIFT_PAE) & L1_PAGETABLE_MASK_PAE)); + else + pte = *(unsigned long long *)(pt + 4 * ((virt >> L1_PAGETABLE_SHIFT) & L1_PAGETABLE_MASK)); + + if ((pte & 0x00000001) == 0) { + fprintf(stderr, "page entry not present in PT\n"); + goto out_unmap_pt; + } + + if (pt_levels >= 3) + mfn = (pte & L0_PAGETABLE_MASK_PAE) >> PAGE_SHIFT; + else + mfn = (pte & L0_PAGETABLE_MASK) >> PAGE_SHIFT; + } + + out_unmap_pt: + munmap(pt, PAGE_SIZE); + out_unmap_pd: + munmap(pd, PAGE_SIZE); + out_unmap_pdp: + munmap(pdppage, PAGE_SIZE); + out_unmap_pml: + munmap(pml, PAGE_SIZE); + out: + return mfn; +} + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff -r 903fb46f240e -r cd914808acf1 xen/arch/x86/x86_32/xen.lds.S --- /dev/null Tue Jan 3 14:59:00 2006 +++ b/xen/arch/x86/x86_32/xen.lds.S Tue Jan 3 16:19:20 2006 @@ -0,0 +1,85 @@ +/* ld script to make i386 Linux kernel + * Written by Martin Mares <mj@xxxxxxxxxxxxxxxxxxxxxxxx> + * Modified for i386 Xen by Keir Fraser + */ + +#include <xen/config.h> +#include <asm/page.h> +#undef ENTRY +#undef ALIGN + +OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") +OUTPUT_ARCH(i386) +ENTRY(start) +PHDRS +{ + text PT_LOAD ; +} +SECTIONS +{ + . = 0xFF000000 + 0x100000; + _text = .; /* Text and read-only data */ + .text : { + *(.text) + *(.fixup) + *(.gnu.warning) + } :text =0x9090 + .text.lock : { *(.text.lock) } :text /* out-of-line lock text */ + + _etext = .; /* End of text section */ + + .rodata : { *(.rodata) *(.rodata.*) } :text + + . = ALIGN(32); /* Exception table */ + __start___ex_table = .; + __ex_table : { *(__ex_table) } :text + __stop___ex_table = .; + + . = ALIGN(32); /* Pre-exception table */ + __start___pre_ex_table = .; + __pre_ex_table : { *(__pre_ex_table) } :text + __stop___pre_ex_table = .; + + .data : { /* Data */ + *(.data) + CONSTRUCTORS + } :text + + . = ALIGN(4096); /* Init code and data */ + __init_begin = .; + .text.init : { *(.text.init) } :text + .data.init : { *(.data.init) } :text + . = ALIGN(32); + __setup_start = .; + .setup.init : { *(.setup.init) } :text + __setup_end = .; + __initcall_start = .; + .initcall.init : { *(.initcall.init) } :text + __initcall_end = .; + . = ALIGN(STACK_SIZE); + __init_end = .; + + __bss_start = .; /* BSS */ + .bss : { + *(.bss.stack_aligned) + *(.bss.page_aligned) + *(.bss) + } :text + _end = . ; + + /* Sections to be discarded */ + /DISCARD/ : { + *(.text.exit) + *(.data.exit) + *(.exitcall.exit) + } + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } +} diff -r 903fb46f240e -r cd914808acf1 xen/arch/x86/x86_64/xen.lds.S --- /dev/null Tue Jan 3 14:59:00 2006 +++ b/xen/arch/x86/x86_64/xen.lds.S Tue Jan 3 16:19:20 2006 @@ -0,0 +1,83 @@ +/* Excerpts written by Martin Mares <mj@xxxxxxxxxxxxxxxxxxxxxxxx> */ +/* Modified for x86-64 Xen by Keir Fraser */ + +#include <xen/config.h> +#include <asm/page.h> +#undef ENTRY +#undef ALIGN + +OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64") +OUTPUT_ARCH(i386:x86-64) +ENTRY(start) +PHDRS +{ + text PT_LOAD ; +} +SECTIONS +{ + . = 0xFFFF830000100000; + _text = .; /* Text and read-only data */ + .text : { + *(.text) + *(.fixup) + *(.gnu.warning) + } :text = 0x9090 + .text.lock : { *(.text.lock) } :text /* out-of-line lock text */ + + _etext = .; /* End of text section */ + + .rodata : { *(.rodata) *(.rodata.*) } :text + + . = ALIGN(32); /* Exception table */ + __start___ex_table = .; + __ex_table : { *(__ex_table) } :text + __stop___ex_table = .; + + . = ALIGN(32); /* Pre-exception table */ + __start___pre_ex_table = .; + __pre_ex_table : { *(__pre_ex_table) } :text + __stop___pre_ex_table = .; + + .data : { /* Data */ + *(.data) + CONSTRUCTORS + } :text + + . = ALIGN(4096); /* Init code and data */ + __init_begin = .; + .text.init : { *(.text.init) } :text + .data.init : { *(.data.init) } :text + . = ALIGN(32); + __setup_start = .; + .setup.init : { *(.setup.init) } :text + __setup_end = .; + __initcall_start = .; + .initcall.init : { *(.initcall.init) } :text + __initcall_end = .; + . = ALIGN(STACK_SIZE); + __init_end = .; + + __bss_start = .; /* BSS */ + .bss : { + *(.bss.stack_aligned) + *(.bss.page_aligned) + *(.bss) + } :text + _end = . ; + + /* Sections to be discarded */ + /DISCARD/ : { + *(.text.exit) + *(.data.exit) + *(.exitcall.exit) + } + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } +} diff -r 903fb46f240e -r cd914808acf1 xen/common/rangeset.c --- /dev/null Tue Jan 3 14:59:00 2006 +++ b/xen/common/rangeset.c Tue Jan 3 16:19:20 2006 @@ -0,0 +1,399 @@ +/****************************************************************************** + * rangeset.c + * + * Creation, maintenance and automatic destruction of per-domain sets of + * numeric ranges. + * + * Copyright (c) 2005, K A Fraser + */ + +#include <xen/sched.h> +#include <xen/rangeset.h> + +/* An inclusive range [s,e] and pointer to next range in ascending order. */ +struct range { + struct list_head list; + unsigned long s, e; +}; + +struct rangeset { + /* Owning domain and threaded list of rangesets. */ + struct list_head rangeset_list; + struct domain *domain; + + /* Ordered list of ranges contained in this set, and protecting lock. */ + struct list_head range_list; + spinlock_t lock; + + /* Pretty-printing name. */ + char name[32]; + + /* RANGESETF flags. */ + unsigned int flags; +}; + +/***************************** + * Private range functions hide the underlying linked-list implemnetation. + */ + +/* Find highest range lower than or containing s. NULL if no such range. */ +static struct range *find_range( + struct rangeset *r, unsigned long s) +{ + struct range *x = NULL, *y; + + list_for_each_entry ( y, &r->range_list, list ) + { + if ( y->s > s ) + break; + x = y; + } + + return x; +} + +/* Return the lowest range in the set r, or NULL if r is empty. */ +static struct range *first_range( + struct rangeset *r) +{ + if ( list_empty(&r->range_list) ) + return NULL; + return list_entry(r->range_list.next, struct range, list); +} + +/* Return range following x in ascending order, or NULL if x is the highest. */ +static struct range *next_range( + struct rangeset *r, struct range *x) +{ + if ( x->list.next == &r->range_list ) + return NULL; + return list_entry(x->list.next, struct range, list); +} + +/* Insert range y after range x in r. Insert as first range if x is NULL. */ +static void insert_range( + struct rangeset *r, struct range *x, struct range *y) +{ + list_add(&y->list, (x != NULL) ? &x->list : &r->range_list); +} + +/* Remove a range from its list and free it. */ +static void destroy_range( + struct range *x) +{ + list_del(&x->list); + xfree(x); +} + +/***************************** + * Core public functions + */ + +int rangeset_add_range( + struct rangeset *r, unsigned long s, unsigned long e) +{ + struct range *x, *y; + int rc = 0; + + spin_lock(&r->lock); + + x = find_range(r, s); + y = find_range(r, e); + + if ( x == y ) + { + if ( (x == NULL) || ((x->e < s) && ((x->e + 1) != s)) ) + { + x = xmalloc(struct range); + if ( x == NULL ) + { + rc = -ENOMEM; + goto out; + } + + x->s = s; + x->e = e; + + insert_range(r, y, x); + } + else if ( x->e < e ) + x->e = e; + } + else + { + if ( x == NULL ) + { + x = first_range(r); + x->s = s; + } + else if ( (x->e < s) && ((x->e + 1) != s) ) + { + x = next_range(r, x); + x->s = s; + } + + x->e = (y->e > e) ? y->e : e; + + for ( ; ; ) + { + y = next_range(r, x); + if ( (y == NULL) || (y->e > x->e) ) + break; + destroy_range(y); + } + } + + y = next_range(r, x); + if ( (y != NULL) && ((x->e + 1) == y->s) ) + { + x->e = y->e; + destroy_range(y); + } + + out: + spin_unlock(&r->lock); + return rc; +} + +int rangeset_remove_range( + struct rangeset *r, unsigned long s, unsigned long e) +{ + struct range *x, *y, *t; + int rc = 0; + + spin_lock(&r->lock); + + x = find_range(r, s); + y = find_range(r, e); + + if ( x == y ) + { + if ( (x == NULL) || (x->e < s) ) + goto out; + + if ( (x->s < s) && (x->e > e) ) + { + y = xmalloc(struct range); + if ( y == NULL ) + { + rc = -ENOMEM; + goto out; + } + + y->s = e + 1; + y->e = x->e; + x->e = s - 1; + + insert_range(r, x, y); + } + else if ( (x->s == s) && (x->e <= e) ) + destroy_range(x); + else if ( x->s == s ) + x->s = e + 1; + else if ( x->e <= e ) + x->e = s - 1; + } + else + { + if ( x == NULL ) + x = first_range(r); + + if ( x->s < s ) + { + x->e = s - 1; + x = next_range(r, x); + } + + while ( x != y ) + { + t = x; + x = next_range(r, x); + destroy_range(t); + } + + x->s = e + 1; + if ( x->s > x->e ) + destroy_range(x); + } + + out: + spin_unlock(&r->lock); + return rc; +} + +int rangeset_contains_range( + struct rangeset *r, unsigned long s, unsigned long e) +{ + struct range *x; + int contains; + + spin_lock(&r->lock); + x = find_range(r, s); + contains = (x && (x->e >= e)); + spin_unlock(&r->lock); + + return contains; +} + +int rangeset_add_singleton( + struct rangeset *r, unsigned long s) +{ + return rangeset_add_range(r, s, s); +} + +int rangeset_remove_singleton( + struct rangeset *r, unsigned long s) +{ + return rangeset_remove_range(r, s, s); +} + +int rangeset_contains_singleton( + struct rangeset *r, unsigned long s) +{ + return rangeset_contains_range(r, s, s); +} + +int rangeset_is_empty( + struct rangeset *r) +{ + return list_empty(&r->range_list); +} + +struct rangeset *rangeset_new( + struct domain *d, char *name, unsigned int flags) +{ + struct rangeset *r; + + r = xmalloc(struct rangeset); + if ( r == NULL ) + return NULL; + + spin_lock_init(&r->lock); + INIT_LIST_HEAD(&r->range_list); + + BUG_ON(flags & ~RANGESETF_prettyprint_hex); + r->flags = flags; + + if ( name != NULL ) + { + strncpy(r->name, name, sizeof(r->name)); + r->name[sizeof(r->name)-1] = '\0'; + } + else + { + sprintf(r->name, "(no name)"); + } + + if ( (r->domain = d) != NULL ) + { + spin_lock(&d->rangesets_lock); + list_add(&r->rangeset_list, &d->rangesets); + spin_unlock(&d->rangesets_lock); + } + + return r; +} + +void rangeset_destroy( + struct rangeset *r) +{ + struct range *x; + + if ( r == NULL ) + return; + + if ( r->domain != NULL ) + { + spin_lock(&r->domain->rangesets_lock); + list_del(&r->rangeset_list); + spin_unlock(&r->domain->rangesets_lock); + } + + while ( (x = first_range(r)) != NULL ) + destroy_range(x); + + xfree(r); +} + +void rangeset_domain_initialise( + struct domain *d) +{ + INIT_LIST_HEAD(&d->rangesets); + spin_lock_init(&d->rangesets_lock); +} + +void rangeset_domain_destroy( + struct domain *d) +{ + struct rangeset *r; + + while ( !list_empty(&d->rangesets) ) + { + r = list_entry(d->rangesets.next, struct rangeset, rangeset_list); + + BUG_ON(r->domain != d); + r->domain = NULL; + list_del(&r->rangeset_list); + + rangeset_destroy(r); + } +} + +/***************************** + * Pretty-printing functions + */ + +static void print_limit(struct rangeset *r, unsigned long s) +{ + printk((r->flags & RANGESETF_prettyprint_hex) ? "%lx" : "%lu", s); +} + +void rangeset_printk( + struct rangeset *r) +{ + int nr_printed = 0; + struct range *x; + + spin_lock(&r->lock); + + printk("%-10s {", r->name); + + for ( x = first_range(r); x != NULL; x = next_range(r, x) ) + { + if ( nr_printed++ ) + printk(","); + printk(" "); + print_limit(r, x->s); + if ( x->s != x->e ) + { + printk("-"); + print_limit(r, x->e); + } + } + + printk(" }"); + + spin_unlock(&r->lock); +} + +void rangeset_domain_printk( + struct domain *d) +{ + struct rangeset *r; + + printk("Rangesets belonging to domain %u:\n", d->domain_id); + + spin_lock(&d->rangesets_lock); + + if ( list_empty(&d->rangesets) ) + printk(" None\n"); + + list_for_each_entry ( r, &d->rangesets, rangeset_list ) + { + printk(" "); + rangeset_printk(r); + printk("\n"); + } + + spin_unlock(&d->rangesets_lock); +} diff -r 903fb46f240e -r cd914808acf1 xen/include/asm-ia64/iocap.h --- /dev/null Tue Jan 3 14:59:00 2006 +++ b/xen/include/asm-ia64/iocap.h Tue Jan 3 16:19:20 2006 @@ -0,0 +1,10 @@ +/****************************************************************************** + * iocap.h + * + * Architecture-specific per-domain I/O capabilities. + */ + +#ifndef __IA64_IOCAP_H__ +#define __IA64_IOCAP_H__ + +#endif /* __IA64_IOCAP_H__ */ diff -r 903fb46f240e -r cd914808acf1 xen/include/asm-x86/iocap.h --- /dev/null Tue Jan 3 14:59:00 2006 +++ b/xen/include/asm-x86/iocap.h Tue Jan 3 16:19:20 2006 @@ -0,0 +1,20 @@ +/****************************************************************************** + * iocap.h + * + * Architecture-specific per-domain I/O capabilities. + */ + +#ifndef __X86_IOCAP_H__ +#define __X86_IOCAP_H__ + +#define ioports_permit_access(d, s, e) \ + rangeset_add_range((d)->arch.ioport_caps, s, e) +#define ioports_deny_access(d, s, e) \ + rangeset_remove_range((d)->arch.ioport_caps, s, e) +#define ioports_access_permitted(d, s, e) \ + rangeset_contains_range((d)->arch.ioport_caps, s, e) + +#define cache_flush_permitted(d) \ + (!rangeset_is_empty((d)->iomem_caps)) + +#endif /* __X86_IOCAP_H__ */ diff -r 903fb46f240e -r cd914808acf1 xen/include/xen/iocap.h --- /dev/null Tue Jan 3 14:59:00 2006 +++ b/xen/include/xen/iocap.h Tue Jan 3 16:19:20 2006 @@ -0,0 +1,34 @@ +/****************************************************************************** + * iocap.h + * + * Per-domain I/O capabilities. + */ + +#ifndef __XEN_IOCAP_H__ +#define __XEN_IOCAP_H__ + +#include <xen/rangeset.h> +#include <asm/iocap.h> + +#define iomem_permit_access(d, s, e) \ + rangeset_add_range((d)->iomem_caps, s, e) +#define iomem_deny_access(d, s, e) \ + rangeset_remove_range((d)->iomem_caps, s, e) +#define iomem_access_permitted(d, s, e) \ + rangeset_contains_range((d)->iomem_caps, s, e) + +#define irq_permit_access(d, i) \ + rangeset_add_singleton((d)->irq_caps, i) +#define irq_deny_access(d, i) \ + rangeset_remove_singleton((d)->irq_caps, i) +#define irqs_permit_access(d, s, e) \ + rangeset_add_range((d)->irq_caps, s, e) +#define irqs_deny_access(d, s, e) \ + rangeset_remove_range((d)->irq_caps, s, e) +#define irq_access_permitted(d, i) \ + rangeset_contains_singleton((d)->irq_caps, i) + +#define multipage_allocation_permitted(d) \ + (!rangeset_is_empty((d)->iomem_caps)) + +#endif /* __XEN_IOCAP_H__ */ diff -r 903fb46f240e -r cd914808acf1 xen/include/xen/rangeset.h --- /dev/null Tue Jan 3 14:59:00 2006 +++ b/xen/include/xen/rangeset.h Tue Jan 3 16:19:20 2006 @@ -0,0 +1,71 @@ +/****************************************************************************** + * rangeset.h + * + * Creation, maintenance and automatic destruction of per-domain sets of + * numeric ranges. + * + * Copyright (c) 2005, K A Fraser + */ + +#ifndef __XEN_RANGESET_H__ +#define __XEN_RANGESET_H__ + +struct domain; +struct rangeset; + +/* + * Initialise/destroy per-domain rangeset information. + * + * It is invalid to create or destroy a rangeset belonging to a domain @d + * before rangeset_domain_initialise(d) returns or after calling + * rangeset_domain_destroy(d). + */ +void rangeset_domain_initialise( + struct domain *d); +void rangeset_domain_destroy( + struct domain *d); + +/* + * Create/destroy a rangeset. Optionally attach to specified domain @d for + * auto-destruction when the domain dies. A name may be specified, for use + * in debug pretty-printing, and various RANGESETF flags (defined below). + * + * It is invalid to perform any operation on a rangeset @r after calling + * rangeset_destroy(r). + */ +struct rangeset *rangeset_new( + struct domain *d, char *name, unsigned int flags); +void rangeset_destroy( + struct rangeset *r); + +/* Flags for passing to rangeset_new(). */ + /* Pretty-print range limits in hexadecimal. */ +#define _RANGESETF_prettyprint_hex 0 +#define RANGESETF_prettyprint_hex (1U << _RANGESETF_prettyprint_hex) + +int __must_check rangeset_is_empty( + struct rangeset *r); + +/* Add/remove/query a numeric range. */ +int __must_check rangeset_add_range( + struct rangeset *r, unsigned long s, unsigned long e); +int __must_check rangeset_remove_range( + struct rangeset *r, unsigned long s, unsigned long e); +int __must_check rangeset_contains_range( + struct rangeset *r, unsigned long s, unsigned long e); + +/* Add/remove/query a single number. */ +int __must_check rangeset_add_singleton( + struct rangeset *r, unsigned long s); +int __must_check rangeset_remove_singleton( + struct rangeset *r, unsigned long s); +int __must_check rangeset_contains_singleton( + struct rangeset *r, unsigned long s); + +/* Rangeset pretty printing. */ +void rangeset_printk( + struct rangeset *r); +void rangeset_domain_printk( + struct domain *d); + +#endif /* __XEN_RANGESET_H__ */ diff -r 903fb46f240e -r cd914808acf1 linux-2.6-xen-sparse/include/asm-xen/asm-i386/bug.h --- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/bug.h Tue Jan 3 14:59:00 2006 +++ /dev/null Tue Jan 3 16:19:20 2006 @@ -1,16 +0,0 @@ -#ifndef _I386_BUG_H -#define _I386_BUG_H - -#include <linux/config.h> - -#define BUG() do { \ - printk("kernel BUG at %s:%d (%s)!\n", \ - __FILE__, __LINE__, __FUNCTION__); \ - dump_stack(); \ - panic("BUG!"); \ -} while (0) -#define HAVE_ARCH_BUG - -#include <asm-generic/bug.h> - -#endif diff -r 903fb46f240e -r cd914808acf1 xen/arch/x86/x86_32/xen.lds --- a/xen/arch/x86/x86_32/xen.lds Tue Jan 3 14:59:00 2006 +++ /dev/null Tue Jan 3 16:19:20 2006 @@ -1,79 +0,0 @@ -/* ld script to make i386 Linux kernel - * Written by Martin Mares <mj@xxxxxxxxxxxxxxxxxxxxxxxx> - * Modified for i386 Xen by Keir Fraser - */ -OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") -OUTPUT_ARCH(i386) -ENTRY(start) -PHDRS -{ - text PT_LOAD ; -} -SECTIONS -{ - . = 0xFF000000 + 0x100000; - _text = .; /* Text and read-only data */ - .text : { - *(.text) - *(.fixup) - *(.gnu.warning) - } :text =0x9090 - .text.lock : { *(.text.lock) } :text /* out-of-line lock text */ - - _etext = .; /* End of text section */ - - .rodata : { *(.rodata) *(.rodata.*) } :text - - . = ALIGN(32); /* Exception table */ - __start___ex_table = .; - __ex_table : { *(__ex_table) } :text - __stop___ex_table = .; - - . = ALIGN(32); /* Pre-exception table */ - __start___pre_ex_table = .; - __pre_ex_table : { *(__pre_ex_table) } :text - __stop___pre_ex_table = .; - - .data : { /* Data */ - *(.data) - CONSTRUCTORS - } :text - - . = ALIGN(4096); /* Init code and data */ - __init_begin = .; - .text.init : { *(.text.init) } :text - .data.init : { *(.data.init) } :text - . = ALIGN(32); - __setup_start = .; - .setup.init : { *(.setup.init) } :text - __setup_end = .; - __initcall_start = .; - .initcall.init : { *(.initcall.init) } :text - __initcall_end = .; - . = ALIGN(8192); - __init_end = .; - - __bss_start = .; /* BSS */ - .bss : { - *(.bss.twopage_aligned) - *(.bss.page_aligned) - *(.bss) - } :text - _end = . ; - - /* Sections to be discarded */ - /DISCARD/ : { - *(.text.exit) - *(.data.exit) - *(.exitcall.exit) - } - - /* Stabs debugging sections. */ - .stab 0 : { *(.stab) } - .stabstr 0 : { *(.stabstr) } - .stab.excl 0 : { *(.stab.excl) } - .stab.exclstr 0 : { *(.stab.exclstr) } - .stab.index 0 : { *(.stab.index) } - .stab.indexstr 0 : { *(.stab.indexstr) } - .comment 0 : { *(.comment) } -} diff -r 903fb46f240e -r cd914808acf1 xen/arch/x86/x86_64/xen.lds --- a/xen/arch/x86/x86_64/xen.lds Tue Jan 3 14:59:00 2006 +++ /dev/null Tue Jan 3 16:19:20 2006 @@ -1,77 +0,0 @@ -/* Excerpts written by Martin Mares <mj@xxxxxxxxxxxxxxxxxxxxxxxx> */ -/* Modified for x86-64 Xen by Keir Fraser */ -OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64") -OUTPUT_ARCH(i386:x86-64) -ENTRY(start) -PHDRS -{ - text PT_LOAD ; -} -SECTIONS -{ - . = 0xFFFF830000100000; - _text = .; /* Text and read-only data */ - .text : { - *(.text) - *(.fixup) - *(.gnu.warning) - } :text = 0x9090 - .text.lock : { *(.text.lock) } :text /* out-of-line lock text */ - - _etext = .; /* End of text section */ - - .rodata : { *(.rodata) *(.rodata.*) } :text - - . = ALIGN(32); /* Exception table */ - __start___ex_table = .; - __ex_table : { *(__ex_table) } :text - __stop___ex_table = .; - - . = ALIGN(32); /* Pre-exception table */ - __start___pre_ex_table = .; - __pre_ex_table : { *(__pre_ex_table) } :text - __stop___pre_ex_table = .; - - .data : { /* Data */ - *(.data) - CONSTRUCTORS - } :text - - . = ALIGN(4096); /* Init code and data */ - __init_begin = .; - .text.init : { *(.text.init) } :text - .data.init : { *(.data.init) } :text - . = ALIGN(32); - __setup_start = .; - .setup.init : { *(.setup.init) } :text - __setup_end = .; - __initcall_start = .; - .initcall.init : { *(.initcall.init) } :text - __initcall_end = .; - . = ALIGN(8192); - __init_end = .; - - __bss_start = .; /* BSS */ - .bss : { - *(.bss.twopage_aligned) - *(.bss.page_aligned) - *(.bss) - } :text - _end = . ; - - /* Sections to be discarded */ - /DISCARD/ : { - *(.text.exit) - *(.data.exit) - *(.exitcall.exit) - } - - /* Stabs debugging sections. */ - .stab 0 : { *(.stab) } - .stabstr 0 : { *(.stabstr) } - .stab.excl 0 : { *(.stab.excl) } - .stab.exclstr 0 : { *(.stab.exclstr) } - .stab.index 0 : { *(.stab.index) } - .stab.indexstr 0 : { *(.stab.indexstr) } - .comment 0 : { *(.comment) } -} diff -r 903fb46f240e -r cd914808acf1 xen/include/asm-x86/physdev.h --- a/xen/include/asm-x86/physdev.h Tue Jan 3 14:59:00 2006 +++ /dev/null Tue Jan 3 16:19:20 2006 @@ -1,17 +0,0 @@ -/****************************************************************************** - * physdev.h - */ - -#ifndef __XEN_PHYSDEV_H__ -#define __XEN_PHYSDEV_H__ - -#include <public/physdev.h> - -void physdev_modify_ioport_access_range( - struct domain *d, int enable, int port, int num ); -void physdev_destroy_state(struct domain *d); -int domain_iomem_in_pfn(struct domain *p, unsigned long pfn); -long do_physdev_op(physdev_op_t *uop); -void physdev_init_dom0(struct domain *d); - -#endif /* __XEN_PHYSDEV_H__ */ _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |