[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] Merged.



# HG changeset patch
# User emellor@xxxxxxxxxxxxxxxxxxxxxx
# Node ID d3b10a2a82d47bb3e52faf2fa4ba27217f486c54
# Parent  11cd619db03540476cef8ec523d46d9a1d13973c
# Parent  931acb64fbaf762fd47f9035b411ae6f1b5cb50b
Merged.

diff -r 11cd619db035 -r d3b10a2a82d4 Makefile
--- a/Makefile  Tue Dec 20 17:16:15 2005
+++ b/Makefile  Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 buildconfigs/mk.linux-2.6-xen
--- a/buildconfigs/mk.linux-2.6-xen     Tue Dec 20 17:16:15 2005
+++ b/buildconfigs/mk.linux-2.6-xen     Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 
linux-2.6-xen-sparse/arch/xen/i386/kernel/ldt.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/ldt.c   Tue Dec 20 17:16:15 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/ldt.c   Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 
linux-2.6-xen-sparse/arch/xen/i386/kernel/swiotlb.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/swiotlb.c       Tue Dec 20 
17:16:15 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/swiotlb.c       Tue Dec 20 
17:16:24 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 11cd619db035 -r d3b10a2a82d4 
linux-2.6-xen-sparse/arch/xen/i386/mm/hypervisor.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/mm/hypervisor.c        Tue Dec 20 
17:16:15 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/mm/hypervisor.c        Tue Dec 20 
17:16:24 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 11cd619db035 -r d3b10a2a82d4 
linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c
--- a/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c     Tue Dec 20 17:16:15 2005
+++ b/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c     Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 
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      Tue Dec 20 
17:16:15 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/desc.h      Tue Dec 20 
17:16:24 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 11cd619db035 -r d3b10a2a82d4 
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     
Tue Dec 20 17:16:15 2005
+++ b/tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/linux-xen-low.c     
Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 
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    Tue Dec 
20 17:16:15 2005
+++ b/tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/server.c    Tue Dec 
20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 tools/examples/xend-config.sxp
--- a/tools/examples/xend-config.sxp    Tue Dec 20 17:16:15 2005
+++ b/tools/examples/xend-config.sxp    Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 tools/examples/xmexample.vmx
--- a/tools/examples/xmexample.vmx      Tue Dec 20 17:16:15 2005
+++ b/tools/examples/xmexample.vmx      Tue Dec 20 17:16:24 2005
@@ -135,7 +135,7 @@
 
 #-----------------------------------------------------------------------------
 #   enable audio support
-#enable-audio=1
+#audio=1
 
 
 #-----------------------------------------------------------------------------
diff -r 11cd619db035 -r d3b10a2a82d4 tools/ioemu/cpu-all.h
--- a/tools/ioemu/cpu-all.h     Tue Dec 20 17:16:15 2005
+++ b/tools/ioemu/cpu-all.h     Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 tools/ioemu/exec.c
--- a/tools/ioemu/exec.c        Tue Dec 20 17:16:15 2005
+++ b/tools/ioemu/exec.c        Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 tools/ioemu/hw/pc.c
--- a/tools/ioemu/hw/pc.c       Tue Dec 20 17:16:15 2005
+++ b/tools/ioemu/hw/pc.c       Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 tools/ioemu/hw/pcnet.h
--- a/tools/ioemu/hw/pcnet.h    Tue Dec 20 17:16:15 2005
+++ b/tools/ioemu/hw/pcnet.h    Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 tools/ioemu/target-i386-dm/Makefile
--- a/tools/ioemu/target-i386-dm/Makefile       Tue Dec 20 17:16:15 2005
+++ b/tools/ioemu/target-i386-dm/Makefile       Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 tools/ioemu/vl.c
--- a/tools/ioemu/vl.c  Tue Dec 20 17:16:15 2005
+++ b/tools/ioemu/vl.c  Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 tools/ioemu/vl.h
--- a/tools/ioemu/vl.h  Tue Dec 20 17:16:15 2005
+++ b/tools/ioemu/vl.h  Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 tools/libxc/xc_domain.c
--- a/tools/libxc/xc_domain.c   Tue Dec 20 17:16:15 2005
+++ b/tools/libxc/xc_domain.c   Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 tools/libxc/xc_ptrace.c
--- a/tools/libxc/xc_ptrace.c   Tue Dec 20 17:16:15 2005
+++ b/tools/libxc/xc_ptrace.c   Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 tools/libxc/xc_vmx_build.c
--- a/tools/libxc/xc_vmx_build.c        Tue Dec 20 17:16:15 2005
+++ b/tools/libxc/xc_vmx_build.c        Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 tools/libxc/xenctrl.h
--- a/tools/libxc/xenctrl.h     Tue Dec 20 17:16:15 2005
+++ b/tools/libxc/xenctrl.h     Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 tools/python/xen/xend/image.py
--- a/tools/python/xen/xend/image.py    Tue Dec 20 17:16:15 2005
+++ b/tools/python/xen/xend/image.py    Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 tools/python/xen/xm/create.py
--- a/tools/python/xen/xm/create.py     Tue Dec 20 17:16:15 2005
+++ b/tools/python/xen/xm/create.py     Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 tools/vtpm_manager/manager/securestorage.c
--- a/tools/vtpm_manager/manager/securestorage.c        Tue Dec 20 17:16:15 2005
+++ b/tools/vtpm_manager/manager/securestorage.c        Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 tools/xm-test/README
--- a/tools/xm-test/README      Tue Dec 20 17:16:15 2005
+++ b/tools/xm-test/README      Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 tools/xm-test/ramdisk/Makefile.am
--- a/tools/xm-test/ramdisk/Makefile.am Tue Dec 20 17:16:15 2005
+++ b/tools/xm-test/ramdisk/Makefile.am Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 tools/xm-test/ramdisk/bin/create_disk_image
--- a/tools/xm-test/ramdisk/bin/create_disk_image       Tue Dec 20 17:16:15 2005
+++ b/tools/xm-test/ramdisk/bin/create_disk_image       Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 xen/Rules.mk
--- a/xen/Rules.mk      Tue Dec 20 17:16:15 2005
+++ b/xen/Rules.mk      Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 xen/arch/x86/audit.c
--- a/xen/arch/x86/audit.c      Tue Dec 20 17:16:15 2005
+++ b/xen/arch/x86/audit.c      Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 xen/arch/x86/dom0_ops.c
--- a/xen/arch/x86/dom0_ops.c   Tue Dec 20 17:16:15 2005
+++ b/xen/arch/x86/dom0_ops.c   Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 xen/arch/x86/domain.c
--- a/xen/arch/x86/domain.c     Tue Dec 20 17:16:15 2005
+++ b/xen/arch/x86/domain.c     Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 xen/arch/x86/domain_build.c
--- a/xen/arch/x86/domain_build.c       Tue Dec 20 17:16:15 2005
+++ b/xen/arch/x86/domain_build.c       Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 xen/arch/x86/mm.c
--- a/xen/arch/x86/mm.c Tue Dec 20 17:16:15 2005
+++ b/xen/arch/x86/mm.c Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 xen/arch/x86/setup.c
--- a/xen/arch/x86/setup.c      Tue Dec 20 17:16:15 2005
+++ b/xen/arch/x86/setup.c      Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 xen/arch/x86/shadow.c
--- a/xen/arch/x86/shadow.c     Tue Dec 20 17:16:15 2005
+++ b/xen/arch/x86/shadow.c     Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 xen/arch/x86/shadow32.c
--- a/xen/arch/x86/shadow32.c   Tue Dec 20 17:16:15 2005
+++ b/xen/arch/x86/shadow32.c   Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 xen/arch/x86/shadow_public.c
--- a/xen/arch/x86/shadow_public.c      Tue Dec 20 17:16:15 2005
+++ b/xen/arch/x86/shadow_public.c      Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 xen/arch/x86/traps.c
--- a/xen/arch/x86/traps.c      Tue Dec 20 17:16:15 2005
+++ b/xen/arch/x86/traps.c      Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 xen/arch/x86/vmx.c
--- a/xen/arch/x86/vmx.c        Tue Dec 20 17:16:15 2005
+++ b/xen/arch/x86/vmx.c        Tue Dec 20 17:16:24 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)
 {
@@ -543,6 +544,13 @@
         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;
@@ -1223,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);
@@ -1841,7 +1850,7 @@
             break;
         }
         case TRAP_nmi:
-            do_nmi(&regs, 0);
+            do_nmi(&regs);
             break;
         default:
             vmx_reflect_exception(v);
diff -r 11cd619db035 -r d3b10a2a82d4 xen/arch/x86/vmx_intercept.c
--- a/xen/arch/x86/vmx_intercept.c      Tue Dec 20 17:16:15 2005
+++ b/xen/arch/x86/vmx_intercept.c      Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 xen/arch/x86/x86_32/entry.S
--- a/xen/arch/x86/x86_32/entry.S       Tue Dec 20 17:16:15 2005
+++ b/xen/arch/x86/x86_32/entry.S       Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 xen/arch/x86/x86_32/mm.c
--- a/xen/arch/x86/x86_32/mm.c  Tue Dec 20 17:16:15 2005
+++ b/xen/arch/x86/x86_32/mm.c  Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 xen/arch/x86/x86_32/traps.c
--- a/xen/arch/x86/x86_32/traps.c       Tue Dec 20 17:16:15 2005
+++ b/xen/arch/x86/x86_32/traps.c       Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 xen/arch/x86/x86_64/entry.S
--- a/xen/arch/x86/x86_64/entry.S       Tue Dec 20 17:16:15 2005
+++ b/xen/arch/x86/x86_64/entry.S       Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 xen/arch/x86/x86_64/mm.c
--- a/xen/arch/x86/x86_64/mm.c  Tue Dec 20 17:16:15 2005
+++ b/xen/arch/x86/x86_64/mm.c  Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 xen/common/dom0_ops.c
--- a/xen/common/dom0_ops.c     Tue Dec 20 17:16:15 2005
+++ b/xen/common/dom0_ops.c     Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 xen/common/grant_table.c
--- a/xen/common/grant_table.c  Tue Dec 20 17:16:15 2005
+++ b/xen/common/grant_table.c  Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 xen/common/memory.c
--- a/xen/common/memory.c       Tue Dec 20 17:16:15 2005
+++ b/xen/common/memory.c       Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 xen/include/asm-x86/debugger.h
--- a/xen/include/asm-x86/debugger.h    Tue Dec 20 17:16:15 2005
+++ b/xen/include/asm-x86/debugger.h    Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 xen/include/asm-x86/shadow.h
--- a/xen/include/asm-x86/shadow.h      Tue Dec 20 17:16:15 2005
+++ b/xen/include/asm-x86/shadow.h      Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 xen/include/asm-x86/shadow_public.h
--- a/xen/include/asm-x86/shadow_public.h       Tue Dec 20 17:16:15 2005
+++ b/xen/include/asm-x86/shadow_public.h       Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 xen/include/public/acm.h
--- a/xen/include/public/acm.h  Tue Dec 20 17:16:15 2005
+++ b/xen/include/public/acm.h  Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 xen/include/public/acm_ops.h
--- a/xen/include/public/acm_ops.h      Tue Dec 20 17:16:15 2005
+++ b/xen/include/public/acm_ops.h      Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 xen/include/public/dom0_ops.h
--- a/xen/include/public/dom0_ops.h     Tue Dec 20 17:16:15 2005
+++ b/xen/include/public/dom0_ops.h     Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 xen/include/public/vmx_assist.h
--- a/xen/include/public/vmx_assist.h   Tue Dec 20 17:16:15 2005
+++ b/xen/include/public/vmx_assist.h   Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 xen/include/public/xen.h
--- a/xen/include/public/xen.h  Tue Dec 20 17:16:15 2005
+++ b/xen/include/public/xen.h  Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 xen/include/xen/sched.h
--- a/xen/include/xen/sched.h   Tue Dec 20 17:16:15 2005
+++ b/xen/include/xen/sched.h   Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 xen/include/xen/softirq.h
--- a/xen/include/xen/softirq.h Tue Dec 20 17:16:15 2005
+++ b/xen/include/xen/softirq.h Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 tools/ioemu/audio/audio.c
--- /dev/null   Tue Dec 20 17:16:15 2005
+++ b/tools/ioemu/audio/audio.c Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 tools/ioemu/audio/audio.h
--- /dev/null   Tue Dec 20 17:16:15 2005
+++ b/tools/ioemu/audio/audio.h Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 tools/ioemu/audio/audio_int.h
--- /dev/null   Tue Dec 20 17:16:15 2005
+++ b/tools/ioemu/audio/audio_int.h     Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 tools/ioemu/audio/mixeng.c
--- /dev/null   Tue Dec 20 17:16:15 2005
+++ b/tools/ioemu/audio/mixeng.c        Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 tools/ioemu/audio/mixeng.h
--- /dev/null   Tue Dec 20 17:16:15 2005
+++ b/tools/ioemu/audio/mixeng.h        Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 tools/ioemu/audio/mixeng_template.h
--- /dev/null   Tue Dec 20 17:16:15 2005
+++ b/tools/ioemu/audio/mixeng_template.h       Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 tools/ioemu/audio/noaudio.c
--- /dev/null   Tue Dec 20 17:16:15 2005
+++ b/tools/ioemu/audio/noaudio.c       Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 tools/ioemu/audio/ossaudio.c
--- /dev/null   Tue Dec 20 17:16:15 2005
+++ b/tools/ioemu/audio/ossaudio.c      Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 tools/ioemu/audio/sdlaudio.c
--- /dev/null   Tue Dec 20 17:16:15 2005
+++ b/tools/ioemu/audio/sdlaudio.c      Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 tools/ioemu/audio/wavaudio.c
--- /dev/null   Tue Dec 20 17:16:15 2005
+++ b/tools/ioemu/audio/wavaudio.c      Tue Dec 20 17:16:24 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 11cd619db035 -r d3b10a2a82d4 tools/libxc/xc_ptrace.h
--- /dev/null   Tue Dec 20 17:16:15 2005
+++ b/tools/libxc/xc_ptrace.h   Tue Dec 20 17:16:24 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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.