WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] Merge

# HG changeset patch
# User djm@xxxxxxxxxxxxxxx
# Node ID 5a790011259e7ab8e50c53acc79dc006e7305298
# Parent  2c75070e41a0980b85a6476ebcb9aefa6005c57e
# Parent  c259492dfb43d83fdb74bb4f4fd8be6ccfa926ee
Merge

diff -r 2c75070e41a0 -r 5a790011259e Makefile
--- a/Makefile  Wed Dec 21 16:30:10 2005
+++ b/Makefile  Wed Dec 21 17:56:19 2005
@@ -10,7 +10,7 @@
 # Export target architecture overrides to Xen and Linux sub-trees.
 ifneq ($(XEN_TARGET_ARCH),)
 SUBARCH := $(subst x86_32,i386,$(XEN_TARGET_ARCH))
-export XEN_TARGET_ARCH SUBARCH
+export XEN_TARGET_ARCH SUBARCH XEN_SYSTYPE
 endif
 
 # Default target must appear before any include lines
diff -r 2c75070e41a0 -r 5a790011259e buildconfigs/mk.linux-2.6-xen
--- a/buildconfigs/mk.linux-2.6-xen     Wed Dec 21 16:30:10 2005
+++ b/buildconfigs/mk.linux-2.6-xen     Wed Dec 21 17:56:19 2005
@@ -30,7 +30,7 @@
        CONFIG_VERSION=$$(sed -ne 's/^EXTRAVERSION = //p' 
$(LINUX_DIR)/Makefile); \
        [ -r 
$(DESTDIR)/boot/config-$(LINUX_VER)$$CONFIG_VERSION-$(EXTRAVERSION) ] && \
          cp 
$(DESTDIR)/boot/config-$(LINUX_VER)$$CONFIG_VERSION-$(EXTRAVERSION) 
$(LINUX_DIR)/.config \
-         || cp 
$(LINUX_DIR)/arch/xen/configs/$(EXTRAVERSION)_defconfig_$(XEN_TARGET_ARCH) \
+         || cp 
$(LINUX_DIR)/arch/xen/configs/$(EXTRAVERSION)_defconfig_$(XEN_TARGET_ARCH)$(XEN_SYSTYPE)
 \
                $(LINUX_DIR)/.config
        # See if we need to munge config to enable PAE
        $(MAKE) CONFIG_FILE=$(LINUX_DIR)/.config -f buildconfigs/Rules.mk 
config-update-pae
diff -r 2c75070e41a0 -r 5a790011259e 
linux-2.6-xen-sparse/arch/xen/i386/kernel/acpi/boot.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/acpi/boot.c     Wed Dec 21 
16:30:10 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/acpi/boot.c     Wed Dec 21 
17:56:19 2005
@@ -659,8 +659,6 @@
        rsdp_phys = acpi_scan_rsdp (0, 0x400);
        if (!rsdp_phys)
                rsdp_phys = acpi_scan_rsdp (0xE0000, 0x20000);
-
-       set_fixmap(FIX_ACPI_RSDP_PAGE, rsdp_phys);
 
        return rsdp_phys;
 }
diff -r 2c75070e41a0 -r 5a790011259e 
linux-2.6-xen-sparse/arch/xen/i386/kernel/ldt.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/ldt.c   Wed Dec 21 16:30:10 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/ldt.c   Wed Dec 21 17:56:19 2005
@@ -186,8 +186,7 @@
 static int write_ldt(void __user * ptr, unsigned long bytecount, int oldmode)
 {
        struct mm_struct * mm = current->mm;
-       __u32 entry_1, entry_2, *lp;
-       maddr_t mach_lp;
+       __u32 entry_1, entry_2;
        int error;
        struct user_desc ldt_info;
 
@@ -215,9 +214,6 @@
                        goto out_unlock;
        }
 
-       lp = (__u32 *) ((ldt_info.entry_number << 3) + (char *) 
mm->context.ldt);
-       mach_lp = arbitrary_virt_to_machine(lp);
-
        /* Allow LDTs to be cleared by the user. */
        if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
                if (oldmode || LDT_empty(&ldt_info)) {
@@ -234,8 +230,8 @@
 
        /* Install the new entry ...  */
 install:
-       error = HYPERVISOR_update_descriptor(
-               mach_lp, (u64)entry_1 | ((u64)entry_2<<32));
+       error = write_ldt_entry(mm->context.ldt, ldt_info.entry_number,
+                               entry_1, entry_2);
 
 out_unlock:
        up(&mm->context.sem);
diff -r 2c75070e41a0 -r 5a790011259e 
linux-2.6-xen-sparse/arch/xen/i386/kernel/swiotlb.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/swiotlb.c       Wed Dec 21 
16:30:10 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/swiotlb.c       Wed Dec 21 
17:56:19 2005
@@ -24,6 +24,7 @@
 #include <asm/io.h>
 #include <asm/pci.h>
 #include <asm/dma.h>
+#include <asm/uaccess.h>
 #include <asm-xen/xen-public/memory.h>
 
 #define OFFSET(val,align) ((unsigned long)((val) & ( (align) - 1)))
@@ -201,6 +202,12 @@
                printk(KERN_INFO "Software IO TLB disabled\n");
 }
 
+/*
+ * We use __copy_to_user to transfer to the host buffer because the buffer
+ * may be mapped read-only (e.g, in blkback driver) but lower-level
+ * drivers map the buffer for DMA_BIDIRECTIONAL access. This causes an
+ * unnecessary copy from the aperture to the host buffer, and a page fault.
+ */
 static void
 __sync_single(struct phys_addr buffer, char *dma_addr, size_t size, int dir)
 {
@@ -214,9 +221,11 @@
                        kmp  = kmap_atomic(buffer.page, KM_SWIOTLB);
                        dev  = dma_addr + size - len;
                        host = kmp + buffer.offset;
-                       memcpy((dir == DMA_FROM_DEVICE) ? host : dev,
-                              (dir == DMA_FROM_DEVICE) ? dev : host,
-                              bytes);
+                       if (dir == DMA_FROM_DEVICE) {
+                               if (__copy_to_user(host, dev, bytes))
+                                       /* inaccessible */;
+                       } else
+                               memcpy(dev, host, bytes);
                        kunmap_atomic(kmp, KM_SWIOTLB);
                        len -= bytes;
                        buffer.page++;
@@ -225,9 +234,10 @@
        } else {
                char *host = (char *)phys_to_virt(
                        page_to_pseudophys(buffer.page)) + buffer.offset;
-               if (dir == DMA_FROM_DEVICE)
-                       memcpy(host, dma_addr, size);
-               else if (dir == DMA_TO_DEVICE)
+               if (dir == DMA_FROM_DEVICE) {
+                       if (__copy_to_user(host, dma_addr, size))
+                               /* inaccessible */;
+               } else if (dir == DMA_TO_DEVICE)
                        memcpy(dma_addr, host, size);
        }
 }
diff -r 2c75070e41a0 -r 5a790011259e 
linux-2.6-xen-sparse/arch/xen/i386/mm/hypervisor.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/mm/hypervisor.c        Wed Dec 21 
16:30:10 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/mm/hypervisor.c        Wed Dec 21 
17:56:19 2005
@@ -438,6 +438,16 @@
        balloon_unlock(flags);
 }
 
+#ifdef __i386__
+int write_ldt_entry(void *ldt, int entry, __u32 entry_a, __u32 entry_b)
+{
+       __u32 *lp = (__u32 *)((char *)ldt + entry * 8);
+       maddr_t mach_lp = arbitrary_virt_to_machine(lp);
+       return HYPERVISOR_update_descriptor(
+               mach_lp, (u64)entry_a | ((u64)entry_b<<32));
+}
+#endif
+
 /*
  * Local variables:
  *  c-file-style: "linux"
diff -r 2c75070e41a0 -r 5a790011259e 
linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c
--- a/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c     Wed Dec 21 16:30:10 2005
+++ b/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c     Wed Dec 21 17:56:19 2005
@@ -163,11 +163,10 @@
        while (l1 != 0) {
                l1i = __ffs(l1);
                l1 &= ~(1UL << l1i);
-        
+
                while ((l2 = active_evtchns(cpu, s, l1i)) != 0) {
                        l2i = __ffs(l2);
-                       l2 &= ~(1UL << l2i);
-            
+
                        port = (l1i * BITS_PER_LONG) + l2i;
                        if ((irq = evtchn_to_irq[port]) != -1)
                                do_IRQ(irq, regs);
diff -r 2c75070e41a0 -r 5a790011259e linux-2.6-xen-sparse/drivers/acpi/tables.c
--- a/linux-2.6-xen-sparse/drivers/acpi/tables.c        Wed Dec 21 16:30:10 2005
+++ b/linux-2.6-xen-sparse/drivers/acpi/tables.c        Wed Dec 21 17:56:19 2005
@@ -566,8 +566,7 @@
  * result: sdt_entry[] is initialized
  */
 #if defined(CONFIG_XEN_X86) || defined(CONFIG_XEN_X86_64)
-#define acpi_rsdp_phys_to_va(rsdp_phys) (__fix_to_virt(FIX_ACPI_RSDP_PAGE) + \
-                                          (rsdp_phys & ~PAGE_MASK))
+#define acpi_rsdp_phys_to_va(rsdp_phys) isa_bus_to_virt(rsdp_phys)
 #else
 #define acpi_rsdp_phys_to_va(rsdp_phys) __va(rsdp_phys)
 #endif
diff -r 2c75070e41a0 -r 5a790011259e 
linux-2.6-xen-sparse/drivers/xen/console/console.c
--- a/linux-2.6-xen-sparse/drivers/xen/console/console.c        Wed Dec 21 
16:30:10 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/console/console.c        Wed Dec 21 
17:56:19 2005
@@ -628,6 +628,7 @@
        if (xencons_driver == NULL)
                return -ENOMEM;
 
+       DRV(xencons_driver)->name            = "xencons";
        DRV(xencons_driver)->major           = TTY_MAJOR;
        DRV(xencons_driver)->type            = TTY_DRIVER_TYPE_SERIAL;
        DRV(xencons_driver)->subtype         = SERIAL_TYPE_NORMAL;
diff -r 2c75070e41a0 -r 5a790011259e 
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c
--- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c    Wed Dec 21 
16:30:10 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c    Wed Dec 21 
17:56:19 2005
@@ -315,15 +315,16 @@
 static int talk_to_otherend(struct xenbus_device *dev)
 {
        struct xenbus_driver *drv = to_xenbus_driver(dev->dev.driver);
-       int err;
 
        free_otherend_watch(dev);
        free_otherend_details(dev);
 
-       err = drv->read_otherend_details(dev);
-       if (err)
-               return err;
-
+       return drv->read_otherend_details(dev);
+}
+
+
+static int watch_otherend(struct xenbus_device *dev)
+{
        return xenbus_watch_path2(dev, dev->otherend, "state",
                                  &dev->otherend_watch, otherend_changed);
 }
@@ -337,6 +338,17 @@
        int err;
 
        DPRINTK("");
+
+       if (!drv->probe) {
+               err = -ENODEV;
+               goto fail;
+       }
+
+       id = match_device(drv->ids, dev);
+       if (!id) {
+               err = -ENODEV;
+               goto fail;
+       }
 
        err = talk_to_otherend(dev);
        if (err) {
@@ -346,20 +358,17 @@
                return err;
        }
 
-       if (!drv->probe) {
-               err = -ENODEV;
-               goto fail;
-       }
-
-       id = match_device(drv->ids, dev);
-       if (!id) {
-               err = -ENODEV;
-               goto fail;
-       }
-
        err = drv->probe(dev, id);
        if (err)
                goto fail;
+
+       err = watch_otherend(dev);
+       if (err) {
+               printk(KERN_WARNING
+                      "xenbus_probe: watch_otherend on %s failed.\n",
+                      dev->nodename);
+               return err;
+       }
 
        return 0;
 fail:
@@ -826,6 +835,14 @@
                return err;
        }
 
+       err = watch_otherend(xdev);
+       if (err) {
+               printk(KERN_WARNING
+                      "xenbus_probe: resume (watch_otherend) %s failed: "
+                      "%d.\n", dev->bus_id, err);
+               return err;
+       }
+
        if (drv->resume)
                err = drv->resume(xdev);
        if (err)
diff -r 2c75070e41a0 -r 5a790011259e 
linux-2.6-xen-sparse/include/asm-xen/asm-i386/desc.h
--- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/desc.h      Wed Dec 21 
16:30:10 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/desc.h      Wed Dec 21 
17:56:19 2005
@@ -87,6 +87,8 @@
        (info)->seg_not_present == 1    && \
        (info)->useable         == 0    )
 
+extern int write_ldt_entry(void *ldt, int entry, __u32 entry_a, __u32 entry_b);
+
 #if TLS_SIZE != 24
 # error update this code.
 #endif
diff -r 2c75070e41a0 -r 5a790011259e 
linux-2.6-xen-sparse/include/asm-xen/asm-i386/fixmap.h
--- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/fixmap.h    Wed Dec 21 
16:30:10 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/fixmap.h    Wed Dec 21 
17:56:19 2005
@@ -80,7 +80,6 @@
 #ifdef CONFIG_ACPI_BOOT
        FIX_ACPI_BEGIN,
        FIX_ACPI_END = FIX_ACPI_BEGIN + FIX_ACPI_PAGES - 1,
-       FIX_ACPI_RSDP_PAGE,
 #endif
 #ifdef CONFIG_PCI_MMCONFIG
        FIX_PCIE_MCFG,
diff -r 2c75070e41a0 -r 5a790011259e 
linux-2.6-xen-sparse/include/asm-xen/asm-i386/io.h
--- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/io.h        Wed Dec 21 
16:30:10 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/io.h        Wed Dec 21 
17:56:19 2005
@@ -309,15 +309,8 @@
 
 #ifdef SLOW_IO_BY_JUMPING
 #define __SLOW_DOWN_IO "jmp 1f; 1: jmp 1f; 1:"
-#elif defined(__UNSAFE_IO__)
+#else
 #define __SLOW_DOWN_IO "outb %%al,$0x80;"
-#else
-#define __SLOW_DOWN_IO "\n1: outb %%al,$0x80\n"                \
-                      "2:\n"                           \
-                      ".section __ex_table,\"a\"\n\t"  \
-                      ".align 4\n\t"                   \
-                      ".long 1b,2b\n"                  \
-                      ".previous"
 #endif
 
 static inline void slow_down_io(void) {
@@ -362,8 +355,7 @@
 #endif
 
 
-#if __UNSAFE_IO__
-#define ____BUILDIO(bwl,bw,type) \
+#define BUILDIO(bwl,bw,type) \
 static inline void out##bwl##_local(unsigned type value, int port) { \
        __asm__ __volatile__("out" #bwl " %" #bw "0, %w1" : : "a"(value), 
"Nd"(port)); \
 } \
@@ -371,35 +363,7 @@
        unsigned type value; \
        __asm__ __volatile__("in" #bwl " %w1, %" #bw "0" : "=a"(value) : 
"Nd"(port)); \
        return value; \
-}
-#else
-#define ____BUILDIO(bwl,bw,type) \
-static inline void out##bwl##_local(unsigned type value, int port) { \
-       __asm__ __volatile__("1: out" #bwl " %" #bw "0, %w1\n"          \
-                            "2:\n"                                     \
-                            ".section __ex_table,\"a\"\n\t"            \
-                            ".align 4\n\t"                             \
-                            ".long 1b,2b\n"                            \
-                            ".previous" : : "a"(value), "Nd"(port));   \
-} \
-static inline unsigned type in##bwl##_local(int port) { \
-       unsigned type value; \
-       __asm__ __volatile__("1:in" #bwl " %w1, %" #bw "0\n"            \
-                            "2:\n"                                     \
-                            ".section .fixup,\"ax\"\n"                 \
-                            "3: mov" #bwl " $~0,%" #bw "0\n\t"         \
-                            "jmp 2b\n"                                 \
-                            ".previous\n"                              \
-                            ".section __ex_table,\"a\"\n\t"            \
-                            ".align 4\n\t"                             \
-                            ".long 1b,3b\n"                            \
-                            ".previous" : "=a"(value) : "Nd"(port));   \
-       return value; \
-}
-#endif
-
-#define BUILDIO(bwl,bw,type) \
-____BUILDIO(bwl,bw,type) \
+} \
 static inline void out##bwl##_local_p(unsigned type value, int port) { \
        out##bwl##_local(value, port); \
        slow_down_io(); \
diff -r 2c75070e41a0 -r 5a790011259e 
linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/fixmap.h
--- a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/fixmap.h  Wed Dec 21 
16:30:10 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/fixmap.h  Wed Dec 21 
17:56:19 2005
@@ -50,7 +50,6 @@
 #ifdef CONFIG_ACPI_BOOT
        FIX_ACPI_BEGIN,
        FIX_ACPI_END = FIX_ACPI_BEGIN + FIX_ACPI_PAGES - 1,
-       FIX_ACPI_RSDP_PAGE,
 #endif
        FIX_SHARED_INFO,
        FIX_GNTTAB_BEGIN,
diff -r 2c75070e41a0 -r 5a790011259e 
tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/linux-xen-low.c
--- a/tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/linux-xen-low.c     
Wed Dec 21 16:30:10 2005
+++ b/tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/linux-xen-low.c     
Wed Dec 21 17:56:19 2005
@@ -36,11 +36,26 @@
 #include <unistd.h>
 #include <errno.h>
 #include <xenctrl.h>
+#include <thread_db.h>
+#include <xc_ptrace.h>
+
 #define TRACE_ENTER /* printf("enter %s\n", __FUNCTION__) */
 
 long (*myptrace)(int xc_handle, enum __ptrace_request, uint32_t, long, long);
 int (*myxcwait)(int xc_handle, int domain, int *status, int options) ;
 static int xc_handle;
+
+static inline int
+curvcpuid()
+{
+  struct process_info *process;
+  if (current_inferior == NULL)
+      return 0;
+  process = get_thread_process(current_inferior);
+  return (process->thread_known ? process->tid : 0);
+
+}
+
 
 #define DOMFLAGS_DYING     (1<<0) /* Domain is scheduled to die.             */
 #define DOMFLAGS_SHUTDOWN  (1<<2) /* The guest OS has shut down.             */
@@ -48,11 +63,14 @@
 #define DOMFLAGS_BLOCKED   (1<<4) /* Currently blocked pending an event.     */
 #define DOMFLAGS_RUNNING   (1<<5) /* Domain is currently running.            */
 
+
+
 struct inferior_list all_processes;
-static int current_domain;
+static int current_domid;
 static int expect_signal = 0;
 static int signal_to_send = 0; 
 static void linux_resume (struct thread_resume *resume_info);
+static void linux_set_inferior (void);
 
 int debug_threads;
 int using_threads;
@@ -96,7 +114,6 @@
    point at the following instruction.  If we continue and hit a
    breakpoint instruction, our PC will point at the breakpoint
    instruction.  */
-#if 0
 static CORE_ADDR
 get_stop_pc (void)
 {
@@ -107,9 +124,9 @@
   else
     return stop_pc - the_low_target.decr_pc_after_break;
 }
-#endif
+
 static void *
-add_process (int pid)
+add_process (int pid, long tid)
 {
   struct process_info *process;
 
@@ -118,9 +135,8 @@
 
   process->head.id = pid;
 
-  /* Default to tid == lwpid == pid.  */
-  process->tid = pid;
-  process->lwpid = pid;
+  process->tid = tid;
+  process->lwpid = tid;
 
   add_inferior_to_list (&all_processes, &process->head);
 
@@ -143,23 +159,25 @@
 }
 
 int
-linux_attach (int domain)
+linux_attach (int domid)
 {
     struct process_info *new_process;
-    current_domain = domain;
-    if (myptrace (xc_handle, PTRACE_ATTACH, domain, 0, 0) != 0) {
-       fprintf (stderr, "Cannot attach to domain %d: %s (%d)\n", domain,
+    current_domid = domid;
+    /* this is handled for all active vcpus in PTRACE_ATTACH via the 
thread_create_callback */
+    new_process = (struct process_info *) add_process (domid, curvcpuid());
+    /* Don't ignore the initial SIGSTOP if we just attached to this process.  
*/
+    /* vcpuid == 0 */
+    add_thread (0, new_process);
+    new_process->stop_expected = 0;
+
+    if (myptrace (xc_handle, PTRACE_ATTACH, domid, 0, 0) != 0) {
+       fprintf (stderr, "Cannot attach to domain %d: %s (%d)\n", domid,
                 strerror (errno), errno);
        fflush (stderr);
-       _exit (0177);
-    }
-    
-    new_process = (struct process_info *) add_process (domain);
-    add_thread (domain, new_process);
-
-    /* Don't ignore the initial SIGSTOP if we just attached to this process.  
*/
-    new_process->stop_expected = 0;
-    
+       if (!using_threads)
+           _exit (0177);
+    }
+
     return 0;
 }
 
@@ -173,20 +191,18 @@
   myptrace (xc_handle, PTRACE_KILL, pid_of (process), 0, 0);
 }
 
+
 static void
 linux_kill (void)
 {
   for_each_inferior (&all_threads, linux_kill_one_process);
 }
 
-
 static void
 linux_detach_one_process (struct inferior_list_entry *entry)
 {
-  struct thread_info *thread = (struct thread_info *) entry;
-  struct process_info *process = get_thread_process (thread);
-
-  myptrace (xc_handle, PTRACE_DETACH, pid_of (process), 0, 0);
+
+  myptrace (xc_handle, PTRACE_DETACH, current_domid, 0, 0);
 }
 
 
@@ -212,14 +228,10 @@
 linux_wait (char *status)
 {
   int w;
-  if (myxcwait(xc_handle, current_domain, &w, 0))
+  if (myxcwait(xc_handle, current_domid, &w, 0))
       return -1;
   
-  if (w & (DOMFLAGS_SHUTDOWN|DOMFLAGS_DYING)) {
-      *status = 'W';
-      return 0;
-  }
-
+  linux_set_inferior();
 
   *status = 'T';
   if (expect_signal)
@@ -236,8 +248,10 @@
   TRACE_ENTER;
   expect_signal = resume_info->sig;
   for_each_inferior(&all_threads, regcache_invalidate_one);
-
-  myptrace (xc_handle, step ? PTRACE_SINGLESTEP : PTRACE_CONT, current_domain, 
0, 0);
+  if (debug_threads)
+    fprintf(stderr, "step: %d\n", step);
+  myptrace (xc_handle, step ? PTRACE_SINGLESTEP : PTRACE_CONT, 
+           resume_info->thread, 0, 0);
 
 }
 
@@ -261,7 +275,9 @@
        }
 
       buf = malloc (regset->size);
-      res = myptrace (xc_handle, regset->get_request, inferior_pid, 0, 
(PTRACE_XFER_TYPE)buf);
+      res = myptrace (xc_handle, regset->get_request, 
+                     curvcpuid(),
+                     0, (PTRACE_XFER_TYPE)buf);
       if (res < 0)
        {
          if (errno == EIO)
@@ -313,7 +329,7 @@
 
       buf = malloc (regset->size);
       regset->fill_function (buf);
-      res = myptrace (xc_handle, regset->set_request, inferior_pid, 0, 
(PTRACE_XFER_TYPE)buf);
+      res = myptrace (xc_handle, regset->set_request, curvcpuid(), 0, 
(PTRACE_XFER_TYPE)buf);
       if (res < 0)
        {
          if (errno == EIO)
@@ -391,7 +407,7 @@
   for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE))
     {
       errno = 0;
-      buffer[i] = myptrace (xc_handle, PTRACE_PEEKTEXT, inferior_pid, 
(PTRACE_ARG3_TYPE) addr, 0);
+      buffer[i] = myptrace (xc_handle, PTRACE_PEEKTEXT, curvcpuid(), 
(PTRACE_ARG3_TYPE) addr, 0);
       if (errno)
        return errno;
     }
@@ -424,13 +440,13 @@
 
   /* Fill start and end extra bytes of buffer with existing memory data.  */
 
-  buffer[0] = myptrace (xc_handle, PTRACE_PEEKTEXT, inferior_pid,
+  buffer[0] = myptrace (xc_handle, PTRACE_PEEKTEXT, curvcpuid(),
                      (PTRACE_ARG3_TYPE) addr, 0);
 
   if (count > 1)
     {
       buffer[count - 1]
-       = myptrace (xc_handle, PTRACE_PEEKTEXT, inferior_pid,
+       = myptrace (xc_handle, PTRACE_PEEKTEXT, curvcpuid(),
                  (PTRACE_ARG3_TYPE) (addr + (count - 1)
                                      * sizeof (PTRACE_XFER_TYPE)),
                  0);
@@ -444,7 +460,8 @@
   for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE))
     {
       errno = 0;
-      myptrace (xc_handle, PTRACE_POKETEXT, inferior_pid, (PTRACE_ARG3_TYPE) 
addr, buffer[i]);
+      myptrace (xc_handle, PTRACE_POKETEXT, curvcpuid(), 
+               (PTRACE_ARG3_TYPE) addr, buffer[i]);
       if (errno)
        return errno;
     }
@@ -455,9 +472,11 @@
 static void
 linux_look_up_symbols (void)
 {
-#if 0
+  if (using_threads) 
+    return;
+
   using_threads = thread_db_init ();
-#endif
+
 }
 
 static void
@@ -535,6 +554,7 @@
 void
 initialize_low (void)
 {
+  using_threads = 0;
   xc_handle = xc_interface_open();
   set_target_ops (&linux_xen_target_ops);
   set_breakpoint_data (the_low_target.breakpoint,
@@ -548,5 +568,122 @@
       myptrace = xc_ptrace;
       myxcwait = xc_waitdomain;
   }
-
-}
+  using_threads = thread_db_init ();
+
+}
+
+
+static void
+thread_create_callback(long vcpuid)
+{
+  struct thread_info *inferior;
+  struct process_info *process;
+
+  /*  If we are attaching to our first thread, things are a little
+   *  different.  
+   */
+  if (all_threads.head == all_threads.tail)
+    {
+      inferior = (struct thread_info *) all_threads.head;
+      process = get_thread_process (inferior);
+      if (process->thread_known == 0)
+       {
+         /* Switch to indexing the threads list by TID.  */
+         change_inferior_id (&all_threads, vcpuid);
+         goto found;
+       }
+    }
+  if (debug_threads)
+    fprintf (stderr, "looking up thread %ld\n",
+            vcpuid);
+  inferior = (struct thread_info *) find_inferior_id (&all_threads,
+                                                     vcpuid);
+  /* if vcpu alread registered - do nothing */
+  if (inferior != NULL) 
+    return;
+
+  if (debug_threads)
+    fprintf (stderr, "Attaching to thread %ld\n",
+            vcpuid);
+
+  process = add_process(current_domid, vcpuid);
+
+  add_thread(vcpuid, process);
+  inferior = (struct thread_info *) find_inferior_id (&all_threads,
+                                                     vcpuid);
+  if (inferior == NULL)
+    {
+      warning ("Could not attach to thread %ld\n",
+              vcpuid);
+      return;
+    }
+
+
+found:
+  if (debug_threads)
+    fprintf (stderr, "notifying of new thread %ld\n",
+            vcpuid);
+  new_thread_notify (vcpuid);
+
+  process->tid = vcpuid;
+  process->lwpid = vcpuid;
+
+  process->thread_known = 1;
+}
+
+static void
+thread_death_callback(long vcpuid)
+{
+    if (debug_threads)
+      fprintf (stderr, "Buuurp...! CPU down event.\n");
+}
+
+int
+thread_db_init(void)
+{
+  debug_threads = 0;
+  xc_register_event_handler(thread_create_callback, TD_CREATE);
+  xc_register_event_handler(thread_death_callback, TD_DEATH);
+  return 1;
+}
+
+/* XXX GAG ME */
+static int breakpoint_found;
+static void
+set_breakpoint_inferior (struct inferior_list_entry *entry)
+{
+  struct thread_info *thread = (struct thread_info *) entry;
+  struct thread_info *saved_inferior = current_inferior;
+  CORE_ADDR eip;
+  unsigned char buf[2] = {0, 0};
+  current_inferior = thread;
+  if (!breakpoint_found) {
+    eip = get_stop_pc();
+    linux_read_memory(eip, buf, 1);
+    if (buf[0] == 0xcc) {
+      breakpoint_found = 1;
+      return;
+    }
+  } else if (breakpoint_found == 2) {
+    if (get_thread_process (current_inferior)->stepping) {
+      printf("stepping\n");
+      breakpoint_found = 1;
+      return;
+    } 
+  }
+  current_inferior = saved_inferior;
+
+
+}
+
+static void
+linux_set_inferior (void)
+{
+  breakpoint_found = 0;
+  for_each_inferior (&all_threads, set_breakpoint_inferior);
+  if (!breakpoint_found) {
+    breakpoint_found = 2;
+    for_each_inferior (&all_threads, set_breakpoint_inferior);
+  }
+}
+
diff -r 2c75070e41a0 -r 5a790011259e 
tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/server.c
--- a/tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/server.c    Wed Dec 
21 16:30:10 2005
+++ b/tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/server.c    Wed Dec 
21 17:56:19 2005
@@ -20,7 +20,7 @@
    Boston, MA 02111-1307, USA.  */
 
 #include "server.h"
-
+#include "linux-low.h"
 #include <unistd.h>
 #include <signal.h>
 #include <sys/wait.h>
@@ -102,7 +102,15 @@
       strcpy (own_buf, "OK");
       return;
     }
-
+  if (strcmp ("qC", own_buf) == 0)
+    {
+      struct process_info *process;
+      if (current_inferior == NULL)
+       return;
+      process = get_thread_process(current_inferior);
+      sprintf(own_buf, "QC%x", process->thread_known ? process->tid : 0);
+
+    }
   if (strcmp ("qfThreadInfo", own_buf) == 0)
     {
       thread_ptr = all_threads.head;
diff -r 2c75070e41a0 -r 5a790011259e tools/examples/xend-config.sxp
--- a/tools/examples/xend-config.sxp    Wed Dec 21 16:30:10 2005
+++ b/tools/examples/xend-config.sxp    Wed Dec 21 17:56:19 2005
@@ -4,9 +4,9 @@
 # Xend configuration file.
 #
 
-# This example configuration is appropriate for an installation that trusts
-# only localhost connections, and is otherwise fully functional, with a
-# bridged network configuration.
+# This example configuration is appropriate for an installation that 
+# utilizes a bridged network configuration. Access to xend via http
+# is disabled.  
 
 # Commented out entries show the default for that entry, unless otherwise
 # specified.
@@ -15,7 +15,6 @@
 #(loglevel DEBUG)
 
 #(xend-http-server no)
-(xend-http-server yes)
 #(xend-unix-server yes)
 #(xend-relocation-server no)
 (xend-relocation-server yes)
@@ -34,7 +33,7 @@
 # Specifying 'localhost' prevents remote connections.
 # Specifying the empty string '' (the default) allows all connections.
 #(xend-address '')
-(xend-address localhost)
+#(xend-address localhost)
 
 # Address xend should listen on for relocation-socket connections, if
 # xend-relocation-server is set.
diff -r 2c75070e41a0 -r 5a790011259e tools/examples/xmexample.vmx
--- a/tools/examples/xmexample.vmx      Wed Dec 21 16:30:10 2005
+++ b/tools/examples/xmexample.vmx      Wed Dec 21 17:56:19 2005
@@ -135,7 +135,7 @@
 
 #-----------------------------------------------------------------------------
 #   enable audio support
-#enable-audio=1
+#audio=1
 
 
 #-----------------------------------------------------------------------------
diff -r 2c75070e41a0 -r 5a790011259e tools/ioemu/cpu-all.h
--- a/tools/ioemu/cpu-all.h     Wed Dec 21 16:30:10 2005
+++ b/tools/ioemu/cpu-all.h     Wed Dec 21 17:56:19 2005
@@ -668,7 +668,7 @@
 #endif
 /* memory API */
 
-extern int phys_ram_size;
+extern uint64_t phys_ram_size;
 extern int phys_ram_fd;
 extern uint8_t *phys_ram_base;
 extern uint8_t *phys_ram_dirty;
diff -r 2c75070e41a0 -r 5a790011259e tools/ioemu/exec.c
--- a/tools/ioemu/exec.c        Wed Dec 21 16:30:10 2005
+++ b/tools/ioemu/exec.c        Wed Dec 21 17:56:19 2005
@@ -61,7 +61,7 @@
 uint8_t code_gen_buffer[CODE_GEN_BUFFER_SIZE];
 uint8_t *code_gen_ptr;
 
-int phys_ram_size;
+uint64_t phys_ram_size;
 int phys_ram_fd;
 uint8_t *phys_ram_base;
 uint8_t *phys_ram_dirty;
diff -r 2c75070e41a0 -r 5a790011259e tools/ioemu/hw/pc.c
--- a/tools/ioemu/hw/pc.c       Wed Dec 21 16:30:10 2005
+++ b/tools/ioemu/hw/pc.c       Wed Dec 21 17:56:19 2005
@@ -119,7 +119,7 @@
 }
 
 /* hd_table must contain 4 block drivers */
-static void cmos_init(int ram_size, int boot_device, BlockDriverState 
**hd_table)
+static void cmos_init(uint64_t ram_size, int boot_device, BlockDriverState 
**hd_table)
 {
     RTCState *s = rtc_state;
     int val;
@@ -375,7 +375,7 @@
 #define NOBIOS 1
 
 /* PC hardware initialisation */
-void pc_init(int ram_size, int vga_ram_size, int boot_device,
+void pc_init(uint64_t ram_size, int vga_ram_size, int boot_device,
              DisplayState *ds, const char **fd_filename, int snapshot,
              const char *kernel_filename, const char *kernel_cmdline,
              const char *initrd_filename)
@@ -563,6 +563,15 @@
 
     kbd_init();
     DMA_init(0);
+   
+    if (audio_enabled) {
+        AUD_init();
+#ifdef USE_SB16
+        if (sb16_enabled)
+            SB16_init();
+#endif
+    }
+    
 
     floppy_controller = fdctrl_init(6, 2, 0, 0x3f0, fd_table);
 
diff -r 2c75070e41a0 -r 5a790011259e tools/ioemu/hw/pcnet.h
--- a/tools/ioemu/hw/pcnet.h    Wed Dec 21 16:30:10 2005
+++ b/tools/ioemu/hw/pcnet.h    Wed Dec 21 17:56:19 2005
@@ -92,7 +92,7 @@
 #define CSR_NRBA(S)      ((S)->csr[22] | ((S)->csr[23] << 16))
 #define CSR_BADR(S)      ((S)->csr[24] | ((S)->csr[25] << 16))
 #define CSR_NRDA(S)      ((S)->csr[26] | ((S)->csr[27] << 16))
-#define CSR_CRDA(S)      ((S)->csr[28] | ((S)->csr[29] << 16))
+#define CSR_CRDA(S)      ((S)->csr[28] | (((uint32_t)((S)->csr[29])) << 16))
 #define CSR_BADX(S)      ((S)->csr[30] | ((S)->csr[31] << 16))
 #define CSR_NXDA(S)      ((S)->csr[32] | ((S)->csr[33] << 16))
 #define CSR_CXDA(S)      ((S)->csr[34] | ((S)->csr[35] << 16))
@@ -102,7 +102,7 @@
 #define CSR_NXBA(S)      ((S)->csr[64] | ((S)->csr[65] << 16))
 
 #define PHYSADDR(S,A) \
-  (BCR_SSIZE32(S) ? (A) : (A) | ((0xff00 & (uint32_t)(s)->csr[2])<<16))
+  (BCR_SSIZE32(S) ? (A) : (A) | ((0xff00 & (uint32_t)(S)->csr[2])<<16))
 
 struct pcnet_initblk16 {
     uint16_t mode;
diff -r 2c75070e41a0 -r 5a790011259e tools/ioemu/target-i386-dm/Makefile
--- a/tools/ioemu/target-i386-dm/Makefile       Wed Dec 21 16:30:10 2005
+++ b/tools/ioemu/target-i386-dm/Makefile       Wed Dec 21 17:56:19 2005
@@ -272,6 +272,7 @@
 VL_OBJS+= ide.o ne2000.o pckbd.o vga.o dma.o
 VL_OBJS+= fdc.o mc146818rtc.o serial.o i8259_stub.o i8254.o pc.o port-e9.o
 VL_OBJS+= cirrus_vga.o pcnet.o
+VL_OBJS+= $(SOUND_HW) $(AUDIODRV) mixeng.o
 
 ifeq ($(TARGET_ARCH), ppc)
 VL_OBJS+= ppc.o ide.o ne2000.o pckbd.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
diff -r 2c75070e41a0 -r 5a790011259e tools/ioemu/vl.c
--- a/tools/ioemu/vl.c  Wed Dec 21 16:30:10 2005
+++ b/tools/ioemu/vl.c  Wed Dec 21 17:56:19 2005
@@ -119,7 +119,7 @@
 const char* keyboard_layout = 0;
 int64_t ticks_per_sec;
 int boot_device = 'c';
-int ram_size;
+uint64_t ram_size;
 int domid = -1;
 static char network_script[1024];
 int pit_min_timer_count = 0;
@@ -2906,7 +2906,7 @@
                 help();
                 break;
             case QEMU_OPTION_m:
-                ram_size = atoi(optarg) * 1024 * 1024;
+                ram_size = atol(optarg) * 1024 * 1024;
                 if (ram_size <= 0)
                     help();
                 break;
diff -r 2c75070e41a0 -r 5a790011259e tools/ioemu/vl.h
--- a/tools/ioemu/vl.h  Wed Dec 21 16:30:10 2005
+++ b/tools/ioemu/vl.h  Wed Dec 21 17:56:19 2005
@@ -37,6 +37,7 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <sys/stat.h>
+#include "audio/audio.h"
 
 #ifndef O_LARGEFILE
 #define O_LARGEFILE 0
@@ -116,7 +117,7 @@
 extern int sb16_enabled;
 extern int adlib_enabled;
 extern int gus_enabled;
-extern int ram_size;
+extern uint64_t ram_size;
 extern int bios_size;
 extern int rtc_utc;
 extern int cirrus_vga_enabled;
@@ -649,7 +650,7 @@
 int pit_get_out(PITState *pit, int channel, int64_t current_time);
 
 /* pc.c */
-void pc_init(int ram_size, int vga_ram_size, int boot_device,
+void pc_init(uint64_t ram_size, int vga_ram_size, int boot_device,
              DisplayState *ds, const char **fd_filename, int snapshot,
              const char *kernel_filename, const char *kernel_cmdline,
              const char *initrd_filename);
diff -r 2c75070e41a0 -r 5a790011259e tools/libxc/xc_domain.c
--- a/tools/libxc/xc_domain.c   Wed Dec 21 16:30:10 2005
+++ b/tools/libxc/xc_domain.c   Wed Dec 21 17:56:19 2005
@@ -380,6 +380,30 @@
     return do_dom0_op(xc_handle, &op);
 }
 
+int xc_domain_setinfo(int xc_handle,
+                      uint32_t domid,
+                      uint32_t vcpu,
+                      vcpu_guest_context_t *ctxt)
+{
+    dom0_op_t op;
+    int rc;
+
+    op.cmd = DOM0_SETDOMAININFO;
+    op.u.setdomaininfo.domain = domid;
+    op.u.setdomaininfo.vcpu = vcpu;
+    op.u.setdomaininfo.ctxt = ctxt;
+
+    if ( (rc = mlock(ctxt, sizeof(*ctxt))) != 0 )
+        return rc;
+
+    rc = do_dom0_op(xc_handle, &op);
+
+    safe_munlock(ctxt, sizeof(*ctxt));
+
+    return rc;
+
+}
+
 /*
  * Local variables:
  * mode: C
diff -r 2c75070e41a0 -r 5a790011259e tools/libxc/xc_ptrace.c
--- a/tools/libxc/xc_ptrace.c   Wed Dec 21 16:30:10 2005
+++ b/tools/libxc/xc_ptrace.c   Wed Dec 21 17:56:19 2005
@@ -1,130 +1,134 @@
+#define XC_PTRACE_PRIVATE
+
+
 #include <sys/ptrace.h>
 #include <sys/wait.h>
+#include <time.h>
+
 #include "xc_private.h"
 #include "xg_private.h"
-#include <time.h>
-
-#define X86_CR0_PE              0x00000001 /* Enable Protected Mode    (RW) */
-#define X86_CR0_PG              0x80000000 /* Paging                   (RW) */
-#define BSD_PAGE_MASK (PAGE_SIZE-1)
-#define PDRSHIFT        22
-#define PSL_T  0x00000100 /* trace enable bit */
-#define VCPU            0               /* XXX */
-
-char * ptrace_names[] = {
-    "PTRACE_TRACEME",
-    "PTRACE_PEEKTEXT",
-    "PTRACE_PEEKDATA",
-    "PTRACE_PEEKUSER",
-    "PTRACE_POKETEXT",
-    "PTRACE_POKEDATA",
-    "PTRACE_POKEUSER",
-    "PTRACE_CONT",
-    "PTRACE_KILL",
-    "PTRACE_SINGLESTEP",
-    "PTRACE_INVALID",
-    "PTRACE_INVALID",
-    "PTRACE_GETREGS",
-    "PTRACE_SETREGS",
-    "PTRACE_GETFPREGS",
-    "PTRACE_SETFPREGS",
-    "PTRACE_ATTACH",
-    "PTRACE_DETACH",
-    "PTRACE_GETFPXREGS",
-    "PTRACE_SETFPXREGS",
-    "PTRACE_INVALID",
-    "PTRACE_INVALID",
-    "PTRACE_INVALID",
-    "PTRACE_INVALID",
-    "PTRACE_SYSCALL",
-};
-
-struct gdb_regs {
-    long ebx; /* 0 */
-    long ecx; /* 4 */
-    long edx; /* 8 */
-    long esi; /* 12 */
-    long edi; /* 16 */
-    long ebp; /* 20 */
-    long eax; /* 24 */ 
-    int  xds; /* 28 */
-    int  xes; /* 32 */
-    int  xfs; /* 36 */
-    int  xgs; /* 40 */
-    long orig_eax; /* 44 */
-    long eip;    /* 48 */
-    int  xcs;    /* 52 */
-    long eflags; /* 56 */
-    long esp;    /* 60 */     
-    int  xss;    /* 64 */
-};
-
-#define FETCH_REGS(cpu)                                         \
-    if (!regs_valid[cpu])                                       \
-    {                                                           \
-        int retval = xc_domain_get_vcpu_context(                \
-            xc_handle, domid, cpu, &ctxt[cpu]);                 \
-        if (retval)                                             \
-            goto error_out;                                     \
-        cr3[cpu] = ctxt[cpu].ctrlreg[3]; /* physical address */ \
-        regs_valid[cpu] = 1;                                    \
-    }
-
-#define printval(x) printf("%s = %lx\n", #x, (long)x);
-#define SET_PT_REGS(pt, xc)                     \
-{                                               \
-    pt.ebx = xc.ebx;                            \
-    pt.ecx = xc.ecx;                            \
-    pt.edx = xc.edx;                            \
-    pt.esi = xc.esi;                            \
-    pt.edi = xc.edi;                            \
-    pt.ebp = xc.ebp;                            \
-    pt.eax = xc.eax;                            \
-    pt.eip = xc.eip;                            \
-    pt.xcs = xc.cs;                             \
-    pt.eflags = xc.eflags;                      \
-    pt.esp = xc.esp;                            \
-    pt.xss = xc.ss;                             \
-    pt.xes = xc.es;                             \
-    pt.xds = xc.ds;                             \
-    pt.xfs = xc.fs;                             \
-    pt.xgs = xc.gs;                             \
-}
-
-#define SET_XC_REGS(pt, xc)                     \
-{                                               \
-    xc.ebx = pt->ebx;                           \
-    xc.ecx = pt->ecx;                           \
-    xc.edx = pt->edx;                           \
-    xc.esi = pt->esi;                           \
-    xc.edi = pt->edi;                           \
-    xc.ebp = pt->ebp;                           \
-    xc.eax = pt->eax;                           \
-    xc.eip = pt->eip;                           \
-    xc.cs = pt->xcs;                            \
-    xc.eflags = pt->eflags;                     \
-    xc.esp = pt->esp;                           \
-    xc.ss = pt->xss;                            \
-    xc.es = pt->xes;                            \
-    xc.ds = pt->xds;                            \
-    xc.fs = pt->xfs;                            \
-    xc.gs = pt->xgs;                            \
-}
-
-#define vtopdi(va) ((va) >> PDRSHIFT)
-#define vtopti(va) (((va) >> PAGE_SHIFT) & 0x3ff)
+#include <thread_db.h>
+#include "xc_ptrace.h"
+
 
 /* XXX application state */
-static long   nr_pages = 0;
-unsigned long   *page_array = NULL;
-static int                      regs_valid[MAX_VIRT_CPUS];
-static unsigned long            cr3[MAX_VIRT_CPUS];
-static vcpu_guest_context_t ctxt[MAX_VIRT_CPUS];
-
-static inline int paging_enabled(vcpu_guest_context_t *v)
+static long                     nr_pages = 0;
+static unsigned long           *page_array = NULL;
+static int                      current_domid = -1;
+
+static cpumap_t                 online_cpumap;
+static cpumap_t                 regs_valid;
+static vcpu_guest_context_t     ctxt[MAX_VIRT_CPUS];
+
+extern int ffsll(long long int);
+#define FOREACH_CPU(cpumap, i)  for ( cpumap = online_cpumap; (i = 
ffsll(cpumap)); cpumap &= ~(1 << (index - 1)) ) 
+
+
+static int
+fetch_regs(int xc_handle, int cpu, int *online)
+{
+    xc_vcpuinfo_t info;
+    int retval = 0;
+
+    if (online)
+        *online = 0;
+    if ( !(regs_valid & (1 << cpu)) ) { 
+        retval = xc_domain_get_vcpu_context(xc_handle, current_domid, 
+                                               cpu, &ctxt[cpu]);
+        if ( retval ) 
+            goto done;
+       regs_valid |= (1 << cpu);
+
+    }
+       if ( online == NULL )
+           goto done;
+
+       retval = xc_domain_get_vcpu_info(xc_handle, current_domid,
+                                        cpu, &info);
+       *online = info.online;
+    
+ done:
+    return retval;    
+}
+
+#define FETCH_REGS(cpu) if (fetch_regs(xc_handle, cpu, NULL)) goto error_out;
+
+
+static struct thr_ev_handlers {
+    thr_ev_handler_t td_create;
+    thr_ev_handler_t td_death;
+} handlers;
+
+void 
+xc_register_event_handler(thr_ev_handler_t h, 
+                          td_event_e e)
+{
+    switch (e) {
+    case TD_CREATE:
+        handlers.td_create = h;
+        break;
+    case TD_DEATH:
+        handlers.td_death = h;
+        break;
+    default:
+        abort(); /* XXX */
+    }
+}
+
+static inline int 
+paging_enabled(vcpu_guest_context_t *v)
 {
     unsigned long cr0 = v->ctrlreg[0];
     return (cr0 & X86_CR0_PE) && (cr0 & X86_CR0_PG);
+}
+
+/*
+ * Fetch registers for all online cpus and set the cpumap
+ * to indicate which cpus are online
+ *
+ */
+
+static int
+get_online_cpumap(int xc_handle, dom0_getdomaininfo_t *d, cpumap_t *cpumap)
+{
+    int i, online, retval;
+    
+    *cpumap = 0;
+    for (i = 0; i <= d->max_vcpu_id; i++) {
+        if ((retval = fetch_regs(xc_handle, i, &online)))
+            goto error_out;        
+        if (online)
+            *cpumap |= (1 << i);            
+    }
+    
+    return 0;
+ error_out:
+    return retval;
+}
+
+/* 
+ * Notify GDB of any vcpus that have come online or gone offline
+ * update online_cpumap
+ *
+ */
+
+static void
+online_vcpus_changed(cpumap_t cpumap)
+{
+    cpumap_t changed_cpumap = cpumap ^ online_cpumap;
+    int index;
+    
+    while ( (index = ffsll(changed_cpumap)) ) {
+        if ( cpumap & (1 << (index - 1)) ) {
+            if (handlers.td_create) handlers.td_create(index - 1);
+        } else {
+            printf("thread death: %d\n", index - 1);
+            if (handlers.td_death) handlers.td_death(index - 1);
+        }
+        changed_cpumap &= ~(1 << (index - 1));
+    }
+    online_cpumap = cpumap;
+    
 }
 
 /* --------------------- */
@@ -132,7 +136,6 @@
 static void *
 map_domain_va_pae(
     int xc_handle,
-    unsigned long domid,
     int cpu,
     void *guest_va,
     int perm)
@@ -144,24 +147,24 @@
     FETCH_REGS(cpu);
 
     l3 = xc_map_foreign_range(
-        xc_handle, domid, PAGE_SIZE, PROT_READ, cr3[cpu] >> PAGE_SHIFT);
+        xc_handle, current_domid, PAGE_SIZE, PROT_READ, ctxt[cpu].ctrlreg[3] 
>> PAGE_SHIFT);
     if ( l3 == NULL )
         goto error_out;
 
     l2p = l3[l3_table_offset_pae(va)] >> PAGE_SHIFT;
-    l2 = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE, PROT_READ, l2p);
+    l2 = xc_map_foreign_range(xc_handle, current_domid, PAGE_SIZE, PROT_READ, 
l2p);
     if ( l2 == NULL )
         goto error_out;
 
     l1p = l2[l2_table_offset_pae(va)] >> PAGE_SHIFT;
-    l1 = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE, perm, l1p);
+    l1 = xc_map_foreign_range(xc_handle, current_domid, PAGE_SIZE, perm, l1p);
     if ( l1 == NULL )
         goto error_out;
 
     p = l1[l1_table_offset_pae(va)] >> PAGE_SHIFT;
     if ( v != NULL )
         munmap(v, PAGE_SIZE);
-    v = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE, perm, p);
+    v = xc_map_foreign_range(xc_handle, current_domid, PAGE_SIZE, perm, p);
     if ( v == NULL )
         goto error_out;
 
@@ -174,16 +177,17 @@
 static void *
 map_domain_va(
     int xc_handle,
-    unsigned long domid,
     int cpu,
     void *guest_va,
     int perm)
 {
+
     unsigned long pde, page;
     unsigned long va = (unsigned long)guest_va;
-    long npgs = xc_get_tot_pages(xc_handle, domid);
-
-    static unsigned long  cr3_phys[MAX_VIRT_CPUS];
+    long npgs = xc_get_tot_pages(xc_handle, current_domid);
+
+
+    static uint32_t  cr3_phys[MAX_VIRT_CPUS];
     static unsigned long *cr3_virt[MAX_VIRT_CPUS];
     static unsigned long  pde_phys[MAX_VIRT_CPUS];
     static unsigned long *pde_virt[MAX_VIRT_CPUS];
@@ -202,7 +206,7 @@
     }
 
     if ( mode == MODE_PAE )
-        return map_domain_va_pae(xc_handle, domid, cpu, guest_va, perm);
+        return map_domain_va_pae(xc_handle, cpu, guest_va, perm);
 
     if ( nr_pages != npgs )
     {
@@ -214,7 +218,7 @@
             printf("Could not allocate memory\n");
             goto error_out;
         }
-        if ( xc_get_pfn_list(xc_handle, domid,
+        if ( xc_get_pfn_list(xc_handle, current_domid,
                              page_array, nr_pages) != nr_pages )
         {
             printf("Could not get the page frame list\n");
@@ -224,13 +228,13 @@
 
     FETCH_REGS(cpu);
 
-    if ( cr3[cpu] != cr3_phys[cpu] )
-    {
-        cr3_phys[cpu] = cr3[cpu];
+    if ( ctxt[cpu].ctrlreg[3] != cr3_phys[cpu] )
+    {
+        cr3_phys[cpu] = ctxt[cpu].ctrlreg[3];
         if ( cr3_virt[cpu] )
             munmap(cr3_virt[cpu], PAGE_SIZE);
         cr3_virt[cpu] = xc_map_foreign_range(
-            xc_handle, domid, PAGE_SIZE, PROT_READ,
+            xc_handle, current_domid, PAGE_SIZE, PROT_READ,
             cr3_phys[cpu] >> PAGE_SHIFT);
         if ( cr3_virt[cpu] == NULL )
             goto error_out;
@@ -245,7 +249,7 @@
         if ( pde_virt[cpu] )
             munmap(pde_virt[cpu], PAGE_SIZE);
         pde_virt[cpu] = xc_map_foreign_range(
-            xc_handle, domid, PAGE_SIZE, PROT_READ,
+            xc_handle, current_domid, PAGE_SIZE, PROT_READ,
             pde_phys[cpu] >> PAGE_SHIFT);
         if ( pde_virt[cpu] == NULL )
             goto error_out;
@@ -260,7 +264,7 @@
         if ( page_virt[cpu] )
             munmap(page_virt[cpu], PAGE_SIZE);
         page_virt[cpu] = xc_map_foreign_range(
-            xc_handle, domid, PAGE_SIZE, perm,
+            xc_handle, current_domid, PAGE_SIZE, perm,
             page_phys[cpu] >> PAGE_SHIFT);
         if ( page_virt[cpu] == NULL )
         {
@@ -286,12 +290,15 @@
     DECLARE_DOM0_OP;
     int retval;
     struct timespec ts;
+    cpumap_t cpumap;
+
     ts.tv_sec = 0;
     ts.tv_nsec = 10*1000*1000;
 
     op.cmd = DOM0_GETDOMAININFO;
     op.u.getdomaininfo.domain = domain;
-
+    
+    
  retry:
     retval = do_dom0_op(xc_handle, &op);
     if ( retval || (op.u.getdomaininfo.domain != domain) )
@@ -309,17 +316,22 @@
         nanosleep(&ts,NULL);
         goto retry;
     }
-
+    /* XXX check for ^C here */
  done:
+    if (get_online_cpumap(xc_handle, &op.u.getdomaininfo, &cpumap))
+        printf("get_online_cpumap failed\n");
+    if (online_cpumap != cpumap)
+        online_vcpus_changed(cpumap);
     return retval;
 
 }
+
 
 long
 xc_ptrace(
     int xc_handle,
     enum __ptrace_request request,
-    uint32_t domid,
+    uint32_t domid_tid,
     long eaddr,
     long edata)
 {
@@ -328,18 +340,19 @@
     struct gdb_regs pt;
     long            retval = 0;
     unsigned long  *guest_va;
-    int             cpu = VCPU;
+    cpumap_t        cpumap;
+    int             cpu, index;
     void           *addr = (char *)eaddr;
     void           *data = (char *)edata;
 
-    op.interface_version = DOM0_INTERFACE_VERSION;
+    cpu = (request != PTRACE_ATTACH) ? domid_tid : 0;
     
     switch ( request )
     { 
     case PTRACE_PEEKTEXT:
     case PTRACE_PEEKDATA:
         guest_va = (unsigned long *)map_domain_va(
-            xc_handle, domid, cpu, addr, PROT_READ);
+            xc_handle, cpu, addr, PROT_READ);
         if ( guest_va == NULL )
         {
             status = EFAULT;
@@ -350,10 +363,10 @@
 
     case PTRACE_POKETEXT:
     case PTRACE_POKEDATA:
+        /* XXX assume that all CPUs have the same address space */
         guest_va = (unsigned long *)map_domain_va(
-            xc_handle, domid, cpu, addr, PROT_READ|PROT_WRITE);
-        if ( guest_va == NULL )
-        {
+                            xc_handle, cpu, addr, PROT_READ|PROT_WRITE);
+        if ( guest_va == NULL ) {
             status = EFAULT;
             goto error_out;
         }
@@ -363,6 +376,7 @@
     case PTRACE_GETREGS:
     case PTRACE_GETFPREGS:
     case PTRACE_GETFPXREGS:
+        
         FETCH_REGS(cpu);
         if ( request == PTRACE_GETREGS )
         {
@@ -380,44 +394,18 @@
         break;
 
     case PTRACE_SETREGS:
-        op.cmd = DOM0_SETDOMAININFO;
-        SET_XC_REGS(((struct gdb_regs *)data), ctxt[VCPU].user_regs);
-        op.u.setdomaininfo.domain = domid;
-        /* XXX need to understand multiple vcpus */
-        op.u.setdomaininfo.vcpu = cpu;
-        op.u.setdomaininfo.ctxt = &ctxt[cpu];
-        retval = do_dom0_op(xc_handle, &op);
+        SET_XC_REGS(((struct gdb_regs *)data), ctxt[cpu].user_regs);
+        retval = xc_domain_setinfo(xc_handle, current_domid, cpu, &ctxt[cpu]);
         if (retval)
             goto error_out;
         break;
 
-    case PTRACE_ATTACH:
-        op.cmd = DOM0_GETDOMAININFO;
-        op.u.getdomaininfo.domain = domid;
-        retval = do_dom0_op(xc_handle, &op);
-        if ( retval || (op.u.getdomaininfo.domain != domid) )
-        {
-            perror("dom0 op failed");
-            goto error_out;
-        }
-        if ( op.u.getdomaininfo.flags & DOMFLAGS_PAUSED )
-        {
-            printf("domain currently paused\n");
-            goto error_out;
-        }
-        printf("domain not currently paused\n");
-        op.cmd = DOM0_PAUSEDOMAIN;
-        op.u.pausedomain.domain = domid;
-        retval = do_dom0_op(xc_handle, &op);
-        break;
-
     case PTRACE_SINGLESTEP:
-        ctxt[VCPU].user_regs.eflags |= PSL_T;
-        op.cmd = DOM0_SETDOMAININFO;
-        op.u.setdomaininfo.domain = domid;
-        op.u.setdomaininfo.vcpu = 0;
-        op.u.setdomaininfo.ctxt = &ctxt[cpu];
-        retval = do_dom0_op(xc_handle, &op); 
+        /*  XXX we can still have problems if the user switches threads
+         *  during single-stepping - but that just seems retarded
+         */
+        ctxt[cpu].user_regs.eflags |= PSL_T; 
+        retval = xc_domain_setinfo(xc_handle, current_domid, cpu, &ctxt[cpu]);
         if ( retval )
         {
             perror("dom0 op failed");
@@ -429,27 +417,56 @@
     case PTRACE_DETACH:
         if ( request != PTRACE_SINGLESTEP )
         {
-            FETCH_REGS(cpu);
-            /* Clear trace flag */
-            if ( ctxt[cpu].user_regs.eflags & PSL_T )
-            {
-                ctxt[cpu].user_regs.eflags &= ~PSL_T;
-                op.cmd = DOM0_SETDOMAININFO;
-                op.u.setdomaininfo.domain = domid;
-                op.u.setdomaininfo.vcpu = cpu;
-                op.u.setdomaininfo.ctxt = &ctxt[cpu];
-                retval = do_dom0_op(xc_handle, &op); 
-                if ( retval )
-                {
-                    perror("dom0 op failed");
-                    goto error_out;
+            FOREACH_CPU(cpumap, index) {
+                cpu = index - 1;
+                FETCH_REGS(cpu);
+                /* Clear trace flag */
+                if ( ctxt[cpu].user_regs.eflags & PSL_T ) {
+                    ctxt[cpu].user_regs.eflags &= ~PSL_T;
+                    retval = xc_domain_setinfo(xc_handle, current_domid, 
+                                               cpu, &ctxt[cpu]);
+                    if ( retval ) {
+                        perror("dom0 op failed");
+                        goto error_out;
+                    }
                 }
             }
         }
-        regs_valid[cpu] = 0;
-        op.cmd = DOM0_UNPAUSEDOMAIN;
-        op.u.unpausedomain.domain = domid > 0 ? domid : -domid;
+        if ( request == PTRACE_DETACH )
+        {
+            op.cmd = DOM0_SETDEBUGGING;
+            op.u.setdebugging.domain = current_domid;
+            op.u.setdebugging.enable = 0;
+            retval = do_dom0_op(xc_handle, &op);
+        }
+        regs_valid = 0;
+        xc_domain_unpause(xc_handle, current_domid > 0 ? current_domid : 
-current_domid);
+        break;
+
+    case PTRACE_ATTACH:
+        current_domid = domid_tid;
+        op.cmd = DOM0_GETDOMAININFO;
+        op.u.getdomaininfo.domain = current_domid;
         retval = do_dom0_op(xc_handle, &op);
+        if ( retval || (op.u.getdomaininfo.domain != current_domid) )
+        {
+            perror("dom0 op failed");
+            goto error_out;
+        }
+        if ( op.u.getdomaininfo.flags & DOMFLAGS_PAUSED )
+        {
+            printf("domain currently paused\n");
+        } else
+            retval = xc_domain_pause(xc_handle, current_domid);
+        op.cmd = DOM0_SETDEBUGGING;
+        op.u.setdebugging.domain = current_domid;
+        op.u.setdebugging.enable = 1;
+        retval = do_dom0_op(xc_handle, &op);
+
+        if (get_online_cpumap(xc_handle, &op.u.getdomaininfo, &cpumap))
+            printf("get_online_cpumap failed\n");
+        if (online_cpumap != cpumap)
+            online_vcpus_changed(cpumap);
         break;
 
     case PTRACE_SETFPREGS:
diff -r 2c75070e41a0 -r 5a790011259e tools/libxc/xc_vmx_build.c
--- a/tools/libxc/xc_vmx_build.c        Wed Dec 21 16:30:10 2005
+++ b/tools/libxc/xc_vmx_build.c        Wed Dec 21 17:56:19 2005
@@ -288,11 +288,11 @@
     l2_pgentry_t *vl2tab=NULL, *vl2e=NULL;
     unsigned long *page_array = NULL;
 #ifdef __x86_64__
-    l3_pgentry_t *vl3tab=NULL, *vl3e=NULL;
+    l3_pgentry_t *vl3tab=NULL;
     unsigned long l3tab;
 #endif
-    unsigned long l2tab;
-    unsigned long l1tab;
+    unsigned long l2tab = 0;
+    unsigned long l1tab = 0;
     unsigned long count, i;
     shared_info_t *shared_info;
     void *e820_page;
@@ -323,7 +323,7 @@
     }
 
     /* memsize is in megabytes */
-    v_end              = memsize << 20;
+    v_end              = (unsigned long)memsize << 20;
 
 #ifdef __i386__
     nr_pt_pages = 1 + ((memsize + 3) >> 2);
@@ -435,15 +435,16 @@
             goto error_out;
         memset(vl2tab, 0, PAGE_SIZE);
         munmap(vl2tab, PAGE_SIZE);
+        vl2tab = NULL;
         vl3tab[i] = l2tab | L3_PROT;
     }
 
-    vl3e = &vl3tab[l3_table_offset(0)];
     for ( count = 0; count < (v_end >> PAGE_SHIFT); count++ )
     {
-        if (!(count & (1 << (L3_PAGETABLE_SHIFT - L1_PAGETABLE_SHIFT)))){
+        if ( !(count & ((1 << (L3_PAGETABLE_SHIFT - L1_PAGETABLE_SHIFT)) - 1)) 
)
+        {
             l2tab = vl3tab[count >> (L3_PAGETABLE_SHIFT - L1_PAGETABLE_SHIFT)]
-                & PAGE_MASK;
+                    & PAGE_MASK;
 
             if (vl2tab != NULL)
                 munmap(vl2tab, PAGE_SIZE);
diff -r 2c75070e41a0 -r 5a790011259e tools/libxc/xenctrl.h
--- a/tools/libxc/xenctrl.h     Wed Dec 21 16:30:10 2005
+++ b/tools/libxc/xenctrl.h     Wed Dec 21 17:56:19 2005
@@ -94,25 +94,12 @@
 } xc_core_header_t;
 
 
-long xc_ptrace(
-    int xc_handle,
-    enum __ptrace_request request, 
-    uint32_t  domid,
-    long addr, 
-    long data);
-
 long xc_ptrace_core(
     int xc_handle,
     enum __ptrace_request request, 
     uint32_t domid, 
     long addr, 
     long data);
-
-int xc_waitdomain(
-    int xc_handle,
-    int domain, 
-    int *status, 
-    int options);
 
 int xc_waitdomain_core(
     int xc_handle,
@@ -219,6 +206,20 @@
                       unsigned int max_doms,
                       xc_dominfo_t *info);
 
+
+/**
+ * This function will set the vcpu context for the specified domain.
+ *
+ * @parm xc_handle a handle to an open hypervisor interface
+ * @parm domid the domain to set the vcpu context for
+ * @parm vcpu the vcpu number for the context
+ * @parm ctxt pointer to the the cpu context with the values to set
+ * @return the number of domains enumerated or -1 on error
+ */
+int xc_domain_setinfo(int xc_handle,
+                      uint32_t domid,
+                      uint32_t vcpu,
+                      vcpu_guest_context_t *ctxt);
 /**
  * This function will return information about one or more domains, using a
  * single hypercall.  The domain information will be stored into the supplied
diff -r 2c75070e41a0 -r 5a790011259e tools/python/xen/xend/image.py
--- a/tools/python/xen/xend/image.py    Wed Dec 21 16:30:10 2005
+++ b/tools/python/xen/xend/image.py    Wed Dec 21 17:56:19 2005
@@ -237,7 +237,7 @@
     # Return a list of cmd line args to the device models based on the
     # xm config file
     def parseDeviceModelArgs(self, imageConfig, deviceConfig):
-        dmargs = [ 'cdrom', 'boot', 'fda', 'fdb', 'ne2000', 
+        dmargs = [ 'cdrom', 'boot', 'fda', 'fdb', 'ne2000', 'audio',
                    'localtime', 'serial', 'stdvga', 'isa', 'vcpus']
         ret = []
         for a in dmargs:
@@ -246,9 +246,10 @@
             # python doesn't allow '-' in variable names
             if a == 'stdvga': a = 'std-vga'
             if a == 'ne2000': a = 'nic-ne2000'
+            if a == 'audio': a = 'enable-audio'
 
             # Handle booleans gracefully
-            if a in ['localtime', 'std-vga', 'isa', 'nic-ne2000']:
+            if a in ['localtime', 'std-vga', 'isa', 'nic-ne2000', 
'enable-audio']:
                 if v != None: v = int(v)
                 if v: ret.append("-%s" % a)
             else:
diff -r 2c75070e41a0 -r 5a790011259e tools/python/xen/xend/uuid.py
--- a/tools/python/xen/xend/uuid.py     Wed Dec 21 16:30:10 2005
+++ b/tools/python/xen/xend/uuid.py     Wed Dec 21 17:56:19 2005
@@ -17,8 +17,13 @@
 #============================================================================
 
 
-"""Universal(ly) Unique Identifiers (UUIDs).
-"""
+"""Universal Unique Identifiers (UUIDs).  By default, UUIDs generated here are
+purely random, with no internal structure.  However, they are the same size,
+and are formatted by the same conventions, as the UUIDs in the Open Software
+Foundation's Distributed Computing Environment (OSF DCE).  This allows Xend to
+be used with UUIDs generated as per the DCE specification, should that be
+required.  These UUIDs are also, by no coincidence, the same size as the
+'handle' stored by the Xen hypervisor along with the domain structure."""
 
 
 import commands
@@ -54,7 +59,8 @@
 
 
 def toString(u):
-    return "-".join(["%02x" * 4] * 4) % tuple(u)
+    return "-".join(["%02x" * 4, "%02x" * 2, "%02x" * 2, "%02x" * 2,
+                     "%02x" * 6]) % tuple(u)
 
 def fromString(s):
     s = s.replace('-', '')
diff -r 2c75070e41a0 -r 5a790011259e tools/python/xen/xm/create.py
--- a/tools/python/xen/xm/create.py     Wed Dec 21 16:30:10 2005
+++ b/tools/python/xen/xm/create.py     Wed Dec 21 17:56:19 2005
@@ -371,6 +371,10 @@
 gopts.var('ne2000', val='no|yes',
           fn=set_bool, default=0,
           use="Should device models use ne2000?")
+
+gopts.var('audio', val='no|yes',
+          fn=set_bool, default=0,
+          use="Should device models enable audio?")
 
 gopts.var('vnc', val='',
           fn=set_value, default=None,
@@ -521,7 +525,7 @@
     """Create the config for VMX devices.
     """
     args = [ 'device_model', 'vcpus', 'cdrom', 'boot', 'fda', 'fdb',
-             'localtime', 'serial', 'stdvga', 'isa', 'nographic',
+             'localtime', 'serial', 'stdvga', 'isa', 'nographic', 'audio',
              'vnc', 'vncviewer', 'sdl', 'display', 'ne2000', 'lapic']
     for a in args:
         if (vals.__dict__[a]):
diff -r 2c75070e41a0 -r 5a790011259e tools/tests/Makefile
--- a/tools/tests/Makefile      Wed Dec 21 16:30:10 2005
+++ b/tools/tests/Makefile      Wed Dec 21 17:56:19 2005
@@ -6,6 +6,8 @@
 
 CC     := gcc
 CFLAGS := -O2 -Wall -Werror -D__TEST_HARNESS__
+
+all: $(TARGET)
 
 $(TARGET): x86_emulate.o test_x86_emulator.o
        $(CC) -o $@ $^
diff -r 2c75070e41a0 -r 5a790011259e tools/tests/test_x86_emulator.c
--- a/tools/tests/test_x86_emulator.c   Wed Dec 21 16:30:10 2005
+++ b/tools/tests/test_x86_emulator.c   Wed Dec 21 17:56:19 2005
@@ -254,6 +254,36 @@
         goto fail;
     printf("okay\n");
 
+    printf("%-40s", "Testing movsxbd (%%eax),%%ecx...");
+    instr[0] = 0x0f; instr[1] = 0xbe; instr[2] = 0x08;
+    regs.eip    = (unsigned long)&instr[0];
+    regs.ecx    = 0x12345678;
+    cr2         = (unsigned long)&res;
+    res         = 0x82;
+    rc = x86_emulate_memop(&regs, cr2, &emulops, 4);
+    if ( (rc != 0) ||
+         (res != 0x82) ||
+         (regs.ecx != 0xFFFFFF82) ||
+         ((regs.eflags&0x240) != 0x200) ||
+         (regs.eip != (unsigned long)&instr[3]) )
+        goto fail;
+    printf("okay\n");
+
+    printf("%-40s", "Testing movzxwd (%%eax),%%ecx...");
+    instr[0] = 0x0f; instr[1] = 0xb7; instr[2] = 0x08;
+    regs.eip    = (unsigned long)&instr[0];
+    regs.ecx    = 0x12345678;
+    cr2         = (unsigned long)&res;
+    res         = 0x1234aa82;
+    rc = x86_emulate_memop(&regs, cr2, &emulops, 4);
+    if ( (rc != 0) ||
+         (res != 0x1234aa82) ||
+         (regs.ecx != 0xaa82) ||
+         ((regs.eflags&0x240) != 0x200) ||
+         (regs.eip != (unsigned long)&instr[3]) )
+        goto fail;
+    printf("okay\n");
+
     return 0;
 
  fail:
diff -r 2c75070e41a0 -r 5a790011259e tools/vtpm_manager/manager/securestorage.c
--- a/tools/vtpm_manager/manager/securestorage.c        Wed Dec 21 16:30:10 2005
+++ b/tools/vtpm_manager/manager/securestorage.c        Wed Dec 21 17:56:19 2005
@@ -54,48 +54,138 @@
 #include "buffer.h"
 #include "log.h"
 
+TPM_RESULT envelope_encrypt(const buffer_t     *inbuf,
+                            CRYPTO_INFO  *asymkey,
+                            buffer_t           *sealed_data) {
+  TPM_RESULT status = TPM_SUCCESS;
+  symkey_t    symkey;
+  buffer_t    data_cipher = NULL_BUF,
+              symkey_cipher = NULL_BUF;
+  
+  UINT32 i;
+  struct pack_constbuf_t symkey_cipher32, data_cipher32;
+  
+  vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Enveloping[%d]: 0x", buffer_len(inbuf));
+  for (i=0; i< buffer_len(inbuf); i++)
+    vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", inbuf->bytes[i]);
+  vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
+  
+  // Generate a sym key and encrypt state with it
+  TPMTRY(TPM_ENCRYPT_ERROR, Crypto_symcrypto_genkey (&symkey) );
+  TPMTRY(TPM_ENCRYPT_ERROR, Crypto_symcrypto_encrypt (&symkey, inbuf, 
&data_cipher) );
+  
+  // Encrypt symmetric key
+  TPMTRYRETURN( VTSP_Bind(    asymkey, 
+                             &symkey.key, 
+                             &symkey_cipher) );
+  
+  // Create output blob: symkey_size + symkey_cipher + state_cipher_size + 
state_cipher
+  
+  symkey_cipher32.size = buffer_len(&symkey_cipher);
+  symkey_cipher32.data = symkey_cipher.bytes;
+  
+  data_cipher32.size = buffer_len(&data_cipher);
+  data_cipher32.data = data_cipher.bytes;
+  
+  TPMTRYRETURN( buffer_init(sealed_data, 2 * sizeof(UINT32) + 
symkey_cipher32.size + data_cipher32.size, NULL));
+  
+  BSG_PackList(sealed_data->bytes, 2,
+              BSG_TPM_SIZE32_DATA, &symkey_cipher32,
+              BSG_TPM_SIZE32_DATA, &data_cipher32);
+
+  vtpmloginfo(VTPM_LOG_VTPM, "Saved %d bytes of E(symkey) + %d bytes of 
E(data)\n", buffer_len(&symkey_cipher), buffer_len(&data_cipher));
+  goto egress;
+
+ abort_egress:
+  vtpmlogerror(VTPM_LOG_VTPM, "Failed to envelope encrypt\n.");
+  
+ egress:
+  
+  buffer_free ( &data_cipher);
+  buffer_free ( &symkey_cipher);
+  Crypto_symcrypto_freekey (&symkey);
+  
+  return status;
+}
+
+TPM_RESULT envelope_decrypt(const long         cipher_size,
+                            const BYTE         *cipher,
+                            TCS_CONTEXT_HANDLE TCSContext,
+                           TPM_HANDLE         keyHandle,
+                           const TPM_AUTHDATA *key_usage_auth,
+                            buffer_t           *unsealed_data) {
+
+  TPM_RESULT status = TPM_SUCCESS;
+  symkey_t    symkey;
+  buffer_t    data_cipher = NULL_BUF, 
+              symkey_clear = NULL_BUF, 
+              symkey_cipher = NULL_BUF;
+  struct pack_buf_t symkey_cipher32, data_cipher32;
+  int i;
+
+  memset(&symkey, 0, sizeof(symkey_t));
+
+  vtpmloginfo(VTPM_LOG_VTPM_DEEP, "envelope decrypting[%ld]: 0x", cipher_size);
+  for (i=0; i< cipher_size; i++)
+    vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", cipher[i]);
+  vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
+  
+  BSG_UnpackList(cipher, 2,
+                BSG_TPM_SIZE32_DATA, &symkey_cipher32,
+                BSG_TPM_SIZE32_DATA, &data_cipher32);
+  
+  TPMTRYRETURN( buffer_init_convert (&symkey_cipher, 
+                                    symkey_cipher32.size, 
+                                    symkey_cipher32.data) );
+  
+  TPMTRYRETURN( buffer_init_convert (&data_cipher, 
+                                    data_cipher32.size, 
+                                    data_cipher32.data) );
+
+  // Decrypt Symmetric Key
+  TPMTRYRETURN( VTSP_Unbind(  TCSContext,
+                             keyHandle,
+                             &symkey_cipher,
+                             key_usage_auth,
+                             &symkey_clear,
+                             &(vtpm_globals->keyAuth) ) );
+  
+  // create symmetric key using saved bits
+  Crypto_symcrypto_initkey (&symkey, &symkey_clear);
+  
+  // Decrypt State
+  TPMTRY(TPM_DECRYPT_ERROR, Crypto_symcrypto_decrypt (&symkey, &data_cipher, 
unsealed_data) );
+  
+  goto egress;
+  
+ abort_egress:
+  vtpmlogerror(VTPM_LOG_VTPM, "Failed to envelope decrypt data\n.");
+  
+ egress:
+  buffer_free ( &data_cipher);
+  buffer_free ( &symkey_clear);
+  buffer_free ( &symkey_cipher);
+  Crypto_symcrypto_freekey (&symkey);
+  
+  return status;
+}
+
 TPM_RESULT VTPM_Handle_Save_NVM(VTPM_DMI_RESOURCE *myDMI, 
                                const buffer_t *inbuf, 
                                buffer_t *outbuf) {
   
   TPM_RESULT status = TPM_SUCCESS;
-  symkey_t    symkey;
-  buffer_t    state_cipher = NULL_BUF,
-              symkey_cipher = NULL_BUF;
   int fh;
   long bytes_written;
-  BYTE *sealed_NVM=NULL;
-  UINT32 sealed_NVM_size, i;
-  struct pack_constbuf_t symkey_cipher32, state_cipher32;
-  
-  vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Save_NVMing[%d]: 0x", buffer_len(inbuf));
-  for (i=0; i< buffer_len(inbuf); i++)
-    vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", inbuf->bytes[i]);
-  vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
-  
-  // Generate a sym key and encrypt state with it
-  TPMTRY(TPM_ENCRYPT_ERROR, Crypto_symcrypto_genkey (&symkey) );
-  TPMTRY(TPM_ENCRYPT_ERROR, Crypto_symcrypto_encrypt (&symkey, inbuf, 
&state_cipher) );
-  
-  // Encrypt symmetric key
-  TPMTRYRETURN( VTSP_Bind(    &vtpm_globals->storageKey, 
-                             &symkey.key, 
-                             &symkey_cipher) );
-  
-  // Create output blob: symkey_size + symkey_cipher + state_cipher_size + 
state_cipher
-  
-  symkey_cipher32.size = buffer_len(&symkey_cipher);
-  symkey_cipher32.data = symkey_cipher.bytes;
-  
-  state_cipher32.size = buffer_len(&state_cipher);
-  state_cipher32.data = state_cipher.bytes;
-  
-  sealed_NVM = (BYTE *) malloc( 2 * sizeof(UINT32) + symkey_cipher32.size + 
state_cipher32.size);
-  
-  sealed_NVM_size = BSG_PackList(sealed_NVM, 2,
-                                BSG_TPM_SIZE32_DATA, &symkey_cipher32,
-                                BSG_TPM_SIZE32_DATA, &state_cipher32);
-  
+  buffer_t sealed_NVM;
+  
+  
+  vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Save_NVMing[%d]: 0x\n", buffer_len(inbuf));
+
+  TPMTRYRETURN( envelope_encrypt(inbuf,
+                                 &vtpm_globals->storageKey,
+                                 &sealed_NVM) );
+                                 
   // Mark DMI Table so new save state info will get pushed to disk on return.
   vtpm_globals->DMI_table_dirty = TRUE;
   
@@ -104,28 +194,22 @@
   //       after writing the file? We can't get the old one back.
   // TODO: Backup old file and try and recover that way.
   fh = open(myDMI->NVMLocation, O_WRONLY | O_CREAT, S_IREAD | S_IWRITE);
-  if ( (bytes_written = write(fh, sealed_NVM, sealed_NVM_size) ) != (long) 
sealed_NVM_size) {
-    vtpmlogerror(VTPM_LOG_VTPM, "We just overwrote a DMI_NVM and failed to 
finish. %ld/%ld bytes.\n", bytes_written, (long)sealed_NVM_size);
+  if ( (bytes_written = write(fh, sealed_NVM.bytes, buffer_len(&sealed_NVM) ) 
!= (long) buffer_len(&sealed_NVM))) {
+    vtpmlogerror(VTPM_LOG_VTPM, "We just overwrote a DMI_NVM and failed to 
finish. %ld/%ld bytes.\n", bytes_written, (long)buffer_len(&sealed_NVM));
     status = TPM_IOERROR;
     goto abort_egress;
   }
   close(fh);
   
-  Crypto_SHA1Full (sealed_NVM, sealed_NVM_size, (BYTE *) 
&myDMI->NVM_measurement);   
-  
-  vtpmloginfo(VTPM_LOG_VTPM, "Saved %d bytes of E(symkey) + %d bytes of 
E(NVM)\n", buffer_len(&symkey_cipher), buffer_len(&state_cipher));
-  goto egress;
-  
- abort_egress:
-  vtpmlogerror(VTPM_LOG_VTPM, "Failed to load NVM\n.");
-  
- egress:
-  
-  buffer_free ( &state_cipher);
-  buffer_free ( &symkey_cipher);
-  free(sealed_NVM);
-  Crypto_symcrypto_freekey (&symkey);
-  
+  Crypto_SHA1Full (sealed_NVM.bytes, buffer_len(&sealed_NVM), (BYTE *) 
&myDMI->NVM_measurement);   
+  
+  goto egress;
+  
+ abort_egress:
+  vtpmlogerror(VTPM_LOG_VTPM, "Failed to save NVM\n.");
+  
+ egress:
+  buffer_free(&sealed_NVM);
   return status;
 }
 
@@ -136,11 +220,7 @@
                                buffer_t *outbuf) {
   
   TPM_RESULT status = TPM_SUCCESS;
-  symkey_t    symkey;
-  buffer_t    state_cipher = NULL_BUF, 
-              symkey_clear = NULL_BUF, 
-              symkey_cipher = NULL_BUF;
-  struct pack_buf_t symkey_cipher32, state_cipher32;
+
   
   UINT32 sealed_NVM_size;
   BYTE *sealed_NVM = NULL;
@@ -148,9 +228,7 @@
   int fh, stat_ret, i;
   struct stat file_stat;
   TPM_DIGEST sealedNVMHash;
-  
-  memset(&symkey, 0, sizeof(symkey_t));
-  
+   
   if (myDMI->NVMLocation == NULL) {
     vtpmlogerror(VTPM_LOG_VTPM, "Unable to load NVM because the file name 
NULL.\n");
     status = TPM_AUTHFAIL;
@@ -168,28 +246,14 @@
   }
   
   sealed_NVM = (BYTE *) malloc(fh_size);
+  sealed_NVM_size = (UINT32) fh_size;
   if (read(fh, sealed_NVM, fh_size) != fh_size) {
     status = TPM_IOERROR;
     goto abort_egress;
   }
   close(fh);
   
-  vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Load_NVMing[%ld]: 0x", fh_size);
-  for (i=0; i< fh_size; i++)
-    vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", sealed_NVM[i]);
-  vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
-  
-  sealed_NVM_size = BSG_UnpackList(sealed_NVM, 2,
-                                  BSG_TPM_SIZE32_DATA, &symkey_cipher32,
-                                  BSG_TPM_SIZE32_DATA, &state_cipher32);
-  
-  TPMTRYRETURN( buffer_init_convert (&symkey_cipher, 
-                                    symkey_cipher32.size, 
-                                    symkey_cipher32.data) );
-  
-  TPMTRYRETURN( buffer_init_convert (&state_cipher, 
-                                    state_cipher32.size, 
-                                    state_cipher32.data) );
+  vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Load_NVMing[%ld],\n", fh_size);
   
   Crypto_SHA1Full(sealed_NVM, sealed_NVM_size, (BYTE *) &sealedNVMHash);    
   
@@ -210,32 +274,19 @@
     goto abort_egress;
   }
   
-  // Decrypt Symmetric Key
-  TPMTRYRETURN( VTSP_Unbind(  myDMI->TCSContext,
-                             vtpm_globals->storageKeyHandle,
-                             &symkey_cipher,
-                             (const 
TPM_AUTHDATA*)&vtpm_globals->storage_key_usage_auth,
-                             &symkey_clear,
-                             &(vtpm_globals->keyAuth) ) );
-  
-  // create symmetric key using saved bits
-  Crypto_symcrypto_initkey (&symkey, &symkey_clear);
-  
-  // Decrypt State
-  TPMTRY(TPM_DECRYPT_ERROR, Crypto_symcrypto_decrypt (&symkey, &state_cipher, 
outbuf) );
-  
+    TPMTRYRETURN( envelope_decrypt(fh_size,
+                                 sealed_NVM,
+                                 myDMI->TCSContext,
+                                vtpm_globals->storageKeyHandle,
+                                (const 
TPM_AUTHDATA*)&vtpm_globals->storage_key_usage_auth,
+                                 outbuf) );  
   goto egress;
   
  abort_egress:
   vtpmlogerror(VTPM_LOG_VTPM, "Failed to load NVM\n.");
   
  egress:
-  
-  buffer_free ( &state_cipher);
-  buffer_free ( &symkey_clear);
-  buffer_free ( &symkey_cipher);
   free( sealed_NVM );
-  Crypto_symcrypto_freekey (&symkey);
   
   return status;
 }
diff -r 2c75070e41a0 -r 5a790011259e tools/xm-test/README
--- a/tools/xm-test/README      Wed Dec 21 16:30:10 2005
+++ b/tools/xm-test/README      Wed Dec 21 17:56:19 2005
@@ -54,6 +54,26 @@
 you should not attempt to use a ramdisk from a previous minor version
 of xm-test (i.e., don't use a ramdisk from 0.4.0 with 0.5.0.  0.5.0
 should work for 0.5.3 though)
+
+If you'd like to build and run this with hardware virtual machine assist
+(HVM) support to test fully virtualized disk images on VMX hardware, 
+please add the --enable-vmx-support option to configure:
+
+  # ./autogen
+  # ./configure --enable-vmx-support
+  # make
+
+The ramdisk/bin/create_disk_image script, which builds the full virt
+disk.img, requires Lilo 22.7+ to be installed on the system. Lilo is 
+used to install the bootloader on the disk.img.
+
+If HVM / VMX support is enabled, the ramdisk/bin/create_disk_image script
+will be run to create a full virt disk.img in the ramdisk directory. The
+script, by default, will look in /boot for the first non-Xen kernel it
+runs across. If you wish to use a different kernel or the script fails
+to find a kernel, please run the script manually to make a disk.img 
+using the -k option. Xm-test will look for disk.img in the ramdisk
+directory when run by default.
 
 
 Running
diff -r 2c75070e41a0 -r 5a790011259e tools/xm-test/ramdisk/Makefile.am
--- a/tools/xm-test/ramdisk/Makefile.am Wed Dec 21 16:30:10 2005
+++ b/tools/xm-test/ramdisk/Makefile.am Wed Dec 21 17:56:19 2005
@@ -45,7 +45,7 @@
 
 disk.img: $(XMTEST_VER_IMG)
        chmod a+x $(VMX_SCRIPT)
-       $(VMX_SCRIPT) -r $(XMTEST_VER_IMG) -i disk.img
+       $(VMX_SCRIPT) -r $(XMTEST_VER_IMG)
 
 existing:
        @[ -f $(XMTEST_VER_IMG) ] && ln -sf $(XMTEST_VER_IMG) initrd.img || \
diff -r 2c75070e41a0 -r 5a790011259e tools/xm-test/ramdisk/bin/create_disk_image
--- a/tools/xm-test/ramdisk/bin/create_disk_image       Wed Dec 21 16:30:10 2005
+++ b/tools/xm-test/ramdisk/bin/create_disk_image       Wed Dec 21 17:56:19 2005
@@ -77,7 +77,7 @@
 function initialize_globals()
 {
        PROGNAME="create_disk_image"
-       IMAGE="hvm.img"
+       IMAGE="disk.img"
        KERNEL=""
        LCONF="lilo.conf"
        LOOPD=""    # Loop device for entire disk image
diff -r 2c75070e41a0 -r 5a790011259e 
tools/xm-test/tests/block-create/11_block_attach_shared_dom0.py
--- a/tools/xm-test/tests/block-create/11_block_attach_shared_dom0.py   Wed Dec 
21 16:30:10 2005
+++ b/tools/xm-test/tests/block-create/11_block_attach_shared_dom0.py   Wed Dec 
21 17:56:19 2005
@@ -34,3 +34,5 @@
     FAIL("Bug #331: Started a DomU with write access to a rw mounted block 
device")
 except DomainError, e:
     s, o = traceCommand("umount mnt")
+
+domain.destroy()
diff -r 2c75070e41a0 -r 5a790011259e 
tools/xm-test/tests/block-create/12_block_attach_shared_domU.py
--- a/tools/xm-test/tests/block-create/12_block_attach_shared_domU.py   Wed Dec 
21 16:30:10 2005
+++ b/tools/xm-test/tests/block-create/12_block_attach_shared_domU.py   Wed Dec 
21 17:56:19 2005
@@ -20,8 +20,11 @@
     FAIL("Unable to start domain")
 
 try:
-    dom2.start()
+    try:
+        dom2.start()
+        FAIL("Bug #331: Started a DomU with write access to an in-use block 
device")
+    except DomainError, e:
+        pass
+finally:
     dom1.destroy()
-    FAIL("Bug #331: Started a DomU with write access to an in-use block 
device")
-except DomainError, e:
-    dom1.destroy()
+    dom2.destroy()
diff -r 2c75070e41a0 -r 5a790011259e 
tools/xm-test/tests/network/11_network_domU_ping_pos.py
--- a/tools/xm-test/tests/network/11_network_domU_ping_pos.py   Wed Dec 21 
16:30:10 2005
+++ b/tools/xm-test/tests/network/11_network_domU_ping_pos.py   Wed Dec 21 
17:56:19 2005
@@ -19,7 +19,7 @@
 
 def netDomain(ip):
     config = {"vif"  : ["ip=%s" % ip]}
-    domain = XmTestDomain(extraConfig=config)
+    dom = XmTestDomain(extraConfig=config)
     try:
         dom.start()
     except DomainError, e:
diff -r 2c75070e41a0 -r 5a790011259e 
tools/xm-test/tests/vcpu-disable/01_vcpu-disable_basic_pos.py
--- a/tools/xm-test/tests/vcpu-disable/01_vcpu-disable_basic_pos.py     Wed Dec 
21 16:30:10 2005
+++ b/tools/xm-test/tests/vcpu-disable/01_vcpu-disable_basic_pos.py     Wed Dec 
21 17:56:19 2005
@@ -50,7 +50,7 @@
     FAIL(str(e))
 
 # Disable VCPU 1
-cmd = "xm set-vcpus %s 1" % domain.getName()
+cmd = "xm vcpu-set %s 1" % domain.getName()
 status, output = safecmd(cmd)
 if check_status and status != 0:
     FAIL("\"%s\" returned invalid %i != 0" %(cmd,status))
@@ -68,7 +68,7 @@
     FAIL("failed to disable VCPU1")
 
 # Enable VCPU 1
-cmd = "xm set-vcpus %s 2" % domain.getName()
+cmd = "xm vcpu-set %s 2" % domain.getName()
 status, output = safecmd(cmd)
 if check_status and status != 0:
     FAIL("\"%s\" returned invalid %i != 0" %(cmd,status))
diff -r 2c75070e41a0 -r 5a790011259e xen/Rules.mk
--- a/xen/Rules.mk      Wed Dec 21 16:30:10 2005
+++ b/xen/Rules.mk      Wed Dec 21 17:56:19 2005
@@ -6,7 +6,6 @@
 debug       ?= n
 perfc       ?= n
 perfc_arrays?= n
-domu_debug  ?= n
 crash_debug ?= n
 
 XEN_ROOT=$(BASEDIR)/..
@@ -54,10 +53,6 @@
 CFLAGS += -g -DVERBOSE
 endif
 
-ifeq ($(domu_debug),y)
-CFLAGS += -DDOMU_DEBUG
-endif
-
 ifeq ($(crash_debug),y)
 CFLAGS += -g -DCRASH_DEBUG
 endif
diff -r 2c75070e41a0 -r 5a790011259e xen/arch/ia64/vmx/vlsapic.c
--- a/xen/arch/ia64/vmx/vlsapic.c       Wed Dec 21 16:30:10 2005
+++ b/xen/arch/ia64/vmx/vlsapic.c       Wed Dec 21 17:56:19 2005
@@ -476,19 +476,20 @@
  * May come from virtualization fault or
  * nested host interrupt.
  */
-void vmx_vcpu_pend_interrupt(VCPU *vcpu, UINT64 vector)
+int vmx_vcpu_pend_interrupt(VCPU *vcpu, uint8_t vector)
 {
     uint64_t    spsr;
+    int ret;
 
     if (vector & ~0xff) {
         DPRINTK("vmx_vcpu_pend_interrupt: bad vector\n");
         return;
     }
     local_irq_save(spsr);
-    VCPU(vcpu,irr[vector>>6]) |= 1UL<<(vector&63);
-    //vlapic_update_shared_irr(vcpu);
+    ret = test_and_set_bit(vector, &VCPU(vcpu, irr[0]));
     local_irq_restore(spsr);
     vcpu->arch.irq_new_pending = 1;
+    return ret;
 }
 
 /*
@@ -505,7 +506,6 @@
     for (i=0 ; i<4; i++ ) {
         VCPU(vcpu,irr[i]) |= pend_irr[i];
     }
-    //vlapic_update_shared_irr(vcpu);
     local_irq_restore(spsr);
     vcpu->arch.irq_new_pending = 1;
 }
@@ -592,7 +592,6 @@
     VLSAPIC_INSVC(vcpu,vec>>6) |= (1UL <<(vec&63));
     VCPU(vcpu, irr[vec>>6]) &= ~(1UL <<(vec&63));
     update_vhpi(vcpu, NULL_VECTOR);     // clear VHPI till EOI or IRR write
-    //vlapic_update_shared_irr(vcpu);
     local_irq_restore(spsr);
     return (uint64_t)vec;
 }
diff -r 2c75070e41a0 -r 5a790011259e xen/arch/x86/audit.c
--- a/xen/arch/x86/audit.c      Wed Dec 21 16:30:10 2005
+++ b/xen/arch/x86/audit.c      Wed Dec 21 17:56:19 2005
@@ -61,7 +61,7 @@
 #ifdef __i386__
 #ifdef CONFIG_X86_PAE
         /* 32b PAE */
-        if ( (( frame_table[mfn].u.inuse.type_info & PGT_va_mask ) 
+        if ( (( pfn_to_page(mfn)->u.inuse.type_info & PGT_va_mask ) 
            >> PGT_va_shift) == 3 )
             return l2_table_offset(HYPERVISOR_VIRT_START); 
         else
@@ -364,7 +364,7 @@
             {
                 gmfn = __gpfn_to_mfn(d, a->gpfn_and_flags & PGT_mfn_mask);
                 smfn = a->smfn;
-                page = &frame_table[smfn];
+                page = pfn_to_page(smfn);
 
                 switch ( a->gpfn_and_flags & PGT_type_mask ) {
                 case PGT_writable_pred:
@@ -433,11 +433,13 @@
         for_each_vcpu(d, v)
         {
             if ( pagetable_get_paddr(v->arch.guest_table) )
-                adjust(&frame_table[pagetable_get_pfn(v->arch.guest_table)], 
!shadow_mode_refcounts(d));
+                adjust(pfn_to_page(pagetable_get_pfn(v->arch.guest_table)),
+                       !shadow_mode_refcounts(d));
             if ( pagetable_get_paddr(v->arch.shadow_table) )
-                adjust(&frame_table[pagetable_get_pfn(v->arch.shadow_table)], 
0);
+                adjust(pfn_to_page(pagetable_get_pfn(v->arch.shadow_table)),
+                       0);
             if ( v->arch.monitor_shadow_ref )
-                adjust(&frame_table[v->arch.monitor_shadow_ref], 0);
+                adjust(pfn_to_page(v->arch.monitor_shadow_ref), 0);
         }
     }
 
@@ -617,7 +619,7 @@
     void scan_for_pfn_in_mfn(struct domain *d, unsigned long xmfn,
                              unsigned long mfn)
     {
-        struct pfn_info *page = &frame_table[mfn];
+        struct pfn_info *page = pfn_to_page(mfn);
         l1_pgentry_t *pt = map_domain_page(mfn);
         int i;
 
diff -r 2c75070e41a0 -r 5a790011259e xen/arch/x86/dm/vmx_vioapic.c
--- a/xen/arch/x86/dm/vmx_vioapic.c     Wed Dec 21 16:30:10 2005
+++ b/xen/arch/x86/dm/vmx_vioapic.c     Wed Dec 21 17:56:19 2005
@@ -306,14 +306,8 @@
     switch (delivery_mode) {
     case VLAPIC_DELIV_MODE_FIXED:
     case VLAPIC_DELIV_MODE_LPRI:
-        if (test_and_set_bit(vector, &VLAPIC_IRR(target)) && trig_mode == 1) {
-            /* the level interrupt should not happen before it is cleard */
+        if (vlapic_set_irq(target, vector, trig_mode) && (trig_mode == 1))
             printk("<ioapic_inj_irq> level interrupt happen before cleard\n");
-        }
-#ifndef __ia64__
-        if (trig_mode)
-            test_and_set_bit(vector, &target->tmr[0]);
-#endif
         result = 1;
         break;
     default:
diff -r 2c75070e41a0 -r 5a790011259e xen/arch/x86/dom0_ops.c
--- a/xen/arch/x86/dom0_ops.c   Wed Dec 21 16:30:10 2005
+++ b/xen/arch/x86/dom0_ops.c   Wed Dec 21 17:56:19 2005
@@ -210,7 +210,7 @@
              unlikely((d = find_domain_by_id(dom)) == NULL) )
             break;
 
-        page = &frame_table[pfn];
+        page = pfn_to_page(pfn);
 
         if ( likely(get_page(page, d)) )
         {
@@ -285,7 +285,7 @@
                 struct pfn_info *page;
                 unsigned long mfn = l_arr[j];
 
-                page = &frame_table[mfn];
+                page = pfn_to_page(mfn);
 
                 if ( likely(pfn_valid(mfn) && get_page(page, d)) ) 
                 {
@@ -350,15 +350,14 @@
             list_ent = d->page_list.next;
             for ( i = 0; (i < max_pfns) && (list_ent != &d->page_list); i++ )
             {
-                pfn = list_entry(list_ent, struct pfn_info, list) - 
-                    frame_table;
+                pfn = page_to_pfn(list_entry(list_ent, struct pfn_info, list));
                 if ( put_user(pfn, buffer) )
                 {
                     ret = -EFAULT;
                     break;
                 }
                 buffer++;
-                list_ent = frame_table[pfn].list.next;
+                list_ent = pfn_to_page(pfn)->list.next;
             }
             spin_unlock(&d->page_alloc_lock);
 
diff -r 2c75070e41a0 -r 5a790011259e xen/arch/x86/domain.c
--- a/xen/arch/x86/domain.c     Wed Dec 21 16:30:10 2005
+++ b/xen/arch/x86/domain.c     Wed Dec 21 17:56:19 2005
@@ -190,7 +190,7 @@
         list_for_each_entry ( page, &d->page_list, list )
         {
             printk("Page %p: mfn=%p, caf=%08x, taf=%" PRtype_info "\n",
-                   _p(page_to_phys(page)), _p(page - frame_table),
+                   _p(page_to_phys(page)), _p(page_to_pfn(page)),
                    page->count_info, page->u.inuse.type_info);
         }
     }
@@ -198,13 +198,13 @@
     list_for_each_entry ( page, &d->xenpage_list, list )
     {
         printk("XenPage %p: mfn=%p, caf=%08x, taf=%" PRtype_info "\n",
-               _p(page_to_phys(page)), _p(page - frame_table),
+               _p(page_to_phys(page)), _p(page_to_pfn(page)),
                page->count_info, page->u.inuse.type_info);
     }
 
     page = virt_to_page(d->shared_info);
     printk("Shared_info@%p: mfn=%p, caf=%08x, taf=%" PRtype_info "\n",
-           _p(page_to_phys(page)), _p(page - frame_table), page->count_info,
+           _p(page_to_phys(page)), _p(page_to_pfn(page)), page->count_info,
            page->u.inuse.type_info);
 }
 
@@ -391,19 +391,19 @@
 
     if ( shadow_mode_refcounts(d) )
     {
-        if ( !get_page(&frame_table[phys_basetab>>PAGE_SHIFT], d) )
+        if ( !get_page(pfn_to_page(phys_basetab>>PAGE_SHIFT), d) )
             return -EINVAL;
     }
     else if ( !(c->flags & VGCF_VMX_GUEST) )
     {
-        if ( !get_page_and_type(&frame_table[phys_basetab>>PAGE_SHIFT], d,
+        if ( !get_page_and_type(pfn_to_page(phys_basetab>>PAGE_SHIFT), d,
                                 PGT_base_page_table) )
             return -EINVAL;
     }
 
     if ( (rc = (int)set_gdt(v, c->gdt_frames, c->gdt_ents)) != 0 )
     {
-        put_page_and_type(&frame_table[phys_basetab>>PAGE_SHIFT]);
+        put_page_and_type(pfn_to_page(phys_basetab>>PAGE_SHIFT));
         return rc;
     }
 
diff -r 2c75070e41a0 -r 5a790011259e xen/arch/x86/domain_build.c
--- a/xen/arch/x86/domain_build.c       Wed Dec 21 16:30:10 2005
+++ b/xen/arch/x86/domain_build.c       Wed Dec 21 17:56:19 2005
@@ -405,7 +405,7 @@
         *l1tab = l1e_from_pfn(mfn, L1_PROT);
         l1tab++;
         
-        page = &frame_table[mfn];
+        page = pfn_to_page(mfn);
         if ( !get_page_and_type(page, d, PGT_writable_page) )
             BUG();
 
@@ -418,7 +418,7 @@
     l1tab += l1_table_offset(vpt_start);
     for ( count = 0; count < nr_pt_pages; count++ ) 
     {
-        page = &frame_table[l1e_get_pfn(*l1tab)];
+        page = pfn_to_page(l1e_get_pfn(*l1tab));
         if ( !opt_dom0_shadow )
             l1e_remove_flags(*l1tab, _PAGE_RW);
         else
@@ -548,7 +548,7 @@
         *l1tab = l1e_from_pfn(mfn, L1_PROT);
         l1tab++;
 
-        page = &frame_table[mfn];
+        page = pfn_to_page(mfn);
         if ( (page->u.inuse.type_info == 0) &&
              !get_page_and_type(page, d, PGT_writable_page) )
             BUG();
@@ -567,7 +567,7 @@
     for ( count = 0; count < nr_pt_pages; count++ ) 
     {
         l1e_remove_flags(*l1tab, _PAGE_RW);
-        page = &frame_table[l1e_get_pfn(*l1tab)];
+        page = pfn_to_page(l1e_get_pfn(*l1tab));
 
         /* Read-only mapping + PGC_allocated + page-table page. */
         page->count_info         = PGC_allocated | 3;
diff -r 2c75070e41a0 -r 5a790011259e xen/arch/x86/mm.c
--- a/xen/arch/x86/mm.c Wed Dec 21 16:30:10 2005
+++ b/xen/arch/x86/mm.c Wed Dec 21 17:56:19 2005
@@ -202,7 +202,7 @@
     /* First 1MB of RAM is historically marked as I/O. */
     for ( i = 0; i < 0x100; i++ )
     {
-        page = &frame_table[i];
+        page = pfn_to_page(i);
         page->count_info        = PGC_allocated | 1;
         page->u.inuse.type_info = PGT_writable_page | PGT_validated | 1;
         page_set_owner(page, dom_io);
@@ -216,10 +216,10 @@
         /* Every page from cursor to start of next RAM region is I/O. */
         rstart_pfn = PFN_UP(e820.map[i].addr);
         rend_pfn   = PFN_DOWN(e820.map[i].addr + e820.map[i].size);
-        while ( pfn < rstart_pfn )
+        for ( ; pfn < rstart_pfn; pfn++ )
         {
             BUG_ON(!pfn_valid(pfn));
-            page = &frame_table[pfn++];
+            page = pfn_to_page(pfn);
             page->count_info        = PGC_allocated | 1;
             page->u.inuse.type_info = PGT_writable_page | PGT_validated | 1;
             page_set_owner(page, dom_io);
@@ -253,7 +253,7 @@
         pfn = l1e_get_pfn(v->arch.perdomain_ptes[i]);
         if ( pfn == 0 ) continue;
         v->arch.perdomain_ptes[i] = l1e_empty();
-        page = &frame_table[pfn];
+        page = pfn_to_page(pfn);
         ASSERT_PAGE_IS_TYPE(page, PGT_ldt_page);
         ASSERT_PAGE_IS_DOMAIN(page, v->domain);
         put_page_and_type(page);
@@ -320,13 +320,13 @@
     if ( unlikely(!VALID_MFN(gmfn)) )
         return 0;
 
-    res = get_page_and_type(&frame_table[gmfn], d, PGT_ldt_page);
+    res = get_page_and_type(pfn_to_page(gmfn), d, PGT_ldt_page);
 
     if ( !res && unlikely(shadow_mode_refcounts(d)) )
     {
         shadow_lock(d);
         shadow_remove_all_write_access(d, gpfn, gmfn);
-        res = get_page_and_type(&frame_table[gmfn], d, PGT_ldt_page);
+        res = get_page_and_type(pfn_to_page(gmfn), d, PGT_ldt_page);
         shadow_unlock(d);
     }
 
@@ -344,7 +344,7 @@
 
 static int get_page_from_pagenr(unsigned long page_nr, struct domain *d)
 {
-    struct pfn_info *page = &frame_table[page_nr];
+    struct pfn_info *page = pfn_to_page(page_nr);
 
     if ( unlikely(!pfn_valid(page_nr)) || unlikely(!get_page(page, d)) )
     {
@@ -360,7 +360,7 @@
                                          unsigned long type,
                                          struct domain *d)
 {
-    struct pfn_info *page = &frame_table[page_nr];
+    struct pfn_info *page = pfn_to_page(page_nr);
 
     if ( unlikely(!get_page_from_pagenr(page_nr, d)) )
         return 0;
@@ -412,7 +412,7 @@
          * Make sure that the mapped frame is an already-validated L2 table. 
          * If so, atomically increment the count (checking for overflow).
          */
-        page = &frame_table[pfn];
+        page = pfn_to_page(pfn);
         y = page->u.inuse.type_info;
         do {
             x = y;
@@ -435,7 +435,7 @@
     l1_pgentry_t l1e, struct domain *d)
 {
     unsigned long mfn = l1e_get_pfn(l1e);
-    struct pfn_info *page = &frame_table[mfn];
+    struct pfn_info *page = pfn_to_page(mfn);
     int okay;
     extern int domain_iomem_in_pfn(struct domain *d, unsigned long pfn);
 
@@ -587,7 +587,7 @@
 void put_page_from_l1e(l1_pgentry_t l1e, struct domain *d)
 {
     unsigned long    pfn  = l1e_get_pfn(l1e);
-    struct pfn_info *page = &frame_table[pfn];
+    struct pfn_info *page = pfn_to_page(pfn);
     struct domain   *e;
     struct vcpu     *v;
 
@@ -645,7 +645,7 @@
 {
     if ( (l2e_get_flags(l2e) & _PAGE_PRESENT) && 
          (l2e_get_pfn(l2e) != pfn) )
-        put_page_and_type(&frame_table[l2e_get_pfn(l2e)]);
+        put_page_and_type(pfn_to_page(l2e_get_pfn(l2e)));
 }
 
 
@@ -655,7 +655,7 @@
 {
     if ( (l3e_get_flags(l3e) & _PAGE_PRESENT) && 
          (l3e_get_pfn(l3e) != pfn) )
-        put_page_and_type(&frame_table[l3e_get_pfn(l3e)]);
+        put_page_and_type(pfn_to_page(l3e_get_pfn(l3e)));
 }
 
 #endif
@@ -666,7 +666,7 @@
 {
     if ( (l4e_get_flags(l4e) & _PAGE_PRESENT) && 
          (l4e_get_pfn(l4e) != pfn) )
-        put_page_and_type(&frame_table[l4e_get_pfn(l4e)]);
+        put_page_and_type(pfn_to_page(l4e_get_pfn(l4e)));
 }
 
 #endif
@@ -1584,9 +1584,9 @@
         write_ptbase(v);
 
         if ( shadow_mode_refcounts(d) )
-            put_page(&frame_table[old_base_mfn]);
+            put_page(pfn_to_page(old_base_mfn));
         else
-            put_page_and_type(&frame_table[old_base_mfn]);
+            put_page_and_type(pfn_to_page(old_base_mfn));
 
         /* CR3 also holds a ref to its shadow... */
         if ( shadow_mode_enabled(d) )
@@ -1595,7 +1595,7 @@
                 put_shadow_ref(v->arch.monitor_shadow_ref);
             v->arch.monitor_shadow_ref =
                 pagetable_get_pfn(v->arch.monitor_table);
-            ASSERT(!page_get_owner(&frame_table[v->arch.monitor_shadow_ref]));
+            ASSERT(!page_get_owner(pfn_to_page(v->arch.monitor_shadow_ref)));
             get_shadow_ref(v->arch.monitor_shadow_ref);
         }
     }
@@ -1763,7 +1763,7 @@
 
         okay = 1;
         mfn  = op.arg1.mfn;
-        page = &frame_table[mfn];
+        page = pfn_to_page(mfn);
 
         switch ( op.cmd )
         {
@@ -1845,7 +1845,7 @@
                     pagetable_get_pfn(v->arch.guest_table_user);
                 v->arch.guest_table_user = mk_pagetable(mfn << PAGE_SHIFT);
                 if ( old_mfn != 0 )
-                    put_page_and_type(&frame_table[old_mfn]);
+                    put_page_and_type(pfn_to_page(old_mfn));
             }
             break;
 #endif
@@ -2145,7 +2145,7 @@
             va = map_domain_page_with_cache(mfn, &mapcache);
             va = (void *)((unsigned long)va +
                           (unsigned long)(req.ptr & ~PAGE_MASK));
-            page = &frame_table[mfn];
+            page = pfn_to_page(mfn);
 
             switch ( (type_info = page->u.inuse.type_info) & PGT_type_mask )
             {
@@ -2285,7 +2285,7 @@
 
             mark_dirty(FOREIGNDOM, mfn);
 
-            put_page(&frame_table[mfn]);
+            put_page(pfn_to_page(mfn));
             break;
 
         default:
@@ -2728,7 +2728,7 @@
     for ( i = 0; i < FIRST_RESERVED_GDT_PAGE; i++ )
     {
         if ( (pfn = l1e_get_pfn(v->arch.perdomain_ptes[i])) != 0 )
-            put_page_and_type(&frame_table[pfn]);
+            put_page_and_type(pfn_to_page(pfn));
         v->arch.perdomain_ptes[i] = l1e_empty();
         v->arch.guest_context.gdt_frames[i] = 0;
     }
@@ -2753,7 +2753,7 @@
     for ( i = 0; i < nr_pages; i++ ) {
         pfn = frames[i];
         if ((pfn >= max_page) ||
-            !get_page_and_type(&frame_table[pfn], d, PGT_gdt_page) )
+            !get_page_and_type(pfn_to_page(pfn), d, PGT_gdt_page) )
             goto fail;
     }
 
@@ -2773,7 +2773,7 @@
 
  fail:
     while ( i-- > 0 )
-        put_page_and_type(&frame_table[frames[i]]);
+        put_page_and_type(pfn_to_page(frames[i]));
     return -EINVAL;
 }
 
@@ -2827,7 +2827,7 @@
         return -EINVAL;
     }
 
-    page = &frame_table[mfn];
+    page = pfn_to_page(mfn);
     if ( unlikely(!get_page(page, dom)) )
     {
         UNLOCK_BIGLOCK(dom);
@@ -3037,7 +3037,7 @@
         if ( likely(l1e_get_intpte(ol1e) == (l1e_get_intpte(nl1e)|_PAGE_RW)) )
         {
             if ( likely(l1e_get_flags(nl1e) & _PAGE_PRESENT) )
-                put_page_type(&frame_table[l1e_get_pfn(nl1e)]);
+                put_page_type(pfn_to_page(l1e_get_pfn(nl1e)));
             continue;
         }
 
@@ -3220,7 +3220,7 @@
     }
 
     pfn  = l1e_get_pfn(pte);
-    page = &frame_table[pfn];
+    page = pfn_to_page(pfn);
 
     /* We are looking only for read-only mappings of p.t. pages. */
     if ( ((l1e_get_flags(pte) & (_PAGE_RW|_PAGE_PRESENT)) != _PAGE_PRESENT) ||
@@ -3331,7 +3331,7 @@
     }
 
     pfn  = l1e_get_pfn(pte);
-    page = &frame_table[pfn];
+    page = pfn_to_page(pfn);
 
 #ifdef CONFIG_X86_64
 #define WRPT_PTE_FLAGS (_PAGE_RW | _PAGE_PRESENT | _PAGE_USER)
diff -r 2c75070e41a0 -r 5a790011259e xen/arch/x86/setup.c
--- a/xen/arch/x86/setup.c      Wed Dec 21 16:30:10 2005
+++ b/xen/arch/x86/setup.c      Wed Dec 21 17:56:19 2005
@@ -264,7 +264,7 @@
     unsigned long _initrd_start = 0, _initrd_len = 0;
     unsigned int initrdidx = 1;
     physaddr_t s, e;
-    int i, e820_raw_nr = 0, bytes = 0;
+    int i, e820_warn = 0, e820_raw_nr = 0, bytes = 0;
     struct ns16550_defaults ns16550 = {
         .data_bits = 8,
         .parity    = 'n',
@@ -313,6 +313,22 @@
         while ( bytes < mbi->mmap_length )
         {
             memory_map_t *map = __va(mbi->mmap_addr + bytes);
+
+            /*
+             * This is a gross workaround for a BIOS bug. Some bootloaders do
+             * not write e820 map entries into pre-zeroed memory. This is
+             * okay if the BIOS fills in all fields of the map entry, but
+             * some broken BIOSes do not bother to write the high word of
+             * the length field if the length is smaller than 4GB. We
+             * detect and fix this by flagging sections below 4GB that
+             * appear to be larger than 4GB in size.
+             */
+            if ( (map->base_addr_high == 0) && (map->length_high != 0) )
+            {
+                e820_warn = 1;
+                map->length_high = 0;
+            }
+
             e820_raw[e820_raw_nr].addr = 
                 ((u64)map->base_addr_high << 32) | (u64)map->base_addr_low;
             e820_raw[e820_raw_nr].size = 
@@ -320,6 +336,7 @@
             e820_raw[e820_raw_nr].type = 
                 (map->type > E820_SHARED_PAGE) ? E820_RESERVED : map->type;
             e820_raw_nr++;
+
             bytes += map->size + 4;
         }
     }
@@ -338,6 +355,10 @@
         printk("FATAL ERROR: Bootloader provided no memory information.\n");
         for ( ; ; ) ;
     }
+
+    if ( e820_warn )
+        printk("WARNING: Buggy e820 map detected and fixed "
+               "(truncated length fields).\n");
 
     max_page = init_e820(e820_raw, &e820_raw_nr);
 
diff -r 2c75070e41a0 -r 5a790011259e xen/arch/x86/shadow.c
--- a/xen/arch/x86/shadow.c     Wed Dec 21 16:30:10 2005
+++ b/xen/arch/x86/shadow.c     Wed Dec 21 17:56:19 2005
@@ -504,7 +504,7 @@
             l2e_from_pfn(smfn, __PAGE_HYPERVISOR);
 
         spl2e[l2_table_offset(PERDOMAIN_VIRT_START)] =
-            
l2e_from_paddr(__pa(page_get_owner(&frame_table[gmfn])->arch.mm_perdomain_pt),
+            
l2e_from_paddr(__pa(page_get_owner(pfn_to_page(gmfn))->arch.mm_perdomain_pt),
                             __PAGE_HYPERVISOR);
 
         if ( shadow_mode_translate(d) ) // NB: not external
@@ -670,7 +670,7 @@
             set_guest_back_ptr(d, sl1e, sl1mfn, i);
         }
 
-        frame_table[sl1mfn].tlbflush_timestamp =
+        pfn_to_page(sl1mfn)->tlbflush_timestamp =
             SHADOW_ENCODE_MIN_MAX(min, max);
 
         unmap_domain_page(gpl1e);
@@ -907,7 +907,7 @@
     u32 min_max = 0;
     int min, max, length;
 
-    if ( test_and_set_bit(_PGC_out_of_sync, &frame_table[gmfn].count_info) )
+    if ( test_and_set_bit(_PGC_out_of_sync, &pfn_to_page(gmfn)->count_info) )
     {
         ASSERT(__shadow_status(d, gpfn, PGT_snapshot));
         return SHADOW_SNAPSHOT_ELSEWHERE;
@@ -953,7 +953,7 @@
                              unsigned long mfn)
 {
     struct domain *d = v->domain;
-    struct pfn_info *page = &frame_table[mfn];
+    struct pfn_info *page = pfn_to_page(mfn);
     struct out_of_sync_entry *entry = shadow_alloc_oos_entry(d);
 
     ASSERT(shadow_lock_is_acquired(d));
@@ -1174,7 +1174,7 @@
                 && i == PAGING_L4)
                 continue;       /* skip the top-level for 3-level */
 
-            if ( page_out_of_sync(&frame_table[gmfn]) &&
+            if ( page_out_of_sync(pfn_to_page(gmfn)) &&
                  !snapshot_entry_matches(
                      d, guest_pt, gpfn, table_offset_64(va, i)) )
             {
@@ -1200,7 +1200,7 @@
         }
 
         /* L2 */
-        if ( page_out_of_sync(&frame_table[gmfn]) &&
+        if ( page_out_of_sync(pfn_to_page(gmfn)) &&
              !snapshot_entry_matches(d, guest_pt, gpfn, l2_table_offset(va)) )
         {
             unmap_and_return (1);
@@ -1214,7 +1214,7 @@
 #undef unmap_and_return
 #endif /* CONFIG_PAGING_LEVELS >= 3 */
     {
-        if ( page_out_of_sync(&frame_table[l2mfn]) &&
+        if ( page_out_of_sync(pfn_to_page(l2mfn)) &&
              !snapshot_entry_matches(d, (guest_l1_pgentry_t 
*)v->arch.guest_vtable,
                                      l2pfn, guest_l2_table_offset(va)) )
             return 1;
@@ -1234,7 +1234,7 @@
 
     guest_pt = (guest_l1_pgentry_t *) map_domain_page(l1mfn);
 
-    if ( page_out_of_sync(&frame_table[l1mfn]) &&
+    if ( page_out_of_sync(pfn_to_page(l1mfn)) &&
          !snapshot_entry_matches(
              d, guest_pt, l1pfn, guest_l1_table_offset(va)) ) 
     {
@@ -1324,18 +1324,18 @@
     int i;
     u32 found = 0;
     int is_l1_shadow =
-        ((frame_table[pt_mfn].u.inuse.type_info & PGT_type_mask) ==
+        ((pfn_to_page(pt_mfn)->u.inuse.type_info & PGT_type_mask) ==
          PGT_l1_shadow);
 #if CONFIG_PAGING_LEVELS == 4
     is_l1_shadow |=
-      ((frame_table[pt_mfn].u.inuse.type_info & PGT_type_mask) ==
+      ((pfn_to_page(pt_mfn)->u.inuse.type_info & PGT_type_mask) ==
                 PGT_fl1_shadow);
 #endif
 
     match = l1e_from_pfn(readonly_gmfn, flags);
 
     if ( shadow_mode_external(d) ) {
-        i = (frame_table[readonly_gmfn].u.inuse.type_info & PGT_va_mask)
+        i = (pfn_to_page(readonly_gmfn)->u.inuse.type_info & PGT_va_mask)
             >> PGT_va_shift;
 
         if ( (i >= 0 && i < L1_PAGETABLE_ENTRIES) &&
@@ -1373,7 +1373,7 @@
 
     // If it's not a writable page, then no writable refs can be outstanding.
     //
-    if ( (frame_table[readonly_gmfn].u.inuse.type_info & PGT_type_mask) !=
+    if ( (pfn_to_page(readonly_gmfn)->u.inuse.type_info & PGT_type_mask) !=
          PGT_writable_page )
     {
         perfc_incrc(remove_write_not_writable);
@@ -1383,7 +1383,7 @@
     // How many outstanding writable PTEs for this page are there?
     //
     write_refs =
-        (frame_table[readonly_gmfn].u.inuse.type_info & PGT_count_mask);
+        (pfn_to_page(readonly_gmfn)->u.inuse.type_info & PGT_count_mask);
     if ( write_refs && MFN_PINNED(readonly_gmfn) )
     {
         write_refs--;
@@ -1401,7 +1401,7 @@
 
          // Use the back pointer to locate the shadow page that can contain
          // the PTE of interest
-         if ( (predicted_smfn = frame_table[readonly_gmfn].tlbflush_timestamp) 
) {
+         if ( (predicted_smfn = 
pfn_to_page(readonly_gmfn)->tlbflush_timestamp) ) {
              found += remove_all_write_access_in_ptpage(
                  d, predicted_smfn, predicted_smfn, readonly_gpfn, 
readonly_gmfn, write_refs, 0);
              if ( found == write_refs )
@@ -1670,7 +1670,7 @@
                     if ( !(entry_get_flags(guest_pt[i]) & _PAGE_PRESENT) &&
                          unlikely(entry_get_value(guest_pt[i]) != 0) &&
                          !unshadow &&
-                         (frame_table[smfn].u.inuse.type_info & PGT_pinned) )
+                         (pfn_to_page(smfn)->u.inuse.type_info & PGT_pinned) )
                         unshadow = 1;
                 }
 #endif
@@ -1718,7 +1718,7 @@
                 if ( !(guest_root_get_flags(new_root_e) & _PAGE_PRESENT) &&
                      unlikely(guest_root_get_intpte(new_root_e) != 0) &&
                      !unshadow &&
-                     (frame_table[smfn].u.inuse.type_info & PGT_pinned) )
+                     (pfn_to_page(smfn)->u.inuse.type_info & PGT_pinned) )
                     unshadow = 1;
             }
             if ( max == -1 )
@@ -2401,7 +2401,7 @@
     {
         printk("eff_guest_pfn=%lx eff_guest_mfn=%lx shadow_mfn=%lx t=0x%08lx 
page_table_page=%d\n",
                eff_guest_pfn, eff_guest_mfn, shadow_mfn,
-               frame_table[eff_guest_mfn].u.inuse.type_info,
+               pfn_to_page(eff_guest_mfn)->u.inuse.type_info,
                page_table_page);
         FAIL("RW coherence");
     }
@@ -2412,7 +2412,7 @@
     {
         printk("eff_guest_pfn=%lx eff_guest_mfn=%lx shadow_mfn=%lx t=0x%08lx 
page_table_page=%d\n",
                eff_guest_pfn, eff_guest_mfn, shadow_mfn,
-               frame_table[eff_guest_mfn].u.inuse.type_info,
+               pfn_to_page(eff_guest_mfn)->u.inuse.type_info,
                page_table_page);
         FAIL("RW2 coherence");
     }
@@ -2781,7 +2781,7 @@
          * When we free L2 pages, we need to tell if the page contains
          * Xen private mappings. Use the va_mask part.
          */
-        frame_table[s2mfn].u.inuse.type_info |= 
+        pfn_to_page(s2mfn)->u.inuse.type_info |= 
             (unsigned long) 3 << PGT_score_shift; 
 
         memset(spl2e, 0, 
@@ -2794,7 +2794,7 @@
         for ( i = 0; i < PDPT_L2_ENTRIES; i++ )
             spl2e[l2_table_offset(PERDOMAIN_VIRT_START) + i] =
                 l2e_from_page(
-                    
virt_to_page(page_get_owner(&frame_table[gmfn])->arch.mm_perdomain_pt) + i, 
+                    
virt_to_page(page_get_owner(pfn_to_page(gmfn))->arch.mm_perdomain_pt) + i, 
                     __PAGE_HYPERVISOR);
         for ( i = 0; i < (LINEARPT_MBYTES >> (L2_PAGETABLE_SHIFT - 20)); i++ )
             spl2e[l2_table_offset(LINEAR_PT_VIRT_START) + i] =
@@ -2896,7 +2896,7 @@
            ROOT_PAGETABLE_XEN_SLOTS * sizeof(l4_pgentry_t));
 
         spl4e[l4_table_offset(PERDOMAIN_VIRT_START)] =
-            
l4e_from_paddr(__pa(page_get_owner(&frame_table[gmfn])->arch.mm_perdomain_l3),
+            
l4e_from_paddr(__pa(page_get_owner(pfn_to_page(gmfn))->arch.mm_perdomain_l3),
                             __PAGE_HYPERVISOR);
 
         if ( shadow_mode_translate(d) ) // NB: not external
diff -r 2c75070e41a0 -r 5a790011259e xen/arch/x86/shadow32.c
--- a/xen/arch/x86/shadow32.c   Wed Dec 21 16:30:10 2005
+++ b/xen/arch/x86/shadow32.c   Wed Dec 21 17:56:19 2005
@@ -30,7 +30,7 @@
 #include <xen/sched.h>
 #include <xen/trace.h>
 
-#define MFN_PINNED(_x) (frame_table[_x].u.inuse.type_info & PGT_pinned)
+#define MFN_PINNED(_x) (pfn_to_page(_x)->u.inuse.type_info & PGT_pinned)
 #define va_to_l1mfn(_ed, _va) \
     (l2e_get_pfn(linear_l2_table(_ed)[_va>>L2_PAGETABLE_SHIFT]))
 
@@ -144,11 +144,11 @@
     if ( !shadow_mode_refcounts(d) )
         return;
 
-    ASSERT(frame_table[gmfn].count_info & PGC_page_table);
+    ASSERT(pfn_to_page(gmfn)->count_info & PGC_page_table);
 
     if ( shadow_max_pgtable_type(d, gpfn, NULL) == PGT_none )
     {
-        clear_bit(_PGC_page_table, &frame_table[gmfn].count_info);
+        clear_bit(_PGC_page_table, &pfn_to_page(gmfn)->count_info);
 
         if ( page_out_of_sync(pfn_to_page(gmfn)) )
         {
@@ -380,7 +380,7 @@
 
 void free_shadow_page(unsigned long smfn)
 {
-    struct pfn_info *page = &frame_table[smfn];
+    struct pfn_info *page = pfn_to_page(smfn);
     unsigned long gmfn = page->u.inuse.type_info & PGT_mfn_mask;
     struct domain *d = page_get_owner(pfn_to_page(gmfn));
     unsigned long gpfn = __mfn_to_gpfn(d, gmfn);
@@ -465,8 +465,8 @@
 {
     struct pfn_info *page;
 
-    page = &frame_table[entry->gmfn];
-        
+    page = pfn_to_page(entry->gmfn);
+
     // Decrement ref count of guest & shadow pages
     //
     put_page(page);
@@ -795,7 +795,7 @@
      */
     mfn = pagetable_get_pfn(v->arch.monitor_table);
     unmap_domain_page(v->arch.monitor_vtable);
-    free_domheap_page(&frame_table[mfn]);
+    free_domheap_page(pfn_to_page(mfn));
 
     v->arch.monitor_table = mk_pagetable(0);
     v->arch.monitor_vtable = 0;
@@ -1018,8 +1018,8 @@
         {
             // external guests provide their own memory for their P2M maps.
             //
-            ASSERT( d == page_get_owner(
-                        &frame_table[pagetable_get_pfn(d->arch.phys_table)]) );
+            ASSERT(d == page_get_owner(pfn_to_page(pagetable_get_pfn(
+                d->arch.phys_table))));
         }
     }
 
@@ -1543,7 +1543,7 @@
             l2e_from_pfn(smfn, __PAGE_HYPERVISOR);
 
         spl2e[l2_table_offset(PERDOMAIN_VIRT_START)] =
-            
l2e_from_paddr(__pa(page_get_owner(&frame_table[gmfn])->arch.mm_perdomain_pt),
+            
l2e_from_paddr(__pa(page_get_owner(pfn_to_page(gmfn))->arch.mm_perdomain_pt),
                             __PAGE_HYPERVISOR);
 
         if ( shadow_mode_translate(d) ) // NB: not external
@@ -1675,7 +1675,7 @@
             set_guest_back_ptr(d, sl1e, sl1mfn, i);
         }
 
-        frame_table[sl1mfn].tlbflush_timestamp =
+        pfn_to_page(sl1mfn)->tlbflush_timestamp =
             SHADOW_ENCODE_MIN_MAX(min, max);
     }
 }
@@ -1758,7 +1758,7 @@
     u32 min_max = 0;
     int min, max, length;
 
-    if ( test_and_set_bit(_PGC_out_of_sync, &frame_table[gmfn].count_info) )
+    if ( test_and_set_bit(_PGC_out_of_sync, &pfn_to_page(gmfn)->count_info) )
     {
         ASSERT(__shadow_status(d, gpfn, PGT_snapshot));
         return SHADOW_SNAPSHOT_ELSEWHERE;
@@ -1809,7 +1809,7 @@
 
     // Clear the out_of_sync bit.
     //
-    clear_bit(_PGC_out_of_sync, &frame_table[entry->gmfn].count_info);
+    clear_bit(_PGC_out_of_sync, &pfn_to_page(entry->gmfn)->count_info);
 
     // XXX Need to think about how to protect the domain's
     // information less expensively.
@@ -1826,7 +1826,7 @@
                              unsigned long mfn)
 {
     struct domain *d = v->domain;
-    struct pfn_info *page = &frame_table[mfn];
+    struct pfn_info *page = pfn_to_page(mfn);
     struct out_of_sync_entry *entry = shadow_alloc_oos_entry(d);
 
     ASSERT(shadow_lock_is_acquired(d));
@@ -1992,7 +1992,7 @@
 
     perfc_incrc(shadow_out_of_sync_calls);
 
-    if ( page_out_of_sync(&frame_table[l2mfn]) &&
+    if ( page_out_of_sync(pfn_to_page(l2mfn)) &&
          !snapshot_entry_matches(d, (l1_pgentry_t *)v->arch.guest_vtable,
                                  l2pfn, l2_table_offset(va)) )
         return 1;
@@ -2008,7 +2008,7 @@
     if ( !VALID_MFN(l1mfn) )
         return 0;
 
-    if ( page_out_of_sync(&frame_table[l1mfn]) &&
+    if ( page_out_of_sync(pfn_to_page(l1mfn)) &&
          !snapshot_entry_matches(
              d, &linear_pg_table[l1_linear_offset(va) & 
~(L1_PAGETABLE_ENTRIES-1)],
              l1pfn, l1_table_offset(va)) )
@@ -2136,13 +2136,13 @@
     int i;
     u32 found = 0;
     int is_l1_shadow =
-        ((frame_table[pt_mfn].u.inuse.type_info & PGT_type_mask) ==
+        ((pfn_to_page(pt_mfn)->u.inuse.type_info & PGT_type_mask) ==
          PGT_l1_shadow);
 
     match = l1e_from_pfn(readonly_gmfn, flags);
 
     if ( shadow_mode_external(d) ) {
-        i = (frame_table[readonly_gmfn].u.inuse.type_info & PGT_va_mask) 
+        i = (pfn_to_page(readonly_gmfn)->u.inuse.type_info & PGT_va_mask) 
             >> PGT_va_shift;
 
         if ( (i >= 0 && i < L1_PAGETABLE_ENTRIES) &&
@@ -2180,7 +2180,7 @@
 
     // If it's not a writable page, then no writable refs can be outstanding.
     //
-    if ( (frame_table[readonly_gmfn].u.inuse.type_info & PGT_type_mask) !=
+    if ( (pfn_to_page(readonly_gmfn)->u.inuse.type_info & PGT_type_mask) !=
          PGT_writable_page )
     {
         perfc_incrc(remove_write_not_writable);
@@ -2190,7 +2190,7 @@
     // How many outstanding writable PTEs for this page are there?
     //
     write_refs =
-        (frame_table[readonly_gmfn].u.inuse.type_info & PGT_count_mask);
+        (pfn_to_page(readonly_gmfn)->u.inuse.type_info & PGT_count_mask);
     if ( write_refs && MFN_PINNED(readonly_gmfn) )
     {
         write_refs--;
@@ -2208,7 +2208,7 @@
 
          // Use the back pointer to locate the shadow page that can contain
          // the PTE of interest
-         if ( (predicted_smfn = frame_table[readonly_gmfn].tlbflush_timestamp) 
) {
+         if ( (predicted_smfn = 
pfn_to_page(readonly_gmfn)->tlbflush_timestamp) ) {
              found += remove_all_write_access_in_ptpage(
                  d, predicted_smfn, predicted_smfn, readonly_gpfn, 
readonly_gmfn, write_refs, 0);
              if ( found == write_refs )
@@ -2249,7 +2249,7 @@
     int i;
     u32 count = 0;
     int is_l1_shadow =
-        ((frame_table[l1mfn].u.inuse.type_info & PGT_type_mask) ==
+        ((pfn_to_page(l1mfn)->u.inuse.type_info & PGT_type_mask) ==
          PGT_l1_shadow);
 
     match = l1e_from_pfn(forbidden_gmfn, flags);
@@ -2266,7 +2266,7 @@
         if ( is_l1_shadow )
             shadow_put_page_from_l1e(ol2e, d);
         else /* must be an hl2 page */
-            put_page(&frame_table[forbidden_gmfn]);
+            put_page(pfn_to_page(forbidden_gmfn));
     }
 
     unmap_domain_page(pl1e);
@@ -2982,6 +2982,23 @@
     }
 }
 
+void clear_all_shadow_status(struct domain *d)
+{
+    shadow_lock(d);
+    free_shadow_pages(d);
+    free_shadow_ht_entries(d);
+    d->arch.shadow_ht = 
+        xmalloc_array(struct shadow_status, shadow_ht_buckets);
+    if ( d->arch.shadow_ht == NULL ) {
+        printk("clear all shadow status:xmalloc fail\n");
+        domain_crash_synchronous();
+    }
+    memset(d->arch.shadow_ht, 0,
+           shadow_ht_buckets * sizeof(struct shadow_status));
+
+    free_out_of_sync_entries(d);
+    shadow_unlock(d);
+}
 
 /************************************************************************/
 /************************************************************************/
@@ -3139,7 +3156,7 @@
     {
         printk("eff_guest_pfn=%lx eff_guest_mfn=%lx shadow_mfn=%lx t=%lx 
page_table_page=%d\n",
                eff_guest_pfn, eff_guest_mfn, shadow_mfn,
-               frame_table[eff_guest_mfn].u.inuse.type_info,
+               pfn_to_page(eff_guest_mfn)->u.inuse.type_info,
                page_table_page);
         FAIL("RW coherence");
     }
@@ -3150,7 +3167,7 @@
     {
         printk("eff_guest_pfn=%lx eff_guest_mfn=%lx shadow_mfn=%lx t=%lx 
page_table_page=%d\n",
                eff_guest_pfn, eff_guest_mfn, shadow_mfn,
-               frame_table[eff_guest_mfn].u.inuse.type_info,
+               pfn_to_page(eff_guest_mfn)->u.inuse.type_info,
                page_table_page);
         FAIL("RW2 coherence");
     }
diff -r 2c75070e41a0 -r 5a790011259e xen/arch/x86/shadow_public.c
--- a/xen/arch/x86/shadow_public.c      Wed Dec 21 16:30:10 2005
+++ b/xen/arch/x86/shadow_public.c      Wed Dec 21 17:56:19 2005
@@ -168,14 +168,14 @@
 #if CONFIG_PAGING_LEVELS >=3
     if ( d->arch.ops->guest_paging_levels == PAGING_L2 )
     {
-        struct pfn_info *page = &frame_table[smfn];
+        struct pfn_info *page = pfn_to_page(smfn);
         for ( i = 0; i < PDP_ENTRIES; i++ )
         {
             if ( entry_get_flags(ple[i]) & _PAGE_PRESENT )
                 free_fake_shadow_l2(d,entry_get_pfn(ple[i]));
         }
 
-        page = &frame_table[entry_get_pfn(ple[0])];
+        page = pfn_to_page(entry_get_pfn(ple[0]));
         free_domheap_pages(page, SL2_ORDER);
         unmap_domain_page(ple);
     }
@@ -208,7 +208,7 @@
                     break;
                 if ( level == PAGING_L2 )
                 {
-                    struct pfn_info *page = &frame_table[smfn]; 
+                    struct pfn_info *page = pfn_to_page(smfn);
                     if ( is_xen_l2_slot(page->u.inuse.type_info, i) )
                         continue;
                 }
@@ -299,7 +299,7 @@
      */
     mfn = pagetable_get_pfn(v->arch.monitor_table);
     unmap_domain_page(v->arch.monitor_vtable);
-    free_domheap_page(&frame_table[mfn]);
+    free_domheap_page(pfn_to_page(mfn));
 
     v->arch.monitor_table = mk_pagetable(0);
     v->arch.monitor_vtable = 0;
@@ -394,7 +394,7 @@
      */
     mfn = pagetable_get_pfn(v->arch.monitor_table);
     unmap_domain_page(v->arch.monitor_vtable);
-    free_domheap_page(&frame_table[mfn]);
+    free_domheap_page(pfn_to_page(mfn));
 
     v->arch.monitor_table = mk_pagetable(0);
     v->arch.monitor_vtable = 0;
@@ -411,7 +411,7 @@
 
     // Clear the out_of_sync bit.
     //
-    clear_bit(_PGC_out_of_sync, &frame_table[entry->gmfn].count_info);
+    clear_bit(_PGC_out_of_sync, &pfn_to_page(entry->gmfn)->count_info);
 
     // XXX Need to think about how to protect the domain's
     // information less expensively.
@@ -428,7 +428,7 @@
 {
     struct pfn_info *page;
 
-    page = &frame_table[entry->gmfn];
+    page = pfn_to_page(entry->gmfn);
         
     // Decrement ref count of guest & shadow pages
     //
@@ -501,11 +501,11 @@
     if ( !shadow_mode_refcounts(d) )
         return;
 
-    ASSERT(frame_table[gmfn].count_info & PGC_page_table);
+    ASSERT(pfn_to_page(gmfn)->count_info & PGC_page_table);
 
     if ( shadow_max_pgtable_type(d, gpfn, NULL) == PGT_none )
     {
-        clear_bit(_PGC_page_table, &frame_table[gmfn].count_info);
+        clear_bit(_PGC_page_table, &pfn_to_page(gmfn)->count_info);
 
         if ( page_out_of_sync(pfn_to_page(gmfn)) )
         {
@@ -600,7 +600,7 @@
 
 void free_shadow_page(unsigned long smfn)
 {
-    struct pfn_info *page = &frame_table[smfn];
+    struct pfn_info *page = pfn_to_page(smfn);
 
     unsigned long gmfn = page->u.inuse.type_info & PGT_mfn_mask;
     struct domain *d = page_get_owner(pfn_to_page(gmfn));
@@ -1067,8 +1067,8 @@
         {
             // external guests provide their own memory for their P2M maps.
             //
-            ASSERT( d == page_get_owner(
-                &frame_table[pagetable_get_pfn(d->arch.phys_table)]) );
+            ASSERT(d == page_get_owner(pfn_to_page(pagetable_get_pfn(
+                d->arch.phys_table))));
         }
     }
 
@@ -1643,7 +1643,7 @@
     int i;
     u32 count = 0;
     int is_l1_shadow =
-        ((frame_table[l1mfn].u.inuse.type_info & PGT_type_mask) ==
+        ((pfn_to_page(l1mfn)->u.inuse.type_info & PGT_type_mask) ==
          PGT_l1_shadow);
 
     match = l1e_from_pfn(forbidden_gmfn, flags);
@@ -1660,7 +1660,7 @@
         if ( is_l1_shadow )
             shadow_put_page_from_l1e(ol2e, d);
         else /* must be an hl2 page */
-            put_page(&frame_table[forbidden_gmfn]);
+            put_page(pfn_to_page(forbidden_gmfn));
     }
 
     unmap_domain_page(pl1e);
@@ -1747,6 +1747,24 @@
     shadow_unlock(d);
 }
 
+void clear_all_shadow_status(struct domain *d)
+{
+    shadow_lock(d);
+    free_shadow_pages(d);
+    free_shadow_ht_entries(d);
+    d->arch.shadow_ht = 
+        xmalloc_array(struct shadow_status, shadow_ht_buckets);
+    if ( d->arch.shadow_ht == NULL ) {
+        printk("clear all shadow status:xmalloc fail\n");
+        domain_crash_synchronous();
+    }
+    memset(d->arch.shadow_ht, 0,
+           shadow_ht_buckets * sizeof(struct shadow_status));
+
+    free_out_of_sync_entries(d);
+    shadow_unlock(d);
+}
+
 /*
  * Local variables:
  * mode: C
diff -r 2c75070e41a0 -r 5a790011259e xen/arch/x86/traps.c
--- a/xen/arch/x86/traps.c      Wed Dec 21 16:30:10 2005
+++ b/xen/arch/x86/traps.c      Wed Dec 21 17:56:19 2005
@@ -1074,29 +1074,35 @@
     return 0;
 }
 
-unsigned long nmi_softirq_reason;
-static void nmi_softirq(void)
+
+/* Defer dom0 notification to softirq context (unsafe in NMI context). */
+static unsigned long nmi_dom0_softirq_reason;
+#define NMI_DOM0_PARITY_ERR 0
+#define NMI_DOM0_IO_ERR     1
+#define NMI_DOM0_UNKNOWN    2
+
+static void nmi_dom0_softirq(void)
 {
     if ( dom0 == NULL )
         return;
 
-    if ( test_and_clear_bit(0, &nmi_softirq_reason) )
+    if ( test_and_clear_bit(NMI_DOM0_PARITY_ERR, &nmi_dom0_softirq_reason) )
         send_guest_virq(dom0->vcpu[0], VIRQ_PARITY_ERR);
 
-    if ( test_and_clear_bit(1, &nmi_softirq_reason) )
+    if ( test_and_clear_bit(NMI_DOM0_IO_ERR, &nmi_dom0_softirq_reason) )
         send_guest_virq(dom0->vcpu[0], VIRQ_IO_ERR);
+
+    if ( test_and_clear_bit(NMI_DOM0_UNKNOWN, &nmi_dom0_softirq_reason) )
+        send_guest_virq(dom0->vcpu[0], VIRQ_NMI);
 }
 
 asmlinkage void mem_parity_error(struct cpu_user_regs *regs)
 {
-    /* Clear and disable the parity-error line. */
-    outb((inb(0x61)&15)|4,0x61);
-
     switch ( opt_nmi[0] )
     {
     case 'd': /* 'dom0' */
-        set_bit(0, &nmi_softirq_reason);
-        raise_softirq(NMI_SOFTIRQ);
+        set_bit(NMI_DOM0_PARITY_ERR, &nmi_dom0_softirq_reason);
+        raise_softirq(NMI_DOM0_SOFTIRQ);
     case 'i': /* 'ignore' */
         break;
     default:  /* 'fatal' */
@@ -1104,18 +1110,19 @@
         printk("\n\nNMI - MEMORY ERROR\n");
         fatal_trap(TRAP_nmi, regs);
     }
+
+    outb((inb(0x61) & 0x0f) | 0x04, 0x61); /* clear-and-disable parity check */
+    mdelay(1);
+    outb((inb(0x61) & 0x0b) | 0x00, 0x61); /* enable parity check */
 }
 
 asmlinkage void io_check_error(struct cpu_user_regs *regs)
 {
-    /* Clear and disable the I/O-error line. */
-    outb((inb(0x61)&15)|8,0x61);
-
     switch ( opt_nmi[0] )
     {
     case 'd': /* 'dom0' */
-        set_bit(0, &nmi_softirq_reason);
-        raise_softirq(NMI_SOFTIRQ);
+        set_bit(NMI_DOM0_IO_ERR, &nmi_dom0_softirq_reason);
+        raise_softirq(NMI_DOM0_SOFTIRQ);
     case 'i': /* 'ignore' */
         break;
     default:  /* 'fatal' */
@@ -1123,43 +1130,59 @@
         printk("\n\nNMI - I/O ERROR\n");
         fatal_trap(TRAP_nmi, regs);
     }
+
+    outb((inb(0x61) & 0x0f) | 0x08, 0x61); /* clear-and-disable IOCK */
+    mdelay(1);
+    outb((inb(0x61) & 0x07) | 0x00, 0x61); /* enable IOCK */
 }
 
 static void unknown_nmi_error(unsigned char reason)
 {
-    printk("Uhhuh. NMI received for unknown reason %02x.\n", reason);
-    printk("Dazed and confused, but trying to continue\n");
-    printk("Do you have a strange power saving mode enabled?\n");
-}
-
-static void default_do_nmi(struct cpu_user_regs *regs, unsigned long reason)
-{
-    if ( nmi_watchdog )
-        nmi_watchdog_tick(regs);
-
-    if ( reason & 0x80 )
-        mem_parity_error(regs);
-    else if ( reason & 0x40 )
-        io_check_error(regs);
-    else if ( !nmi_watchdog )
-        unknown_nmi_error((unsigned char)(reason&0xff));
+    switch ( opt_nmi[0] )
+    {
+    case 'd': /* 'dom0' */
+        set_bit(NMI_DOM0_UNKNOWN, &nmi_dom0_softirq_reason);
+        raise_softirq(NMI_DOM0_SOFTIRQ);
+    case 'i': /* 'ignore' */
+        break;
+    default:  /* 'fatal' */
+        printk("Uhhuh. NMI received for unknown reason %02x.\n", reason);
+        printk("Dazed and confused, but trying to continue\n");
+        printk("Do you have a strange power saving mode enabled?\n");
+    }
 }
 
 static int dummy_nmi_callback(struct cpu_user_regs *regs, int cpu)
 {
-       return 0;
+    return 0;
 }
  
 static nmi_callback_t nmi_callback = dummy_nmi_callback;
  
-asmlinkage void do_nmi(struct cpu_user_regs *regs, unsigned long reason)
+asmlinkage void do_nmi(struct cpu_user_regs *regs)
 {
     unsigned int cpu = smp_processor_id();
+    unsigned char reason;
 
     ++nmi_count(cpu);
 
-       if ( !nmi_callback(regs, cpu) )
-               default_do_nmi(regs, reason);
+    if ( nmi_callback(regs, cpu) )
+        return;
+
+    if ( nmi_watchdog )
+        nmi_watchdog_tick(regs);
+
+    /* Only the BSP gets external NMIs from the system. */
+    if ( cpu == 0 )
+    {
+        reason = inb(0x61);
+        if ( reason & 0x80 )
+            mem_parity_error(regs);
+        else if ( reason & 0x40 )
+            io_check_error(regs);
+        else if ( !nmi_watchdog )
+            unknown_nmi_error((unsigned char)(reason&0xff));
+    }
 }
 
 void set_nmi_callback(nmi_callback_t callback)
@@ -1169,7 +1192,7 @@
 
 void unset_nmi_callback(void)
 {
-       nmi_callback = dummy_nmi_callback;
+    nmi_callback = dummy_nmi_callback;
 }
 
 asmlinkage int math_state_restore(struct cpu_user_regs *regs)
@@ -1318,7 +1341,7 @@
 
     cpu_init();
 
-    open_softirq(NMI_SOFTIRQ, nmi_softirq);
+    open_softirq(NMI_DOM0_SOFTIRQ, nmi_dom0_softirq);
 }
 
 
diff -r 2c75070e41a0 -r 5a790011259e xen/arch/x86/vmx.c
--- a/xen/arch/x86/vmx.c        Wed Dec 21 16:30:10 2005
+++ b/xen/arch/x86/vmx.c        Wed Dec 21 17:56:19 2005
@@ -102,7 +102,8 @@
     if (v->vcpu_id == 0) {
         /* unmap IO shared page */
         struct domain *d = v->domain;
-        unmap_domain_page((void *)d->arch.vmx_platform.shared_page_va);
+        if ( d->arch.vmx_platform.shared_page_va )
+            unmap_domain_page((void *)d->arch.vmx_platform.shared_page_va);
     }
 
     destroy_vmcs(&v->arch.arch_vmx);
@@ -110,12 +111,12 @@
     vpit = &v->domain->arch.vmx_platform.vmx_pit;
     if ( active_ac_timer(&(vpit->pit_timer)) )
         rem_ac_timer(&vpit->pit_timer);
-    if ( active_ac_timer(&v->arch.arch_vmx.hlt_timer) ) {
+    if ( active_ac_timer(&v->arch.arch_vmx.hlt_timer) )
         rem_ac_timer(&v->arch.arch_vmx.hlt_timer);
-    }
-    if ( vmx_apic_support(v->domain) ) {
-        rem_ac_timer( &(VLAPIC(v)->vlapic_timer) );
-        xfree( VLAPIC(v) );
+    if ( vmx_apic_support(v->domain) && (VLAPIC(v) != NULL) )
+    {
+        rem_ac_timer(&VLAPIC(v)->vlapic_timer);
+        xfree(VLAPIC(v));
     }
 }
 
@@ -334,7 +335,7 @@
 
 extern long evtchn_send(int lport);
 extern long do_block(void);
-void do_nmi(struct cpu_user_regs *, unsigned long);
+void do_nmi(struct cpu_user_regs *);
 
 static int check_vmx_controls(ctrls, msr)
 {
@@ -503,6 +504,8 @@
     __vm_clear_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_NM);
 }
 
+/* Reserved bits: [31:15], [12:11], [9], [6], [2:1] */
+#define VMX_VCPU_CPUID_L1_RESERVED 0xffff9a46 
 
 static void vmx_vmexit_do_cpuid(unsigned long input, struct cpu_user_regs 
*regs)
 {
@@ -537,9 +540,17 @@
         }
 
         /* Unsupportable for virtualised CPUs. */
+        ecx &= ~VMX_VCPU_CPUID_L1_RESERVED; /* mask off reserved bits */
         clear_bit(X86_FEATURE_VMXE & 31, &ecx);
         clear_bit(X86_FEATURE_MWAIT & 31, &ecx);
     }
+#ifdef __i386__
+    else if ( input == 0x80000001 )
+    {
+        /* Mask feature for Intel ia32e or AMD long mode. */
+        clear_bit(X86_FEATURE_LM & 31, &edx);
+    }
+#endif
 
     regs->eax = (unsigned long) eax;
     regs->ebx = (unsigned long) ebx;
@@ -1091,11 +1102,21 @@
     unsigned long eip;
     int paging_enabled;
     unsigned long vm_entry_value;
+    unsigned long old_cr0;
 
     /*
      * CR0: We don't want to lose PE and PG.
      */
-    paging_enabled = vmx_paging_enabled(v);
+    __vmread_vcpu(v, CR0_READ_SHADOW, &old_cr0);
+    paging_enabled = (old_cr0 & X86_CR0_PE) && (old_cr0 & X86_CR0_PG);
+    /* If OS don't use clts to clear TS bit...*/
+    if((old_cr0 & X86_CR0_TS) && !(value & X86_CR0_TS))
+    {
+            clts();
+            setup_fpu(v);
+    }
+
+
     __vmwrite(GUEST_CR0, value | X86_CR0_PE | X86_CR0_PG | X86_CR0_NE);
     __vmwrite(CR0_READ_SHADOW, value);
 
@@ -1210,6 +1231,7 @@
             }
         }
 
+        clear_all_shadow_status(v->domain);
         if (vmx_assist(v, VMX_ASSIST_INVOKE)) {
             set_bit(VMX_CPU_STATE_ASSIST_ENABLED, &v->arch.arch_vmx.cpu_state);
             __vmread(GUEST_RIP, &eip);
@@ -1828,7 +1850,7 @@
             break;
         }
         case TRAP_nmi:
-            do_nmi(&regs, 0);
+            do_nmi(&regs);
             break;
         default:
             vmx_reflect_exception(v);
diff -r 2c75070e41a0 -r 5a790011259e xen/arch/x86/vmx_intercept.c
--- a/xen/arch/x86/vmx_intercept.c      Wed Dec 21 16:30:10 2005
+++ b/xen/arch/x86/vmx_intercept.c      Wed Dec 21 17:56:19 2005
@@ -203,6 +203,12 @@
     u64 nsec_delta = (unsigned int)((NOW() - vpit->inject_point));
     if (nsec_delta > vpit->period)
         VMX_DBG_LOG(DBG_LEVEL_1, "VMX_PIT:long time has passed from last 
injection!");
+    if(vpit->init_val == 0)
+    {
+        printk("PIT init value == 0!\n");
+        domain_crash_synchronous();
+    }
+
     vpit->count = vpit->init_val - ((nsec_delta * PIT_FREQ / 1000000000ULL) % 
vpit->init_val );
 }
 
diff -r 2c75070e41a0 -r 5a790011259e xen/arch/x86/x86_32/entry.S
--- a/xen/arch/x86/x86_32/entry.S       Wed Dec 21 16:30:10 2005
+++ b/xen/arch/x86/x86_32/entry.S       Wed Dec 21 17:56:19 2005
@@ -601,15 +601,7 @@
        pushl %eax
        SAVE_ALL_NOSEGREGS(a)
 
-        # Check for hardware problems.
-        inb   $0x61,%al
-        testb $0x80,%al
-        jne   nmi_parity_err
-        testb $0x40,%al
-        jne   nmi_io_err
-        movl  %eax,%ebx
-        
-        # Okay, its almost a normal NMI tick. We can only process it if:
+        # We can only process the NMI if:
         #  A. We are the outermost Xen activation (in which case we have
         #     the selectors safely saved on our stack)
         #  B. DS and ES contain sane Xen values.
@@ -619,7 +611,7 @@
         movl  UREGS_eflags(%esp),%eax
         movb  UREGS_cs(%esp),%al
         testl $(3|X86_EFLAGS_VM),%eax
-        jnz   do_watchdog_tick
+        jnz   continue_nmi
         movl  %ds,%eax
         cmpw  $(__HYPERVISOR_DS),%ax
         jne   defer_nmi
@@ -627,15 +619,14 @@
         cmpw  $(__HYPERVISOR_DS),%ax
         jne   defer_nmi
 
-do_watchdog_tick:
+continue_nmi:
         movl  $(__HYPERVISOR_DS),%edx
         movl  %edx,%ds
         movl  %edx,%es
         movl  %esp,%edx
-        pushl %ebx   # reason
-        pushl %edx   # regs
+        pushl %edx
         call  do_nmi
-        addl  $8,%esp
+        addl  $4,%esp
         jmp   ret_from_intr
 
 defer_nmi:
@@ -648,55 +639,6 @@
         movl  $(APIC_DM_FIXED | APIC_DEST_SELF | APIC_DEST_LOGICAL | \
                 TRAP_deferred_nmi),%ss:APIC_ICR(%eax)
         jmp   restore_all_xen
-
-nmi_parity_err:
-        # Clear and disable the parity-error line
-        andb $0xf,%al
-        orb  $0x4,%al
-        outb %al,$0x61
-        cmpb $'i',%ss:opt_nmi # nmi=ignore
-        je   nmi_out
-        bts  $0,%ss:nmi_softirq_reason
-        bts  $NMI_SOFTIRQ,%ss:irq_stat
-        cmpb $'d',%ss:opt_nmi # nmi=dom0
-        je   nmi_out
-        movl $(__HYPERVISOR_DS),%edx       # nmi=fatal
-        movl %edx,%ds
-        movl %edx,%es
-        movl %esp,%edx
-        push %edx
-        call mem_parity_error
-        addl $4,%esp
-nmi_out:movl  %ss:UREGS_eflags(%esp),%eax
-        movb  %ss:UREGS_cs(%esp),%al
-        testl $(3|X86_EFLAGS_VM),%eax
-        jz    restore_all_xen
-        movl  $(__HYPERVISOR_DS),%edx
-        movl  %edx,%ds
-        movl  %edx,%es
-        GET_CURRENT(%ebx)
-        jmp   test_all_events
-                
-nmi_io_err: 
-        # Clear and disable the I/O-error line
-        andb $0xf,%al
-        orb  $0x8,%al
-        outb %al,$0x61
-        cmpb $'i',%ss:opt_nmi # nmi=ignore
-        je   nmi_out
-        bts  $1,%ss:nmi_softirq_reason
-        bts  $NMI_SOFTIRQ,%ss:irq_stat
-        cmpb $'d',%ss:opt_nmi # nmi=dom0
-        je   nmi_out
-        movl $(__HYPERVISOR_DS),%edx       # nmi=fatal
-        movl %edx,%ds
-        movl %edx,%es
-        movl %esp,%edx
-        push %edx
-        call io_check_error                        
-        addl $4,%esp
-        jmp  nmi_out
-
 
 ENTRY(setup_vm86_frame)
         # Copies the entire stack frame forwards by 16 bytes.
diff -r 2c75070e41a0 -r 5a790011259e xen/arch/x86/x86_32/mm.c
--- a/xen/arch/x86/x86_32/mm.c  Wed Dec 21 16:30:10 2005
+++ b/xen/arch/x86/x86_32/mm.c  Wed Dec 21 17:56:19 2005
@@ -177,10 +177,11 @@
             idle_pg_table_l2[l2_linear_offset(RDWR_MPT_VIRT_START) + i]);
         for ( j = 0; j < L2_PAGETABLE_ENTRIES; j++ )
         {
-            frame_table[m2p_start_mfn+j].count_info = PGC_allocated | 1;
+            struct pfn_info *page = pfn_to_page(m2p_start_mfn + j);
+            page->count_info = PGC_allocated | 1;
             /* Ensure it's only mapped read-only by domains. */
-            frame_table[m2p_start_mfn+j].u.inuse.type_info = PGT_gdt_page | 1;
-            page_set_owner(&frame_table[m2p_start_mfn+j], dom_xen);
+            page->u.inuse.type_info = PGT_gdt_page | 1;
+            page_set_owner(page, dom_xen);
         }
     }
 }
diff -r 2c75070e41a0 -r 5a790011259e xen/arch/x86/x86_32/traps.c
--- a/xen/arch/x86/x86_32/traps.c       Wed Dec 21 16:30:10 2005
+++ b/xen/arch/x86/x86_32/traps.c       Wed Dec 21 17:56:19 2005
@@ -160,9 +160,9 @@
 BUILD_SMP_INTERRUPT(deferred_nmi, TRAP_deferred_nmi)
 asmlinkage void smp_deferred_nmi(struct cpu_user_regs regs)
 {
-    asmlinkage void do_nmi(struct cpu_user_regs *, unsigned long);
+    asmlinkage void do_nmi(struct cpu_user_regs *);
     ack_APIC_irq();
-    do_nmi(&regs, 0);
+    do_nmi(&regs);
 }
 
 void __init percpu_traps_init(void)
diff -r 2c75070e41a0 -r 5a790011259e xen/arch/x86/x86_64/entry.S
--- a/xen/arch/x86/x86_64/entry.S       Wed Dec 21 16:30:10 2005
+++ b/xen/arch/x86/x86_64/entry.S       Wed Dec 21 17:56:19 2005
@@ -567,9 +567,7 @@
 ENTRY(nmi)
         pushq $0
         SAVE_ALL
-        inb   $0x61,%al
-        movl  %eax,%esi # reason
-        movq  %rsp,%rdi # regs
+        movq  %rsp,%rdi
         call  do_nmi
        jmp   restore_all_xen
 
diff -r 2c75070e41a0 -r 5a790011259e xen/arch/x86/x86_64/mm.c
--- a/xen/arch/x86/x86_64/mm.c  Wed Dec 21 16:30:10 2005
+++ b/xen/arch/x86/x86_64/mm.c  Wed Dec 21 17:56:19 2005
@@ -166,11 +166,12 @@
 
         for ( i = 0; i < L1_PAGETABLE_ENTRIES; i++ )
         {
-            frame_table[m2p_start_mfn+i].count_info = PGC_allocated | 1;
+            struct pfn_info *page = pfn_to_page(m2p_start_mfn + i);
+            page->count_info = PGC_allocated | 1;
             /* gdt to make sure it's only mapped read-only by non-privileged
                domains. */
-            frame_table[m2p_start_mfn+i].u.inuse.type_info = PGT_gdt_page | 1;
-            page_set_owner(&frame_table[m2p_start_mfn+i], dom_xen);
+            page->u.inuse.type_info = PGT_gdt_page | 1;
+            page_set_owner(page, dom_xen);
         }
     }
 }
diff -r 2c75070e41a0 -r 5a790011259e xen/arch/x86/x86_emulate.c
--- a/xen/arch/x86/x86_emulate.c        Wed Dec 21 16:30:10 2005
+++ b/xen/arch/x86/x86_emulate.c        Wed Dec 21 17:56:19 2005
@@ -9,14 +9,6 @@
 #ifdef __TEST_HARNESS__
 #include <stdio.h>
 #include <stdint.h>
-typedef uint8_t            u8;
-typedef uint16_t           u16;
-typedef uint32_t           u32;
-typedef uint64_t           u64;
-typedef int8_t             s8;
-typedef int16_t            s16;
-typedef int32_t            s32;
-typedef int64_t            s64;
 #include <public/xen.h>
 #define DPRINTF(_f, _a...) printf( _f , ## _a )
 #else
@@ -50,15 +42,17 @@
 #define SrcImplicit (0<<3) /* Source operand is implicit in the opcode. */
 #define SrcReg      (1<<3) /* Register operand. */
 #define SrcMem      (2<<3) /* Memory operand. */
-#define SrcImm      (3<<3) /* Immediate operand. */
-#define SrcImmByte  (4<<3) /* 8-bit sign-extended immediate 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 SrcMask     (7<<3)
 /* Generic ModRM decode. */
 #define ModRM       (1<<6)
 /* Destination is only written; never read. */
 #define Mov         (1<<7)
 
-static u8 opcode_table[256] = {
+static uint8_t opcode_table[256] = {
     /* 0x00 - 0x07 */
     ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM,
     ByteOp|DstReg|SrcMem|ModRM, DstReg|SrcMem|ModRM,
@@ -96,7 +90,8 @@
     /* 0x50 - 0x5F */
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     /* 0x60 - 0x6F */
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, DstReg|SrcMem32|ModRM|Mov /* movsxd (x86/64) */,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     /* 0x70 - 0x7F */
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     /* 0x80 - 0x87 */
@@ -142,7 +137,7 @@
     0, 0, ByteOp|DstMem|SrcNone|ModRM, DstMem|SrcNone|ModRM
 };
 
-static u8 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 */
@@ -177,9 +172,10 @@
     0, 0, 0, DstMem|SrcReg|ModRM, 0, 0, 0, 0,
     /* 0xB0 - 0xB7 */
     ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM, 0, DstMem|SrcReg|ModRM,
-    0, 0, 0, 0,
+    0, 0, ByteOp|DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem16|ModRM|Mov,
     /* 0xB8 - 0xBF */
-    0, 0, DstMem|SrcImmByte|ModRM, DstMem|SrcReg|ModRM, 0, 0, 0, 0,
+    0, 0, DstMem|SrcImmByte|ModRM, DstMem|SrcReg|ModRM,
+    0, 0, ByteOp|DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem16|ModRM|Mov,
     /* 0xC0 - 0xCF */
     0, 0, 0, 0, 0, 0, 0, ImplicitOps|ModRM, 0, 0, 0, 0, 0, 0, 0, 0,
     /* 0xD0 - 0xDF */
@@ -377,7 +373,7 @@
 
 void *
 decode_register(
-    u8 modrm_reg, struct cpu_user_regs *regs, int highbyte_regs)
+    uint8_t modrm_reg, struct cpu_user_regs *regs, int highbyte_regs)
 {
     void *p;
 
@@ -422,8 +418,8 @@
     struct x86_mem_emulator *ops,
     int mode)
 {
-    u8 b, d, sib, twobyte = 0, rex_prefix = 0;
-    u8 modrm, modrm_mod = 0, modrm_reg = 0, modrm_rm = 0;
+    uint8_t b, d, sib, twobyte = 0, rex_prefix = 0;
+    uint8_t modrm, modrm_mod = 0, modrm_reg = 0, modrm_rm = 0;
     unsigned int op_bytes = (mode == 8) ? 4 : mode, ad_bytes = mode;
     unsigned int lock_prefix = 0, rep_prefix = 0, i;
     int rc = 0;
@@ -435,7 +431,7 @@
     /* Legacy prefixes. */
     for ( i = 0; i < 8; i++ )
     {
-        switch ( b = insn_fetch(u8, 1, _regs.eip) )
+        switch ( b = insn_fetch(uint8_t, 1, _regs.eip) )
         {
         case 0x66: /* operand-size override */
             op_bytes ^= 6;                    /* switch between 2/4 bytes */
@@ -465,12 +461,6 @@
     }
  done_prefixes:
 
-    if ( ad_bytes == 2 )
-    {
-        DPRINTF("Cannot parse 16-bit effective addresses.\n");
-        goto cannot_emulate;
-    }
-
     /* REX prefix. */
     if ( (mode == 8) && ((b & 0xf0) == 0x40) )
     {
@@ -479,7 +469,7 @@
             op_bytes = 8;          /* REX.W */
         modrm_reg = (b & 4) << 1;  /* REX.R */
         /* REX.B and REX.X do not need to be decoded. */
-        b = insn_fetch(u8, 1, _regs.eip);
+        b = insn_fetch(uint8_t, 1, _regs.eip);
     }
 
     /* Opcode byte(s). */
@@ -490,7 +480,7 @@
         if ( b == 0x0f )
         {
             twobyte = 1;
-            b = insn_fetch(u8, 1, _regs.eip);
+            b = insn_fetch(uint8_t, 1, _regs.eip);
             d = twobyte_table[b];
         }
 
@@ -502,32 +492,57 @@
     /* ModRM and SIB bytes. */
     if ( d & ModRM )
     {
-        modrm = insn_fetch(u8, 1, _regs.eip);
+        modrm = insn_fetch(uint8_t, 1, _regs.eip);
         modrm_mod |= (modrm & 0xc0) >> 6;
         modrm_reg |= (modrm & 0x38) >> 3;
         modrm_rm  |= (modrm & 0x07);
-        switch ( modrm_mod )
-        {
-        case 0:
-            if ( (modrm_rm == 4) && 
-                 (((sib = insn_fetch(u8, 1, _regs.eip)) & 7) == 5) )
-                _regs.eip += 4; /* skip disp32 specified by SIB.base */
-            else if ( modrm_rm == 5 )
-                _regs.eip += 4; /* skip disp32 */
-            break;
-        case 1:
-            if ( modrm_rm == 4 )
-                sib = insn_fetch(u8, 1, _regs.eip);
-            _regs.eip += 1; /* skip disp8 */
-            break;
-        case 2:
-            if ( modrm_rm == 4 )
-                sib = insn_fetch(u8, 1, _regs.eip);
-            _regs.eip += 4; /* skip disp32 */
-            break;
-        case 3:
+
+        if ( modrm_mod == 3 )
+        {
             DPRINTF("Cannot parse ModRM.mod == 3.\n");
             goto cannot_emulate;
+        }
+
+        if ( ad_bytes == 2 )
+        {
+            /* 16-bit ModR/M decode. */
+            switch ( modrm_mod )
+            {
+            case 0:
+                if ( modrm_rm == 6 )
+                    _regs.eip += 2; /* skip disp16 */
+                break;
+            case 1:
+                _regs.eip += 1; /* skip disp8 */
+                break;
+            case 2:
+                _regs.eip += 2; /* skip disp16 */
+                break;
+            }
+        }
+        else
+        {
+            /* 32/64-bit ModR/M decode. */
+            switch ( modrm_mod )
+            {
+            case 0:
+                if ( (modrm_rm == 4) && 
+                     (((sib = insn_fetch(uint8_t, 1, _regs.eip)) & 7) == 5) )
+                    _regs.eip += 4; /* skip disp32 specified by SIB.base */
+                else if ( modrm_rm == 5 )
+                    _regs.eip += 4; /* skip disp32 */
+                break;
+            case 1:
+                if ( modrm_rm == 4 )
+                    sib = insn_fetch(uint8_t, 1, _regs.eip);
+                _regs.eip += 1; /* skip disp8 */
+                break;
+            case 2:
+                if ( modrm_rm == 4 )
+                    sib = insn_fetch(uint8_t, 1, _regs.eip);
+                _regs.eip += 4; /* skip disp32 */
+                break;
+            }
         }
     }
 
@@ -542,7 +557,7 @@
         if ( d & ByteOp )
         {
             dst.ptr = decode_register(modrm_reg, &_regs, (rex_prefix == 0));
-            dst.val = *(u8 *)dst.ptr;
+            dst.val = *(uint8_t *)dst.ptr;
             dst.bytes = 1;
         }
         else
@@ -550,9 +565,9 @@
             dst.ptr = decode_register(modrm_reg, &_regs, 0);
             switch ( (dst.bytes = op_bytes) )
             {
-            case 2: dst.val = *(u16 *)dst.ptr; break;
-            case 4: dst.val = *(u32 *)dst.ptr; break;
-            case 8: dst.val = *(u64 *)dst.ptr; break;
+            case 2: dst.val = *(uint16_t *)dst.ptr; break;
+            case 4: dst.val = *(uint32_t *)dst.ptr; break;
+            case 8: dst.val = *(uint64_t *)dst.ptr; break;
             }
         }
         break;
@@ -578,7 +593,7 @@
         if ( d & ByteOp )
         {
             src.ptr = decode_register(modrm_reg, &_regs, (rex_prefix == 0));
-            src.val = src.orig_val = *(u8 *)src.ptr;
+            src.val = src.orig_val = *(uint8_t *)src.ptr;
             src.bytes = 1;
         }
         else
@@ -586,16 +601,23 @@
             src.ptr = decode_register(modrm_reg, &_regs, 0);
             switch ( (src.bytes = op_bytes) )
             {
-            case 2: src.val = src.orig_val = *(u16 *)src.ptr; break;
-            case 4: src.val = src.orig_val = *(u32 *)src.ptr; break;
-            case 8: src.val = src.orig_val = *(u64 *)src.ptr; break;
+            case 2: src.val = src.orig_val = *(uint16_t *)src.ptr; break;
+            case 4: src.val = src.orig_val = *(uint32_t *)src.ptr; break;
+            case 8: src.val = src.orig_val = *(uint64_t *)src.ptr; break;
             }
         }
         break;
+    case SrcMem16:
+        src.bytes = 2;
+        goto srcmem_common;
+    case SrcMem32:
+        src.bytes = 4;
+        goto srcmem_common;
     case SrcMem:
+        src.bytes = (d & ByteOp) ? 1 : op_bytes;
+    srcmem_common:
         src.type  = OP_MEM;
         src.ptr   = (unsigned long *)cr2;
-        src.bytes = (d & ByteOp) ? 1 : op_bytes;
         if ( (rc = ops->read_emulated((unsigned long)src.ptr, 
                                       &src.val, src.bytes)) != 0 )
             goto done;
@@ -609,16 +631,16 @@
         /* NB. Immediates are sign-extended as necessary. */
         switch ( src.bytes )
         {
-        case 1: src.val = insn_fetch(s8,  1, _regs.eip); break;
-        case 2: src.val = insn_fetch(s16, 2, _regs.eip); break;
-        case 4: src.val = insn_fetch(s32, 4, _regs.eip); break;
+        case 1: src.val = insn_fetch(int8_t,  1, _regs.eip); break;
+        case 2: src.val = insn_fetch(int16_t, 2, _regs.eip); break;
+        case 4: src.val = insn_fetch(int32_t, 4, _regs.eip); break;
         }
         break;
     case SrcImmByte:
         src.type  = OP_IMM;
         src.ptr   = (unsigned long *)_regs.eip;
         src.bytes = 1;
-        src.val   = insn_fetch(s8,  1, _regs.eip);
+        src.val   = insn_fetch(int8_t,  1, _regs.eip);
         break;
     }
 
@@ -650,6 +672,11 @@
         break;
     case 0x38 ... 0x3d: cmp: /* cmp */
         emulate_2op_SrcV("cmp", src, dst, _regs.eflags);
+        break;
+    case 0x63: /* movsxd */
+        if ( mode != 8 ) /* x86/64 long mode only */
+            goto cannot_emulate;
+        dst.val = (int32_t)src.val;
         break;
     case 0x80 ... 0x83: /* Grp1 */
         switch ( modrm_reg )
@@ -671,9 +698,9 @@
         /* Write back the register source. */
         switch ( dst.bytes )
         {
-        case 1: *(u8  *)src.ptr = (u8)dst.val; break;
-        case 2: *(u16 *)src.ptr = (u16)dst.val; break;
-        case 4: *src.ptr = (u32)dst.val; break; /* 64b mode: zero-extend */
+        case 1: *(uint8_t  *)src.ptr = (uint8_t)dst.val; break;
+        case 2: *(uint16_t *)src.ptr = (uint16_t)dst.val; break;
+        case 4: *src.ptr = (uint32_t)dst.val; break; /* 64b reg: zero-extend */
         case 8: *src.ptr = dst.val; break;
         }
         /* Write back the memory destination with implicit LOCK prefix. */
@@ -745,9 +772,9 @@
             if ( src.bytes == 8 ) src.bytes = 4;
             switch ( src.bytes )
             {
-            case 1: src.val = insn_fetch(s8,  1, _regs.eip); break;
-            case 2: src.val = insn_fetch(s16, 2, _regs.eip); break;
-            case 4: src.val = insn_fetch(s32, 4, _regs.eip); break;
+            case 1: src.val = insn_fetch(int8_t,  1, _regs.eip); break;
+            case 2: src.val = insn_fetch(int16_t, 2, _regs.eip); break;
+            case 4: src.val = insn_fetch(int32_t, 4, _regs.eip); break;
             }
             goto test;
         case 2: /* not */
@@ -798,9 +825,9 @@
             /* The 4-byte case *is* correct: in 64-bit mode we zero-extend. */
             switch ( dst.bytes )
             {
-            case 1: *(u8  *)dst.ptr = (u8)dst.val; break;
-            case 2: *(u16 *)dst.ptr = (u16)dst.val; break;
-            case 4: *dst.ptr = (u32)dst.val; break; /* 64b mode: zero-extend */
+            case 1: *(uint8_t  *)dst.ptr = (uint8_t)dst.val; break;
+            case 2: *(uint16_t *)dst.ptr = (uint16_t)dst.val; break;
+            case 4: *dst.ptr = (uint32_t)dst.val; break; /* 64b: zero-ext */
             case 8: *dst.ptr = dst.val; break;
             }
             break;
@@ -953,6 +980,10 @@
         src.val &= (dst.bytes << 3) - 1; /* only subword offset */
         emulate_2op_SrcV_nobyte("bts", src, dst, _regs.eflags);
         break;
+    case 0xb6 ... 0xb7: /* movzx */
+        dst.bytes = op_bytes;
+        dst.val = (d & ByteOp) ? (uint8_t)src.val : (uint16_t)src.val;
+        break;
     case 0xbb: btc: /* btc */
         src.val &= (dst.bytes << 3) - 1; /* only subword offset */
         emulate_2op_SrcV_nobyte("btc", src, dst, _regs.eflags);
@@ -965,6 +996,10 @@
         case 2: goto btr;
         case 3: goto btc;
         }
+        break;
+    case 0xbe ... 0xbf: /* movsx */
+        dst.bytes = op_bytes;
+        dst.val = (d & ByteOp) ? (int8_t)src.val : (int16_t)src.val;
         break;
     }
     goto writeback;
@@ -1009,16 +1044,16 @@
         unsigned long old, new;
         if ( (rc = ops->read_emulated(cr2, &old, 8)) != 0 )
             goto done;
-        if ( ((u32)(old>>0) != (u32)_regs.eax) ||
-             ((u32)(old>>32) != (u32)_regs.edx) )
-        {
-            _regs.eax = (u32)(old>>0);
-            _regs.edx = (u32)(old>>32);
+        if ( ((uint32_t)(old>>0) != (uint32_t)_regs.eax) ||
+             ((uint32_t)(old>>32) != (uint32_t)_regs.edx) )
+        {
+            _regs.eax = (uint32_t)(old>>0);
+            _regs.edx = (uint32_t)(old>>32);
             _regs.eflags &= ~EFLG_ZF;
         }
         else
         {
-            new = (_regs.ecx<<32)|(u32)_regs.ebx;
+            new = (_regs.ecx<<32)|(uint32_t)_regs.ebx;
             if ( (rc = ops->cmpxchg_emulated(cr2, old, new, 8)) != 0 )
                 goto done;
             _regs.eflags |= EFLG_ZF;
diff -r 2c75070e41a0 -r 5a790011259e xen/common/dom0_ops.c
--- a/xen/common/dom0_ops.c     Wed Dec 21 16:30:10 2005
+++ b/xen/common/dom0_ops.c     Wed Dec 21 17:56:19 2005
@@ -358,12 +358,17 @@
     case DOM0_GETDOMAININFO:
     { 
         struct domain *d;
+        domid_t dom;
+
+        dom = op->u.getdomaininfo.domain;
+        if ( dom == DOMID_SELF )
+            dom = current->domain->domain_id;
 
         read_lock(&domlist_lock);
 
         for_each_domain ( d )
         {
-            if ( d->domain_id >= op->u.getdomaininfo.domain )
+            if ( d->domain_id >= dom )
                 break;
         }
 
@@ -577,6 +582,22 @@
         }
     }
     break;
+    case DOM0_SETDEBUGGING:
+    {
+        struct domain *d; 
+        ret = -ESRCH;
+        d = find_domain_by_id(op->u.setdebugging.domain);
+        if ( d != NULL )
+        {
+            if ( op->u.setdebugging.enable )
+                set_bit(_DOMF_debugging, &d->domain_flags);
+            else
+                clear_bit(_DOMF_debugging, &d->domain_flags);
+            put_domain(d);
+            ret = 0;
+        }
+    }
+    break;
 
 #ifdef PERF_COUNTERS
     case DOM0_PERFCCONTROL:
diff -r 2c75070e41a0 -r 5a790011259e xen/common/grant_table.c
--- a/xen/common/grant_table.c  Wed Dec 21 16:30:10 2005
+++ b/xen/common/grant_table.c  Wed Dec 21 17:56:19 2005
@@ -238,8 +238,8 @@
 
         if ( unlikely(!pfn_valid(frame)) ||
              unlikely(!((dev_hst_ro_flags & GNTMAP_readonly) ?
-                        get_page(&frame_table[frame], rd) :
-                        get_page_and_type(&frame_table[frame], rd,
+                        get_page(pfn_to_page(frame), rd) :
+                        get_page_and_type(pfn_to_page(frame), rd,
                                           PGT_writable_page))) )
         {
             clear_bit(_GTF_writing, &sha->flags);
@@ -301,7 +301,7 @@
                 sflags = prev_sflags;
             }
 
-            if ( unlikely(!get_page_type(&frame_table[frame],
+            if ( unlikely(!get_page_type(pfn_to_page(frame),
                                          PGT_writable_page)) )
             {
                 clear_bit(_GTF_writing, &sha->flags);
@@ -347,14 +347,14 @@
                 if ( (act->pin & (GNTPIN_hstw_mask|GNTPIN_devw_mask)) == 0 )
                 {
                     clear_bit(_GTF_writing, &sha->flags);
-                    put_page_type(&frame_table[frame]);
+                    put_page_type(pfn_to_page(frame));
                 }
             }
 
             if ( act->pin == 0 )
             {
                 clear_bit(_GTF_reading, &sha->flags);
-                put_page(&frame_table[frame]);
+                put_page(pfn_to_page(frame));
             }
 
             spin_unlock(&rd->grant_table->lock);
@@ -500,14 +500,14 @@
          !(flags & GNTMAP_readonly) )
     {
         clear_bit(_GTF_writing, &sha->flags);
-        put_page_type(&frame_table[frame]);
+        put_page_type(pfn_to_page(frame));
     }
 
     if ( act->pin == 0 )
     {
         act->frame = 0xdeadbeef;
         clear_bit(_GTF_reading, &sha->flags);
-        put_page(&frame_table[frame]);
+        put_page(pfn_to_page(frame));
     }
 
  unmap_out:
@@ -691,7 +691,7 @@
         }
 
         /* Check the passed page frame for basic validity. */
-        page = &frame_table[gop.mfn];
+        page = pfn_to_page(gop.mfn);
         if ( unlikely(!pfn_valid(gop.mfn) || IS_XEN_HEAP_FRAME(page)) )
         { 
             DPRINTK("gnttab_transfer: out-of-range or xen frame %lx\n",
@@ -1016,14 +1016,14 @@
             if ( (act->pin & (GNTPIN_devw_mask|GNTPIN_hstw_mask)) == 0 )
             {
                 clear_bit(_GTF_writing, &sha->flags);
-                put_page_type(&frame_table[act->frame]);
+                put_page_type(pfn_to_page(act->frame));
             }
         }
 
         if ( act->pin == 0 )
         {
             clear_bit(_GTF_reading, &sha->flags);
-            put_page(&frame_table[act->frame]);
+            put_page(pfn_to_page(act->frame));
         }
 
         spin_unlock(&rd->grant_table->lock);
diff -r 2c75070e41a0 -r 5a790011259e xen/common/keyhandler.c
--- a/xen/common/keyhandler.c   Wed Dec 21 16:30:10 2005
+++ b/xen/common/keyhandler.c   Wed Dec 21 17:56:19 2005
@@ -112,8 +112,11 @@
         printk("Xen: DOM %u, flags=%lx refcnt=%d nr_pages=%d "
                "xenheap_pages=%d\n", d->domain_id, d->domain_flags,
                atomic_read(&d->refcnt), d->tot_pages, d->xenheap_pages);
-        printk("     handle=%02x%02x%02x%02x-%02x%02x%02x%02x-"
-               "%02x%02x%02x%02x-%02x%02x%02x%02x\n",
+        /* The handle is printed according to the OSF DCE UUID spec., even
+           though it is not necessarily such a thing, for ease of use when it
+           _is_ one of those. */
+        printk("     handle=%02x%02x%02x%02x-%02x%02x-%02x%02x-"
+               "%02x%02x-%02x%02x%02x%02x%02x%02x\n",
                d->handle[ 0], d->handle[ 1], d->handle[ 2], d->handle[ 3],
                d->handle[ 4], d->handle[ 5], d->handle[ 6], d->handle[ 7],
                d->handle[ 8], d->handle[ 9], d->handle[10], d->handle[11],
diff -r 2c75070e41a0 -r 5a790011259e xen/common/memory.c
--- a/xen/common/memory.c       Wed Dec 21 16:30:10 2005
+++ b/xen/common/memory.c       Wed Dec 21 17:56:19 2005
@@ -102,7 +102,7 @@
                 return i;
             }
             
-            page = &frame_table[mpfn + j];
+            page = pfn_to_page(mpfn + j);
             if ( unlikely(!get_page(page, d)) )
             {
                 DPRINTK("Bad page free for domain %u\n", d->domain_id);
diff -r 2c75070e41a0 -r 5a790011259e xen/include/asm-ia64/vmx_platform.h
--- a/xen/include/asm-ia64/vmx_platform.h       Wed Dec 21 16:30:10 2005
+++ b/xen/include/asm-ia64/vmx_platform.h       Wed Dec 21 17:56:19 2005
@@ -55,6 +55,12 @@
 #define VLAPIC_ID(l) (uint16_t)(VCPU((l)->vcpu, lid) >> 16)
 #define VLAPIC_IRR(l) VCPU((l)->vcpu, irr[0])
 
+extern int vmx_vcpu_pend_interrupt(struct vcpu *vcpu, uint8_t vector);
+static inline int vlapic_set_irq(struct vlapic *t, uint8_t vec, uint8_t trig)
+{
+    return vmx_vcpu_pend_interrupt(t->vcpu, vec);
+}
+
 /* As long as we register vlsapic to ioapic controller, it's said enabled */
 #define vlapic_enabled(l) 1
 #define vmx_apic_support(d) 1
diff -r 2c75070e41a0 -r 5a790011259e xen/include/asm-ia64/vmx_vcpu.h
--- a/xen/include/asm-ia64/vmx_vcpu.h   Wed Dec 21 16:30:10 2005
+++ b/xen/include/asm-ia64/vmx_vcpu.h   Wed Dec 21 17:56:19 2005
@@ -112,7 +112,7 @@
 extern void guest_write_eoi(VCPU *vcpu);
 extern uint64_t guest_read_vivr(VCPU *vcpu);
 extern void vmx_inject_vhpi(VCPU *vcpu, u8 vec);
-extern void vmx_vcpu_pend_interrupt(VCPU *vcpu, UINT64 vector);
+extern int vmx_vcpu_pend_interrupt(VCPU *vcpu, uint8_t vector);
 extern struct virutal_platform_def *vmx_vcpu_get_plat(VCPU *vcpu);
 extern void memread_p(VCPU *vcpu, u64 *src, u64 *dest, size_t s);
 extern void memread_v(VCPU *vcpu, thash_data_t *vtlb, u64 *src, u64 *dest, 
size_t s);
@@ -474,4 +474,7 @@
 #endif 
 
 }
+
+#define check_work_pending(v)  \
+    (event_pending((v)) || ((v)->arch.irq_new_pending))
 #endif
diff -r 2c75070e41a0 -r 5a790011259e xen/include/asm-x86/debugger.h
--- a/xen/include/asm-x86/debugger.h    Wed Dec 21 16:30:10 2005
+++ b/xen/include/asm-x86/debugger.h    Wed Dec 21 17:56:19 2005
@@ -30,6 +30,8 @@
 #ifndef __X86_DEBUGGER_H__
 #define __X86_DEBUGGER_H__
 
+#include <xen/sched.h>
+#include <asm/regs.h>
 #include <asm/processor.h>
 
 /* The main trap handlers use these helper macros which include early bail. */
@@ -41,9 +43,10 @@
 #if defined(CRASH_DEBUG)
 
 extern int __trap_to_cdb(struct cpu_user_regs *r);
-#define debugger_trap_entry(_v, _r) (0)
 
-static inline int debugger_trap_fatal(
+#define __debugger_trap_entry(_v, _r) (0)
+
+static inline int __debugger_trap_fatal(
     unsigned int vector, struct cpu_user_regs *regs)
 {
     (void)__trap_to_cdb(regs);
@@ -51,60 +54,52 @@
 }
 
 /* Int3 is a trivial way to gather cpu_user_regs context. */
-#define debugger_trap_immediate() __asm__ __volatile__ ( "int3" );
+#define __debugger_trap_immediate() __asm__ __volatile__ ( "int3" );
 
-#elif defined(DOMU_DEBUG)
+#elif 0
 
-#include <xen/sched.h>
-#include <asm/regs.h>
+extern int kdb_trap(int, int, struct cpu_user_regs *);
+
+static inline int __debugger_trap_entry(
+    unsigned int vector, struct cpu_user_regs *regs)
+{
+    return 0;
+}
+
+static inline int __debugger_trap_fatal(
+    unsigned int vector, struct cpu_user_regs *regs)
+{
+    return kdb_trap(vector, 0, regs);
+}
+
+/* Int3 is a trivial way to gather cpu_user_regs context. */
+#define __debugger_trap_immediate() __asm__ __volatile__ ( "int3" )
+
+#else
+
+#define __debugger_trap_entry(_v, _r) (0)
+#define __debugger_trap_fatal(_v, _r) (0)
+#define __debugger_trap_immediate()   ((void)0)
+
+#endif
 
 static inline int debugger_trap_entry(
     unsigned int vector, struct cpu_user_regs *regs)
 {
     struct vcpu *v = current;
 
-    if ( !KERNEL_MODE(v, regs) || (v->domain->domain_id == 0) )
-        return 0;
-    
-    switch ( vector )
+    if ( KERNEL_MODE(v, regs) &&
+         test_bit(_DOMF_debugging, &v->domain->domain_flags) &&
+         ((vector == TRAP_int3) || (vector == TRAP_debug)) )
     {
-    case TRAP_int3:
-    case TRAP_debug:
         domain_pause_for_debugger();
         return 1;
     }
 
-    return 0;
+    return __debugger_trap_entry(vector, regs);
 }
 
-#define debugger_trap_fatal(_v, _r) (0)
-#define debugger_trap_immediate()
-
-#elif 0
-
-extern int kdb_trap(int, int, struct cpu_user_regs *);
-
-static inline int debugger_trap_entry(
-    unsigned int vector, struct cpu_user_regs *regs)
-{
-    return 0;
-}
-
-static inline int debugger_trap_fatal(
-    unsigned int vector, struct cpu_user_regs *regs)
-{
-    return kdb_trap(vector, 0, regs);
-}
-
-/* Int3 is a trivial way to gather cpu_user_regs context. */
-#define debugger_trap_immediate() __asm__ __volatile__ ( "int3" );
-
-#else
-
-#define debugger_trap_entry(_v, _r) (0)
-#define debugger_trap_fatal(_v, _r) (0)
-#define debugger_trap_immediate()
-
-#endif
+#define debugger_trap_fatal(v, r) (__debugger_trap_fatal(v, r))
+#define debugger_trap_immediate() (__debugger_trap_immediate())
 
 #endif /* __X86_DEBUGGER_H__ */
diff -r 2c75070e41a0 -r 5a790011259e xen/include/asm-x86/shadow.h
--- a/xen/include/asm-x86/shadow.h      Wed Dec 21 16:30:10 2005
+++ b/xen/include/asm-x86/shadow.h      Wed Dec 21 17:56:19 2005
@@ -493,9 +493,9 @@
         SH_VLOG("mark_dirty OOR! mfn=%x pfn=%lx max=%x (dom %p)",
                mfn, pfn, d->arch.shadow_dirty_bitmap_size, d);
         SH_VLOG("dom=%p caf=%08x taf=%" PRtype_info, 
-               page_get_owner(&frame_table[mfn]),
-               frame_table[mfn].count_info, 
-               frame_table[mfn].u.inuse.type_info );
+                page_get_owner(pfn_to_page(mfn)),
+                pfn_to_page(mfn)->count_info, 
+                pfn_to_page(mfn)->u.inuse.type_info );
     }
 #endif
 }
@@ -648,20 +648,20 @@
 
     ASSERT(pfn_valid(smfn));
 
-    x = frame_table[smfn].count_info;
+    x = pfn_to_page(smfn)->count_info;
     nx = x + 1;
 
     if ( unlikely(nx == 0) )
     {
         printk("get_shadow_ref overflow, gmfn=%" PRtype_info  " smfn=%lx\n",
-               frame_table[smfn].u.inuse.type_info & PGT_mfn_mask,
+               pfn_to_page(smfn)->u.inuse.type_info & PGT_mfn_mask,
                smfn);
         BUG();
     }
     
     // Guarded by the shadow lock...
     //
-    frame_table[smfn].count_info = nx;
+    pfn_to_page(smfn)->count_info = nx;
 
     return 1;
 }
@@ -678,7 +678,7 @@
 
     ASSERT(pfn_valid(smfn));
 
-    x = frame_table[smfn].count_info;
+    x = pfn_to_page(smfn)->count_info;
     nx = x - 1;
 
     if ( unlikely(x == 0) )
@@ -686,14 +686,14 @@
         printk("put_shadow_ref underflow, smfn=%lx oc=%08x t=%" 
                PRtype_info "\n",
                smfn,
-               frame_table[smfn].count_info,
-               frame_table[smfn].u.inuse.type_info);
+               pfn_to_page(smfn)->count_info,
+               pfn_to_page(smfn)->u.inuse.type_info);
         BUG();
     }
 
     // Guarded by the shadow lock...
     //
-    frame_table[smfn].count_info = nx;
+    pfn_to_page(smfn)->count_info = nx;
 
     if ( unlikely(nx == 0) )
     {
@@ -704,9 +704,9 @@
 static inline void
 shadow_pin(unsigned long smfn)
 {
-    ASSERT( !(frame_table[smfn].u.inuse.type_info & PGT_pinned) );
-
-    frame_table[smfn].u.inuse.type_info |= PGT_pinned;
+    ASSERT( !(pfn_to_page(smfn)->u.inuse.type_info & PGT_pinned) );
+
+    pfn_to_page(smfn)->u.inuse.type_info |= PGT_pinned;
     if ( unlikely(!get_shadow_ref(smfn)) )
         BUG();
 }
@@ -714,9 +714,9 @@
 static inline void
 shadow_unpin(unsigned long smfn)
 {
-    ASSERT( (frame_table[smfn].u.inuse.type_info & PGT_pinned) );
-
-    frame_table[smfn].u.inuse.type_info &= ~PGT_pinned;
+    ASSERT( (pfn_to_page(smfn)->u.inuse.type_info & PGT_pinned) );
+
+    pfn_to_page(smfn)->u.inuse.type_info &= ~PGT_pinned;
     put_shadow_ref(smfn);
 }
 
@@ -732,9 +732,9 @@
 
         ASSERT(shadow_lock_is_acquired(d));
         gmfn = l1e_get_pfn(spte);
-        frame_table[gmfn].tlbflush_timestamp = smfn;
-        frame_table[gmfn].u.inuse.type_info &= ~PGT_va_mask;
-        frame_table[gmfn].u.inuse.type_info |= (unsigned long) index << 
PGT_va_shift;
+        pfn_to_page(gmfn)->tlbflush_timestamp = smfn;
+        pfn_to_page(gmfn)->u.inuse.type_info &= ~PGT_va_mask;
+        pfn_to_page(gmfn)->u.inuse.type_info |= (unsigned long) index << 
PGT_va_shift;
     }
 }
 
@@ -941,7 +941,7 @@
             //
             perfc_incrc(validate_pte_changes2);
             if ( likely(l1e_get_flags(new_spte) & _PAGE_PRESENT) )
-                shadow_put_page_type(d, &frame_table[l1e_get_pfn(new_spte)]);
+                shadow_put_page_type(d, pfn_to_page(l1e_get_pfn(new_spte)));
         }
         else if ( ((l1e_get_flags(old_spte) | l1e_get_flags(new_spte)) &
                    _PAGE_PRESENT ) &&
@@ -1216,8 +1216,8 @@
             printk("d->id=%d gpfn=%lx gmfn=%lx stype=%lx c=%x t=%" PRtype_info 
" "
                    "mfn_out_of_sync(gmfn)=%d mfn_is_page_table(gmfn)=%d\n",
                    d->domain_id, gpfn, gmfn, stype,
-                   frame_table[gmfn].count_info,
-                   frame_table[gmfn].u.inuse.type_info,
+                   pfn_to_page(gmfn)->count_info,
+                   pfn_to_page(gmfn)->u.inuse.type_info,
                    mfn_out_of_sync(gmfn), mfn_is_page_table(gmfn));
             BUG();
         }
@@ -1597,7 +1597,7 @@
     struct vcpu *v = current;
     struct domain *d = v->domain;
     unsigned long mfn = __gpfn_to_mfn(d, gpfn);
-    u32 type = frame_table[mfn].u.inuse.type_info & PGT_type_mask;
+    u32 type = pfn_to_page(mfn)->u.inuse.type_info & PGT_type_mask;
 
     if ( shadow_mode_refcounts(d) &&
          (type == PGT_writable_page) )
@@ -1707,6 +1707,8 @@
     }
 }
 
+void clear_all_shadow_status(struct domain *d);
+
 #if SHADOW_DEBUG
 extern int _check_pagetable(struct vcpu *v, char *s);
 extern int _check_all_pagetables(struct vcpu *v, char *s);
diff -r 2c75070e41a0 -r 5a790011259e xen/include/asm-x86/shadow_public.h
--- a/xen/include/asm-x86/shadow_public.h       Wed Dec 21 16:30:10 2005
+++ b/xen/include/asm-x86/shadow_public.h       Wed Dec 21 17:56:19 2005
@@ -22,7 +22,7 @@
 #ifndef _XEN_SHADOW_PUBLIC_H
 #define _XEN_SHADOW_PUBLIC_H
 #if CONFIG_PAGING_LEVELS >= 3
-#define MFN_PINNED(_x) (frame_table[_x].u.inuse.type_info & PGT_pinned)
+#define MFN_PINNED(_x) (pfn_to_page(_x)->u.inuse.type_info & PGT_pinned)
 
 extern int alloc_p2m_table(struct domain *d);
 
diff -r 2c75070e41a0 -r 5a790011259e xen/include/asm-x86/vmx_vlapic.h
--- a/xen/include/asm-x86/vmx_vlapic.h  Wed Dec 21 16:30:10 2005
+++ b/xen/include/asm-x86/vmx_vlapic.h  Wed Dec 21 17:56:19 2005
@@ -202,6 +202,18 @@
     struct domain      *domain;
 };
 
+static inline int vlapic_set_irq(struct vlapic *t, uint8_t vec, uint8_t trig)
+{
+    int ret;
+
+    ret = test_and_set_bit(vec, &t->irr[0]);
+    if (trig)
+       test_and_set_bit(vec, &t->tmr[0]);
+
+    /* We may need to wake up target vcpu, besides set pending bit here */
+    return ret;
+}
+
 static inline int  vlapic_timer_active(struct vlapic *vlapic)
 {
     return  active_ac_timer(&(vlapic->vlapic_timer));
diff -r 2c75070e41a0 -r 5a790011259e xen/include/asm-x86/x86_emulate.h
--- a/xen/include/asm-x86/x86_emulate.h Wed Dec 21 16:30:10 2005
+++ b/xen/include/asm-x86/x86_emulate.h Wed Dec 21 17:56:19 2005
@@ -164,6 +164,6 @@
  */
 extern void *
 decode_register(
-    u8 modrm_reg, struct cpu_user_regs *regs, int highbyte_regs);
+    uint8_t modrm_reg, struct cpu_user_regs *regs, int highbyte_regs);
 
 #endif /* __X86_EMULATE_H__ */
diff -r 2c75070e41a0 -r 5a790011259e xen/include/public/acm.h
--- a/xen/include/public/acm.h  Wed Dec 21 16:30:10 2005
+++ b/xen/include/public/acm.h  Wed Dec 21 17:56:19 2005
@@ -1,25 +1,8 @@
-/****************************************************************
- * acm.h
- * 
- * Copyright (C) 2005 IBM Corporation
+/*
+ * acm.h: Xen access control module interface defintions
  *
- * Author:
  * Reiner Sailer <sailer@xxxxxxxxxxxxxx>
- *
- * Contributors:
- * Stefan Berger <stefanb@xxxxxxxxxxxxxx> 
- * added network byte order support for binary policies
- *
- * 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, version 2 of the
- * License.
- *
- * sHype general access control module header file.
- *     here are all definitions that are shared between
- *     xen-core, guest-kernels, and applications.
- *
- * todo: move from static policy choice to compile option.
+ * Copyright (c) 2005, International Business Machines Corporation.
  */
 
 #ifndef _XEN_PUBLIC_ACM_H
diff -r 2c75070e41a0 -r 5a790011259e xen/include/public/acm_ops.h
--- a/xen/include/public/acm_ops.h      Wed Dec 21 16:30:10 2005
+++ b/xen/include/public/acm_ops.h      Wed Dec 21 17:56:19 2005
@@ -1,19 +1,8 @@
-/******************************************************************************
- * acm_ops.h
+/*
+ * acm_ops.h: Xen access control module hypervisor commands
  *
- * Copyright (C) 2005 IBM Corporation
- *
- * Author:
  * Reiner Sailer <sailer@xxxxxxxxxxxxxx>
- *
- * 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, version 2 of the
- * License.
- *
- * Process acm policy command requests from guest OS.
- * access checked by policy; not restricted to DOM0
- *
+ * Copyright (c) 2005, International Business Machines Corporation.
  */
 
 #ifndef __XEN_PUBLIC_ACM_OPS_H__
diff -r 2c75070e41a0 -r 5a790011259e xen/include/public/dom0_ops.h
--- a/xen/include/public/dom0_ops.h     Wed Dec 21 16:30:10 2005
+++ b/xen/include/public/dom0_ops.h     Wed Dec 21 17:56:19 2005
@@ -403,6 +403,12 @@
     domid_t domain;
     xen_domain_handle_t handle;
 } dom0_setdomainhandle_t;
+
+#define DOM0_SETDEBUGGING 45
+typedef struct {
+    domid_t domain;
+    uint8_t enable;
+} dom0_setdebugging_t;
 
 typedef struct {
     uint32_t cmd;
@@ -440,7 +446,8 @@
         dom0_platform_quirk_t    platform_quirk;
         dom0_physical_memory_map_t physical_memory_map;
         dom0_max_vcpus_t         max_vcpus;
-        dom0_setdomainhandle_t   setdomainhandle;
+        dom0_setdomainhandle_t   setdomainhandle;        
+        dom0_setdebugging_t      setdebugging;
         uint8_t                  pad[128];
     } u;
 } dom0_op_t;
diff -r 2c75070e41a0 -r 5a790011259e xen/include/public/vmx_assist.h
--- a/xen/include/public/vmx_assist.h   Wed Dec 21 16:30:10 2005
+++ b/xen/include/public/vmx_assist.h   Wed Dec 21 17:56:19 2005
@@ -3,21 +3,8 @@
  *
  * Leendert van Doorn, leendert@xxxxxxxxxxxxxx
  * Copyright (c) 2005, International Business Machines Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope 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 _VMX_ASSIST_H_
 #define _VMX_ASSIST_H_
 
diff -r 2c75070e41a0 -r 5a790011259e xen/include/public/xen.h
--- a/xen/include/public/xen.h  Wed Dec 21 16:30:10 2005
+++ b/xen/include/public/xen.h  Wed Dec 21 17:56:19 2005
@@ -67,12 +67,13 @@
  */
 #define VIRQ_TIMER      0  /* Timebase update, and/or requested timeout.  */
 #define VIRQ_DEBUG      1  /* Request guest to dump debug info.           */
-#define VIRQ_CONSOLE    2  /* (DOM0) bytes received on emergency console. */
+#define VIRQ_CONSOLE    2  /* (DOM0) Bytes received on emergency console. */
 #define VIRQ_DOM_EXC    3  /* (DOM0) Exceptional event for some domain.   */
-#define VIRQ_PARITY_ERR 4  /* (DOM0) NMI parity error.                    */
-#define VIRQ_IO_ERR     5  /* (DOM0) NMI I/O error.                       */
+#define VIRQ_PARITY_ERR 4  /* (DOM0) NMI parity error (port 0x61, bit 7). */
+#define VIRQ_IO_ERR     5  /* (DOM0) NMI I/O error    (port 0x61, bit 6). */
 #define VIRQ_DEBUGGER   6  /* (DOM0) A domain has paused for debugging.   */
-#define NR_VIRQS        7
+#define VIRQ_NMI        7  /* (DOM0) Unknown NMI (not from ISA port 0x61).*/
+#define NR_VIRQS        8
 
 /*
  * MMU-UPDATE REQUESTS
diff -r 2c75070e41a0 -r 5a790011259e xen/include/xen/sched.h
--- a/xen/include/xen/sched.h   Wed Dec 21 16:30:10 2005
+++ b/xen/include/xen/sched.h   Wed Dec 21 17:56:19 2005
@@ -393,6 +393,10 @@
  /* Domain is paused by controller software. */
 #define _DOMF_ctrl_pause       6
 #define DOMF_ctrl_pause        (1UL<<_DOMF_ctrl_pause)
+ /* Domain is being debugged by controller software. */
+#define _DOMF_debugging        7
+#define DOMF_debugging         (1UL<<_DOMF_debugging)
+
 
 static inline int domain_runnable(struct vcpu *v)
 {
diff -r 2c75070e41a0 -r 5a790011259e xen/include/xen/softirq.h
--- a/xen/include/xen/softirq.h Wed Dec 21 16:30:10 2005
+++ b/xen/include/xen/softirq.h Wed Dec 21 17:56:19 2005
@@ -6,7 +6,7 @@
 #define SCHEDULE_SOFTIRQ                  1
 #define NEW_TLBFLUSH_CLOCK_PERIOD_SOFTIRQ 2
 #define KEYPRESS_SOFTIRQ                  3
-#define NMI_SOFTIRQ                       4
+#define NMI_DOM0_SOFTIRQ                  4
 #define PAGE_SCRUB_SOFTIRQ                5
 #define DOMAIN_SHUTDOWN_FINALISE_SOFTIRQ  6
 #define NR_SOFTIRQS                       7
diff -r 2c75070e41a0 -r 5a790011259e tools/ioemu/audio/audio.c
--- /dev/null   Wed Dec 21 16:30:10 2005
+++ b/tools/ioemu/audio/audio.c Wed Dec 21 17:56:19 2005
@@ -0,0 +1,910 @@
+/*
+ * QEMU Audio subsystem
+ * 
+ * Copyright (c) 2003-2004 Vassili Karpov (malc)
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include <assert.h>
+#include "vl.h"
+
+#define USE_WAV_AUDIO
+
+#include "audio/audio_int.h"
+
+#define dolog(...) AUD_log ("audio", __VA_ARGS__)
+#ifdef DEBUG
+#define ldebug(...) dolog (__VA_ARGS__)
+#else
+#define ldebug(...)
+#endif
+
+#define QC_AUDIO_DRV    "QEMU_AUDIO_DRV"
+#define QC_VOICES       "QEMU_VOICES"
+#define QC_FIXED_FORMAT "QEMU_FIXED_FORMAT"
+#define QC_FIXED_FREQ   "QEMU_FIXED_FREQ"
+
+static HWVoice *hw_voices;
+
+AudioState audio_state = {
+    1,                          /* use fixed settings */
+    44100,                      /* fixed frequency */
+    2,                          /* fixed channels */
+    AUD_FMT_S16,                /* fixed format */
+    1,                          /* number of hw voices */
+    -1                          /* voice size */
+};
+
+/* http://www.df.lth.se/~john_e/gems/gem002d.html */
+/* http://www.multi-platforms.com/Tips/PopCount.htm */
+uint32_t popcount (uint32_t u)
+{
+    u = ((u&0x55555555) + ((u>>1)&0x55555555));
+    u = ((u&0x33333333) + ((u>>2)&0x33333333));
+    u = ((u&0x0f0f0f0f) + ((u>>4)&0x0f0f0f0f));
+    u = ((u&0x00ff00ff) + ((u>>8)&0x00ff00ff));
+    u = ( u&0x0000ffff) + (u>>16);
+    return u;
+}
+
+inline uint32_t lsbindex (uint32_t u)
+{
+    return popcount ((u&-u)-1);
+}
+
+int audio_get_conf_int (const char *key, int defval)
+{
+    int val = defval;
+    char *strval;
+
+    strval = getenv (key);
+    if (strval) {
+        val = atoi (strval);
+    }
+
+    return val;
+}
+
+const char *audio_get_conf_str (const char *key, const char *defval)
+{
+    const char *val = getenv (key);
+    if (!val)
+        return defval;
+    else
+        return val;
+}
+
+void AUD_log (const char *cap, const char *fmt, ...)
+{
+    va_list ap;
+    fprintf (stderr, "%s: ", cap);
+    va_start (ap, fmt);
+    vfprintf (stderr, fmt, ap);
+    va_end (ap);
+}
+
+/*
+ * Soft Voice
+ */
+void pcm_sw_free_resources (SWVoice *sw)
+{
+    if (sw->buf) qemu_free (sw->buf);
+    if (sw->rate) st_rate_stop (sw->rate);
+    sw->buf = NULL;
+    sw->rate = NULL;
+}
+
+int pcm_sw_alloc_resources (SWVoice *sw)
+{
+    sw->buf = qemu_mallocz (sw->hw->samples * sizeof (st_sample_t));
+    if (!sw->buf)
+        return -1;
+
+    sw->rate = st_rate_start (sw->freq, sw->hw->freq);
+    if (!sw->rate) {
+        qemu_free (sw->buf);
+        sw->buf = NULL;
+        return -1;
+    }
+    return 0;
+}
+
+void pcm_sw_fini (SWVoice *sw)
+{
+    pcm_sw_free_resources (sw);
+}
+
+int pcm_sw_init (SWVoice *sw, HWVoice *hw, int freq,
+                 int nchannels, audfmt_e fmt)
+{
+    int bits = 8, sign = 0;
+
+    switch (fmt) {
+    case AUD_FMT_S8:
+        sign = 1;
+    case AUD_FMT_U8:
+        break;
+
+    case AUD_FMT_S16:
+        sign = 1;
+    case AUD_FMT_U16:
+        bits = 16;
+        break;
+    }
+
+    sw->hw = hw;
+    sw->freq = freq;
+    sw->fmt = fmt;
+    sw->nchannels = nchannels;
+    sw->shift = (nchannels == 2) + (bits == 16);
+    sw->align = (1 << sw->shift) - 1;
+    sw->left = 0;
+    sw->pos = 0;
+    sw->wpos = 0;
+    sw->live = 0;
+    sw->ratio = (sw->hw->freq * ((int64_t) INT_MAX)) / sw->freq;
+    sw->bytes_per_second = sw->freq << sw->shift;
+    sw->conv = mixeng_conv[nchannels == 2][sign][bits == 16];
+
+    pcm_sw_free_resources (sw);
+    return pcm_sw_alloc_resources (sw);
+}
+
+/* Hard voice */
+void pcm_hw_free_resources (HWVoice *hw)
+{
+    if (hw->mix_buf)
+        qemu_free (hw->mix_buf);
+    hw->mix_buf = NULL;
+}
+
+int pcm_hw_alloc_resources (HWVoice *hw)
+{
+    hw->mix_buf = qemu_mallocz (hw->samples * sizeof (st_sample_t));
+    if (!hw->mix_buf)
+        return -1;
+    return 0;
+}
+
+void pcm_hw_fini (HWVoice *hw)
+{
+    if (hw->active) {
+        ldebug ("pcm_hw_fini: %d %d %d\n", hw->freq, hw->nchannels, hw->fmt);
+        pcm_hw_free_resources (hw);
+        hw->pcm_ops->fini (hw);
+        memset (hw, 0, audio_state.drv->voice_size);
+    }
+}
+
+void pcm_hw_gc (HWVoice *hw)
+{
+    if (hw->nb_voices)
+        return;
+
+    pcm_hw_fini (hw);
+}
+
+int pcm_hw_get_live (HWVoice *hw)
+{
+    int i, alive = 0, live = hw->samples;
+
+    for (i = 0; i < hw->nb_voices; i++) {
+        if (hw->pvoice[i]->live) {
+            live = audio_MIN (hw->pvoice[i]->live, live);
+            alive += 1;
+        }
+    }
+
+    if (alive)
+        return live;
+    else
+        return -1;
+}
+
+int pcm_hw_get_live2 (HWVoice *hw, int *nb_active)
+{
+    int i, alive = 0, live = hw->samples;
+
+    *nb_active = 0;
+    for (i = 0; i < hw->nb_voices; i++) {
+        if (hw->pvoice[i]->live) {
+            if (hw->pvoice[i]->live < live) {
+                *nb_active = hw->pvoice[i]->active != 0;
+                live = hw->pvoice[i]->live;
+            }
+            alive += 1;
+        }
+    }
+
+    if (alive)
+        return live;
+    else
+        return -1;
+}
+
+void pcm_hw_dec_live (HWVoice *hw, int decr)
+{
+    int i;
+
+    for (i = 0; i < hw->nb_voices; i++) {
+        if (hw->pvoice[i]->live) {
+            hw->pvoice[i]->live -= decr;
+        }
+    }
+}
+
+void pcm_hw_clear (HWVoice *hw, void *buf, int len)
+{
+    if (!len)
+        return;
+
+    switch (hw->fmt) {
+    case AUD_FMT_S16:
+    case AUD_FMT_S8:
+        memset (buf, len << hw->shift, 0x00);
+        break;
+
+    case AUD_FMT_U8:
+        memset (buf, len << hw->shift, 0x80);
+        break;
+
+    case AUD_FMT_U16:
+        {
+            unsigned int i;
+            uint16_t *p = buf;
+            int shift = hw->nchannels - 1;
+
+            for (i = 0; i < len << shift; i++) {
+                p[i] = INT16_MAX;
+            }
+        }
+        break;
+    }
+}
+
+int pcm_hw_write (SWVoice *sw, void *buf, int size)
+{
+    int hwsamples, samples, isamp, osamp, wpos, live, dead, left, swlim, blck;
+    int ret = 0, pos = 0;
+    if (!sw)
+        return size;
+
+    hwsamples = sw->hw->samples;
+    samples = size >> sw->shift;
+
+    if (!sw->live) {
+        sw->wpos = sw->hw->rpos;
+    }
+    wpos = sw->wpos;
+    live = sw->live;
+    dead = hwsamples - live;
+    swlim = (dead * ((int64_t) INT_MAX)) / sw->ratio;
+    swlim = audio_MIN (swlim, samples);
+
+    ldebug ("size=%d live=%d dead=%d swlim=%d wpos=%d\n",
+           size, live, dead, swlim, wpos);
+    if (swlim)
+        sw->conv (sw->buf, buf, swlim);
+
+    while (swlim) {
+        dead = hwsamples - live;
+        left = hwsamples - wpos;
+        blck = audio_MIN (dead, left);
+        if (!blck) {
+            /* dolog ("swlim=%d\n", swlim); */
+            break;
+        }
+        isamp = swlim;
+        osamp = blck;
+        st_rate_flow (sw->rate, sw->buf + pos, sw->hw->mix_buf + wpos, &isamp, 
&osamp);
+        ret += isamp;
+        swlim -= isamp;
+        pos += isamp;
+        live += osamp;
+        wpos = (wpos + osamp) % hwsamples;
+    }
+
+    sw->wpos = wpos;
+    sw->live = live;
+    return ret << sw->shift;
+}
+
+int pcm_hw_init (HWVoice *hw, int freq, int nchannels, audfmt_e fmt)
+{
+    int sign = 0, bits = 8;
+
+    pcm_hw_fini (hw);
+    ldebug ("pcm_hw_init: %d %d %d\n", freq, nchannels, fmt);
+    if (hw->pcm_ops->init (hw, freq, nchannels, fmt)) {
+        memset (hw, 0, audio_state.drv->voice_size);
+        return -1;
+    }
+
+    switch (hw->fmt) {
+    case AUD_FMT_S8:
+        sign = 1;
+    case AUD_FMT_U8:
+        break;
+
+    case AUD_FMT_S16:
+        sign = 1;
+    case AUD_FMT_U16:
+        bits = 16;
+        break;
+    }
+
+    hw->nb_voices = 0;
+    hw->active = 1;
+    hw->shift = (hw->nchannels == 2) + (bits == 16);
+    hw->bytes_per_second = hw->freq << hw->shift;
+    hw->align = (1 << hw->shift) - 1;
+    hw->samples = hw->bufsize >> hw->shift;
+    hw->clip = mixeng_clip[hw->nchannels == 2][sign][bits == 16];
+    if (pcm_hw_alloc_resources (hw)) {
+        pcm_hw_fini (hw);
+        return -1;
+    }
+    return 0;
+}
+
+static int dist (void *hw)
+{
+    if (hw) {
+        return (((uint8_t *) hw - (uint8_t *) hw_voices)
+                / audio_state.voice_size) + 1;
+    }
+    else {
+        return 0;
+    }
+}
+
+#define ADVANCE(hw) hw ? advance (hw, audio_state.voice_size) : hw_voices
+
+HWVoice *pcm_hw_find_any (HWVoice *hw)
+{
+    int i = dist (hw);
+    for (; i < audio_state.nb_hw_voices; i++) {
+        hw = ADVANCE (hw);
+        return hw;
+    }
+    return NULL;
+}
+
+HWVoice *pcm_hw_find_any_active (HWVoice *hw)
+{
+    int i = dist (hw);
+    for (; i < audio_state.nb_hw_voices; i++) {
+        hw = ADVANCE (hw);
+        if (hw->active)
+            return hw;
+    }
+    return NULL;
+}
+
+HWVoice *pcm_hw_find_any_active_enabled (HWVoice *hw)
+{
+    int i = dist (hw);
+    for (; i < audio_state.nb_hw_voices; i++) {
+        hw = ADVANCE (hw);
+        if (hw->active && hw->enabled)
+            return hw;
+    }
+    return NULL;
+}
+
+HWVoice *pcm_hw_find_any_passive (HWVoice *hw)
+{
+    int i = dist (hw);
+    for (; i < audio_state.nb_hw_voices; i++) {
+        hw = ADVANCE (hw);
+        if (!hw->active)
+            return hw;
+    }
+    return NULL;
+}
+
+HWVoice *pcm_hw_find_specific (HWVoice *hw, int freq,
+                               int nchannels, audfmt_e fmt)
+{
+    while ((hw = pcm_hw_find_any_active (hw))) {
+        if (hw->freq == freq &&
+            hw->nchannels == nchannels &&
+            hw->fmt == fmt)
+            return hw;
+    }
+    return NULL;
+}
+
+HWVoice *pcm_hw_add (int freq, int nchannels, audfmt_e fmt)
+{
+    HWVoice *hw;
+
+    if (audio_state.fixed_format) {
+        freq = audio_state.fixed_freq;
+        nchannels = audio_state.fixed_channels;
+        fmt = audio_state.fixed_fmt;
+    }
+
+    hw = pcm_hw_find_specific (NULL, freq, nchannels, fmt);
+
+    if (hw)
+        return hw;
+
+    hw = pcm_hw_find_any_passive (NULL);
+    if (hw) {
+        hw->pcm_ops = audio_state.drv->pcm_ops;
+        if (!hw->pcm_ops)
+            return NULL;
+
+        if (pcm_hw_init (hw, freq, nchannels, fmt)) {
+            pcm_hw_gc (hw);
+            return NULL;
+        }
+        else
+            return hw;
+    }
+
+    return pcm_hw_find_any (NULL);
+}
+
+int pcm_hw_add_sw (HWVoice *hw, SWVoice *sw)
+{
+    SWVoice **pvoice = qemu_mallocz ((hw->nb_voices + 1) * sizeof (sw));
+    if (!pvoice)
+        return -1;
+
+    memcpy (pvoice, hw->pvoice, hw->nb_voices * sizeof (sw));
+    qemu_free (hw->pvoice);
+    hw->pvoice = pvoice;
+    hw->pvoice[hw->nb_voices++] = sw;
+    return 0;
+}
+
+int pcm_hw_del_sw (HWVoice *hw, SWVoice *sw)
+{
+    int i, j;
+    if (hw->nb_voices > 1) {
+        SWVoice **pvoice = qemu_mallocz ((hw->nb_voices - 1) * sizeof (sw));
+
+        if (!pvoice) {
+            dolog ("Can not maintain consistent state (not enough memory)\n");
+            return -1;
+        }
+
+        for (i = 0, j = 0; i < hw->nb_voices; i++) {
+            if (j >= hw->nb_voices - 1) {
+                dolog ("Can not maintain consistent state "
+                       "(invariant violated)\n");
+                return -1;
+            }
+            if (hw->pvoice[i] != sw)
+                pvoice[j++] = hw->pvoice[i];
+        }
+        qemu_free (hw->pvoice);
+        hw->pvoice = pvoice;
+        hw->nb_voices -= 1;
+    }
+    else {
+        qemu_free (hw->pvoice);
+        hw->pvoice = NULL;
+        hw->nb_voices = 0;
+    }
+    return 0;
+}
+
+SWVoice *pcm_create_voice_pair (int freq, int nchannels, audfmt_e fmt)
+{
+    SWVoice *sw;
+    HWVoice *hw;
+
+    sw = qemu_mallocz (sizeof (*sw));
+    if (!sw)
+        goto err1;
+
+    hw = pcm_hw_add (freq, nchannels, fmt);
+    if (!hw)
+        goto err2;
+
+    if (pcm_hw_add_sw (hw, sw))
+        goto err3;
+
+    if (pcm_sw_init (sw, hw, freq, nchannels, fmt))
+        goto err4;
+
+    return sw;
+
+err4:
+    pcm_hw_del_sw (hw, sw);
+err3:
+    pcm_hw_gc (hw);
+err2:
+    qemu_free (sw);
+err1:
+    return NULL;
+}
+
+SWVoice *AUD_open (SWVoice *sw, const char *name,
+                   int freq, int nchannels, audfmt_e fmt)
+{
+    if (!audio_state.drv) {
+        return NULL;
+    }
+
+    if (sw && freq == sw->freq && sw->nchannels == nchannels && sw->fmt == 
fmt) {
+        return sw;
+    }
+
+    if (sw) {
+        ldebug ("Different format %s %d %d %d\n",
+                name,
+                sw->freq == freq,
+                sw->nchannels == nchannels,
+                sw->fmt == fmt);
+    }
+
+    if (nchannels != 1 && nchannels != 2) {
+        dolog ("Bogus channel count %d for voice %s\n", nchannels, name);
+        return NULL;
+    }
+
+    if (!audio_state.fixed_format && sw) {
+        pcm_sw_fini (sw);
+        pcm_hw_del_sw (sw->hw, sw);
+        pcm_hw_gc (sw->hw);
+        if (sw->name) {
+            qemu_free (sw->name);
+            sw->name = NULL;
+        }
+        qemu_free (sw);
+        sw = NULL;
+    }
+
+    if (sw) {
+        HWVoice *hw = sw->hw;
+        if (!hw) {
+            dolog ("Internal logic error voice %s has no hardware store\n",
+                   name);
+            return sw;
+        }
+
+        if (pcm_sw_init (sw, hw, freq, nchannels, fmt)) {
+            pcm_sw_fini (sw);
+            pcm_hw_del_sw (hw, sw);
+            pcm_hw_gc (hw);
+            if (sw->name) {
+                qemu_free (sw->name);
+                sw->name = NULL;
+            }
+            qemu_free (sw);
+            return NULL;
+        }
+    }
+    else {
+        sw = pcm_create_voice_pair (freq, nchannels, fmt);
+        if (!sw) {
+            dolog ("Failed to create voice %s\n", name);
+            return NULL;
+        }
+    }
+
+    if (sw->name) {
+        qemu_free (sw->name);
+        sw->name = NULL;
+    }
+    sw->name = qemu_strdup (name);
+    return sw;
+}
+
+void AUD_close (SWVoice *sw)
+{
+    if (!sw)
+        return;
+
+    pcm_sw_fini (sw);
+    pcm_hw_del_sw (sw->hw, sw);
+    pcm_hw_gc (sw->hw);
+    if (sw->name) {
+        qemu_free (sw->name);
+        sw->name = NULL;
+    }
+    qemu_free (sw);
+}
+
+int AUD_write (SWVoice *sw, void *buf, int size)
+{
+    int bytes;
+
+    if (!sw->hw->enabled)
+        dolog ("Writing to disabled voice %s\n", sw->name);
+    bytes = sw->hw->pcm_ops->write (sw, buf, size);
+    return bytes;
+}
+
+void AUD_run (void)
+{
+    HWVoice *hw = NULL;
+
+    while ((hw = pcm_hw_find_any_active_enabled (hw))) {
+        int i;
+        if (hw->pending_disable && pcm_hw_get_live (hw) <= 0) {
+            hw->enabled = 0;
+            hw->pcm_ops->ctl (hw, VOICE_DISABLE);
+            for (i = 0; i < hw->nb_voices; i++) {
+                hw->pvoice[i]->live = 0;
+                /* hw->pvoice[i]->old_ticks = 0; */
+            }
+            continue;
+        }
+
+        hw->pcm_ops->run (hw);
+        assert (hw->rpos < hw->samples);
+        for (i = 0; i < hw->nb_voices; i++) {
+            SWVoice *sw = hw->pvoice[i];
+            if (!sw->active && !sw->live && sw->old_ticks) {
+                int64_t delta = qemu_get_clock (vm_clock) - sw->old_ticks;
+                if (delta > audio_state.ticks_threshold) {
+                    ldebug ("resetting old_ticks for %s\n", sw->name);
+                    sw->old_ticks = 0;
+                }
+            }
+        }
+    }
+}
+
+int AUD_get_free (SWVoice *sw)
+{
+    int free;
+
+    if (!sw)
+        return 4096;
+
+    free = ((sw->hw->samples - sw->live) << sw->hw->shift) * sw->ratio
+        / INT_MAX;
+
+    free &= ~sw->hw->align;
+    if (!free) return 0;
+
+    return free;
+}
+
+int AUD_get_buffer_size (SWVoice *sw)
+{
+    return sw->hw->bufsize;
+}
+
+void AUD_adjust (SWVoice *sw, int bytes)
+{
+    if (!sw)
+        return;
+    sw->old_ticks += (ticks_per_sec * (int64_t) bytes) / sw->bytes_per_second;
+}
+
+void AUD_reset (SWVoice *sw)
+{
+    sw->active = 0;
+    sw->old_ticks = 0;
+}
+
+int AUD_calc_elapsed (SWVoice *sw)
+{
+    int64_t now, delta, bytes;
+    int dead, swlim;
+
+    if (!sw)
+        return 0;
+
+    now = qemu_get_clock (vm_clock);
+    delta = now - sw->old_ticks;
+    bytes = (delta * sw->bytes_per_second) / ticks_per_sec;
+    if (delta < 0) {
+        dolog ("whoops delta(<0)=%lld\n", delta);
+        return 0;
+    }
+
+    dead = sw->hw->samples - sw->live;
+    swlim = ((dead * (int64_t) INT_MAX) / sw->ratio);
+
+    if (bytes > swlim) {
+        return swlim;
+    }
+    else {
+        return bytes;
+    }
+}
+
+void AUD_enable (SWVoice *sw, int on)
+{
+    int i;
+    HWVoice *hw;
+
+    if (!sw)
+        return;
+
+    hw = sw->hw;
+    if (on) {
+        if (!sw->live)
+            sw->wpos = sw->hw->rpos;
+        if (!sw->old_ticks) {
+            sw->old_ticks = qemu_get_clock (vm_clock);
+        }
+    }
+
+    if (sw->active != on) {
+        if (on) {
+            hw->pending_disable = 0;
+            if (!hw->enabled) {
+                hw->enabled = 1;
+                for (i = 0; i < hw->nb_voices; i++) {
+                    ldebug ("resetting voice\n");
+                    sw = hw->pvoice[i];
+                    sw->old_ticks = qemu_get_clock (vm_clock);
+                }
+                hw->pcm_ops->ctl (hw, VOICE_ENABLE);
+            }
+        }
+        else {
+            if (hw->enabled && !hw->pending_disable) {
+                int nb_active = 0;
+                for (i = 0; i < hw->nb_voices; i++) {
+                    nb_active += hw->pvoice[i]->active != 0;
+                }
+
+                if (nb_active == 1) {
+                    hw->pending_disable = 1;
+                }
+            }
+        }
+        sw->active = on;
+    }
+}
+
+static struct audio_output_driver *drvtab[] = {
+#ifdef CONFIG_OSS
+    &oss_output_driver,
+#endif
+#ifdef CONFIG_FMOD
+    &fmod_output_driver,
+#endif
+#ifdef CONFIG_SDL
+    &sdl_output_driver,
+#endif
+    &no_output_driver,
+#ifdef USE_WAV_AUDIO
+    &wav_output_driver,
+#endif
+};
+
+static int voice_init (struct audio_output_driver *drv)
+{
+    audio_state.opaque = drv->init ();
+    if (audio_state.opaque) {
+        if (audio_state.nb_hw_voices > drv->max_voices) {
+            dolog ("`%s' does not support %d multiple hardware channels\n"
+                   "Resetting to %d\n",
+                   drv->name, audio_state.nb_hw_voices, drv->max_voices);
+            audio_state.nb_hw_voices = drv->max_voices;
+        }
+        hw_voices = qemu_mallocz (audio_state.nb_hw_voices * drv->voice_size);
+        if (hw_voices) {
+            audio_state.drv = drv;
+            return 1;
+        }
+        else {
+            dolog ("Not enough memory for %d `%s' voices (each %d bytes)\n",
+                   audio_state.nb_hw_voices, drv->name, drv->voice_size);
+            drv->fini (audio_state.opaque);
+            return 0;
+        }
+    }
+    else {
+        dolog ("Could not init `%s' audio\n", drv->name);
+        return 0;
+    }
+}
+
+static void audio_vm_stop_handler (void *opaque, int reason)
+{
+    HWVoice *hw = NULL;
+
+    while ((hw = pcm_hw_find_any (hw))) {
+        if (!hw->pcm_ops)
+            continue;
+
+        hw->pcm_ops->ctl (hw, reason ? VOICE_ENABLE : VOICE_DISABLE);
+    }
+}
+
+static void audio_atexit (void)
+{
+    HWVoice *hw = NULL;
+
+    while ((hw = pcm_hw_find_any (hw))) {
+        if (!hw->pcm_ops)
+            continue;
+
+        hw->pcm_ops->ctl (hw, VOICE_DISABLE);
+        hw->pcm_ops->fini (hw);
+    }
+    audio_state.drv->fini (audio_state.opaque);
+}
+
+static void audio_save (QEMUFile *f, void *opaque)
+{
+}
+
+static int audio_load (QEMUFile *f, void *opaque, int version_id)
+{
+    if (version_id != 1)
+        return -EINVAL;
+
+    return 0;
+}
+
+void AUD_init (void)
+{
+    int i;
+    int done = 0;
+    const char *drvname;
+
+    audio_state.fixed_format =
+        !!audio_get_conf_int (QC_FIXED_FORMAT, audio_state.fixed_format);
+    audio_state.fixed_freq =
+        audio_get_conf_int (QC_FIXED_FREQ, audio_state.fixed_freq);
+    audio_state.nb_hw_voices =
+        audio_get_conf_int (QC_VOICES, audio_state.nb_hw_voices);
+
+    if (audio_state.nb_hw_voices <= 0) {
+        dolog ("Bogus number of voices %d, resetting to 1\n",
+               audio_state.nb_hw_voices);
+    }
+
+    drvname = audio_get_conf_str (QC_AUDIO_DRV, NULL);
+    if (drvname) {
+        int found = 0;
+        for (i = 0; i < sizeof (drvtab) / sizeof (drvtab[0]); i++) {
+            if (!strcmp (drvname, drvtab[i]->name)) {
+                done = voice_init (drvtab[i]);
+                found = 1;
+                break;
+            }
+        }
+        if (!found) {
+            dolog ("Unknown audio driver `%s'\n", drvname);
+        }
+    }
+
+    qemu_add_vm_stop_handler (audio_vm_stop_handler, NULL);
+    atexit (audio_atexit);
+
+    if (!done) {
+        for (i = 0; !done && i < sizeof (drvtab) / sizeof (drvtab[0]); i++) {
+            if (drvtab[i]->can_be_default)
+                done = voice_init (drvtab[i]);
+        }
+    }
+
+    audio_state.ticks_threshold = ticks_per_sec / 50;
+    audio_state.freq_threshold = 100;
+
+    register_savevm ("audio", 0, 1, audio_save, audio_load, NULL);
+    if (!done) {
+        dolog ("Can not initialize audio subsystem\n");
+        voice_init (&no_output_driver);
+    }
+}
diff -r 2c75070e41a0 -r 5a790011259e tools/ioemu/audio/audio.h
--- /dev/null   Wed Dec 21 16:30:10 2005
+++ b/tools/ioemu/audio/audio.h Wed Dec 21 17:56:19 2005
@@ -0,0 +1,65 @@
+/*
+ * QEMU Audio subsystem header
+ * 
+ * Copyright (c) 2003-2004 Vassili Karpov (malc)
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#ifndef QEMU_AUDIO_H
+#define QEMU_AUDIO_H
+
+#include "mixeng.h"
+
+typedef enum {
+  AUD_FMT_U8,
+  AUD_FMT_S8,
+  AUD_FMT_U16,
+  AUD_FMT_S16
+} audfmt_e;
+
+typedef struct SWVoice SWVoice;
+
+SWVoice * AUD_open (SWVoice *sw, const char *name, int freq,
+                    int nchannels, audfmt_e fmt);
+void   AUD_init (void);
+void   AUD_log (const char *cap, const char *fmt, ...)
+    __attribute__ ((__format__ (__printf__, 2, 3)));;
+void   AUD_close (SWVoice *sw);
+int    AUD_write (SWVoice *sw, void *pcm_buf, int size);
+void   AUD_adjust (SWVoice *sw, int leftover);
+void   AUD_reset (SWVoice *sw);
+int    AUD_get_free (SWVoice *sw);
+int    AUD_get_buffer_size (SWVoice *sw);
+void   AUD_run (void);
+void   AUD_enable (SWVoice *sw, int on);
+int    AUD_calc_elapsed (SWVoice *sw);
+
+static inline void *advance (void *p, int incr)
+{
+    uint8_t *d = p;
+    return (d + incr);
+}
+
+uint32_t popcount (uint32_t u);
+inline uint32_t lsbindex (uint32_t u);
+
+#define audio_MIN(a, b) ((a)>(b)?(b):(a))
+#define audio_MAX(a, b) ((a)<(b)?(b):(a))
+
+#endif  /* audio.h */
diff -r 2c75070e41a0 -r 5a790011259e tools/ioemu/audio/audio_int.h
--- /dev/null   Wed Dec 21 16:30:10 2005
+++ b/tools/ioemu/audio/audio_int.h     Wed Dec 21 17:56:19 2005
@@ -0,0 +1,164 @@
+/*
+ * QEMU Audio subsystem header
+ * 
+ * Copyright (c) 2003-2004 Vassili Karpov (malc)
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#ifndef QEMU_AUDIO_INT_H
+#define QEMU_AUDIO_INT_H
+
+#include "vl.h"
+
+struct pcm_ops;
+
+typedef struct HWVoice {
+    int active;
+    int enabled;
+    int pending_disable;
+    int valid;
+    int freq;
+
+    f_sample *clip;
+    audfmt_e fmt;
+    int nchannels;
+
+    int align;
+    int shift;
+
+    int rpos;
+    int bufsize;
+
+    int bytes_per_second;
+    st_sample_t *mix_buf;
+
+    int samples;
+    int64_t old_ticks;
+    int nb_voices;
+    struct SWVoice **pvoice;
+    struct pcm_ops *pcm_ops;
+} HWVoice;
+
+extern struct pcm_ops no_pcm_ops;
+extern struct audio_output_driver no_output_driver;
+
+extern struct pcm_ops oss_pcm_ops;
+extern struct audio_output_driver oss_output_driver;
+
+extern struct pcm_ops sdl_pcm_ops;
+extern struct audio_output_driver sdl_output_driver;
+
+extern struct pcm_ops wav_pcm_ops;
+extern struct audio_output_driver wav_output_driver;
+
+extern struct pcm_ops fmod_pcm_ops;
+extern struct audio_output_driver fmod_output_driver;
+
+struct audio_output_driver {
+    const char *name;
+    void *(*init) (void);
+    void (*fini) (void *);
+    struct pcm_ops *pcm_ops;
+    int can_be_default;
+    int max_voices;
+    int voice_size;
+};
+
+typedef struct AudioState {
+    int fixed_format;
+    int fixed_freq;
+    int fixed_channels;
+    int fixed_fmt;
+    int nb_hw_voices;
+    int voice_size;
+    int64_t ticks_threshold;
+    int freq_threshold;
+    void *opaque;
+    struct audio_output_driver *drv;
+} AudioState;
+extern AudioState audio_state;
+
+struct SWVoice {
+    int freq;
+    audfmt_e fmt;
+    int nchannels;
+
+    int shift;
+    int align;
+
+    t_sample *conv;
+
+    int left;
+    int pos;
+    int bytes_per_second;
+    int64_t ratio;
+    st_sample_t *buf;
+    void *rate;
+
+    int wpos;
+    int live;
+    int active;
+    int64_t old_ticks;
+    HWVoice *hw;
+    char *name;
+};
+
+struct pcm_ops {
+    int  (*init)  (HWVoice *hw, int freq, int nchannels, audfmt_e fmt);
+    void (*fini)  (HWVoice *hw);
+    void (*run)   (HWVoice *hw);
+    int  (*write) (SWVoice *sw, void *buf, int size);
+    int  (*ctl)   (HWVoice *hw, int cmd, ...);
+};
+
+void      pcm_sw_free_resources (SWVoice *sw);
+int       pcm_sw_alloc_resources (SWVoice *sw);
+void      pcm_sw_fini (SWVoice *sw);
+int       pcm_sw_init (SWVoice *sw, HWVoice *hw, int freq,
+                       int nchannels, audfmt_e fmt);
+
+void      pcm_hw_clear (HWVoice *hw, void *buf, int len);
+HWVoice * pcm_hw_find_any (HWVoice *hw);
+HWVoice * pcm_hw_find_any_active (HWVoice *hw);
+HWVoice * pcm_hw_find_any_passive (HWVoice *hw);
+HWVoice * pcm_hw_find_specific (HWVoice *hw, int freq,
+                                int nchannels, audfmt_e fmt);
+HWVoice * pcm_hw_add (int freq, int nchannels, audfmt_e fmt);
+int       pcm_hw_add_sw (HWVoice *hw, SWVoice *sw);
+int       pcm_hw_del_sw (HWVoice *hw, SWVoice *sw);
+SWVoice * pcm_create_voice_pair (int freq, int nchannels, audfmt_e fmt);
+
+void      pcm_hw_free_resources (HWVoice *hw);
+int       pcm_hw_alloc_resources (HWVoice *hw);
+void      pcm_hw_fini (HWVoice *hw);
+void      pcm_hw_gc (HWVoice *hw);
+int       pcm_hw_get_live (HWVoice *hw);
+int       pcm_hw_get_live2 (HWVoice *hw, int *nb_active);
+void      pcm_hw_dec_live (HWVoice *hw, int decr);
+int       pcm_hw_write (SWVoice *sw, void *buf, int len);
+
+int         audio_get_conf_int (const char *key, int defval);
+const char *audio_get_conf_str (const char *key, const char *defval);
+
+struct audio_output_driver;
+
+#define VOICE_ENABLE 1
+#define VOICE_DISABLE 2
+
+#endif /* audio_int.h */
diff -r 2c75070e41a0 -r 5a790011259e tools/ioemu/audio/mixeng.c
--- /dev/null   Wed Dec 21 16:30:10 2005
+++ b/tools/ioemu/audio/mixeng.c        Wed Dec 21 17:56:19 2005
@@ -0,0 +1,255 @@
+/*
+ * QEMU Mixing engine
+ *
+ * Copyright (c) 2004 Vassili Karpov (malc)
+ * Copyright (c) 1998 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+//#define DEBUG_FP
+#include "audio/mixeng.h"
+
+#define IN_T int8_t
+#define IN_MIN CHAR_MIN
+#define IN_MAX CHAR_MAX
+#define SIGNED
+#include "mixeng_template.h"
+#undef SIGNED
+#undef IN_MAX
+#undef IN_MIN
+#undef IN_T
+
+#define IN_T uint8_t
+#define IN_MIN 0
+#define IN_MAX UCHAR_MAX
+#include "mixeng_template.h"
+#undef IN_MAX
+#undef IN_MIN
+#undef IN_T
+
+#define IN_T int16_t
+#define IN_MIN SHRT_MIN
+#define IN_MAX SHRT_MAX
+#define SIGNED
+#include "mixeng_template.h"
+#undef SIGNED
+#undef IN_MAX
+#undef IN_MIN
+#undef IN_T
+
+#define IN_T uint16_t
+#define IN_MIN 0
+#define IN_MAX USHRT_MAX
+#include "mixeng_template.h"
+#undef IN_MAX
+#undef IN_MIN
+#undef IN_T
+
+t_sample *mixeng_conv[2][2][2] = {
+    {
+        {
+            conv_uint8_t_to_mono,
+            conv_uint16_t_to_mono
+        },
+        {
+            conv_int8_t_to_mono,
+            conv_int16_t_to_mono
+        }
+    },
+    {
+        {
+            conv_uint8_t_to_stereo,
+            conv_uint16_t_to_stereo
+        },
+        {
+            conv_int8_t_to_stereo,
+            conv_int16_t_to_stereo
+        }
+    }
+};
+
+f_sample *mixeng_clip[2][2][2] = {
+    {
+        {
+            clip_uint8_t_from_mono,
+            clip_uint16_t_from_mono
+        },
+        {
+            clip_int8_t_from_mono,
+            clip_int16_t_from_mono
+        }
+    },
+    {
+        {
+            clip_uint8_t_from_stereo,
+            clip_uint16_t_from_stereo
+        },
+        {
+            clip_int8_t_from_stereo,
+            clip_int16_t_from_stereo
+        }
+    }
+};
+
+/*
+ * August 21, 1998
+ * Copyright 1998 Fabrice Bellard.
+ *
+ * [Rewrote completly the code of Lance Norskog And Sundry
+ * Contributors with a more efficient algorithm.]
+ *
+ * This source code is freely redistributable and may be used for
+ * any purpose.  This copyright notice must be maintained. 
+ * Lance Norskog And Sundry Contributors are not responsible for 
+ * the consequences of using this software.  
+ */
+
+/*
+ * Sound Tools rate change effect file.
+ */
+/*
+ * Linear Interpolation.
+ *
+ * The use of fractional increment allows us to use no buffer. It
+ * avoid the problems at the end of the buffer we had with the old
+ * method which stored a possibly big buffer of size
+ * lcm(in_rate,out_rate).
+ *
+ * Limited to 16 bit samples and sampling frequency <= 65535 Hz. If
+ * the input & output frequencies are equal, a delay of one sample is
+ * introduced.  Limited to processing 32-bit count worth of samples.
+ *
+ * 1 << FRAC_BITS evaluating to zero in several places.  Changed with
+ * an (unsigned long) cast to make it safe.  MarkMLl 2/1/99
+ */
+
+/* Private data */
+typedef struct ratestuff {
+    uint64_t opos;
+    uint64_t opos_inc;
+    uint32_t ipos;              /* position in the input stream (integer) */
+    st_sample_t ilast;          /* last sample in the input stream */
+} *rate_t;
+
+/*
+ * Prepare processing.
+ */
+void *st_rate_start (int inrate, int outrate)
+{
+    rate_t rate = (rate_t) qemu_mallocz (sizeof (struct ratestuff));
+
+    if (!rate) {
+        exit (EXIT_FAILURE);
+    }
+
+    if (inrate == outrate) {
+        // exit (EXIT_FAILURE);
+    }
+
+    if (inrate >= 65535 || outrate >= 65535) {
+        // exit (EXIT_FAILURE);
+    }
+
+    rate->opos = 0;
+
+    /* increment */
+    rate->opos_inc = (inrate * ((int64_t) UINT_MAX)) / outrate;
+
+    rate->ipos = 0;
+    rate->ilast.l = 0;
+    rate->ilast.r = 0;
+    return rate;
+}
+
+/*
+ * Processed signed long samples from ibuf to obuf.
+ * Return number of samples processed.
+ */
+void st_rate_flow (void *opaque, st_sample_t *ibuf, st_sample_t *obuf,
+                   int *isamp, int *osamp)
+{
+    rate_t rate = (rate_t) opaque;
+    st_sample_t *istart, *iend;
+    st_sample_t *ostart, *oend;
+    st_sample_t ilast, icur, out;
+    int64_t t;
+
+    ilast = rate->ilast;
+
+    istart = ibuf;
+    iend = ibuf + *isamp;
+
+    ostart = obuf;
+    oend = obuf + *osamp;
+
+    if (rate->opos_inc == 1ULL << 32) {
+        int i, n = *isamp > *osamp ? *osamp : *isamp;
+        for (i = 0; i < n; i++) {
+            obuf[i].l += ibuf[i].r;
+            obuf[i].r += ibuf[i].r;
+        }
+        *isamp = n;
+        *osamp = n;
+        return;
+    }
+
+    while (obuf < oend) {
+
+        /* Safety catch to make sure we have input samples.  */
+        if (ibuf >= iend)
+            break;
+
+        /* read as many input samples so that ipos > opos */
+
+        while (rate->ipos <= (rate->opos >> 32)) {
+            ilast = *ibuf++;
+            rate->ipos++;
+            /* See if we finished the input buffer yet */
+            if (ibuf >= iend) goto the_end;
+        }
+
+        icur = *ibuf;
+
+        /* interpolate */
+        t = rate->opos & 0xffffffff;
+        out.l = (ilast.l * (INT_MAX - t) + icur.l * t) / INT_MAX;
+        out.r = (ilast.r * (INT_MAX - t) + icur.r * t) / INT_MAX;
+
+        /* output sample & increment position */
+#if 0
+        *obuf++ = out;
+#else
+        obuf->l += out.l;
+        obuf->r += out.r;
+        obuf += 1;
+#endif
+        rate->opos += rate->opos_inc;
+    }
+
+the_end:
+    *isamp = ibuf - istart;
+    *osamp = obuf - ostart;
+    rate->ilast = ilast;
+}
+
+void st_rate_stop (void *opaque)
+{
+    qemu_free (opaque);
+}
diff -r 2c75070e41a0 -r 5a790011259e tools/ioemu/audio/mixeng.h
--- /dev/null   Wed Dec 21 16:30:10 2005
+++ b/tools/ioemu/audio/mixeng.h        Wed Dec 21 17:56:19 2005
@@ -0,0 +1,39 @@
+/*
+ * QEMU Mixing engine header
+ * 
+ * Copyright (c) 2004 Vassili Karpov (malc)
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#ifndef QEMU_MIXENG_H
+#define QEMU_MIXENG_H
+
+typedef void (t_sample) (void *dst, const void *src, int samples);
+typedef void (f_sample) (void *dst, const void *src, int samples);
+typedef struct { int64_t l; int64_t r; } st_sample_t;
+
+extern t_sample *mixeng_conv[2][2][2];
+extern f_sample *mixeng_clip[2][2][2];
+
+void *st_rate_start (int inrate, int outrate);
+void st_rate_flow (void *opaque, st_sample_t *ibuf, st_sample_t *obuf,
+                   int *isamp, int *osamp);
+void st_rate_stop (void *opaque);
+
+#endif  /* mixeng.h */
diff -r 2c75070e41a0 -r 5a790011259e tools/ioemu/audio/mixeng_template.h
--- /dev/null   Wed Dec 21 16:30:10 2005
+++ b/tools/ioemu/audio/mixeng_template.h       Wed Dec 21 17:56:19 2005
@@ -0,0 +1,111 @@
+/*
+ * QEMU Mixing engine
+ * 
+ * Copyright (c) 2004 Vassili Karpov (malc)
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/*
+ * Tusen tack till Mike Nordell
+ * dec++'ified by Dscho
+ */
+
+#ifdef SIGNED
+#define HALFT IN_MAX
+#define HALF IN_MAX
+#else
+#define HALFT ((IN_MAX)>>1)
+#define HALF HALFT
+#endif
+
+static int64_t inline glue(conv_,IN_T) (IN_T v)
+{
+#ifdef SIGNED
+    return (INT_MAX*(int64_t)v)/HALF;
+#else
+    return (INT_MAX*((int64_t)v-HALFT))/HALF;
+#endif
+}
+
+static IN_T inline glue(clip_,IN_T) (int64_t v)
+{
+    if (v >= INT_MAX)
+        return IN_MAX;
+    else if (v < -INT_MAX)
+        return IN_MIN;
+
+#ifdef SIGNED
+    return (IN_T) (v*HALF/INT_MAX);
+#else
+    return (IN_T) (v+INT_MAX/2)*HALF/INT_MAX;
+#endif
+}
+
+static void glue(glue(conv_,IN_T),_to_stereo) (void *dst, const void *src,
+                                               int samples)
+{
+    st_sample_t *out = (st_sample_t *) dst;
+    IN_T *in = (IN_T *) src;
+    while (samples--) {
+        out->l = glue(conv_,IN_T) (*in++);
+        out->r = glue(conv_,IN_T) (*in++);
+        out += 1;
+    }
+}
+
+static void glue(glue(conv_,IN_T),_to_mono) (void *dst, const void *src,
+                                             int samples)
+{
+    st_sample_t *out = (st_sample_t *) dst;
+    IN_T *in = (IN_T *) src;
+    while (samples--) {
+        out->l = glue(conv_,IN_T) (in[0]);
+        out->r = out->l;
+        out += 1;
+        in += 1;
+    }
+}
+
+static void glue(glue(clip_,IN_T),_from_stereo) (void *dst, const void *src,
+                                                 int samples)
+{
+    st_sample_t *in = (st_sample_t *) src;
+    IN_T *out = (IN_T *) dst;
+    while (samples--) {
+        *out++ = glue(clip_,IN_T) (in->l);
+        *out++ = glue(clip_,IN_T) (in->r);
+        in += 1;
+    }
+}
+
+static void glue(glue(clip_,IN_T),_from_mono) (void *dst, const void *src,
+                                               int samples)
+{
+    st_sample_t *in = (st_sample_t *) src;
+    IN_T *out = (IN_T *) dst;
+    while (samples--) {
+        *out++ = glue(clip_,IN_T) (in->l + in->r);
+        in += 1;
+    }
+}
+
+#undef HALF
+#undef HALFT
+
diff -r 2c75070e41a0 -r 5a790011259e tools/ioemu/audio/noaudio.c
--- /dev/null   Wed Dec 21 16:30:10 2005
+++ b/tools/ioemu/audio/noaudio.c       Wed Dec 21 17:56:19 2005
@@ -0,0 +1,130 @@
+/*
+ * QEMU NULL audio output driver
+ * 
+ * Copyright (c) 2004 Vassili Karpov (malc)
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+
+#include "audio/audio_int.h"
+
+typedef struct NoVoice {
+    HWVoice hw;
+    int64_t old_ticks;
+} NoVoice;
+
+#define dolog(...) AUD_log ("noaudio", __VA_ARGS__)
+#ifdef DEBUG
+#define ldebug(...) dolog (__VA_ARGS__)
+#else
+#define ldebug(...)
+#endif
+
+static void no_hw_run (HWVoice *hw)
+{
+    NoVoice *no = (NoVoice *) hw;
+    int rpos, live, decr, samples;
+    uint8_t *dst;
+    st_sample_t *src;
+    int64_t now = qemu_get_clock (vm_clock);
+    int64_t ticks = now - no->old_ticks;
+    int64_t bytes = (ticks * hw->bytes_per_second) / ticks_per_sec;
+
+    if (bytes > INT_MAX)
+        samples = INT_MAX >> hw->shift;
+    else
+        samples = bytes >> hw->shift;
+
+    live = pcm_hw_get_live (hw);
+    if (live <= 0)
+        return;
+
+    no->old_ticks = now;
+    decr = audio_MIN (live, samples);
+    samples = decr;
+    rpos = hw->rpos;
+    while (samples) {
+        int left_till_end_samples = hw->samples - rpos;
+        int convert_samples = audio_MIN (samples, left_till_end_samples);
+
+        src = advance (hw->mix_buf, rpos * sizeof (st_sample_t));
+        memset (src, 0, convert_samples * sizeof (st_sample_t));
+
+        rpos = (rpos + convert_samples) % hw->samples;
+        samples -= convert_samples;
+    }
+
+    pcm_hw_dec_live (hw, decr);
+    hw->rpos = rpos;
+}
+
+static int no_hw_write (SWVoice *sw, void *buf, int len)
+{
+    return pcm_hw_write (sw, buf, len);
+}
+
+static int no_hw_init (HWVoice *hw, int freq, int nchannels, audfmt_e fmt)
+{
+    NoVoice *no = (NoVoice *) hw;
+    hw->freq = freq;
+    hw->nchannels = nchannels;
+    hw->fmt = fmt;
+    hw->bufsize = 4096;
+    return 0;
+}
+
+static void no_hw_fini (HWVoice *hw)
+{
+    (void) hw;
+}
+
+static int no_hw_ctl (HWVoice *hw, int cmd, ...)
+{
+    (void) hw;
+    (void) cmd;
+    return 0;
+}
+
+static void *no_audio_init (void)
+{
+    return &no_audio_init;
+}
+
+static void no_audio_fini (void *opaque)
+{
+}
+
+struct pcm_ops no_pcm_ops = {
+    no_hw_init,
+    no_hw_fini,
+    no_hw_run,
+    no_hw_write,
+    no_hw_ctl
+};
+
+struct audio_output_driver no_output_driver = {
+    "none",
+    no_audio_init,
+    no_audio_fini,
+    &no_pcm_ops,
+    1,
+    1,
+    sizeof (NoVoice)
+};
diff -r 2c75070e41a0 -r 5a790011259e tools/ioemu/audio/ossaudio.c
--- /dev/null   Wed Dec 21 16:30:10 2005
+++ b/tools/ioemu/audio/ossaudio.c      Wed Dec 21 17:56:19 2005
@@ -0,0 +1,475 @@
+/*
+ * QEMU OSS audio output driver
+ * 
+ * Copyright (c) 2003-2004 Vassili Karpov (malc)
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/soundcard.h>
+#include <assert.h>
+#include "vl.h"
+
+#include "audio/audio_int.h"
+
+typedef struct OSSVoice {
+    HWVoice hw;
+    void *pcm_buf;
+    int fd;
+    int nfrags;
+    int fragsize;
+    int mmapped;
+    int old_optr;
+} OSSVoice;
+
+#define dolog(...) AUD_log ("oss", __VA_ARGS__)
+#ifdef DEBUG
+#define ldebug(...) dolog (__VA_ARGS__)
+#else
+#define ldebug(...)
+#endif
+
+#define QC_OSS_FRAGSIZE "QEMU_OSS_FRAGSIZE"
+#define QC_OSS_NFRAGS   "QEMU_OSS_NFRAGS"
+#define QC_OSS_MMAP     "QEMU_OSS_MMAP"
+#define QC_OSS_DEV      "QEMU_OSS_DEV"
+
+#define errstr() strerror (errno)
+
+static struct {
+    int try_mmap;
+    int nfrags;
+    int fragsize;
+    const char *dspname;
+} conf = {
+    .try_mmap = 0,
+    .nfrags = 4,
+    .fragsize = 4096,
+    .dspname = "/dev/dsp"
+};
+
+struct oss_params {
+    int freq;
+    audfmt_e fmt;
+    int nchannels;
+    int nfrags;
+    int fragsize;
+};
+
+static int oss_hw_write (SWVoice *sw, void *buf, int len)
+{
+    return pcm_hw_write (sw, buf, len);
+}
+
+static int AUD_to_ossfmt (audfmt_e fmt)
+{
+    switch (fmt) {
+    case AUD_FMT_S8: return AFMT_S8;
+    case AUD_FMT_U8: return AFMT_U8;
+    case AUD_FMT_S16: return AFMT_S16_LE;
+    case AUD_FMT_U16: return AFMT_U16_LE;
+    default:
+        dolog ("Internal logic error: Bad audio format %d\nAborting\n", fmt);
+        exit (EXIT_FAILURE);
+    }
+}
+
+static int oss_to_audfmt (int fmt)
+{
+    switch (fmt) {
+    case AFMT_S8: return AUD_FMT_S8;
+    case AFMT_U8: return AUD_FMT_U8;
+    case AFMT_S16_LE: return AUD_FMT_S16;
+    case AFMT_U16_LE: return AUD_FMT_U16;
+    default:
+        dolog ("Internal logic error: Unrecognized OSS audio format %d\n"
+               "Aborting\n",
+               fmt);
+        exit (EXIT_FAILURE);
+    }
+}
+
+#ifdef DEBUG_PCM
+static void oss_dump_pcm_info (struct oss_params *req, struct oss_params *obt)
+{
+    dolog ("parameter | requested value | obtained value\n");
+    dolog ("format    |      %10d |     %10d\n", req->fmt, obt->fmt);
+    dolog ("channels  |      %10d |     %10d\n", req->nchannels, 
obt->nchannels);
+    dolog ("frequency |      %10d |     %10d\n", req->freq, obt->freq);
+    dolog ("nfrags    |      %10d |     %10d\n", req->nfrags, obt->nfrags);
+    dolog ("fragsize  |      %10d |     %10d\n", req->fragsize, obt->fragsize);
+}
+#endif
+
+static int oss_open (struct oss_params *req, struct oss_params *obt, int *pfd)
+{
+    int fd;
+    int mmmmssss;
+    audio_buf_info abinfo;
+    int fmt, freq, nchannels;
+    const char *dspname = conf.dspname;
+
+    fd = open (dspname, O_RDWR | O_NONBLOCK);
+    if (-1 == fd) {
+        dolog ("Could not initialize audio hardware. Failed to open `%s':\n"
+               "Reason:%s\n",
+               dspname,
+               errstr ());
+        return -1;
+    }
+
+    freq = req->freq;
+    nchannels = req->nchannels;
+    fmt = req->fmt;
+
+    if (ioctl (fd, SNDCTL_DSP_SAMPLESIZE, &fmt)) {
+        dolog ("Could not initialize audio hardware\n"
+               "Failed to set sample size\n"
+               "Reason: %s\n",
+               errstr ());
+        goto err;
+    }
+
+    if (ioctl (fd, SNDCTL_DSP_CHANNELS, &nchannels)) {
+        dolog ("Could not initialize audio hardware\n"
+               "Failed to set number of channels\n"
+               "Reason: %s\n",
+               errstr ());
+        goto err;
+    }
+
+    if (ioctl (fd, SNDCTL_DSP_SPEED, &freq)) {
+        dolog ("Could not initialize audio hardware\n"
+               "Failed to set frequency\n"
+               "Reason: %s\n",
+               errstr ());
+        goto err;
+    }
+
+    if (ioctl (fd, SNDCTL_DSP_NONBLOCK)) {
+        dolog ("Could not initialize audio hardware\n"
+               "Failed to set non-blocking mode\n"
+               "Reason: %s\n",
+               errstr ());
+        goto err;
+    }
+
+    mmmmssss = (req->nfrags << 16) | lsbindex (req->fragsize);
+    if (ioctl (fd, SNDCTL_DSP_SETFRAGMENT, &mmmmssss)) {
+        dolog ("Could not initialize audio hardware\n"
+               "Failed to set buffer length (%d, %d)\n"
+               "Reason:%s\n",
+               conf.nfrags, conf.fragsize,
+               errstr ());
+        goto err;
+    }
+
+    if (ioctl (fd, SNDCTL_DSP_GETOSPACE, &abinfo)) {
+        dolog ("Could not initialize audio hardware\n"
+               "Failed to get buffer length\n"
+               "Reason:%s\n",
+               errstr ());
+        goto err;
+    }
+
+    obt->fmt = fmt;
+    obt->nchannels = nchannels;
+    obt->freq = freq;
+    obt->nfrags = abinfo.fragstotal;
+    obt->fragsize = abinfo.fragsize;
+    *pfd = fd;
+
+    if ((req->fmt != obt->fmt) ||
+        (req->nchannels != obt->nchannels) ||
+        (req->freq != obt->freq) ||
+        (req->fragsize != obt->fragsize) ||
+        (req->nfrags != obt->nfrags)) {
+#ifdef DEBUG_PCM
+        dolog ("Audio parameters mismatch\n");
+        oss_dump_pcm_info (req, obt);
+#endif
+    }
+
+#ifdef DEBUG_PCM
+    oss_dump_pcm_info (req, obt);
+#endif
+    return 0;
+
+err:
+    close (fd);
+    return -1;
+}
+
+static void oss_hw_run (HWVoice *hw)
+{
+    OSSVoice *oss = (OSSVoice *) hw;
+    int err, rpos, live, decr;
+    int samples;
+    uint8_t *dst;
+    st_sample_t *src;
+    struct audio_buf_info abinfo;
+    struct count_info cntinfo;
+
+    live = pcm_hw_get_live (hw);
+    if (live <= 0)
+        return;
+
+    if (oss->mmapped) {
+        int bytes;
+
+        err = ioctl (oss->fd, SNDCTL_DSP_GETOPTR, &cntinfo);
+        if (err < 0) {
+            dolog ("SNDCTL_DSP_GETOPTR failed\nReason: %s\n", errstr ());
+            return;
+        }
+
+        if (cntinfo.ptr == oss->old_optr) {
+            if (abs (hw->samples - live) < 64)
+                dolog ("overrun\n");
+            return;
+        }
+
+        if (cntinfo.ptr > oss->old_optr) {
+            bytes = cntinfo.ptr - oss->old_optr;
+        }
+        else {
+            bytes = hw->bufsize + cntinfo.ptr - oss->old_optr;
+        }
+
+        decr = audio_MIN (bytes >> hw->shift, live);
+    }
+    else {
+        err = ioctl (oss->fd, SNDCTL_DSP_GETOSPACE, &abinfo);
+        if (err < 0) {
+            dolog ("SNDCTL_DSP_GETOSPACE failed\nReason: %s\n", errstr ());
+            return;
+        }
+
+        decr = audio_MIN (abinfo.bytes >> hw->shift, live);
+        if (decr <= 0)
+            return;
+    }
+
+    samples = decr;
+    rpos = hw->rpos;
+    while (samples) {
+        int left_till_end_samples = hw->samples - rpos;
+        int convert_samples = audio_MIN (samples, left_till_end_samples);
+
+        src = advance (hw->mix_buf, rpos * sizeof (st_sample_t));
+        dst = advance (oss->pcm_buf, rpos << hw->shift);
+
+        hw->clip (dst, src, convert_samples);
+        if (!oss->mmapped) {
+            int written;
+
+            written = write (oss->fd, dst, convert_samples << hw->shift);
+            /* XXX: follow errno recommendations ? */
+            if (written == -1) {
+                dolog ("Failed to write audio\nReason: %s\n", errstr ());
+                continue;
+            }
+
+            if (written != convert_samples << hw->shift) {
+                int wsamples = written >> hw->shift;
+                int wbytes = wsamples << hw->shift;
+                if (wbytes != written) {
+                    dolog ("Unaligned write %d, %d\n", wbytes, written);
+                }
+                memset (src, 0, wbytes);
+                decr -= samples;
+                rpos = (rpos + wsamples) % hw->samples;
+                break;
+            }
+        }
+        memset (src, 0, convert_samples * sizeof (st_sample_t));
+
+        rpos = (rpos + convert_samples) % hw->samples;
+        samples -= convert_samples;
+    }
+    if (oss->mmapped) {
+        oss->old_optr = cntinfo.ptr;
+    }
+
+    pcm_hw_dec_live (hw, decr);
+    hw->rpos = rpos;
+}
+
+static void oss_hw_fini (HWVoice *hw)
+{
+    int err;
+    OSSVoice *oss = (OSSVoice *) hw;
+
+    ldebug ("oss_hw_fini\n");
+    err = close (oss->fd);
+    if (err) {
+        dolog ("Failed to close OSS descriptor\nReason: %s\n", errstr ());
+    }
+    oss->fd = -1;
+
+    if (oss->pcm_buf) {
+        if (oss->mmapped) {
+            err = munmap (oss->pcm_buf, hw->bufsize);
+            if (err) {
+                dolog ("Failed to unmap OSS buffer\nReason: %s\n",
+                       errstr ());
+            }
+        }
+        else {
+            qemu_free (oss->pcm_buf);
+        }
+        oss->pcm_buf = NULL;
+    }
+}
+
+static int oss_hw_init (HWVoice *hw, int freq, int nchannels, audfmt_e fmt)
+{
+    OSSVoice *oss = (OSSVoice *) hw;
+    struct oss_params req, obt;
+
+    assert (!oss->fd);
+    req.fmt = AUD_to_ossfmt (fmt);
+    req.freq = freq;
+    req.nchannels = nchannels;
+    req.fragsize = conf.fragsize;
+    req.nfrags = conf.nfrags;
+
+    if (oss_open (&req, &obt, &oss->fd))
+        return -1;
+
+    hw->freq = obt.freq;
+    hw->fmt = oss_to_audfmt (obt.fmt);
+    hw->nchannels = obt.nchannels;
+
+    oss->nfrags = obt.nfrags;
+    oss->fragsize = obt.fragsize;
+    hw->bufsize = obt.nfrags * obt.fragsize;
+
+    oss->mmapped = 0;
+    if (conf.try_mmap) {
+        oss->pcm_buf = mmap (0, hw->bufsize, PROT_READ | PROT_WRITE,
+                             MAP_SHARED, oss->fd, 0);
+        if (oss->pcm_buf == MAP_FAILED) {
+            dolog ("Failed to mmap OSS device\nReason: %s\n",
+                   errstr ());
+        } else {
+            int err;
+            int trig = 0;
+            if (ioctl (oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) {
+                dolog ("SNDCTL_DSP_SETTRIGGER 0 failed\nReason: %s\n",
+                       errstr ());
+            }
+            else {
+                trig = PCM_ENABLE_OUTPUT;
+                if (ioctl (oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) {
+                    dolog ("SNDCTL_DSP_SETTRIGGER PCM_ENABLE_OUTPUT failed\n"
+                           "Reason: %s\n", errstr ());
+                }
+                else {
+                    oss->mmapped = 1;
+                }
+            }
+
+            if (!oss->mmapped) {
+                err = munmap (oss->pcm_buf, hw->bufsize);
+                if (err) {
+                    dolog ("Failed to unmap OSS device\nReason: %s\n",
+                           errstr ());
+                }
+            }
+        }
+    }
+
+    if (!oss->mmapped) {
+        oss->pcm_buf = qemu_mallocz (hw->bufsize);
+        if (!oss->pcm_buf) {
+            close (oss->fd);
+            oss->fd = -1;
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+static int oss_hw_ctl (HWVoice *hw, int cmd, ...)
+{
+    int trig;
+    OSSVoice *oss = (OSSVoice *) hw;
+
+    if (!oss->mmapped)
+        return 0;
+
+    switch (cmd) {
+    case VOICE_ENABLE:
+        ldebug ("enabling voice\n");
+        pcm_hw_clear (hw, oss->pcm_buf, hw->samples);
+        trig = PCM_ENABLE_OUTPUT;
+        if (ioctl (oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) {
+            dolog ("SNDCTL_DSP_SETTRIGGER PCM_ENABLE_OUTPUT failed\n"
+                   "Reason: %s\n", errstr ());
+            return -1;
+        }
+        break;
+
+    case VOICE_DISABLE:
+        ldebug ("disabling voice\n");
+        trig = 0;
+        if (ioctl (oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) {
+            dolog ("SNDCTL_DSP_SETTRIGGER 0 failed\nReason: %s\n",
+                   errstr ());
+            return -1;
+        }
+        break;
+    }
+    return 0;
+}
+
+static void *oss_audio_init (void)
+{
+    conf.fragsize = audio_get_conf_int (QC_OSS_FRAGSIZE, conf.fragsize);
+    conf.nfrags = audio_get_conf_int (QC_OSS_NFRAGS, conf.nfrags);
+    conf.try_mmap = audio_get_conf_int (QC_OSS_MMAP, conf.try_mmap);
+    conf.dspname = audio_get_conf_str (QC_OSS_DEV, conf.dspname);
+    return &conf;
+}
+
+static void oss_audio_fini (void *opaque)
+{
+}
+
+struct pcm_ops oss_pcm_ops = {
+    oss_hw_init,
+    oss_hw_fini,
+    oss_hw_run,
+    oss_hw_write,
+    oss_hw_ctl
+};
+
+struct audio_output_driver oss_output_driver = {
+    "oss",
+    oss_audio_init,
+    oss_audio_fini,
+    &oss_pcm_ops,
+    1,
+    INT_MAX,
+    sizeof (OSSVoice)
+};
diff -r 2c75070e41a0 -r 5a790011259e tools/ioemu/audio/sdlaudio.c
--- /dev/null   Wed Dec 21 16:30:10 2005
+++ b/tools/ioemu/audio/sdlaudio.c      Wed Dec 21 17:56:19 2005
@@ -0,0 +1,332 @@
+/*
+ * QEMU SDL audio output driver
+ * 
+ * Copyright (c) 2004 Vassili Karpov (malc)
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include <SDL.h>
+#include <SDL_thread.h>
+#include "vl.h"
+
+#include "audio/audio_int.h"
+
+typedef struct SDLVoice {
+    HWVoice hw;
+} SDLVoice;
+
+#define dolog(...) AUD_log ("sdl", __VA_ARGS__)
+#ifdef DEBUG
+#define ldebug(...) dolog (__VA_ARGS__)
+#else
+#define ldebug(...)
+#endif
+
+#define QC_SDL_SAMPLES "QEMU_SDL_SAMPLES"
+
+#define errstr() SDL_GetError ()
+
+static struct {
+    int nb_samples;
+} conf = {
+    1024
+};
+
+struct SDLAudioState {
+    int exit;
+    SDL_mutex *mutex;
+    SDL_sem *sem;
+    int initialized;
+} glob_sdl;
+typedef struct SDLAudioState SDLAudioState;
+
+static void sdl_hw_run (HWVoice *hw)
+{
+    (void) hw;
+}
+
+static int sdl_lock (SDLAudioState *s)
+{
+    if (SDL_LockMutex (s->mutex)) {
+        dolog ("SDL_LockMutex failed\nReason: %s\n", errstr ());
+        return -1;
+    }
+    return 0;
+}
+
+static int sdl_unlock (SDLAudioState *s)
+{
+    if (SDL_UnlockMutex (s->mutex)) {
+        dolog ("SDL_UnlockMutex failed\nReason: %s\n", errstr ());
+        return -1;
+    }
+    return 0;
+}
+
+static int sdl_post (SDLAudioState *s)
+{
+    if (SDL_SemPost (s->sem)) {
+        dolog ("SDL_SemPost failed\nReason: %s\n", errstr ());
+        return -1;
+    }
+    return 0;
+}
+
+static int sdl_wait (SDLAudioState *s)
+{
+    if (SDL_SemWait (s->sem)) {
+        dolog ("SDL_SemWait failed\nReason: %s\n", errstr ());
+        return -1;
+    }
+    return 0;
+}
+
+static int sdl_unlock_and_post (SDLAudioState *s)
+{
+    if (sdl_unlock (s))
+        return -1;
+
+    return sdl_post (s);
+}
+
+static int sdl_hw_write (SWVoice *sw, void *buf, int len)
+{
+    int ret;
+    SDLAudioState *s = &glob_sdl;
+    sdl_lock (s);
+    ret = pcm_hw_write (sw, buf, len);
+    sdl_unlock_and_post (s);
+    return ret;
+}
+
+static int AUD_to_sdlfmt (audfmt_e fmt, int *shift)
+{
+    *shift = 0;
+    switch (fmt) {
+    case AUD_FMT_S8: return AUDIO_S8;
+    case AUD_FMT_U8: return AUDIO_U8;
+    case AUD_FMT_S16: *shift = 1; return AUDIO_S16LSB;
+    case AUD_FMT_U16: *shift = 1; return AUDIO_U16LSB;
+    default:
+        dolog ("Internal logic error: Bad audio format %d\nAborting\n", fmt);
+        exit (EXIT_FAILURE);
+    }
+}
+
+static int sdl_to_audfmt (int fmt)
+{
+    switch (fmt) {
+    case AUDIO_S8: return AUD_FMT_S8;
+    case AUDIO_U8: return AUD_FMT_U8;
+    case AUDIO_S16LSB: return AUD_FMT_S16;
+    case AUDIO_U16LSB: return AUD_FMT_U16;
+    default:
+        dolog ("Internal logic error: Unrecognized SDL audio format %d\n"
+               "Aborting\n", fmt);
+        exit (EXIT_FAILURE);
+    }
+}
+
+static int sdl_open (SDL_AudioSpec *req, SDL_AudioSpec *obt)
+{
+    int status;
+
+    status = SDL_OpenAudio (req, obt);
+    if (status) {
+        dolog ("SDL_OpenAudio failed\nReason: %s\n", errstr ());
+    }
+    return status;
+}
+
+static void sdl_close (SDLAudioState *s)
+{
+    if (s->initialized) {
+        sdl_lock (s);
+        s->exit = 1;
+        sdl_unlock_and_post (s);
+        SDL_PauseAudio (1);
+        SDL_CloseAudio ();
+        s->initialized = 0;
+    }
+}
+
+static void sdl_callback (void *opaque, Uint8 *buf, int len)
+{
+    SDLVoice *sdl = opaque;
+    SDLAudioState *s = &glob_sdl;
+    HWVoice *hw = &sdl->hw;
+    int samples = len >> hw->shift;
+
+    if (s->exit) {
+        return;
+    }
+
+    while (samples) {
+        int to_mix, live, decr;
+
+        /* dolog ("in callback samples=%d\n", samples); */
+        sdl_wait (s);
+        if (s->exit) {
+            return;
+        }
+
+        sdl_lock (s);
+        live = pcm_hw_get_live (hw);
+        if (live <= 0)
+            goto again;
+
+        /* dolog ("in callback live=%d\n", live); */
+        to_mix = audio_MIN (samples, live);
+        decr = to_mix;
+        while (to_mix) {
+            int chunk = audio_MIN (to_mix, hw->samples - hw->rpos);
+            st_sample_t *src = hw->mix_buf + hw->rpos;
+
+            /* dolog ("in callback to_mix %d, chunk %d\n", to_mix, chunk); */
+            hw->clip (buf, src, chunk);
+            memset (src, 0, chunk * sizeof (st_sample_t));
+            hw->rpos = (hw->rpos + chunk) % hw->samples;
+            to_mix -= chunk;
+            buf += chunk << hw->shift;
+        }
+        samples -= decr;
+        pcm_hw_dec_live (hw, decr);
+
+    again:
+        sdl_unlock (s);
+    }
+    /* dolog ("done len=%d\n", len); */
+}
+
+static void sdl_hw_fini (HWVoice *hw)
+{
+    ldebug ("sdl_hw_fini %d fixed=%d\n",
+             glob_sdl.initialized, audio_conf.fixed_format);
+    sdl_close (&glob_sdl);
+}
+
+static int sdl_hw_init (HWVoice *hw, int freq, int nchannels, audfmt_e fmt)
+{
+    SDLVoice *sdl = (SDLVoice *) hw;
+    SDLAudioState *s = &glob_sdl;
+    SDL_AudioSpec req, obt;
+    int shift;
+
+    ldebug ("sdl_hw_init %d freq=%d fixed=%d\n",
+            s->initialized, freq, audio_conf.fixed_format);
+
+    if (nchannels != 2) {
+        dolog ("Bogus channel count %d\n", nchannels);
+        return -1;
+    }
+
+    req.freq = freq;
+    req.format = AUD_to_sdlfmt (fmt, &shift);
+    req.channels = nchannels;
+    req.samples = conf.nb_samples;
+    shift <<= nchannels == 2;
+
+    req.callback = sdl_callback;
+    req.userdata = sdl;
+
+    if (sdl_open (&req, &obt))
+        return -1;
+
+    hw->freq = obt.freq;
+    hw->fmt = sdl_to_audfmt (obt.format);
+    hw->nchannels = obt.channels;
+    hw->bufsize = obt.samples << shift;
+
+    s->initialized = 1;
+    s->exit = 0;
+    SDL_PauseAudio (0);
+    return 0;
+}
+
+static int sdl_hw_ctl (HWVoice *hw, int cmd, ...)
+{
+    (void) hw;
+
+    switch (cmd) {
+    case VOICE_ENABLE:
+        SDL_PauseAudio (0);
+        break;
+
+    case VOICE_DISABLE:
+        SDL_PauseAudio (1);
+        break;
+    }
+    return 0;
+}
+
+static void *sdl_audio_init (void)
+{
+    SDLAudioState *s = &glob_sdl;
+    conf.nb_samples = audio_get_conf_int (QC_SDL_SAMPLES, conf.nb_samples);
+
+    if (SDL_InitSubSystem (SDL_INIT_AUDIO)) {
+        dolog ("SDL failed to initialize audio subsystem\nReason: %s\n",
+               errstr ());
+        return NULL;
+    }
+
+    s->mutex = SDL_CreateMutex ();
+    if (!s->mutex) {
+        dolog ("Failed to create SDL mutex\nReason: %s\n", errstr ());
+        SDL_QuitSubSystem (SDL_INIT_AUDIO);
+        return NULL;
+    }
+
+    s->sem = SDL_CreateSemaphore (0);
+    if (!s->sem) {
+        dolog ("Failed to create SDL semaphore\nReason: %s\n", errstr ());
+        SDL_DestroyMutex (s->mutex);
+        SDL_QuitSubSystem (SDL_INIT_AUDIO);
+        return NULL;
+    }
+
+    return s;
+}
+
+static void sdl_audio_fini (void *opaque)
+{
+    SDLAudioState *s = opaque;
+    sdl_close (s);
+    SDL_DestroySemaphore (s->sem);
+    SDL_DestroyMutex (s->mutex);
+    SDL_QuitSubSystem (SDL_INIT_AUDIO);
+}
+
+struct pcm_ops sdl_pcm_ops = {
+    sdl_hw_init,
+    sdl_hw_fini,
+    sdl_hw_run,
+    sdl_hw_write,
+    sdl_hw_ctl
+};
+
+struct audio_output_driver sdl_output_driver = {
+    "sdl",
+    sdl_audio_init,
+    sdl_audio_fini,
+    &sdl_pcm_ops,
+    1,
+    1,
+    sizeof (SDLVoice)
+};
diff -r 2c75070e41a0 -r 5a790011259e tools/ioemu/audio/wavaudio.c
--- /dev/null   Wed Dec 21 16:30:10 2005
+++ b/tools/ioemu/audio/wavaudio.c      Wed Dec 21 17:56:19 2005
@@ -0,0 +1,217 @@
+/*
+ * QEMU WAV audio output driver
+ * 
+ * Copyright (c) 2004 Vassili Karpov (malc)
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+
+#include "audio/audio_int.h"
+
+typedef struct WAVVoice {
+    HWVoice hw;
+    QEMUFile *f;
+    int64_t old_ticks;
+    void *pcm_buf;
+    int total_samples;
+} WAVVoice;
+
+#define dolog(...) AUD_log ("wav", __VA_ARGS__)
+#ifdef DEBUG
+#define ldebug(...) dolog (__VA_ARGS__)
+#else
+#define ldebug(...)
+#endif
+
+static struct {
+    const char *wav_path;
+} conf = {
+    .wav_path = "qemu.wav"
+};
+
+static void wav_hw_run (HWVoice *hw)
+{
+    WAVVoice *wav = (WAVVoice *) hw;
+    int rpos, live, decr, samples;
+    uint8_t *dst;
+    st_sample_t *src;
+    int64_t now = qemu_get_clock (vm_clock);
+    int64_t ticks = now - wav->old_ticks;
+    int64_t bytes = (ticks * hw->bytes_per_second) / ticks_per_sec;
+
+    if (bytes > INT_MAX)
+        samples = INT_MAX >> hw->shift;
+    else
+        samples = bytes >> hw->shift;
+
+    live = pcm_hw_get_live (hw);
+    if (live <= 0)
+        return;
+
+    wav->old_ticks = now;
+    decr = audio_MIN (live, samples);
+    samples = decr;
+    rpos = hw->rpos;
+    while (samples) {
+        int left_till_end_samples = hw->samples - rpos;
+        int convert_samples = audio_MIN (samples, left_till_end_samples);
+
+        src = advance (hw->mix_buf, rpos * sizeof (st_sample_t));
+        dst = advance (wav->pcm_buf, rpos << hw->shift);
+
+        hw->clip (dst, src, convert_samples);
+        qemu_put_buffer (wav->f, dst, convert_samples << hw->shift);
+        memset (src, 0, convert_samples * sizeof (st_sample_t));
+
+        rpos = (rpos + convert_samples) % hw->samples;
+        samples -= convert_samples;
+        wav->total_samples += convert_samples;
+    }
+
+    pcm_hw_dec_live (hw, decr);
+    hw->rpos = rpos;
+}
+
+static int wav_hw_write (SWVoice *sw, void *buf, int len)
+{
+    return pcm_hw_write (sw, buf, len);
+}
+
+/* VICE code: Store number as little endian. */
+static void le_store (uint8_t *buf, uint32_t val, int len)
+{
+    int i;
+    for (i = 0; i < len; i++) {
+        buf[i] = (uint8_t) (val & 0xff);
+        val >>= 8;
+    }
+}
+
+static int wav_hw_init (HWVoice *hw, int freq, int nchannels, audfmt_e fmt)
+{
+    WAVVoice *wav = (WAVVoice *) hw;
+    int bits16 = 0, stereo = audio_state.fixed_channels == 2;
+    uint8_t hdr[] = {
+        0x52, 0x49, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x57, 0x41, 0x56,
+        0x45, 0x66, 0x6d, 0x74, 0x20, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00,
+        0x02, 0x00, 0x44, 0xac, 0x00, 0x00, 0x10, 0xb1, 0x02, 0x00, 0x04,
+        0x00, 0x10, 0x00, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x00
+    };
+
+    switch (audio_state.fixed_fmt) {
+    case AUD_FMT_S8:
+    case AUD_FMT_U8:
+        break;
+
+    case AUD_FMT_S16:
+    case AUD_FMT_U16:
+        bits16 = 1;
+        break;
+    }
+
+    hdr[34] = bits16 ? 0x10 : 0x08;
+    hw->freq = 44100;
+    hw->nchannels = stereo ? 2 : 1;
+    hw->fmt = bits16 ? AUD_FMT_S16 : AUD_FMT_U8;
+    hw->bufsize = 4096;
+    wav->pcm_buf = qemu_mallocz (hw->bufsize);
+    if (!wav->pcm_buf)
+        return -1;
+
+    le_store (hdr + 22, hw->nchannels, 2);
+    le_store (hdr + 24, hw->freq, 4);
+    le_store (hdr + 28, hw->freq << (bits16 + stereo), 4);
+    le_store (hdr + 32, 1 << (bits16 + stereo), 2);
+
+    wav->f = fopen (conf.wav_path, "wb");
+    if (!wav->f) {
+        dolog ("failed to open wave file `%s'\nReason: %s\n",
+               conf.wav_path, strerror (errno));
+        qemu_free (wav->pcm_buf);
+        wav->pcm_buf = NULL;
+        return -1;
+    }
+
+    qemu_put_buffer (wav->f, hdr, sizeof (hdr));
+    return 0;
+}
+
+static void wav_hw_fini (HWVoice *hw)
+{
+    WAVVoice *wav = (WAVVoice *) hw;
+    int stereo = hw->nchannels == 2;
+    uint8_t rlen[4];
+    uint8_t dlen[4];
+    uint32_t rifflen = (wav->total_samples << stereo) + 36;
+    uint32_t datalen = wav->total_samples << stereo;
+
+    if (!wav->f || !hw->active)
+        return;
+
+    le_store (rlen, rifflen, 4);
+    le_store (dlen, datalen, 4);
+
+    qemu_fseek (wav->f, 4, SEEK_SET);
+    qemu_put_buffer (wav->f, rlen, 4);
+
+    qemu_fseek (wav->f, 32, SEEK_CUR);
+    qemu_put_buffer (wav->f, dlen, 4);
+
+    fclose (wav->f);
+    wav->f = NULL;
+
+    qemu_free (wav->pcm_buf);
+    wav->pcm_buf = NULL;
+}
+
+static int wav_hw_ctl (HWVoice *hw, int cmd, ...)
+{
+    (void) hw;
+    (void) cmd;
+    return 0;
+}
+
+static void *wav_audio_init (void)
+{
+    return &conf;
+}
+
+static void wav_audio_fini (void *opaque)
+{
+    ldebug ("wav_fini");
+}
+
+struct pcm_ops wav_pcm_ops = {
+    wav_hw_init,
+    wav_hw_fini,
+    wav_hw_run,
+    wav_hw_write,
+    wav_hw_ctl
+};
+
+struct audio_output_driver wav_output_driver = {
+    "wav",
+    wav_audio_init,
+    wav_audio_fini,
+    &wav_pcm_ops,
+    1,
+    1,
+    sizeof (WAVVoice)
+};
diff -r 2c75070e41a0 -r 5a790011259e tools/libxc/xc_ptrace.h
--- /dev/null   Wed Dec 21 16:30:10 2005
+++ b/tools/libxc/xc_ptrace.h   Wed Dec 21 17:56:19 2005
@@ -0,0 +1,124 @@
+#ifndef XC_PTRACE_
+#define XC_PTRACE_
+
+#ifdef XC_PTRACE_PRIVATE
+#define X86_CR0_PE              0x00000001 /* Enable Protected Mode    (RW) */
+#define X86_CR0_PG              0x80000000 /* Paging                   (RW) */
+#define BSD_PAGE_MASK (PAGE_SIZE-1)
+#define PDRSHIFT        22
+#define PSL_T  0x00000100 /* trace enable bit */
+
+char * ptrace_names[] = {
+    "PTRACE_TRACEME",
+    "PTRACE_PEEKTEXT",
+    "PTRACE_PEEKDATA",
+    "PTRACE_PEEKUSER",
+    "PTRACE_POKETEXT",
+    "PTRACE_POKEDATA",
+    "PTRACE_POKEUSER",
+    "PTRACE_CONT",
+    "PTRACE_KILL",
+    "PTRACE_SINGLESTEP",
+    "PTRACE_INVALID",
+    "PTRACE_INVALID",
+    "PTRACE_GETREGS",
+    "PTRACE_SETREGS",
+    "PTRACE_GETFPREGS",
+    "PTRACE_SETFPREGS",
+    "PTRACE_ATTACH",
+    "PTRACE_DETACH",
+    "PTRACE_GETFPXREGS",
+    "PTRACE_SETFPXREGS",
+    "PTRACE_INVALID",
+    "PTRACE_INVALID",
+    "PTRACE_INVALID",
+    "PTRACE_INVALID",
+    "PTRACE_SYSCALL",
+};
+
+struct gdb_regs {
+    long ebx; /* 0 */
+    long ecx; /* 4 */
+    long edx; /* 8 */
+    long esi; /* 12 */
+    long edi; /* 16 */
+    long ebp; /* 20 */
+    long eax; /* 24 */ 
+    int  xds; /* 28 */
+    int  xes; /* 32 */
+    int  xfs; /* 36 */
+    int  xgs; /* 40 */
+    long orig_eax; /* 44 */
+    long eip;    /* 48 */
+    int  xcs;    /* 52 */
+    long eflags; /* 56 */
+    long esp;    /* 60 */     
+    int  xss;    /* 64 */
+};
+
+
+#define printval(x) printf("%s = %lx\n", #x, (long)x);
+#define SET_PT_REGS(pt, xc)                     \
+{                                               \
+    pt.ebx = xc.ebx;                            \
+    pt.ecx = xc.ecx;                            \
+    pt.edx = xc.edx;                            \
+    pt.esi = xc.esi;                            \
+    pt.edi = xc.edi;                            \
+    pt.ebp = xc.ebp;                            \
+    pt.eax = xc.eax;                            \
+    pt.eip = xc.eip;                            \
+    pt.xcs = xc.cs;                             \
+    pt.eflags = xc.eflags;                      \
+    pt.esp = xc.esp;                            \
+    pt.xss = xc.ss;                             \
+    pt.xes = xc.es;                             \
+    pt.xds = xc.ds;                             \
+    pt.xfs = xc.fs;                             \
+    pt.xgs = xc.gs;                             \
+}
+
+#define SET_XC_REGS(pt, xc)                     \
+{                                               \
+    xc.ebx = pt->ebx;                           \
+    xc.ecx = pt->ecx;                           \
+    xc.edx = pt->edx;                           \
+    xc.esi = pt->esi;                           \
+    xc.edi = pt->edi;                           \
+    xc.ebp = pt->ebp;                           \
+    xc.eax = pt->eax;                           \
+    xc.eip = pt->eip;                           \
+    xc.cs = pt->xcs;                            \
+    xc.eflags = pt->eflags;                     \
+    xc.esp = pt->esp;                           \
+    xc.ss = pt->xss;                            \
+    xc.es = pt->xes;                            \
+    xc.ds = pt->xds;                            \
+    xc.fs = pt->xfs;                            \
+    xc.gs = pt->xgs;                            \
+}
+
+#define vtopdi(va) ((va) >> PDRSHIFT)
+#define vtopti(va) (((va) >> PAGE_SHIFT) & 0x3ff)
+#endif
+
+typedef void (*thr_ev_handler_t)(long);
+
+void xc_register_event_handler(
+    thr_ev_handler_t h, 
+    td_event_e e);
+
+long xc_ptrace(
+    int xc_handle,
+    enum __ptrace_request request, 
+    uint32_t  domid,
+    long addr, 
+    long data);
+
+int xc_waitdomain(
+    int xc_handle,
+    int domain, 
+    int *status, 
+    int options);
+
+#endif /* XC_PTRACE */

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>