[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] merge with xen-unstable.hg
# HG changeset patch # User awilliam@xxxxxxxxxxxx # Date 1168899326 25200 # Node ID a2b2b2a011f1d406d49caba478020f3b2b173cb8 # Parent c6b683ba68f5417a5b397d8530edd9df14ad586c # Parent fb46005e07564bd152621c2ebf2c737b4115dc83 merge with xen-unstable.hg --- linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/kmap_types.h | 32 patches/linux-2.6.16.33/ipv6-no-autoconf.patch | 18 tools/xm-test/lib/XmTestLib/XenManagedDomain.py | 177 -- .hgignore | 4 buildconfigs/linux-defconfig_xen0_x86_32 | 1 buildconfigs/linux-defconfig_xenU_x86_32 | 1 buildconfigs/linux-defconfig_xen_x86_32 | 1 docs/xen-api/wire-protocol.tex | 2 extras/mini-os/Makefile | 24 extras/mini-os/gnttab.c | 36 extras/mini-os/include/hypervisor.h | 1 extras/mini-os/include/netfront.h | 2 extras/mini-os/include/x86/x86_32/hypercall-x86_32.h | 8 extras/mini-os/include/x86/x86_64/hypercall-x86_64.h | 8 extras/mini-os/include/xenbus.h | 3 extras/mini-os/kernel.c | 11 extras/mini-os/netfront.c | 455 +++++ extras/mini-os/xenbus/xenbus.c | 86 - linux-2.6-xen-sparse/arch/i386/Kconfig | 2 linux-2.6-xen-sparse/arch/i386/kernel/pci-dma-xen.c | 19 linux-2.6-xen-sparse/arch/i386/kernel/swiotlb.c | 74 linux-2.6-xen-sparse/arch/i386/mm/fault-xen.c | 4 linux-2.6-xen-sparse/arch/i386/mm/highmem-xen.c | 1 linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c | 30 linux-2.6-xen-sparse/arch/x86_64/mm/pageattr-xen.c | 16 linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c | 32 linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c | 32 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/dma-mapping.h | 6 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgalloc.h | 2 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/swiotlb.h | 4 linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/pgalloc.h | 85 patches/linux-2.6.16.33/series | 1 tools/check/check_udev | 4 tools/examples/vtpm-common.sh | 4 tools/examples/xen-network-common.sh | 5 tools/examples/xmexample1 | 34 tools/examples/xmexample2 | 34 tools/examples/xmexample3 | 34 tools/libxc/xc_load_elf.c | 14 tools/libxc/xc_ptrace.c | 18 tools/pygrub/src/pygrub | 65 tools/python/xen/xend/XendConfig.py | 9 tools/python/xen/xend/XendDomainInfo.py | 33 tools/python/xen/xend/server/blkif.py | 1 tools/python/xen/xm/create.py | 3 tools/tests/Makefile | 13 tools/tests/blowfish.c | 439 +++++ tools/tests/blowfish.mk | 23 tools/tests/test_x86_emulator.c | 46 tools/xenstat/xentop/xentop.c | 2 tools/xm-test/README | 43 tools/xm-test/configure.ac | 1 tools/xm-test/grouptest/xapi | 1 tools/xm-test/lib/XmTestLib/DomainTracking.py | 18 tools/xm-test/lib/XmTestLib/XenAPIDomain.py | 176 ++ tools/xm-test/lib/XmTestLib/Xm.py | 2 tools/xm-test/lib/XmTestLib/xapi.py | 79 tools/xm-test/runtest.sh | 8 tools/xm-test/tests/vtpm/09_vtpm-xapi.py | 99 - tools/xm-test/tests/xapi/01_xapi-vm_basic.py | 61 tools/xm-test/tests/xapi/Makefile.am | 19 unmodified_drivers/linux-2.6/platform-pci/platform-pci.c | 34 unmodified_drivers/linux-2.6/platform-pci/platform-pci.h | 4 xen/arch/ia64/linux-xen/unaligned.c | 2 xen/arch/ia64/xen/xenmisc.c | 4 xen/arch/x86/domain.c | 2 xen/arch/x86/hvm/hpet.c | 2 xen/arch/x86/hvm/hvm.c | 2 xen/arch/x86/hvm/irq.c | 187 +- xen/arch/x86/hvm/vioapic.c | 11 xen/arch/x86/hvm/vmx/vmcs.c | 9 xen/arch/x86/hvm/vmx/vmx.c | 133 - xen/arch/x86/hvm/vmx/x86_32/exits.S | 33 xen/arch/x86/hvm/vmx/x86_64/exits.S | 29 xen/arch/x86/mm.c | 19 xen/arch/x86/mm/shadow/common.c | 5 xen/arch/x86/oprofile/nmi_int.c | 2 xen/arch/x86/setup.c | 25 xen/arch/x86/traps.c | 18 xen/arch/x86/x86_64/compat/mm.c | 20 xen/arch/x86/x86_emulate.c | 853 ++++++++-- xen/common/elf.c | 2 xen/common/kexec.c | 22 xen/common/keyhandler.c | 13 xen/common/lib.c | 644 +++---- xen/common/xencomm.c | 4 xen/drivers/video/vga.c | 11 xen/include/Makefile | 52 xen/include/asm-x86/guest_access.h | 18 xen/include/asm-x86/hvm/irq.h | 16 xen/include/asm-x86/x86_emulate.h | 16 xen/include/public/elfnote.h | 9 xen/include/public/hvm/params.h | 22 xen/tools/compat-build-header.py | 21 xen/tools/compat-build-source.py | 27 xen/tools/get-fields.sh | 53 96 files changed, 3430 insertions(+), 1360 deletions(-) diff -r c6b683ba68f5 -r a2b2b2a011f1 .hgignore --- a/.hgignore Sun Jan 14 22:18:38 2007 -0700 +++ b/.hgignore Mon Jan 15 15:15:26 2007 -0700 @@ -58,7 +58,7 @@ ^docs/xen-api/xenapi-datamodel-graph.eps$ ^extras/mini-os/h/hypervisor-ifs$ ^extras/mini-os/h/xen-public$ -^extras/mini-os/mini-os\..*$ +^extras/mini-os/mini-os.*$ ^install/.*$ ^linux-[^/]*-native/.*$ ^linux-[^/]*-xen/.*$ @@ -142,6 +142,8 @@ ^tools/python/build/.*$ ^tools/security/secpol_tool$ ^tools/security/xen/.*$ +^tools/tests/blowfish\.bin$ +^tools/tests/blowfish\.h$ ^tools/tests/test_x86_emulator$ ^tools/vnet/Make.local$ ^tools/vnet/build/.*$ diff -r c6b683ba68f5 -r a2b2b2a011f1 buildconfigs/linux-defconfig_xen0_x86_32 --- a/buildconfigs/linux-defconfig_xen0_x86_32 Sun Jan 14 22:18:38 2007 -0700 +++ b/buildconfigs/linux-defconfig_xen0_x86_32 Mon Jan 15 15:15:26 2007 -0700 @@ -172,6 +172,7 @@ CONFIG_FLAT_NODE_MEM_MAP=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4096 +# CONFIG_HIGHPTE is not set CONFIG_MTRR=y # CONFIG_REGPARM is not set CONFIG_SECCOMP=y diff -r c6b683ba68f5 -r a2b2b2a011f1 buildconfigs/linux-defconfig_xenU_x86_32 --- a/buildconfigs/linux-defconfig_xenU_x86_32 Sun Jan 14 22:18:38 2007 -0700 +++ b/buildconfigs/linux-defconfig_xenU_x86_32 Mon Jan 15 15:15:26 2007 -0700 @@ -172,6 +172,7 @@ CONFIG_FLAT_NODE_MEM_MAP=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4096 +# CONFIG_HIGHPTE is not set # CONFIG_REGPARM is not set CONFIG_SECCOMP=y CONFIG_HZ_100=y diff -r c6b683ba68f5 -r a2b2b2a011f1 buildconfigs/linux-defconfig_xen_x86_32 --- a/buildconfigs/linux-defconfig_xen_x86_32 Sun Jan 14 22:18:38 2007 -0700 +++ b/buildconfigs/linux-defconfig_xen_x86_32 Mon Jan 15 15:15:26 2007 -0700 @@ -180,6 +180,7 @@ CONFIG_FLAT_NODE_MEM_MAP=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4096 +# CONFIG_HIGHPTE is not set CONFIG_MTRR=y CONFIG_REGPARM=y CONFIG_SECCOMP=y diff -r c6b683ba68f5 -r a2b2b2a011f1 docs/xen-api/wire-protocol.tex --- a/docs/xen-api/wire-protocol.tex Sun Jan 14 22:18:38 2007 -0700 +++ b/docs/xen-api/wire-protocol.tex Mon Jan 15 15:15:26 2007 -0700 @@ -153,7 +153,7 @@ you must login and initiate a session. F \end{verbatim} Where {\tt uname} and {\tt password} refer to your username and password respectively, as defined by the Xen administrator. -The {\tt session\_id} returned by {\tt session.login_with_password} is passed +The {\tt session\_id} returned by {\tt session.login\_with\_password} is passed to subequent RPC calls as an authentication token. A session can be terminated with the {\tt session.logout} function: diff -r c6b683ba68f5 -r a2b2b2a011f1 extras/mini-os/Makefile --- a/extras/mini-os/Makefile Sun Jan 14 22:18:38 2007 -0700 +++ b/extras/mini-os/Makefile Mon Jan 15 15:15:26 2007 -0700 @@ -7,7 +7,7 @@ include $(XEN_ROOT)/Config.mk # Set TARGET_ARCH override TARGET_ARCH := $(XEN_TARGET_ARCH) -XEN_INTERFACE_VERSION := 0x00030203 +XEN_INTERFACE_VERSION := 0x00030204 # NB. '-Wcast-qual' is nasty, so I omitted it. CFLAGS := -fno-builtin -Wall -Werror -Wredundant-decls -Wno-format @@ -17,7 +17,13 @@ ASFLAGS = -D__ASSEMBLY__ ASFLAGS = -D__ASSEMBLY__ LDLIBS = -L. -lminios -LDFLAGS := -N -T minios-$(TARGET_ARCH).lds +LDFLAGS_FINAL := -N -T minios-$(TARGET_ARCH).lds +LDFLAGS := + +# Prefix for global API names. All other symbols are localised before +# linking with EXTRA_OBJS. +GLOBAL_PREFIX := xenos_ +EXTRA_OBJS = # For possible special source directories. EXTRA_SRC = @@ -110,18 +116,16 @@ links: $(ARCH_LINKS) links: $(ARCH_LINKS) [ -e include/xen ] || ln -sf ../../../xen/include/public include/xen -libminios.a: links $(OBJS) $(HEAD) - $(AR) r libminios.a $(HEAD) $(OBJS) - -$(TARGET): libminios.a $(HEAD) - $(LD) $(LDFLAGS) $(HEAD) $(LDLIBS) -o $@.elf - gzip -f -9 -c $@.elf >$@.gz +$(TARGET): links $(OBJS) $(HEAD) + $(LD) -r $(LDFLAGS) $(HEAD) $(OBJS) -o $@.o + $(OBJCOPY) -w -G $(GLOBAL_PREFIX)* -G _start $@.o $@.o + $(LD) $(LDFLAGS) $(LDFLAGS_FINAL) $@.o $(EXTRA_OBJS) -o $@ + gzip -f -9 -c $@ >$@.gz .PHONY: clean clean: find . -type f -name '*.o' | xargs rm -f - rm -f *.o *~ core $(TARGET).elf $(TARGET).raw $(TARGET) $(TARGET).gz - rm -f libminios.a + rm -f *.o *~ core $(TARGET) $(TARGET).gz find . -type l | xargs rm -f rm -f tags TAGS diff -r c6b683ba68f5 -r a2b2b2a011f1 extras/mini-os/gnttab.c --- a/extras/mini-os/gnttab.c Sun Jan 14 22:18:38 2007 -0700 +++ b/extras/mini-os/gnttab.c Mon Jan 15 15:15:26 2007 -0700 @@ -23,31 +23,24 @@ #define NR_GRANT_FRAMES 4 #define NR_GRANT_ENTRIES (NR_GRANT_FRAMES * PAGE_SIZE / sizeof(grant_entry_t)) -#define GNTTAB_LIST_END (NR_GRANT_ENTRIES + 1) static grant_entry_t *gnttab_table; static grant_ref_t gnttab_list[NR_GRANT_ENTRIES]; -static grant_ref_t gnttab_free_head; + +static void +put_free_entry(grant_ref_t ref) +{ + gnttab_list[ref] = gnttab_list[0]; + gnttab_list[0] = ref; + +} static grant_ref_t -get_free_entries(int count) +get_free_entry(void) { - grant_ref_t ref; - grant_ref_t head; - - ref = head = gnttab_free_head; - while (count-- > 1) - head = gnttab_list[head]; - gnttab_free_head = gnttab_list[head]; - gnttab_list[head] = GNTTAB_LIST_END; + unsigned int ref = gnttab_list[0]; + gnttab_list[0] = gnttab_list[ref]; return ref; -} - -static void -put_free_entry(grant_ref_t gref) -{ - gnttab_list[gref] = gnttab_free_head; - gnttab_free_head = gref; } grant_ref_t @@ -55,7 +48,7 @@ gnttab_grant_access(domid_t domid, unsig { grant_ref_t ref; - ref = get_free_entries(1); + ref = get_free_entry(); gnttab_table[ref].frame = frame; gnttab_table[ref].domid = domid; wmb(); @@ -70,7 +63,7 @@ gnttab_grant_transfer(domid_t domid, uns { grant_ref_t ref; - ref = get_free_entries(1); + ref = get_free_entry(); gnttab_table[ref].frame = pfn; gnttab_table[ref].domid = domid; wmb(); @@ -157,8 +150,7 @@ init_gnttab(void) int i; for (i = NR_RESERVED_ENTRIES; i < NR_GRANT_ENTRIES; i++) - gnttab_list[i] = i + 1; - gnttab_free_head = NR_RESERVED_ENTRIES; + put_free_entry(i); setup.dom = DOMID_SELF; setup.nr_frames = NR_GRANT_FRAMES; diff -r c6b683ba68f5 -r a2b2b2a011f1 extras/mini-os/include/hypervisor.h --- a/extras/mini-os/include/hypervisor.h Sun Jan 14 22:18:38 2007 -0700 +++ b/extras/mini-os/include/hypervisor.h Mon Jan 15 15:15:26 2007 -0700 @@ -15,7 +15,6 @@ #include <types.h> #include <xen/xen.h> -#include <xen/dom0_ops.h> #if defined(__i386__) #include <hypercall-x86_32.h> #elif defined(__x86_64__) diff -r c6b683ba68f5 -r a2b2b2a011f1 extras/mini-os/include/netfront.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extras/mini-os/include/netfront.h Mon Jan 15 15:15:26 2007 -0700 @@ -0,0 +1,2 @@ +void init_netfront(void*); +void netfront_xmit(unsigned char* data,int len); diff -r c6b683ba68f5 -r a2b2b2a011f1 extras/mini-os/include/x86/x86_32/hypercall-x86_32.h --- a/extras/mini-os/include/x86/x86_32/hypercall-x86_32.h Sun Jan 14 22:18:38 2007 -0700 +++ b/extras/mini-os/include/x86/x86_32/hypercall-x86_32.h Mon Jan 15 15:15:26 2007 -0700 @@ -179,14 +179,6 @@ HYPERVISOR_set_timer_op( unsigned long timeout_hi = (unsigned long)(timeout>>32); unsigned long timeout_lo = (unsigned long)timeout; return _hypercall2(long, set_timer_op, timeout_lo, timeout_hi); -} - -static inline int -HYPERVISOR_dom0_op( - dom0_op_t *dom0_op) -{ - dom0_op->interface_version = DOM0_INTERFACE_VERSION; - return _hypercall1(int, dom0_op, dom0_op); } static inline int diff -r c6b683ba68f5 -r a2b2b2a011f1 extras/mini-os/include/x86/x86_64/hypercall-x86_64.h --- a/extras/mini-os/include/x86/x86_64/hypercall-x86_64.h Sun Jan 14 22:18:38 2007 -0700 +++ b/extras/mini-os/include/x86/x86_64/hypercall-x86_64.h Mon Jan 15 15:15:26 2007 -0700 @@ -181,14 +181,6 @@ HYPERVISOR_set_timer_op( u64 timeout) { return _hypercall1(long, set_timer_op, timeout); -} - -static inline int -HYPERVISOR_dom0_op( - dom0_op_t *dom0_op) -{ - dom0_op->interface_version = DOM0_INTERFACE_VERSION; - return _hypercall1(int, dom0_op, dom0_op); } static inline int diff -r c6b683ba68f5 -r a2b2b2a011f1 extras/mini-os/include/xenbus.h --- a/extras/mini-os/include/xenbus.h Sun Jan 14 22:18:38 2007 -0700 +++ b/extras/mini-os/include/xenbus.h Mon Jan 15 15:15:26 2007 -0700 @@ -11,6 +11,9 @@ void init_xenbus(void); string on failure and sets *value to NULL. On success, *value is set to a malloc'd copy of the value. */ char *xenbus_read(xenbus_transaction_t xbt, const char *path, char **value); + +char *xenbus_watch_path(xenbus_transaction_t xbt, const char *path); +char* xenbus_wait_for_value(const char*,const char*); /* Associates a value with a path. Returns a malloc'd error string on failure. */ diff -r c6b683ba68f5 -r a2b2b2a011f1 extras/mini-os/kernel.c --- a/extras/mini-os/kernel.c Sun Jan 14 22:18:38 2007 -0700 +++ b/extras/mini-os/kernel.c Mon Jan 15 15:15:26 2007 -0700 @@ -37,6 +37,7 @@ #include <sched.h> #include <xenbus.h> #include <gnttab.h> +#include <netfront.h> #include <xen/features.h> #include <xen/version.h> @@ -61,13 +62,13 @@ void setup_xen_features(void) void test_xenbus(void); -void xenbus_tester(void *p) +static void xenbus_tester(void *p) { printk("Xenbus tests disabled, because of a Xend bug.\n"); /* test_xenbus(); */ } -void periodic_thread(void *p) +static void periodic_thread(void *p) { struct timeval tv; printk("Periodic thread started.\n"); @@ -79,12 +80,18 @@ void periodic_thread(void *p) } } +static void netfront_thread(void *p) +{ + init_netfront(&start_info); +} + /* This should be overridden by the application we are linked against. */ __attribute__((weak)) int app_main(start_info_t *si) { printk("Dummy main: start_info=%p\n", si); create_thread("xenbus_tester", xenbus_tester, si); create_thread("periodic_thread", periodic_thread, si); + create_thread("netfront", netfront_thread, si); return 0; } diff -r c6b683ba68f5 -r a2b2b2a011f1 extras/mini-os/netfront.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extras/mini-os/netfront.c Mon Jan 15 15:15:26 2007 -0700 @@ -0,0 +1,455 @@ +/* Minimal network driver for Mini-OS. + * Copyright (c) 2006-2007 Jacob Gorm Hansen, University of Copenhagen. + * Based on netfront.c from Xen Linux. + * + * Does not handle fragments or extras. + */ + +#include <os.h> +#include <xenbus.h> +#include <events.h> +#include <errno.h> +#include <xen/io/netif.h> +#include <gnttab.h> +#include <xmalloc.h> +#include <time.h> + +void init_rx_buffers(void); + +struct net_info { + struct netif_tx_front_ring tx; + struct netif_rx_front_ring rx; + int tx_ring_ref; + int rx_ring_ref; + unsigned int evtchn, local_port; + +} net_info; + + +char* xenbus_printf(xenbus_transaction_t xbt, + char* node,char* path, + char* fmt,unsigned int arg) +{ + char fullpath[256]; + char val[256]; + + sprintf(fullpath,"%s/%s",node,path); + sprintf(val,fmt,arg); + xenbus_write(xbt,fullpath,val); + + return NULL; +} + + +#define NET_TX_RING_SIZE __RING_SIZE((struct netif_tx_sring *)0, PAGE_SIZE) +#define NET_RX_RING_SIZE __RING_SIZE((struct netif_rx_sring *)0, PAGE_SIZE) +#define GRANT_INVALID_REF 0 + + +unsigned short rx_freelist[NET_RX_RING_SIZE]; +unsigned short tx_freelist[NET_TX_RING_SIZE]; + +struct net_buffer { + void* page; + int gref; +}; +struct net_buffer rx_buffers[NET_RX_RING_SIZE]; +struct net_buffer tx_buffers[NET_TX_RING_SIZE]; + +static inline void add_id_to_freelist(unsigned int id,unsigned short* freelist) +{ + freelist[id] = freelist[0]; + freelist[0] = id; +} + +static inline unsigned short get_id_from_freelist(unsigned short* freelist) +{ + unsigned int id = freelist[0]; + freelist[0] = freelist[id]; + return id; +} + +__attribute__((weak)) void netif_rx(unsigned char* data,int len) +{ + printk("%d bytes incoming at %p\n",len,data); +} + +__attribute__((weak)) void net_app_main(void*si,unsigned char*mac) {} + +static inline int xennet_rxidx(RING_IDX idx) +{ + return idx & (NET_RX_RING_SIZE - 1); +} + +void network_rx(void) +{ + struct net_info *np = &net_info; + RING_IDX rp,cons; + struct netif_rx_response *rx; + + +moretodo: + rp = np->rx.sring->rsp_prod; + rmb(); /* Ensure we see queued responses up to 'rp'. */ + cons = np->rx.rsp_cons; + + int nr_consumed=0; + while ((cons != rp)) + { + struct net_buffer* buf; + unsigned char* page; + + rx = RING_GET_RESPONSE(&np->rx, cons); + + if (rx->flags & NETRXF_extra_info) + { + printk("+++++++++++++++++++++ we have extras!\n"); + continue; + } + + + if (rx->status == NETIF_RSP_NULL) continue; + + int id = rx->id; + + buf = &rx_buffers[id]; + page = (unsigned char*)buf->page; + gnttab_end_access(buf->gref); + + if(rx->status>0) + { + netif_rx(page+rx->offset,rx->status); + } + + add_id_to_freelist(id,rx_freelist); + + nr_consumed++; + + ++cons; + } + np->rx.rsp_cons=rp; + + int more; + RING_FINAL_CHECK_FOR_RESPONSES(&np->rx,more); + if(more) goto moretodo; + + RING_IDX req_prod = np->rx.req_prod_pvt; + + int i; + netif_rx_request_t *req; + + for(i=0; i<nr_consumed; i++) + { + int id = xennet_rxidx(req_prod + i); + req = RING_GET_REQUEST(&np->rx, req_prod + i); + struct net_buffer* buf = &rx_buffers[id]; + void* page = buf->page; + + buf->gref = req->gref = + gnttab_grant_access(0,virt_to_mfn(page),0); + + req->id = id; + } + + wmb(); + + np->rx.req_prod_pvt = req_prod + i; + + int notify; + RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&np->rx, notify); + if (notify) + notify_remote_via_evtchn(np->evtchn); + +} + +void network_tx_buf_gc(void) +{ + + + RING_IDX cons, prod; + unsigned short id; + struct net_info *np = &net_info; + + do { + prod = np->tx.sring->rsp_prod; + rmb(); /* Ensure we see responses up to 'rp'. */ + + for (cons = np->tx.rsp_cons; cons != prod; cons++) + { + struct netif_tx_response *txrsp; + + txrsp = RING_GET_RESPONSE(&np->tx, cons); + if (txrsp->status == NETIF_RSP_NULL) + continue; + + id = txrsp->id; + struct net_buffer* buf = &tx_buffers[id]; + gnttab_end_access(buf->gref); + buf->gref=GRANT_INVALID_REF; + + add_id_to_freelist(id,tx_freelist); + } + + np->tx.rsp_cons = prod; + + /* + * Set a new event, then check for race with update of tx_cons. + * Note that it is essential to schedule a callback, no matter + * how few tx_buffers are pending. Even if there is space in the + * transmit ring, higher layers may be blocked because too much + * data is outstanding: in such cases notification from Xen is + * likely to be the only kick that we'll get. + */ + np->tx.sring->rsp_event = + prod + ((np->tx.sring->req_prod - prod) >> 1) + 1; + mb(); + } while ((cons == prod) && (prod != np->tx.sring->rsp_prod)); + + +} + +void netfront_handler(evtchn_port_t port, struct pt_regs *regs, void *data) +{ + int flags; + + local_irq_save(flags); + + network_tx_buf_gc(); + network_rx(); + + local_irq_restore(flags); +} + +char* backend; + +void init_netfront(void* si) +{ + xenbus_transaction_t xbt; + struct net_info* info = &net_info; + char* err; + char* message=NULL; + char nodename[] = "device/vif/0"; + struct netif_tx_sring *txs; + struct netif_rx_sring *rxs; + int retry=0; + int i; + char* mac; + char* msg; + + printk("************************ NETFRONT **********\n\n\n"); + + for(i=0;i<NET_TX_RING_SIZE;i++) + { + add_id_to_freelist(i,tx_freelist); + tx_buffers[i].page = (char*)alloc_page(); + } + + for(i=0;i<NET_RX_RING_SIZE;i++) + { + add_id_to_freelist(i,rx_freelist); + rx_buffers[i].page = (char*)alloc_page(); + } + + txs = (struct netif_tx_sring*) alloc_page(); + rxs = (struct netif_rx_sring *) alloc_page(); + memset(txs,0,PAGE_SIZE); + memset(rxs,0,PAGE_SIZE); + + + SHARED_RING_INIT(txs); + SHARED_RING_INIT(rxs); + FRONT_RING_INIT(&info->tx, txs, PAGE_SIZE); + FRONT_RING_INIT(&info->rx, rxs, PAGE_SIZE); + + info->tx_ring_ref = gnttab_grant_access(0,virt_to_mfn(txs),0); + info->rx_ring_ref = gnttab_grant_access(0,virt_to_mfn(rxs),0); + + evtchn_alloc_unbound_t op; + op.dom = DOMID_SELF; + op.remote_dom = 0; + HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, &op); + clear_evtchn(op.port); /* Without, handler gets invoked now! */ + info->local_port = bind_evtchn(op.port, netfront_handler, NULL); + info->evtchn=op.port; + +again: + err = xenbus_transaction_start(&xbt); + if (err) { + printk("starting transaction\n"); + } + + err = xenbus_printf(xbt, nodename, "tx-ring-ref","%u", + info->tx_ring_ref); + if (err) { + message = "writing tx ring-ref"; + goto abort_transaction; + } + err = xenbus_printf(xbt, nodename, "rx-ring-ref","%u", + info->rx_ring_ref); + if (err) { + message = "writing rx ring-ref"; + goto abort_transaction; + } + err = xenbus_printf(xbt, nodename, + "event-channel", "%u", info->evtchn); + if (err) { + message = "writing event-channel"; + goto abort_transaction; + } + + err = xenbus_printf(xbt, nodename, "request-rx-copy", "%u", 1); + + if (err) { + message = "writing request-rx-copy"; + goto abort_transaction; + } + + err = xenbus_printf(xbt, nodename, "state", "%u", + 4); /* connected */ + + + err = xenbus_transaction_end(xbt, 0, &retry); + if (retry) { + goto again; + printk("completing transaction\n"); + } + + goto done; + +abort_transaction: + xenbus_transaction_end(xbt, 1, &retry); + +done: + + msg = xenbus_read(XBT_NIL, "device/vif/0/backend", &backend); + msg = xenbus_read(XBT_NIL, "device/vif/0/mac", &mac); + + printk("backend at %s\n",backend); + printk("mac is %s\n",mac); + + char *res; + char path[256]; + sprintf(path,"%s/state",backend); + + xenbus_watch_path(XBT_NIL, path); + + xenbus_wait_for_value(path,"4"); + + //free(backend); + free(res); + + printk("**************************\n"); + + init_rx_buffers(); + + unsigned char rawmac[6]; + sscanf(mac,"%x:%x:%x:%x:%x:%x", + &rawmac[0], + &rawmac[1], + &rawmac[2], + &rawmac[3], + &rawmac[4], + &rawmac[5]); + + net_app_main(si,rawmac); +} + +void shutdown_netfront(void) +{ + //xenbus_transaction_t xbt; + char* err; + char nodename[] = "device/vif/0"; + + char path[256]; + + printk("close network: backend at %s\n",backend); + + err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 6); /* closing */ + sprintf(path,"%s/state",backend); + + xenbus_wait_for_value(path,"6"); + + err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 1); + + xenbus_wait_for_value(path,"2"); + + unbind_all_ports(); + +} + + +void init_rx_buffers(void) +{ + struct net_info* np = &net_info; + int i, requeue_idx; + netif_rx_request_t *req; + int notify; + + np->rx.req_prod_pvt = requeue_idx; + + + /* Step 2: Rebuild the RX buffer freelist and the RX ring itself. */ + for (requeue_idx = 0, i = 0; i < NET_RX_RING_SIZE; i++) + { + struct net_buffer* buf = &rx_buffers[requeue_idx]; + req = RING_GET_REQUEST(&np->rx, requeue_idx); + + buf->gref = req->gref = + gnttab_grant_access(0,virt_to_mfn(buf->page),0); + + req->id = requeue_idx; + + requeue_idx++; + } + + np->rx.req_prod_pvt = requeue_idx; + + + + RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&np->rx, notify); + + if(notify) + notify_remote_via_evtchn(np->evtchn); + + np->rx.sring->rsp_event = np->rx.rsp_cons + 1; + + +} + + +void netfront_xmit(unsigned char* data,int len) +{ + int flags; + local_irq_save(flags); + + struct net_info* info = &net_info; + struct netif_tx_request *tx; + RING_IDX i = info->tx.req_prod_pvt; + int notify; + int id = get_id_from_freelist(tx_freelist); + struct net_buffer* buf = &tx_buffers[id]; + void* page = buf->page; + + tx = RING_GET_REQUEST(&info->tx, i); + + memcpy(page,data,len); + + buf->gref = + tx->gref = gnttab_grant_access(0,virt_to_mfn(page),0); + + tx->offset=0; + tx->size = len; + tx->flags=0; + tx->id = id; + info->tx.req_prod_pvt = i + 1; + + wmb(); + + RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&info->tx, notify); + + if(notify) notify_remote_via_evtchn(info->evtchn); + + network_tx_buf_gc(); + + local_irq_restore(flags); +} diff -r c6b683ba68f5 -r a2b2b2a011f1 extras/mini-os/xenbus/xenbus.c --- a/extras/mini-os/xenbus/xenbus.c Sun Jan 14 22:18:38 2007 -0700 +++ b/extras/mini-os/xenbus/xenbus.c Mon Jan 15 15:15:26 2007 -0700 @@ -45,9 +45,9 @@ #define DEBUG(_f, _a...) ((void)0) #endif - static struct xenstore_domain_interface *xenstore_buf; static DECLARE_WAIT_QUEUE_HEAD(xb_waitq); +static DECLARE_WAIT_QUEUE_HEAD(watch_queue); struct xenbus_req_info { int in_use:1; @@ -71,6 +71,34 @@ static void memcpy_from_ring(const void memcpy(dest, ring + off, c1); memcpy(dest + c1, ring, c2); } + +static inline void wait_for_watch(void) +{ + DEFINE_WAIT(w); + add_waiter(w,watch_queue); + schedule(); + wake(current); +} + +char* xenbus_wait_for_value(const char* path,const char* value) +{ + for(;;) + { + char *res, *msg; + int r; + + msg = xenbus_read(XBT_NIL, path, &res); + if(msg) return msg; + + r = strcmp(value,res); + free(res); + + if(r==0) break; + else wait_for_watch(); + } + return NULL; +} + static void xenbus_thread_func(void *ign) { @@ -101,13 +129,35 @@ static void xenbus_thread_func(void *ign break; DEBUG("Message is good.\n"); - req_info[msg.req_id].reply = malloc(sizeof(msg) + msg.len); - memcpy_from_ring(xenstore_buf->rsp, + + if(msg.type == XS_WATCH_EVENT) + { + char* payload = (char*)malloc(sizeof(msg) + msg.len); + char *path,*token; + + memcpy_from_ring(xenstore_buf->rsp, + payload, + MASK_XENSTORE_IDX(xenstore_buf->rsp_cons), + msg.len + sizeof(msg)); + + path = payload + sizeof(msg); + token = path + strlen(path) + 1; + + xenstore_buf->rsp_cons += msg.len + sizeof(msg); + free(payload); + wake_up(&watch_queue); + } + + else + { + req_info[msg.req_id].reply = malloc(sizeof(msg) + msg.len); + memcpy_from_ring(xenstore_buf->rsp, req_info[msg.req_id].reply, MASK_XENSTORE_IDX(xenstore_buf->rsp_cons), msg.len + sizeof(msg)); - wake_up(&req_info[msg.req_id].waitq); - xenstore_buf->rsp_cons += msg.len + sizeof(msg); + xenstore_buf->rsp_cons += msg.len + sizeof(msg); + wake_up(&req_info[msg.req_id].waitq); + } } } } @@ -381,9 +431,29 @@ char *xenbus_write(xenbus_transaction_t struct xsd_sockmsg *rep; rep = xenbus_msg_reply(XS_WRITE, xbt, req, ARRAY_SIZE(req)); char *msg = errmsg(rep); - if (msg) - return msg; - free(rep); + if (msg) return msg; + free(rep); + return NULL; +} + +char* xenbus_watch_path( xenbus_transaction_t xbt, const char *path) +{ + /* in the future one could have multiple watch queues, and use + * the token for demuxing. For now the token is 0. */ + + struct xsd_sockmsg *rep; + + struct write_req req[] = { + {path, strlen(path) + 1}, + {"0",2 }, + }; + + rep = xenbus_msg_reply(XS_WATCH, xbt, req, ARRAY_SIZE(req)); + + char *msg = errmsg(rep); + if (msg) return msg; + free(rep); + return NULL; } diff -r c6b683ba68f5 -r a2b2b2a011f1 linux-2.6-xen-sparse/arch/i386/Kconfig --- a/linux-2.6-xen-sparse/arch/i386/Kconfig Sun Jan 14 22:18:38 2007 -0700 +++ b/linux-2.6-xen-sparse/arch/i386/Kconfig Mon Jan 15 15:15:26 2007 -0700 @@ -594,7 +594,7 @@ config HAVE_ARCH_EARLY_PFN_TO_NID config HIGHPTE bool "Allocate 3rd-level pagetables from highmem" - depends on (HIGHMEM4G || HIGHMEM64G) && !X86_XEN + depends on HIGHMEM4G || HIGHMEM64G help The VM uses one page table entry for each page of physical memory. For systems with a lot of RAM, this can be wasteful of precious diff -r c6b683ba68f5 -r a2b2b2a011f1 linux-2.6-xen-sparse/arch/i386/kernel/pci-dma-xen.c --- a/linux-2.6-xen-sparse/arch/i386/kernel/pci-dma-xen.c Sun Jan 14 22:18:38 2007 -0700 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/pci-dma-xen.c Mon Jan 15 15:15:26 2007 -0700 @@ -94,13 +94,7 @@ dma_unmap_sg(struct device *hwdev, struc } EXPORT_SYMBOL(dma_unmap_sg); -/* - * XXX This file is also used by xenLinux/ia64. - * "defined(__i386__) || defined (__x86_64__)" means "!defined(__ia64__)". - * This #if work around should be removed once this file is merbed back into - * i386' pci-dma or is moved to drivers/xen/core. - */ -#if defined(__i386__) || defined(__x86_64__) +#ifdef CONFIG_HIGHMEM dma_addr_t dma_map_page(struct device *dev, struct page *page, unsigned long offset, size_t size, enum dma_data_direction direction) @@ -130,7 +124,7 @@ dma_unmap_page(struct device *dev, dma_a swiotlb_unmap_page(dev, dma_address, size, direction); } EXPORT_SYMBOL(dma_unmap_page); -#endif /* defined(__i386__) || defined(__x86_64__) */ +#endif /* CONFIG_HIGHMEM */ int dma_mapping_error(dma_addr_t dma_addr) @@ -161,6 +155,8 @@ void *dma_alloc_coherent(struct device * struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL; unsigned int order = get_order(size); unsigned long vstart; + u64 mask; + /* ignore region specifiers */ gfp &= ~(__GFP_DMA | __GFP_HIGHMEM); @@ -183,9 +179,14 @@ void *dma_alloc_coherent(struct device * vstart = __get_free_pages(gfp, order); ret = (void *)vstart; + if (dev != NULL && dev->coherent_dma_mask) + mask = dev->coherent_dma_mask; + else + mask = 0xffffffff; + if (ret != NULL) { if (xen_create_contiguous_region(vstart, order, - dma_bits) != 0) { + fls64(mask)) != 0) { free_pages(vstart, order); return NULL; } diff -r c6b683ba68f5 -r a2b2b2a011f1 linux-2.6-xen-sparse/arch/i386/kernel/swiotlb.c --- a/linux-2.6-xen-sparse/arch/i386/kernel/swiotlb.c Sun Jan 14 22:18:38 2007 -0700 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/swiotlb.c Mon Jan 15 15:15:26 2007 -0700 @@ -47,9 +47,6 @@ EXPORT_SYMBOL(swiotlb); */ #define IO_TLB_SHIFT 11 -/* Width of DMA addresses. 30 bits is a b44 limitation. */ -#define DEFAULT_DMA_BITS 30 - static int swiotlb_force; static char *iotlb_virt_start; static unsigned long iotlb_nslabs; @@ -98,11 +95,12 @@ static struct phys_addr { */ static DEFINE_SPINLOCK(io_tlb_lock); -unsigned int dma_bits = DEFAULT_DMA_BITS; +static unsigned int dma_bits; +static unsigned int __initdata max_dma_bits = 32; static int __init setup_dma_bits(char *str) { - dma_bits = simple_strtoul(str, NULL, 0); + max_dma_bits = simple_strtoul(str, NULL, 0); return 0; } __setup("dma_bits=", setup_dma_bits); @@ -143,6 +141,7 @@ swiotlb_init_with_default_size (size_t d swiotlb_init_with_default_size (size_t default_size) { unsigned long i, bytes; + int rc; if (!iotlb_nslabs) { iotlb_nslabs = (default_size >> IO_TLB_SHIFT); @@ -159,16 +158,33 @@ swiotlb_init_with_default_size (size_t d */ iotlb_virt_start = alloc_bootmem_low_pages(bytes); if (!iotlb_virt_start) - panic("Cannot allocate SWIOTLB buffer!\n" - "Use dom0_mem Xen boot parameter to reserve\n" - "some DMA memory (e.g., dom0_mem=-128M).\n"); - + panic("Cannot allocate SWIOTLB buffer!\n"); + + dma_bits = get_order(IO_TLB_SEGSIZE << IO_TLB_SHIFT) + PAGE_SHIFT; for (i = 0; i < iotlb_nslabs; i += IO_TLB_SEGSIZE) { - int rc = xen_create_contiguous_region( - (unsigned long)iotlb_virt_start + (i << IO_TLB_SHIFT), - get_order(IO_TLB_SEGSIZE << IO_TLB_SHIFT), - dma_bits); - BUG_ON(rc); + do { + rc = xen_create_contiguous_region( + (unsigned long)iotlb_virt_start + (i << IO_TLB_SHIFT), + get_order(IO_TLB_SEGSIZE << IO_TLB_SHIFT), + dma_bits); + } while (rc && dma_bits++ < max_dma_bits); + if (rc) { + if (i == 0) + panic("No suitable physical memory available for SWIOTLB buffer!\n" + "Use dom0_mem Xen boot parameter to reserve\n" + "some DMA memory (e.g., dom0_mem=-128M).\n"); + iotlb_nslabs = i; + i <<= IO_TLB_SHIFT; + free_bootmem(__pa(iotlb_virt_start + i), bytes - i); + bytes = i; + for (dma_bits = 0; i > 0; i -= IO_TLB_SEGSIZE << IO_TLB_SHIFT) { + unsigned int bits = fls64(virt_to_bus(iotlb_virt_start + i - 1)); + + if (bits > dma_bits) + dma_bits = bits; + } + break; + } } /* @@ -186,17 +202,27 @@ swiotlb_init_with_default_size (size_t d * Get the overflow emergency buffer */ io_tlb_overflow_buffer = alloc_bootmem_low(io_tlb_overflow); + if (!io_tlb_overflow_buffer) + panic("Cannot allocate SWIOTLB overflow buffer!\n"); + + do { + rc = xen_create_contiguous_region( + (unsigned long)io_tlb_overflow_buffer, + get_order(io_tlb_overflow), + dma_bits); + } while (rc && dma_bits++ < max_dma_bits); + if (rc) + panic("No suitable physical memory available for SWIOTLB overflow buffer!\n"); iotlb_pfn_start = __pa(iotlb_virt_start) >> PAGE_SHIFT; iotlb_pfn_end = iotlb_pfn_start + (bytes >> PAGE_SHIFT); printk(KERN_INFO "Software IO TLB enabled: \n" " Aperture: %lu megabytes\n" - " Kernel range: 0x%016lx - 0x%016lx\n" + " Kernel range: %p - %p\n" " Address size: %u bits\n", bytes >> 20, - (unsigned long)iotlb_virt_start, - (unsigned long)iotlb_virt_start + bytes, + iotlb_virt_start, iotlb_virt_start + bytes, dma_bits); } @@ -238,9 +264,12 @@ __sync_single(struct phys_addr buffer, c char *dev, *host, *kmp; len = size; while (len != 0) { + unsigned long flags; + if (((bytes = len) + buffer.offset) > PAGE_SIZE) bytes = PAGE_SIZE - buffer.offset; - kmp = kmap_atomic(buffer.page, KM_SWIOTLB); + local_irq_save(flags); /* protects KM_BOUNCE_READ */ + kmp = kmap_atomic(buffer.page, KM_BOUNCE_READ); dev = dma_addr + size - len; host = kmp + buffer.offset; if (dir == DMA_FROM_DEVICE) { @@ -248,7 +277,8 @@ __sync_single(struct phys_addr buffer, c /* inaccessible */; } else memcpy(dev, host, bytes); - kunmap_atomic(kmp, KM_SWIOTLB); + kunmap_atomic(kmp, KM_BOUNCE_READ); + local_irq_restore(flags); len -= bytes; buffer.page++; buffer.offset = 0; @@ -617,6 +647,8 @@ swiotlb_sync_sg_for_device(struct device sg->dma_length, dir); } +#ifdef CONFIG_HIGHMEM + dma_addr_t swiotlb_map_page(struct device *hwdev, struct page *page, unsigned long offset, size_t size, @@ -650,6 +682,8 @@ swiotlb_unmap_page(struct device *hwdev, unmap_single(hwdev, bus_to_virt(dma_address), size, direction); } +#endif + int swiotlb_dma_mapping_error(dma_addr_t dma_addr) { @@ -677,7 +711,5 @@ EXPORT_SYMBOL(swiotlb_sync_single_for_de EXPORT_SYMBOL(swiotlb_sync_single_for_device); EXPORT_SYMBOL(swiotlb_sync_sg_for_cpu); EXPORT_SYMBOL(swiotlb_sync_sg_for_device); -EXPORT_SYMBOL(swiotlb_map_page); -EXPORT_SYMBOL(swiotlb_unmap_page); EXPORT_SYMBOL(swiotlb_dma_mapping_error); EXPORT_SYMBOL(swiotlb_dma_supported); diff -r c6b683ba68f5 -r a2b2b2a011f1 linux-2.6-xen-sparse/arch/i386/mm/fault-xen.c --- a/linux-2.6-xen-sparse/arch/i386/mm/fault-xen.c Sun Jan 14 22:18:38 2007 -0700 +++ b/linux-2.6-xen-sparse/arch/i386/mm/fault-xen.c Mon Jan 15 15:15:26 2007 -0700 @@ -225,7 +225,7 @@ static void dump_fault_path(unsigned lon p += (address >> 30) * 2; printk(KERN_ALERT "%08lx -> *pde = %08lx:%08lx\n", page, p[1], p[0]); if (p[0] & 1) { - mfn = (p[0] >> PAGE_SHIFT) | ((p[1] & 0x7) << 20); + mfn = (p[0] >> PAGE_SHIFT) | (p[1] << 20); page = mfn_to_pfn(mfn) << PAGE_SHIFT; p = (unsigned long *)__va(page); address &= 0x3fffffff; @@ -234,7 +234,7 @@ static void dump_fault_path(unsigned lon page, p[1], p[0]); #ifndef CONFIG_HIGHPTE if (p[0] & 1) { - mfn = (p[0] >> PAGE_SHIFT) | ((p[1] & 0x7) << 20); + mfn = (p[0] >> PAGE_SHIFT) | (p[1] << 20); page = mfn_to_pfn(mfn) << PAGE_SHIFT; p = (unsigned long *) __va(page); address &= 0x001fffff; diff -r c6b683ba68f5 -r a2b2b2a011f1 linux-2.6-xen-sparse/arch/i386/mm/highmem-xen.c --- a/linux-2.6-xen-sparse/arch/i386/mm/highmem-xen.c Sun Jan 14 22:18:38 2007 -0700 +++ b/linux-2.6-xen-sparse/arch/i386/mm/highmem-xen.c Mon Jan 15 15:15:26 2007 -0700 @@ -129,5 +129,6 @@ EXPORT_SYMBOL(kmap); EXPORT_SYMBOL(kmap); EXPORT_SYMBOL(kunmap); EXPORT_SYMBOL(kmap_atomic); +EXPORT_SYMBOL(kmap_atomic_pte); EXPORT_SYMBOL(kunmap_atomic); EXPORT_SYMBOL(kmap_atomic_to_page); diff -r c6b683ba68f5 -r a2b2b2a011f1 linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c --- a/linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c Sun Jan 14 22:18:38 2007 -0700 +++ b/linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c Mon Jan 15 15:15:26 2007 -0700 @@ -238,23 +238,41 @@ struct page *pte_alloc_one(struct mm_str #ifdef CONFIG_HIGHPTE pte = alloc_pages(GFP_KERNEL|__GFP_HIGHMEM|__GFP_REPEAT|__GFP_ZERO, 0); + if (pte && PageHighMem(pte)) { + struct mmuext_op op; + + kmap_flush_unused(); + op.cmd = MMUEXT_PIN_L1_TABLE; + op.arg1.mfn = pfn_to_mfn(page_to_pfn(pte)); + BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0); + } #else pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0); +#endif if (pte) { SetPageForeign(pte, pte_free); set_page_count(pte, 1); } -#endif return pte; } void pte_free(struct page *pte) { - unsigned long va = (unsigned long)__va(page_to_pfn(pte)<<PAGE_SHIFT); - - if (!pte_write(*virt_to_ptep(va))) - BUG_ON(HYPERVISOR_update_va_mapping( - va, pfn_pte(page_to_pfn(pte), PAGE_KERNEL), 0)); + unsigned long pfn = page_to_pfn(pte); + + if (!PageHighMem(pte)) { + unsigned long va = (unsigned long)__va(pfn << PAGE_SHIFT); + + if (!pte_write(*virt_to_ptep(va))) + BUG_ON(HYPERVISOR_update_va_mapping( + va, pfn_pte(pfn, PAGE_KERNEL), 0)); + } else { + struct mmuext_op op; + + op.cmd = MMUEXT_UNPIN_TABLE; + op.arg1.mfn = pfn_to_mfn(pfn); + BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0); + } ClearPageForeign(pte); set_page_count(pte, 1); diff -r c6b683ba68f5 -r a2b2b2a011f1 linux-2.6-xen-sparse/arch/x86_64/mm/pageattr-xen.c --- a/linux-2.6-xen-sparse/arch/x86_64/mm/pageattr-xen.c Sun Jan 14 22:18:38 2007 -0700 +++ b/linux-2.6-xen-sparse/arch/x86_64/mm/pageattr-xen.c Mon Jan 15 15:15:26 2007 -0700 @@ -164,6 +164,18 @@ void _arch_exit_mmap(struct mm_struct *m mm_unpin(mm); } +struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address) +{ + struct page *pte; + + pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0); + if (pte) { + SetPageForeign(pte, pte_free); + set_page_count(pte, 1); + } + return pte; +} + void pte_free(struct page *pte) { unsigned long va = (unsigned long)__va(page_to_pfn(pte)<<PAGE_SHIFT); @@ -171,6 +183,10 @@ void pte_free(struct page *pte) if (!pte_write(*virt_to_ptep(va))) BUG_ON(HYPERVISOR_update_va_mapping( va, pfn_pte(page_to_pfn(pte), PAGE_KERNEL), 0)); + + ClearPageForeign(pte); + set_page_count(pte, 1); + __free_page(pte); } #endif /* CONFIG_XEN */ diff -r c6b683ba68f5 -r a2b2b2a011f1 linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c --- a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c Sun Jan 14 22:18:38 2007 -0700 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c Mon Jan 15 15:15:26 2007 -0700 @@ -42,9 +42,30 @@ static void backend_changed(struct xenbu static void backend_changed(struct xenbus_watch *, const char **, unsigned int); +static int blkback_name(blkif_t *blkif, char *buf) +{ + char *devpath, *devname; + struct xenbus_device *dev = blkif->be->dev; + + devpath = xenbus_read(XBT_NIL, dev->nodename, "dev", NULL); + if (IS_ERR(devpath)) + return PTR_ERR(devpath); + + if ((devname = strstr(devpath, "/dev/")) != NULL) + devname += strlen("/dev/"); + else + devname = devpath; + + snprintf(buf, TASK_COMM_LEN, "blkback.%d.%s", blkif->domid, devname); + kfree(devpath); + + return 0; +} + static void update_blkif_status(blkif_t *blkif) { int err; + char name[TASK_COMM_LEN]; /* Not ready to connect? */ if (!blkif->irq || !blkif->vbd.bdev) @@ -59,10 +80,13 @@ static void update_blkif_status(blkif_t if (blkif->be->dev->state != XenbusStateConnected) return; - blkif->xenblkd = kthread_run(blkif_schedule, blkif, - "xvd %d %02x:%02x", - blkif->domid, - blkif->be->major, blkif->be->minor); + err = blkback_name(blkif, name); + if (err) { + xenbus_dev_error(blkif->be->dev, err, "get blkback dev name"); + return; + } + + blkif->xenblkd = kthread_run(blkif_schedule, blkif, name); if (IS_ERR(blkif->xenblkd)) { err = PTR_ERR(blkif->xenblkd); blkif->xenblkd = NULL; diff -r c6b683ba68f5 -r a2b2b2a011f1 linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c --- a/linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c Sun Jan 14 22:18:38 2007 -0700 +++ b/linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c Mon Jan 15 15:15:26 2007 -0700 @@ -92,9 +92,30 @@ static long get_id(const char *str) return simple_strtol(num, NULL, 10); } +static int blktap_name(blkif_t *blkif, char *buf) +{ + char *devpath, *devname; + struct xenbus_device *dev = blkif->be->dev; + + devpath = xenbus_read(XBT_NIL, dev->nodename, "dev", NULL); + if (IS_ERR(devpath)) + return PTR_ERR(devpath); + + if ((devname = strstr(devpath, "/dev/")) != NULL) + devname += strlen("/dev/"); + else + devname = devpath; + + snprintf(buf, TASK_COMM_LEN, "blktap.%d.%s", blkif->domid, devname); + kfree(devpath); + + return 0; +} + static void tap_update_blkif_status(blkif_t *blkif) { int err; + char name[TASK_COMM_LEN]; /* Not ready to connect? */ if(!blkif->irq || !blkif->sectors) { @@ -110,10 +131,13 @@ static void tap_update_blkif_status(blki if (blkif->be->dev->state != XenbusStateConnected) return; - blkif->xenblkd = kthread_run(tap_blkif_schedule, blkif, - "xvd %d", - blkif->domid); - + err = blktap_name(blkif, name); + if (err) { + xenbus_dev_error(blkif->be->dev, err, "get blktap dev name"); + return; + } + + blkif->xenblkd = kthread_run(tap_blkif_schedule, blkif, name); if (IS_ERR(blkif->xenblkd)) { err = PTR_ERR(blkif->xenblkd); blkif->xenblkd = NULL; diff -r c6b683ba68f5 -r a2b2b2a011f1 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/dma-mapping.h --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/dma-mapping.h Sun Jan 14 22:18:38 2007 -0700 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/dma-mapping.h Mon Jan 15 15:15:26 2007 -0700 @@ -53,6 +53,7 @@ extern void dma_unmap_sg(struct device * extern void dma_unmap_sg(struct device *hwdev, struct scatterlist *sg, int nents, enum dma_data_direction direction); +#ifdef CONFIG_HIGHMEM extern dma_addr_t dma_map_page(struct device *dev, struct page *page, unsigned long offset, size_t size, enum dma_data_direction direction); @@ -60,6 +61,11 @@ extern void extern void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size, enum dma_data_direction direction); +#else +#define dma_map_page(dev, page, offset, size, dir) \ + dma_map_single(dev, page_address(page) + (offset), (size), (dir)) +#define dma_unmap_page dma_unmap_single +#endif extern void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size, diff -r c6b683ba68f5 -r a2b2b2a011f1 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/kmap_types.h --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/kmap_types.h Sun Jan 14 22:18:38 2007 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,32 +0,0 @@ -#ifndef _ASM_KMAP_TYPES_H -#define _ASM_KMAP_TYPES_H - -#include <linux/config.h> - -#ifdef CONFIG_DEBUG_HIGHMEM -# define D(n) __KM_FENCE_##n , -#else -# define D(n) -#endif - -enum km_type { -D(0) KM_BOUNCE_READ, -D(1) KM_SKB_SUNRPC_DATA, -D(2) KM_SKB_DATA_SOFTIRQ, -D(3) KM_USER0, -D(4) KM_USER1, -D(5) KM_BIO_SRC_IRQ, -D(6) KM_BIO_DST_IRQ, -D(7) KM_PTE0, -D(8) KM_PTE1, -D(9) KM_IRQ0, -D(10) KM_IRQ1, -D(11) KM_SOFTIRQ0, -D(12) KM_SOFTIRQ1, -D(13) KM_SWIOTLB, -D(14) KM_TYPE_NR -}; - -#undef D - -#endif diff -r c6b683ba68f5 -r a2b2b2a011f1 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgalloc.h --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgalloc.h Sun Jan 14 22:18:38 2007 -0700 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgalloc.h Mon Jan 15 15:15:26 2007 -0700 @@ -42,7 +42,7 @@ static inline void pte_free_kernel(pte_t static inline void pte_free_kernel(pte_t *pte) { free_page((unsigned long)pte); - make_page_writable(pte, XENFEAT_writable_page_tables); + make_lowmem_page_writable(pte, XENFEAT_writable_page_tables); } extern void pte_free(struct page *pte); diff -r c6b683ba68f5 -r a2b2b2a011f1 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/swiotlb.h --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/swiotlb.h Sun Jan 14 22:18:38 2007 -0700 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/swiotlb.h Mon Jan 15 15:15:26 2007 -0700 @@ -26,15 +26,15 @@ extern void swiotlb_unmap_sg(struct devi extern void swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sg, int nents, int direction); extern int swiotlb_dma_mapping_error(dma_addr_t dma_addr); +#ifdef CONFIG_HIGHMEM extern dma_addr_t swiotlb_map_page(struct device *hwdev, struct page *page, unsigned long offset, size_t size, enum dma_data_direction direction); extern void swiotlb_unmap_page(struct device *hwdev, dma_addr_t dma_address, size_t size, enum dma_data_direction direction); +#endif extern int swiotlb_dma_supported(struct device *hwdev, u64 mask); extern void swiotlb_init(void); - -extern unsigned int dma_bits; #ifdef CONFIG_SWIOTLB extern int swiotlb; diff -r c6b683ba68f5 -r a2b2b2a011f1 linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/pgalloc.h --- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/pgalloc.h Sun Jan 14 22:18:38 2007 -0700 +++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/pgalloc.h Mon Jan 15 15:15:26 2007 -0700 @@ -64,50 +64,43 @@ static inline void pgd_populate(struct m } } -static inline void pmd_free(pmd_t *pmd) -{ - pte_t *ptep = virt_to_ptep(pmd); - - if (!pte_write(*ptep)) { - BUG_ON(HYPERVISOR_update_va_mapping( - (unsigned long)pmd, - pfn_pte(virt_to_phys(pmd)>>PAGE_SHIFT, PAGE_KERNEL), - 0)); - } - free_page((unsigned long)pmd); -} +extern struct page *pte_alloc_one(struct mm_struct *mm, unsigned long addr); +extern void pte_free(struct page *pte); static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr) { - pmd_t *pmd = (pmd_t *) get_zeroed_page(GFP_KERNEL|__GFP_REPEAT); - return pmd; + struct page *pg; + + pg = pte_alloc_one(mm, addr); + return pg ? page_address(pg) : NULL; +} + +static inline void pmd_free(pmd_t *pmd) +{ + BUG_ON((unsigned long)pmd & (PAGE_SIZE-1)); + pte_free(virt_to_page(pmd)); } static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr) { - pud_t *pud = (pud_t *) get_zeroed_page(GFP_KERNEL|__GFP_REPEAT); - return pud; + struct page *pg; + + pg = pte_alloc_one(mm, addr); + return pg ? page_address(pg) : NULL; } static inline void pud_free(pud_t *pud) { - pte_t *ptep = virt_to_ptep(pud); - - if (!pte_write(*ptep)) { - BUG_ON(HYPERVISOR_update_va_mapping( - (unsigned long)pud, - pfn_pte(virt_to_phys(pud)>>PAGE_SHIFT, PAGE_KERNEL), - 0)); - } - free_page((unsigned long)pud); + BUG_ON((unsigned long)pud & (PAGE_SIZE-1)); + pte_free(virt_to_page(pud)); } static inline pgd_t *pgd_alloc(struct mm_struct *mm) { - /* - * We allocate two contiguous pages for kernel and user. - */ - unsigned boundary; + /* + * We allocate two contiguous pages for kernel and user. + */ + unsigned boundary; pgd_t *pgd = (pgd_t *)__get_free_pages(GFP_KERNEL|__GFP_REPEAT, 1); if (!pgd) @@ -124,11 +117,11 @@ static inline pgd_t *pgd_alloc(struct mm (PTRS_PER_PGD - boundary) * sizeof(pgd_t)); memset(__user_pgd(pgd), 0, PAGE_SIZE); /* clean up user pgd */ - /* - * Set level3_user_pgt for vsyscall area - */ + /* + * Set level3_user_pgt for vsyscall area + */ set_pgd(__user_pgd(pgd) + pgd_index(VSYSCALL_START), - mk_kernel_pgd(__pa_symbol(level3_user_pgt))); + mk_kernel_pgd(__pa_symbol(level3_user_pgt))); return pgd; } @@ -160,18 +153,10 @@ static inline void pgd_free(pgd_t *pgd) static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address) { - pte_t *pte = (pte_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT); - if (pte) + pte_t *pte = (pte_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT); + if (pte) make_page_readonly(pte, XENFEAT_writable_page_tables); - return pte; -} - -static inline struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address) -{ - struct page *pte; - - pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0); return pte; } @@ -181,18 +166,12 @@ static inline void pte_free_kernel(pte_t static inline void pte_free_kernel(pte_t *pte) { BUG_ON((unsigned long)pte & (PAGE_SIZE-1)); - make_page_writable(pte, XENFEAT_writable_page_tables); + make_page_writable(pte, XENFEAT_writable_page_tables); free_page((unsigned long)pte); } -extern void pte_free(struct page *pte); - -//#define __pte_free_tlb(tlb,pte) tlb_remove_page((tlb),(pte)) -//#define __pmd_free_tlb(tlb,x) tlb_remove_page((tlb),virt_to_page(x)) -//#define __pud_free_tlb(tlb,x) tlb_remove_page((tlb),virt_to_page(x)) - -#define __pte_free_tlb(tlb,x) pte_free((x)) -#define __pmd_free_tlb(tlb,x) pmd_free((x)) -#define __pud_free_tlb(tlb,x) pud_free((x)) +#define __pte_free_tlb(tlb,pte) tlb_remove_page((tlb),(pte)) +#define __pmd_free_tlb(tlb,x) tlb_remove_page((tlb),virt_to_page(x)) +#define __pud_free_tlb(tlb,x) tlb_remove_page((tlb),virt_to_page(x)) #endif /* _X86_64_PGALLOC_H */ diff -r c6b683ba68f5 -r a2b2b2a011f1 patches/linux-2.6.16.33/ipv6-no-autoconf.patch --- a/patches/linux-2.6.16.33/ipv6-no-autoconf.patch Sun Jan 14 22:18:38 2007 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,19 +0,0 @@ -diff -pruN ../orig-linux-2.6.16.29/net/ipv6/addrconf.c ./net/ipv6/addrconf.c ---- ../orig-linux-2.6.16.29/net/ipv6/addrconf.c 2006-09-12 19:02:10.000000000 +0100 -+++ ./net/ipv6/addrconf.c 2006-09-19 13:59:11.000000000 +0100 -@@ -2471,6 +2471,7 @@ static void addrconf_dad_start(struct in - spin_lock_bh(&ifp->lock); - - if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) || -+ !(dev->flags&IFF_MULTICAST) || - !(ifp->flags&IFA_F_TENTATIVE)) { - ifp->flags &= ~IFA_F_TENTATIVE; - spin_unlock_bh(&ifp->lock); -@@ -2555,6 +2556,7 @@ static void addrconf_dad_completed(struc - if (ifp->idev->cnf.forwarding == 0 && - ifp->idev->cnf.rtr_solicits > 0 && - (dev->flags&IFF_LOOPBACK) == 0 && -+ (dev->flags & IFF_MULTICAST) && - (ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL)) { - struct in6_addr all_routers; - diff -r c6b683ba68f5 -r a2b2b2a011f1 patches/linux-2.6.16.33/series --- a/patches/linux-2.6.16.33/series Sun Jan 14 22:18:38 2007 -0700 +++ b/patches/linux-2.6.16.33/series Mon Jan 15 15:15:26 2007 -0700 @@ -9,7 +9,6 @@ fix-hz-suspend.patch fix-hz-suspend.patch fix-ide-cd-pio-mode.patch i386-mach-io-check-nmi.patch -ipv6-no-autoconf.patch net-csum.patch net-gso-0-base.patch net-gso-1-check-dodgy.patch diff -r c6b683ba68f5 -r a2b2b2a011f1 tools/check/check_udev --- a/tools/check/check_udev Sun Jan 14 22:18:38 2007 -0700 +++ b/tools/check/check_udev Mon Jan 15 15:15:26 2007 -0700 @@ -11,7 +11,7 @@ Linux) Linux) TOOL="udevinfo" UDEV_VERSION="0" - test -x "$(which ${TOOL})" && \ + test -x "$(which ${TOOL} 2>/dev/null)" && \ UDEV_VERSION=$(${TOOL} -V | sed -e 's/^[^0-9]* \([0-9]\{1,\}\)[^0-9]\{0,\}/\1/') if test "${UDEV_VERSION}" -ge 059; then RC=0 @@ -28,7 +28,7 @@ esac if test ${RC} -ne 0; then echo - echo ' *** Check for ${TOOL} FAILED' + echo " *** Check for ${TOOL} FAILED" fi exit ${RC} diff -r c6b683ba68f5 -r a2b2b2a011f1 tools/examples/vtpm-common.sh --- a/tools/examples/vtpm-common.sh Sun Jan 14 22:18:38 2007 -0700 +++ b/tools/examples/vtpm-common.sh Mon Jan 15 15:15:26 2007 -0700 @@ -24,7 +24,9 @@ VTPMDB="/etc/xen/vtpm.db" #In the vtpm-impl file some commands should be defined: # vtpm_create, vtpm_setup, vtpm_start, etc. (see below) -if [ -r "$dir/vtpm-impl" ]; then +if [ -r "$dir/vtpm-impl.alt" ]; then + . "$dir/vtpm-impl.alt" +elif [ -r "$dir/vtpm-impl" ]; then . "$dir/vtpm-impl" else function vtpm_create () { diff -r c6b683ba68f5 -r a2b2b2a011f1 tools/examples/xen-network-common.sh --- a/tools/examples/xen-network-common.sh Sun Jan 14 22:18:38 2007 -0700 +++ b/tools/examples/xen-network-common.sh Mon Jan 15 15:15:26 2007 -0700 @@ -117,7 +117,12 @@ create_bridge () { ip link set ${bridge} arp off ip link set ${bridge} multicast off fi + + # A small MTU disables IPv6 (and therefore IPv6 addrconf). + mtu=$(ip link show ${bridge} | sed -n 's/.* mtu \([0-9]\+\).*/\1/p') + ip link set ${bridge} mtu 68 ip link set ${bridge} up + ip link set ${bridge} mtu ${mtu:-1500} } # Usage: add_to_bridge bridge dev diff -r c6b683ba68f5 -r a2b2b2a011f1 tools/examples/xmexample1 --- a/tools/examples/xmexample1 Sun Jan 14 22:18:38 2007 -0700 +++ b/tools/examples/xmexample1 Mon Jan 15 15:15:26 2007 -0700 @@ -64,6 +64,40 @@ vif = [ '' ] # and MODE is r for read-only, w for read-write. disk = [ 'phy:hda1,hda1,w' ] + +#---------------------------------------------------------------------------- +# Define frame buffer device. +# +# By default, no frame buffer device is configured. +# +# To create one using the SDL backend and sensible defaults: +# +# vfb = [ 'type=sdl' ] +# +# This uses environment variables XAUTHORITY and DISPLAY. You +# can override that: +# +# vfb = [ 'type=sdl,xauthority=/home/bozo/.Xauthority,display=:1' ] +# +# To create one using the VNC backend and sensible defaults: +# +# vfb = [ 'type=vnc' ] +# +# The backend listens on 127.0.0.1 port 5900+N by default, where N is +# the domain ID. You can override both address and N: +# +# vfb = [ 'type=vnc,vnclisten=127.0.0.1,vncdisplay=1' ] +# +# Or you can bind the first unused port above 5900: +# +# vfb = [ 'type=vnc,vnclisten=0.0.0.0,vnunused=1' ] +# +# You can override the password: +# +# vfb = [ 'type=vnc,vncpasswd=MYPASSWD' ] +# +# Empty password disables authentication. Defaults to the vncpasswd +# configured in xend-config.sxp. #---------------------------------------------------------------------------- # Define to which TPM instance the user domain should communicate. diff -r c6b683ba68f5 -r a2b2b2a011f1 tools/examples/xmexample2 --- a/tools/examples/xmexample2 Sun Jan 14 22:18:38 2007 -0700 +++ b/tools/examples/xmexample2 Mon Jan 15 15:15:26 2007 -0700 @@ -100,6 +100,40 @@ vif = [ '' ] # All domains get sda6 read-only (to use for /usr, see below). disk = [ 'phy:sda%d,sda1,w' % (7+vmid), 'phy:sda6,sda6,r' ] + +#---------------------------------------------------------------------------- +# Define frame buffer device. +# +# By default, no frame buffer device is configured. +# +# To create one using the SDL backend and sensible defaults: +# +# vfb = [ 'type=sdl' ] +# +# This uses environment variables XAUTHORITY and DISPLAY. You +# can override that: +# +# vfb = [ 'type=sdl,xauthority=/home/bozo/.Xauthority,display=:1' ] +# +# To create one using the VNC backend and sensible defaults: +# +# vfb = [ 'type=vnc' ] +# +# The backend listens on 127.0.0.1 port 5900+N by default, where N is +# the domain ID. You can override both address and N: +# +# vfb = [ 'type=vnc,vnclisten=127.0.0.1,vncdisplay=%d' % vmid ] +# +# Or you can bind the first unused port above 5900: +# +# vfb = [ 'type=vnc,vnclisten=0.0.0.0,vnunused=1' ] +# +# You can override the password: +# +# vfb = [ 'type=vnc,vncpasswd=MYPASSWD' ] +# +# Empty password disables authentication. Defaults to the vncpasswd +# configured in xend-config.sxp. #---------------------------------------------------------------------------- # Define to which TPM instance the user domain should communicate. diff -r c6b683ba68f5 -r a2b2b2a011f1 tools/examples/xmexample3 --- a/tools/examples/xmexample3 Sun Jan 14 22:18:38 2007 -0700 +++ b/tools/examples/xmexample3 Mon Jan 15 15:15:26 2007 -0700 @@ -85,6 +85,40 @@ vif = [ 'ip=192.168.%d.1/24' % (vmid)] # to all domains as sda1. # All domains get sda6 read-only (to use for /usr, see below). disk = [ 'phy:hda%d,hda1,w' % (vmid)] + +#---------------------------------------------------------------------------- +# Define frame buffer device. +# +# By default, no frame buffer device is configured. +# +# To create one using the SDL backend and sensible defaults: +# +# vfb = [ 'type=sdl' ] +# +# This uses environment variables XAUTHORITY and DISPLAY. You +# can override that: +# +# vfb = [ 'type=sdl,xauthority=/home/bozo/.Xauthority,display=:1' ] +# +# To create one using the VNC backend and sensible defaults: +# +# vfb = [ 'type=vnc' ] +# +# The backend listens on 127.0.0.1 port 5900+N by default, where N is +# the domain ID. You can override both address and N: +# +# vfb = [ 'type=vnc,vnclisten=127.0.0.1,vncdisplay=%d' % vmid ] +# +# Or you can bind the first unused port above 5900: +# +# vfb = [ 'type=vnc,vnclisten=0.0.0.0,vnunused=1' ] +# +# You can override the password: +# +# vfb = [ 'type=vnc,vncpasswd=MYPASSWD' ] +# +# Empty password disables authentication. Defaults to the vncpasswd +# configured in xend-config.sxp. #---------------------------------------------------------------------------- # Define to which TPM instance the user domain should communicate. diff -r c6b683ba68f5 -r a2b2b2a011f1 tools/libxc/xc_load_elf.c --- a/tools/libxc/xc_load_elf.c Sun Jan 14 22:18:38 2007 -0700 +++ b/tools/libxc/xc_load_elf.c Mon Jan 15 15:15:26 2007 -0700 @@ -406,17 +406,19 @@ static int parseelfimage(const char *ima } /* - * A "bimodal" ELF note indicates the kernel will adjust to the - * current paging mode, including handling extended cr3 syntax. - * If we have ELF notes then PAE=yes implies that we must support - * the extended cr3 syntax. Otherwise we need to find the - * [extended-cr3] syntax in the __xen_guest string. + * A "bimodal" ELF note indicates the kernel will adjust to the current + * paging mode, including handling extended cr3 syntax. If we have ELF + * notes then PAE=yes implies that we must support the extended cr3 syntax. + * Otherwise we need to find the [extended-cr3] syntax in the __xen_guest + * string. We use strstr() to look for "bimodal" to allow guests to use + * "yes,bimodal" or "no,bimodal" for compatibility reasons. */ + dsi->pae_kernel = PAEKERN_no; if ( dsi->__elfnote_section ) { p = xen_elfnote_string(dsi, XEN_ELFNOTE_PAE_MODE); - if ( p != NULL && strncmp(p, "bimodal", 7) == 0 ) + if ( p != NULL && strstr(p, "bimodal") != NULL ) dsi->pae_kernel = PAEKERN_bimodal; else if ( p != NULL && strncmp(p, "yes", 3) == 0 ) dsi->pae_kernel = PAEKERN_extended_cr3; diff -r c6b683ba68f5 -r a2b2b2a011f1 tools/libxc/xc_ptrace.c --- a/tools/libxc/xc_ptrace.c Sun Jan 14 22:18:38 2007 -0700 +++ b/tools/libxc/xc_ptrace.c Mon Jan 15 15:15:26 2007 -0700 @@ -166,14 +166,11 @@ static unsigned long *page_arr * tables. * */ -static unsigned long -to_ma(int cpu, - unsigned long in_addr) -{ - unsigned long maddr = in_addr; - +static uint64_t +to_ma(int cpu, uint64_t maddr) +{ if ( current_is_hvm && paging_enabled(&ctxt[cpu]) ) - maddr = page_array[maddr >> PAGE_SHIFT] << PAGE_SHIFT; + maddr = (uint64_t)page_array[maddr >> PAGE_SHIFT] << PAGE_SHIFT; return maddr; } @@ -225,7 +222,8 @@ map_domain_va_pae( void *guest_va, int perm) { - unsigned long l3e, l2e, l1e, l2p, l1p, p, va = (unsigned long)guest_va; + uint64_t l3e, l2e, l1e, l2p, l1p, p; + unsigned long va = (unsigned long)guest_va; uint64_t *l3, *l2, *l1; static void *v[MAX_VIRT_CPUS]; @@ -380,12 +378,12 @@ map_domain_va( if (!paging_enabled(&ctxt[cpu])) { static void * v; - unsigned long page; + uint64_t page; if ( v != NULL ) munmap(v, PAGE_SIZE); - page = to_ma(cpu, page_array[va >> PAGE_SHIFT]); + page = to_ma(cpu, va); v = xc_map_foreign_range( xc_handle, current_domid, PAGE_SIZE, perm, page >> PAGE_SHIFT); diff -r c6b683ba68f5 -r a2b2b2a011f1 tools/pygrub/src/pygrub --- a/tools/pygrub/src/pygrub Sun Jan 14 22:18:38 2007 -0700 +++ b/tools/pygrub/src/pygrub Mon Jan 15 15:15:26 2007 -0700 @@ -48,8 +48,7 @@ def is_disk_image(file): return True return False -SECTOR_SIZE=512 -def get_active_offset(file): +def get_active_partition(file): """Find the offset for the start of the first active partition " "in the disk image file.""" @@ -58,22 +57,56 @@ def get_active_offset(file): for poff in (446, 462, 478, 494): # partition offsets # active partition has 0x80 as the first byte if struct.unpack("<c", buf[poff:poff+1]) == ('\x80',): - return struct.unpack("<L", - buf[poff+8:poff+12])[0] * SECTOR_SIZE + return buf[poff:poff+16] # if there's not a partition marked as active, fall back to # the first partition - P1 = 446 - return struct.unpack("<L", buf[P1+8:P1+12])[0] * SECTOR_SIZE - -def open_fs(file): - offset = 0 - if is_disk_image(file): - offset = get_active_offset(file) - if offset == -1: - raise RuntimeError, "Unable to find active partition on disk" - - return fsimage.open(file, offset) + return buf[446:446+16] + +SECTOR_SIZE=512 +DK_LABEL_LOC=1 +DKL_MAGIC=0xdabe +V_ROOT=0x2 + +def get_solaris_slice(file, offset): + """Find the root slice in a Solaris VTOC.""" + + fd = os.open(file, os.O_RDONLY) + os.lseek(fd, offset + (DK_LABEL_LOC * SECTOR_SIZE), 0) + buf = os.read(fd, 512) + if struct.unpack("<H", buf[508:510])[0] != DKL_MAGIC: + raise RuntimeError, "Invalid disklabel magic" + + nslices = struct.unpack("<H", buf[30:32])[0] + + for i in range(nslices): + sliceoff = 72 + 12 * i + slicetag = struct.unpack("<H", buf[sliceoff:sliceoff+2])[0] + slicesect = struct.unpack("<L", buf[sliceoff+4:sliceoff+8])[0] + if slicetag == V_ROOT: + return slicesect * SECTOR_SIZE + + raise RuntimeError, "No root slice found" + +FDISK_PART_SOLARIS=0xbf +FDISK_PART_SOLARIS_OLD=0x82 + +def get_fs_offset(file): + if not is_disk_image(file): + return 0 + + partbuf = get_active_partition(file) + if len(partbuf) == 0: + raise RuntimeError, "Unable to find active partition on disk" + + offset = struct.unpack("<L", partbuf[8:12])[0] * SECTOR_SIZE + + type = struct.unpack("<B", partbuf[4:5])[0] + + if type == FDISK_PART_SOLARIS or type == FDISK_PART_SOLARIS_OLD: + offset += get_solaris_slice(file, offset) + + return offset class GrubLineEditor(curses.textpad.Textbox): def __init__(self, screen, startx, starty, line = ""): @@ -571,7 +604,7 @@ if __name__ == "__main__": print " args: %s" % chosencfg["args"] sys.exit(0) - fs = open_fs(file) + fs = fsimage.open(file, get_fs_offset(file)) chosencfg = sniff_solaris(fs, incfg) diff -r c6b683ba68f5 -r a2b2b2a011f1 tools/python/xen/xend/XendConfig.py --- a/tools/python/xen/xend/XendConfig.py Sun Jan 14 22:18:38 2007 -0700 +++ b/tools/python/xen/xend/XendConfig.py Mon Jan 15 15:15:26 2007 -0700 @@ -1020,10 +1020,11 @@ class XendConfig(dict): @return: Returns True if succesfully found and updated a device conf """ if dev_uuid in self['devices']: - config = sxp.child0(cfg_sxp) - dev_type = sxp.name(config) - dev_info = {} - + if sxp.child0(cfg_sxp) == 'device': + config = sxp.child0(cfg_sxp) + else: + config = cfg_sxp + for opt_val in config[1:]: try: opt, val = opt_val diff -r c6b683ba68f5 -r a2b2b2a011f1 tools/python/xen/xend/XendDomainInfo.py --- a/tools/python/xen/xend/XendDomainInfo.py Sun Jan 14 22:18:38 2007 -0700 +++ b/tools/python/xen/xend/XendDomainInfo.py Mon Jan 15 15:15:26 2007 -0700 @@ -496,7 +496,7 @@ class XendDomainInfo: self._waitForDevice(dev_type, devid) return self.getDeviceController(dev_type).sxpr(devid) - def device_configure(self, dev_config, devid = None): + def device_configure(self, dev_sxp, devid = None): """Configure an existing device. @param dev_config: device configuration @@ -506,19 +506,24 @@ class XendDomainInfo: @return: Returns True if successfully updated device @rtype: boolean """ - deviceClass = sxp.name(dev_config) - - # look up uuid of the device - dev_control = self.getDeviceController(deviceClass) - dev_sxpr = dev_control.sxpr(devid) - dev_uuid = sxp.child_value(dev_sxpr, 'uuid') - if not dev_uuid: - return False - - self.info.device_update(dev_uuid, dev_config) - dev_config_dict = self.info['devices'].get(dev_uuid) - if dev_config_dict: - dev_control.reconfigureDevice(devid, dev_config_dict[1]) + + # convert device sxp to a dict + dev_class = sxp.name(dev_sxp) + dev_config = {} + for opt_val in dev_sxp[1:]: + try: + dev_config[opt_val[0]] = opt_val[1] + except IndexError: + pass + + # use DevController.reconfigureDevice to change device config + dev_control = self.getDeviceController(dev_class) + dev_uuid = dev_control.reconfigureDevice(devid, dev_config) + + # update XendConfig with new device info + if dev_uuid: + self.info.device_update(dev_uuid, dev_sxp) + return True def waitForDevices(self): diff -r c6b683ba68f5 -r a2b2b2a011f1 tools/python/xen/xend/server/blkif.py --- a/tools/python/xen/xend/server/blkif.py Sun Jan 14 22:18:38 2007 -0700 +++ b/tools/python/xen/xend/server/blkif.py Mon Jan 15 15:15:26 2007 -0700 @@ -101,6 +101,7 @@ class BlkifController(DevController): self.writeBackend(devid, 'type', new_back['type'], 'params', new_back['params']) + return new_back.get('uuid') else: raise VmError('Refusing to reconfigure device %s:%d to %s' % (self.deviceClass, devid, config)) diff -r c6b683ba68f5 -r a2b2b2a011f1 tools/python/xen/xm/create.py --- a/tools/python/xen/xm/create.py Sun Jan 14 22:18:38 2007 -0700 +++ b/tools/python/xen/xm/create.py Mon Jan 15 15:15:26 2007 -0700 @@ -292,7 +292,8 @@ gopts.var('vfb', val="type={vnc,sdl},vnc For type=vnc, connect an external vncviewer. The server will listen on ADDR (default 127.0.0.1) on port N+5900. N defaults to the domain id. If vncunused=1, the server will try to find an arbitrary - unused port above 5900. + unused port above 5900. vncpasswd overrides the XenD configured + default password. For type=sdl, a viewer will be started automatically using the given DISPLAY and XAUTHORITY, which default to the current user's ones.""") diff -r c6b683ba68f5 -r a2b2b2a011f1 tools/tests/Makefile --- a/tools/tests/Makefile Sun Jan 14 22:18:38 2007 -0700 +++ b/tools/tests/Makefile Mon Jan 15 15:15:26 2007 -0700 @@ -7,12 +7,21 @@ TARGET := test_x86_emulator .PHONY: all all: $(TARGET) +.PHONY: blowfish.bin +blowfish.bin: + make -f blowfish.mk all + +blowfish.h: blowfish.bin + (echo "static unsigned int blowfish_code[] = {"; \ + od -v -t x $< | sed 's/^[0-9]* /0x/' | sed 's/ /, 0x/g' | sed 's/$$/,/';\ + echo "};") >$@ + $(TARGET): x86_emulate.o test_x86_emulator.o $(HOSTCC) -o $@ $^ .PHONY: clean clean: - rm -rf $(TARGET) *.o *~ core + rm -rf $(TARGET) *.o *~ core blowfish.h blowfish.bin .PHONY: install install: @@ -20,5 +29,5 @@ x86_emulate.o: $(XEN_ROOT)/xen/arch/x86/ x86_emulate.o: $(XEN_ROOT)/xen/arch/x86/x86_emulate.c $(HOSTCC) $(HOSTCFLAGS) -I$(XEN_ROOT)/xen/include -c -o $@ $< -%.o: %.c +test_x86_emulator.o: test_x86_emulator.c blowfish.h $(HOSTCC) $(HOSTCFLAGS) -I$(XEN_ROOT)/xen/include -c -o $@ $< diff -r c6b683ba68f5 -r a2b2b2a011f1 tools/tests/blowfish.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/tests/blowfish.c Mon Jan 15 15:15:26 2007 -0700 @@ -0,0 +1,439 @@ +/* +blowfish.c: C implementation of the Blowfish algorithm. + +Copyright (C) 1997 by Paul Kocher + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) +#define __attribute_used__ __attribute__((__used__)) +#else +#define __attribute_used__ __attribute__((__unused__)) +#endif + +static unsigned long long blowfish_test(unsigned long long input) + __attribute_used__; + +asm ( + ".globl _start\n" + "_start:\n" + "push %edx; push %eax; " + "call blowfish_test; " + "addl $8,%esp; " + "ret" + ); + +typedef struct { + unsigned long P[16 + 2]; + unsigned long S[4][256]; +} BLOWFISH_CTX; + +#define N 16 + +static const unsigned long ORIG_P[16 + 2] = { + 0x243F6A88L, 0x85A308D3L, 0x13198A2EL, 0x03707344L, + 0xA4093822L, 0x299F31D0L, 0x082EFA98L, 0xEC4E6C89L, + 0x452821E6L, 0x38D01377L, 0xBE5466CFL, 0x34E90C6CL, + 0xC0AC29B7L, 0xC97C50DDL, 0x3F84D5B5L, 0xB5470917L, + 0x9216D5D9L, 0x8979FB1BL +}; + +static const unsigned long ORIG_S[4][256] = { + { 0xD1310BA6L, 0x98DFB5ACL, 0x2FFD72DBL, 0xD01ADFB7L, + 0xB8E1AFEDL, 0x6A267E96L, 0xBA7C9045L, 0xF12C7F99L, + 0x24A19947L, 0xB3916CF7L, 0x0801F2E2L, 0x858EFC16L, + 0x636920D8L, 0x71574E69L, 0xA458FEA3L, 0xF4933D7EL, + 0x0D95748FL, 0x728EB658L, 0x718BCD58L, 0x82154AEEL, + 0x7B54A41DL, 0xC25A59B5L, 0x9C30D539L, 0x2AF26013L, + 0xC5D1B023L, 0x286085F0L, 0xCA417918L, 0xB8DB38EFL, + 0x8E79DCB0L, 0x603A180EL, 0x6C9E0E8BL, 0xB01E8A3EL, + 0xD71577C1L, 0xBD314B27L, 0x78AF2FDAL, 0x55605C60L, + 0xE65525F3L, 0xAA55AB94L, 0x57489862L, 0x63E81440L, + 0x55CA396AL, 0x2AAB10B6L, 0xB4CC5C34L, 0x1141E8CEL, + 0xA15486AFL, 0x7C72E993L, 0xB3EE1411L, 0x636FBC2AL, + 0x2BA9C55DL, 0x741831F6L, 0xCE5C3E16L, 0x9B87931EL, + 0xAFD6BA33L, 0x6C24CF5CL, 0x7A325381L, 0x28958677L, + 0x3B8F4898L, 0x6B4BB9AFL, 0xC4BFE81BL, 0x66282193L, + 0x61D809CCL, 0xFB21A991L, 0x487CAC60L, 0x5DEC8032L, + 0xEF845D5DL, 0xE98575B1L, 0xDC262302L, 0xEB651B88L, + 0x23893E81L, 0xD396ACC5L, 0x0F6D6FF3L, 0x83F44239L, + 0x2E0B4482L, 0xA4842004L, 0x69C8F04AL, 0x9E1F9B5EL, + 0x21C66842L, 0xF6E96C9AL, 0x670C9C61L, 0xABD388F0L, + 0x6A51A0D2L, 0xD8542F68L, 0x960FA728L, 0xAB5133A3L, + 0x6EEF0B6CL, 0x137A3BE4L, 0xBA3BF050L, 0x7EFB2A98L, + 0xA1F1651DL, 0x39AF0176L, 0x66CA593EL, 0x82430E88L, + 0x8CEE8619L, 0x456F9FB4L, 0x7D84A5C3L, 0x3B8B5EBEL, + 0xE06F75D8L, 0x85C12073L, 0x401A449FL, 0x56C16AA6L, + 0x4ED3AA62L, 0x363F7706L, 0x1BFEDF72L, 0x429B023DL, + 0x37D0D724L, 0xD00A1248L, 0xDB0FEAD3L, 0x49F1C09BL, + 0x075372C9L, 0x80991B7BL, 0x25D479D8L, 0xF6E8DEF7L, + 0xE3FE501AL, 0xB6794C3BL, 0x976CE0BDL, 0x04C006BAL, + 0xC1A94FB6L, 0x409F60C4L, 0x5E5C9EC2L, 0x196A2463L, + 0x68FB6FAFL, 0x3E6C53B5L, 0x1339B2EBL, 0x3B52EC6FL, + 0x6DFC511FL, 0x9B30952CL, 0xCC814544L, 0xAF5EBD09L, + 0xBEE3D004L, 0xDE334AFDL, 0x660F2807L, 0x192E4BB3L, + 0xC0CBA857L, 0x45C8740FL, 0xD20B5F39L, 0xB9D3FBDBL, + 0x5579C0BDL, 0x1A60320AL, 0xD6A100C6L, 0x402C7279L, + 0x679F25FEL, 0xFB1FA3CCL, 0x8EA5E9F8L, 0xDB3222F8L, + 0x3C7516DFL, 0xFD616B15L, 0x2F501EC8L, 0xAD0552ABL, + 0x323DB5FAL, 0xFD238760L, 0x53317B48L, 0x3E00DF82L, + 0x9E5C57BBL, 0xCA6F8CA0L, 0x1A87562EL, 0xDF1769DBL, + 0xD542A8F6L, 0x287EFFC3L, 0xAC6732C6L, 0x8C4F5573L, + 0x695B27B0L, 0xBBCA58C8L, 0xE1FFA35DL, 0xB8F011A0L, + 0x10FA3D98L, 0xFD2183B8L, 0x4AFCB56CL, 0x2DD1D35BL, + 0x9A53E479L, 0xB6F84565L, 0xD28E49BCL, 0x4BFB9790L, + 0xE1DDF2DAL, 0xA4CB7E33L, 0x62FB1341L, 0xCEE4C6E8L, + 0xEF20CADAL, 0x36774C01L, 0xD07E9EFEL, 0x2BF11FB4L, + 0x95DBDA4DL, 0xAE909198L, 0xEAAD8E71L, 0x6B93D5A0L, + 0xD08ED1D0L, 0xAFC725E0L, 0x8E3C5B2FL, 0x8E7594B7L, + 0x8FF6E2FBL, 0xF2122B64L, 0x8888B812L, 0x900DF01CL, + 0x4FAD5EA0L, 0x688FC31CL, 0xD1CFF191L, 0xB3A8C1ADL, + 0x2F2F2218L, 0xBE0E1777L, 0xEA752DFEL, 0x8B021FA1L, + 0xE5A0CC0FL, 0xB56F74E8L, 0x18ACF3D6L, 0xCE89E299L, + 0xB4A84FE0L, 0xFD13E0B7L, 0x7CC43B81L, 0xD2ADA8D9L, + 0x165FA266L, 0x80957705L, 0x93CC7314L, 0x211A1477L, + 0xE6AD2065L, 0x77B5FA86L, 0xC75442F5L, 0xFB9D35CFL, + 0xEBCDAF0CL, 0x7B3E89A0L, 0xD6411BD3L, 0xAE1E7E49L, + 0x00250E2DL, 0x2071B35EL, 0x226800BBL, 0x57B8E0AFL, + 0x2464369BL, 0xF009B91EL, 0x5563911DL, 0x59DFA6AAL, + 0x78C14389L, 0xD95A537FL, 0x207D5BA2L, 0x02E5B9C5L, + 0x83260376L, 0x6295CFA9L, 0x11C81968L, 0x4E734A41L, + 0xB3472DCAL, 0x7B14A94AL, 0x1B510052L, 0x9A532915L, + 0xD60F573FL, 0xBC9BC6E4L, 0x2B60A476L, 0x81E67400L, + 0x08BA6FB5L, 0x571BE91FL, 0xF296EC6BL, 0x2A0DD915L, + 0xB6636521L, 0xE7B9F9B6L, 0xFF34052EL, 0xC5855664L, + 0x53B02D5DL, 0xA99F8FA1L, 0x08BA4799L, 0x6E85076AL }, + { 0x4B7A70E9L, 0xB5B32944L, 0xDB75092EL, 0xC4192623L, + 0xAD6EA6B0L, 0x49A7DF7DL, 0x9CEE60B8L, 0x8FEDB266L, + 0xECAA8C71L, 0x699A17FFL, 0x5664526CL, 0xC2B19EE1L, + 0x193602A5L, 0x75094C29L, 0xA0591340L, 0xE4183A3EL, + 0x3F54989AL, 0x5B429D65L, 0x6B8FE4D6L, 0x99F73FD6L, + 0xA1D29C07L, 0xEFE830F5L, 0x4D2D38E6L, 0xF0255DC1L, + 0x4CDD2086L, 0x8470EB26L, 0x6382E9C6L, 0x021ECC5EL, + 0x09686B3FL, 0x3EBAEFC9L, 0x3C971814L, 0x6B6A70A1L, + 0x687F3584L, 0x52A0E286L, 0xB79C5305L, 0xAA500737L, + 0x3E07841CL, 0x7FDEAE5CL, 0x8E7D44ECL, 0x5716F2B8L, + 0xB03ADA37L, 0xF0500C0DL, 0xF01C1F04L, 0x0200B3FFL, + 0xAE0CF51AL, 0x3CB574B2L, 0x25837A58L, 0xDC0921BDL, + 0xD19113F9L, 0x7CA92FF6L, 0x94324773L, 0x22F54701L, + 0x3AE5E581L, 0x37C2DADCL, 0xC8B57634L, 0x9AF3DDA7L, + 0xA9446146L, 0x0FD0030EL, 0xECC8C73EL, 0xA4751E41L, + 0xE238CD99L, 0x3BEA0E2FL, 0x3280BBA1L, 0x183EB331L, + 0x4E548B38L, 0x4F6DB908L, 0x6F420D03L, 0xF60A04BFL, + 0x2CB81290L, 0x24977C79L, 0x5679B072L, 0xBCAF89AFL, + 0xDE9A771FL, 0xD9930810L, 0xB38BAE12L, 0xDCCF3F2EL, + 0x5512721FL, 0x2E6B7124L, 0x501ADDE6L, 0x9F84CD87L, + 0x7A584718L, 0x7408DA17L, 0xBC9F9ABCL, 0xE94B7D8CL, + 0xEC7AEC3AL, 0xDB851DFAL, 0x63094366L, 0xC464C3D2L, + 0xEF1C1847L, 0x3215D908L, 0xDD433B37L, 0x24C2BA16L, + 0x12A14D43L, 0x2A65C451L, 0x50940002L, 0x133AE4DDL, + 0x71DFF89EL, 0x10314E55L, 0x81AC77D6L, 0x5F11199BL, + 0x043556F1L, 0xD7A3C76BL, 0x3C11183BL, 0x5924A509L, + 0xF28FE6EDL, 0x97F1FBFAL, 0x9EBABF2CL, 0x1E153C6EL, + 0x86E34570L, 0xEAE96FB1L, 0x860E5E0AL, 0x5A3E2AB3L, + 0x771FE71CL, 0x4E3D06FAL, 0x2965DCB9L, 0x99E71D0FL, + 0x803E89D6L, 0x5266C825L, 0x2E4CC978L, 0x9C10B36AL, + 0xC6150EBAL, 0x94E2EA78L, 0xA5FC3C53L, 0x1E0A2DF4L, + 0xF2F74EA7L, 0x361D2B3DL, 0x1939260FL, 0x19C27960L, + 0x5223A708L, 0xF71312B6L, 0xEBADFE6EL, 0xEAC31F66L, + 0xE3BC4595L, 0xA67BC883L, 0xB17F37D1L, 0x018CFF28L, + 0xC332DDEFL, 0xBE6C5AA5L, 0x65582185L, 0x68AB9802L, + 0xEECEA50FL, 0xDB2F953BL, 0x2AEF7DADL, 0x5B6E2F84L, + 0x1521B628L, 0x29076170L, 0xECDD4775L, 0x619F1510L, + 0x13CCA830L, 0xEB61BD96L, 0x0334FE1EL, 0xAA0363CFL, + 0xB5735C90L, 0x4C70A239L, 0xD59E9E0BL, 0xCBAADE14L, + 0xEECC86BCL, 0x60622CA7L, 0x9CAB5CABL, 0xB2F3846EL, + 0x648B1EAFL, 0x19BDF0CAL, 0xA02369B9L, 0x655ABB50L, + 0x40685A32L, 0x3C2AB4B3L, 0x319EE9D5L, 0xC021B8F7L, + 0x9B540B19L, 0x875FA099L, 0x95F7997EL, 0x623D7DA8L, + 0xF837889AL, 0x97E32D77L, 0x11ED935FL, 0x16681281L, + 0x0E358829L, 0xC7E61FD6L, 0x96DEDFA1L, 0x7858BA99L, + 0x57F584A5L, 0x1B227263L, 0x9B83C3FFL, 0x1AC24696L, + 0xCDB30AEBL, 0x532E3054L, 0x8FD948E4L, 0x6DBC3128L, + 0x58EBF2EFL, 0x34C6FFEAL, 0xFE28ED61L, 0xEE7C3C73L, + 0x5D4A14D9L, 0xE864B7E3L, 0x42105D14L, 0x203E13E0L, + 0x45EEE2B6L, 0xA3AAABEAL, 0xDB6C4F15L, 0xFACB4FD0L, + 0xC742F442L, 0xEF6ABBB5L, 0x654F3B1DL, 0x41CD2105L, + 0xD81E799EL, 0x86854DC7L, 0xE44B476AL, 0x3D816250L, + 0xCF62A1F2L, 0x5B8D2646L, 0xFC8883A0L, 0xC1C7B6A3L, + 0x7F1524C3L, 0x69CB7492L, 0x47848A0BL, 0x5692B285L, + 0x095BBF00L, 0xAD19489DL, 0x1462B174L, 0x23820E00L, + 0x58428D2AL, 0x0C55F5EAL, 0x1DADF43EL, 0x233F7061L, + 0x3372F092L, 0x8D937E41L, 0xD65FECF1L, 0x6C223BDBL, + 0x7CDE3759L, 0xCBEE7460L, 0x4085F2A7L, 0xCE77326EL, + 0xA6078084L, 0x19F8509EL, 0xE8EFD855L, 0x61D99735L, + 0xA969A7AAL, 0xC50C06C2L, 0x5A04ABFCL, 0x800BCADCL, + 0x9E447A2EL, 0xC3453484L, 0xFDD56705L, 0x0E1E9EC9L, + 0xDB73DBD3L, 0x105588CDL, 0x675FDA79L, 0xE3674340L, + 0xC5C43465L, 0x713E38D8L, 0x3D28F89EL, 0xF16DFF20L, + 0x153E21E7L, 0x8FB03D4AL, 0xE6E39F2BL, 0xDB83ADF7L }, + { 0xE93D5A68L, 0x948140F7L, 0xF64C261CL, 0x94692934L, + 0x411520F7L, 0x7602D4F7L, 0xBCF46B2EL, 0xD4A20068L, + 0xD4082471L, 0x3320F46AL, 0x43B7D4B7L, 0x500061AFL, + 0x1E39F62EL, 0x97244546L, 0x14214F74L, 0xBF8B8840L, + 0x4D95FC1DL, 0x96B591AFL, 0x70F4DDD3L, 0x66A02F45L, + 0xBFBC09ECL, 0x03BD9785L, 0x7FAC6DD0L, 0x31CB8504L, + 0x96EB27B3L, 0x55FD3941L, 0xDA2547E6L, 0xABCA0A9AL, + 0x28507825L, 0x530429F4L, 0x0A2C86DAL, 0xE9B66DFBL, + 0x68DC1462L, 0xD7486900L, 0x680EC0A4L, 0x27A18DEEL, + 0x4F3FFEA2L, 0xE887AD8CL, 0xB58CE006L, 0x7AF4D6B6L, + 0xAACE1E7CL, 0xD3375FECL, 0xCE78A399L, 0x406B2A42L, + 0x20FE9E35L, 0xD9F385B9L, 0xEE39D7ABL, 0x3B124E8BL, + 0x1DC9FAF7L, 0x4B6D1856L, 0x26A36631L, 0xEAE397B2L, + 0x3A6EFA74L, 0xDD5B4332L, 0x6841E7F7L, 0xCA7820FBL, + 0xFB0AF54EL, 0xD8FEB397L, 0x454056ACL, 0xBA489527L, + 0x55533A3AL, 0x20838D87L, 0xFE6BA9B7L, 0xD096954BL, + 0x55A867BCL, 0xA1159A58L, 0xCCA92963L, 0x99E1DB33L, + 0xA62A4A56L, 0x3F3125F9L, 0x5EF47E1CL, 0x9029317CL, + 0xFDF8E802L, 0x04272F70L, 0x80BB155CL, 0x05282CE3L, + 0x95C11548L, 0xE4C66D22L, 0x48C1133FL, 0xC70F86DCL, + 0x07F9C9EEL, 0x41041F0FL, 0x404779A4L, 0x5D886E17L, + 0x325F51EBL, 0xD59BC0D1L, 0xF2BCC18FL, 0x41113564L, + 0x257B7834L, 0x602A9C60L, 0xDFF8E8A3L, 0x1F636C1BL, + 0x0E12B4C2L, 0x02E1329EL, 0xAF664FD1L, 0xCAD18115L, + 0x6B2395E0L, 0x333E92E1L, 0x3B240B62L, 0xEEBEB922L, + 0x85B2A20EL, 0xE6BA0D99L, 0xDE720C8CL, 0x2DA2F728L, + 0xD0127845L, 0x95B794FDL, 0x647D0862L, 0xE7CCF5F0L, + 0x5449A36FL, 0x877D48FAL, 0xC39DFD27L, 0xF33E8D1EL, + 0x0A476341L, 0x992EFF74L, 0x3A6F6EABL, 0xF4F8FD37L, + 0xA812DC60L, 0xA1EBDDF8L, 0x991BE14CL, 0xDB6E6B0DL, + 0xC67B5510L, 0x6D672C37L, 0x2765D43BL, 0xDCD0E804L, + 0xF1290DC7L, 0xCC00FFA3L, 0xB5390F92L, 0x690FED0BL, + 0x667B9FFBL, 0xCEDB7D9CL, 0xA091CF0BL, 0xD9155EA3L, + 0xBB132F88L, 0x515BAD24L, 0x7B9479BFL, 0x763BD6EBL, + 0x37392EB3L, 0xCC115979L, 0x8026E297L, 0xF42E312DL, + 0x6842ADA7L, 0xC66A2B3BL, 0x12754CCCL, 0x782EF11CL, + 0x6A124237L, 0xB79251E7L, 0x06A1BBE6L, 0x4BFB6350L, + 0x1A6B1018L, 0x11CAEDFAL, 0x3D25BDD8L, 0xE2E1C3C9L, + 0x44421659L, 0x0A121386L, 0xD90CEC6EL, 0xD5ABEA2AL, + 0x64AF674EL, 0xDA86A85FL, 0xBEBFE988L, 0x64E4C3FEL, + 0x9DBC8057L, 0xF0F7C086L, 0x60787BF8L, 0x6003604DL, + 0xD1FD8346L, 0xF6381FB0L, 0x7745AE04L, 0xD736FCCCL, + 0x83426B33L, 0xF01EAB71L, 0xB0804187L, 0x3C005E5FL, + 0x77A057BEL, 0xBDE8AE24L, 0x55464299L, 0xBF582E61L, + 0x4E58F48FL, 0xF2DDFDA2L, 0xF474EF38L, 0x8789BDC2L, + 0x5366F9C3L, 0xC8B38E74L, 0xB475F255L, 0x46FCD9B9L, + 0x7AEB2661L, 0x8B1DDF84L, 0x846A0E79L, 0x915F95E2L, + 0x466E598EL, 0x20B45770L, 0x8CD55591L, 0xC902DE4CL, + 0xB90BACE1L, 0xBB8205D0L, 0x11A86248L, 0x7574A99EL, + 0xB77F19B6L, 0xE0A9DC09L, 0x662D09A1L, 0xC4324633L, + 0xE85A1F02L, 0x09F0BE8CL, 0x4A99A025L, 0x1D6EFE10L, + 0x1AB93D1DL, 0x0BA5A4DFL, 0xA186F20FL, 0x2868F169L, + 0xDCB7DA83L, 0x573906FEL, 0xA1E2CE9BL, 0x4FCD7F52L, + 0x50115E01L, 0xA70683FAL, 0xA002B5C4L, 0x0DE6D027L, + 0x9AF88C27L, 0x773F8641L, 0xC3604C06L, 0x61A806B5L, + 0xF0177A28L, 0xC0F586E0L, 0x006058AAL, 0x30DC7D62L, + 0x11E69ED7L, 0x2338EA63L, 0x53C2DD94L, 0xC2C21634L, + 0xBBCBEE56L, 0x90BCB6DEL, 0xEBFC7DA1L, 0xCE591D76L, + 0x6F05E409L, 0x4B7C0188L, 0x39720A3DL, 0x7C927C24L, + 0x86E3725FL, 0x724D9DB9L, 0x1AC15BB4L, 0xD39EB8FCL, + 0xED545578L, 0x08FCA5B5L, 0xD83D7CD3L, 0x4DAD0FC4L, + 0x1E50EF5EL, 0xB161E6F8L, 0xA28514D9L, 0x6C51133CL, + 0x6FD5C7E7L, 0x56E14EC4L, 0x362ABFCEL, 0xDDC6C837L, + 0xD79A3234L, 0x92638212L, 0x670EFA8EL, 0x406000E0L }, + { 0x3A39CE37L, 0xD3FAF5CFL, 0xABC27737L, 0x5AC52D1BL, + 0x5CB0679EL, 0x4FA33742L, 0xD3822740L, 0x99BC9BBEL, + 0xD5118E9DL, 0xBF0F7315L, 0xD62D1C7EL, 0xC700C47BL, + 0xB78C1B6BL, 0x21A19045L, 0xB26EB1BEL, 0x6A366EB4L, + 0x5748AB2FL, 0xBC946E79L, 0xC6A376D2L, 0x6549C2C8L, + 0x530FF8EEL, 0x468DDE7DL, 0xD5730A1DL, 0x4CD04DC6L, + 0x2939BBDBL, 0xA9BA4650L, 0xAC9526E8L, 0xBE5EE304L, + 0xA1FAD5F0L, 0x6A2D519AL, 0x63EF8CE2L, 0x9A86EE22L, + 0xC089C2B8L, 0x43242EF6L, 0xA51E03AAL, 0x9CF2D0A4L, + 0x83C061BAL, 0x9BE96A4DL, 0x8FE51550L, 0xBA645BD6L, + 0x2826A2F9L, 0xA73A3AE1L, 0x4BA99586L, 0xEF5562E9L, + 0xC72FEFD3L, 0xF752F7DAL, 0x3F046F69L, 0x77FA0A59L, + 0x80E4A915L, 0x87B08601L, 0x9B09E6ADL, 0x3B3EE593L, + 0xE990FD5AL, 0x9E34D797L, 0x2CF0B7D9L, 0x022B8B51L, + 0x96D5AC3AL, 0x017DA67DL, 0xD1CF3ED6L, 0x7C7D2D28L, + 0x1F9F25CFL, 0xADF2B89BL, 0x5AD6B472L, 0x5A88F54CL, + 0xE029AC71L, 0xE019A5E6L, 0x47B0ACFDL, 0xED93FA9BL, + 0xE8D3C48DL, 0x283B57CCL, 0xF8D56629L, 0x79132E28L, + 0x785F0191L, 0xED756055L, 0xF7960E44L, 0xE3D35E8CL, + 0x15056DD4L, 0x88F46DBAL, 0x03A16125L, 0x0564F0BDL, + 0xC3EB9E15L, 0x3C9057A2L, 0x97271AECL, 0xA93A072AL, + 0x1B3F6D9BL, 0x1E6321F5L, 0xF59C66FBL, 0x26DCF319L, + 0x7533D928L, 0xB155FDF5L, 0x03563482L, 0x8ABA3CBBL, + 0x28517711L, 0xC20AD9F8L, 0xABCC5167L, 0xCCAD925FL, + 0x4DE81751L, 0x3830DC8EL, 0x379D5862L, 0x9320F991L, + 0xEA7A90C2L, 0xFB3E7BCEL, 0x5121CE64L, 0x774FBE32L, + 0xA8B6E37EL, 0xC3293D46L, 0x48DE5369L, 0x6413E680L, + 0xA2AE0810L, 0xDD6DB224L, 0x69852DFDL, 0x09072166L, + 0xB39A460AL, 0x6445C0DDL, 0x586CDECFL, 0x1C20C8AEL, + 0x5BBEF7DDL, 0x1B588D40L, 0xCCD2017FL, 0x6BB4E3BBL, + 0xDDA26A7EL, 0x3A59FF45L, 0x3E350A44L, 0xBCB4CDD5L, + 0x72EACEA8L, 0xFA6484BBL, 0x8D6612AEL, 0xBF3C6F47L, + 0xD29BE463L, 0x542F5D9EL, 0xAEC2771BL, 0xF64E6370L, + 0x740E0D8DL, 0xE75B1357L, 0xF8721671L, 0xAF537D5DL, + 0x4040CB08L, 0x4EB4E2CCL, 0x34D2466AL, 0x0115AF84L, + 0xE1B00428L, 0x95983A1DL, 0x06B89FB4L, 0xCE6EA048L, + 0x6F3F3B82L, 0x3520AB82L, 0x011A1D4BL, 0x277227F8L, + 0x611560B1L, 0xE7933FDCL, 0xBB3A792BL, 0x344525BDL, + 0xA08839E1L, 0x51CE794BL, 0x2F32C9B7L, 0xA01FBAC9L, + 0xE01CC87EL, 0xBCC7D1F6L, 0xCF0111C3L, 0xA1E8AAC7L, + 0x1A908749L, 0xD44FBD9AL, 0xD0DADECBL, 0xD50ADA38L, + 0x0339C32AL, 0xC6913667L, 0x8DF9317CL, 0xE0B12B4FL, + 0xF79E59B7L, 0x43F5BB3AL, 0xF2D519FFL, 0x27D9459CL, + 0xBF97222CL, 0x15E6FC2AL, 0x0F91FC71L, 0x9B941525L, + 0xFAE59361L, 0xCEB69CEBL, 0xC2A86459L, 0x12BAA8D1L, + 0xB6C1075EL, 0xE3056A0CL, 0x10D25065L, 0xCB03A442L, + 0xE0EC6E0EL, 0x1698DB3BL, 0x4C98A0BEL, 0x3278E964L, + 0x9F1F9532L, 0xE0D392DFL, 0xD3A0342BL, 0x8971F21EL, + 0x1B0A7441L, 0x4BA3348CL, 0xC5BE7120L, 0xC37632D8L, + 0xDF359F8DL, 0x9B992F2EL, 0xE60B6F47L, 0x0FE3F11DL, + 0xE54CDA54L, 0x1EDAD891L, 0xCE6279CFL, 0xCD3E7E6FL, + 0x1618B166L, 0xFD2C1D05L, 0x848FD2C5L, 0xF6FB2299L, + 0xF523F357L, 0xA6327623L, 0x93A83531L, 0x56CCCD02L, + 0xACF08162L, 0x5A75EBB5L, 0x6E163697L, 0x88D273CCL, + 0xDE966292L, 0x81B949D0L, 0x4C50901BL, 0x71C65614L, + 0xE6C6C7BDL, 0x327A140AL, 0x45E1D006L, 0xC3F27B9AL, + 0xC9AA53FDL, 0x62A80F00L, 0xBB25BFE2L, 0x35BDD2F6L, + 0x71126905L, 0xB2040222L, 0xB6CBCF7CL, 0xCD769C2BL, + 0x53113EC0L, 0x1640E3D3L, 0x38ABBD60L, 0x2547ADF0L, + 0xBA38209CL, 0xF746CE76L, 0x77AFA1C5L, 0x20756060L, + 0x85CBFE4EL, 0x8AE88DD8L, 0x7AAAF9B0L, 0x4CF9AA7EL, + 0x1948C25CL, 0x02FB8A8CL, 0x01C36AE4L, 0xD6EBE1F9L, + 0x90D4F869L, 0xA65CDEA0L, 0x3F09252DL, 0xC208E69FL, + 0xB74E6132L, 0xCE77E25BL, 0x578FDFE3L, 0x3AC372E6L } +}; + + +static unsigned long F(BLOWFISH_CTX *ctx, unsigned long x) { + unsigned short a, b, c, d; + unsigned long y; + + d = (unsigned short)(x & 0xFF); + x >>= 8; + c = (unsigned short)(x & 0xFF); + x >>= 8; + b = (unsigned short)(x & 0xFF); + x >>= 8; + a = (unsigned short)(x & 0xFF); + y = ctx->S[0][a] + ctx->S[1][b]; + y = y ^ ctx->S[2][c]; + y = y + ctx->S[3][d]; + + return y; +} + + +static void Blowfish_Encrypt(BLOWFISH_CTX *ctx, unsigned long *xl, unsigned long *xr){ + unsigned long Xl; + unsigned long Xr; + unsigned long temp; + short i; + + Xl = *xl; + Xr = *xr; + + for (i = 0; i < N; ++i) { + Xl = Xl ^ ctx->P[i]; + Xr = F(ctx, Xl) ^ Xr; + + temp = Xl; + Xl = Xr; + Xr = temp; + } + + temp = Xl; + Xl = Xr; + Xr = temp; + + Xr = Xr ^ ctx->P[N]; + Xl = Xl ^ ctx->P[N + 1]; + + *xl = Xl; + *xr = Xr; +} + + +static void Blowfish_Decrypt(BLOWFISH_CTX *ctx, unsigned long *xl, unsigned long *xr){ + unsigned long Xl; + unsigned long Xr; + unsigned long temp; + short i; + + Xl = *xl; + Xr = *xr; + + for (i = N + 1; i > 1; --i) { + Xl = Xl ^ ctx->P[i]; + Xr = F(ctx, Xl) ^ Xr; + + /* Exchange Xl and Xr */ + temp = Xl; + Xl = Xr; + Xr = temp; + } + + /* Exchange Xl and Xr */ + temp = Xl; + Xl = Xr; + Xr = temp; + + Xr = Xr ^ ctx->P[1]; + Xl = Xl ^ ctx->P[0]; + + *xl = Xl; + *xr = Xr; +} + +static void Blowfish_Init(BLOWFISH_CTX *ctx, unsigned char *key, int keyLen) { + int i, j, k; + unsigned long data, datal, datar; + + for (i = 0; i < 4; i++) { + for (j = 0; j < 256; j++) + ctx->S[i][j] = ORIG_S[i][j]; + } + + j = 0; + for (i = 0; i < N + 2; ++i) { + data = 0x00000000; + for (k = 0; k < 4; ++k) { + data = (data << 8) | key[j]; + j = j + 1; + if (j >= keyLen) + j = 0; + } + ctx->P[i] = ORIG_P[i] ^ data; + } + + datal = 0x00000000; + datar = 0x00000000; + + for (i = 0; i < N + 2; i += 2) { + Blowfish_Encrypt(ctx, &datal, &datar); + ctx->P[i] = datal; + ctx->P[i + 1] = datar; + } + + for (i = 0; i < 4; ++i) { + for (j = 0; j < 256; j += 2) { + Blowfish_Encrypt(ctx, &datal, &datar); + ctx->S[i][j] = datal; + ctx->S[i][j + 1] = datar; + } + } +} + +static unsigned long long blowfish_test(unsigned long long input) +{ + unsigned long L = input >> 32, R = input; + BLOWFISH_CTX ctx; + Blowfish_Init(&ctx, (unsigned char*)"TESTKEY", 7); + Blowfish_Encrypt(&ctx, &L, &R); + Blowfish_Decrypt(&ctx, &L, &R); + return ((unsigned long long)L << 32) | R; +} diff -r c6b683ba68f5 -r a2b2b2a011f1 tools/tests/blowfish.mk --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/tests/blowfish.mk Mon Jan 15 15:15:26 2007 -0700 @@ -0,0 +1,23 @@ + +override XEN_TARGET_ARCH = x86_32 +XEN_ROOT = ../.. +CFLAGS := +include $(XEN_ROOT)/tools/Rules.mk + +# Disable PIE/SSP if GCC supports them. They can break us. +CFLAGS += $(call cc-option,$(CC),-nopie,) +CFLAGS += $(call cc-option,$(CC),-fno-stack-protector,) +CFLAGS += $(call cc-option,$(CC),-fno-stack-protector-all,) + +OBJCOPY = objcopy +CFLAGS += -fno-builtin -O2 -msoft-float +LDFLAGS = -nostdlib -Wl,-N -Wl,-Ttext -Wl,0x100000 + +.PHONY: all +all: blowfish.bin + +blowfish.bin: blowfish.c + $(CC) $(CFLAGS) -c blowfish.c + $(CC) $(CFLAGS) $(LDFLAGS) -o blowfish.tmp blowfish.o + $(OBJCOPY) -O binary blowfish.tmp blowfish.bin + rm -f blowfish.tmp diff -r c6b683ba68f5 -r a2b2b2a011f1 tools/tests/test_x86_emulator.c --- a/tools/tests/test_x86_emulator.c Sun Jan 14 22:18:38 2007 -0700 +++ b/tools/tests/test_x86_emulator.c Mon Jan 15 15:15:26 2007 -0700 @@ -15,6 +15,10 @@ typedef int64_t s64; #include <asm-x86/x86_emulate.h> #include <sys/mman.h> +#include "blowfish.h" + +#define MMAP_SZ 16384 + /* EFLAGS bit definitions. */ #define EFLG_OF (1<<11) #define EFLG_DF (1<<10) @@ -107,16 +111,16 @@ int main(int argc, char **argv) struct x86_emulate_ctxt ctxt; struct cpu_user_regs regs; char *instr; - unsigned int *res; + unsigned int *res, i; int rc; #ifndef __x86_64__ - unsigned int i, bcdres_native, bcdres_emul; + unsigned int bcdres_native, bcdres_emul; #endif ctxt.regs = ®s; ctxt.address_bytes = 4; - res = mmap((void *)0x100000, 0x1000, PROT_READ|PROT_WRITE, + res = mmap((void *)0x100000, MMAP_SZ, PROT_READ|PROT_WRITE, MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, 0, 0); if ( res == MAP_FAILED ) { @@ -482,6 +486,42 @@ int main(int argc, char **argv) printf("skipped\n"); #endif + printf("Testing blowfish code sequence"); + memcpy(res, blowfish_code, sizeof(blowfish_code)); + regs.eax = 2; + regs.edx = 1; + regs.eip = (unsigned long)res; + regs.esp = (unsigned long)res + MMAP_SZ - 4; + *(uint32_t *)(unsigned long)regs.esp = 0x12345678; + regs.eflags = 2; + i = 0; + while ( (uint32_t)regs.eip != 0x12345678 ) + { + if ( (i++ & 8191) == 0 ) + printf("."); + rc = x86_emulate(&ctxt, &emulops); + if ( rc != 0 ) + { + printf("failed at %%eip == %08x\n", (unsigned int)regs.eip); + return 1; + } + } + if ( (regs.esp != ((unsigned long)res + MMAP_SZ)) || + (regs.eax != 2) || (regs.edx != 1) ) + goto fail; + printf("okay\n"); + +#ifndef __x86_64__ + printf("%-40s", "Testing blowfish native execution..."); + asm volatile ( + "movl $0x100000,%%ecx; call *%%ecx" + : "=a" (regs.eax), "=d" (regs.edx) + : "0" (2), "1" (1) : "ecx" ); + if ( (regs.eax != 2) || (regs.edx != 1) ) + goto fail; + printf("okay\n"); +#endif + return 0; fail: diff -r c6b683ba68f5 -r a2b2b2a011f1 tools/xenstat/xentop/xentop.c --- a/tools/xenstat/xentop/xentop.c Sun Jan 14 22:18:38 2007 -0700 +++ b/tools/xenstat/xentop/xentop.c Mon Jan 15 15:15:26 2007 -0700 @@ -1067,9 +1067,9 @@ int main(int argc, char **argv) gettimeofday(&curtime, NULL); top(); oldtime = curtime; - sleep(delay); if ((!loop) && !(--iterations)) break; + sleep(delay); } while (1); } diff -r c6b683ba68f5 -r a2b2b2a011f1 tools/xm-test/README --- a/tools/xm-test/README Sun Jan 14 22:18:38 2007 -0700 +++ b/tools/xm-test/README Mon Jan 15 15:15:26 2007 -0700 @@ -207,6 +207,49 @@ running DomUs on the system to provide e running DomUs on the system to provide each test with a "clean slate". +Testing the XML-RPC and Xen-API interfaces of xend +================================================== + +The xm-test suite can be used to test xm's interface with xend using +either XML-RPC or the Xen-API. In order to use either one of these modes, +xm needs to be configured using its configuration file +'/etc/xen/xm-config.xml'. +Note: The current default configuration after a fresh install of the xen +sources currently is to use the XML-RPC interface for communication with xend. + +Example content for the xm-config.xml for using the Xen-API looks as +follows: + +<xm> + <server type='Xen-API' + uri='http://localhost:9363/' + username='me' + password='mypassword' /> +</xm> + +This configuration makes xm talk to xend using port 9363. For this to +work, also xend needs to be configured to listen to port 9363. Therefore +The following line must be in /etc/xen/xend-config.sxp. + +(xen-api-server (( 127.0.0.1:9363 none ))) + +To communicate via the legacy XML-RPC interface, the file +'/etc/xen/xm-config.xml' may simply have the following content or +may be complete remove from the /etc/xen directory. + +<xm> +</xm> + +A few tests have been written for the xm-test suite that test the +Xen-API interface directly without relying on 'xm'. These tests can be +found in the grouptest 'xapi' and for them to work properly, xm must have +been configured to use the Xen-API following the instructions above. To +run these test, the following command line can be invoked: + + # ./runtest.sh -g xapi <logfile> + + + Extending ========= diff -r c6b683ba68f5 -r a2b2b2a011f1 tools/xm-test/configure.ac --- a/tools/xm-test/configure.ac Sun Jan 14 22:18:38 2007 -0700 +++ b/tools/xm-test/configure.ac Mon Jan 15 15:15:26 2007 -0700 @@ -150,6 +150,7 @@ AC_CONFIG_FILES([ tests/vcpu-pin/Makefile tests/vcpu-disable/Makefile tests/vtpm/Makefile + tests/xapi/Makefile tests/enforce_dom0_cpus/Makefile lib/XmTestReport/xmtest.py lib/XmTestLib/config.py diff -r c6b683ba68f5 -r a2b2b2a011f1 tools/xm-test/grouptest/xapi --- a/tools/xm-test/grouptest/xapi Sun Jan 14 22:18:38 2007 -0700 +++ b/tools/xm-test/grouptest/xapi Mon Jan 15 15:15:26 2007 -0700 @@ -1,1 +1,2 @@ vtpm 09_vtpm-xapi.test +xapi vtpm 09_vtpm-xapi.test diff -r c6b683ba68f5 -r a2b2b2a011f1 tools/xm-test/lib/XmTestLib/DomainTracking.py --- a/tools/xm-test/lib/XmTestLib/DomainTracking.py Sun Jan 14 22:18:38 2007 -0700 +++ b/tools/xm-test/lib/XmTestLib/DomainTracking.py Mon Jan 15 15:15:26 2007 -0700 @@ -20,9 +20,11 @@ import atexit import Test +import xapi # Tracking of managed domains _managedDomains = [] +_VMuuids = [] registered = 0 def addManagedDomain(name): @@ -36,8 +38,24 @@ def delManagedDomain(name): if name in _managedDomains: del _managedDomains[_managedDomains.index(name)] +def addXAPIDomain(uuid): + global registered + _VMuuids.append(uuid) + if not registered: + atexit.register(destroyManagedDomains) + registered = 1 + +def delXAPIDomain(uuid): + _VMuuids.remove(uuid) + def destroyManagedDomains(): if len(_managedDomains) > 0: for m in _managedDomains: Test.traceCommand("xm destroy %s" % m) Test.traceCommand("xm delete %s" % m) + if len(_VMuuids) > 0: + for uuid in _VMuuids: + Test.traceCommand("xm destroy %s" % uuid) + Test.traceCommand("xm delete %s" % uuid) + + diff -r c6b683ba68f5 -r a2b2b2a011f1 tools/xm-test/lib/XmTestLib/XenAPIDomain.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/xm-test/lib/XmTestLib/XenAPIDomain.py Mon Jan 15 15:15:26 2007 -0700 @@ -0,0 +1,176 @@ +#!/usr/bin/python +""" + Copyright (C) International Business Machines Corp., 2005 + Author: Stefan Berger <stefanb@xxxxxxxxxx> + + Based on XenDomain.py by Dan Smith <danms@xxxxxxxxxx> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; under version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +""" +import os +import sys +from XmTestLib import * +from xen.util.xmlrpclib2 import ServerProxy +from types import DictType + + +class XenAPIConfig: + """An object to help create a VM configuration usable via Xen-API""" + def __init__(self): + self.opts = {} + #Array to translate old option to new ones + self.opttrlate = { 'name' : 'name_label' , + 'memory' : [ 'memory_static_max' , + 'memory_static_min' , + 'memory_dynamic_min', + 'memory_dynamic_max' ], + 'kernel' : 'PV_kernel', + 'ramdisk': 'PV_ramdisk', + 'root' : 'PV_args'} + + def setOpt(self, name, value): + """Set an option in the config""" + if name in self.opttrlate.keys(): + _name = self.opttrlate[name] + else: + _name = name + + if isinstance(_name, list): + for _n in _name: + self.opts[_n] = value + else: + self.opts[_name] = value + + def getOpt(self, name): + """Return the value of a config option""" + if name in self.opts.keys(): + return self.opts[name] + else: + return None + + def setOpts(self, opts): + """Batch-set options from a dictionary""" + for k, v in opts.items(): + self.setOpt(k, v) + + def getOpts(self): + return self.opts + + +class XenAPIDomain(XenDomain): + + def __init__(self, name=None, config=None): + if name: + self.name = name + else: + self.name = getUniqueName() + + self.config = config + self.console = None + self.netEnv = "bridge" + + self.session = xapi.connect() + session = self.session + try: + self.vm_uuid = session.xenapi.VM.create(self.config.getOpts()) + addXAPIDomain(self.vm_uuid) + except: + raise DomainError("Could not create VM config file for " + "managed domain.") + + #Only support PV for now. + self.type = "PV" + + def start(self, noConsole=False, startpaused=False): + #start the VM + session = self.session + if self.vm_uuid: + try: + session.xenapi.VM.start(self.vm_uuid, startpaused) + except: + raise DomainError("Could not start domain") + else: + raise DomainError("VM has no UUID - does VM config exist?") + + if startpaused: + return + + if self.getDomainType() == "HVM": + waitForBoot() + + if self.console and noConsole == True: + self.closeConsole() + + elif self.console and noConsole == False: + return self.console + + elif not self.console and noConsole == False: + return self.getConsole() + + def stop(self): + if self.vm_uuid: + self.session.xenapi.VM.hard_shutdown(self.vm_uuid) + else: + raise DomainError("VM has no UUID - does VM config exist?") + + def destroy(self): + #Stop VM first. + self.stop() + if self.vm_uuid: + self.session.xenapi.VM.destroy(self.vm_uuid) + delXAPIDomain(self.vm_uuid) + else: + raise DomainError("VM has no UUID - does VM config exist?") + + def get_uuid(self): + return self.vm_uuid + + def newDevice(self, Device, *args): + raise DomainError("No support for newDevice().") + + def removeDevice(self, id): + raise DomainError("No support for removeDevice().") + + def removeAllDevices(self, id): + raise DomainError("No support for removeAllDevices().") + + def isRunning(self): + return isDomainRunning(self.name) + + def getDevice(self, id): + raise DomainError("No support for getDevice().") + + +class XmTestAPIDomain(XenAPIDomain): + + """Create a new managed xm-test domain + @param name: The requested domain name + @param extraConfig: Additional configuration options + @param baseConfig: The initial configuration defaults to use + """ + def __init__(self, name=None, extraConfig=None, + baseConfig=arch.configDefaults): + config = XenAPIConfig() + config.setOpts(baseConfig) + if extraConfig: + config.setOpts(extraConfig) + + if name: + config.setOpt("name_label", name) + elif not config.getOpt("name_label"): + config.setOpt("name_label", getUniqueName()) + + XenAPIDomain.__init__(self, config.getOpt("name_label"), + config=config) diff -r c6b683ba68f5 -r a2b2b2a011f1 tools/xm-test/lib/XmTestLib/XenManagedDomain.py --- a/tools/xm-test/lib/XmTestLib/XenManagedDomain.py Sun Jan 14 22:18:38 2007 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,177 +0,0 @@ -#!/usr/bin/python -""" - Copyright (C) International Business Machines Corp., 2005 - Author: Stefan Berger <stefanb@xxxxxxxxxx> - - Based on XenDomain.py by Dan Smith <danms@xxxxxxxxxx> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; under version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -""" -import os -import sys -from XmTestLib import * -from xen.util.xmlrpclib2 import ServerProxy -from types import DictType - - -class XenManagedConfig: - """An object to help create a VM configuration usable via Xen-API""" - def __init__(self): - self.opts = {} - #Array to translate old option to new ones - self.opttrlate = { 'name' : 'name_label' , - 'memory' : [ 'memory_static_max' , - 'memory_static_min' , - 'memory_dynamic_min', - 'memory_dynamic_max' ], - 'kernel' : 'kernel_kernel', - 'ramdisk': 'kernel_initrd', - 'root' : 'kernel_args'} - - def setOpt(self, name, value): - """Set an option in the config""" - if name in self.opttrlate.keys(): - _name = self.opttrlate[name] - else: - _name = name - - if isinstance(_name, list): - for _n in _name: - self.opts[_n] = value - else: - self.opts[_name] = value - - def getOpt(self, name): - """Return the value of a config option""" - if name in self.opts.keys(): - return self.opts[name] - else: - return None - - def setOpts(self, opts): - """Batch-set options from a dictionary""" - for k, v in opts.items(): - self.setOpt(k, v) - - def getOpts(self): - return self.opts - - -class XenManagedDomain(XenDomain): - - def __init__(self, name=None, config=None): - if name: - self.name = name - else: - self.name = getUniqueName() - - self.config = config - self.console = None - self.netEnv = "bridge" - - self.server, self.session = xapi._connect() - server = self.server - try: - self.vm_uuid = xapi.execute(server.VM.create, self.session, - self.config.getOpts()) - xapi._VMuuids.append(self.vm_uuid) - except: - raise DomainError("Could not create VM config file for " - "managed domain.") - - #Only support PV for now. - self.type = "PV" - - def start(self, noConsole=False, startpaused=False): - #start the VM - server = self.server - if self.vm_uuid: - try: - xapi.execute(server.VM.start, self.session, self.vm_uuid, - startpaused) - except: - raise DomainError("Could not start domain") - else: - raise DomainError("VM has not UUID - VM config does not exist?") - - if self.getDomainType() == "HVM": - waitForBoot() - - if self.console and noConsole == True: - self.closeConsole() - - elif self.console and noConsole == False: - return self.console - - elif not self.console and noConsole == False: - return self.getConsole() - - def stop(self): - if self.vm_uuid: - server = self.server - xapi.execute(server.VM.hard_shutdown, self.session, self.vm_uuid) - else: - raise DomainError("VM has not UUID - VM config does not exist?") - - def destroy(self): - #Stop VM first. - self.stop() - if self.vm_uuid: - server = self.server - xapi.execute(server.VM.destroy, self.session, self.vm_uuid) - xapi._VMuuids.remove(self.vm_uuid) - else: - raise DomainError("VM has not UUID - VM config does not exist?") - - def get_uuid(self): - return self.vm_uuid - - def newDevice(self, Device, *args): - raise DomainError("No support for newDevice().") - - def removeDevice(self, id): - raise DomainError("No support for removeDevice().") - - def removeAllDevices(self, id): - raise DomainError("No support for removeAllDevices().") - - def isRunning(self): - return isDomainRunning(self.name) - - def getDevice(self, id): - raise DomainError("No support for getDevice().") - - -class XmTestManagedDomain(XenManagedDomain): - - """Create a new managed xm-test domain - @param name: The requested domain name - @param extraConfig: Additional configuration options - @param baseConfig: The initial configuration defaults to use - """ - def __init__(self, name=None, extraConfig=None, - baseConfig=arch.configDefaults): - config = XenManagedConfig() - config.setOpts(baseConfig) - if extraConfig: - config.setOpts(extraConfig) - - if name: - config.setOpt("name_label", name) - elif not config.getOpt("name_label"): - config.setOpt("name_label", getUniqueName()) - - XenManagedDomain.__init__(self, config.getOpt("name_label"), - config=config) diff -r c6b683ba68f5 -r a2b2b2a011f1 tools/xm-test/lib/XmTestLib/Xm.py --- a/tools/xm-test/lib/XmTestLib/Xm.py Sun Jan 14 22:18:38 2007 -0700 +++ b/tools/xm-test/lib/XmTestLib/Xm.py Mon Jan 15 15:15:26 2007 -0700 @@ -48,6 +48,8 @@ def domid(name): status, output = traceCommand("xm domid " + name); if status != 0 or "Traceback" in output: + return -1 + if output == "None": return -1 try: return int(output) diff -r c6b683ba68f5 -r a2b2b2a011f1 tools/xm-test/lib/XmTestLib/xapi.py --- a/tools/xm-test/lib/XmTestLib/xapi.py Sun Jan 14 22:18:38 2007 -0700 +++ b/tools/xm-test/lib/XmTestLib/xapi.py Mon Jan 15 15:15:26 2007 -0700 @@ -17,50 +17,49 @@ # Copyright (C) 2006 IBM Corporation #============================================================================ +import atexit import os import sys from XmTestLib import * -from xen.util.xmlrpclib2 import ServerProxy +from xen.xm import main as xmmain +from xen.xm import XenAPI +from xen.xm.opts import OptionError from types import DictType +import xml.dom.minidom +def get_login_pwd(): + if xmmain.serverType == xmmain.SERVER_XEN_API: + try: + login, password = xmmain.parseAuthentication() + return (login, password) + except: + raise OptionError("Configuration for login/pwd not found. " + "Need to run xapi-setup.py?") + raise OptionError("Xm configuration file not using Xen-API for " + "communication with xend.") -XAPI_DEFAULT_LOGIN = " " -XAPI_DEFAULT_PASSWORD = " " +sessions=[] -class XenAPIError(Exception): - pass - - -#A list of VMs' UUIDs that were created using vm_create -_VMuuids = [] - -#Terminate previously created managed(!) VMs and destroy their configs -def vm_destroy_all(): - server, session = _connect() - for uuid in _VMuuids: - execute(server.VM.hard_shutdown, session, uuid) - execute(server.VM.destroy , session, uuid) - - -def execute(fn, *args): - result = fn(*args) - if type(result) != DictType: - raise TypeError("Function returned object of type: %s" % - str(type(result))) - if 'Value' not in result: - raise XenAPIError(*result['ErrorDescription']) - return result['Value'] - -_initialised = False -_server = None -_session = None -def _connect(*args): - global _server, _session, _initialised - if not _initialised: - _server = ServerProxy('httpu:///var/run/xend/xen-api.sock') - login = XAPI_DEFAULT_LOGIN - password = XAPI_DEFAULT_PASSWORD - creds = (login, password) - _session = execute(_server.session.login_with_password, *creds) - _initialised = True - return (_server, _session) +def connect(*args): + try: + creds = get_login_pwd() + except Exception, e: + FAIL("%s" % str(e)) + try: + session = XenAPI.Session(xmmain.serverURI) + except: + raise OptionError("Could not create XenAPI session with Xend." \ + "URI=%s" % xmmain.serverURI) + try: + session.login_with_password(*creds) + except: + raise OptionError("Could not login to Xend. URI=%s" % xmmain.serverURI) + def logout(): + try: + for s in sessions: + s.xenapi.session.logout() + except: + pass + sessions.append(session) + atexit.register(logout) + return session diff -r c6b683ba68f5 -r a2b2b2a011f1 tools/xm-test/runtest.sh --- a/tools/xm-test/runtest.sh Sun Jan 14 22:18:38 2007 -0700 +++ b/tools/xm-test/runtest.sh Mon Jan 15 15:15:26 2007 -0700 @@ -16,6 +16,7 @@ usage() { echo " -r <url> : url of test results repository to use" echo " -s <report> : just submit report <report>" echo " -u : unsafe -- do not run the sanity checks before starting" + echo " -md : all created domains are xend-'managed' domains" echo " -h | --help : show this help" } @@ -218,10 +219,13 @@ unsafe=no unsafe=no GROUPENTERED=default +#Prepare for usage with ACM if [ -d /etc/xen/acm-security/policies ]; then cp -f tests/security-acm/xm-test-security_policy.xml \ /etc/xen/acm-security/policies fi + +unset XM_MANAGED_DOMAINS # Resolve options while [ $# -gt 0 ] @@ -260,6 +264,10 @@ while [ $# -gt 0 ] unsafe=yes report=no ;; + -md) + echo "(use managed domains)" + export XM_MANAGED_DOMAINS=1 + ;; -h|--help) usage exit 0 diff -r c6b683ba68f5 -r a2b2b2a011f1 tools/xm-test/tests/vtpm/09_vtpm-xapi.py --- a/tools/xm-test/tests/vtpm/09_vtpm-xapi.py Sun Jan 14 22:18:38 2007 -0700 +++ b/tools/xm-test/tests/vtpm/09_vtpm-xapi.py Mon Jan 15 15:15:26 2007 -0700 @@ -6,71 +6,66 @@ # Test to test the vtpm class through the Xen-API from XmTestLib import xapi -from XmTestLib.XenManagedDomain import XmTestManagedDomain +from XmTestLib.XenAPIDomain import XmTestAPIDomain from XmTestLib import * from vtpm_utils import * import commands import os -def do_test(): - domain = XmTestManagedDomain() - vm_uuid = domain.get_uuid() +try: + # XmTestAPIDomain tries to establish a connection to XenD + domain = XmTestAPIDomain() +except Exception, e: + SKIP("Skipping test. Error: %s" % str(e)) +vm_uuid = domain.get_uuid() - vtpmcfg = {} - vtpmcfg['type'] = "paravirtualised" - vtpmcfg['backend'] = "Domain-0" - vtpmcfg['instance'] = 1 - vtpmcfg['VM'] = vm_uuid +vtpmcfg = {} +vtpmcfg['type'] = "paravirtualised" +vtpmcfg['backend'] = "Domain-0" +vtpmcfg['instance'] = 1 +vtpmcfg['VM'] = vm_uuid - server, session = xapi._connect() +session = xapi.connect() - vtpm_uuid = xapi.execute(server.VTPM.create, session, vtpmcfg) +vtpm_uuid = session.xenapi.VTPM.create(vtpmcfg) - vtpm_id = xapi.execute(server.VTPM.get_instance, session, vtpm_uuid) - vtpm_be = xapi.execute(server.VTPM.get_backend , session, vtpm_uuid) - if vtpm_be != vtpmcfg['backend']: - FAIL("vTPM's backend is in '%s', expected: '%s'" % - (vtpm_be, vtpmcfg['backend'])) +vtpm_id = session.xenapi.VTPM.get_instance(vtpm_uuid) +vtpm_be = session.xenapi.VTPM.get_backend(vtpm_uuid) +if vtpm_be != vtpmcfg['backend']: + FAIL("vTPM's backend is in '%s', expected: '%s'" % + (vtpm_be, vtpmcfg['backend'])) - driver = xapi.execute(server.VTPM.get_driver, session, vtpm_uuid) - if driver != vtpmcfg['type']: - FAIL("vTPM has driver type '%s', expected: '%s'" % - (driver, vtpmcfg['type'])) +driver = session.xenapi.VTPM.get_driver(vtpm_uuid) +if driver != vtpmcfg['type']: + FAIL("vTPM has driver type '%s', expected: '%s'" % + (driver, vtpmcfg['type'])) - vtpm_rec = xapi.execute(server.VTPM.get_record, session, vtpm_uuid) +vtpm_rec = session.xenapi.VTPM.get_record(vtpm_uuid) - if vtpm_rec['driver'] != vtpmcfg['type']: - FAIL("vTPM record shows driver type '%s', expected: '%s'" % - (vtpm_rec['driver'], vtpmcfg['type'])) - if vtpm_rec['uuid'] != vtpm_uuid: - FAIL("vTPM record shows vtpm uuid '%s', expected: '%s'" % - (vtpm_rec['uuid'], vtpm_uuid)) - if vtpm_rec['VM'] != vm_uuid: - FAIL("vTPM record shows VM uuid '%s', expected: '%s'" % - (vtpm_rec['VM'], vm_uuid)) +if vtpm_rec['driver'] != vtpmcfg['type']: + FAIL("vTPM record shows driver type '%s', expected: '%s'" % + (vtpm_rec['driver'], vtpmcfg['type'])) +if vtpm_rec['uuid'] != vtpm_uuid: + FAIL("vTPM record shows vtpm uuid '%s', expected: '%s'" % + (vtpm_rec['uuid'], vtpm_uuid)) +if vtpm_rec['VM'] != vm_uuid: + FAIL("vTPM record shows VM uuid '%s', expected: '%s'" % + (vtpm_rec['VM'], vm_uuid)) - success = domain.start() +success = domain.start() - console = domain.getConsole() - - try: - run = console.runCmd("cat /sys/devices/xen/vtpm-0/pcrs") - except ConsoleError, e: - saveLog(console.getHistory()) - vtpm_cleanup(domName) - FAIL("No result from dumping the PCRs") - - if re.search("No such file",run["output"]): - vtpm_cleanup(domName) - FAIL("TPM frontend support not compiled into (domU?) kernel") - - domain.stop() - domain.destroy() - - +console = domain.getConsole() try: - do_test() -finally: - #Make sure all domains are gone that were created in this test case - xapi.vm_destroy_all() + run = console.runCmd("cat /sys/devices/xen/vtpm-0/pcrs") +except ConsoleError, e: + saveLog(console.getHistory()) + vtpm_cleanup(domName) + FAIL("No result from dumping the PCRs") + +if re.search("No such file",run["output"]): + vtpm_cleanup(domName) + FAIL("TPM frontend support not compiled into (domU?) kernel") + +domain.stop() +domain.destroy() diff -r c6b683ba68f5 -r a2b2b2a011f1 tools/xm-test/tests/xapi/01_xapi-vm_basic.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/xm-test/tests/xapi/01_xapi-vm_basic.py Mon Jan 15 15:15:26 2007 -0700 @@ -0,0 +1,61 @@ +#!/usr/bin/python + +# Copyright (C) International Business Machines Corp., 2006 +# Author: Stefan Berger <stefanb@xxxxxxxxxx> + +# Basic VM creation test + +from XmTestLib import xapi +from XmTestLib.XenAPIDomain import XmTestAPIDomain +from XmTestLib import * +from xen.xend import XendAPIConstants +import commands +import os + +try: + # XmTestAPIDomain tries to establish a connection to XenD + domain = XmTestAPIDomain() +except Exception, e: + SKIP("Skipping test. Error: %s" % str(e)) +vm_uuid = domain.get_uuid() + +session = xapi.connect() + +domain.start(startpaused=True) + +res = session.xenapi.VM.get_power_state(vm_uuid) + +if res != XendAPIConstants.XEN_API_VM_POWER_STATE[XendAPIConstants.XEN_API_VM_POWER_STATE_PAUSED]: + FAIL("VM was not started in 'paused' state") + +res = session.xenapi.VM.unpause(vm_uuid) + +res = session.xenapi.VM.get_power_state(vm_uuid) + +if res != XendAPIConstants.XEN_API_VM_POWER_STATE[XendAPIConstants.XEN_API_VM_POWER_STATE_RUNNING]: + FAIL("VM could not be put into 'running' state") + +console = domain.getConsole() + +try: + run = console.runCmd("cat /proc/interrupts") +except ConsoleError, e: + saveLog(console.getHistory()) + FAIL("Could not access proc-filesystem") + +res = session.xenapi.VM.pause(vm_uuid) + +res = session.xenapi.VM.get_power_state(vm_uuid) + +if res != XendAPIConstants.XEN_API_VM_POWER_STATE[XendAPIConstants.XEN_API_VM_POWER_STATE_PAUSED]: + FAIL("VM could not be put into 'paused' state") + +res = session.xenapi.VM.unpause(vm_uuid) + +res = session.xenapi.VM.get_power_state(vm_uuid) + +if res != XendAPIConstants.XEN_API_VM_POWER_STATE[XendAPIConstants.XEN_API_VM_POWER_STATE_RUNNING]: + FAIL("VM could not be 'unpaused'") + +domain.stop() +domain.destroy() diff -r c6b683ba68f5 -r a2b2b2a011f1 tools/xm-test/tests/xapi/Makefile.am --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/xm-test/tests/xapi/Makefile.am Mon Jan 15 15:15:26 2007 -0700 @@ -0,0 +1,19 @@ +SUBDIRS = + +TESTS = 01_xapi-vm_basic.test + +XFAIL_TESTS = + +EXTRA_DIST = $(TESTS) $(XFAIL_TESTS) xapi_utils.py +TESTS_ENVIRONMENT=@TENV@ + +%.test: %.py + cp $< $@ + chmod +x $@ + +clean-local: am_config_clean-local + +am_config_clean-local: + rm -f *test + rm -f *log + rm -f *~ diff -r c6b683ba68f5 -r a2b2b2a011f1 unmodified_drivers/linux-2.6/platform-pci/platform-pci.c --- a/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c Sun Jan 14 22:18:38 2007 -0700 +++ b/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c Mon Jan 15 15:15:26 2007 -0700 @@ -179,7 +179,7 @@ static int get_hypercall_stubs(void) #define get_hypercall_stubs() (0) #endif -static int get_callback_irq(struct pci_dev *pdev) +static uint64_t get_callback_via(struct pci_dev *pdev) { #ifdef __ia64__ int irq, rid; @@ -194,16 +194,24 @@ static int get_callback_irq(struct pci_d rid); return rid | IA64_CALLBACK_IRQ_RID; #else /* !__ia64__ */ - return pdev->irq; + if (pdev->irq < 16) + return pdev->irq; /* ISA IRQ */ + /* We don't know the GSI. Specify the PCI INTx line instead. */ + return (((uint64_t)0x01 << 56) | /* PCI INTx identifier */ + ((uint64_t)pci_domain_nr(pdev->bus) << 32) | + ((uint64_t)pdev->bus->number << 16) | + ((uint64_t)(pdev->devfn & 0xff) << 8) | + ((uint64_t)(pdev->pin - 1) & 3)); #endif } static int __devinit platform_pci_init(struct pci_dev *pdev, const struct pci_device_id *ent) { - int i, ret, callback_irq; + int i, ret; long ioaddr, iolen; long mmio_addr, mmio_len; + uint64_t callback_via; i = pci_enable_device(pdev); if (i) @@ -215,9 +223,9 @@ static int __devinit platform_pci_init(s mmio_addr = pci_resource_start(pdev, 1); mmio_len = pci_resource_len(pdev, 1); - callback_irq = get_callback_irq(pdev); - - if (mmio_addr == 0 || ioaddr == 0 || callback_irq == 0) { + callback_via = get_callback_via(pdev); + + if (mmio_addr == 0 || ioaddr == 0 || callback_via == 0) { printk(KERN_WARNING DRV_NAME ":no resources found\n"); return -ENOENT; } @@ -247,12 +255,12 @@ static int __devinit platform_pci_init(s if ((ret = init_xen_info())) goto out; - if ((ret = request_irq(pdev->irq, evtchn_interrupt, SA_SHIRQ, - "xen-platform-pci", pdev))) { - goto out; - } - - if ((ret = set_callback_irq(callback_irq))) + if ((ret = request_irq(pdev->irq, evtchn_interrupt, + SA_SHIRQ | SA_SAMPLE_RANDOM, + "xen-platform-pci", pdev))) + goto out; + + if ((ret = set_callback_via(callback_via))) goto out; out: @@ -302,7 +310,7 @@ static void __exit platform_pci_module_c { printk(KERN_INFO DRV_NAME ":Do platform module cleanup\n"); /* disable hypervisor for callback irq */ - set_callback_irq(0); + set_callback_via(0); if (pci_device_registered) pci_unregister_driver(&platform_driver); } diff -r c6b683ba68f5 -r a2b2b2a011f1 unmodified_drivers/linux-2.6/platform-pci/platform-pci.h --- a/unmodified_drivers/linux-2.6/platform-pci/platform-pci.h Sun Jan 14 22:18:38 2007 -0700 +++ b/unmodified_drivers/linux-2.6/platform-pci/platform-pci.h Mon Jan 15 15:15:26 2007 -0700 @@ -24,13 +24,13 @@ #include <linux/interrupt.h> #include <xen/interface/hvm/params.h> -static inline int set_callback_irq(int irq) +static inline int set_callback_via(uint64_t via) { struct xen_hvm_param a; a.domid = DOMID_SELF; a.index = HVM_PARAM_CALLBACK_IRQ; - a.value = irq; + a.value = via; return HYPERVISOR_hvm_op(HVMOP_set_param, &a); } diff -r c6b683ba68f5 -r a2b2b2a011f1 xen/arch/ia64/linux-xen/unaligned.c --- a/xen/arch/ia64/linux-xen/unaligned.c Sun Jan 14 22:18:38 2007 -0700 +++ b/xen/arch/ia64/linux-xen/unaligned.c Mon Jan 15 15:15:26 2007 -0700 @@ -24,7 +24,7 @@ #include <asm/uaccess.h> #include <asm/unaligned.h> -extern void die_if_kernel(char *str, struct pt_regs *regs, long err) __attribute__ ((noreturn)); +extern void die_if_kernel(char *str, struct pt_regs *regs, long err); #undef DEBUG_UNALIGNED_TRAP diff -r c6b683ba68f5 -r a2b2b2a011f1 xen/arch/ia64/xen/xenmisc.c --- a/xen/arch/ia64/xen/xenmisc.c Sun Jan 14 22:18:38 2007 -0700 +++ b/xen/arch/ia64/xen/xenmisc.c Mon Jan 15 15:15:26 2007 -0700 @@ -77,7 +77,7 @@ void console_print(char *msg) // called from unaligned.c //////////////////////////////////// -void die_if_kernel(char *str, struct pt_regs *regs, long err) /* __attribute__ ((noreturn)) */ +void die_if_kernel(char *str, struct pt_regs *regs, long err) { if (user_mode(regs)) return; @@ -88,7 +88,7 @@ void die_if_kernel(char *str, struct pt_ domain_crash_synchronous(); } -void vmx_die_if_kernel(char *str, struct pt_regs *regs, long err) /* __attribute__ ((noreturn)) */ +void vmx_die_if_kernel(char *str, struct pt_regs *regs, long err) { if (vmx_user_mode(regs)) return; diff -r c6b683ba68f5 -r a2b2b2a011f1 xen/arch/x86/domain.c --- a/xen/arch/x86/domain.c Sun Jan 14 22:18:38 2007 -0700 +++ b/xen/arch/x86/domain.c Mon Jan 15 15:15:26 2007 -0700 @@ -1047,7 +1047,7 @@ void context_switch(struct vcpu *prev, s local_irq_disable(); - if ( is_hvm_vcpu(prev) ) + if ( is_hvm_vcpu(prev) && !list_empty(&prev->arch.hvm_vcpu.tm_list) ) pt_freeze_time(prev); set_current(next); diff -r c6b683ba68f5 -r a2b2b2a011f1 xen/arch/x86/hvm/hpet.c --- a/xen/arch/x86/hvm/hpet.c Sun Jan 14 22:18:38 2007 -0700 +++ b/xen/arch/x86/hvm/hpet.c Mon Jan 15 15:15:26 2007 -0700 @@ -356,8 +356,6 @@ static void hpet_timer_fn(void *opaque) } set_timer(&h->timers[tn], NOW() + hpet_tick_to_ns(h, h->period[tn])); } - - vcpu_kick(h->vcpu); } void hpet_migrate_timers(struct vcpu *v) diff -r c6b683ba68f5 -r a2b2b2a011f1 xen/arch/x86/hvm/hvm.c --- a/xen/arch/x86/hvm/hvm.c Sun Jan 14 22:18:38 2007 -0700 +++ b/xen/arch/x86/hvm/hvm.c Mon Jan 15 15:15:26 2007 -0700 @@ -800,7 +800,7 @@ long do_hvm_op(unsigned long op, XEN_GUE d->arch.hvm_domain.buffered_io_va = (unsigned long)p; break; case HVM_PARAM_CALLBACK_IRQ: - hvm_set_callback_gsi(d, a.value); + hvm_set_callback_via(d, a.value); break; } d->arch.hvm_domain.params[a.index] = a.value; diff -r c6b683ba68f5 -r a2b2b2a011f1 xen/arch/x86/hvm/irq.c --- a/xen/arch/x86/hvm/irq.c Sun Jan 14 22:18:38 2007 -0700 +++ b/xen/arch/x86/hvm/irq.c Mon Jan 15 15:15:26 2007 -0700 @@ -25,7 +25,7 @@ #include <xen/sched.h> #include <asm/hvm/domain.h> -void hvm_pci_intx_assert( +static void __hvm_pci_intx_assert( struct domain *d, unsigned int device, unsigned int intx) { struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq; @@ -33,10 +33,8 @@ void hvm_pci_intx_assert( ASSERT((device <= 31) && (intx <= 3)); - spin_lock(&hvm_irq->lock); - if ( __test_and_set_bit(device*4 + intx, &hvm_irq->pci_intx) ) - goto out; + return; gsi = hvm_pci_intx_gsi(device, intx); if ( hvm_irq->gsi_assert_count[gsi]++ == 0 ) @@ -50,12 +48,19 @@ void hvm_pci_intx_assert( vioapic_irq_positive_edge(d, isa_irq); vpic_irq_positive_edge(d, isa_irq); } - - out: - spin_unlock(&hvm_irq->lock); -} - -void hvm_pci_intx_deassert( +} + +void hvm_pci_intx_assert( + struct domain *d, unsigned int device, unsigned int intx) +{ + struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq; + + spin_lock(&hvm_irq->lock); + __hvm_pci_intx_assert(d, device, intx); + spin_unlock(&hvm_irq->lock); +} + +static void __hvm_pci_intx_deassert( struct domain *d, unsigned int device, unsigned int intx) { struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq; @@ -63,10 +68,8 @@ void hvm_pci_intx_deassert( ASSERT((device <= 31) && (intx <= 3)); - spin_lock(&hvm_irq->lock); - if ( !__test_and_clear_bit(device*4 + intx, &hvm_irq->pci_intx) ) - goto out; + return; gsi = hvm_pci_intx_gsi(device, intx); --hvm_irq->gsi_assert_count[gsi]; @@ -76,8 +79,15 @@ void hvm_pci_intx_deassert( if ( (--hvm_irq->pci_link_assert_count[link] == 0) && isa_irq && (--hvm_irq->gsi_assert_count[isa_irq] == 0) ) vpic_irq_negative_edge(d, isa_irq); - - out: +} + +void hvm_pci_intx_deassert( + struct domain *d, unsigned int device, unsigned int intx) +{ + struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq; + + spin_lock(&hvm_irq->lock); + __hvm_pci_intx_deassert(d, device, intx); spin_unlock(&hvm_irq->lock); } @@ -123,37 +133,47 @@ void hvm_set_callback_irq_level(void) struct vcpu *v = current; struct domain *d = v->domain; struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq; - unsigned int gsi = hvm_irq->callback_gsi; + unsigned int gsi, pdev, pintx, asserted; /* Fast lock-free tests. */ - if ( (v->vcpu_id != 0) || (gsi == 0) ) + if ( (v->vcpu_id != 0) || + (hvm_irq->callback_via_type == HVMIRQ_callback_none) ) return; spin_lock(&hvm_irq->lock); - gsi = hvm_irq->callback_gsi; - if ( gsi == 0 ) + /* NB. Do not check the evtchn_upcall_mask. It is not used in HVM mode. */ + asserted = !!vcpu_info(v, evtchn_upcall_pending); + if ( hvm_irq->callback_via_asserted == asserted ) goto out; - - /* NB. Do not check the evtchn_upcall_mask. It is not used in HVM mode. */ - if ( vcpu_info(v, evtchn_upcall_pending) ) - { - if ( !__test_and_set_bit(0, &hvm_irq->callback_irq_wire) && - (hvm_irq->gsi_assert_count[gsi]++ == 0) ) + hvm_irq->callback_via_asserted = asserted; + + /* Callback status has changed. Update the callback via. */ + switch ( hvm_irq->callback_via_type ) + { + case HVMIRQ_callback_gsi: + gsi = hvm_irq->callback_via.gsi; + if ( asserted && (hvm_irq->gsi_assert_count[gsi]++ == 0) ) { vioapic_irq_positive_edge(d, gsi); if ( gsi <= 15 ) vpic_irq_positive_edge(d, gsi); } - } - else - { - if ( __test_and_clear_bit(0, &hvm_irq->callback_irq_wire) && - (--hvm_irq->gsi_assert_count[gsi] == 0) ) + else if ( !asserted && (--hvm_irq->gsi_assert_count[gsi] == 0) ) { if ( gsi <= 15 ) vpic_irq_negative_edge(d, gsi); } + break; + case HVMIRQ_callback_pci_intx: + pdev = hvm_irq->callback_via.pci.dev; + pintx = hvm_irq->callback_via.pci.intx; + if ( asserted ) + __hvm_pci_intx_assert(d, pdev, pintx); + else + __hvm_pci_intx_deassert(d, pdev, pintx); + default: + break; } out: @@ -193,40 +213,79 @@ void hvm_set_pci_link_route(struct domai d->domain_id, link, old_isa_irq, isa_irq); } -void hvm_set_callback_gsi(struct domain *d, unsigned int gsi) -{ - struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq; - unsigned int old_gsi; - - if ( gsi >= ARRAY_SIZE(hvm_irq->gsi_assert_count) ) - gsi = 0; - - spin_lock(&hvm_irq->lock); - - old_gsi = hvm_irq->callback_gsi; - if ( old_gsi == gsi ) - goto out; - hvm_irq->callback_gsi = gsi; - - if ( !test_bit(0, &hvm_irq->callback_irq_wire) ) - goto out; - - if ( old_gsi && (--hvm_irq->gsi_assert_count[old_gsi] == 0) ) - if ( old_gsi <= 15 ) - vpic_irq_negative_edge(d, old_gsi); - - if ( gsi && (hvm_irq->gsi_assert_count[gsi]++ == 0) ) - { - vioapic_irq_positive_edge(d, gsi); - if ( gsi <= 15 ) - vpic_irq_positive_edge(d, gsi); - } - - out: - spin_unlock(&hvm_irq->lock); - - dprintk(XENLOG_G_INFO, "Dom%u callback GSI changed %u -> %u\n", - d->domain_id, old_gsi, gsi); +void hvm_set_callback_via(struct domain *d, uint64_t via) +{ + struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq; + unsigned int gsi=0, pdev=0, pintx=0; + uint8_t via_type; + + via_type = (uint8_t)(via >> 56) + 1; + if ( ((via_type == HVMIRQ_callback_gsi) && (via == 0)) || + (via_type > HVMIRQ_callback_pci_intx) ) + via_type = HVMIRQ_callback_none; + + spin_lock(&hvm_irq->lock); + + /* Tear down old callback via. */ + if ( hvm_irq->callback_via_asserted ) + { + switch ( hvm_irq->callback_via_type ) + { + case HVMIRQ_callback_gsi: + gsi = hvm_irq->callback_via.gsi; + if ( (--hvm_irq->gsi_assert_count[gsi] == 0) && (gsi <= 15) ) + vpic_irq_negative_edge(d, gsi); + break; + case HVMIRQ_callback_pci_intx: + pdev = hvm_irq->callback_via.pci.dev; + pintx = hvm_irq->callback_via.pci.intx; + __hvm_pci_intx_deassert(d, pdev, pintx); + break; + default: + break; + } + } + + /* Set up new callback via. */ + switch ( hvm_irq->callback_via_type = via_type ) + { + case HVMIRQ_callback_gsi: + gsi = hvm_irq->callback_via.gsi = (uint8_t)via; + if ( (gsi == 0) || (gsi >= ARRAY_SIZE(hvm_irq->gsi_assert_count)) ) + hvm_irq->callback_via_type = HVMIRQ_callback_none; + else if ( hvm_irq->callback_via_asserted && + (hvm_irq->gsi_assert_count[gsi]++ == 0) ) + { + vioapic_irq_positive_edge(d, gsi); + if ( gsi <= 15 ) + vpic_irq_positive_edge(d, gsi); + } + break; + case HVMIRQ_callback_pci_intx: + pdev = hvm_irq->callback_via.pci.dev = (uint8_t)(via >> 11) & 31; + pintx = hvm_irq->callback_via.pci.intx = (uint8_t)via & 3; + if ( hvm_irq->callback_via_asserted ) + __hvm_pci_intx_assert(d, pdev, pintx); + break; + default: + break; + } + + spin_unlock(&hvm_irq->lock); + + dprintk(XENLOG_G_INFO, "Dom%u callback via changed to ", d->domain_id); + switch ( via_type ) + { + case HVMIRQ_callback_gsi: + printk("GSI %u\n", gsi); + break; + case HVMIRQ_callback_pci_intx: + printk("PCI INTx Dev 0x%02x Int%c\n", pdev, 'A' + pintx); + break; + default: + printk("None\n"); + break; + } } int cpu_has_pending_irq(struct vcpu *v) diff -r c6b683ba68f5 -r a2b2b2a011f1 xen/arch/x86/hvm/vioapic.c --- a/xen/arch/x86/hvm/vioapic.c Sun Jan 14 22:18:38 2007 -0700 +++ b/xen/arch/x86/hvm/vioapic.c Mon Jan 15 15:15:26 2007 -0700 @@ -309,6 +309,13 @@ static uint32_t ioapic_get_delivery_bitm return mask; } +static inline int pit_channel0_enabled(void) +{ + PITState *pit = ¤t->domain->arch.hvm_domain.pl_time.vpit; + struct periodic_time *pt = &pit->channels[0].pt; + return pt->enabled; +} + static void vioapic_deliver(struct vioapic *vioapic, int irq) { uint16_t dest = vioapic->redirtbl[irq].fields.dest_id; @@ -341,7 +348,7 @@ static void vioapic_deliver(struct vioap { #ifdef IRQ0_SPECIAL_ROUTING /* Force round-robin to pick VCPU 0 */ - if ( irq == hvm_isa_irq_to_gsi(0) ) + if ( (irq == hvm_isa_irq_to_gsi(0)) && pit_channel0_enabled() ) { v = vioapic_domain(vioapic)->vcpu[0]; target = v ? vcpu_vlapic(v) : NULL; @@ -374,7 +381,7 @@ static void vioapic_deliver(struct vioap deliver_bitmask &= ~(1 << bit); #ifdef IRQ0_SPECIAL_ROUTING /* Do not deliver timer interrupts to VCPU != 0 */ - if ( irq == hvm_isa_irq_to_gsi(0) ) + if ( (irq == hvm_isa_irq_to_gsi(0)) && pit_channel0_enabled() ) v = vioapic_domain(vioapic)->vcpu[0]; else #endif diff -r c6b683ba68f5 -r a2b2b2a011f1 xen/arch/x86/hvm/vmx/vmcs.c --- a/xen/arch/x86/hvm/vmx/vmcs.c Sun Jan 14 22:18:38 2007 -0700 +++ b/xen/arch/x86/hvm/vmx/vmcs.c Mon Jan 15 15:15:26 2007 -0700 @@ -278,7 +278,14 @@ static void vmx_set_host_env(struct vcpu host_env.tr_base = (unsigned long) &init_tss[cpu]; __vmwrite(HOST_TR_SELECTOR, host_env.tr_selector); __vmwrite(HOST_TR_BASE, host_env.tr_base); - __vmwrite(HOST_RSP, (unsigned long)get_stack_bottom()); + + /* + * Skip end of cpu_user_regs when entering the hypervisor because the + * CPU does not save context onto the stack. SS,RSP,CS,RIP,RFLAGS,etc + * all get saved into the VMCS instead. + */ + __vmwrite(HOST_RSP, + (unsigned long)&get_cpu_info()->guest_cpu_user_regs.error_code); } static void construct_vmcs(struct vcpu *v) diff -r c6b683ba68f5 -r a2b2b2a011f1 xen/arch/x86/hvm/vmx/vmx.c --- a/xen/arch/x86/hvm/vmx/vmx.c Sun Jan 14 22:18:38 2007 -0700 +++ b/xen/arch/x86/hvm/vmx/vmx.c Mon Jan 15 15:15:26 2007 -0700 @@ -410,10 +410,6 @@ static void vmx_store_cpu_guest_regs( regs->eflags = __vmread(GUEST_RFLAGS); regs->ss = __vmread(GUEST_SS_SELECTOR); regs->cs = __vmread(GUEST_CS_SELECTOR); - regs->ds = __vmread(GUEST_DS_SELECTOR); - regs->es = __vmread(GUEST_ES_SELECTOR); - regs->gs = __vmread(GUEST_GS_SELECTOR); - regs->fs = __vmread(GUEST_FS_SELECTOR); regs->eip = __vmread(GUEST_RIP); regs->esp = __vmread(GUEST_RSP); } @@ -429,62 +425,39 @@ static void vmx_store_cpu_guest_regs( vmx_vmcs_exit(v); } -/* - * The VMX spec (section 4.3.1.2, Checks on Guest Segment - * Registers) says that virtual-8086 mode guests' segment - * base-address fields in the VMCS must be equal to their - * corresponding segment selector field shifted right by - * four bits upon vmentry. - * - * This function (called only for VM86-mode guests) fixes - * the bases to be consistent with the selectors in regs - * if they're not already. Without this, we can fail the - * vmentry check mentioned above. - */ -static void fixup_vm86_seg_bases(struct cpu_user_regs *regs) +static void vmx_load_cpu_guest_regs(struct vcpu *v, struct cpu_user_regs *regs) { unsigned long base; - base = __vmread(GUEST_ES_BASE); - if (regs->es << 4 != base) - __vmwrite(GUEST_ES_BASE, regs->es << 4); - base = __vmread(GUEST_CS_BASE); - if (regs->cs << 4 != base) - __vmwrite(GUEST_CS_BASE, regs->cs << 4); - base = __vmread(GUEST_SS_BASE); - if (regs->ss << 4 != base) - __vmwrite(GUEST_SS_BASE, regs->ss << 4); - base = __vmread(GUEST_DS_BASE); - if (regs->ds << 4 != base) - __vmwrite(GUEST_DS_BASE, regs->ds << 4); - base = __vmread(GUEST_FS_BASE); - if (regs->fs << 4 != base) - __vmwrite(GUEST_FS_BASE, regs->fs << 4); - base = __vmread(GUEST_GS_BASE); - if (regs->gs << 4 != base) - __vmwrite(GUEST_GS_BASE, regs->gs << 4); -} - -static void vmx_load_cpu_guest_regs(struct vcpu *v, struct cpu_user_regs *regs) -{ vmx_vmcs_enter(v); __vmwrite(GUEST_SS_SELECTOR, regs->ss); - __vmwrite(GUEST_DS_SELECTOR, regs->ds); - __vmwrite(GUEST_ES_SELECTOR, regs->es); - __vmwrite(GUEST_GS_SELECTOR, regs->gs); - __vmwrite(GUEST_FS_SELECTOR, regs->fs); - __vmwrite(GUEST_RSP, regs->esp); /* NB. Bit 1 of RFLAGS must be set for VMENTRY to succeed. */ __vmwrite(GUEST_RFLAGS, regs->eflags | 2UL); - if (regs->eflags & EF_TF) + + if ( regs->eflags & EF_TF ) __vm_set_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB); else __vm_clear_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB); - if (regs->eflags & EF_VM) - fixup_vm86_seg_bases(regs); + + if ( regs->eflags & EF_VM ) + { + /* + * The VMX spec (section 4.3.1.2, Checks on Guest Segment + * Registers) says that virtual-8086 mode guests' segment + * base-address fields in the VMCS must be equal to their + * corresponding segment selector field shifted right by + * four bits upon vmentry. + */ + base = __vmread(GUEST_CS_BASE); + if ( (regs->cs << 4) != base ) + __vmwrite(GUEST_CS_BASE, regs->cs << 4); + base = __vmread(GUEST_SS_BASE); + if ( (regs->ss << 4) != base ) + __vmwrite(GUEST_SS_BASE, regs->ss << 4); + } __vmwrite(GUEST_CS_SELECTOR, regs->cs); __vmwrite(GUEST_RIP, regs->eip); @@ -2251,47 +2224,54 @@ static void vmx_reflect_exception(struct } } +static void vmx_failed_vmentry(unsigned int exit_reason) +{ + unsigned int failed_vmentry_reason = (uint16_t)exit_reason; + unsigned long exit_qualification; + + exit_qualification = __vmread(EXIT_QUALIFICATION); + printk("Failed vm entry (exit reason 0x%x) ", exit_reason); + switch ( failed_vmentry_reason ) + { + case EXIT_REASON_INVALID_GUEST_STATE: + printk("caused by invalid guest state (%ld).\n", exit_qualification); + break; + case EXIT_REASON_MSR_LOADING: + printk("caused by MSR entry %ld loading.\n", exit_qualification); + break; + case EXIT_REASON_MACHINE_CHECK: + printk("caused by machine check.\n"); + break; + default: + printk("reason not known yet!"); + break; + } + + printk("************* VMCS Area **************\n"); + vmcs_dump_vcpu(); + printk("**************************************\n"); + + domain_crash(current->domain); +} + asmlinkage void vmx_vmexit_handler(struct cpu_user_regs *regs) { unsigned int exit_reason; unsigned long exit_qualification, inst_len = 0; struct vcpu *v = current; + TRACE_3D(TRC_VMX_VMEXIT + v->vcpu_id, 0, 0, 0); + exit_reason = __vmread(VM_EXIT_REASON); perfc_incra(vmexits, exit_reason); + TRACE_VMEXIT(0, exit_reason); if ( exit_reason != EXIT_REASON_EXTERNAL_INTERRUPT ) local_irq_enable(); if ( unlikely(exit_reason & VMX_EXIT_REASONS_FAILED_VMENTRY) ) - { - unsigned int failed_vmentry_reason = exit_reason & 0xFFFF; - - exit_qualification = __vmread(EXIT_QUALIFICATION); - printk("Failed vm entry (exit reason 0x%x) ", exit_reason); - switch ( failed_vmentry_reason ) { - case EXIT_REASON_INVALID_GUEST_STATE: - printk("caused by invalid guest state (%ld).\n", exit_qualification); - break; - case EXIT_REASON_MSR_LOADING: - printk("caused by MSR entry %ld loading.\n", exit_qualification); - break; - case EXIT_REASON_MACHINE_CHECK: - printk("caused by machine check.\n"); - break; - default: - printk("reason not known yet!"); - break; - } - - printk("************* VMCS Area **************\n"); - vmcs_dump_vcpu(); - printk("**************************************\n"); - goto exit_and_crash; - } - - TRACE_VMEXIT(0, exit_reason); + return vmx_failed_vmentry(exit_reason); switch ( exit_reason ) { @@ -2519,11 +2499,6 @@ asmlinkage void vmx_trace_vmentry(void) TRACE_VMEXIT(4, 0); } -asmlinkage void vmx_trace_vmexit (void) -{ - TRACE_3D(TRC_VMX_VMEXIT + current->vcpu_id, 0, 0, 0); -} - /* * Local variables: * mode: C diff -r c6b683ba68f5 -r a2b2b2a011f1 xen/arch/x86/hvm/vmx/x86_32/exits.S --- a/xen/arch/x86/hvm/vmx/x86_32/exits.S Sun Jan 14 22:18:38 2007 -0700 +++ b/xen/arch/x86/hvm/vmx/x86_32/exits.S Mon Jan 15 15:15:26 2007 -0700 @@ -29,35 +29,7 @@ andl $~3,reg; \ movl (reg),reg; -/* - * At VMExit time the processor saves the guest selectors, esp, eip, - * and eflags. Therefore we don't save them, but simply decrement - * the kernel stack pointer to make it consistent with the stack frame - * at usual interruption time. The eflags of the host is not saved by VMX, - * and we set it to the fixed value. - * - * We also need the room, especially because orig_eax field is used - * by do_IRQ(). Compared the cpu_user_regs, we skip pushing for the following: - * (10) u32 gs; - * (9) u32 fs; - * (8) u32 ds; - * (7) u32 es; - * <- get_stack_bottom() (= HOST_ESP) - * (6) u32 ss; - * (5) u32 esp; - * (4) u32 eflags; - * (3) u32 cs; - * (2) u32 eip; - * (2/1) u16 entry_vector; - * (1/1) u16 error_code; - * However, get_stack_bottom() actually returns 20 bytes before the real - * bottom of the stack to allow space for: - * domain pointer, DS, ES, FS, GS. Therefore, we effectively skip 6 registers. - */ - -#define NR_SKIPPED_REGS 6 /* See the above explanation */ #define HVM_SAVE_ALL_NOSEGREGS \ - subl $(NR_SKIPPED_REGS*4), %esp; \ movl $0, 0xc(%esp); /* XXX why do we need to force eflags==0 ?? */ \ pushl %eax; \ pushl %ebp; \ @@ -74,14 +46,11 @@ popl %esi; \ popl %edi; \ popl %ebp; \ - popl %eax; \ - addl $(NR_SKIPPED_REGS*4), %esp + popl %eax ALIGN ENTRY(vmx_asm_vmexit_handler) - /* selectors are restored/saved by VMX */ HVM_SAVE_ALL_NOSEGREGS - call vmx_trace_vmexit movl %esp,%eax push %eax call vmx_vmexit_handler diff -r c6b683ba68f5 -r a2b2b2a011f1 xen/arch/x86/hvm/vmx/x86_64/exits.S --- a/xen/arch/x86/hvm/vmx/x86_64/exits.S Sun Jan 14 22:18:38 2007 -0700 +++ b/xen/arch/x86/hvm/vmx/x86_64/exits.S Mon Jan 15 15:15:26 2007 -0700 @@ -29,31 +29,7 @@ andq $~7,reg; \ movq (reg),reg; -/* - * At VMExit time the processor saves the guest selectors, rsp, rip, - * and rflags. Therefore we don't save them, but simply decrement - * the kernel stack pointer to make it consistent with the stack frame - * at usual interruption time. The rflags of the host is not saved by VMX, - * and we set it to the fixed value. - * - * We also need the room, especially because orig_eax field is used - * by do_IRQ(). Compared the cpu_user_regs, we skip pushing for the following: - * (10) u64 gs; - * (9) u64 fs; - * (8) u64 ds; - * (7) u64 es; - * <- get_stack_bottom() (= HOST_ESP) - * (6) u64 ss; - * (5) u64 rsp; - * (4) u64 rflags; - * (3) u64 cs; - * (2) u64 rip; - * (2/1) u32 entry_vector; - * (1/1) u32 error_code; - */ -#define NR_SKIPPED_REGS 6 /* See the above explanation */ #define HVM_SAVE_ALL_NOSEGREGS \ - subq $(NR_SKIPPED_REGS*8), %rsp; \ pushq %rdi; \ pushq %rsi; \ pushq %rdx; \ @@ -85,14 +61,11 @@ popq %rcx; \ popq %rdx; \ popq %rsi; \ - popq %rdi; \ - addq $(NR_SKIPPED_REGS*8), %rsp; + popq %rdi ALIGN ENTRY(vmx_asm_vmexit_handler) - /* selectors are restored/saved by VMX */ HVM_SAVE_ALL_NOSEGREGS - call vmx_trace_vmexit movq %rsp,%rdi call vmx_vmexit_handler jmp vmx_asm_do_vmentry diff -r c6b683ba68f5 -r a2b2b2a011f1 xen/arch/x86/mm.c --- a/xen/arch/x86/mm.c Sun Jan 14 22:18:38 2007 -0700 +++ b/xen/arch/x86/mm.c Mon Jan 15 15:15:26 2007 -0700 @@ -826,7 +826,7 @@ static void put_page_from_l2e(l2_pgentry { if ( (l2e_get_flags(l2e) & _PAGE_PRESENT) && (l2e_get_pfn(l2e) != pfn) ) - put_page_and_type(mfn_to_page(l2e_get_pfn(l2e))); + put_page_and_type(l2e_get_page(l2e)); } @@ -835,7 +835,7 @@ static void put_page_from_l3e(l3_pgentry { if ( (l3e_get_flags(l3e) & _PAGE_PRESENT) && (l3e_get_pfn(l3e) != pfn) ) - put_page_and_type(mfn_to_page(l3e_get_pfn(l3e))); + put_page_and_type(l3e_get_page(l3e)); } #endif @@ -844,7 +844,7 @@ static void put_page_from_l4e(l4_pgentry { if ( (l4e_get_flags(l4e) & _PAGE_PRESENT) && (l4e_get_pfn(l4e) != pfn) ) - put_page_and_type(mfn_to_page(l4e_get_pfn(l4e))); + put_page_and_type(l4e_get_page(l4e)); } #endif @@ -1376,7 +1376,7 @@ static int mod_l2_entry(l2_pgentry_t *pl if ( !l2e_has_changed(ol2e, nl2e, _PAGE_PRESENT)) return UPDATE_ENTRY(l2, pl2e, ol2e, nl2e, pfn, current); - if ( unlikely(!get_page_from_l2e(nl2e, pfn, current->domain)) ) + if ( unlikely(!get_page_from_l2e(nl2e, pfn, d)) ) return 0; if ( unlikely(!UPDATE_ENTRY(l2, pl2e, ol2e, nl2e, pfn, current)) ) @@ -1439,7 +1439,7 @@ static int mod_l3_entry(l3_pgentry_t *pl if (!l3e_has_changed(ol3e, nl3e, _PAGE_PRESENT)) return UPDATE_ENTRY(l3, pl3e, ol3e, nl3e, pfn, current); - if ( unlikely(!get_page_from_l3e(nl3e, pfn, current->domain)) ) + if ( unlikely(!get_page_from_l3e(nl3e, pfn, d)) ) return 0; if ( unlikely(!UPDATE_ENTRY(l3, pl3e, ol3e, nl3e, pfn, current)) ) @@ -3182,7 +3182,7 @@ static int ptwr_emulated_update( unsigned int do_cmpxchg, struct ptwr_emulate_ctxt *ptwr_ctxt) { - unsigned long gmfn, mfn; + unsigned long mfn; struct page_info *page; l1_pgentry_t pte, ol1e, nl1e, *pl1e; struct vcpu *v = current; @@ -3222,8 +3222,7 @@ static int ptwr_emulated_update( } pte = ptwr_ctxt->pte; - gmfn = l1e_get_pfn(pte); - mfn = gmfn_to_mfn(d, gmfn); + mfn = l1e_get_pfn(pte); page = mfn_to_page(mfn); /* We are looking only for read-only mappings of p.t. pages. */ @@ -3354,7 +3353,6 @@ int ptwr_do_page_fault(struct vcpu *v, u struct cpu_user_regs *regs) { struct domain *d = v->domain; - unsigned long pfn; struct page_info *page; l1_pgentry_t pte; struct ptwr_emulate_ctxt ptwr_ctxt; @@ -3368,8 +3366,7 @@ int ptwr_do_page_fault(struct vcpu *v, u guest_get_eff_l1e(v, addr, &pte); if ( !(l1e_get_flags(pte) & _PAGE_PRESENT) ) goto bail; - pfn = l1e_get_pfn(pte); - page = mfn_to_page(pfn); + page = l1e_get_page(pte); /* We are looking only for read-only mappings of p.t. pages. */ if ( ((l1e_get_flags(pte) & (_PAGE_PRESENT|_PAGE_RW)) != _PAGE_PRESENT) || diff -r c6b683ba68f5 -r a2b2b2a011f1 xen/arch/x86/mm/shadow/common.c --- a/xen/arch/x86/mm/shadow/common.c Sun Jan 14 22:18:38 2007 -0700 +++ b/xen/arch/x86/mm/shadow/common.c Mon Jan 15 15:15:26 2007 -0700 @@ -1303,6 +1303,9 @@ shadow_alloc_p2m_table(struct domain *d) if ( !shadow_set_p2m_entry(d, gfn, mfn) ) goto error; + /* Build a p2m map that matches the m2p entries for this domain's + * allocated pages. Skip any pages that have an explicitly invalid + * or obviously bogus m2p entry. */ for ( entry = d->page_list.next; entry != &d->page_list; entry = entry->next ) @@ -1318,6 +1321,8 @@ shadow_alloc_p2m_table(struct domain *d) (gfn != 0x55555555L) #endif && gfn != INVALID_M2P_ENTRY + && (gfn < + (RO_MPT_VIRT_END - RO_MPT_VIRT_START) / sizeof (l1_pgentry_t)) && !shadow_set_p2m_entry(d, gfn, mfn) ) goto error; } diff -r c6b683ba68f5 -r a2b2b2a011f1 xen/arch/x86/oprofile/nmi_int.c --- a/xen/arch/x86/oprofile/nmi_int.c Sun Jan 14 22:18:38 2007 -0700 +++ b/xen/arch/x86/oprofile/nmi_int.c Mon Jan 15 15:15:26 2007 -0700 @@ -42,7 +42,7 @@ extern size_t strlcpy(char *dest, const extern size_t strlcpy(char *dest, const char *src, size_t size); -int nmi_callback(struct cpu_user_regs *regs, int cpu) +static int nmi_callback(struct cpu_user_regs *regs, int cpu) { int xen_mode, ovf; diff -r c6b683ba68f5 -r a2b2b2a011f1 xen/arch/x86/setup.c --- a/xen/arch/x86/setup.c Sun Jan 14 22:18:38 2007 -0700 +++ b/xen/arch/x86/setup.c Mon Jan 15 15:15:26 2007 -0700 @@ -411,6 +411,23 @@ void __init __start_xen(multiboot_info_t printk("WARNING: Buggy e820 map detected and fixed " "(truncated length fields).\n"); + /* Ensure that all E820 RAM regions are page-aligned and -sized. */ + for ( i = 0; i < e820_raw_nr; i++ ) + { + uint64_t s, e; + if ( e820_raw[i].type != E820_RAM ) + continue; + s = PFN_UP(e820_raw[i].addr); + e = PFN_DOWN(e820_raw[i].addr + e820_raw[i].size); + e820_raw[i].size = 0; /* discarded later */ + if ( s < e ) + { + e820_raw[i].addr = s << PAGE_SHIFT; + e820_raw[i].size = (e - s) << PAGE_SHIFT; + } + } + + /* Sanitise the raw E820 map to produce a final clean version. */ max_page = init_e820(e820_raw, &e820_raw_nr); modules_length = mod[mbi->mods_count-1].mod_end - mod[0].mod_start; @@ -423,7 +440,7 @@ void __init __start_xen(multiboot_info_t printk("Not enough memory to stash the DOM0 kernel image.\n"); for ( ; ; ) ; } - + if ( (e820.map[i].type == E820_RAM) && (e820.map[i].size >= modules_length) && ((e820.map[i].addr + e820.map[i].size) >= @@ -474,10 +491,10 @@ void __init __start_xen(multiboot_info_t start = PFN_UP(e820.map[i].addr); end = PFN_DOWN(e820.map[i].addr + e820.map[i].size); /* Clip the range to exclude what the bootstrapper initialised. */ - if ( end < init_mapped ) - continue; if ( start < init_mapped ) start = init_mapped; + if ( end <= start ) + continue; /* Request the mapping. */ map_pages_to_xen( PAGE_OFFSET + (start << PAGE_SHIFT), @@ -486,7 +503,7 @@ void __init __start_xen(multiboot_info_t #endif } - if ( kexec_crash_area.size > 0 ) + if ( kexec_crash_area.size > 0 && kexec_crash_area.start > 0) { unsigned long kdump_start, kdump_size, k; diff -r c6b683ba68f5 -r a2b2b2a011f1 xen/arch/x86/traps.c --- a/xen/arch/x86/traps.c Sun Jan 14 22:18:38 2007 -0700 +++ b/xen/arch/x86/traps.c Mon Jan 15 15:15:26 2007 -0700 @@ -1121,7 +1121,7 @@ static int emulate_privileged_op(struct { struct vcpu *v = current; unsigned long *reg, eip = regs->eip, res; - u8 opcode, modrm_reg = 0, modrm_rm = 0, rep_prefix = 0, rex = 0; + u8 opcode, modrm_reg = 0, modrm_rm = 0, rep_prefix = 0, lock = 0, rex = 0; enum { lm_seg_none, lm_seg_fs, lm_seg_gs } lm_ovr = lm_seg_none; unsigned int port, i, data_sel, ar, data, rc; unsigned int op_bytes, op_default, ad_bytes, ad_default; @@ -1184,6 +1184,7 @@ static int emulate_privileged_op(struct data_sel = regs->ss; continue; case 0xf0: /* LOCK */ + lock = 1; continue; case 0xf2: /* REPNE/REPNZ */ case 0xf3: /* REP/REPE/REPZ */ @@ -1210,6 +1211,9 @@ static int emulate_privileged_op(struct if ( opcode == 0x0f ) goto twobyte_opcode; + if ( lock ) + goto fail; + /* Input/Output String instructions. */ if ( (opcode >= 0x6c) && (opcode <= 0x6f) ) { @@ -1472,6 +1476,8 @@ static int emulate_privileged_op(struct /* Privileged (ring 0) instructions. */ opcode = insn_fetch(u8, code_base, eip, code_limit); + if ( lock && (opcode & ~3) != 0x20 ) + goto fail; switch ( opcode ) { case 0x06: /* CLTS */ @@ -1490,7 +1496,7 @@ static int emulate_privileged_op(struct case 0x20: /* MOV CR?,<reg> */ opcode = insn_fetch(u8, code_base, eip, code_limit); - modrm_reg |= (opcode >> 3) & 7; + modrm_reg += ((opcode >> 3) & 7) + (lock << 3); modrm_rm |= (opcode >> 0) & 7; reg = decode_register(modrm_rm, regs, 0); switch ( modrm_reg ) @@ -1530,7 +1536,7 @@ static int emulate_privileged_op(struct case 0x21: /* MOV DR?,<reg> */ opcode = insn_fetch(u8, code_base, eip, code_limit); - modrm_reg |= (opcode >> 3) & 7; + modrm_reg += ((opcode >> 3) & 7) + (lock << 3); modrm_rm |= (opcode >> 0) & 7; reg = decode_register(modrm_rm, regs, 0); if ( (res = do_get_debugreg(modrm_reg)) > (unsigned long)-256 ) @@ -1540,7 +1546,7 @@ static int emulate_privileged_op(struct case 0x22: /* MOV <reg>,CR? */ opcode = insn_fetch(u8, code_base, eip, code_limit); - modrm_reg |= (opcode >> 3) & 7; + modrm_reg += ((opcode >> 3) & 7) + (lock << 3); modrm_rm |= (opcode >> 0) & 7; reg = decode_register(modrm_rm, regs, 0); switch ( modrm_reg ) @@ -1588,7 +1594,7 @@ static int emulate_privileged_op(struct case 0x23: /* MOV <reg>,DR? */ opcode = insn_fetch(u8, code_base, eip, code_limit); - modrm_reg |= (opcode >> 3) & 7; + modrm_reg += ((opcode >> 3) & 7) + (lock << 3); modrm_rm |= (opcode >> 0) & 7; reg = decode_register(modrm_rm, regs, 0); if ( do_set_debugreg(modrm_reg, *reg) != 0 ) @@ -1854,7 +1860,7 @@ static int dummy_nmi_callback(struct cpu } static nmi_callback_t nmi_callback = dummy_nmi_callback; - + asmlinkage void do_nmi(struct cpu_user_regs *regs) { unsigned int cpu = smp_processor_id(); diff -r c6b683ba68f5 -r a2b2b2a011f1 xen/arch/x86/x86_64/compat/mm.c --- a/xen/arch/x86/x86_64/compat/mm.c Sun Jan 14 22:18:38 2007 -0700 +++ b/xen/arch/x86/x86_64/compat/mm.c Mon Jan 15 15:15:26 2007 -0700 @@ -1,6 +1,7 @@ #ifdef CONFIG_COMPAT #include <xen/event.h> +#include <xen/multicall.h> #include <compat/memory.h> #include <compat/xen.h> @@ -289,20 +290,27 @@ int compat_mmuext_op(XEN_GUEST_HANDLE(mm if ( err == __HYPERVISOR_mmuext_op ) { struct cpu_user_regs *regs = guest_cpu_user_regs(); - unsigned int left = regs->ecx & ~MMU_UPDATE_PREEMPTED; - - BUG_ON(!(regs->ecx & MMU_UPDATE_PREEMPTED)); + struct mc_state *mcs = &this_cpu(mc_state); + unsigned int arg1 = !test_bit(_MCSF_in_multicall, &mcs->flags) + ? regs->ecx + : mcs->call.args[1]; + unsigned int left = arg1 & ~MMU_UPDATE_PREEMPTED; + + BUG_ON(left == arg1); BUG_ON(left > count); guest_handle_add_offset(nat_ops, count - left); BUG_ON(left + i < count); guest_handle_add_offset(cmp_uops, (signed int)(count - left - i)); left = 1; BUG_ON(!hypercall_xlat_continuation(&left, 0x01, nat_ops, cmp_uops)); - BUG_ON(left != regs->ecx); - regs->ecx += count - i; + BUG_ON(left != arg1); + if (!test_bit(_MCSF_in_multicall, &mcs->flags)) + regs->_ecx += count - i; + else + mcs->compat_call.args[1] += count - i; } else - BUG_ON(rc > 0); + BUG_ON(err > 0); rc = err; } diff -r c6b683ba68f5 -r a2b2b2a011f1 xen/arch/x86/x86_emulate.c --- a/xen/arch/x86/x86_emulate.c Sun Jan 14 22:18:38 2007 -0700 +++ b/xen/arch/x86/x86_emulate.c Mon Jan 15 15:15:26 2007 -0700 @@ -3,7 +3,21 @@ * * Generic x86 (32-bit and 64-bit) instruction decoder and emulator. * - * Copyright (c) 2005 Keir Fraser + * Copyright (c) 2005-2007 Keir Fraser + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __XEN__ @@ -33,9 +47,8 @@ #define SrcReg (1<<3) /* Register operand. */ #define SrcMem (2<<3) /* Memory operand. */ #define SrcMem16 (3<<3) /* Memory operand (16-bit). */ -#define SrcMem32 (4<<3) /* Memory operand (32-bit). */ -#define SrcImm (5<<3) /* Immediate operand. */ -#define SrcImmByte (6<<3) /* 8-bit sign-extended immediate operand. */ +#define SrcImm (4<<3) /* Immediate operand. */ +#define SrcImmByte (5<<3) /* 8-bit sign-extended immediate operand. */ #define SrcMask (7<<3) /* Generic ModRM decode. */ #define ModRM (1<<6) @@ -85,9 +98,13 @@ static uint8_t opcode_table[256] = { ImplicitOps|Mov, ImplicitOps|Mov, ImplicitOps|Mov, ImplicitOps|Mov, ImplicitOps|Mov, ImplicitOps|Mov, ImplicitOps|Mov, ImplicitOps|Mov, ImplicitOps|Mov, ImplicitOps|Mov, ImplicitOps|Mov, ImplicitOps|Mov, - /* 0x60 - 0x6F */ - 0, 0, 0, DstReg|SrcMem32|ModRM|Mov /* movsxd (x86/64) */, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 0x60 - 0x67 */ + ImplicitOps, ImplicitOps, DstReg|SrcMem|ModRM, DstReg|SrcMem16|ModRM|Mov, + 0, 0, 0, 0, + /* 0x68 - 0x6F */ + ImplicitOps|Mov, DstMem|SrcImm|ModRM|Mov, + ImplicitOps|Mov, DstMem|SrcImmByte|ModRM|Mov, + 0, 0, 0, 0, /* 0x70 - 0x77 */ ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, @@ -107,7 +124,7 @@ static uint8_t opcode_table[256] = { ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, /* 0x98 - 0x9F */ - 0, 0, 0, 0, 0, 0, 0, 0, + ImplicitOps, ImplicitOps, 0, 0, 0, 0, ImplicitOps, ImplicitOps, /* 0xA0 - 0xA7 */ ByteOp|ImplicitOps|Mov, ImplicitOps|Mov, ByteOp|ImplicitOps|Mov, ImplicitOps|Mov, @@ -125,7 +142,8 @@ static uint8_t opcode_table[256] = { DstReg|SrcImm|Mov, DstReg|SrcImm|Mov, DstReg|SrcImm|Mov, DstReg|SrcImm|Mov, DstReg|SrcImm|Mov, DstReg|SrcImm|Mov, DstReg|SrcImm|Mov, DstReg|SrcImm|Mov, /* 0xC0 - 0xC7 */ - ByteOp|DstMem|SrcImm|ModRM, DstMem|SrcImmByte|ModRM, 0, 0, + ByteOp|DstMem|SrcImm|ModRM, DstMem|SrcImmByte|ModRM, + ImplicitOps, ImplicitOps, 0, 0, ByteOp|DstMem|SrcImm|ModRM|Mov, DstMem|SrcImm|ModRM|Mov, /* 0xC8 - 0xCF */ 0, 0, 0, 0, 0, 0, 0, 0, @@ -136,9 +154,9 @@ static uint8_t opcode_table[256] = { /* 0xD8 - 0xDF */ 0, 0, 0, 0, 0, 0, 0, 0, /* 0xE0 - 0xE7 */ - 0, 0, 0, ImplicitOps, 0, 0, 0, 0, + ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, 0, 0, 0, 0, /* 0xE8 - 0xEF */ - 0, ImplicitOps, 0, ImplicitOps, 0, 0, 0, 0, + ImplicitOps, ImplicitOps, 0, ImplicitOps, 0, 0, 0, 0, /* 0xF0 - 0xF7 */ 0, 0, 0, 0, 0, ImplicitOps, ByteOp|DstMem|SrcNone|ModRM, DstMem|SrcNone|ModRM, @@ -150,8 +168,11 @@ static uint8_t twobyte_table[256] = { static uint8_t twobyte_table[256] = { /* 0x00 - 0x0F */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ImplicitOps|ModRM, 0, 0, - /* 0x10 - 0x1F */ - 0, 0, 0, 0, 0, 0, 0, 0, ImplicitOps|ModRM, 0, 0, 0, 0, 0, 0, 0, + /* 0x10 - 0x17 */ + 0, 0, 0, 0, 0, 0, 0, 0, + /* 0x18 - 0x1F */ + ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM, + ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM, /* 0x20 - 0x2F */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x30 - 0x3F */ @@ -178,24 +199,34 @@ static uint8_t twobyte_table[256] = { /* 0x88 - 0x8F */ ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, - /* 0x90 - 0x9F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 0x90 - 0x97 */ + ByteOp|DstMem|SrcNone|ModRM|Mov, ByteOp|DstMem|SrcNone|ModRM|Mov, + ByteOp|DstMem|SrcNone|ModRM|Mov, ByteOp|DstMem|SrcNone|ModRM|Mov, + ByteOp|DstMem|SrcNone|ModRM|Mov, ByteOp|DstMem|SrcNone|ModRM|Mov, + ByteOp|DstMem|SrcNone|ModRM|Mov, ByteOp|DstMem|SrcNone|ModRM|Mov, + /* 0x98 - 0x9F */ + ByteOp|DstMem|SrcNone|ModRM|Mov, ByteOp|DstMem|SrcNone|ModRM|Mov, + ByteOp|DstMem|SrcNone|ModRM|Mov, ByteOp|DstMem|SrcNone|ModRM|Mov, + ByteOp|DstMem|SrcNone|ModRM|Mov, ByteOp|DstMem|SrcNone|ModRM|Mov, + ByteOp|DstMem|SrcNone|ModRM|Mov, ByteOp|DstMem|SrcNone|ModRM|Mov, /* 0xA0 - 0xA7 */ 0, 0, 0, DstBitBase|SrcReg|ModRM, 0, 0, 0, 0, /* 0xA8 - 0xAF */ - 0, 0, 0, DstBitBase|SrcReg|ModRM, 0, 0, 0, 0, + 0, 0, 0, DstBitBase|SrcReg|ModRM, 0, 0, 0, DstReg|SrcMem|ModRM, /* 0xB0 - 0xB7 */ ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM, 0, DstBitBase|SrcReg|ModRM, 0, 0, ByteOp|DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem16|ModRM|Mov, /* 0xB8 - 0xBF */ 0, 0, DstBitBase|SrcImmByte|ModRM, DstBitBase|SrcReg|ModRM, - 0, 0, ByteOp|DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem16|ModRM|Mov, + DstReg|SrcMem|ModRM, DstReg|SrcMem|ModRM, + ByteOp|DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem16|ModRM|Mov, /* 0xC0 - 0xC7 */ ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM, 0, 0, 0, 0, 0, ImplicitOps|ModRM, /* 0xC8 - 0xCF */ - 0, 0, 0, 0, 0, 0, 0, 0, + ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, + ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, /* 0xD0 - 0xDF */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xE0 - 0xEF */ @@ -206,7 +237,7 @@ static uint8_t twobyte_table[256] = { /* Type, address-of, and value of an instruction's operand. */ struct operand { - enum { OP_REG, OP_MEM, OP_IMM } type; + enum { OP_REG, OP_MEM, OP_IMM, OP_NONE } type; unsigned int bytes; unsigned long val, orig_val; union { @@ -230,7 +261,10 @@ struct operand { #define EFLG_CF (1<<0) /* Exception definitions. */ -#define EXC_DE 0 +#define EXC_DE 0 +#define EXC_BR 5 +#define EXC_UD 6 +#define EXC_GP 13 /* * Instruction emulation: @@ -289,7 +323,8 @@ do{ unsigned long _tmp; _op"w %"_wx"3,%1; " \ _POST_EFLAGS("0","4","2") \ : "=m" (_eflags), "=m" ((_dst).val), "=&r" (_tmp) \ - : _wy ((_src).val), "i" (EFLAGS_MASK) ); \ + : _wy ((_src).val), "i" (EFLAGS_MASK), \ + "m" (_eflags), "m" ((_dst).val) ); \ break; \ case 4: \ __asm__ __volatile__ ( \ @@ -297,7 +332,8 @@ do{ unsigned long _tmp; _op"l %"_lx"3,%1; " \ _POST_EFLAGS("0","4","2") \ : "=m" (_eflags), "=m" ((_dst).val), "=&r" (_tmp) \ - : _ly ((_src).val), "i" (EFLAGS_MASK) ); \ + : _ly ((_src).val), "i" (EFLAGS_MASK), \ + "m" (_eflags), "m" ((_dst).val) ); \ break; \ case 8: \ __emulate_2op_8byte(_op, _src, _dst, _eflags, _qx, _qy); \ @@ -314,7 +350,8 @@ do{ unsigned long _tmp; _op"b %"_bx"3,%1; " \ _POST_EFLAGS("0","4","2") \ : "=m" (_eflags), "=m" ((_dst).val), "=&r" (_tmp) \ - : _by ((_src).val), "i" (EFLAGS_MASK) ); \ + : _by ((_src).val), "i" (EFLAGS_MASK), \ + "m" (_eflags), "m" ((_dst).val) ); \ break; \ default: \ __emulate_2op_nobyte(_op,_src,_dst,_eflags,_wx,_wy,_lx,_ly,_qx,_qy);\ @@ -345,7 +382,7 @@ do{ unsigned long _tmp; _op"b %1; " \ _POST_EFLAGS("0","3","2") \ : "=m" (_eflags), "=m" ((_dst).val), "=&r" (_tmp) \ - : "i" (EFLAGS_MASK) ); \ + : "i" (EFLAGS_MASK), "m" (_eflags), "m" ((_dst).val) ); \ break; \ case 2: \ __asm__ __volatile__ ( \ @@ -353,7 +390,7 @@ do{ unsigned long _tmp; _op"w %1; " \ _POST_EFLAGS("0","3","2") \ : "=m" (_eflags), "=m" ((_dst).val), "=&r" (_tmp) \ - : "i" (EFLAGS_MASK) ); \ + : "i" (EFLAGS_MASK), "m" (_eflags), "m" ((_dst).val) ); \ break; \ case 4: \ __asm__ __volatile__ ( \ @@ -361,7 +398,7 @@ do{ unsigned long _tmp; _op"l %1; " \ _POST_EFLAGS("0","3","2") \ : "=m" (_eflags), "=m" ((_dst).val), "=&r" (_tmp) \ - : "i" (EFLAGS_MASK) ); \ + : "i" (EFLAGS_MASK), "m" (_eflags), "m" ((_dst).val) ); \ break; \ case 8: \ __emulate_1op_8byte(_op, _dst, _eflags); \ @@ -377,7 +414,8 @@ do{ __asm__ __volatile__ ( _op"q %"_qx"3,%1; " \ _POST_EFLAGS("0","4","2") \ : "=m" (_eflags), "=m" ((_dst).val), "=&r" (_tmp) \ - : _qy ((_src).val), "i" (EFLAGS_MASK) ); \ + : _qy ((_src).val), "i" (EFLAGS_MASK), \ + "m" (_eflags), "m" ((_dst).val) ); \ } while (0) #define __emulate_1op_8byte(_op, _dst, _eflags) \ do{ __asm__ __volatile__ ( \ @@ -385,7 +423,7 @@ do{ __asm__ __volatile__ ( _op"q %1; " \ _POST_EFLAGS("0","3","2") \ : "=m" (_eflags), "=m" ((_dst).val), "=&r" (_tmp) \ - : "i" (EFLAGS_MASK) ); \ + : "i" (EFLAGS_MASK), "m" (_eflags), "m" ((_dst).val) ); \ } while (0) #elif defined(__i386__) #define __emulate_2op_8byte(_op, _src, _dst, _eflags, _qx, _qy) @@ -394,11 +432,13 @@ do{ __asm__ __volatile__ ( /* Fetch next part of the instruction being emulated. */ #define insn_fetch_bytes(_size) \ -({ unsigned long _x, _eip = _truncate_ea(_regs.eip, def_ad_bytes); \ +({ unsigned long _x, _eip = _regs.eip; \ if ( !mode_64bit() ) _eip = (uint32_t)_eip; /* ignore upper dword */ \ + _regs.eip += (_size); /* real hardware doesn't truncate */ \ + generate_exception_if((uint8_t)(_regs.eip - ctxt->regs->eip) > 15, \ + EXC_GP); \ rc = ops->insn_fetch(x86_seg_cs, _eip, &_x, (_size), ctxt); \ if ( rc ) goto done; \ - _regs.eip += (_size); /* real hardware doesn't truncate */ \ _x; \ }) #define insn_fetch_type(_type) ((_type)insn_fetch_bytes(sizeof(_type))) @@ -451,6 +491,92 @@ do { _regs.eip = ((op_bytes == 2) \ ? (uint16_t)_regs.eip : (uint32_t)_regs.eip); \ } while (0) + +/* + * Unsigned multiplication with double-word result. + * IN: Multiplicand=m[0], Multiplier=m[1] + * OUT: Return CF/OF (overflow status); Result=m[1]:m[0] + */ +static int mul_dbl(unsigned long m[2]) +{ + int rc; + asm ( "mul %4; seto %b2" + : "=a" (m[0]), "=d" (m[1]), "=q" (rc) + : "0" (m[0]), "1" (m[1]), "2" (0) ); + return rc; +} + +/* + * Signed multiplication with double-word result. + * IN: Multiplicand=m[0], Multiplier=m[1] + * OUT: Return CF/OF (overflow status); Result=m[1]:m[0] + */ +static int imul_dbl(unsigned long m[2]) +{ + int rc; + asm ( "imul %4; seto %b2" + : "=a" (m[0]), "=d" (m[1]), "=q" (rc) + : "0" (m[0]), "1" (m[1]), "2" (0) ); + return rc; +} + +/* + * Unsigned division of double-word dividend. + * IN: Dividend=u[1]:u[0], Divisor=v + * OUT: Return 1: #DE + * Return 0: Quotient=u[0], Remainder=u[1] + */ +static int div_dbl(unsigned long u[2], unsigned long v) +{ + if ( (v == 0) || (u[1] > v) || ((u[1] == v) && (u[0] != 0)) ) + return 1; + asm ( "div %4" + : "=a" (u[0]), "=d" (u[1]) + : "0" (u[0]), "1" (u[1]), "r" (v) ); + return 0; +} + +/* + * Signed division of double-word dividend. + * IN: Dividend=u[1]:u[0], Divisor=v + * OUT: Return 1: #DE + * Return 0: Quotient=u[0], Remainder=u[1] + * NB. We don't use idiv directly as it's moderately hard to work out + * ahead of time whether it will #DE, which we cannot allow to happen. + */ +static int idiv_dbl(unsigned long u[2], unsigned long v) +{ + int negu = (long)u[1] < 0, negv = (long)v < 0; + + /* u = abs(u) */ + if ( negu ) + { + u[1] = ~u[1]; + if ( (u[0] = -u[0]) == 0 ) + u[1]++; + } + + /* abs(u) / abs(v) */ + if ( div_dbl(u, negv ? -v : v) ) + return 1; + + /* Remainder has same sign as dividend. It cannot overflow. */ + if ( negu ) + u[1] = -u[1]; + + /* Quotient is overflowed if sign bit is set. */ + if ( negu ^ negv ) + { + if ( (long)u[0] >= 0 ) + u[0] = -u[0]; + else if ( (u[0] << 1) != 0 ) /* == 0x80...0 is okay */ + return 1; + } + else if ( (long)u[0] < 0 ) + return 1; + + return 0; +} static int test_cc( @@ -540,8 +666,8 @@ x86_emulate( uint8_t b, d, sib, sib_index, sib_base, twobyte = 0, rex_prefix = 0; uint8_t modrm, modrm_mod = 0, modrm_reg = 0, modrm_rm = 0; - unsigned int op_bytes, ad_bytes, def_ad_bytes; - unsigned int lock_prefix = 0, rep_prefix = 0, i; + unsigned int op_bytes, def_op_bytes, ad_bytes, def_ad_bytes; + unsigned int lock_prefix = 0, rep_prefix = 0; int rc = 0; struct operand src, dst; @@ -553,28 +679,25 @@ x86_emulate( ea.mem.seg = x86_seg_ds; ea.mem.off = 0; - op_bytes = ad_bytes = def_ad_bytes = ctxt->address_bytes; + op_bytes = def_op_bytes = ad_bytes = def_ad_bytes = ctxt->address_bytes; if ( op_bytes == 8 ) { - op_bytes = 4; + op_bytes = def_op_bytes = 4; #ifndef __x86_64__ return -1; #endif } /* Prefix bytes. */ - for ( i = 0; i < 8; i++ ) + for ( ; ; ) { switch ( b = insn_fetch_type(uint8_t) ) { case 0x66: /* operand-size override */ - op_bytes ^= 6; /* switch between 2/4 bytes */ + op_bytes = def_op_bytes ^ 6; break; case 0x67: /* address-size override */ - if ( mode_64bit() ) - ad_bytes ^= 12; /* switch between 4/8 bytes */ - else - ad_bytes ^= 6; /* switch between 2/4 bytes */ + ad_bytes = def_ad_bytes ^ (mode_64bit() ? 12 : 6); break; case 0x2e: /* CS override */ ea.mem.seg = x86_seg_cs; @@ -634,6 +757,9 @@ x86_emulate( if ( d == 0 ) goto cannot_emulate; } + + /* Lock prefix is allowed only on RMW instructions. */ + generate_exception_if((d & Mov) && lock_prefix, EXC_GP); /* ModRM and SIB bytes. */ if ( d & ModRM ) @@ -767,9 +893,6 @@ x86_emulate( case SrcMem16: ea.bytes = 2; goto srcmem_common; - case SrcMem32: - ea.bytes = 4; - goto srcmem_common; case SrcMem: ea.bytes = (d & ByteOp) ? 1 : op_bytes; srcmem_common: @@ -838,7 +961,7 @@ x86_emulate( { /* * EA += BitOffset DIV op_bytes*8 - * BitOffset = BitOffset MOD op_byte*8 + * BitOffset = BitOffset MOD op_bytes*8 * DIV truncates towards negative infinity. * MOD always produces a positive result. */ @@ -874,13 +997,18 @@ x86_emulate( case 8: dst.val = *(uint64_t *)dst.reg; break; } } - else if ( !(d & Mov) && /* optimisation - avoid slow emulated read */ - (rc = ops->read(dst.mem.seg, dst.mem.off, - &dst.val, dst.bytes, ctxt)) ) - goto done; - break; - } - dst.orig_val = dst.val; + else if ( !(d & Mov) ) /* optimisation - avoid slow emulated read */ + { + if ( (rc = ops->read(dst.mem.seg, dst.mem.off, + &dst.val, dst.bytes, ctxt)) ) + goto done; + dst.orig_val = dst.val; + } + break; + } + + /* LOCK prefix allowed only on instructions with memory destination. */ + generate_exception_if(lock_prefix && (dst.type != OP_MEM), EXC_GP); if ( twobyte ) goto twobyte_insn; @@ -889,65 +1017,132 @@ x86_emulate( { case 0x04 ... 0x05: /* add imm,%%eax */ dst.reg = (unsigned long *)&_regs.eax; - dst.val = dst.orig_val = _regs.eax; + dst.val = _regs.eax; case 0x00 ... 0x03: add: /* add */ emulate_2op_SrcV("add", src, dst, _regs.eflags); break; case 0x0c ... 0x0d: /* or imm,%%eax */ dst.reg = (unsigned long *)&_regs.eax; - dst.val = dst.orig_val = _regs.eax; + dst.val = _regs.eax; case 0x08 ... 0x0b: or: /* or */ emulate_2op_SrcV("or", src, dst, _regs.eflags); break; case 0x14 ... 0x15: /* adc imm,%%eax */ dst.reg = (unsigned long *)&_regs.eax; - dst.val = dst.orig_val = _regs.eax; + dst.val = _regs.eax; case 0x10 ... 0x13: adc: /* adc */ emulate_2op_SrcV("adc", src, dst, _regs.eflags); break; case 0x1c ... 0x1d: /* sbb imm,%%eax */ dst.reg = (unsigned long *)&_regs.eax; - dst.val = dst.orig_val = _regs.eax; + dst.val = _regs.eax; case 0x18 ... 0x1b: sbb: /* sbb */ emulate_2op_SrcV("sbb", src, dst, _regs.eflags); break; case 0x24 ... 0x25: /* and imm,%%eax */ dst.reg = (unsigned long *)&_regs.eax; - dst.val = dst.orig_val = _regs.eax; + dst.val = _regs.eax; case 0x20 ... 0x23: and: /* and */ emulate_2op_SrcV("and", src, dst, _regs.eflags); break; case 0x2c ... 0x2d: /* sub imm,%%eax */ dst.reg = (unsigned long *)&_regs.eax; - dst.val = dst.orig_val = _regs.eax; + dst.val = _regs.eax; case 0x28 ... 0x2b: sub: /* sub */ emulate_2op_SrcV("sub", src, dst, _regs.eflags); break; case 0x34 ... 0x35: /* xor imm,%%eax */ dst.reg = (unsigned long *)&_regs.eax; - dst.val = dst.orig_val = _regs.eax; + dst.val = _regs.eax; case 0x30 ... 0x33: xor: /* xor */ emulate_2op_SrcV("xor", src, dst, _regs.eflags); break; case 0x3c ... 0x3d: /* cmp imm,%%eax */ dst.reg = (unsigned long *)&_regs.eax; - dst.val = dst.orig_val = _regs.eax; + dst.val = _regs.eax; case 0x38 ... 0x3b: cmp: /* cmp */ emulate_2op_SrcV("cmp", src, dst, _regs.eflags); break; - case 0x63: /* movsxd */ - if ( !mode_64bit() ) - goto cannot_emulate; - dst.val = (int32_t)src.val; - break; + case 0x62: /* bound */ { + unsigned long src_val2; + int lb, ub, idx; + generate_exception_if(mode_64bit() || (src.type != OP_MEM), EXC_UD); + if ( (rc = ops->read(src.mem.seg, src.mem.off + op_bytes, + &src_val2, op_bytes, ctxt)) ) + goto done; + ub = (op_bytes == 2) ? (int16_t)src_val2 : (int32_t)src_val2; + lb = (op_bytes == 2) ? (int16_t)src.val : (int32_t)src.val; + idx = (op_bytes == 2) ? (int16_t)dst.val : (int32_t)dst.val; + generate_exception_if((idx < lb) || (idx > ub), EXC_BR); + dst.type = OP_NONE; + break; + } + + case 0x63: /* movsxd (x86/64) / arpl (x86/32) */ + if ( mode_64bit() ) + { + /* movsxd */ + if ( src.type == OP_REG ) + src.val = *(int32_t *)src.reg; + else if ( (rc = ops->read(src.mem.seg, src.mem.off, + &src.val, 4, ctxt)) ) + goto done; + dst.val = (int32_t)src.val; + } + else + { + /* arpl */ + uint16_t src_val = dst.val; + dst = src; + _regs.eflags &= ~EFLG_ZF; + _regs.eflags |= ((src_val & 3) > (dst.val & 3)) ? EFLG_ZF : 0; + if ( _regs.eflags & EFLG_ZF ) + dst.val = (dst.val & ~3) | (src_val & 3); + else + dst.type = OP_NONE; + } + break; + + case 0x69: /* imul imm16/32 */ + case 0x6b: /* imul imm8 */ { + unsigned long reg = *(long *)decode_register(modrm_reg, &_regs, 0); + _regs.eflags &= ~(EFLG_OF|EFLG_CF); + switch ( dst.bytes ) + { + case 2: + dst.val = ((uint32_t)(int16_t)src.val * + (uint32_t)(int16_t)reg); + if ( (int16_t)dst.val != (uint32_t)dst.val ) + _regs.eflags |= EFLG_OF|EFLG_CF; + break; +#ifdef __x86_64__ + case 4: + dst.val = ((uint64_t)(int32_t)src.val * + (uint64_t)(int32_t)reg); + if ( (int32_t)dst.val != dst.val ) + _regs.eflags |= EFLG_OF|EFLG_CF; + break; +#endif + default: { + unsigned long m[2] = { src.val, reg }; + if ( imul_dbl(m) ) + _regs.eflags |= EFLG_OF|EFLG_CF; + dst.val = m[0]; + break; + } + } + dst.type = OP_REG; + dst.reg = decode_register(modrm_reg, &_regs, 0); + break; + } case 0x80 ... 0x83: /* Grp1 */ switch ( modrm_reg & 7 ) @@ -965,7 +1160,7 @@ x86_emulate( case 0xa8 ... 0xa9: /* test imm,%%eax */ dst.reg = (unsigned long *)&_regs.eax; - dst.val = dst.orig_val = _regs.eax; + dst.val = _regs.eax; case 0x84 ... 0x85: test: /* test */ emulate_2op_SrcV("test", src, dst, _regs.eflags); break; @@ -985,7 +1180,7 @@ x86_emulate( break; case 0xc6 ... 0xc7: /* mov (sole member of Grp11) */ - fail_if((modrm_reg & 7) != 0); + generate_exception_if((modrm_reg & 7) != 0, EXC_UD); case 0x88 ... 0x8b: /* mov */ dst.val = src.val; break; @@ -995,7 +1190,7 @@ x86_emulate( break; case 0x8f: /* pop (sole member of Grp1a) */ - fail_if((modrm_reg & 7) != 0); + generate_exception_if((modrm_reg & 7) != 0, EXC_UD); /* 64-bit mode: POP defaults to a 64-bit operand. */ if ( mode_64bit() && (dst.bytes == 4) ) dst.bytes = 8; @@ -1077,13 +1272,190 @@ x86_emulate( case 3: /* neg */ emulate_1op("neg", dst, _regs.eflags); break; + case 4: /* mul */ + src = dst; + dst.type = OP_REG; + dst.reg = (unsigned long *)&_regs.eax; + dst.val = *dst.reg; + _regs.eflags &= ~(EFLG_OF|EFLG_CF); + switch ( src.bytes ) + { + case 1: + dst.val *= src.val; + if ( (uint8_t)dst.val != (uint16_t)dst.val ) + _regs.eflags |= EFLG_OF|EFLG_CF; + break; + case 2: + dst.val *= src.val; + if ( (uint16_t)dst.val != (uint32_t)dst.val ) + _regs.eflags |= EFLG_OF|EFLG_CF; + *(uint16_t *)&_regs.edx = dst.val >> 16; + break; +#ifdef __x86_64__ + case 4: + dst.val *= src.val; + if ( (uint32_t)dst.val != dst.val ) + _regs.eflags |= EFLG_OF|EFLG_CF; + _regs.edx = (uint32_t)(dst.val >> 32); + break; +#endif + default: { + unsigned long m[2] = { src.val, dst.val }; + if ( mul_dbl(m) ) + _regs.eflags |= EFLG_OF|EFLG_CF; + _regs.edx = m[1]; + dst.val = m[0]; + break; + } + } + break; + case 5: /* imul */ + src = dst; + dst.type = OP_REG; + dst.reg = (unsigned long *)&_regs.eax; + dst.val = *dst.reg; + _regs.eflags &= ~(EFLG_OF|EFLG_CF); + switch ( src.bytes ) + { + case 1: + dst.val = ((uint16_t)(int8_t)src.val * + (uint16_t)(int8_t)dst.val); + if ( (int8_t)dst.val != (uint16_t)dst.val ) + _regs.eflags |= EFLG_OF|EFLG_CF; + break; + case 2: + dst.val = ((uint32_t)(int16_t)src.val * + (uint32_t)(int16_t)dst.val); + if ( (int16_t)dst.val != (uint32_t)dst.val ) + _regs.eflags |= EFLG_OF|EFLG_CF; + *(uint16_t *)&_regs.edx = dst.val >> 16; + break; +#ifdef __x86_64__ + case 4: + dst.val = ((uint64_t)(int32_t)src.val * + (uint64_t)(int32_t)dst.val); + if ( (int32_t)dst.val != dst.val ) + _regs.eflags |= EFLG_OF|EFLG_CF; + _regs.edx = (uint32_t)(dst.val >> 32); + break; +#endif + default: { + unsigned long m[2] = { src.val, dst.val }; + if ( imul_dbl(m) ) + _regs.eflags |= EFLG_OF|EFLG_CF; + _regs.edx = m[1]; + dst.val = m[0]; + break; + } + } + break; + case 6: /* div */ { + unsigned long u[2], v; + src = dst; + dst.type = OP_REG; + dst.reg = (unsigned long *)&_regs.eax; + switch ( src.bytes ) + { + case 1: + u[0] = (uint16_t)_regs.eax; + u[1] = 0; + v = (uint8_t)src.val; + generate_exception_if( + div_dbl(u, v) || ((uint8_t)u[0] != (uint16_t)u[0]), + EXC_DE); + dst.val = (uint8_t)u[0]; + ((uint8_t *)&_regs.eax)[1] = u[1]; + break; + case 2: + u[0] = ((uint32_t)_regs.edx << 16) | (uint16_t)_regs.eax; + u[1] = 0; + v = (uint16_t)src.val; + generate_exception_if( + div_dbl(u, v) || ((uint16_t)u[0] != (uint32_t)u[0]), + EXC_DE); + dst.val = (uint16_t)u[0]; + *(uint16_t *)&_regs.edx = u[1]; + break; +#ifdef __x86_64__ + case 4: + u[0] = (_regs.edx << 32) | (uint32_t)_regs.eax; + u[1] = 0; + v = (uint32_t)src.val; + generate_exception_if( + div_dbl(u, v) || ((uint32_t)u[0] != u[0]), + EXC_DE); + dst.val = (uint32_t)u[0]; + _regs.edx = (uint32_t)u[1]; + break; +#endif + default: + u[0] = _regs.eax; + u[1] = _regs.edx; + v = src.val; + generate_exception_if(div_dbl(u, v), EXC_DE); + dst.val = u[0]; + _regs.edx = u[1]; + break; + } + break; + } + case 7: /* idiv */ { + unsigned long u[2], v; + src = dst; + dst.type = OP_REG; + dst.reg = (unsigned long *)&_regs.eax; + switch ( src.bytes ) + { + case 1: + u[0] = (int16_t)_regs.eax; + u[1] = ((long)u[0] < 0) ? ~0UL : 0UL; + v = (int8_t)src.val; + generate_exception_if( + idiv_dbl(u, v) || ((int8_t)u[0] != (int16_t)u[0]), + EXC_DE); + dst.val = (int8_t)u[0]; + ((int8_t *)&_regs.eax)[1] = u[1]; + break; + case 2: + u[0] = (int32_t)((_regs.edx << 16) | (uint16_t)_regs.eax); + u[1] = ((long)u[0] < 0) ? ~0UL : 0UL; + v = (int16_t)src.val; + generate_exception_if( + idiv_dbl(u, v) || ((int16_t)u[0] != (int32_t)u[0]), + EXC_DE); + dst.val = (int16_t)u[0]; + *(int16_t *)&_regs.edx = u[1]; + break; +#ifdef __x86_64__ + case 4: + u[0] = (_regs.edx << 32) | (uint32_t)_regs.eax; + u[1] = ((long)u[0] < 0) ? ~0UL : 0UL; + v = (int32_t)src.val; + generate_exception_if( + idiv_dbl(u, v) || ((int32_t)u[0] != u[0]), + EXC_DE); + dst.val = (int32_t)u[0]; + _regs.edx = (uint32_t)u[1]; + break; +#endif + default: + u[0] = _regs.eax; + u[1] = _regs.edx; + v = src.val; + generate_exception_if(idiv_dbl(u, v), EXC_DE); + dst.val = u[0]; + _regs.edx = u[1]; + break; + } + break; + } default: goto cannot_emulate; } break; case 0xfe: /* Grp4 */ - fail_if((modrm_reg & 7) >= 2); + generate_exception_if((modrm_reg & 7) >= 2, EXC_UD); case 0xff: /* Grp5 */ switch ( modrm_reg & 7 ) { @@ -1092,6 +1464,20 @@ x86_emulate( break; case 1: /* dec */ emulate_1op("dec", dst, _regs.eflags); + break; + case 2: /* call (near) */ + case 3: /* jmp (near) */ + if ( ((op_bytes = dst.bytes) != 8) && mode_64bit() ) + { + dst.bytes = op_bytes = 8; + if ( (rc = ops->read(dst.mem.seg, dst.mem.off, + &dst.val, 8, ctxt)) != 0 ) + goto done; + } + src.val = _regs.eip; + _regs.eip = dst.val; + if ( (modrm_reg & 7) == 2 ) + goto push; /* call */ break; case 6: /* push */ /* 64-bit mode: PUSH defaults to a 64-bit operand. */ @@ -1106,10 +1492,10 @@ x86_emulate( if ( (rc = ops->write(x86_seg_ss, truncate_ea(_regs.esp), dst.val, dst.bytes, ctxt)) != 0 ) goto done; - dst.val = dst.orig_val; /* skanky: disable writeback */ + dst.type = OP_NONE; break; case 7: - fail_if(1); + generate_exception_if(1, EXC_UD); default: goto cannot_emulate; } @@ -1117,33 +1503,32 @@ x86_emulate( } writeback: - if ( (d & Mov) || (dst.orig_val != dst.val) ) + switch ( dst.type ) { - switch ( dst.type ) - { - case OP_REG: - /* The 4-byte case *is* correct: in 64-bit mode we zero-extend. */ - switch ( dst.bytes ) - { - case 1: *(uint8_t *)dst.reg = (uint8_t)dst.val; break; - case 2: *(uint16_t *)dst.reg = (uint16_t)dst.val; break; - case 4: *dst.reg = (uint32_t)dst.val; break; /* 64b: zero-ext */ - case 8: *dst.reg = dst.val; break; - } - break; - case OP_MEM: - if ( lock_prefix ) - rc = ops->cmpxchg( - dst.mem.seg, dst.mem.off, dst.orig_val, - dst.val, dst.bytes, ctxt); - else - rc = ops->write( - dst.mem.seg, dst.mem.off, dst.val, dst.bytes, ctxt); - if ( rc != 0 ) - goto done; - default: - break; - } + case OP_REG: + /* The 4-byte case *is* correct: in 64-bit mode we zero-extend. */ + switch ( dst.bytes ) + { + case 1: *(uint8_t *)dst.reg = (uint8_t)dst.val; break; + case 2: *(uint16_t *)dst.reg = (uint16_t)dst.val; break; + case 4: *dst.reg = (uint32_t)dst.val; break; /* 64b: zero-ext */ + case 8: *dst.reg = dst.val; break; + } + break; + case OP_MEM: + if ( !(d & Mov) && (dst.orig_val == dst.val) ) + /* nothing to do */; + else if ( lock_prefix ) + rc = ops->cmpxchg( + dst.mem.seg, dst.mem.off, dst.orig_val, + dst.val, dst.bytes, ctxt); + else + rc = ops->write( + dst.mem.seg, dst.mem.off, dst.val, dst.bytes, ctxt); + if ( rc != 0 ) + goto done; + default: + break; } /* Commit shadow register state. */ @@ -1153,8 +1538,13 @@ x86_emulate( return (rc == X86EMUL_UNHANDLEABLE) ? -1 : 0; special_insn: - /* Default action: disable writeback. There may be no dest operand. */ - dst.orig_val = dst.val; + dst.type = OP_NONE; + + /* + * The only implicit-operands instruction allowed a LOCK prefix is + * CMPXCHG{8,16}B. + */ + generate_exception_if(lock_prefix && (b != 0xc7), EXC_GP); if ( twobyte ) goto twobyte_special_insn; @@ -1175,7 +1565,7 @@ x86_emulate( case 0x27: /* daa */ { uint8_t al = _regs.eax; unsigned long eflags = _regs.eflags; - fail_if(mode_64bit()); + generate_exception_if(mode_64bit(), EXC_UD); _regs.eflags &= ~(EFLG_CF|EFLG_AF); if ( ((al & 0x0f) > 9) || (eflags & EFLG_AF) ) { @@ -1197,7 +1587,7 @@ x86_emulate( case 0x2f: /* das */ { uint8_t al = _regs.eax; unsigned long eflags = _regs.eflags; - fail_if(mode_64bit()); + generate_exception_if(mode_64bit(), EXC_UD); _regs.eflags &= ~(EFLG_CF|EFLG_AF); if ( ((al & 0x0f) > 9) || (eflags & EFLG_AF) ) { @@ -1220,7 +1610,7 @@ x86_emulate( case 0x37: /* aaa */ case 0x3f: /* aas */ - fail_if(mode_64bit()); + generate_exception_if(mode_64bit(), EXC_UD); _regs.eflags &= ~EFLG_CF; if ( ((uint8_t)_regs.eax > 9) || (_regs.eflags & EFLG_AF) ) { @@ -1235,7 +1625,7 @@ x86_emulate( dst.type = OP_REG; dst.reg = decode_register(b & 7, &_regs, 0); dst.bytes = op_bytes; - dst.orig_val = dst.val = *dst.reg; + dst.val = *dst.reg; if ( b & 8 ) emulate_1op("dec", dst, _regs.eflags); else @@ -1243,16 +1633,9 @@ x86_emulate( break; case 0x50 ... 0x57: /* push reg */ - dst.type = OP_MEM; - dst.bytes = op_bytes; - if ( mode_64bit() && (dst.bytes == 4) ) - dst.bytes = 8; - dst.val = *(unsigned long *)decode_register( + src.val = *(unsigned long *)decode_register( (b & 7) | ((rex_prefix & 1) << 3), &_regs, 0); - register_address_increment(_regs.esp, -dst.bytes); - dst.mem.seg = x86_seg_ss; - dst.mem.off = truncate_ea(_regs.esp); - break; + goto push; case 0x58 ... 0x5f: /* pop reg */ dst.type = OP_REG; @@ -1267,6 +1650,58 @@ x86_emulate( register_address_increment(_regs.esp, dst.bytes); break; + case 0x60: /* pusha */ { + int i; + unsigned long regs[] = { + _regs.eax, _regs.ecx, _regs.edx, _regs.ebx, + _regs.esp, _regs.ebp, _regs.esi, _regs.edi }; + generate_exception_if(mode_64bit(), EXC_UD); + for ( i = 0; i < 8; i++ ) + if ( (rc = ops->write(x86_seg_ss, + truncate_ea(_regs.esp-(i+1)*op_bytes), + regs[i], op_bytes, ctxt)) != 0 ) + goto done; + register_address_increment(_regs.esp, -8*op_bytes); + break; + } + + case 0x61: /* popa */ { + int i; + unsigned long dummy_esp, *regs[] = { + (unsigned long *)&_regs.edi, (unsigned long *)&_regs.esi, + (unsigned long *)&_regs.ebp, (unsigned long *)&dummy_esp, + (unsigned long *)&_regs.ebx, (unsigned long *)&_regs.edx, + (unsigned long *)&_regs.ecx, (unsigned long *)&_regs.eax }; + generate_exception_if(mode_64bit(), EXC_UD); + for ( i = 0; i < 8; i++ ) + if ( (rc = ops->read(x86_seg_ss, + truncate_ea(_regs.esp+i*op_bytes), + regs[i], op_bytes, ctxt)) != 0 ) + goto done; + register_address_increment(_regs.esp, 8*op_bytes); + break; + } + + case 0x68: /* push imm{16,32,64} */ + src.val = ((op_bytes == 2) + ? (int32_t)insn_fetch_type(int16_t) + : insn_fetch_type(int32_t)); + goto push; + + case 0x6a: /* push imm8 */ + src.val = insn_fetch_type(int8_t); + push: + d |= Mov; /* force writeback */ + dst.type = OP_MEM; + dst.bytes = op_bytes; + if ( mode_64bit() && (dst.bytes == 4) ) + dst.bytes = 8; + dst.val = src.val; + register_address_increment(_regs.esp, -dst.bytes); + dst.mem.seg = x86_seg_ss; + dst.mem.off = truncate_ea(_regs.esp); + break; + case 0x70 ... 0x7f: /* jcc (short) */ { int rel = insn_fetch_type(int8_t); if ( test_cc(b, _regs.eflags) ) @@ -1285,8 +1720,40 @@ x86_emulate( src.val = *src.reg; dst.reg = decode_register( (b & 7) | ((rex_prefix & 1) << 3), &_regs, 0); - dst.val = dst.orig_val = *dst.reg; + dst.val = *dst.reg; goto xchg; + + case 0x98: /* cbw/cwde/cdqe */ + switch ( op_bytes ) + { + case 2: *(int16_t *)&_regs.eax = (int8_t)_regs.eax; break; /* cbw */ + case 4: _regs.eax = (uint32_t)(int16_t)_regs.eax; break; /* cwde */ + case 8: _regs.eax = (int32_t)_regs.eax; break; /* cdqe */ + } + break; + + case 0x99: /* cwd/cdq/cqo */ + switch ( op_bytes ) + { + case 2: + *(int16_t *)&_regs.edx = ((int16_t)_regs.eax < 0) ? -1 : 0; + break; + case 4: + _regs.edx = (uint32_t)(((int32_t)_regs.eax < 0) ? -1 : 0); + break; + case 8: + _regs.edx = (_regs.eax < 0) ? -1 : 0; + break; + } + break; + + case 0x9e: /* sahf */ + *(uint8_t *)_regs.eflags = (((uint8_t *)&_regs.eax)[1] & 0xd7) | 0x02; + break; + + case 0x9f: /* lahf */ + ((uint8_t *)&_regs.eax)[1] = (_regs.eflags & 0xd7) | 0x02; + break; case 0xa0 ... 0xa1: /* mov mem.offs,{%al,%ax,%eax,%rax} */ /* Source EA is not encoded via ModRM. */ @@ -1342,10 +1809,22 @@ x86_emulate( _regs.esi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes); break; + case 0xc2: /* ret imm16 (near) */ + case 0xc3: /* ret (near) */ { + int offset = (b == 0xc2) ? insn_fetch_type(uint16_t) : 0; + op_bytes = mode_64bit() ? 8 : op_bytes; + if ( (rc = ops->read(x86_seg_ss, truncate_ea(_regs.esp), + &dst.val, op_bytes, ctxt)) != 0 ) + goto done; + _regs.eip = dst.val; + register_address_increment(_regs.esp, op_bytes + offset); + break; + } + case 0xd4: /* aam */ { unsigned int base = insn_fetch_type(uint8_t); uint8_t al = _regs.eax; - fail_if(mode_64bit()); + generate_exception_if(mode_64bit(), EXC_UD); generate_exception_if(base == 0, EXC_DE); *(uint16_t *)&_regs.eax = ((al / base) << 8) | (al % base); _regs.eflags &= ~(EFLG_SF|EFLG_ZF|EFLG_PF); @@ -1358,7 +1837,7 @@ x86_emulate( case 0xd5: /* aad */ { unsigned int base = insn_fetch_type(uint8_t); uint16_t ax = _regs.eax; - fail_if(mode_64bit()); + generate_exception_if(mode_64bit(), EXC_UD); *(uint16_t *)&_regs.eax = (uint8_t)(ax + ((ax >> 8) * base)); _regs.eflags &= ~(EFLG_SF|EFLG_ZF|EFLG_PF); _regs.eflags |= ((uint8_t)_regs.eax == 0) ? EFLG_ZF : 0; @@ -1368,7 +1847,7 @@ x86_emulate( } case 0xd6: /* salc */ - fail_if(mode_64bit()); + generate_exception_if(mode_64bit(), EXC_UD); *(uint8_t *)&_regs.eax = (_regs.eflags & EFLG_CF) ? 0xff : 0x00; break; @@ -1381,6 +1860,31 @@ x86_emulate( break; } + case 0xe0 ... 0xe2: /* loop{,z,nz} */ { + int rel = insn_fetch_type(int8_t); + int do_jmp = !(_regs.eflags & EFLG_ZF); /* loopnz */ + if ( b == 0xe1 ) + do_jmp = !do_jmp; /* loopz */ + else if ( b == 0xe2 ) + do_jmp = 1; /* loop */ + switch ( ad_bytes ) + { + case 2: + do_jmp &= --(*(uint16_t *)&_regs.ecx) != 0; + break; + case 4: + do_jmp &= --(*(uint32_t *)&_regs.ecx) != 0; + _regs.ecx = (uint32_t)_regs.ecx; /* zero extend in x86/64 mode */ + break; + default: /* case 8: */ + do_jmp &= --_regs.ecx != 0; + break; + } + if ( do_jmp ) + jmp_rel(rel); + break; + } + case 0xe3: /* jcxz/jecxz (short) */ { int rel = insn_fetch_type(int8_t); if ( (ad_bytes == 2) ? !(uint16_t)_regs.ecx : @@ -1389,12 +1893,26 @@ x86_emulate( break; } - case 0xe9: /* jmp (short) */ + case 0xe8: /* call (near) */ { + int rel = (((op_bytes == 2) && !mode_64bit()) + ? (int32_t)insn_fetch_type(int16_t) + : insn_fetch_type(int32_t)); + op_bytes = mode_64bit() ? 8 : op_bytes; + src.val = _regs.eip; + jmp_rel(rel); + goto push; + } + + case 0xe9: /* jmp (near) */ { + int rel = (((op_bytes == 2) && !mode_64bit()) + ? (int32_t)insn_fetch_type(int16_t) + : insn_fetch_type(int32_t)); + jmp_rel(rel); + break; + } + + case 0xeb: /* jmp (short) */ jmp_rel(insn_fetch_type(int8_t)); - break; - - case 0xeb: /* jmp (near) */ - jmp_rel(insn_fetch_bytes(mode_64bit() ? 4 : op_bytes)); break; case 0xf5: /* cmc */ @@ -1422,9 +1940,14 @@ x86_emulate( twobyte_insn: switch ( b ) { - case 0x40 ... 0x4f: /* cmov */ - dst.val = dst.orig_val = src.val; - d = (d & ~Mov) | (test_cc(b, _regs.eflags) ? Mov : 0); + case 0x40 ... 0x4f: /* cmovcc */ + dst.val = src.val; + if ( !test_cc(b, _regs.eflags) ) + dst.type = OP_NONE; + break; + + case 0x90 ... 0x9f: /* setcc */ + dst.val = test_cc(b, _regs.eflags); break; case 0xb0 ... 0xb1: /* cmpxchg */ @@ -1459,6 +1982,34 @@ x86_emulate( emulate_2op_SrcV_nobyte("bts", src, dst, _regs.eflags); break; + case 0xaf: /* imul */ + _regs.eflags &= ~(EFLG_OF|EFLG_CF); + switch ( dst.bytes ) + { + case 2: + dst.val = ((uint32_t)(int16_t)src.val * + (uint32_t)(int16_t)dst.val); + if ( (int16_t)dst.val != (uint32_t)dst.val ) + _regs.eflags |= EFLG_OF|EFLG_CF; + break; +#ifdef __x86_64__ + case 4: + dst.val = ((uint64_t)(int32_t)src.val * + (uint64_t)(int32_t)dst.val); + if ( (int32_t)dst.val != dst.val ) + _regs.eflags |= EFLG_OF|EFLG_CF; + break; +#endif + default: { + unsigned long m[2] = { src.val, dst.val }; + if ( imul_dbl(m) ) + _regs.eflags |= EFLG_OF|EFLG_CF; + dst.val = m[0]; + break; + } + } + break; + case 0xb6: /* movzx rm8,r{16,32,64} */ /* Recompute DstReg as we may have decoded AH/BH/CH/DH. */ dst.reg = decode_register(modrm_reg, &_regs, 0); @@ -1466,6 +2017,26 @@ x86_emulate( dst.val = (uint8_t)src.val; break; + case 0xbc: /* bsf */ { + int zf; + asm ( "bsf %2,%0; setc %b1" + : "=r" (dst.val), "=q" (zf) + : "r" (src.val), "1" (0) ); + _regs.eflags &= ~EFLG_ZF; + _regs.eflags |= zf ? EFLG_ZF : 0; + break; + } + + case 0xbd: /* bsr */ { + int zf; + asm ( "bsr %2,%0; setc %b1" + : "=r" (dst.val), "=q" (zf) + : "r" (src.val), "1" (0) ); + _regs.eflags &= ~EFLG_ZF; + _regs.eflags |= zf ? EFLG_ZF : 0; + break; + } + case 0xb7: /* movzx rm16,r{16,32,64} */ dst.val = (uint16_t)src.val; break; @@ -1513,10 +2084,13 @@ x86_emulate( { case 0x0d: /* GrpP (prefetch) */ case 0x18: /* Grp16 (prefetch/nop) */ + case 0x19 ... 0x1f: /* nop (amd-defined) */ break; case 0x80 ... 0x8f: /* jcc (near) */ { - int rel = insn_fetch_bytes(mode_64bit() ? 4 : op_bytes); + int rel = (((op_bytes == 2) && !mode_64bit()) + ? (int32_t)insn_fetch_type(int16_t) + : insn_fetch_type(int32_t)); if ( test_cc(b, _regs.eflags) ) jmp_rel(rel); break; @@ -1572,6 +2146,37 @@ x86_emulate( break; } #endif + + case 0xc8 ... 0xcf: /* bswap */ + dst.type = OP_REG; + dst.reg = decode_register(b & 7, &_regs, 0); + dst.val = *dst.reg; + switch ( dst.bytes = op_bytes ) + { + case 2: + dst.val = (((dst.val & 0x00FFUL) << 8) | + ((dst.val & 0xFF00UL) >> 8)); + break; + case 4: + dst.val = (((dst.val & 0x000000FFUL) << 24) | + ((dst.val & 0x0000FF00UL) << 8) | + ((dst.val & 0x00FF0000UL) >> 8) | + ((dst.val & 0xFF000000UL) >> 24)); + break; +#ifdef __x86_64__ + case 8: + dst.val = (((dst.val & 0x00000000000000FFUL) << 56) | + ((dst.val & 0x000000000000FF00UL) << 40) | + ((dst.val & 0x0000000000FF0000UL) << 24) | + ((dst.val & 0x00000000FF000000UL) << 8) | + ((dst.val & 0x000000FF00000000UL) >> 8) | + ((dst.val & 0x0000FF0000000000UL) >> 24) | + ((dst.val & 0x00FF000000000000UL) >> 40) | + ((dst.val & 0xFF00000000000000UL) >> 56)); + break; +#endif + } + break; } goto writeback; diff -r c6b683ba68f5 -r a2b2b2a011f1 xen/common/elf.c --- a/xen/common/elf.c Sun Jan 14 22:18:38 2007 -0700 +++ b/xen/common/elf.c Mon Jan 15 15:15:26 2007 -0700 @@ -300,7 +300,7 @@ int parseelfimage(struct domain_setup_in if ( dsi->__elfnote_section ) { p = xen_elfnote_string(dsi, XEN_ELFNOTE_PAE_MODE); - if ( p != NULL && strncmp(p, "bimodal", 7) == 0 ) + if ( p != NULL && strstr(p, "bimodal") != NULL ) dsi->pae_kernel = PAEKERN_bimodal; else if ( p != NULL && strncmp(p, "yes", 3) == 0 ) dsi->pae_kernel = PAEKERN_extended_cr3; diff -r c6b683ba68f5 -r a2b2b2a011f1 xen/common/kexec.c --- a/xen/common/kexec.c Sun Jan 14 22:18:38 2007 -0700 +++ b/xen/common/kexec.c Mon Jan 15 15:15:26 2007 -0700 @@ -51,19 +51,9 @@ xen_kexec_reserve_t kexec_crash_area; static void __init parse_crashkernel(const char *str) { - unsigned long start, size; - - size = parse_size_and_unit(str, &str); + kexec_crash_area.size = parse_size_and_unit(str, &str); if ( *str == '@' ) - start = parse_size_and_unit(str+1, NULL); - else - start = 0; - - if ( start && size ) - { - kexec_crash_area.start = start; - kexec_crash_area.size = size; - } + kexec_crash_area.start = parse_size_and_unit(str+1, NULL); } custom_param("crashkernel", parse_crashkernel); @@ -158,8 +148,12 @@ static void setup_note(Elf_Note *n, cons static int kexec_get(reserve)(xen_kexec_range_t *range) { - range->start = kexec_crash_area.start; - range->size = kexec_crash_area.size; + if ( kexec_crash_area.size > 0 && kexec_crash_area.start > 0) { + range->start = kexec_crash_area.start; + range->size = kexec_crash_area.size; + } + else + range->start = range->size = 0; return 0; } diff -r c6b683ba68f5 -r a2b2b2a011f1 xen/common/keyhandler.c --- a/xen/common/keyhandler.c Sun Jan 14 22:18:38 2007 -0700 +++ b/xen/common/keyhandler.c Mon Jan 15 15:15:26 2007 -0700 @@ -95,6 +95,11 @@ static void __dump_execstate(void *unuse static void __dump_execstate(void *unused) { dump_execution_state(); + printk("*** Dumping CPU%d guest state: ***\n", smp_processor_id()); + if ( is_idle_vcpu(current) ) + printk("No guest context (CPU is idle).\n"); + else + show_execution_state(guest_cpu_user_regs()); } static void dump_registers(unsigned char key, struct cpu_user_regs *regs) @@ -104,16 +109,18 @@ static void dump_registers(unsigned char printk("'%c' pressed -> dumping registers\n", key); /* Get local execution state out immediately, in case we get stuck. */ - printk("\n*** Dumping CPU%d state: ***\n", smp_processor_id()); - show_execution_state(regs); + printk("\n*** Dumping CPU%d host state: ***\n", smp_processor_id()); + __dump_execstate(NULL); for_each_online_cpu ( cpu ) { if ( cpu == smp_processor_id() ) continue; - printk("\n*** Dumping CPU%d state: ***\n", cpu); + printk("\n*** Dumping CPU%d host state: ***\n", cpu); on_selected_cpus(cpumask_of_cpu(cpu), __dump_execstate, NULL, 1, 1); } + + printk("\n"); } static void halt_machine(unsigned char key, struct cpu_user_regs *regs) diff -r c6b683ba68f5 -r a2b2b2a011f1 xen/common/lib.c --- a/xen/common/lib.c Sun Jan 14 22:18:38 2007 -0700 +++ b/xen/common/lib.c Mon Jan 15 15:15:26 2007 -0700 @@ -1,41 +1,44 @@ #include <xen/ctype.h> #include <xen/lib.h> - - -/* for inc/ctype.h */ +#include <xen/types.h> + +/* for ctype.h */ unsigned char _ctype[] = { -_C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */ -_C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */ -_C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */ -_C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */ -_S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */ -_P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */ -_D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */ -_D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */ -_P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */ -_U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */ -_U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */ -_U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */ -_P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */ -_L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */ -_L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */ -_L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */ -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */ -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */ -_S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 160-175 */ -_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 176-191 */ -_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U, /* 192-207 */ -_U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L, /* 208-223 */ -_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L, /* 224-239 */ -_L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */ - - -/* a couple of 64 bit operations ported from freebsd */ - -/*- + _C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */ + _C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */ + _C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */ + _C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */ + _S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */ + _P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */ + _D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */ + _D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */ + _P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */ + _U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */ + _U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */ + _U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */ + _P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */ + _L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */ + _L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */ + _L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */ + _S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 160-175 */ + _P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 176-191 */ + _U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U, /* 192-207 */ + _U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L, /* 208-223 */ + _L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L, /* 224-239 */ + _L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */ + +/* + * A couple of 64 bit operations ported from FreeBSD. + * The code within the '#if BITS_PER_LONG == 32' block below, and no other + * code in this file, is distributed under the following licensing terms + * This is the modified '3-clause' BSD license with the obnoxious + * advertising clause removed, as permitted by University of California. + * * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. + * The Regents of the University of California. All rights reserved. * * This software was developed by the Computer Systems Engineering group * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and @@ -49,11 +52,7 @@ _L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -68,12 +67,7 @@ _L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD: src/sys/libkern/divdi3.c,v 1.6 1999/08/28 00:46:31 peter Exp $ - */ - -#include <asm/types.h> - + */ #if BITS_PER_LONG == 32 /* @@ -81,10 +75,10 @@ _L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_ * one or more of the following formats. */ union uu { - s64 q; /* as a (signed) quad */ - s64 uq; /* as an unsigned quad */ - long sl[2]; /* as two signed longs */ - unsigned long ul[2]; /* as two unsigned longs */ + s64 q; /* as a (signed) quad */ + s64 uq; /* as an unsigned quad */ + long sl[2]; /* as two signed longs */ + unsigned long ul[2]; /* as two unsigned longs */ }; /* XXX RN: Yuck hardcoded endianess :) */ #define _QUAD_HIGHWORD 1 @@ -122,31 +116,26 @@ union uu { * Multiprecision divide. This algorithm is from Knuth vol. 2 (2nd ed), * section 4.3.1, pp. 257--259. */ -#define B (1 << HALF_BITS) /* digit base */ +#define B (1 << HALF_BITS) /* digit base */ /* Combine two `digits' to make a single two-digit number. */ -#define COMBINE(a, b) (((u_long)(a) << HALF_BITS) | (b)) - -/* select a type for digits in base B: use unsigned short if they fit */ -#if ULONG_MAX == 0xffffffff && USHRT_MAX >= 0xffff -typedef unsigned short digit; -#else +#define COMBINE(a, b) (((u_long)(a) << HALF_BITS) | (b)) + +/* select a type for digits in base B */ typedef u_long digit; -#endif /* * Shift p[0]..p[len] left `sh' bits, ignoring any bits that * `fall out' the left (there never will be any such anyway). * We may assume len >= 0. NOTE THAT THIS WRITES len+1 DIGITS. */ -static void -shl(register digit *p, register int len, register int sh) -{ - register int i; - - for (i = 0; i < len; i++) - p[i] = LHALF(p[i] << sh) | (p[i + 1] >> (HALF_BITS - sh)); - p[i] = LHALF(p[i] << sh); +static void shl(register digit *p, register int len, register int sh) +{ + register int i; + + for (i = 0; i < len; i++) + p[i] = LHALF(p[i] << sh) | (p[i + 1] >> (HALF_BITS - sh)); + p[i] = LHALF(p[i] << sh); } /* @@ -157,234 +146,222 @@ shl(register digit *p, register int len, * divisor are 4 `digits' in this base (they are shorter if they have * leading zeros). */ -u64 -__qdivrem(u64 uq, u64 vq, u64 *arq) -{ - union uu tmp; - digit *u, *v, *q; - register digit v1, v2; - u_long qhat, rhat, t; - int m, n, d, j, i; - digit uspace[5], vspace[5], qspace[5]; - - /* - * Take care of special cases: divide by zero, and u < v. - */ - if (vq == 0) { - /* divide by zero. */ - static volatile const unsigned int zero = 0; - - tmp.ul[H] = tmp.ul[L] = 1 / zero; - if (arq) - *arq = uq; - return (tmp.q); - } - if (uq < vq) { - if (arq) - *arq = uq; - return (0); - } - u = &uspace[0]; - v = &vspace[0]; - q = &qspace[0]; - - /* - * Break dividend and divisor into digits in base B, then - * count leading zeros to determine m and n. When done, we - * will have: - * u = (u[1]u[2]...u[m+n]) sub B - * v = (v[1]v[2]...v[n]) sub B - * v[1] != 0 - * 1 < n <= 4 (if n = 1, we use a different division algorithm) - * m >= 0 (otherwise u < v, which we already checked) - * m + n = 4 - * and thus - * m = 4 - n <= 2 - */ - tmp.uq = uq; - u[0] = 0; - u[1] = HHALF(tmp.ul[H]); - u[2] = LHALF(tmp.ul[H]); - u[3] = HHALF(tmp.ul[L]); - u[4] = LHALF(tmp.ul[L]); - tmp.uq = vq; - v[1] = HHALF(tmp.ul[H]); - v[2] = LHALF(tmp.ul[H]); - v[3] = HHALF(tmp.ul[L]); - v[4] = LHALF(tmp.ul[L]); - for (n = 4; v[1] == 0; v++) { - if (--n == 1) { - u_long rbj; /* r*B+u[j] (not root boy jim) */ - digit q1, q2, q3, q4; - - /* - * Change of plan, per exercise 16. - * r = 0; - * for j = 1..4: - * q[j] = floor((r*B + u[j]) / v), - * r = (r*B + u[j]) % v; - * We unroll this completely here. - */ - t = v[2]; /* nonzero, by definition */ - q1 = u[1] / t; - rbj = COMBINE(u[1] % t, u[2]); - q2 = rbj / t; - rbj = COMBINE(rbj % t, u[3]); - q3 = rbj / t; - rbj = COMBINE(rbj % t, u[4]); - q4 = rbj / t; - if (arq) - *arq = rbj % t; - tmp.ul[H] = COMBINE(q1, q2); - tmp.ul[L] = COMBINE(q3, q4); - return (tmp.q); - } - } - - /* - * By adjusting q once we determine m, we can guarantee that - * there is a complete four-digit quotient at &qspace[1] when - * we finally stop. - */ - for (m = 4 - n; u[1] == 0; u++) - m--; - for (i = 4 - m; --i >= 0;) - q[i] = 0; - q += 4 - m; - - /* - * Here we run Program D, translated from MIX to C and acquiring - * a few minor changes. - * - * D1: choose multiplier 1 << d to ensure v[1] >= B/2. - */ - d = 0; - for (t = v[1]; t < B / 2; t <<= 1) - d++; - if (d > 0) { - shl(&u[0], m + n, d); /* u <<= d */ - shl(&v[1], n - 1, d); /* v <<= d */ - } - /* - * D2: j = 0. - */ - j = 0; - v1 = v[1]; /* for D3 -- note that v[1..n] are constant */ - v2 = v[2]; /* for D3 */ - do { - register digit uj0, uj1, uj2; - - /* - * D3: Calculate qhat (\^q, in TeX notation). - * Let qhat = min((u[j]*B + u[j+1])/v[1], B-1), and - * let rhat = (u[j]*B + u[j+1]) mod v[1]. - * While rhat < B and v[2]*qhat > rhat*B+u[j+2], - * decrement qhat and increase rhat correspondingly. - * Note that if rhat >= B, v[2]*qhat < rhat*B. - */ - uj0 = u[j + 0]; /* for D3 only -- note that u[j+...] change */ - uj1 = u[j + 1]; /* for D3 only */ - uj2 = u[j + 2]; /* for D3 only */ - if (uj0 == v1) { - qhat = B; - rhat = uj1; - goto qhat_too_big; - } else { - u_long nn = COMBINE(uj0, uj1); - qhat = nn / v1; - rhat = nn % v1; - } - while (v2 * qhat > COMBINE(rhat, uj2)) { - qhat_too_big: - qhat--; - if ((rhat += v1) >= B) - break; - } - /* - * D4: Multiply and subtract. - * The variable `t' holds any borrows across the loop. - * We split this up so that we do not require v[0] = 0, - * and to eliminate a final special case. - */ - for (t = 0, i = n; i > 0; i--) { - t = u[i + j] - v[i] * qhat - t; - u[i + j] = LHALF(t); - t = (B - HHALF(t)) & (B - 1); - } - t = u[j] - t; - u[j] = LHALF(t); - /* - * D5: test remainder. - * There is a borrow if and only if HHALF(t) is nonzero; - * in that (rare) case, qhat was too large (by exactly 1). - * Fix it by adding v[1..n] to u[j..j+n]. - */ - if (HHALF(t)) { - qhat--; - for (t = 0, i = n; i > 0; i--) { /* D6: add back. */ - t += u[i + j] + v[i]; - u[i + j] = LHALF(t); - t = HHALF(t); - } - u[j] = LHALF(u[j] + t); - } - q[j] = qhat; - } while (++j <= m); /* D7: loop on j. */ - - /* - * If caller wants the remainder, we have to calculate it as - * u[m..m+n] >> d (this is at most n digits and thus fits in - * u[m+1..m+n], but we may need more source digits). - */ - if (arq) { - if (d) { - for (i = m + n; i > m; --i) - u[i] = (u[i] >> d) | - LHALF(u[i - 1] << (HALF_BITS - d)); - u[i] = 0; - } - tmp.ul[H] = COMBINE(uspace[1], uspace[2]); - tmp.ul[L] = COMBINE(uspace[3], uspace[4]); - *arq = tmp.q; - } - - tmp.ul[H] = COMBINE(qspace[1], qspace[2]); - tmp.ul[L] = COMBINE(qspace[3], qspace[4]); - return (tmp.q); +u64 __qdivrem(u64 uq, u64 vq, u64 *arq) +{ + union uu tmp; + digit *u, *v, *q; + register digit v1, v2; + u_long qhat, rhat, t; + int m, n, d, j, i; + digit uspace[5], vspace[5], qspace[5]; + + /* + * Take care of special cases: divide by zero, and u < v. + */ + if (vq == 0) { + /* divide by zero. */ + static volatile const unsigned int zero = 0; + + tmp.ul[H] = tmp.ul[L] = 1 / zero; + if (arq) + *arq = uq; + return (tmp.q); + } + if (uq < vq) { + if (arq) + *arq = uq; + return (0); + } + u = &uspace[0]; + v = &vspace[0]; + q = &qspace[0]; + + /* + * Break dividend and divisor into digits in base B, then + * count leading zeros to determine m and n. When done, we + * will have: + * u = (u[1]u[2]...u[m+n]) sub B + * v = (v[1]v[2]...v[n]) sub B + * v[1] != 0 + * 1 < n <= 4 (if n = 1, we use a different division algorithm) + * m >= 0 (otherwise u < v, which we already checked) + * m + n = 4 + * and thus + * m = 4 - n <= 2 + */ + tmp.uq = uq; + u[0] = 0; + u[1] = HHALF(tmp.ul[H]); + u[2] = LHALF(tmp.ul[H]); + u[3] = HHALF(tmp.ul[L]); + u[4] = LHALF(tmp.ul[L]); + tmp.uq = vq; + v[1] = HHALF(tmp.ul[H]); + v[2] = LHALF(tmp.ul[H]); + v[3] = HHALF(tmp.ul[L]); + v[4] = LHALF(tmp.ul[L]); + for (n = 4; v[1] == 0; v++) { + if (--n == 1) { + u_long rbj; /* r*B+u[j] (not root boy jim) */ + digit q1, q2, q3, q4; + + /* + * Change of plan, per exercise 16. + * r = 0; + * for j = 1..4: + * q[j] = floor((r*B + u[j]) / v), + * r = (r*B + u[j]) % v; + * We unroll this completely here. + */ + t = v[2]; /* nonzero, by definition */ + q1 = u[1] / t; + rbj = COMBINE(u[1] % t, u[2]); + q2 = rbj / t; + rbj = COMBINE(rbj % t, u[3]); + q3 = rbj / t; + rbj = COMBINE(rbj % t, u[4]); + q4 = rbj / t; + if (arq) + *arq = rbj % t; + tmp.ul[H] = COMBINE(q1, q2); + tmp.ul[L] = COMBINE(q3, q4); + return (tmp.q); + } + } + + /* + * By adjusting q once we determine m, we can guarantee that + * there is a complete four-digit quotient at &qspace[1] when + * we finally stop. + */ + for (m = 4 - n; u[1] == 0; u++) + m--; + for (i = 4 - m; --i >= 0;) + q[i] = 0; + q += 4 - m; + + /* + * Here we run Program D, translated from MIX to C and acquiring + * a few minor changes. + * + * D1: choose multiplier 1 << d to ensure v[1] >= B/2. + */ + d = 0; + for (t = v[1]; t < B / 2; t <<= 1) + d++; + if (d > 0) { + shl(&u[0], m + n, d); /* u <<= d */ + shl(&v[1], n - 1, d); /* v <<= d */ + } + /* + * D2: j = 0. + */ + j = 0; + v1 = v[1]; /* for D3 -- note that v[1..n] are constant */ + v2 = v[2]; /* for D3 */ + do { + register digit uj0, uj1, uj2; + + /* + * D3: Calculate qhat (\^q, in TeX notation). + * Let qhat = min((u[j]*B + u[j+1])/v[1], B-1), and + * let rhat = (u[j]*B + u[j+1]) mod v[1]. + * While rhat < B and v[2]*qhat > rhat*B+u[j+2], + * decrement qhat and increase rhat correspondingly. + * Note that if rhat >= B, v[2]*qhat < rhat*B. + */ + uj0 = u[j + 0]; /* for D3 only -- note that u[j+...] change */ + uj1 = u[j + 1]; /* for D3 only */ + uj2 = u[j + 2]; /* for D3 only */ + if (uj0 == v1) { + qhat = B; + rhat = uj1; + goto qhat_too_big; + } else { + u_long nn = COMBINE(uj0, uj1); + qhat = nn / v1; + rhat = nn % v1; + } + while (v2 * qhat > COMBINE(rhat, uj2)) { + qhat_too_big: + qhat--; + if ((rhat += v1) >= B) + break; + } + /* + * D4: Multiply and subtract. + * The variable `t' holds any borrows across the loop. + * We split this up so that we do not require v[0] = 0, + * and to eliminate a final special case. + */ + for (t = 0, i = n; i > 0; i--) { + t = u[i + j] - v[i] * qhat - t; + u[i + j] = LHALF(t); + t = (B - HHALF(t)) & (B - 1); + } + t = u[j] - t; + u[j] = LHALF(t); + /* + * D5: test remainder. + * There is a borrow if and only if HHALF(t) is nonzero; + * in that (rare) case, qhat was too large (by exactly 1). + * Fix it by adding v[1..n] to u[j..j+n]. + */ + if (HHALF(t)) { + qhat--; + for (t = 0, i = n; i > 0; i--) { /* D6: add back. */ + t += u[i + j] + v[i]; + u[i + j] = LHALF(t); + t = HHALF(t); + } + u[j] = LHALF(u[j] + t); + } + q[j] = qhat; + } while (++j <= m); /* D7: loop on j. */ + + /* + * If caller wants the remainder, we have to calculate it as + * u[m..m+n] >> d (this is at most n digits and thus fits in + * u[m+1..m+n], but we may need more source digits). + */ + if (arq) { + if (d) { + for (i = m + n; i > m; --i) + u[i] = (u[i] >> d) | + LHALF(u[i - 1] << (HALF_BITS - d)); + u[i] = 0; + } + tmp.ul[H] = COMBINE(uspace[1], uspace[2]); + tmp.ul[L] = COMBINE(uspace[3], uspace[4]); + *arq = tmp.q; + } + + tmp.ul[H] = COMBINE(qspace[1], qspace[2]); + tmp.ul[L] = COMBINE(qspace[3], qspace[4]); + return (tmp.q); } /* * Divide two signed quads. - * ??? if -1/2 should produce -1 on this machine, this code is wrong - * (Grzegorz Milos) Note for the above: -1/2 is 0. And so it should. - */ -s64 -__divdi3(s64 a, s64 b) -{ - u64 ua, ub, uq; - int neg; - - if (a < 0) - ua = -(u64)a, neg = 1; - else - ua = a, neg = 0; - if (b < 0) - ub = -(u64)b, neg ^= 1; - else - ub = b; - uq = __qdivrem(ua, ub, (u64 *)0); - return (neg ? -uq : uq); + * Truncates towards zero, as required by C99. + */ +s64 __divdi3(s64 a, s64 b) +{ + u64 ua, ub, uq; + int neg = (a < 0) ^ (b < 0); + ua = (a < 0) ? -(u64)a : a; + ub = (b < 0) ? -(u64)b : b; + uq = __qdivrem(ua, ub, (u64 *)0); + return (neg ? -uq : uq); } /* * Divide two unsigned quads. */ -u64 -__udivdi3(u64 a, u64 b) -{ - - return (__qdivrem(a, b, (u64 *)0)); +u64 __udivdi3(u64 a, u64 b) +{ + return __qdivrem(a, b, (u64 *)0); } /* @@ -392,87 +369,66 @@ __udivdi3(u64 a, u64 b) */ u64 __umoddi3(u64 a, u64 b) { - u64 rem; - __qdivrem(a, b, &rem); - return rem; + u64 rem; + __qdivrem(a, b, &rem); + return rem; } /* * Remainder of signed quad division. - * The result of mod is not always equal to division - * remainder. The following example shows the result for all - * four possible cases: + * Truncates towards zero, as required by C99: * 11 % 5 = 1 - * -11 % 5 = 4 - * 11 % -5 = -4 - * -11 % -5 = -1 + * -11 % 5 = -1 + * 11 % -5 = 1 + * -11 % -5 = 1 */ s64 __moddi3(s64 a, s64 b) { - u64 ua, ub, urem; - int neg1, neg2; - - if (a < 0) - ua = -(u64)a, neg1 = 1; - else - ua = a, neg1 = 0; - - if (b < 0) - ub = -(u64)b, neg2 = 1; - else - ub = b, neg2 = 0; - __qdivrem(ua, ub, &urem); - - /* There 4 different cases: */ - if (neg1) { - if (neg2) - return -urem; - else - return ub - urem; - } else { - if (neg2) - return -ub + urem; - else - return urem; - } + u64 ua, ub, urem; + int neg = (a < 0); + ua = neg ? -(u64)a : a; + ub = (b < 0) ? -(u64)b : b; + __qdivrem(ua, ub, &urem); + return (neg ? -urem : urem); } #endif /* BITS_PER_LONG == 32 */ unsigned long long parse_size_and_unit(const char *s, const char **ps) { - unsigned long long ret; - const char *s1; - - ret = simple_strtoull(s, &s1, 0); - - switch (*s1) { - case 'G': case 'g': - ret <<= 10; - case 'M': case 'm': - ret <<= 10; - case 'K': case 'k': - ret <<= 10; - case 'B': case 'b': - s1++; - break; - default: - ret <<= 10; /* default to kB */ - break; - } - - if (ps != NULL) - *ps = s1; - - return ret; + unsigned long long ret; + const char *s1; + + ret = simple_strtoull(s, &s1, 0); + + switch ( *s1 ) + { + case 'G': case 'g': + ret <<= 10; + case 'M': case 'm': + ret <<= 10; + case 'K': case 'k': + ret <<= 10; + case 'B': case 'b': + s1++; + break; + default: + ret <<= 10; /* default to kB */ + break; + } + + if ( ps != NULL ) + *ps = s1; + + return ret; } /* * Local variables: * mode: C * c-set-style: "BSD" - * c-basic-offset: 8 - * tab-width: 8 - * indent-tabs-mode: t + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil * End: */ diff -r c6b683ba68f5 -r a2b2b2a011f1 xen/common/xencomm.c --- a/xen/common/xencomm.c Sun Jan 14 22:18:38 2007 -0700 +++ b/xen/common/xencomm.c Mon Jan 15 15:15:26 2007 -0700 @@ -119,7 +119,7 @@ xencomm_copy_from_guest(void *to, const chunksz -= chunk_skip; skip -= chunk_skip; - if (skip == 0) { + if (skip == 0 && chunksz > 0) { unsigned long src_maddr; unsigned long dest = (unsigned long)to + to_pos; unsigned int bytes = min(chunksz, n - to_pos); @@ -225,7 +225,7 @@ xencomm_copy_to_guest(void *to, const vo chunksz -= chunk_skip; skip -= chunk_skip; - if (skip == 0) { + if (skip == 0 && chunksz > 0) { unsigned long dest_maddr; unsigned long source = (unsigned long)from + from_pos; unsigned int bytes = min(chunksz, n - from_pos); diff -r c6b683ba68f5 -r a2b2b2a011f1 xen/drivers/video/vga.c --- a/xen/drivers/video/vga.c Sun Jan 14 22:18:38 2007 -0700 +++ b/xen/drivers/video/vga.c Mon Jan 15 15:15:26 2007 -0700 @@ -557,7 +557,7 @@ static int vga_load_font(const struct fo static int vgacon_enabled = 0; static int vgacon_keep = 0; -static int vgacon_lines = 25; +static int vgacon_lines = 50; static const struct font_desc *font; static int xpos, ypos; @@ -606,12 +606,9 @@ void vga_init(void) case 60: font = &font_vga_8x8; break; - default: - vgacon_lines = 25; - break; - } - - if ( (font != NULL) && (vga_load_font(font, vgacon_lines) < 0) ) + } + + if ( (font == NULL) || (vga_load_font(font, vgacon_lines) < 0) ) { vgacon_lines = 25; font = NULL; diff -r c6b683ba68f5 -r a2b2b2a011f1 xen/include/Makefile --- a/xen/include/Makefile Sun Jan 14 22:18:38 2007 -0700 +++ b/xen/include/Makefile Mon Jan 15 15:15:26 2007 -0700 @@ -2,8 +2,28 @@ ifneq ($(CONFIG_COMPAT),) compat-arch-$(CONFIG_X86) := x86_32 -headers-y := $(shell echo public/*.h | sed -e 's,[^[:space:]]*-[^[:space:]]*,,g' -e 's,public/,compat/,g') -headers-y := $(filter-out %/dom0_ops.h,$(headers-y)) +headers-y := \ + compat/acm.h \ + compat/acm_ops.h \ + compat/callback.h \ + compat/domctl.h \ + compat/elfnote.h \ + compat/event_channel.h \ + compat/features.h \ + compat/grant_table.h \ + compat/kexec.h \ + compat/memory.h \ + compat/nmi.h \ + compat/physdev.h \ + compat/platform.h \ + compat/sched.h \ + compat/sysctl.h \ + compat/trace.h \ + compat/vcpu.h \ + compat/version.h \ + compat/xen.h \ + compat/xencomm.h \ + compat/xenoprof.h headers-$(CONFIG_X86) += compat/arch-x86/xen.h headers-$(CONFIG_X86) += compat/arch-x86/xen-$(compat-arch-y).h headers-y += compat/arch-$(compat-arch-y).h compat/xlat.h @@ -21,24 +41,14 @@ all: $(headers-y) all: $(headers-y) compat/%.h: compat/%.i Makefile - id=_$$(echo $@ | sed 'y,abcdefghijklmnopqrstuvwxyz-/.,ABCDEFGHIJKLMNOPQRSTUVWXYZ___,'); \ + id=_$$(echo $@ | tr '[:lower:]-/.' '[:upper:]___'); \ echo "#ifndef $$id" >$@.new; \ echo "#define $$id" >>$@.new; \ echo "#include <xen/compat.h>" >>$@.new; \ $(if $(filter-out compat/arch-%.h,$@),echo "#include <$(patsubst compat/%,public/%,$@)>" >>$@.new;) \ $(if $(prefix-y),echo "$(prefix-y)" >>$@.new;) \ - grep -v '^# [[:digit:]]' $< | \ - sed -e 's,__InClUdE__,#include,' \ - -e 's,"xen-compat.h",<public/xen-compat.h>,' \ - -e 's,\(struct\|union\|enum\)[[:space:]]\+\(xen_\?\)\?\([[:alpha:]_]\),\1 compat_\3,g' \ - -e 's,@KeeP@,,g' \ - -e 's,_t\([^[:alnum:]_]\|$$\),_compat_t\1,g' \ - -e 's,\(8\|16\|32\|64\)_compat_t\([^[:alnum:]_]\|$$\),\1_t\2,g' \ - -e 's,\(^\|[^[:alnum:]_]\)xen_\?\([[:alnum:]_]*\)_compat_t\([^[:alnum:]_]\|$$\),\1compat_\2_t\3,g' \ - -e 's,\(^\|[^[:alnum:]_]\)XEN_\?,\1COMPAT_,' \ - -e 's,\(^\|[^[:alnum:]_]\)Xen_\?,\1Compat_,' \ - -e 's,\(^\|[^[:alnum:]]\)long\([^[:alnum:]]\|$$\),\1int\2,g' | \ - uniq >>$@.new; \ + grep -v '^# [0-9]' $< | \ + $(BASEDIR)/tools/compat-build-header.py | uniq >>$@.new; \ $(if $(suffix-y),echo "$(suffix-y)" >>$@.new;) \ echo "#endif /* $$id */" >>$@.new mv -f $@.new $@ @@ -49,19 +59,13 @@ compat/%.c: public/%.h xlat.lst Makefile compat/%.c: public/%.h xlat.lst Makefile mkdir -p $(@D) grep -v 'DEFINE_XEN_GUEST_HANDLE(long)' $< | \ - sed -e 's,^[[:space:]]*#[[:space:]]*include[[:space:]]\+,__InClUdE__ ,' \ - -e 's,^[[:space:]]*#[[:space:]]*define[[:space:]]\+\([[:upper:]_]*_GUEST_HANDLE\),#define HIDE_\1,' \ - -e 's,^[[:space:]]*#[[:space:]]*define[[:space:]]\+\([[:lower:]_]*_guest_handle\),#define hide_\1,' \ - -e 's,XEN_GUEST_HANDLE\(_[[:xdigit:]]\+\)\?,COMPAT_HANDLE,g' \ - $(foreach n,$(shell sed -n 's,^[[:space:]]*?[[:space:]]\+\([[:alnum:]_]*\)[[:space:]].*,\1,p' xlat.lst), \ - -e 's,\(struct\|union\)[[:space:]]\+\(xen_\?\)\?$n[[:space:]]\+\([[:alpha:]_]\),\1 @KeeP@\2$n \3,g') \ - >$@.new + $(BASEDIR)/tools/compat-build-source.py >$@.new mv -f $@.new $@ compat/xlat.h: xlat.lst $(filter-out compat/xlat.h,$(headers-y)) $(BASEDIR)/tools/get-fields.sh Makefile - grep -v '^[[:space:]]*#' xlat.lst | \ + grep -v '^[ ]*#' xlat.lst | \ while read what name hdr; do \ - $(SHELL) $(BASEDIR)/tools/get-fields.sh "$$what" compat_$$name $$(echo compat/$$hdr | sed 's,@arch@,$(compat-arch-y),g') || exit $$?; \ + /bin/bash $(BASEDIR)/tools/get-fields.sh "$$what" compat_$$name $$(echo compat/$$hdr | sed 's,@arch@,$(compat-arch-y),g') || exit $$?; \ done >$@.new mv -f $@.new $@ diff -r c6b683ba68f5 -r a2b2b2a011f1 xen/include/asm-x86/guest_access.h --- a/xen/include/asm-x86/guest_access.h Sun Jan 14 22:18:38 2007 -0700 +++ b/xen/include/asm-x86/guest_access.h Mon Jan 15 15:15:26 2007 -0700 @@ -32,7 +32,7 @@ * specifying an offset into the guest array. */ #define copy_to_guest_offset(hnd, off, ptr, nr) ({ \ - const typeof(ptr) _x = (hnd).p; \ + typeof(ptr) _x = (hnd).p; \ const typeof(ptr) _y = (ptr); \ is_hvm_vcpu(current) ? \ copy_to_user_hvm(_x+(off), _y, sizeof(*_x)*(nr)) : \ @@ -45,7 +45,7 @@ */ #define copy_from_guest_offset(ptr, hnd, off, nr) ({ \ const typeof(ptr) _x = (hnd).p; \ - const typeof(ptr) _y = (ptr); \ + typeof(ptr) _y = (ptr); \ is_hvm_vcpu(current) ? \ copy_from_user_hvm(_y, _x+(off), sizeof(*_x)*(nr)) :\ copy_from_user(_y, _x+(off), sizeof(*_x)*(nr)); \ @@ -53,7 +53,7 @@ /* Copy sub-field of a structure to guest context via a guest handle. */ #define copy_field_to_guest(hnd, ptr, field) ({ \ - const typeof(&(ptr)->field) _x = &(hnd).p->field; \ + typeof(&(ptr)->field) _x = &(hnd).p->field; \ const typeof(&(ptr)->field) _y = &(ptr)->field; \ is_hvm_vcpu(current) ? \ copy_to_user_hvm(_x, _y, sizeof(*_x)) : \ @@ -63,7 +63,7 @@ /* Copy sub-field of a structure from guest context via a guest handle. */ #define copy_field_from_guest(ptr, hnd, field) ({ \ const typeof(&(ptr)->field) _x = &(hnd).p->field; \ - const typeof(&(ptr)->field) _y = &(ptr)->field; \ + typeof(&(ptr)->field) _y = &(ptr)->field; \ is_hvm_vcpu(current) ? \ copy_from_user_hvm(_y, _x, sizeof(*_x)) : \ copy_from_user(_y, _x, sizeof(*_x)); \ @@ -78,7 +78,7 @@ array_access_ok((hnd).p, (nr), sizeof(*(hnd).p))) #define __copy_to_guest_offset(hnd, off, ptr, nr) ({ \ - const typeof(ptr) _x = (hnd).p; \ + typeof(ptr) _x = (hnd).p; \ const typeof(ptr) _y = (ptr); \ is_hvm_vcpu(current) ? \ copy_to_user_hvm(_x+(off), _y, sizeof(*_x)*(nr)) : \ @@ -87,14 +87,14 @@ #define __copy_from_guest_offset(ptr, hnd, off, nr) ({ \ const typeof(ptr) _x = (hnd).p; \ - const typeof(ptr) _y = (ptr); \ + typeof(ptr) _y = (ptr); \ is_hvm_vcpu(current) ? \ copy_from_user_hvm(_y, _x+(off),sizeof(*_x)*(nr)) : \ __copy_from_user(_y, _x+(off), sizeof(*_x)*(nr)); \ }) #define __copy_field_to_guest(hnd, ptr, field) ({ \ - const typeof(&(ptr)->field) _x = &(hnd).p->field; \ + typeof(&(ptr)->field) _x = &(hnd).p->field; \ const typeof(&(ptr)->field) _y = &(ptr)->field; \ is_hvm_vcpu(current) ? \ copy_to_user_hvm(_x, _y, sizeof(*_x)) : \ @@ -103,9 +103,9 @@ #define __copy_field_from_guest(ptr, hnd, field) ({ \ const typeof(&(ptr)->field) _x = &(hnd).p->field; \ - const typeof(&(ptr)->field) _y = &(ptr)->field; \ + typeof(&(ptr)->field) _y = &(ptr)->field; \ is_hvm_vcpu(current) ? \ - copy_from_user_hvm(_x, _y, sizeof(*_x)) : \ + copy_from_user_hvm(_y, _x, sizeof(*_x)) : \ __copy_from_user(_y, _x, sizeof(*_x)); \ }) diff -r c6b683ba68f5 -r a2b2b2a011f1 xen/include/asm-x86/hvm/irq.h --- a/xen/include/asm-x86/hvm/irq.h Sun Jan 14 22:18:38 2007 -0700 +++ b/xen/include/asm-x86/hvm/irq.h Mon Jan 15 15:15:26 2007 -0700 @@ -43,9 +43,17 @@ struct hvm_irq { */ DECLARE_BITMAP(isa_irq, 16); - /* Virtual interrupt wire and GSI link for paravirtual platform driver. */ - DECLARE_BITMAP(callback_irq_wire, 1); - unsigned int callback_gsi; + /* Virtual interrupt and via-link for paravirtual platform driver. */ + unsigned int callback_via_asserted; + enum { + HVMIRQ_callback_none, + HVMIRQ_callback_gsi, + HVMIRQ_callback_pci_intx + } callback_via_type; + union { + unsigned int gsi; + struct { uint8_t dev, intx; } pci; + } callback_via; /* * PCI-ISA interrupt router. @@ -105,7 +113,7 @@ void hvm_set_pci_link_route(struct domai void hvm_set_pci_link_route(struct domain *d, u8 link, u8 isa_irq); void hvm_set_callback_irq_level(void); -void hvm_set_callback_gsi(struct domain *d, unsigned int gsi); +void hvm_set_callback_via(struct domain *d, uint64_t via); int cpu_get_interrupt(struct vcpu *v, int *type); int cpu_has_pending_irq(struct vcpu *v); diff -r c6b683ba68f5 -r a2b2b2a011f1 xen/include/asm-x86/x86_emulate.h --- a/xen/include/asm-x86/x86_emulate.h Sun Jan 14 22:18:38 2007 -0700 +++ b/xen/include/asm-x86/x86_emulate.h Mon Jan 15 15:15:26 2007 -0700 @@ -3,7 +3,21 @@ * * Generic x86 (32-bit and 64-bit) instruction decoder and emulator. * - * Copyright (c) 2005 Keir Fraser + * Copyright (c) 2005-2007 Keir Fraser + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __X86_EMULATE_H__ diff -r c6b683ba68f5 -r a2b2b2a011f1 xen/include/public/elfnote.h --- a/xen/include/public/elfnote.h Sun Jan 14 22:18:38 2007 -0700 +++ b/xen/include/public/elfnote.h Mon Jan 15 15:15:26 2007 -0700 @@ -40,8 +40,6 @@ /* * NAME=VALUE pair (string). - * - * LEGACY: FEATURES and PAE */ #define XEN_ELFNOTE_INFO 0 @@ -108,7 +106,12 @@ #define XEN_ELFNOTE_LOADER 8 /* - * The kernel supports PAE (x86/32 only, string = "yes" or "no"). + * The kernel supports PAE (x86/32 only, string = "yes", "no" or + * "bimodal"). + * + * For compatibility with Xen 3.0.3 and earlier the "bimodal" setting + * may be given as "yes,bimodal" which will cause older Xen to treat + * this kernel as PAE. * * LEGACY: PAE (n.b. The legacy interface included a provision to * indicate 'extended-cr3' support allowing L3 page tables to be diff -r c6b683ba68f5 -r a2b2b2a011f1 xen/include/public/hvm/params.h --- a/xen/include/public/hvm/params.h Sun Jan 14 22:18:38 2007 -0700 +++ b/xen/include/public/hvm/params.h Mon Jan 15 15:15:26 2007 -0700 @@ -24,13 +24,33 @@ #include "hvm_op.h" -/* Parameter space for HVMOP_{set,get}_param. */ +/* + * Parameter space for HVMOP_{set,get}_param. + */ + +/* + * How should CPU0 event-channel notifications be delivered? + * val[63:56] == 0: val[55:0] is a delivery GSI (Global System Interrupt). + * val[63:56] == 1: val[55:0] is a delivery PCI INTx line, as follows: + * Domain = val[47:32], Bus = val[31:16], + * DevFn = val[15: 8], IntX = val[ 1: 0] + * If val == 0 then CPU0 event-channel notifications are not delivered. + */ #define HVM_PARAM_CALLBACK_IRQ 0 + +/* + * These are not used by Xen. They are here for convenience of HVM-guest + * xenbus implementations. + */ #define HVM_PARAM_STORE_PFN 1 #define HVM_PARAM_STORE_EVTCHN 2 + #define HVM_PARAM_PAE_ENABLED 4 + #define HVM_PARAM_IOREQ_PFN 5 + #define HVM_PARAM_BUFIOREQ_PFN 6 + #define HVM_NR_PARAMS 7 #endif /* __XEN_PUBLIC_HVM_PARAMS_H__ */ diff -r c6b683ba68f5 -r a2b2b2a011f1 xen/tools/compat-build-header.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/tools/compat-build-header.py Mon Jan 15 15:15:26 2007 -0700 @@ -0,0 +1,21 @@ +#!/usr/bin/python + +import re,sys + +pats = [ + [ r"__InClUdE__", r"#include" ], + [ r"\"xen-compat.h\"", r"<public/xen-compat.h>" ], + [ r"(struct|union|enum)\s+(xen_?)?(\w)", r"\1 compat_\3" ], + [ r"@KeeP@", r"" ], + [ r"_t([^\w]|$)", r"_compat_t\1" ], + [ r"(8|16|32|64)_compat_t([^\w]|$)", r"\1_t\2" ], + [ r"(^|[^\w])xen_?(\w*)_compat_t([^\w]|$$)", r"\1compat_\2_t\3" ], + [ r"(^|[^\w])XEN_?", r"\1COMPAT_" ], + [ r"(^|[^\w])Xen_?", r"\1Compat_" ], + [ r"(^|[^\w])long([^\w]|$$)", r"\1int\2" ] +]; + +for line in sys.stdin.readlines(): + for pat in pats: + line = re.subn(pat[0], pat[1], line)[0] + print line.rstrip() diff -r c6b683ba68f5 -r a2b2b2a011f1 xen/tools/compat-build-source.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/tools/compat-build-source.py Mon Jan 15 15:15:26 2007 -0700 @@ -0,0 +1,27 @@ +#!/usr/bin/python + +import re,sys + +pats = [ + [ r"^\s*#\s*include\s+", r"__InClUdE__ " ], + [ r"^\s*#\s*define\s+([A-Z_]*_GUEST_HANDLE)", r"#define HIDE_\1" ], + [ r"^\s*#\s*define\s+([a-z_]*_guest_handle)", r"#define hide_\1" ], + [ r"XEN_GUEST_HANDLE(_[0-9A-Fa-f]+)?", r"COMPAT_HANDLE" ], +]; + +xlats = [] + +xlatf = open('xlat.lst', 'r') +for line in xlatf.readlines(): + match = re.subn(r"^\s*\?\s+(\w*)\s.*", r"\1", line.rstrip()) + if match[1]: + xlats.append(match[0]) +xlatf.close() + +for line in sys.stdin.readlines(): + for pat in pats: + line = re.subn(pat[0], pat[1], line)[0] + for xlat in xlats: + line = re.subn(r"(struct|union)\s+(%s|xen_%s)\s+(\w)" % (xlat, xlat), + r"\1 @KeeP@\2 \3", line.rstrip())[0] + print line.rstrip() diff -r c6b683ba68f5 -r a2b2b2a011f1 xen/tools/get-fields.sh --- a/xen/tools/get-fields.sh Sun Jan 14 22:18:38 2007 -0700 +++ b/xen/tools/get-fields.sh Mon Jan 15 15:15:26 2007 -0700 @@ -1,6 +1,9 @@ -#!/bin/sh +#!/bin/bash test -n "$1" -a -n "$2" -a -n "$3" set -ef + +SED=sed +[ -x /usr/xpg4/bin/sed ] && SED=/usr/xpg4/bin/sed get_fields() { local level=1 aggr=0 name= fields= @@ -90,11 +93,15 @@ handle_field() { then echo -n "$1(_d_)->$3 = (_s_)->$3;" else - echo -n "$1XLAT_${2}_HNDL_$(echo $3 | sed 's,\.,_,g')(_d_, _s_);" + echo -n "$1XLAT_${2}_HNDL_$(echo $3 | $SED 's,\.,_,g')(_d_, _s_);" fi - elif [ -z "$(echo "$5" | sed 's,[^{}],,g')" ] + elif [ -z "$(echo "$5" | $SED 's,[^{}],,g')" ] then - local tag=$(echo "$5" | sed 's,[[:space:]]*\(struct\|union\)[[:space:]]\+\(compat_\)\?\([[:alnum:]_]\+\)[[:space:]].*,\3,') + local tag=$(echo "$5" | python -c ' +import re,sys +for line in sys.stdin.readlines(): + print re.subn(r"\s*(struct|union)\s+(compat_)?(\w+)\s.*", r"\3", line)[0].rstrip() +') echo " \\" echo -n "${1}XLAT_$tag(&(_d_)->$3, &(_s_)->$3);" else @@ -104,13 +111,13 @@ handle_field() { case "$token" in struct|union) test $level != 2 || fields=" " - if [ $level == 1 ] + if [ $level = 1 ] then kind=$token if [ $kind = union ] then echo " \\" - echo -n "${1}switch ($(echo $3 | sed 's,\.,_,g')) {" + echo -n "${1}switch ($(echo $3 | $SED 's,\.,_,g')) {" fi fi ;; @@ -119,7 +126,7 @@ handle_field() { ;; "}") level=$(expr $level - 1) id= - if [ $level == 1 -a $kind = union ] + if [ $level = 1 -a $kind = union ] then echo " \\" echo -n "$1}" @@ -141,7 +148,7 @@ handle_field() { arrlvl=$(expr $arrlvl - 1) ;; COMPAT_HANDLE\(*\)) - if [ $level == 2 -a -z "$id" ] + if [ $level = 2 -a -z "$id" ] then type=${token#COMPAT_HANDLE?} type=${type%?} @@ -149,7 +156,7 @@ handle_field() { fi ;; compat_domain_handle_t) - if [ $level == 2 -a -z "$id" ] + if [ $level = 2 -a -z "$id" ] then array_type=$token fi @@ -158,12 +165,12 @@ handle_field() { id=$token ;; [\,\;]) - if [ $level == 2 -a -n "$(echo $id | sed 's,^_pad[[:digit:]]*,,')" ] + if [ $level = 2 -a -n "$(echo $id | $SED 's,^_pad[[:digit:]]*,,')" ] then if [ $kind = union ] then echo " \\" - echo -n "${1}case XLAT_${2}_$(echo $3.$id | sed 's,\.,_,g'):" + echo -n "${1}case XLAT_${2}_$(echo $3.$id | $SED 's,\.,_,g'):" handle_field "$1 " $2 $3.$id "$type" "$fields" elif [ -z "$array" -a -z "$array_type" ] then @@ -202,7 +209,7 @@ copy_array() { } handle_array() { - local i="i$(echo $4 | sed 's,[^;], ,g' | wc -w)" + local i="i$(echo $4 | $SED 's,[^;], ,g' | wc -w | $SED 's,[[:space:]]*,,g')" echo " \\" echo "$1{ \\" echo "$1 unsigned int $i; \\" @@ -250,7 +257,7 @@ build_body() { arrlvl=$(expr $arrlvl - 1) ;; COMPAT_HANDLE\(*\)) - if [ $level == 2 -a -z "$id" ] + if [ $level = 2 -a -z "$id" ] then type=${token#COMPAT_HANDLE?} type=${type%?} @@ -258,7 +265,7 @@ build_body() { fi ;; compat_domain_handle_t) - if [ $level == 2 -a -z "$id" ] + if [ $level = 2 -a -z "$id" ] then array_type=$token fi @@ -272,7 +279,7 @@ build_body() { fi ;; [\,\;]) - if [ $level == 2 -a -n "$(echo $id | sed 's,^_pad[[:digit:]]*,,')" ] + if [ $level = 2 -a -n "$(echo $id | $SED 's,^_pad[[:digit:]]*,,')" ] then if [ -z "$array" -a -z "$array_type" ] then @@ -300,10 +307,10 @@ build_body() { } check_field() { - if [ -z "$(echo "$4" | sed 's,[^{}],,g')" ] + if [ -z "$(echo "$4" | $SED 's,[^{}],,g')" ] then echo "; \\" - local n=$(echo $3 | sed 's,[^.], ,g' | wc -w) + local n=$(echo $3 | $SED 's,[^.], ,g' | wc -w | $SED 's,[[:space:]]*,,g') if [ -n "$4" ] then for n in $4 @@ -325,7 +332,7 @@ check_field() { then echo -n " CHECK_FIELD_($1, $2, $3)" else - echo -n " CHECK_SUBFIELD_${n}_($1, $2, $(echo $3 | sed 's!\.!, !g'))" + echo -n " CHECK_SUBFIELD_${n}_($1, $2, $(echo $3 | $SED 's!\.!, !g'))" fi else local level=1 fields= id= token @@ -345,7 +352,7 @@ check_field() { id=$token ;; [\,\;]) - if [ $level == 2 -a -n "$(echo $id | sed 's,^_pad[[:digit:]]*,,')" ] + if [ $level = 2 -a -n "$(echo $id | $SED 's,^_pad[[:digit:]]*,,')" ] then check_field $1 $2 $3.$id "$fields" test "$token" != ";" || fields= id= @@ -365,11 +372,11 @@ build_check() { do case "$token" in struct|union) - if [ $level == 1 ] + if [ $level = 1 ] then kind=$token echo -n " CHECK_SIZE_($kind, $1)" - elif [ $level == 2 ] + elif [ $level = 2 ] then fields=" " fi @@ -390,7 +397,7 @@ build_check() { test $level != 2 -o $arrlvl != 1 || id=$token ;; [\,\;]) - if [ $level == 2 -a -n "$(echo $id | sed 's,^_pad[[:digit:]]*,,')" ] + if [ $level = 2 -a -n "$(echo $id | $SED 's,^_pad[[:digit:]]*,,')" ] then check_field $kind $1 $id "$fields" test "$token" != ";" || fields= id= @@ -402,7 +409,7 @@ build_check() { echo "" } -fields="$(get_fields $(echo $2 | sed 's,^compat_xen,compat_,') "$(sed -e 's,^[[:space:]]#.*,,' -e 's!\([]\[,;:{}]\)! \1 !g' $3)")" +fields="$(get_fields $(echo $2 | $SED 's,^compat_xen,compat_,') "$($SED -e 's,^[[:space:]]#.*,,' -e 's!\([]\[,;:{}]\)! \1 !g' $3)")" if [ -z "$fields" ] then echo "Fields of '$2' not found in '$3'" >&2 _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |