ia64/xen-unstable

changeset 8420:d3b10a2a82d4

Merged.
author emellor@leeni.uk.xensource.com
date Tue Dec 20 17:16:24 2005 +0000 (2005-12-20)
parents 11cd619db035 931acb64fbaf
children 68d72ac55fe5
files
line diff
     1.1 --- a/Makefile	Tue Dec 20 17:16:15 2005 +0000
     1.2 +++ b/Makefile	Tue Dec 20 17:16:24 2005 +0000
     1.3 @@ -10,7 +10,7 @@ XKERNELS := $(foreach kernel, $(KERNELS)
     1.4  # Export target architecture overrides to Xen and Linux sub-trees.
     1.5  ifneq ($(XEN_TARGET_ARCH),)
     1.6  SUBARCH := $(subst x86_32,i386,$(XEN_TARGET_ARCH))
     1.7 -export XEN_TARGET_ARCH SUBARCH
     1.8 +export XEN_TARGET_ARCH SUBARCH XEN_SYSTYPE
     1.9  endif
    1.10  
    1.11  # Default target must appear before any include lines
     2.1 --- a/buildconfigs/mk.linux-2.6-xen	Tue Dec 20 17:16:15 2005 +0000
     2.2 +++ b/buildconfigs/mk.linux-2.6-xen	Tue Dec 20 17:16:24 2005 +0000
     2.3 @@ -30,7 +30,7 @@ build: $(LINUX_DIR)/include/linux/autoco
     2.4  	CONFIG_VERSION=$$(sed -ne 's/^EXTRAVERSION = //p' $(LINUX_DIR)/Makefile); \
     2.5  	[ -r $(DESTDIR)/boot/config-$(LINUX_VER)$$CONFIG_VERSION-$(EXTRAVERSION) ] && \
     2.6  	  cp $(DESTDIR)/boot/config-$(LINUX_VER)$$CONFIG_VERSION-$(EXTRAVERSION) $(LINUX_DIR)/.config \
     2.7 -	  || cp $(LINUX_DIR)/arch/xen/configs/$(EXTRAVERSION)_defconfig_$(XEN_TARGET_ARCH) \
     2.8 +	  || cp $(LINUX_DIR)/arch/xen/configs/$(EXTRAVERSION)_defconfig_$(XEN_TARGET_ARCH)$(XEN_SYSTYPE) \
     2.9  		$(LINUX_DIR)/.config
    2.10  	# See if we need to munge config to enable PAE
    2.11  	$(MAKE) CONFIG_FILE=$(LINUX_DIR)/.config -f buildconfigs/Rules.mk config-update-pae
     3.1 --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/ldt.c	Tue Dec 20 17:16:15 2005 +0000
     3.2 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/ldt.c	Tue Dec 20 17:16:24 2005 +0000
     3.3 @@ -186,8 +186,7 @@ static int read_default_ldt(void __user 
     3.4  static int write_ldt(void __user * ptr, unsigned long bytecount, int oldmode)
     3.5  {
     3.6  	struct mm_struct * mm = current->mm;
     3.7 -	__u32 entry_1, entry_2, *lp;
     3.8 -	maddr_t mach_lp;
     3.9 +	__u32 entry_1, entry_2;
    3.10  	int error;
    3.11  	struct user_desc ldt_info;
    3.12  
    3.13 @@ -215,9 +214,6 @@ static int write_ldt(void __user * ptr, 
    3.14  			goto out_unlock;
    3.15  	}
    3.16  
    3.17 -	lp = (__u32 *) ((ldt_info.entry_number << 3) + (char *) mm->context.ldt);
    3.18 -	mach_lp = arbitrary_virt_to_machine(lp);
    3.19 -
    3.20     	/* Allow LDTs to be cleared by the user. */
    3.21     	if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
    3.22  		if (oldmode || LDT_empty(&ldt_info)) {
    3.23 @@ -234,8 +230,8 @@ static int write_ldt(void __user * ptr, 
    3.24  
    3.25  	/* Install the new entry ...  */
    3.26  install:
    3.27 -	error = HYPERVISOR_update_descriptor(
    3.28 -		mach_lp, (u64)entry_1 | ((u64)entry_2<<32));
    3.29 +	error = write_ldt_entry(mm->context.ldt, ldt_info.entry_number,
    3.30 +				entry_1, entry_2);
    3.31  
    3.32  out_unlock:
    3.33  	up(&mm->context.sem);
     4.1 --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/swiotlb.c	Tue Dec 20 17:16:15 2005 +0000
     4.2 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/swiotlb.c	Tue Dec 20 17:16:24 2005 +0000
     4.3 @@ -24,6 +24,7 @@
     4.4  #include <asm/io.h>
     4.5  #include <asm/pci.h>
     4.6  #include <asm/dma.h>
     4.7 +#include <asm/uaccess.h>
     4.8  #include <asm-xen/xen-public/memory.h>
     4.9  
    4.10  #define OFFSET(val,align) ((unsigned long)((val) & ( (align) - 1)))
    4.11 @@ -201,6 +202,12 @@ swiotlb_init(void)
    4.12  		printk(KERN_INFO "Software IO TLB disabled\n");
    4.13  }
    4.14  
    4.15 +/*
    4.16 + * We use __copy_to_user to transfer to the host buffer because the buffer
    4.17 + * may be mapped read-only (e.g, in blkback driver) but lower-level
    4.18 + * drivers map the buffer for DMA_BIDIRECTIONAL access. This causes an
    4.19 + * unnecessary copy from the aperture to the host buffer, and a page fault.
    4.20 + */
    4.21  static void
    4.22  __sync_single(struct phys_addr buffer, char *dma_addr, size_t size, int dir)
    4.23  {
    4.24 @@ -214,9 +221,11 @@ static void
    4.25  			kmp  = kmap_atomic(buffer.page, KM_SWIOTLB);
    4.26  			dev  = dma_addr + size - len;
    4.27  			host = kmp + buffer.offset;
    4.28 -			memcpy((dir == DMA_FROM_DEVICE) ? host : dev,
    4.29 -			       (dir == DMA_FROM_DEVICE) ? dev : host,
    4.30 -			       bytes);
    4.31 +			if (dir == DMA_FROM_DEVICE) {
    4.32 +				if (__copy_to_user(host, dev, bytes))
    4.33 +					/* inaccessible */;
    4.34 +			} else
    4.35 +				memcpy(dev, host, bytes);
    4.36  			kunmap_atomic(kmp, KM_SWIOTLB);
    4.37  			len -= bytes;
    4.38  			buffer.page++;
    4.39 @@ -225,9 +234,10 @@ static void
    4.40  	} else {
    4.41  		char *host = (char *)phys_to_virt(
    4.42  			page_to_pseudophys(buffer.page)) + buffer.offset;
    4.43 -		if (dir == DMA_FROM_DEVICE)
    4.44 -			memcpy(host, dma_addr, size);
    4.45 -		else if (dir == DMA_TO_DEVICE)
    4.46 +		if (dir == DMA_FROM_DEVICE) {
    4.47 +			if (__copy_to_user(host, dma_addr, size))
    4.48 +				/* inaccessible */;
    4.49 +		} else if (dir == DMA_TO_DEVICE)
    4.50  			memcpy(dma_addr, host, size);
    4.51  	}
    4.52  }
     5.1 --- a/linux-2.6-xen-sparse/arch/xen/i386/mm/hypervisor.c	Tue Dec 20 17:16:15 2005 +0000
     5.2 +++ b/linux-2.6-xen-sparse/arch/xen/i386/mm/hypervisor.c	Tue Dec 20 17:16:24 2005 +0000
     5.3 @@ -438,6 +438,16 @@ void xen_destroy_contiguous_region(unsig
     5.4  	balloon_unlock(flags);
     5.5  }
     5.6  
     5.7 +#ifdef __i386__
     5.8 +int write_ldt_entry(void *ldt, int entry, __u32 entry_a, __u32 entry_b)
     5.9 +{
    5.10 +	__u32 *lp = (__u32 *)((char *)ldt + entry * 8);
    5.11 +	maddr_t mach_lp = arbitrary_virt_to_machine(lp);
    5.12 +	return HYPERVISOR_update_descriptor(
    5.13 +		mach_lp, (u64)entry_a | ((u64)entry_b<<32));
    5.14 +}
    5.15 +#endif
    5.16 +
    5.17  /*
    5.18   * Local variables:
    5.19   *  c-file-style: "linux"
     6.1 --- a/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c	Tue Dec 20 17:16:15 2005 +0000
     6.2 +++ b/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c	Tue Dec 20 17:16:24 2005 +0000
     6.3 @@ -163,11 +163,10 @@ asmlinkage void evtchn_do_upcall(struct 
     6.4  	while (l1 != 0) {
     6.5  		l1i = __ffs(l1);
     6.6  		l1 &= ~(1UL << l1i);
     6.7 -        
     6.8 +
     6.9  		while ((l2 = active_evtchns(cpu, s, l1i)) != 0) {
    6.10  			l2i = __ffs(l2);
    6.11 -			l2 &= ~(1UL << l2i);
    6.12 -            
    6.13 +
    6.14  			port = (l1i * BITS_PER_LONG) + l2i;
    6.15  			if ((irq = evtchn_to_irq[port]) != -1)
    6.16  				do_IRQ(irq, regs);
     7.1 --- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/desc.h	Tue Dec 20 17:16:15 2005 +0000
     7.2 +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/desc.h	Tue Dec 20 17:16:24 2005 +0000
     7.3 @@ -87,6 +87,8 @@ static inline void set_ldt_desc(unsigned
     7.4  	(info)->seg_not_present	== 1	&& \
     7.5  	(info)->useable		== 0	)
     7.6  
     7.7 +extern int write_ldt_entry(void *ldt, int entry, __u32 entry_a, __u32 entry_b);
     7.8 +
     7.9  #if TLS_SIZE != 24
    7.10  # error update this code.
    7.11  #endif
     8.1 --- a/tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/linux-xen-low.c	Tue Dec 20 17:16:15 2005 +0000
     8.2 +++ b/tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/linux-xen-low.c	Tue Dec 20 17:16:24 2005 +0000
     8.3 @@ -36,23 +36,41 @@
     8.4  #include <unistd.h>
     8.5  #include <errno.h>
     8.6  #include <xenctrl.h>
     8.7 +#include <thread_db.h>
     8.8 +#include <xc_ptrace.h>
     8.9 +
    8.10  #define TRACE_ENTER /* printf("enter %s\n", __FUNCTION__) */
    8.11  
    8.12  long (*myptrace)(int xc_handle, enum __ptrace_request, uint32_t, long, long);
    8.13  int (*myxcwait)(int xc_handle, int domain, int *status, int options) ;
    8.14  static int xc_handle;
    8.15  
    8.16 +static inline int
    8.17 +curvcpuid()
    8.18 +{
    8.19 +  struct process_info *process;
    8.20 +  if (current_inferior == NULL)
    8.21 +      return 0;
    8.22 +  process = get_thread_process(current_inferior);
    8.23 +  return (process->thread_known ? process->tid : 0);
    8.24 +
    8.25 +}
    8.26 +
    8.27 +
    8.28  #define DOMFLAGS_DYING     (1<<0) /* Domain is scheduled to die.             */
    8.29  #define DOMFLAGS_SHUTDOWN  (1<<2) /* The guest OS has shut down.             */
    8.30  #define DOMFLAGS_PAUSED    (1<<3) /* Currently paused by control software.   */
    8.31  #define DOMFLAGS_BLOCKED   (1<<4) /* Currently blocked pending an event.     */
    8.32  #define DOMFLAGS_RUNNING   (1<<5) /* Domain is currently running.            */
    8.33  
    8.34 +
    8.35 +
    8.36  struct inferior_list all_processes;
    8.37 -static int current_domain;
    8.38 +static int current_domid;
    8.39  static int expect_signal = 0;
    8.40  static int signal_to_send = 0; 
    8.41  static void linux_resume (struct thread_resume *resume_info);
    8.42 +static void linux_set_inferior (void);
    8.43  
    8.44  int debug_threads;
    8.45  int using_threads;
    8.46 @@ -96,7 +114,6 @@ static int use_regsets_p = 1;
    8.47     point at the following instruction.  If we continue and hit a
    8.48     breakpoint instruction, our PC will point at the breakpoint
    8.49     instruction.  */
    8.50 -#if 0
    8.51  static CORE_ADDR
    8.52  get_stop_pc (void)
    8.53  {
    8.54 @@ -107,9 +124,9 @@ get_stop_pc (void)
    8.55    else
    8.56      return stop_pc - the_low_target.decr_pc_after_break;
    8.57  }
    8.58 -#endif
    8.59 +
    8.60  static void *
    8.61 -add_process (int pid)
    8.62 +add_process (int pid, long tid)
    8.63  {
    8.64    struct process_info *process;
    8.65  
    8.66 @@ -118,9 +135,8 @@ add_process (int pid)
    8.67  
    8.68    process->head.id = pid;
    8.69  
    8.70 -  /* Default to tid == lwpid == pid.  */
    8.71 -  process->tid = pid;
    8.72 -  process->lwpid = pid;
    8.73 +  process->tid = tid;
    8.74 +  process->lwpid = tid;
    8.75  
    8.76    add_inferior_to_list (&all_processes, &process->head);
    8.77  
    8.78 @@ -143,23 +159,25 @@ linux_create_inferior (char *program, ch
    8.79  }
    8.80  
    8.81  int
    8.82 -linux_attach (int domain)
    8.83 +linux_attach (int domid)
    8.84  {
    8.85      struct process_info *new_process;
    8.86 -    current_domain = domain;
    8.87 -    if (myptrace (xc_handle, PTRACE_ATTACH, domain, 0, 0) != 0) {
    8.88 -	fprintf (stderr, "Cannot attach to domain %d: %s (%d)\n", domain,
    8.89 +    current_domid = domid;
    8.90 +    /* this is handled for all active vcpus in PTRACE_ATTACH via the thread_create_callback */
    8.91 +    new_process = (struct process_info *) add_process (domid, curvcpuid());
    8.92 +    /* Don't ignore the initial SIGSTOP if we just attached to this process.  */
    8.93 +    /* vcpuid == 0 */
    8.94 +    add_thread (0, new_process);
    8.95 +    new_process->stop_expected = 0;
    8.96 +
    8.97 +    if (myptrace (xc_handle, PTRACE_ATTACH, domid, 0, 0) != 0) {
    8.98 +	fprintf (stderr, "Cannot attach to domain %d: %s (%d)\n", domid,
    8.99  		 strerror (errno), errno);
   8.100  	fflush (stderr);
   8.101 -	_exit (0177);
   8.102 +	if (!using_threads)
   8.103 +	    _exit (0177);
   8.104      }
   8.105 -    
   8.106 -    new_process = (struct process_info *) add_process (domain);
   8.107 -    add_thread (domain, new_process);
   8.108  
   8.109 -    /* Don't ignore the initial SIGSTOP if we just attached to this process.  */
   8.110 -    new_process->stop_expected = 0;
   8.111 -    
   8.112      return 0;
   8.113  }
   8.114  
   8.115 @@ -173,20 +191,18 @@ linux_kill_one_process (struct inferior_
   8.116    myptrace (xc_handle, PTRACE_KILL, pid_of (process), 0, 0);
   8.117  }
   8.118  
   8.119 +
   8.120  static void
   8.121  linux_kill (void)
   8.122  {
   8.123    for_each_inferior (&all_threads, linux_kill_one_process);
   8.124  }
   8.125  
   8.126 -
   8.127  static void
   8.128  linux_detach_one_process (struct inferior_list_entry *entry)
   8.129  {
   8.130 -  struct thread_info *thread = (struct thread_info *) entry;
   8.131 -  struct process_info *process = get_thread_process (thread);
   8.132  
   8.133 -  myptrace (xc_handle, PTRACE_DETACH, pid_of (process), 0, 0);
   8.134 +  myptrace (xc_handle, PTRACE_DETACH, current_domid, 0, 0);
   8.135  }
   8.136  
   8.137  
   8.138 @@ -212,14 +228,10 @@ static unsigned char
   8.139  linux_wait (char *status)
   8.140  {
   8.141    int w;
   8.142 -  if (myxcwait(xc_handle, current_domain, &w, 0))
   8.143 +  if (myxcwait(xc_handle, current_domid, &w, 0))
   8.144        return -1;
   8.145    
   8.146 -  if (w & (DOMFLAGS_SHUTDOWN|DOMFLAGS_DYING)) {
   8.147 -      *status = 'W';
   8.148 -      return 0;
   8.149 -  }
   8.150 -
   8.151 +  linux_set_inferior();
   8.152  
   8.153    *status = 'T';
   8.154    if (expect_signal)
   8.155 @@ -236,8 +248,10 @@ linux_resume (struct thread_resume *resu
   8.156    TRACE_ENTER;
   8.157    expect_signal = resume_info->sig;
   8.158    for_each_inferior(&all_threads, regcache_invalidate_one);
   8.159 -
   8.160 -  myptrace (xc_handle, step ? PTRACE_SINGLESTEP : PTRACE_CONT, current_domain, 0, 0);
   8.161 +  if (debug_threads)
   8.162 +    fprintf(stderr, "step: %d\n", step);
   8.163 +  myptrace (xc_handle, step ? PTRACE_SINGLESTEP : PTRACE_CONT, 
   8.164 +	    resume_info->thread, 0, 0);
   8.165  
   8.166  }
   8.167  
   8.168 @@ -261,7 +275,9 @@ regsets_fetch_inferior_registers ()
   8.169  	}
   8.170  
   8.171        buf = malloc (regset->size);
   8.172 -      res = myptrace (xc_handle, regset->get_request, inferior_pid, 0, (PTRACE_XFER_TYPE)buf);
   8.173 +      res = myptrace (xc_handle, regset->get_request, 
   8.174 +		      curvcpuid(),
   8.175 +		      0, (PTRACE_XFER_TYPE)buf);
   8.176        if (res < 0)
   8.177  	{
   8.178  	  if (errno == EIO)
   8.179 @@ -313,7 +329,7 @@ regsets_store_inferior_registers ()
   8.180  
   8.181        buf = malloc (regset->size);
   8.182        regset->fill_function (buf);
   8.183 -      res = myptrace (xc_handle, regset->set_request, inferior_pid, 0, (PTRACE_XFER_TYPE)buf);
   8.184 +      res = myptrace (xc_handle, regset->set_request, curvcpuid(), 0, (PTRACE_XFER_TYPE)buf);
   8.185        if (res < 0)
   8.186  	{
   8.187  	  if (errno == EIO)
   8.188 @@ -391,7 +407,7 @@ linux_read_memory (CORE_ADDR memaddr, ch
   8.189    for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE))
   8.190      {
   8.191        errno = 0;
   8.192 -      buffer[i] = myptrace (xc_handle, PTRACE_PEEKTEXT, inferior_pid, (PTRACE_ARG3_TYPE) addr, 0);
   8.193 +      buffer[i] = myptrace (xc_handle, PTRACE_PEEKTEXT, curvcpuid(), (PTRACE_ARG3_TYPE) addr, 0);
   8.194        if (errno)
   8.195  	return errno;
   8.196      }
   8.197 @@ -424,13 +440,13 @@ linux_write_memory (CORE_ADDR memaddr, c
   8.198  
   8.199    /* Fill start and end extra bytes of buffer with existing memory data.  */
   8.200  
   8.201 -  buffer[0] = myptrace (xc_handle, PTRACE_PEEKTEXT, inferior_pid,
   8.202 +  buffer[0] = myptrace (xc_handle, PTRACE_PEEKTEXT, curvcpuid(),
   8.203  		      (PTRACE_ARG3_TYPE) addr, 0);
   8.204  
   8.205    if (count > 1)
   8.206      {
   8.207        buffer[count - 1]
   8.208 -	= myptrace (xc_handle, PTRACE_PEEKTEXT, inferior_pid,
   8.209 +	= myptrace (xc_handle, PTRACE_PEEKTEXT, curvcpuid(),
   8.210  		  (PTRACE_ARG3_TYPE) (addr + (count - 1)
   8.211  				      * sizeof (PTRACE_XFER_TYPE)),
   8.212  		  0);
   8.213 @@ -444,7 +460,8 @@ linux_write_memory (CORE_ADDR memaddr, c
   8.214    for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE))
   8.215      {
   8.216        errno = 0;
   8.217 -      myptrace (xc_handle, PTRACE_POKETEXT, inferior_pid, (PTRACE_ARG3_TYPE) addr, buffer[i]);
   8.218 +      myptrace (xc_handle, PTRACE_POKETEXT, curvcpuid(), 
   8.219 +		(PTRACE_ARG3_TYPE) addr, buffer[i]);
   8.220        if (errno)
   8.221  	return errno;
   8.222      }
   8.223 @@ -455,9 +472,11 @@ linux_write_memory (CORE_ADDR memaddr, c
   8.224  static void
   8.225  linux_look_up_symbols (void)
   8.226  {
   8.227 -#if 0
   8.228 +  if (using_threads) 
   8.229 +    return;
   8.230 +
   8.231    using_threads = thread_db_init ();
   8.232 -#endif
   8.233 +
   8.234  }
   8.235  
   8.236  static void
   8.237 @@ -535,6 +554,7 @@ linux_init_signals ()
   8.238  void
   8.239  initialize_low (void)
   8.240  {
   8.241 +  using_threads = 0;
   8.242    xc_handle = xc_interface_open();
   8.243    set_target_ops (&linux_xen_target_ops);
   8.244    set_breakpoint_data (the_low_target.breakpoint,
   8.245 @@ -548,5 +568,122 @@ initialize_low (void)
   8.246        myptrace = xc_ptrace;
   8.247        myxcwait = xc_waitdomain;
   8.248    }
   8.249 +  using_threads = thread_db_init ();
   8.250  
   8.251  }
   8.252 +
   8.253 +
   8.254 +static void
   8.255 +thread_create_callback(long vcpuid)
   8.256 +{
   8.257 +  struct thread_info *inferior;
   8.258 +  struct process_info *process;
   8.259 +
   8.260 +  /*  If we are attaching to our first thread, things are a little
   8.261 +   *  different.  
   8.262 +   */
   8.263 +  if (all_threads.head == all_threads.tail)
   8.264 +    {
   8.265 +      inferior = (struct thread_info *) all_threads.head;
   8.266 +      process = get_thread_process (inferior);
   8.267 +      if (process->thread_known == 0)
   8.268 +	{
   8.269 +	  /* Switch to indexing the threads list by TID.  */
   8.270 +	  change_inferior_id (&all_threads, vcpuid);
   8.271 +	  goto found;
   8.272 +	}
   8.273 +    }
   8.274 +  if (debug_threads)
   8.275 +    fprintf (stderr, "looking up thread %ld\n",
   8.276 +	     vcpuid);
   8.277 +  inferior = (struct thread_info *) find_inferior_id (&all_threads,
   8.278 +						      vcpuid);
   8.279 +  /* if vcpu alread registered - do nothing */
   8.280 +  if (inferior != NULL) 
   8.281 +    return;
   8.282 +
   8.283 +  if (debug_threads)
   8.284 +    fprintf (stderr, "Attaching to thread %ld\n",
   8.285 +	     vcpuid);
   8.286 +
   8.287 +  process = add_process(current_domid, vcpuid);
   8.288 +
   8.289 +  add_thread(vcpuid, process);
   8.290 +  inferior = (struct thread_info *) find_inferior_id (&all_threads,
   8.291 +						      vcpuid);
   8.292 +  if (inferior == NULL)
   8.293 +    {
   8.294 +      warning ("Could not attach to thread %ld\n",
   8.295 +	       vcpuid);
   8.296 +      return;
   8.297 +    }
   8.298 +
   8.299 +
   8.300 +found:
   8.301 +  if (debug_threads)
   8.302 +    fprintf (stderr, "notifying of new thread %ld\n",
   8.303 +	     vcpuid);
   8.304 +  new_thread_notify (vcpuid);
   8.305 +
   8.306 +  process->tid = vcpuid;
   8.307 +  process->lwpid = vcpuid;
   8.308 +
   8.309 +  process->thread_known = 1;
   8.310 +}
   8.311 +
   8.312 +static void
   8.313 +thread_death_callback(long vcpuid)
   8.314 +{
   8.315 +    if (debug_threads)
   8.316 +      fprintf (stderr, "Buuurp...! CPU down event.\n");
   8.317 +}
   8.318 +
   8.319 +int
   8.320 +thread_db_init(void)
   8.321 +{
   8.322 +  debug_threads = 0;
   8.323 +  xc_register_event_handler(thread_create_callback, TD_CREATE);
   8.324 +  xc_register_event_handler(thread_death_callback, TD_DEATH);
   8.325 +  return 1;
   8.326 +}
   8.327 +
   8.328 +/* XXX GAG ME */
   8.329 +static int breakpoint_found;
   8.330 +static void
   8.331 +set_breakpoint_inferior (struct inferior_list_entry *entry)
   8.332 +{
   8.333 +  struct thread_info *thread = (struct thread_info *) entry;
   8.334 +  struct thread_info *saved_inferior = current_inferior;
   8.335 +  CORE_ADDR eip;
   8.336 +  unsigned char buf[2] = {0, 0};
   8.337 +  current_inferior = thread;
   8.338 +  if (!breakpoint_found) {
   8.339 +    eip = get_stop_pc();
   8.340 +    linux_read_memory(eip, buf, 1);
   8.341 +    if (buf[0] == 0xcc) {
   8.342 +      breakpoint_found = 1;
   8.343 +      return;
   8.344 +    }
   8.345 +  } else if (breakpoint_found == 2) {
   8.346 +    if (get_thread_process (current_inferior)->stepping) {
   8.347 +      printf("stepping\n");
   8.348 +      breakpoint_found = 1;
   8.349 +      return;
   8.350 +    } 
   8.351 +  }
   8.352 +  current_inferior = saved_inferior;
   8.353 +
   8.354 +
   8.355 +}
   8.356 +
   8.357 +static void
   8.358 +linux_set_inferior (void)
   8.359 +{
   8.360 +  breakpoint_found = 0;
   8.361 +  for_each_inferior (&all_threads, set_breakpoint_inferior);
   8.362 +  if (!breakpoint_found) {
   8.363 +    breakpoint_found = 2;
   8.364 +    for_each_inferior (&all_threads, set_breakpoint_inferior);
   8.365 +  }
   8.366 +}
   8.367 +
     9.1 --- a/tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/server.c	Tue Dec 20 17:16:15 2005 +0000
     9.2 +++ b/tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/server.c	Tue Dec 20 17:16:24 2005 +0000
     9.3 @@ -20,7 +20,7 @@
     9.4     Boston, MA 02111-1307, USA.  */
     9.5  
     9.6  #include "server.h"
     9.7 -
     9.8 +#include "linux-low.h"
     9.9  #include <unistd.h>
    9.10  #include <signal.h>
    9.11  #include <sys/wait.h>
    9.12 @@ -102,7 +102,15 @@ handle_query (char *own_buf)
    9.13        strcpy (own_buf, "OK");
    9.14        return;
    9.15      }
    9.16 +  if (strcmp ("qC", own_buf) == 0)
    9.17 +    {
    9.18 +      struct process_info *process;
    9.19 +      if (current_inferior == NULL)
    9.20 +	return;
    9.21 +      process = get_thread_process(current_inferior);
    9.22 +      sprintf(own_buf, "QC%x", process->thread_known ? process->tid : 0);
    9.23  
    9.24 +    }
    9.25    if (strcmp ("qfThreadInfo", own_buf) == 0)
    9.26      {
    9.27        thread_ptr = all_threads.head;
    10.1 --- a/tools/examples/xend-config.sxp	Tue Dec 20 17:16:15 2005 +0000
    10.2 +++ b/tools/examples/xend-config.sxp	Tue Dec 20 17:16:24 2005 +0000
    10.3 @@ -4,9 +4,9 @@
    10.4  # Xend configuration file.
    10.5  #
    10.6  
    10.7 -# This example configuration is appropriate for an installation that trusts
    10.8 -# only localhost connections, and is otherwise fully functional, with a
    10.9 -# bridged network configuration.
   10.10 +# This example configuration is appropriate for an installation that 
   10.11 +# utilizes a bridged network configuration. Access to xend via http
   10.12 +# is disabled.  
   10.13  
   10.14  # Commented out entries show the default for that entry, unless otherwise
   10.15  # specified.
   10.16 @@ -15,7 +15,6 @@
   10.17  #(loglevel DEBUG)
   10.18  
   10.19  #(xend-http-server no)
   10.20 -(xend-http-server yes)
   10.21  #(xend-unix-server yes)
   10.22  #(xend-relocation-server no)
   10.23  (xend-relocation-server yes)
   10.24 @@ -34,7 +33,7 @@
   10.25  # Specifying 'localhost' prevents remote connections.
   10.26  # Specifying the empty string '' (the default) allows all connections.
   10.27  #(xend-address '')
   10.28 -(xend-address localhost)
   10.29 +#(xend-address localhost)
   10.30  
   10.31  # Address xend should listen on for relocation-socket connections, if
   10.32  # xend-relocation-server is set.
    11.1 --- a/tools/examples/xmexample.vmx	Tue Dec 20 17:16:15 2005 +0000
    11.2 +++ b/tools/examples/xmexample.vmx	Tue Dec 20 17:16:24 2005 +0000
    11.3 @@ -135,7 +135,7 @@ ne2000=0
    11.4  
    11.5  #-----------------------------------------------------------------------------
    11.6  #   enable audio support
    11.7 -#enable-audio=1
    11.8 +#audio=1
    11.9  
   11.10  
   11.11  #-----------------------------------------------------------------------------
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/tools/ioemu/audio/audio.c	Tue Dec 20 17:16:24 2005 +0000
    12.3 @@ -0,0 +1,910 @@
    12.4 +/*
    12.5 + * QEMU Audio subsystem
    12.6 + * 
    12.7 + * Copyright (c) 2003-2004 Vassili Karpov (malc)
    12.8 + * 
    12.9 + * Permission is hereby granted, free of charge, to any person obtaining a copy
   12.10 + * of this software and associated documentation files (the "Software"), to deal
   12.11 + * in the Software without restriction, including without limitation the rights
   12.12 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   12.13 + * copies of the Software, and to permit persons to whom the Software is
   12.14 + * furnished to do so, subject to the following conditions:
   12.15 + *
   12.16 + * The above copyright notice and this permission notice shall be included in
   12.17 + * all copies or substantial portions of the Software.
   12.18 + *
   12.19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   12.20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   12.21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   12.22 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   12.23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   12.24 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   12.25 + * THE SOFTWARE.
   12.26 + */
   12.27 +#include <assert.h>
   12.28 +#include "vl.h"
   12.29 +
   12.30 +#define USE_WAV_AUDIO
   12.31 +
   12.32 +#include "audio/audio_int.h"
   12.33 +
   12.34 +#define dolog(...) AUD_log ("audio", __VA_ARGS__)
   12.35 +#ifdef DEBUG
   12.36 +#define ldebug(...) dolog (__VA_ARGS__)
   12.37 +#else
   12.38 +#define ldebug(...)
   12.39 +#endif
   12.40 +
   12.41 +#define QC_AUDIO_DRV    "QEMU_AUDIO_DRV"
   12.42 +#define QC_VOICES       "QEMU_VOICES"
   12.43 +#define QC_FIXED_FORMAT "QEMU_FIXED_FORMAT"
   12.44 +#define QC_FIXED_FREQ   "QEMU_FIXED_FREQ"
   12.45 +
   12.46 +static HWVoice *hw_voices;
   12.47 +
   12.48 +AudioState audio_state = {
   12.49 +    1,                          /* use fixed settings */
   12.50 +    44100,                      /* fixed frequency */
   12.51 +    2,                          /* fixed channels */
   12.52 +    AUD_FMT_S16,                /* fixed format */
   12.53 +    1,                          /* number of hw voices */
   12.54 +    -1                          /* voice size */
   12.55 +};
   12.56 +
   12.57 +/* http://www.df.lth.se/~john_e/gems/gem002d.html */
   12.58 +/* http://www.multi-platforms.com/Tips/PopCount.htm */
   12.59 +uint32_t popcount (uint32_t u)
   12.60 +{
   12.61 +    u = ((u&0x55555555) + ((u>>1)&0x55555555));
   12.62 +    u = ((u&0x33333333) + ((u>>2)&0x33333333));
   12.63 +    u = ((u&0x0f0f0f0f) + ((u>>4)&0x0f0f0f0f));
   12.64 +    u = ((u&0x00ff00ff) + ((u>>8)&0x00ff00ff));
   12.65 +    u = ( u&0x0000ffff) + (u>>16);
   12.66 +    return u;
   12.67 +}
   12.68 +
   12.69 +inline uint32_t lsbindex (uint32_t u)
   12.70 +{
   12.71 +    return popcount ((u&-u)-1);
   12.72 +}
   12.73 +
   12.74 +int audio_get_conf_int (const char *key, int defval)
   12.75 +{
   12.76 +    int val = defval;
   12.77 +    char *strval;
   12.78 +
   12.79 +    strval = getenv (key);
   12.80 +    if (strval) {
   12.81 +        val = atoi (strval);
   12.82 +    }
   12.83 +
   12.84 +    return val;
   12.85 +}
   12.86 +
   12.87 +const char *audio_get_conf_str (const char *key, const char *defval)
   12.88 +{
   12.89 +    const char *val = getenv (key);
   12.90 +    if (!val)
   12.91 +        return defval;
   12.92 +    else
   12.93 +        return val;
   12.94 +}
   12.95 +
   12.96 +void AUD_log (const char *cap, const char *fmt, ...)
   12.97 +{
   12.98 +    va_list ap;
   12.99 +    fprintf (stderr, "%s: ", cap);
  12.100 +    va_start (ap, fmt);
  12.101 +    vfprintf (stderr, fmt, ap);
  12.102 +    va_end (ap);
  12.103 +}
  12.104 +
  12.105 +/*
  12.106 + * Soft Voice
  12.107 + */
  12.108 +void pcm_sw_free_resources (SWVoice *sw)
  12.109 +{
  12.110 +    if (sw->buf) qemu_free (sw->buf);
  12.111 +    if (sw->rate) st_rate_stop (sw->rate);
  12.112 +    sw->buf = NULL;
  12.113 +    sw->rate = NULL;
  12.114 +}
  12.115 +
  12.116 +int pcm_sw_alloc_resources (SWVoice *sw)
  12.117 +{
  12.118 +    sw->buf = qemu_mallocz (sw->hw->samples * sizeof (st_sample_t));
  12.119 +    if (!sw->buf)
  12.120 +        return -1;
  12.121 +
  12.122 +    sw->rate = st_rate_start (sw->freq, sw->hw->freq);
  12.123 +    if (!sw->rate) {
  12.124 +        qemu_free (sw->buf);
  12.125 +        sw->buf = NULL;
  12.126 +        return -1;
  12.127 +    }
  12.128 +    return 0;
  12.129 +}
  12.130 +
  12.131 +void pcm_sw_fini (SWVoice *sw)
  12.132 +{
  12.133 +    pcm_sw_free_resources (sw);
  12.134 +}
  12.135 +
  12.136 +int pcm_sw_init (SWVoice *sw, HWVoice *hw, int freq,
  12.137 +                 int nchannels, audfmt_e fmt)
  12.138 +{
  12.139 +    int bits = 8, sign = 0;
  12.140 +
  12.141 +    switch (fmt) {
  12.142 +    case AUD_FMT_S8:
  12.143 +        sign = 1;
  12.144 +    case AUD_FMT_U8:
  12.145 +        break;
  12.146 +
  12.147 +    case AUD_FMT_S16:
  12.148 +        sign = 1;
  12.149 +    case AUD_FMT_U16:
  12.150 +        bits = 16;
  12.151 +        break;
  12.152 +    }
  12.153 +
  12.154 +    sw->hw = hw;
  12.155 +    sw->freq = freq;
  12.156 +    sw->fmt = fmt;
  12.157 +    sw->nchannels = nchannels;
  12.158 +    sw->shift = (nchannels == 2) + (bits == 16);
  12.159 +    sw->align = (1 << sw->shift) - 1;
  12.160 +    sw->left = 0;
  12.161 +    sw->pos = 0;
  12.162 +    sw->wpos = 0;
  12.163 +    sw->live = 0;
  12.164 +    sw->ratio = (sw->hw->freq * ((int64_t) INT_MAX)) / sw->freq;
  12.165 +    sw->bytes_per_second = sw->freq << sw->shift;
  12.166 +    sw->conv = mixeng_conv[nchannels == 2][sign][bits == 16];
  12.167 +
  12.168 +    pcm_sw_free_resources (sw);
  12.169 +    return pcm_sw_alloc_resources (sw);
  12.170 +}
  12.171 +
  12.172 +/* Hard voice */
  12.173 +void pcm_hw_free_resources (HWVoice *hw)
  12.174 +{
  12.175 +    if (hw->mix_buf)
  12.176 +        qemu_free (hw->mix_buf);
  12.177 +    hw->mix_buf = NULL;
  12.178 +}
  12.179 +
  12.180 +int pcm_hw_alloc_resources (HWVoice *hw)
  12.181 +{
  12.182 +    hw->mix_buf = qemu_mallocz (hw->samples * sizeof (st_sample_t));
  12.183 +    if (!hw->mix_buf)
  12.184 +        return -1;
  12.185 +    return 0;
  12.186 +}
  12.187 +
  12.188 +void pcm_hw_fini (HWVoice *hw)
  12.189 +{
  12.190 +    if (hw->active) {
  12.191 +        ldebug ("pcm_hw_fini: %d %d %d\n", hw->freq, hw->nchannels, hw->fmt);
  12.192 +        pcm_hw_free_resources (hw);
  12.193 +        hw->pcm_ops->fini (hw);
  12.194 +        memset (hw, 0, audio_state.drv->voice_size);
  12.195 +    }
  12.196 +}
  12.197 +
  12.198 +void pcm_hw_gc (HWVoice *hw)
  12.199 +{
  12.200 +    if (hw->nb_voices)
  12.201 +        return;
  12.202 +
  12.203 +    pcm_hw_fini (hw);
  12.204 +}
  12.205 +
  12.206 +int pcm_hw_get_live (HWVoice *hw)
  12.207 +{
  12.208 +    int i, alive = 0, live = hw->samples;
  12.209 +
  12.210 +    for (i = 0; i < hw->nb_voices; i++) {
  12.211 +        if (hw->pvoice[i]->live) {
  12.212 +            live = audio_MIN (hw->pvoice[i]->live, live);
  12.213 +            alive += 1;
  12.214 +        }
  12.215 +    }
  12.216 +
  12.217 +    if (alive)
  12.218 +        return live;
  12.219 +    else
  12.220 +        return -1;
  12.221 +}
  12.222 +
  12.223 +int pcm_hw_get_live2 (HWVoice *hw, int *nb_active)
  12.224 +{
  12.225 +    int i, alive = 0, live = hw->samples;
  12.226 +
  12.227 +    *nb_active = 0;
  12.228 +    for (i = 0; i < hw->nb_voices; i++) {
  12.229 +        if (hw->pvoice[i]->live) {
  12.230 +            if (hw->pvoice[i]->live < live) {
  12.231 +                *nb_active = hw->pvoice[i]->active != 0;
  12.232 +                live = hw->pvoice[i]->live;
  12.233 +            }
  12.234 +            alive += 1;
  12.235 +        }
  12.236 +    }
  12.237 +
  12.238 +    if (alive)
  12.239 +        return live;
  12.240 +    else
  12.241 +        return -1;
  12.242 +}
  12.243 +
  12.244 +void pcm_hw_dec_live (HWVoice *hw, int decr)
  12.245 +{
  12.246 +    int i;
  12.247 +
  12.248 +    for (i = 0; i < hw->nb_voices; i++) {
  12.249 +        if (hw->pvoice[i]->live) {
  12.250 +            hw->pvoice[i]->live -= decr;
  12.251 +        }
  12.252 +    }
  12.253 +}
  12.254 +
  12.255 +void pcm_hw_clear (HWVoice *hw, void *buf, int len)
  12.256 +{
  12.257 +    if (!len)
  12.258 +        return;
  12.259 +
  12.260 +    switch (hw->fmt) {
  12.261 +    case AUD_FMT_S16:
  12.262 +    case AUD_FMT_S8:
  12.263 +        memset (buf, len << hw->shift, 0x00);
  12.264 +        break;
  12.265 +
  12.266 +    case AUD_FMT_U8:
  12.267 +        memset (buf, len << hw->shift, 0x80);
  12.268 +        break;
  12.269 +
  12.270 +    case AUD_FMT_U16:
  12.271 +        {
  12.272 +            unsigned int i;
  12.273 +            uint16_t *p = buf;
  12.274 +            int shift = hw->nchannels - 1;
  12.275 +
  12.276 +            for (i = 0; i < len << shift; i++) {
  12.277 +                p[i] = INT16_MAX;
  12.278 +            }
  12.279 +        }
  12.280 +        break;
  12.281 +    }
  12.282 +}
  12.283 +
  12.284 +int pcm_hw_write (SWVoice *sw, void *buf, int size)
  12.285 +{
  12.286 +    int hwsamples, samples, isamp, osamp, wpos, live, dead, left, swlim, blck;
  12.287 +    int ret = 0, pos = 0;
  12.288 +    if (!sw)
  12.289 +        return size;
  12.290 +
  12.291 +    hwsamples = sw->hw->samples;
  12.292 +    samples = size >> sw->shift;
  12.293 +
  12.294 +    if (!sw->live) {
  12.295 +        sw->wpos = sw->hw->rpos;
  12.296 +    }
  12.297 +    wpos = sw->wpos;
  12.298 +    live = sw->live;
  12.299 +    dead = hwsamples - live;
  12.300 +    swlim = (dead * ((int64_t) INT_MAX)) / sw->ratio;
  12.301 +    swlim = audio_MIN (swlim, samples);
  12.302 +
  12.303 +    ldebug ("size=%d live=%d dead=%d swlim=%d wpos=%d\n",
  12.304 +           size, live, dead, swlim, wpos);
  12.305 +    if (swlim)
  12.306 +        sw->conv (sw->buf, buf, swlim);
  12.307 +
  12.308 +    while (swlim) {
  12.309 +        dead = hwsamples - live;
  12.310 +        left = hwsamples - wpos;
  12.311 +        blck = audio_MIN (dead, left);
  12.312 +        if (!blck) {
  12.313 +            /* dolog ("swlim=%d\n", swlim); */
  12.314 +            break;
  12.315 +        }
  12.316 +        isamp = swlim;
  12.317 +        osamp = blck;
  12.318 +        st_rate_flow (sw->rate, sw->buf + pos, sw->hw->mix_buf + wpos, &isamp, &osamp);
  12.319 +        ret += isamp;
  12.320 +        swlim -= isamp;
  12.321 +        pos += isamp;
  12.322 +        live += osamp;
  12.323 +        wpos = (wpos + osamp) % hwsamples;
  12.324 +    }
  12.325 +
  12.326 +    sw->wpos = wpos;
  12.327 +    sw->live = live;
  12.328 +    return ret << sw->shift;
  12.329 +}
  12.330 +
  12.331 +int pcm_hw_init (HWVoice *hw, int freq, int nchannels, audfmt_e fmt)
  12.332 +{
  12.333 +    int sign = 0, bits = 8;
  12.334 +
  12.335 +    pcm_hw_fini (hw);
  12.336 +    ldebug ("pcm_hw_init: %d %d %d\n", freq, nchannels, fmt);
  12.337 +    if (hw->pcm_ops->init (hw, freq, nchannels, fmt)) {
  12.338 +        memset (hw, 0, audio_state.drv->voice_size);
  12.339 +        return -1;
  12.340 +    }
  12.341 +
  12.342 +    switch (hw->fmt) {
  12.343 +    case AUD_FMT_S8:
  12.344 +        sign = 1;
  12.345 +    case AUD_FMT_U8:
  12.346 +        break;
  12.347 +
  12.348 +    case AUD_FMT_S16:
  12.349 +        sign = 1;
  12.350 +    case AUD_FMT_U16:
  12.351 +        bits = 16;
  12.352 +        break;
  12.353 +    }
  12.354 +
  12.355 +    hw->nb_voices = 0;
  12.356 +    hw->active = 1;
  12.357 +    hw->shift = (hw->nchannels == 2) + (bits == 16);
  12.358 +    hw->bytes_per_second = hw->freq << hw->shift;
  12.359 +    hw->align = (1 << hw->shift) - 1;
  12.360 +    hw->samples = hw->bufsize >> hw->shift;
  12.361 +    hw->clip = mixeng_clip[hw->nchannels == 2][sign][bits == 16];
  12.362 +    if (pcm_hw_alloc_resources (hw)) {
  12.363 +        pcm_hw_fini (hw);
  12.364 +        return -1;
  12.365 +    }
  12.366 +    return 0;
  12.367 +}
  12.368 +
  12.369 +static int dist (void *hw)
  12.370 +{
  12.371 +    if (hw) {
  12.372 +        return (((uint8_t *) hw - (uint8_t *) hw_voices)
  12.373 +                / audio_state.voice_size) + 1;
  12.374 +    }
  12.375 +    else {
  12.376 +        return 0;
  12.377 +    }
  12.378 +}
  12.379 +
  12.380 +#define ADVANCE(hw) hw ? advance (hw, audio_state.voice_size) : hw_voices
  12.381 +
  12.382 +HWVoice *pcm_hw_find_any (HWVoice *hw)
  12.383 +{
  12.384 +    int i = dist (hw);
  12.385 +    for (; i < audio_state.nb_hw_voices; i++) {
  12.386 +        hw = ADVANCE (hw);
  12.387 +        return hw;
  12.388 +    }
  12.389 +    return NULL;
  12.390 +}
  12.391 +
  12.392 +HWVoice *pcm_hw_find_any_active (HWVoice *hw)
  12.393 +{
  12.394 +    int i = dist (hw);
  12.395 +    for (; i < audio_state.nb_hw_voices; i++) {
  12.396 +        hw = ADVANCE (hw);
  12.397 +        if (hw->active)
  12.398 +            return hw;
  12.399 +    }
  12.400 +    return NULL;
  12.401 +}
  12.402 +
  12.403 +HWVoice *pcm_hw_find_any_active_enabled (HWVoice *hw)
  12.404 +{
  12.405 +    int i = dist (hw);
  12.406 +    for (; i < audio_state.nb_hw_voices; i++) {
  12.407 +        hw = ADVANCE (hw);
  12.408 +        if (hw->active && hw->enabled)
  12.409 +            return hw;
  12.410 +    }
  12.411 +    return NULL;
  12.412 +}
  12.413 +
  12.414 +HWVoice *pcm_hw_find_any_passive (HWVoice *hw)
  12.415 +{
  12.416 +    int i = dist (hw);
  12.417 +    for (; i < audio_state.nb_hw_voices; i++) {
  12.418 +        hw = ADVANCE (hw);
  12.419 +        if (!hw->active)
  12.420 +            return hw;
  12.421 +    }
  12.422 +    return NULL;
  12.423 +}
  12.424 +
  12.425 +HWVoice *pcm_hw_find_specific (HWVoice *hw, int freq,
  12.426 +                               int nchannels, audfmt_e fmt)
  12.427 +{
  12.428 +    while ((hw = pcm_hw_find_any_active (hw))) {
  12.429 +        if (hw->freq == freq &&
  12.430 +            hw->nchannels == nchannels &&
  12.431 +            hw->fmt == fmt)
  12.432 +            return hw;
  12.433 +    }
  12.434 +    return NULL;
  12.435 +}
  12.436 +
  12.437 +HWVoice *pcm_hw_add (int freq, int nchannels, audfmt_e fmt)
  12.438 +{
  12.439 +    HWVoice *hw;
  12.440 +
  12.441 +    if (audio_state.fixed_format) {
  12.442 +        freq = audio_state.fixed_freq;
  12.443 +        nchannels = audio_state.fixed_channels;
  12.444 +        fmt = audio_state.fixed_fmt;
  12.445 +    }
  12.446 +
  12.447 +    hw = pcm_hw_find_specific (NULL, freq, nchannels, fmt);
  12.448 +
  12.449 +    if (hw)
  12.450 +        return hw;
  12.451 +
  12.452 +    hw = pcm_hw_find_any_passive (NULL);
  12.453 +    if (hw) {
  12.454 +        hw->pcm_ops = audio_state.drv->pcm_ops;
  12.455 +        if (!hw->pcm_ops)
  12.456 +            return NULL;
  12.457 +
  12.458 +        if (pcm_hw_init (hw, freq, nchannels, fmt)) {
  12.459 +            pcm_hw_gc (hw);
  12.460 +            return NULL;
  12.461 +        }
  12.462 +        else
  12.463 +            return hw;
  12.464 +    }
  12.465 +
  12.466 +    return pcm_hw_find_any (NULL);
  12.467 +}
  12.468 +
  12.469 +int pcm_hw_add_sw (HWVoice *hw, SWVoice *sw)
  12.470 +{
  12.471 +    SWVoice **pvoice = qemu_mallocz ((hw->nb_voices + 1) * sizeof (sw));
  12.472 +    if (!pvoice)
  12.473 +        return -1;
  12.474 +
  12.475 +    memcpy (pvoice, hw->pvoice, hw->nb_voices * sizeof (sw));
  12.476 +    qemu_free (hw->pvoice);
  12.477 +    hw->pvoice = pvoice;
  12.478 +    hw->pvoice[hw->nb_voices++] = sw;
  12.479 +    return 0;
  12.480 +}
  12.481 +
  12.482 +int pcm_hw_del_sw (HWVoice *hw, SWVoice *sw)
  12.483 +{
  12.484 +    int i, j;
  12.485 +    if (hw->nb_voices > 1) {
  12.486 +        SWVoice **pvoice = qemu_mallocz ((hw->nb_voices - 1) * sizeof (sw));
  12.487 +
  12.488 +        if (!pvoice) {
  12.489 +            dolog ("Can not maintain consistent state (not enough memory)\n");
  12.490 +            return -1;
  12.491 +        }
  12.492 +
  12.493 +        for (i = 0, j = 0; i < hw->nb_voices; i++) {
  12.494 +            if (j >= hw->nb_voices - 1) {
  12.495 +                dolog ("Can not maintain consistent state "
  12.496 +                       "(invariant violated)\n");
  12.497 +                return -1;
  12.498 +            }
  12.499 +            if (hw->pvoice[i] != sw)
  12.500 +                pvoice[j++] = hw->pvoice[i];
  12.501 +        }
  12.502 +        qemu_free (hw->pvoice);
  12.503 +        hw->pvoice = pvoice;
  12.504 +        hw->nb_voices -= 1;
  12.505 +    }
  12.506 +    else {
  12.507 +        qemu_free (hw->pvoice);
  12.508 +        hw->pvoice = NULL;
  12.509 +        hw->nb_voices = 0;
  12.510 +    }
  12.511 +    return 0;
  12.512 +}
  12.513 +
  12.514 +SWVoice *pcm_create_voice_pair (int freq, int nchannels, audfmt_e fmt)
  12.515 +{
  12.516 +    SWVoice *sw;
  12.517 +    HWVoice *hw;
  12.518 +
  12.519 +    sw = qemu_mallocz (sizeof (*sw));
  12.520 +    if (!sw)
  12.521 +        goto err1;
  12.522 +
  12.523 +    hw = pcm_hw_add (freq, nchannels, fmt);
  12.524 +    if (!hw)
  12.525 +        goto err2;
  12.526 +
  12.527 +    if (pcm_hw_add_sw (hw, sw))
  12.528 +        goto err3;
  12.529 +
  12.530 +    if (pcm_sw_init (sw, hw, freq, nchannels, fmt))
  12.531 +        goto err4;
  12.532 +
  12.533 +    return sw;
  12.534 +
  12.535 +err4:
  12.536 +    pcm_hw_del_sw (hw, sw);
  12.537 +err3:
  12.538 +    pcm_hw_gc (hw);
  12.539 +err2:
  12.540 +    qemu_free (sw);
  12.541 +err1:
  12.542 +    return NULL;
  12.543 +}
  12.544 +
  12.545 +SWVoice *AUD_open (SWVoice *sw, const char *name,
  12.546 +                   int freq, int nchannels, audfmt_e fmt)
  12.547 +{
  12.548 +    if (!audio_state.drv) {
  12.549 +        return NULL;
  12.550 +    }
  12.551 +
  12.552 +    if (sw && freq == sw->freq && sw->nchannels == nchannels && sw->fmt == fmt) {
  12.553 +        return sw;
  12.554 +    }
  12.555 +
  12.556 +    if (sw) {
  12.557 +        ldebug ("Different format %s %d %d %d\n",
  12.558 +                name,
  12.559 +                sw->freq == freq,
  12.560 +                sw->nchannels == nchannels,
  12.561 +                sw->fmt == fmt);
  12.562 +    }
  12.563 +
  12.564 +    if (nchannels != 1 && nchannels != 2) {
  12.565 +        dolog ("Bogus channel count %d for voice %s\n", nchannels, name);
  12.566 +        return NULL;
  12.567 +    }
  12.568 +
  12.569 +    if (!audio_state.fixed_format && sw) {
  12.570 +        pcm_sw_fini (sw);
  12.571 +        pcm_hw_del_sw (sw->hw, sw);
  12.572 +        pcm_hw_gc (sw->hw);
  12.573 +        if (sw->name) {
  12.574 +            qemu_free (sw->name);
  12.575 +            sw->name = NULL;
  12.576 +        }
  12.577 +        qemu_free (sw);
  12.578 +        sw = NULL;
  12.579 +    }
  12.580 +
  12.581 +    if (sw) {
  12.582 +        HWVoice *hw = sw->hw;
  12.583 +        if (!hw) {
  12.584 +            dolog ("Internal logic error voice %s has no hardware store\n",
  12.585 +                   name);
  12.586 +            return sw;
  12.587 +        }
  12.588 +
  12.589 +        if (pcm_sw_init (sw, hw, freq, nchannels, fmt)) {
  12.590 +            pcm_sw_fini (sw);
  12.591 +            pcm_hw_del_sw (hw, sw);
  12.592 +            pcm_hw_gc (hw);
  12.593 +            if (sw->name) {
  12.594 +                qemu_free (sw->name);
  12.595 +                sw->name = NULL;
  12.596 +            }
  12.597 +            qemu_free (sw);
  12.598 +            return NULL;
  12.599 +        }
  12.600 +    }
  12.601 +    else {
  12.602 +        sw = pcm_create_voice_pair (freq, nchannels, fmt);
  12.603 +        if (!sw) {
  12.604 +            dolog ("Failed to create voice %s\n", name);
  12.605 +            return NULL;
  12.606 +        }
  12.607 +    }
  12.608 +
  12.609 +    if (sw->name) {
  12.610 +        qemu_free (sw->name);
  12.611 +        sw->name = NULL;
  12.612 +    }
  12.613 +    sw->name = qemu_strdup (name);
  12.614 +    return sw;
  12.615 +}
  12.616 +
  12.617 +void AUD_close (SWVoice *sw)
  12.618 +{
  12.619 +    if (!sw)
  12.620 +        return;
  12.621 +
  12.622 +    pcm_sw_fini (sw);
  12.623 +    pcm_hw_del_sw (sw->hw, sw);
  12.624 +    pcm_hw_gc (sw->hw);
  12.625 +    if (sw->name) {
  12.626 +        qemu_free (sw->name);
  12.627 +        sw->name = NULL;
  12.628 +    }
  12.629 +    qemu_free (sw);
  12.630 +}
  12.631 +
  12.632 +int AUD_write (SWVoice *sw, void *buf, int size)
  12.633 +{
  12.634 +    int bytes;
  12.635 +
  12.636 +    if (!sw->hw->enabled)
  12.637 +        dolog ("Writing to disabled voice %s\n", sw->name);
  12.638 +    bytes = sw->hw->pcm_ops->write (sw, buf, size);
  12.639 +    return bytes;
  12.640 +}
  12.641 +
  12.642 +void AUD_run (void)
  12.643 +{
  12.644 +    HWVoice *hw = NULL;
  12.645 +
  12.646 +    while ((hw = pcm_hw_find_any_active_enabled (hw))) {
  12.647 +        int i;
  12.648 +        if (hw->pending_disable && pcm_hw_get_live (hw) <= 0) {
  12.649 +            hw->enabled = 0;
  12.650 +            hw->pcm_ops->ctl (hw, VOICE_DISABLE);
  12.651 +            for (i = 0; i < hw->nb_voices; i++) {
  12.652 +                hw->pvoice[i]->live = 0;
  12.653 +                /* hw->pvoice[i]->old_ticks = 0; */
  12.654 +            }
  12.655 +            continue;
  12.656 +        }
  12.657 +
  12.658 +        hw->pcm_ops->run (hw);
  12.659 +        assert (hw->rpos < hw->samples);
  12.660 +        for (i = 0; i < hw->nb_voices; i++) {
  12.661 +            SWVoice *sw = hw->pvoice[i];
  12.662 +            if (!sw->active && !sw->live && sw->old_ticks) {
  12.663 +                int64_t delta = qemu_get_clock (vm_clock) - sw->old_ticks;
  12.664 +                if (delta > audio_state.ticks_threshold) {
  12.665 +                    ldebug ("resetting old_ticks for %s\n", sw->name);
  12.666 +                    sw->old_ticks = 0;
  12.667 +                }
  12.668 +            }
  12.669 +        }
  12.670 +    }
  12.671 +}
  12.672 +
  12.673 +int AUD_get_free (SWVoice *sw)
  12.674 +{
  12.675 +    int free;
  12.676 +
  12.677 +    if (!sw)
  12.678 +        return 4096;
  12.679 +
  12.680 +    free = ((sw->hw->samples - sw->live) << sw->hw->shift) * sw->ratio
  12.681 +        / INT_MAX;
  12.682 +
  12.683 +    free &= ~sw->hw->align;
  12.684 +    if (!free) return 0;
  12.685 +
  12.686 +    return free;
  12.687 +}
  12.688 +
  12.689 +int AUD_get_buffer_size (SWVoice *sw)
  12.690 +{
  12.691 +    return sw->hw->bufsize;
  12.692 +}
  12.693 +
  12.694 +void AUD_adjust (SWVoice *sw, int bytes)
  12.695 +{
  12.696 +    if (!sw)
  12.697 +        return;
  12.698 +    sw->old_ticks += (ticks_per_sec * (int64_t) bytes) / sw->bytes_per_second;
  12.699 +}
  12.700 +
  12.701 +void AUD_reset (SWVoice *sw)
  12.702 +{
  12.703 +    sw->active = 0;
  12.704 +    sw->old_ticks = 0;
  12.705 +}
  12.706 +
  12.707 +int AUD_calc_elapsed (SWVoice *sw)
  12.708 +{
  12.709 +    int64_t now, delta, bytes;
  12.710 +    int dead, swlim;
  12.711 +
  12.712 +    if (!sw)
  12.713 +        return 0;
  12.714 +
  12.715 +    now = qemu_get_clock (vm_clock);
  12.716 +    delta = now - sw->old_ticks;
  12.717 +    bytes = (delta * sw->bytes_per_second) / ticks_per_sec;
  12.718 +    if (delta < 0) {
  12.719 +        dolog ("whoops delta(<0)=%lld\n", delta);
  12.720 +        return 0;
  12.721 +    }
  12.722 +
  12.723 +    dead = sw->hw->samples - sw->live;
  12.724 +    swlim = ((dead * (int64_t) INT_MAX) / sw->ratio);
  12.725 +
  12.726 +    if (bytes > swlim) {
  12.727 +        return swlim;
  12.728 +    }
  12.729 +    else {
  12.730 +        return bytes;
  12.731 +    }
  12.732 +}
  12.733 +
  12.734 +void AUD_enable (SWVoice *sw, int on)
  12.735 +{
  12.736 +    int i;
  12.737 +    HWVoice *hw;
  12.738 +
  12.739 +    if (!sw)
  12.740 +        return;
  12.741 +
  12.742 +    hw = sw->hw;
  12.743 +    if (on) {
  12.744 +        if (!sw->live)
  12.745 +            sw->wpos = sw->hw->rpos;
  12.746 +        if (!sw->old_ticks) {
  12.747 +            sw->old_ticks = qemu_get_clock (vm_clock);
  12.748 +        }
  12.749 +    }
  12.750 +
  12.751 +    if (sw->active != on) {
  12.752 +        if (on) {
  12.753 +            hw->pending_disable = 0;
  12.754 +            if (!hw->enabled) {
  12.755 +                hw->enabled = 1;
  12.756 +                for (i = 0; i < hw->nb_voices; i++) {
  12.757 +                    ldebug ("resetting voice\n");
  12.758 +                    sw = hw->pvoice[i];
  12.759 +                    sw->old_ticks = qemu_get_clock (vm_clock);
  12.760 +                }
  12.761 +                hw->pcm_ops->ctl (hw, VOICE_ENABLE);
  12.762 +            }
  12.763 +        }
  12.764 +        else {
  12.765 +            if (hw->enabled && !hw->pending_disable) {
  12.766 +                int nb_active = 0;
  12.767 +                for (i = 0; i < hw->nb_voices; i++) {
  12.768 +                    nb_active += hw->pvoice[i]->active != 0;
  12.769 +                }
  12.770 +
  12.771 +                if (nb_active == 1) {
  12.772 +                    hw->pending_disable = 1;
  12.773 +                }
  12.774 +            }
  12.775 +        }
  12.776 +        sw->active = on;
  12.777 +    }
  12.778 +}
  12.779 +
  12.780 +static struct audio_output_driver *drvtab[] = {
  12.781 +#ifdef CONFIG_OSS
  12.782 +    &oss_output_driver,
  12.783 +#endif
  12.784 +#ifdef CONFIG_FMOD
  12.785 +    &fmod_output_driver,
  12.786 +#endif
  12.787 +#ifdef CONFIG_SDL
  12.788 +    &sdl_output_driver,
  12.789 +#endif
  12.790 +    &no_output_driver,
  12.791 +#ifdef USE_WAV_AUDIO
  12.792 +    &wav_output_driver,
  12.793 +#endif
  12.794 +};
  12.795 +
  12.796 +static int voice_init (struct audio_output_driver *drv)
  12.797 +{
  12.798 +    audio_state.opaque = drv->init ();
  12.799 +    if (audio_state.opaque) {
  12.800 +        if (audio_state.nb_hw_voices > drv->max_voices) {
  12.801 +            dolog ("`%s' does not support %d multiple hardware channels\n"
  12.802 +                   "Resetting to %d\n",
  12.803 +                   drv->name, audio_state.nb_hw_voices, drv->max_voices);
  12.804 +            audio_state.nb_hw_voices = drv->max_voices;
  12.805 +        }
  12.806 +        hw_voices = qemu_mallocz (audio_state.nb_hw_voices * drv->voice_size);
  12.807 +        if (hw_voices) {
  12.808 +            audio_state.drv = drv;
  12.809 +            return 1;
  12.810 +        }
  12.811 +        else {
  12.812 +            dolog ("Not enough memory for %d `%s' voices (each %d bytes)\n",
  12.813 +                   audio_state.nb_hw_voices, drv->name, drv->voice_size);
  12.814 +            drv->fini (audio_state.opaque);
  12.815 +            return 0;
  12.816 +        }
  12.817 +    }
  12.818 +    else {
  12.819 +        dolog ("Could not init `%s' audio\n", drv->name);
  12.820 +        return 0;
  12.821 +    }
  12.822 +}
  12.823 +
  12.824 +static void audio_vm_stop_handler (void *opaque, int reason)
  12.825 +{
  12.826 +    HWVoice *hw = NULL;
  12.827 +
  12.828 +    while ((hw = pcm_hw_find_any (hw))) {
  12.829 +        if (!hw->pcm_ops)
  12.830 +            continue;
  12.831 +
  12.832 +        hw->pcm_ops->ctl (hw, reason ? VOICE_ENABLE : VOICE_DISABLE);
  12.833 +    }
  12.834 +}
  12.835 +
  12.836 +static void audio_atexit (void)
  12.837 +{
  12.838 +    HWVoice *hw = NULL;
  12.839 +
  12.840 +    while ((hw = pcm_hw_find_any (hw))) {
  12.841 +        if (!hw->pcm_ops)
  12.842 +            continue;
  12.843 +
  12.844 +        hw->pcm_ops->ctl (hw, VOICE_DISABLE);
  12.845 +        hw->pcm_ops->fini (hw);
  12.846 +    }
  12.847 +    audio_state.drv->fini (audio_state.opaque);
  12.848 +}
  12.849 +
  12.850 +static void audio_save (QEMUFile *f, void *opaque)
  12.851 +{
  12.852 +}
  12.853 +
  12.854 +static int audio_load (QEMUFile *f, void *opaque, int version_id)
  12.855 +{
  12.856 +    if (version_id != 1)
  12.857 +        return -EINVAL;
  12.858 +
  12.859 +    return 0;
  12.860 +}
  12.861 +
  12.862 +void AUD_init (void)
  12.863 +{
  12.864 +    int i;
  12.865 +    int done = 0;
  12.866 +    const char *drvname;
  12.867 +
  12.868 +    audio_state.fixed_format =
  12.869 +        !!audio_get_conf_int (QC_FIXED_FORMAT, audio_state.fixed_format);
  12.870 +    audio_state.fixed_freq =
  12.871 +        audio_get_conf_int (QC_FIXED_FREQ, audio_state.fixed_freq);
  12.872 +    audio_state.nb_hw_voices =
  12.873 +        audio_get_conf_int (QC_VOICES, audio_state.nb_hw_voices);
  12.874 +
  12.875 +    if (audio_state.nb_hw_voices <= 0) {
  12.876 +        dolog ("Bogus number of voices %d, resetting to 1\n",
  12.877 +               audio_state.nb_hw_voices);
  12.878 +    }
  12.879 +
  12.880 +    drvname = audio_get_conf_str (QC_AUDIO_DRV, NULL);
  12.881 +    if (drvname) {
  12.882 +        int found = 0;
  12.883 +        for (i = 0; i < sizeof (drvtab) / sizeof (drvtab[0]); i++) {
  12.884 +            if (!strcmp (drvname, drvtab[i]->name)) {
  12.885 +                done = voice_init (drvtab[i]);
  12.886 +                found = 1;
  12.887 +                break;
  12.888 +            }
  12.889 +        }
  12.890 +        if (!found) {
  12.891 +            dolog ("Unknown audio driver `%s'\n", drvname);
  12.892 +        }
  12.893 +    }
  12.894 +
  12.895 +    qemu_add_vm_stop_handler (audio_vm_stop_handler, NULL);
  12.896 +    atexit (audio_atexit);
  12.897 +
  12.898 +    if (!done) {
  12.899 +        for (i = 0; !done && i < sizeof (drvtab) / sizeof (drvtab[0]); i++) {
  12.900 +            if (drvtab[i]->can_be_default)
  12.901 +                done = voice_init (drvtab[i]);
  12.902 +        }
  12.903 +    }
  12.904 +
  12.905 +    audio_state.ticks_threshold = ticks_per_sec / 50;
  12.906 +    audio_state.freq_threshold = 100;
  12.907 +
  12.908 +    register_savevm ("audio", 0, 1, audio_save, audio_load, NULL);
  12.909 +    if (!done) {
  12.910 +        dolog ("Can not initialize audio subsystem\n");
  12.911 +        voice_init (&no_output_driver);
  12.912 +    }
  12.913 +}
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/tools/ioemu/audio/audio.h	Tue Dec 20 17:16:24 2005 +0000
    13.3 @@ -0,0 +1,65 @@
    13.4 +/*
    13.5 + * QEMU Audio subsystem header
    13.6 + * 
    13.7 + * Copyright (c) 2003-2004 Vassili Karpov (malc)
    13.8 + * 
    13.9 + * Permission is hereby granted, free of charge, to any person obtaining a copy
   13.10 + * of this software and associated documentation files (the "Software"), to deal
   13.11 + * in the Software without restriction, including without limitation the rights
   13.12 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   13.13 + * copies of the Software, and to permit persons to whom the Software is
   13.14 + * furnished to do so, subject to the following conditions:
   13.15 + *
   13.16 + * The above copyright notice and this permission notice shall be included in
   13.17 + * all copies or substantial portions of the Software.
   13.18 + *
   13.19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   13.20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   13.21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   13.22 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   13.23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   13.24 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   13.25 + * THE SOFTWARE.
   13.26 + */
   13.27 +#ifndef QEMU_AUDIO_H
   13.28 +#define QEMU_AUDIO_H
   13.29 +
   13.30 +#include "mixeng.h"
   13.31 +
   13.32 +typedef enum {
   13.33 +  AUD_FMT_U8,
   13.34 +  AUD_FMT_S8,
   13.35 +  AUD_FMT_U16,
   13.36 +  AUD_FMT_S16
   13.37 +} audfmt_e;
   13.38 +
   13.39 +typedef struct SWVoice SWVoice;
   13.40 +
   13.41 +SWVoice * AUD_open (SWVoice *sw, const char *name, int freq,
   13.42 +                    int nchannels, audfmt_e fmt);
   13.43 +void   AUD_init (void);
   13.44 +void   AUD_log (const char *cap, const char *fmt, ...)
   13.45 +    __attribute__ ((__format__ (__printf__, 2, 3)));;
   13.46 +void   AUD_close (SWVoice *sw);
   13.47 +int    AUD_write (SWVoice *sw, void *pcm_buf, int size);
   13.48 +void   AUD_adjust (SWVoice *sw, int leftover);
   13.49 +void   AUD_reset (SWVoice *sw);
   13.50 +int    AUD_get_free (SWVoice *sw);
   13.51 +int    AUD_get_buffer_size (SWVoice *sw);
   13.52 +void   AUD_run (void);
   13.53 +void   AUD_enable (SWVoice *sw, int on);
   13.54 +int    AUD_calc_elapsed (SWVoice *sw);
   13.55 +
   13.56 +static inline void *advance (void *p, int incr)
   13.57 +{
   13.58 +    uint8_t *d = p;
   13.59 +    return (d + incr);
   13.60 +}
   13.61 +
   13.62 +uint32_t popcount (uint32_t u);
   13.63 +inline uint32_t lsbindex (uint32_t u);
   13.64 +
   13.65 +#define audio_MIN(a, b) ((a)>(b)?(b):(a))
   13.66 +#define audio_MAX(a, b) ((a)<(b)?(b):(a))
   13.67 +
   13.68 +#endif  /* audio.h */
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/tools/ioemu/audio/audio_int.h	Tue Dec 20 17:16:24 2005 +0000
    14.3 @@ -0,0 +1,164 @@
    14.4 +/*
    14.5 + * QEMU Audio subsystem header
    14.6 + * 
    14.7 + * Copyright (c) 2003-2004 Vassili Karpov (malc)
    14.8 + * 
    14.9 + * Permission is hereby granted, free of charge, to any person obtaining a copy
   14.10 + * of this software and associated documentation files (the "Software"), to deal
   14.11 + * in the Software without restriction, including without limitation the rights
   14.12 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   14.13 + * copies of the Software, and to permit persons to whom the Software is
   14.14 + * furnished to do so, subject to the following conditions:
   14.15 + *
   14.16 + * The above copyright notice and this permission notice shall be included in
   14.17 + * all copies or substantial portions of the Software.
   14.18 + *
   14.19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   14.20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   14.21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   14.22 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   14.23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   14.24 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   14.25 + * THE SOFTWARE.
   14.26 + */
   14.27 +#ifndef QEMU_AUDIO_INT_H
   14.28 +#define QEMU_AUDIO_INT_H
   14.29 +
   14.30 +#include "vl.h"
   14.31 +
   14.32 +struct pcm_ops;
   14.33 +
   14.34 +typedef struct HWVoice {
   14.35 +    int active;
   14.36 +    int enabled;
   14.37 +    int pending_disable;
   14.38 +    int valid;
   14.39 +    int freq;
   14.40 +
   14.41 +    f_sample *clip;
   14.42 +    audfmt_e fmt;
   14.43 +    int nchannels;
   14.44 +
   14.45 +    int align;
   14.46 +    int shift;
   14.47 +
   14.48 +    int rpos;
   14.49 +    int bufsize;
   14.50 +
   14.51 +    int bytes_per_second;
   14.52 +    st_sample_t *mix_buf;
   14.53 +
   14.54 +    int samples;
   14.55 +    int64_t old_ticks;
   14.56 +    int nb_voices;
   14.57 +    struct SWVoice **pvoice;
   14.58 +    struct pcm_ops *pcm_ops;
   14.59 +} HWVoice;
   14.60 +
   14.61 +extern struct pcm_ops no_pcm_ops;
   14.62 +extern struct audio_output_driver no_output_driver;
   14.63 +
   14.64 +extern struct pcm_ops oss_pcm_ops;
   14.65 +extern struct audio_output_driver oss_output_driver;
   14.66 +
   14.67 +extern struct pcm_ops sdl_pcm_ops;
   14.68 +extern struct audio_output_driver sdl_output_driver;
   14.69 +
   14.70 +extern struct pcm_ops wav_pcm_ops;
   14.71 +extern struct audio_output_driver wav_output_driver;
   14.72 +
   14.73 +extern struct pcm_ops fmod_pcm_ops;
   14.74 +extern struct audio_output_driver fmod_output_driver;
   14.75 +
   14.76 +struct audio_output_driver {
   14.77 +    const char *name;
   14.78 +    void *(*init) (void);
   14.79 +    void (*fini) (void *);
   14.80 +    struct pcm_ops *pcm_ops;
   14.81 +    int can_be_default;
   14.82 +    int max_voices;
   14.83 +    int voice_size;
   14.84 +};
   14.85 +
   14.86 +typedef struct AudioState {
   14.87 +    int fixed_format;
   14.88 +    int fixed_freq;
   14.89 +    int fixed_channels;
   14.90 +    int fixed_fmt;
   14.91 +    int nb_hw_voices;
   14.92 +    int voice_size;
   14.93 +    int64_t ticks_threshold;
   14.94 +    int freq_threshold;
   14.95 +    void *opaque;
   14.96 +    struct audio_output_driver *drv;
   14.97 +} AudioState;
   14.98 +extern AudioState audio_state;
   14.99 +
  14.100 +struct SWVoice {
  14.101 +    int freq;
  14.102 +    audfmt_e fmt;
  14.103 +    int nchannels;
  14.104 +
  14.105 +    int shift;
  14.106 +    int align;
  14.107 +
  14.108 +    t_sample *conv;
  14.109 +
  14.110 +    int left;
  14.111 +    int pos;
  14.112 +    int bytes_per_second;
  14.113 +    int64_t ratio;
  14.114 +    st_sample_t *buf;
  14.115 +    void *rate;
  14.116 +
  14.117 +    int wpos;
  14.118 +    int live;
  14.119 +    int active;
  14.120 +    int64_t old_ticks;
  14.121 +    HWVoice *hw;
  14.122 +    char *name;
  14.123 +};
  14.124 +
  14.125 +struct pcm_ops {
  14.126 +    int  (*init)  (HWVoice *hw, int freq, int nchannels, audfmt_e fmt);
  14.127 +    void (*fini)  (HWVoice *hw);
  14.128 +    void (*run)   (HWVoice *hw);
  14.129 +    int  (*write) (SWVoice *sw, void *buf, int size);
  14.130 +    int  (*ctl)   (HWVoice *hw, int cmd, ...);
  14.131 +};
  14.132 +
  14.133 +void      pcm_sw_free_resources (SWVoice *sw);
  14.134 +int       pcm_sw_alloc_resources (SWVoice *sw);
  14.135 +void      pcm_sw_fini (SWVoice *sw);
  14.136 +int       pcm_sw_init (SWVoice *sw, HWVoice *hw, int freq,
  14.137 +                       int nchannels, audfmt_e fmt);
  14.138 +
  14.139 +void      pcm_hw_clear (HWVoice *hw, void *buf, int len);
  14.140 +HWVoice * pcm_hw_find_any (HWVoice *hw);
  14.141 +HWVoice * pcm_hw_find_any_active (HWVoice *hw);
  14.142 +HWVoice * pcm_hw_find_any_passive (HWVoice *hw);
  14.143 +HWVoice * pcm_hw_find_specific (HWVoice *hw, int freq,
  14.144 +                                int nchannels, audfmt_e fmt);
  14.145 +HWVoice * pcm_hw_add (int freq, int nchannels, audfmt_e fmt);
  14.146 +int       pcm_hw_add_sw (HWVoice *hw, SWVoice *sw);
  14.147 +int       pcm_hw_del_sw (HWVoice *hw, SWVoice *sw);
  14.148 +SWVoice * pcm_create_voice_pair (int freq, int nchannels, audfmt_e fmt);
  14.149 +
  14.150 +void      pcm_hw_free_resources (HWVoice *hw);
  14.151 +int       pcm_hw_alloc_resources (HWVoice *hw);
  14.152 +void      pcm_hw_fini (HWVoice *hw);
  14.153 +void      pcm_hw_gc (HWVoice *hw);
  14.154 +int       pcm_hw_get_live (HWVoice *hw);
  14.155 +int       pcm_hw_get_live2 (HWVoice *hw, int *nb_active);
  14.156 +void      pcm_hw_dec_live (HWVoice *hw, int decr);
  14.157 +int       pcm_hw_write (SWVoice *sw, void *buf, int len);
  14.158 +
  14.159 +int         audio_get_conf_int (const char *key, int defval);
  14.160 +const char *audio_get_conf_str (const char *key, const char *defval);
  14.161 +
  14.162 +struct audio_output_driver;
  14.163 +
  14.164 +#define VOICE_ENABLE 1
  14.165 +#define VOICE_DISABLE 2
  14.166 +
  14.167 +#endif /* audio_int.h */
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/tools/ioemu/audio/mixeng.c	Tue Dec 20 17:16:24 2005 +0000
    15.3 @@ -0,0 +1,255 @@
    15.4 +/*
    15.5 + * QEMU Mixing engine
    15.6 + *
    15.7 + * Copyright (c) 2004 Vassili Karpov (malc)
    15.8 + * Copyright (c) 1998 Fabrice Bellard
    15.9 + *
   15.10 + * Permission is hereby granted, free of charge, to any person obtaining a copy
   15.11 + * of this software and associated documentation files (the "Software"), to deal
   15.12 + * in the Software without restriction, including without limitation the rights
   15.13 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   15.14 + * copies of the Software, and to permit persons to whom the Software is
   15.15 + * furnished to do so, subject to the following conditions:
   15.16 + *
   15.17 + * The above copyright notice and this permission notice shall be included in
   15.18 + * all copies or substantial portions of the Software.
   15.19 + *
   15.20 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   15.21 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   15.22 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   15.23 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   15.24 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   15.25 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   15.26 + * THE SOFTWARE.
   15.27 + */
   15.28 +#include "vl.h"
   15.29 +//#define DEBUG_FP
   15.30 +#include "audio/mixeng.h"
   15.31 +
   15.32 +#define IN_T int8_t
   15.33 +#define IN_MIN CHAR_MIN
   15.34 +#define IN_MAX CHAR_MAX
   15.35 +#define SIGNED
   15.36 +#include "mixeng_template.h"
   15.37 +#undef SIGNED
   15.38 +#undef IN_MAX
   15.39 +#undef IN_MIN
   15.40 +#undef IN_T
   15.41 +
   15.42 +#define IN_T uint8_t
   15.43 +#define IN_MIN 0
   15.44 +#define IN_MAX UCHAR_MAX
   15.45 +#include "mixeng_template.h"
   15.46 +#undef IN_MAX
   15.47 +#undef IN_MIN
   15.48 +#undef IN_T
   15.49 +
   15.50 +#define IN_T int16_t
   15.51 +#define IN_MIN SHRT_MIN
   15.52 +#define IN_MAX SHRT_MAX
   15.53 +#define SIGNED
   15.54 +#include "mixeng_template.h"
   15.55 +#undef SIGNED
   15.56 +#undef IN_MAX
   15.57 +#undef IN_MIN
   15.58 +#undef IN_T
   15.59 +
   15.60 +#define IN_T uint16_t
   15.61 +#define IN_MIN 0
   15.62 +#define IN_MAX USHRT_MAX
   15.63 +#include "mixeng_template.h"
   15.64 +#undef IN_MAX
   15.65 +#undef IN_MIN
   15.66 +#undef IN_T
   15.67 +
   15.68 +t_sample *mixeng_conv[2][2][2] = {
   15.69 +    {
   15.70 +        {
   15.71 +            conv_uint8_t_to_mono,
   15.72 +            conv_uint16_t_to_mono
   15.73 +        },
   15.74 +        {
   15.75 +            conv_int8_t_to_mono,
   15.76 +            conv_int16_t_to_mono
   15.77 +        }
   15.78 +    },
   15.79 +    {
   15.80 +        {
   15.81 +            conv_uint8_t_to_stereo,
   15.82 +            conv_uint16_t_to_stereo
   15.83 +        },
   15.84 +        {
   15.85 +            conv_int8_t_to_stereo,
   15.86 +            conv_int16_t_to_stereo
   15.87 +        }
   15.88 +    }
   15.89 +};
   15.90 +
   15.91 +f_sample *mixeng_clip[2][2][2] = {
   15.92 +    {
   15.93 +        {
   15.94 +            clip_uint8_t_from_mono,
   15.95 +            clip_uint16_t_from_mono
   15.96 +        },
   15.97 +        {
   15.98 +            clip_int8_t_from_mono,
   15.99 +            clip_int16_t_from_mono
  15.100 +        }
  15.101 +    },
  15.102 +    {
  15.103 +        {
  15.104 +            clip_uint8_t_from_stereo,
  15.105 +            clip_uint16_t_from_stereo
  15.106 +        },
  15.107 +        {
  15.108 +            clip_int8_t_from_stereo,
  15.109 +            clip_int16_t_from_stereo
  15.110 +        }
  15.111 +    }
  15.112 +};
  15.113 +
  15.114 +/*
  15.115 + * August 21, 1998
  15.116 + * Copyright 1998 Fabrice Bellard.
  15.117 + *
  15.118 + * [Rewrote completly the code of Lance Norskog And Sundry
  15.119 + * Contributors with a more efficient algorithm.]
  15.120 + *
  15.121 + * This source code is freely redistributable and may be used for
  15.122 + * any purpose.  This copyright notice must be maintained. 
  15.123 + * Lance Norskog And Sundry Contributors are not responsible for 
  15.124 + * the consequences of using this software.  
  15.125 + */
  15.126 +
  15.127 +/*
  15.128 + * Sound Tools rate change effect file.
  15.129 + */
  15.130 +/*
  15.131 + * Linear Interpolation.
  15.132 + *
  15.133 + * The use of fractional increment allows us to use no buffer. It
  15.134 + * avoid the problems at the end of the buffer we had with the old
  15.135 + * method which stored a possibly big buffer of size
  15.136 + * lcm(in_rate,out_rate).
  15.137 + *
  15.138 + * Limited to 16 bit samples and sampling frequency <= 65535 Hz. If
  15.139 + * the input & output frequencies are equal, a delay of one sample is
  15.140 + * introduced.  Limited to processing 32-bit count worth of samples.
  15.141 + *
  15.142 + * 1 << FRAC_BITS evaluating to zero in several places.  Changed with
  15.143 + * an (unsigned long) cast to make it safe.  MarkMLl 2/1/99
  15.144 + */
  15.145 +
  15.146 +/* Private data */
  15.147 +typedef struct ratestuff {
  15.148 +    uint64_t opos;
  15.149 +    uint64_t opos_inc;
  15.150 +    uint32_t ipos;              /* position in the input stream (integer) */
  15.151 +    st_sample_t ilast;          /* last sample in the input stream */
  15.152 +} *rate_t;
  15.153 +
  15.154 +/*
  15.155 + * Prepare processing.
  15.156 + */
  15.157 +void *st_rate_start (int inrate, int outrate)
  15.158 +{
  15.159 +    rate_t rate = (rate_t) qemu_mallocz (sizeof (struct ratestuff));
  15.160 +
  15.161 +    if (!rate) {
  15.162 +        exit (EXIT_FAILURE);
  15.163 +    }
  15.164 +
  15.165 +    if (inrate == outrate) {
  15.166 +        // exit (EXIT_FAILURE);
  15.167 +    }
  15.168 +
  15.169 +    if (inrate >= 65535 || outrate >= 65535) {
  15.170 +        // exit (EXIT_FAILURE);
  15.171 +    }
  15.172 +
  15.173 +    rate->opos = 0;
  15.174 +
  15.175 +    /* increment */
  15.176 +    rate->opos_inc = (inrate * ((int64_t) UINT_MAX)) / outrate;
  15.177 +
  15.178 +    rate->ipos = 0;
  15.179 +    rate->ilast.l = 0;
  15.180 +    rate->ilast.r = 0;
  15.181 +    return rate;
  15.182 +}
  15.183 +
  15.184 +/*
  15.185 + * Processed signed long samples from ibuf to obuf.
  15.186 + * Return number of samples processed.
  15.187 + */
  15.188 +void st_rate_flow (void *opaque, st_sample_t *ibuf, st_sample_t *obuf,
  15.189 +                   int *isamp, int *osamp)
  15.190 +{
  15.191 +    rate_t rate = (rate_t) opaque;
  15.192 +    st_sample_t *istart, *iend;
  15.193 +    st_sample_t *ostart, *oend;
  15.194 +    st_sample_t ilast, icur, out;
  15.195 +    int64_t t;
  15.196 +
  15.197 +    ilast = rate->ilast;
  15.198 +
  15.199 +    istart = ibuf;
  15.200 +    iend = ibuf + *isamp;
  15.201 +
  15.202 +    ostart = obuf;
  15.203 +    oend = obuf + *osamp;
  15.204 +
  15.205 +    if (rate->opos_inc == 1ULL << 32) {
  15.206 +        int i, n = *isamp > *osamp ? *osamp : *isamp;
  15.207 +        for (i = 0; i < n; i++) {
  15.208 +            obuf[i].l += ibuf[i].r;
  15.209 +            obuf[i].r += ibuf[i].r;
  15.210 +        }
  15.211 +        *isamp = n;
  15.212 +        *osamp = n;
  15.213 +        return;
  15.214 +    }
  15.215 +
  15.216 +    while (obuf < oend) {
  15.217 +
  15.218 +        /* Safety catch to make sure we have input samples.  */
  15.219 +        if (ibuf >= iend)
  15.220 +            break;
  15.221 +
  15.222 +        /* read as many input samples so that ipos > opos */
  15.223 +
  15.224 +        while (rate->ipos <= (rate->opos >> 32)) {
  15.225 +            ilast = *ibuf++;
  15.226 +            rate->ipos++;
  15.227 +            /* See if we finished the input buffer yet */
  15.228 +            if (ibuf >= iend) goto the_end;
  15.229 +        }
  15.230 +
  15.231 +        icur = *ibuf;
  15.232 +
  15.233 +        /* interpolate */
  15.234 +        t = rate->opos & 0xffffffff;
  15.235 +        out.l = (ilast.l * (INT_MAX - t) + icur.l * t) / INT_MAX;
  15.236 +        out.r = (ilast.r * (INT_MAX - t) + icur.r * t) / INT_MAX;
  15.237 +
  15.238 +        /* output sample & increment position */
  15.239 +#if 0
  15.240 +        *obuf++ = out;
  15.241 +#else
  15.242 +        obuf->l += out.l;
  15.243 +        obuf->r += out.r;
  15.244 +        obuf += 1;
  15.245 +#endif
  15.246 +        rate->opos += rate->opos_inc;
  15.247 +    }
  15.248 +
  15.249 +the_end:
  15.250 +    *isamp = ibuf - istart;
  15.251 +    *osamp = obuf - ostart;
  15.252 +    rate->ilast = ilast;
  15.253 +}
  15.254 +
  15.255 +void st_rate_stop (void *opaque)
  15.256 +{
  15.257 +    qemu_free (opaque);
  15.258 +}
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/tools/ioemu/audio/mixeng.h	Tue Dec 20 17:16:24 2005 +0000
    16.3 @@ -0,0 +1,39 @@
    16.4 +/*
    16.5 + * QEMU Mixing engine header
    16.6 + * 
    16.7 + * Copyright (c) 2004 Vassili Karpov (malc)
    16.8 + * 
    16.9 + * Permission is hereby granted, free of charge, to any person obtaining a copy
   16.10 + * of this software and associated documentation files (the "Software"), to deal
   16.11 + * in the Software without restriction, including without limitation the rights
   16.12 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   16.13 + * copies of the Software, and to permit persons to whom the Software is
   16.14 + * furnished to do so, subject to the following conditions:
   16.15 + *
   16.16 + * The above copyright notice and this permission notice shall be included in
   16.17 + * all copies or substantial portions of the Software.
   16.18 + *
   16.19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   16.20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   16.21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   16.22 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   16.23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   16.24 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   16.25 + * THE SOFTWARE.
   16.26 + */
   16.27 +#ifndef QEMU_MIXENG_H
   16.28 +#define QEMU_MIXENG_H
   16.29 +
   16.30 +typedef void (t_sample) (void *dst, const void *src, int samples);
   16.31 +typedef void (f_sample) (void *dst, const void *src, int samples);
   16.32 +typedef struct { int64_t l; int64_t r; } st_sample_t;
   16.33 +
   16.34 +extern t_sample *mixeng_conv[2][2][2];
   16.35 +extern f_sample *mixeng_clip[2][2][2];
   16.36 +
   16.37 +void *st_rate_start (int inrate, int outrate);
   16.38 +void st_rate_flow (void *opaque, st_sample_t *ibuf, st_sample_t *obuf,
   16.39 +                   int *isamp, int *osamp);
   16.40 +void st_rate_stop (void *opaque);
   16.41 +
   16.42 +#endif  /* mixeng.h */
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/tools/ioemu/audio/mixeng_template.h	Tue Dec 20 17:16:24 2005 +0000
    17.3 @@ -0,0 +1,111 @@
    17.4 +/*
    17.5 + * QEMU Mixing engine
    17.6 + * 
    17.7 + * Copyright (c) 2004 Vassili Karpov (malc)
    17.8 + * 
    17.9 + * Permission is hereby granted, free of charge, to any person obtaining a copy
   17.10 + * of this software and associated documentation files (the "Software"), to deal
   17.11 + * in the Software without restriction, including without limitation the rights
   17.12 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   17.13 + * copies of the Software, and to permit persons to whom the Software is
   17.14 + * furnished to do so, subject to the following conditions:
   17.15 + *
   17.16 + * The above copyright notice and this permission notice shall be included in
   17.17 + * all copies or substantial portions of the Software.
   17.18 + *
   17.19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   17.20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   17.21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   17.22 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   17.23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   17.24 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   17.25 + * THE SOFTWARE.
   17.26 + */
   17.27 +
   17.28 +/*
   17.29 + * Tusen tack till Mike Nordell
   17.30 + * dec++'ified by Dscho
   17.31 + */
   17.32 +
   17.33 +#ifdef SIGNED
   17.34 +#define HALFT IN_MAX
   17.35 +#define HALF IN_MAX
   17.36 +#else
   17.37 +#define HALFT ((IN_MAX)>>1)
   17.38 +#define HALF HALFT
   17.39 +#endif
   17.40 +
   17.41 +static int64_t inline glue(conv_,IN_T) (IN_T v)
   17.42 +{
   17.43 +#ifdef SIGNED
   17.44 +    return (INT_MAX*(int64_t)v)/HALF;
   17.45 +#else
   17.46 +    return (INT_MAX*((int64_t)v-HALFT))/HALF;
   17.47 +#endif
   17.48 +}
   17.49 +
   17.50 +static IN_T inline glue(clip_,IN_T) (int64_t v)
   17.51 +{
   17.52 +    if (v >= INT_MAX)
   17.53 +        return IN_MAX;
   17.54 +    else if (v < -INT_MAX)
   17.55 +        return IN_MIN;
   17.56 +
   17.57 +#ifdef SIGNED
   17.58 +    return (IN_T) (v*HALF/INT_MAX);
   17.59 +#else
   17.60 +    return (IN_T) (v+INT_MAX/2)*HALF/INT_MAX;
   17.61 +#endif
   17.62 +}
   17.63 +
   17.64 +static void glue(glue(conv_,IN_T),_to_stereo) (void *dst, const void *src,
   17.65 +                                               int samples)
   17.66 +{
   17.67 +    st_sample_t *out = (st_sample_t *) dst;
   17.68 +    IN_T *in = (IN_T *) src;
   17.69 +    while (samples--) {
   17.70 +        out->l = glue(conv_,IN_T) (*in++);
   17.71 +        out->r = glue(conv_,IN_T) (*in++);
   17.72 +        out += 1;
   17.73 +    }
   17.74 +}
   17.75 +
   17.76 +static void glue(glue(conv_,IN_T),_to_mono) (void *dst, const void *src,
   17.77 +                                             int samples)
   17.78 +{
   17.79 +    st_sample_t *out = (st_sample_t *) dst;
   17.80 +    IN_T *in = (IN_T *) src;
   17.81 +    while (samples--) {
   17.82 +        out->l = glue(conv_,IN_T) (in[0]);
   17.83 +        out->r = out->l;
   17.84 +        out += 1;
   17.85 +        in += 1;
   17.86 +    }
   17.87 +}
   17.88 +
   17.89 +static void glue(glue(clip_,IN_T),_from_stereo) (void *dst, const void *src,
   17.90 +                                                 int samples)
   17.91 +{
   17.92 +    st_sample_t *in = (st_sample_t *) src;
   17.93 +    IN_T *out = (IN_T *) dst;
   17.94 +    while (samples--) {
   17.95 +        *out++ = glue(clip_,IN_T) (in->l);
   17.96 +        *out++ = glue(clip_,IN_T) (in->r);
   17.97 +        in += 1;
   17.98 +    }
   17.99 +}
  17.100 +
  17.101 +static void glue(glue(clip_,IN_T),_from_mono) (void *dst, const void *src,
  17.102 +                                               int samples)
  17.103 +{
  17.104 +    st_sample_t *in = (st_sample_t *) src;
  17.105 +    IN_T *out = (IN_T *) dst;
  17.106 +    while (samples--) {
  17.107 +        *out++ = glue(clip_,IN_T) (in->l + in->r);
  17.108 +        in += 1;
  17.109 +    }
  17.110 +}
  17.111 +
  17.112 +#undef HALF
  17.113 +#undef HALFT
  17.114 +
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/tools/ioemu/audio/noaudio.c	Tue Dec 20 17:16:24 2005 +0000
    18.3 @@ -0,0 +1,130 @@
    18.4 +/*
    18.5 + * QEMU NULL audio output driver
    18.6 + * 
    18.7 + * Copyright (c) 2004 Vassili Karpov (malc)
    18.8 + * 
    18.9 + * Permission is hereby granted, free of charge, to any person obtaining a copy
   18.10 + * of this software and associated documentation files (the "Software"), to deal
   18.11 + * in the Software without restriction, including without limitation the rights
   18.12 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   18.13 + * copies of the Software, and to permit persons to whom the Software is
   18.14 + * furnished to do so, subject to the following conditions:
   18.15 + *
   18.16 + * The above copyright notice and this permission notice shall be included in
   18.17 + * all copies or substantial portions of the Software.
   18.18 + *
   18.19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   18.20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   18.21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   18.22 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   18.23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   18.24 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   18.25 + * THE SOFTWARE.
   18.26 + */
   18.27 +#include "vl.h"
   18.28 +
   18.29 +#include "audio/audio_int.h"
   18.30 +
   18.31 +typedef struct NoVoice {
   18.32 +    HWVoice hw;
   18.33 +    int64_t old_ticks;
   18.34 +} NoVoice;
   18.35 +
   18.36 +#define dolog(...) AUD_log ("noaudio", __VA_ARGS__)
   18.37 +#ifdef DEBUG
   18.38 +#define ldebug(...) dolog (__VA_ARGS__)
   18.39 +#else
   18.40 +#define ldebug(...)
   18.41 +#endif
   18.42 +
   18.43 +static void no_hw_run (HWVoice *hw)
   18.44 +{
   18.45 +    NoVoice *no = (NoVoice *) hw;
   18.46 +    int rpos, live, decr, samples;
   18.47 +    uint8_t *dst;
   18.48 +    st_sample_t *src;
   18.49 +    int64_t now = qemu_get_clock (vm_clock);
   18.50 +    int64_t ticks = now - no->old_ticks;
   18.51 +    int64_t bytes = (ticks * hw->bytes_per_second) / ticks_per_sec;
   18.52 +
   18.53 +    if (bytes > INT_MAX)
   18.54 +        samples = INT_MAX >> hw->shift;
   18.55 +    else
   18.56 +        samples = bytes >> hw->shift;
   18.57 +
   18.58 +    live = pcm_hw_get_live (hw);
   18.59 +    if (live <= 0)
   18.60 +        return;
   18.61 +
   18.62 +    no->old_ticks = now;
   18.63 +    decr = audio_MIN (live, samples);
   18.64 +    samples = decr;
   18.65 +    rpos = hw->rpos;
   18.66 +    while (samples) {
   18.67 +        int left_till_end_samples = hw->samples - rpos;
   18.68 +        int convert_samples = audio_MIN (samples, left_till_end_samples);
   18.69 +
   18.70 +        src = advance (hw->mix_buf, rpos * sizeof (st_sample_t));
   18.71 +        memset (src, 0, convert_samples * sizeof (st_sample_t));
   18.72 +
   18.73 +        rpos = (rpos + convert_samples) % hw->samples;
   18.74 +        samples -= convert_samples;
   18.75 +    }
   18.76 +
   18.77 +    pcm_hw_dec_live (hw, decr);
   18.78 +    hw->rpos = rpos;
   18.79 +}
   18.80 +
   18.81 +static int no_hw_write (SWVoice *sw, void *buf, int len)
   18.82 +{
   18.83 +    return pcm_hw_write (sw, buf, len);
   18.84 +}
   18.85 +
   18.86 +static int no_hw_init (HWVoice *hw, int freq, int nchannels, audfmt_e fmt)
   18.87 +{
   18.88 +    NoVoice *no = (NoVoice *) hw;
   18.89 +    hw->freq = freq;
   18.90 +    hw->nchannels = nchannels;
   18.91 +    hw->fmt = fmt;
   18.92 +    hw->bufsize = 4096;
   18.93 +    return 0;
   18.94 +}
   18.95 +
   18.96 +static void no_hw_fini (HWVoice *hw)
   18.97 +{
   18.98 +    (void) hw;
   18.99 +}
  18.100 +
  18.101 +static int no_hw_ctl (HWVoice *hw, int cmd, ...)
  18.102 +{
  18.103 +    (void) hw;
  18.104 +    (void) cmd;
  18.105 +    return 0;
  18.106 +}
  18.107 +
  18.108 +static void *no_audio_init (void)
  18.109 +{
  18.110 +    return &no_audio_init;
  18.111 +}
  18.112 +
  18.113 +static void no_audio_fini (void *opaque)
  18.114 +{
  18.115 +}
  18.116 +
  18.117 +struct pcm_ops no_pcm_ops = {
  18.118 +    no_hw_init,
  18.119 +    no_hw_fini,
  18.120 +    no_hw_run,
  18.121 +    no_hw_write,
  18.122 +    no_hw_ctl
  18.123 +};
  18.124 +
  18.125 +struct audio_output_driver no_output_driver = {
  18.126 +    "none",
  18.127 +    no_audio_init,
  18.128 +    no_audio_fini,
  18.129 +    &no_pcm_ops,
  18.130 +    1,
  18.131 +    1,
  18.132 +    sizeof (NoVoice)
  18.133 +};
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/tools/ioemu/audio/ossaudio.c	Tue Dec 20 17:16:24 2005 +0000
    19.3 @@ -0,0 +1,475 @@
    19.4 +/*
    19.5 + * QEMU OSS audio output driver
    19.6 + * 
    19.7 + * Copyright (c) 2003-2004 Vassili Karpov (malc)
    19.8 + * 
    19.9 + * Permission is hereby granted, free of charge, to any person obtaining a copy
   19.10 + * of this software and associated documentation files (the "Software"), to deal
   19.11 + * in the Software without restriction, including without limitation the rights
   19.12 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   19.13 + * copies of the Software, and to permit persons to whom the Software is
   19.14 + * furnished to do so, subject to the following conditions:
   19.15 + *
   19.16 + * The above copyright notice and this permission notice shall be included in
   19.17 + * all copies or substantial portions of the Software.
   19.18 + *
   19.19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   19.20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   19.21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   19.22 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   19.23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   19.24 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   19.25 + * THE SOFTWARE.
   19.26 + */
   19.27 +#include <sys/mman.h>
   19.28 +#include <sys/types.h>
   19.29 +#include <sys/ioctl.h>
   19.30 +#include <sys/soundcard.h>
   19.31 +#include <assert.h>
   19.32 +#include "vl.h"
   19.33 +
   19.34 +#include "audio/audio_int.h"
   19.35 +
   19.36 +typedef struct OSSVoice {
   19.37 +    HWVoice hw;
   19.38 +    void *pcm_buf;
   19.39 +    int fd;
   19.40 +    int nfrags;
   19.41 +    int fragsize;
   19.42 +    int mmapped;
   19.43 +    int old_optr;
   19.44 +} OSSVoice;
   19.45 +
   19.46 +#define dolog(...) AUD_log ("oss", __VA_ARGS__)
   19.47 +#ifdef DEBUG
   19.48 +#define ldebug(...) dolog (__VA_ARGS__)
   19.49 +#else
   19.50 +#define ldebug(...)
   19.51 +#endif
   19.52 +
   19.53 +#define QC_OSS_FRAGSIZE "QEMU_OSS_FRAGSIZE"
   19.54 +#define QC_OSS_NFRAGS   "QEMU_OSS_NFRAGS"
   19.55 +#define QC_OSS_MMAP     "QEMU_OSS_MMAP"
   19.56 +#define QC_OSS_DEV      "QEMU_OSS_DEV"
   19.57 +
   19.58 +#define errstr() strerror (errno)
   19.59 +
   19.60 +static struct {
   19.61 +    int try_mmap;
   19.62 +    int nfrags;
   19.63 +    int fragsize;
   19.64 +    const char *dspname;
   19.65 +} conf = {
   19.66 +    .try_mmap = 0,
   19.67 +    .nfrags = 4,
   19.68 +    .fragsize = 4096,
   19.69 +    .dspname = "/dev/dsp"
   19.70 +};
   19.71 +
   19.72 +struct oss_params {
   19.73 +    int freq;
   19.74 +    audfmt_e fmt;
   19.75 +    int nchannels;
   19.76 +    int nfrags;
   19.77 +    int fragsize;
   19.78 +};
   19.79 +
   19.80 +static int oss_hw_write (SWVoice *sw, void *buf, int len)
   19.81 +{
   19.82 +    return pcm_hw_write (sw, buf, len);
   19.83 +}
   19.84 +
   19.85 +static int AUD_to_ossfmt (audfmt_e fmt)
   19.86 +{
   19.87 +    switch (fmt) {
   19.88 +    case AUD_FMT_S8: return AFMT_S8;
   19.89 +    case AUD_FMT_U8: return AFMT_U8;
   19.90 +    case AUD_FMT_S16: return AFMT_S16_LE;
   19.91 +    case AUD_FMT_U16: return AFMT_U16_LE;
   19.92 +    default:
   19.93 +        dolog ("Internal logic error: Bad audio format %d\nAborting\n", fmt);
   19.94 +        exit (EXIT_FAILURE);
   19.95 +    }
   19.96 +}
   19.97 +
   19.98 +static int oss_to_audfmt (int fmt)
   19.99 +{
  19.100 +    switch (fmt) {
  19.101 +    case AFMT_S8: return AUD_FMT_S8;
  19.102 +    case AFMT_U8: return AUD_FMT_U8;
  19.103 +    case AFMT_S16_LE: return AUD_FMT_S16;
  19.104 +    case AFMT_U16_LE: return AUD_FMT_U16;
  19.105 +    default:
  19.106 +        dolog ("Internal logic error: Unrecognized OSS audio format %d\n"
  19.107 +               "Aborting\n",
  19.108 +               fmt);
  19.109 +        exit (EXIT_FAILURE);
  19.110 +    }
  19.111 +}
  19.112 +
  19.113 +#ifdef DEBUG_PCM
  19.114 +static void oss_dump_pcm_info (struct oss_params *req, struct oss_params *obt)
  19.115 +{
  19.116 +    dolog ("parameter | requested value | obtained value\n");
  19.117 +    dolog ("format    |      %10d |     %10d\n", req->fmt, obt->fmt);
  19.118 +    dolog ("channels  |      %10d |     %10d\n", req->nchannels, obt->nchannels);
  19.119 +    dolog ("frequency |      %10d |     %10d\n", req->freq, obt->freq);
  19.120 +    dolog ("nfrags    |      %10d |     %10d\n", req->nfrags, obt->nfrags);
  19.121 +    dolog ("fragsize  |      %10d |     %10d\n", req->fragsize, obt->fragsize);
  19.122 +}
  19.123 +#endif
  19.124 +
  19.125 +static int oss_open (struct oss_params *req, struct oss_params *obt, int *pfd)
  19.126 +{
  19.127 +    int fd;
  19.128 +    int mmmmssss;
  19.129 +    audio_buf_info abinfo;
  19.130 +    int fmt, freq, nchannels;
  19.131 +    const char *dspname = conf.dspname;
  19.132 +
  19.133 +    fd = open (dspname, O_RDWR | O_NONBLOCK);
  19.134 +    if (-1 == fd) {
  19.135 +        dolog ("Could not initialize audio hardware. Failed to open `%s':\n"
  19.136 +               "Reason:%s\n",
  19.137 +               dspname,
  19.138 +               errstr ());
  19.139 +        return -1;
  19.140 +    }
  19.141 +
  19.142 +    freq = req->freq;
  19.143 +    nchannels = req->nchannels;
  19.144 +    fmt = req->fmt;
  19.145 +
  19.146 +    if (ioctl (fd, SNDCTL_DSP_SAMPLESIZE, &fmt)) {
  19.147 +        dolog ("Could not initialize audio hardware\n"
  19.148 +               "Failed to set sample size\n"
  19.149 +               "Reason: %s\n",
  19.150 +               errstr ());
  19.151 +        goto err;
  19.152 +    }
  19.153 +
  19.154 +    if (ioctl (fd, SNDCTL_DSP_CHANNELS, &nchannels)) {
  19.155 +        dolog ("Could not initialize audio hardware\n"
  19.156 +               "Failed to set number of channels\n"
  19.157 +               "Reason: %s\n",
  19.158 +               errstr ());
  19.159 +        goto err;
  19.160 +    }
  19.161 +
  19.162 +    if (ioctl (fd, SNDCTL_DSP_SPEED, &freq)) {
  19.163 +        dolog ("Could not initialize audio hardware\n"
  19.164 +               "Failed to set frequency\n"
  19.165 +               "Reason: %s\n",
  19.166 +               errstr ());
  19.167 +        goto err;
  19.168 +    }
  19.169 +
  19.170 +    if (ioctl (fd, SNDCTL_DSP_NONBLOCK)) {
  19.171 +        dolog ("Could not initialize audio hardware\n"
  19.172 +               "Failed to set non-blocking mode\n"
  19.173 +               "Reason: %s\n",
  19.174 +               errstr ());
  19.175 +        goto err;
  19.176 +    }
  19.177 +
  19.178 +    mmmmssss = (req->nfrags << 16) | lsbindex (req->fragsize);
  19.179 +    if (ioctl (fd, SNDCTL_DSP_SETFRAGMENT, &mmmmssss)) {
  19.180 +        dolog ("Could not initialize audio hardware\n"
  19.181 +               "Failed to set buffer length (%d, %d)\n"
  19.182 +               "Reason:%s\n",
  19.183 +               conf.nfrags, conf.fragsize,
  19.184 +               errstr ());
  19.185 +        goto err;
  19.186 +    }
  19.187 +
  19.188 +    if (ioctl (fd, SNDCTL_DSP_GETOSPACE, &abinfo)) {
  19.189 +        dolog ("Could not initialize audio hardware\n"
  19.190 +               "Failed to get buffer length\n"
  19.191 +               "Reason:%s\n",
  19.192 +               errstr ());
  19.193 +        goto err;
  19.194 +    }
  19.195 +
  19.196 +    obt->fmt = fmt;
  19.197 +    obt->nchannels = nchannels;
  19.198 +    obt->freq = freq;
  19.199 +    obt->nfrags = abinfo.fragstotal;
  19.200 +    obt->fragsize = abinfo.fragsize;
  19.201 +    *pfd = fd;
  19.202 +
  19.203 +    if ((req->fmt != obt->fmt) ||
  19.204 +        (req->nchannels != obt->nchannels) ||
  19.205 +        (req->freq != obt->freq) ||
  19.206 +        (req->fragsize != obt->fragsize) ||
  19.207 +        (req->nfrags != obt->nfrags)) {
  19.208 +#ifdef DEBUG_PCM
  19.209 +        dolog ("Audio parameters mismatch\n");
  19.210 +        oss_dump_pcm_info (req, obt);
  19.211 +#endif
  19.212 +    }
  19.213 +
  19.214 +#ifdef DEBUG_PCM
  19.215 +    oss_dump_pcm_info (req, obt);
  19.216 +#endif
  19.217 +    return 0;
  19.218 +
  19.219 +err:
  19.220 +    close (fd);
  19.221 +    return -1;
  19.222 +}
  19.223 +
  19.224 +static void oss_hw_run (HWVoice *hw)
  19.225 +{
  19.226 +    OSSVoice *oss = (OSSVoice *) hw;
  19.227 +    int err, rpos, live, decr;
  19.228 +    int samples;
  19.229 +    uint8_t *dst;
  19.230 +    st_sample_t *src;
  19.231 +    struct audio_buf_info abinfo;
  19.232 +    struct count_info cntinfo;
  19.233 +
  19.234 +    live = pcm_hw_get_live (hw);
  19.235 +    if (live <= 0)
  19.236 +        return;
  19.237 +
  19.238 +    if (oss->mmapped) {
  19.239 +        int bytes;
  19.240 +
  19.241 +        err = ioctl (oss->fd, SNDCTL_DSP_GETOPTR, &cntinfo);
  19.242 +        if (err < 0) {
  19.243 +            dolog ("SNDCTL_DSP_GETOPTR failed\nReason: %s\n", errstr ());
  19.244 +            return;
  19.245 +        }
  19.246 +
  19.247 +        if (cntinfo.ptr == oss->old_optr) {
  19.248 +            if (abs (hw->samples - live) < 64)
  19.249 +                dolog ("overrun\n");
  19.250 +            return;
  19.251 +        }
  19.252 +
  19.253 +        if (cntinfo.ptr > oss->old_optr) {
  19.254 +            bytes = cntinfo.ptr - oss->old_optr;
  19.255 +        }
  19.256 +        else {
  19.257 +            bytes = hw->bufsize + cntinfo.ptr - oss->old_optr;
  19.258 +        }
  19.259 +
  19.260 +        decr = audio_MIN (bytes >> hw->shift, live);
  19.261 +    }
  19.262 +    else {
  19.263 +        err = ioctl (oss->fd, SNDCTL_DSP_GETOSPACE, &abinfo);
  19.264 +        if (err < 0) {
  19.265 +            dolog ("SNDCTL_DSP_GETOSPACE failed\nReason: %s\n", errstr ());
  19.266 +            return;
  19.267 +        }
  19.268 +
  19.269 +        decr = audio_MIN (abinfo.bytes >> hw->shift, live);
  19.270 +        if (decr <= 0)
  19.271 +            return;
  19.272 +    }
  19.273 +
  19.274 +    samples = decr;
  19.275 +    rpos = hw->rpos;
  19.276 +    while (samples) {
  19.277 +        int left_till_end_samples = hw->samples - rpos;
  19.278 +        int convert_samples = audio_MIN (samples, left_till_end_samples);
  19.279 +
  19.280 +        src = advance (hw->mix_buf, rpos * sizeof (st_sample_t));
  19.281 +        dst = advance (oss->pcm_buf, rpos << hw->shift);
  19.282 +
  19.283 +        hw->clip (dst, src, convert_samples);
  19.284 +        if (!oss->mmapped) {
  19.285 +            int written;
  19.286 +
  19.287 +            written = write (oss->fd, dst, convert_samples << hw->shift);
  19.288 +            /* XXX: follow errno recommendations ? */
  19.289 +            if (written == -1) {
  19.290 +                dolog ("Failed to write audio\nReason: %s\n", errstr ());
  19.291 +                continue;
  19.292 +            }
  19.293 +
  19.294 +            if (written != convert_samples << hw->shift) {
  19.295 +                int wsamples = written >> hw->shift;
  19.296 +                int wbytes = wsamples << hw->shift;
  19.297 +                if (wbytes != written) {
  19.298 +                    dolog ("Unaligned write %d, %d\n", wbytes, written);
  19.299 +                }
  19.300 +                memset (src, 0, wbytes);
  19.301 +                decr -= samples;
  19.302 +                rpos = (rpos + wsamples) % hw->samples;
  19.303 +                break;
  19.304 +            }
  19.305 +        }
  19.306 +        memset (src, 0, convert_samples * sizeof (st_sample_t));
  19.307 +
  19.308 +        rpos = (rpos + convert_samples) % hw->samples;
  19.309 +        samples -= convert_samples;
  19.310 +    }
  19.311 +    if (oss->mmapped) {
  19.312 +        oss->old_optr = cntinfo.ptr;
  19.313 +    }
  19.314 +
  19.315 +    pcm_hw_dec_live (hw, decr);
  19.316 +    hw->rpos = rpos;
  19.317 +}
  19.318 +
  19.319 +static void oss_hw_fini (HWVoice *hw)
  19.320 +{
  19.321 +    int err;
  19.322 +    OSSVoice *oss = (OSSVoice *) hw;
  19.323 +
  19.324 +    ldebug ("oss_hw_fini\n");
  19.325 +    err = close (oss->fd);
  19.326 +    if (err) {
  19.327 +        dolog ("Failed to close OSS descriptor\nReason: %s\n", errstr ());
  19.328 +    }
  19.329 +    oss->fd = -1;
  19.330 +
  19.331 +    if (oss->pcm_buf) {
  19.332 +        if (oss->mmapped) {
  19.333 +            err = munmap (oss->pcm_buf, hw->bufsize);
  19.334 +            if (err) {
  19.335 +                dolog ("Failed to unmap OSS buffer\nReason: %s\n",
  19.336 +                       errstr ());
  19.337 +            }
  19.338 +        }
  19.339 +        else {
  19.340 +            qemu_free (oss->pcm_buf);
  19.341 +        }
  19.342 +        oss->pcm_buf = NULL;
  19.343 +    }
  19.344 +}
  19.345 +
  19.346 +static int oss_hw_init (HWVoice *hw, int freq, int nchannels, audfmt_e fmt)
  19.347 +{
  19.348 +    OSSVoice *oss = (OSSVoice *) hw;
  19.349 +    struct oss_params req, obt;
  19.350 +
  19.351 +    assert (!oss->fd);
  19.352 +    req.fmt = AUD_to_ossfmt (fmt);
  19.353 +    req.freq = freq;
  19.354 +    req.nchannels = nchannels;
  19.355 +    req.fragsize = conf.fragsize;
  19.356 +    req.nfrags = conf.nfrags;
  19.357 +
  19.358 +    if (oss_open (&req, &obt, &oss->fd))
  19.359 +        return -1;
  19.360 +
  19.361 +    hw->freq = obt.freq;
  19.362 +    hw->fmt = oss_to_audfmt (obt.fmt);
  19.363 +    hw->nchannels = obt.nchannels;
  19.364 +
  19.365 +    oss->nfrags = obt.nfrags;
  19.366 +    oss->fragsize = obt.fragsize;
  19.367 +    hw->bufsize = obt.nfrags * obt.fragsize;
  19.368 +
  19.369 +    oss->mmapped = 0;
  19.370 +    if (conf.try_mmap) {
  19.371 +        oss->pcm_buf = mmap (0, hw->bufsize, PROT_READ | PROT_WRITE,
  19.372 +                             MAP_SHARED, oss->fd, 0);
  19.373 +        if (oss->pcm_buf == MAP_FAILED) {
  19.374 +            dolog ("Failed to mmap OSS device\nReason: %s\n",
  19.375 +                   errstr ());
  19.376 +        } else {
  19.377 +            int err;
  19.378 +            int trig = 0;
  19.379 +            if (ioctl (oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) {
  19.380 +                dolog ("SNDCTL_DSP_SETTRIGGER 0 failed\nReason: %s\n",
  19.381 +                       errstr ());
  19.382 +            }
  19.383 +            else {
  19.384 +                trig = PCM_ENABLE_OUTPUT;
  19.385 +                if (ioctl (oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) {
  19.386 +                    dolog ("SNDCTL_DSP_SETTRIGGER PCM_ENABLE_OUTPUT failed\n"
  19.387 +                           "Reason: %s\n", errstr ());
  19.388 +                }
  19.389 +                else {
  19.390 +                    oss->mmapped = 1;
  19.391 +                }
  19.392 +            }
  19.393 +
  19.394 +            if (!oss->mmapped) {
  19.395 +                err = munmap (oss->pcm_buf, hw->bufsize);
  19.396 +                if (err) {
  19.397 +                    dolog ("Failed to unmap OSS device\nReason: %s\n",
  19.398 +                           errstr ());
  19.399 +                }
  19.400 +            }
  19.401 +        }
  19.402 +    }
  19.403 +
  19.404 +    if (!oss->mmapped) {
  19.405 +        oss->pcm_buf = qemu_mallocz (hw->bufsize);
  19.406 +        if (!oss->pcm_buf) {
  19.407 +            close (oss->fd);
  19.408 +            oss->fd = -1;
  19.409 +            return -1;
  19.410 +        }
  19.411 +    }
  19.412 +
  19.413 +    return 0;
  19.414 +}
  19.415 +
  19.416 +static int oss_hw_ctl (HWVoice *hw, int cmd, ...)
  19.417 +{
  19.418 +    int trig;
  19.419 +    OSSVoice *oss = (OSSVoice *) hw;
  19.420 +
  19.421 +    if (!oss->mmapped)
  19.422 +        return 0;
  19.423 +
  19.424 +    switch (cmd) {
  19.425 +    case VOICE_ENABLE:
  19.426 +        ldebug ("enabling voice\n");
  19.427 +        pcm_hw_clear (hw, oss->pcm_buf, hw->samples);
  19.428 +        trig = PCM_ENABLE_OUTPUT;
  19.429 +        if (ioctl (oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) {
  19.430 +            dolog ("SNDCTL_DSP_SETTRIGGER PCM_ENABLE_OUTPUT failed\n"
  19.431 +                   "Reason: %s\n", errstr ());
  19.432 +            return -1;
  19.433 +        }
  19.434 +        break;
  19.435 +
  19.436 +    case VOICE_DISABLE:
  19.437 +        ldebug ("disabling voice\n");
  19.438 +        trig = 0;
  19.439 +        if (ioctl (oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) {
  19.440 +            dolog ("SNDCTL_DSP_SETTRIGGER 0 failed\nReason: %s\n",
  19.441 +                   errstr ());
  19.442 +            return -1;
  19.443 +        }
  19.444 +        break;
  19.445 +    }
  19.446 +    return 0;
  19.447 +}
  19.448 +
  19.449 +static void *oss_audio_init (void)
  19.450 +{
  19.451 +    conf.fragsize = audio_get_conf_int (QC_OSS_FRAGSIZE, conf.fragsize);
  19.452 +    conf.nfrags = audio_get_conf_int (QC_OSS_NFRAGS, conf.nfrags);
  19.453 +    conf.try_mmap = audio_get_conf_int (QC_OSS_MMAP, conf.try_mmap);
  19.454 +    conf.dspname = audio_get_conf_str (QC_OSS_DEV, conf.dspname);
  19.455 +    return &conf;
  19.456 +}
  19.457 +
  19.458 +static void oss_audio_fini (void *opaque)
  19.459 +{
  19.460 +}
  19.461 +
  19.462 +struct pcm_ops oss_pcm_ops = {
  19.463 +    oss_hw_init,
  19.464 +    oss_hw_fini,
  19.465 +    oss_hw_run,
  19.466 +    oss_hw_write,
  19.467 +    oss_hw_ctl
  19.468 +};
  19.469 +
  19.470 +struct audio_output_driver oss_output_driver = {
  19.471 +    "oss",
  19.472 +    oss_audio_init,
  19.473 +    oss_audio_fini,
  19.474 +    &oss_pcm_ops,
  19.475 +    1,
  19.476 +    INT_MAX,
  19.477 +    sizeof (OSSVoice)
  19.478 +};
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/tools/ioemu/audio/sdlaudio.c	Tue Dec 20 17:16:24 2005 +0000
    20.3 @@ -0,0 +1,332 @@
    20.4 +/*
    20.5 + * QEMU SDL audio output driver
    20.6 + * 
    20.7 + * Copyright (c) 2004 Vassili Karpov (malc)
    20.8 + * 
    20.9 + * Permission is hereby granted, free of charge, to any person obtaining a copy
   20.10 + * of this software and associated documentation files (the "Software"), to deal
   20.11 + * in the Software without restriction, including without limitation the rights
   20.12 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   20.13 + * copies of the Software, and to permit persons to whom the Software is
   20.14 + * furnished to do so, subject to the following conditions:
   20.15 + *
   20.16 + * The above copyright notice and this permission notice shall be included in
   20.17 + * all copies or substantial portions of the Software.
   20.18 + *
   20.19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   20.20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   20.21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   20.22 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   20.23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   20.24 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   20.25 + * THE SOFTWARE.
   20.26 + */
   20.27 +#include <SDL.h>
   20.28 +#include <SDL_thread.h>
   20.29 +#include "vl.h"
   20.30 +
   20.31 +#include "audio/audio_int.h"
   20.32 +
   20.33 +typedef struct SDLVoice {
   20.34 +    HWVoice hw;
   20.35 +} SDLVoice;
   20.36 +
   20.37 +#define dolog(...) AUD_log ("sdl", __VA_ARGS__)
   20.38 +#ifdef DEBUG
   20.39 +#define ldebug(...) dolog (__VA_ARGS__)
   20.40 +#else
   20.41 +#define ldebug(...)
   20.42 +#endif
   20.43 +
   20.44 +#define QC_SDL_SAMPLES "QEMU_SDL_SAMPLES"
   20.45 +
   20.46 +#define errstr() SDL_GetError ()
   20.47 +
   20.48 +static struct {
   20.49 +    int nb_samples;
   20.50 +} conf = {
   20.51 +    1024
   20.52 +};
   20.53 +
   20.54 +struct SDLAudioState {
   20.55 +    int exit;
   20.56 +    SDL_mutex *mutex;
   20.57 +    SDL_sem *sem;
   20.58 +    int initialized;
   20.59 +} glob_sdl;
   20.60 +typedef struct SDLAudioState SDLAudioState;
   20.61 +
   20.62 +static void sdl_hw_run (HWVoice *hw)
   20.63 +{
   20.64 +    (void) hw;
   20.65 +}
   20.66 +
   20.67 +static int sdl_lock (SDLAudioState *s)
   20.68 +{
   20.69 +    if (SDL_LockMutex (s->mutex)) {
   20.70 +        dolog ("SDL_LockMutex failed\nReason: %s\n", errstr ());
   20.71 +        return -1;
   20.72 +    }
   20.73 +    return 0;
   20.74 +}
   20.75 +
   20.76 +static int sdl_unlock (SDLAudioState *s)
   20.77 +{
   20.78 +    if (SDL_UnlockMutex (s->mutex)) {
   20.79 +        dolog ("SDL_UnlockMutex failed\nReason: %s\n", errstr ());
   20.80 +        return -1;
   20.81 +    }
   20.82 +    return 0;
   20.83 +}
   20.84 +
   20.85 +static int sdl_post (SDLAudioState *s)
   20.86 +{
   20.87 +    if (SDL_SemPost (s->sem)) {
   20.88 +        dolog ("SDL_SemPost failed\nReason: %s\n", errstr ());
   20.89 +        return -1;
   20.90 +    }
   20.91 +    return 0;
   20.92 +}
   20.93 +
   20.94 +static int sdl_wait (SDLAudioState *s)
   20.95 +{
   20.96 +    if (SDL_SemWait (s->sem)) {
   20.97 +        dolog ("SDL_SemWait failed\nReason: %s\n", errstr ());
   20.98 +        return -1;
   20.99 +    }
  20.100 +    return 0;
  20.101 +}
  20.102 +
  20.103 +static int sdl_unlock_and_post (SDLAudioState *s)
  20.104 +{
  20.105 +    if (sdl_unlock (s))
  20.106 +        return -1;
  20.107 +
  20.108 +    return sdl_post (s);
  20.109 +}
  20.110 +
  20.111 +static int sdl_hw_write (SWVoice *sw, void *buf, int len)
  20.112 +{
  20.113 +    int ret;
  20.114 +    SDLAudioState *s = &glob_sdl;
  20.115 +    sdl_lock (s);
  20.116 +    ret = pcm_hw_write (sw, buf, len);
  20.117 +    sdl_unlock_and_post (s);
  20.118 +    return ret;
  20.119 +}
  20.120 +
  20.121 +static int AUD_to_sdlfmt (audfmt_e fmt, int *shift)
  20.122 +{
  20.123 +    *shift = 0;
  20.124 +    switch (fmt) {
  20.125 +    case AUD_FMT_S8: return AUDIO_S8;
  20.126 +    case AUD_FMT_U8: return AUDIO_U8;
  20.127 +    case AUD_FMT_S16: *shift = 1; return AUDIO_S16LSB;
  20.128 +    case AUD_FMT_U16: *shift = 1; return AUDIO_U16LSB;
  20.129 +    default:
  20.130 +        dolog ("Internal logic error: Bad audio format %d\nAborting\n", fmt);
  20.131 +        exit (EXIT_FAILURE);
  20.132 +    }
  20.133 +}
  20.134 +
  20.135 +static int sdl_to_audfmt (int fmt)
  20.136 +{
  20.137 +    switch (fmt) {
  20.138 +    case AUDIO_S8: return AUD_FMT_S8;
  20.139 +    case AUDIO_U8: return AUD_FMT_U8;
  20.140 +    case AUDIO_S16LSB: return AUD_FMT_S16;
  20.141 +    case AUDIO_U16LSB: return AUD_FMT_U16;
  20.142 +    default:
  20.143 +        dolog ("Internal logic error: Unrecognized SDL audio format %d\n"
  20.144 +               "Aborting\n", fmt);
  20.145 +        exit (EXIT_FAILURE);
  20.146 +    }
  20.147 +}
  20.148 +
  20.149 +static int sdl_open (SDL_AudioSpec *req, SDL_AudioSpec *obt)
  20.150 +{
  20.151 +    int status;
  20.152 +
  20.153 +    status = SDL_OpenAudio (req, obt);
  20.154 +    if (status) {
  20.155 +        dolog ("SDL_OpenAudio failed\nReason: %s\n", errstr ());
  20.156 +    }
  20.157 +    return status;
  20.158 +}
  20.159 +
  20.160 +static void sdl_close (SDLAudioState *s)
  20.161 +{
  20.162 +    if (s->initialized) {
  20.163 +        sdl_lock (s);
  20.164 +        s->exit = 1;
  20.165 +        sdl_unlock_and_post (s);
  20.166 +        SDL_PauseAudio (1);
  20.167 +        SDL_CloseAudio ();
  20.168 +        s->initialized = 0;
  20.169 +    }
  20.170 +}
  20.171 +
  20.172 +static void sdl_callback (void *opaque, Uint8 *buf, int len)
  20.173 +{
  20.174 +    SDLVoice *sdl = opaque;
  20.175 +    SDLAudioState *s = &glob_sdl;
  20.176 +    HWVoice *hw = &sdl->hw;
  20.177 +    int samples = len >> hw->shift;
  20.178 +
  20.179 +    if (s->exit) {
  20.180 +        return;
  20.181 +    }
  20.182 +
  20.183 +    while (samples) {
  20.184 +        int to_mix, live, decr;
  20.185 +
  20.186 +        /* dolog ("in callback samples=%d\n", samples); */
  20.187 +        sdl_wait (s);
  20.188 +        if (s->exit) {
  20.189 +            return;
  20.190 +        }
  20.191 +
  20.192 +        sdl_lock (s);
  20.193 +        live = pcm_hw_get_live (hw);
  20.194 +        if (live <= 0)
  20.195 +            goto again;
  20.196 +
  20.197 +        /* dolog ("in callback live=%d\n", live); */
  20.198 +        to_mix = audio_MIN (samples, live);
  20.199 +        decr = to_mix;
  20.200 +        while (to_mix) {
  20.201 +            int chunk = audio_MIN (to_mix, hw->samples - hw->rpos);
  20.202 +            st_sample_t *src = hw->mix_buf + hw->rpos;
  20.203 +
  20.204 +            /* dolog ("in callback to_mix %d, chunk %d\n", to_mix, chunk); */
  20.205 +            hw->clip (buf, src, chunk);
  20.206 +            memset (src, 0, chunk * sizeof (st_sample_t));
  20.207 +            hw->rpos = (hw->rpos + chunk) % hw->samples;
  20.208 +            to_mix -= chunk;
  20.209 +            buf += chunk << hw->shift;
  20.210 +        }
  20.211 +        samples -= decr;
  20.212 +        pcm_hw_dec_live (hw, decr);
  20.213 +
  20.214 +    again:
  20.215 +        sdl_unlock (s);
  20.216 +    }
  20.217 +    /* dolog ("done len=%d\n", len); */
  20.218 +}
  20.219 +
  20.220 +static void sdl_hw_fini (HWVoice *hw)
  20.221 +{
  20.222 +    ldebug ("sdl_hw_fini %d fixed=%d\n",
  20.223 +             glob_sdl.initialized, audio_conf.fixed_format);
  20.224 +    sdl_close (&glob_sdl);
  20.225 +}
  20.226 +
  20.227 +static int sdl_hw_init (HWVoice *hw, int freq, int nchannels, audfmt_e fmt)
  20.228 +{
  20.229 +    SDLVoice *sdl = (SDLVoice *) hw;
  20.230 +    SDLAudioState *s = &glob_sdl;
  20.231 +    SDL_AudioSpec req, obt;
  20.232 +    int shift;
  20.233 +
  20.234 +    ldebug ("sdl_hw_init %d freq=%d fixed=%d\n",
  20.235 +            s->initialized, freq, audio_conf.fixed_format);
  20.236 +
  20.237 +    if (nchannels != 2) {
  20.238 +        dolog ("Bogus channel count %d\n", nchannels);
  20.239 +        return -1;
  20.240 +    }
  20.241 +
  20.242 +    req.freq = freq;
  20.243 +    req.format = AUD_to_sdlfmt (fmt, &shift);
  20.244 +    req.channels = nchannels;
  20.245 +    req.samples = conf.nb_samples;
  20.246 +    shift <<= nchannels == 2;
  20.247 +
  20.248 +    req.callback = sdl_callback;
  20.249 +    req.userdata = sdl;
  20.250 +
  20.251 +    if (sdl_open (&req, &obt))
  20.252 +        return -1;
  20.253 +
  20.254 +    hw->freq = obt.freq;
  20.255 +    hw->fmt = sdl_to_audfmt (obt.format);
  20.256 +    hw->nchannels = obt.channels;
  20.257 +    hw->bufsize = obt.samples << shift;
  20.258 +
  20.259 +    s->initialized = 1;
  20.260 +    s->exit = 0;
  20.261 +    SDL_PauseAudio (0);
  20.262 +    return 0;
  20.263 +}
  20.264 +
  20.265 +static int sdl_hw_ctl (HWVoice *hw, int cmd, ...)
  20.266 +{
  20.267 +    (void) hw;
  20.268 +
  20.269 +    switch (cmd) {
  20.270 +    case VOICE_ENABLE:
  20.271 +        SDL_PauseAudio (0);
  20.272 +        break;
  20.273 +
  20.274 +    case VOICE_DISABLE:
  20.275 +        SDL_PauseAudio (1);
  20.276 +        break;
  20.277 +    }
  20.278 +    return 0;
  20.279 +}
  20.280 +
  20.281 +static void *sdl_audio_init (void)
  20.282 +{
  20.283 +    SDLAudioState *s = &glob_sdl;
  20.284 +    conf.nb_samples = audio_get_conf_int (QC_SDL_SAMPLES, conf.nb_samples);
  20.285 +
  20.286 +    if (SDL_InitSubSystem (SDL_INIT_AUDIO)) {
  20.287 +        dolog ("SDL failed to initialize audio subsystem\nReason: %s\n",
  20.288 +               errstr ());
  20.289 +        return NULL;
  20.290 +    }
  20.291 +
  20.292 +    s->mutex = SDL_CreateMutex ();
  20.293 +    if (!s->mutex) {
  20.294 +        dolog ("Failed to create SDL mutex\nReason: %s\n", errstr ());
  20.295 +        SDL_QuitSubSystem (SDL_INIT_AUDIO);
  20.296 +        return NULL;
  20.297 +    }
  20.298 +
  20.299 +    s->sem = SDL_CreateSemaphore (0);
  20.300 +    if (!s->sem) {
  20.301 +        dolog ("Failed to create SDL semaphore\nReason: %s\n", errstr ());
  20.302 +        SDL_DestroyMutex (s->mutex);
  20.303 +        SDL_QuitSubSystem (SDL_INIT_AUDIO);
  20.304 +        return NULL;
  20.305 +    }
  20.306 +
  20.307 +    return s;
  20.308 +}
  20.309 +
  20.310 +static void sdl_audio_fini (void *opaque)
  20.311 +{
  20.312 +    SDLAudioState *s = opaque;
  20.313 +    sdl_close (s);
  20.314 +    SDL_DestroySemaphore (s->sem);
  20.315 +    SDL_DestroyMutex (s->mutex);
  20.316 +    SDL_QuitSubSystem (SDL_INIT_AUDIO);
  20.317 +}
  20.318 +
  20.319 +struct pcm_ops sdl_pcm_ops = {
  20.320 +    sdl_hw_init,
  20.321 +    sdl_hw_fini,
  20.322 +    sdl_hw_run,
  20.323 +    sdl_hw_write,
  20.324 +    sdl_hw_ctl
  20.325 +};
  20.326 +
  20.327 +struct audio_output_driver sdl_output_driver = {
  20.328 +    "sdl",
  20.329 +    sdl_audio_init,
  20.330 +    sdl_audio_fini,
  20.331 +    &sdl_pcm_ops,
  20.332 +    1,
  20.333 +    1,
  20.334 +    sizeof (SDLVoice)
  20.335 +};
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/tools/ioemu/audio/wavaudio.c	Tue Dec 20 17:16:24 2005 +0000
    21.3 @@ -0,0 +1,217 @@
    21.4 +/*
    21.5 + * QEMU WAV audio output driver
    21.6 + * 
    21.7 + * Copyright (c) 2004 Vassili Karpov (malc)
    21.8 + * 
    21.9 + * Permission is hereby granted, free of charge, to any person obtaining a copy
   21.10 + * of this software and associated documentation files (the "Software"), to deal
   21.11 + * in the Software without restriction, including without limitation the rights
   21.12 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   21.13 + * copies of the Software, and to permit persons to whom the Software is
   21.14 + * furnished to do so, subject to the following conditions:
   21.15 + *
   21.16 + * The above copyright notice and this permission notice shall be included in
   21.17 + * all copies or substantial portions of the Software.
   21.18 + *
   21.19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   21.20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   21.21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   21.22 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   21.23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   21.24 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   21.25 + * THE SOFTWARE.
   21.26 + */
   21.27 +#include "vl.h"
   21.28 +
   21.29 +#include "audio/audio_int.h"
   21.30 +
   21.31 +typedef struct WAVVoice {
   21.32 +    HWVoice hw;
   21.33 +    QEMUFile *f;
   21.34 +    int64_t old_ticks;
   21.35 +    void *pcm_buf;
   21.36 +    int total_samples;
   21.37 +} WAVVoice;
   21.38 +
   21.39 +#define dolog(...) AUD_log ("wav", __VA_ARGS__)
   21.40 +#ifdef DEBUG
   21.41 +#define ldebug(...) dolog (__VA_ARGS__)
   21.42 +#else
   21.43 +#define ldebug(...)
   21.44 +#endif
   21.45 +
   21.46 +static struct {
   21.47 +    const char *wav_path;
   21.48 +} conf = {
   21.49 +    .wav_path = "qemu.wav"
   21.50 +};
   21.51 +
   21.52 +static void wav_hw_run (HWVoice *hw)
   21.53 +{
   21.54 +    WAVVoice *wav = (WAVVoice *) hw;
   21.55 +    int rpos, live, decr, samples;
   21.56 +    uint8_t *dst;
   21.57 +    st_sample_t *src;
   21.58 +    int64_t now = qemu_get_clock (vm_clock);
   21.59 +    int64_t ticks = now - wav->old_ticks;
   21.60 +    int64_t bytes = (ticks * hw->bytes_per_second) / ticks_per_sec;
   21.61 +
   21.62 +    if (bytes > INT_MAX)
   21.63 +        samples = INT_MAX >> hw->shift;
   21.64 +    else
   21.65 +        samples = bytes >> hw->shift;
   21.66 +
   21.67 +    live = pcm_hw_get_live (hw);
   21.68 +    if (live <= 0)
   21.69 +        return;
   21.70 +
   21.71 +    wav->old_ticks = now;
   21.72 +    decr = audio_MIN (live, samples);
   21.73 +    samples = decr;
   21.74 +    rpos = hw->rpos;
   21.75 +    while (samples) {
   21.76 +        int left_till_end_samples = hw->samples - rpos;
   21.77 +        int convert_samples = audio_MIN (samples, left_till_end_samples);
   21.78 +
   21.79 +        src = advance (hw->mix_buf, rpos * sizeof (st_sample_t));
   21.80 +        dst = advance (wav->pcm_buf, rpos << hw->shift);
   21.81 +
   21.82 +        hw->clip (dst, src, convert_samples);
   21.83 +        qemu_put_buffer (wav->f, dst, convert_samples << hw->shift);
   21.84 +        memset (src, 0, convert_samples * sizeof (st_sample_t));
   21.85 +
   21.86 +        rpos = (rpos + convert_samples) % hw->samples;
   21.87 +        samples -= convert_samples;
   21.88 +        wav->total_samples += convert_samples;
   21.89 +    }
   21.90 +
   21.91 +    pcm_hw_dec_live (hw, decr);
   21.92 +    hw->rpos = rpos;
   21.93 +}
   21.94 +
   21.95 +static int wav_hw_write (SWVoice *sw, void *buf, int len)
   21.96 +{
   21.97 +    return pcm_hw_write (sw, buf, len);
   21.98 +}
   21.99 +
  21.100 +/* VICE code: Store number as little endian. */
  21.101 +static void le_store (uint8_t *buf, uint32_t val, int len)
  21.102 +{
  21.103 +    int i;
  21.104 +    for (i = 0; i < len; i++) {
  21.105 +        buf[i] = (uint8_t) (val & 0xff);
  21.106 +        val >>= 8;
  21.107 +    }
  21.108 +}
  21.109 +
  21.110 +static int wav_hw_init (HWVoice *hw, int freq, int nchannels, audfmt_e fmt)
  21.111 +{
  21.112 +    WAVVoice *wav = (WAVVoice *) hw;
  21.113 +    int bits16 = 0, stereo = audio_state.fixed_channels == 2;
  21.114 +    uint8_t hdr[] = {
  21.115 +        0x52, 0x49, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x57, 0x41, 0x56,
  21.116 +        0x45, 0x66, 0x6d, 0x74, 0x20, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00,
  21.117 +        0x02, 0x00, 0x44, 0xac, 0x00, 0x00, 0x10, 0xb1, 0x02, 0x00, 0x04,
  21.118 +        0x00, 0x10, 0x00, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x00
  21.119 +    };
  21.120 +
  21.121 +    switch (audio_state.fixed_fmt) {
  21.122 +    case AUD_FMT_S8:
  21.123 +    case AUD_FMT_U8:
  21.124 +        break;
  21.125 +
  21.126 +    case AUD_FMT_S16:
  21.127 +    case AUD_FMT_U16:
  21.128 +        bits16 = 1;
  21.129 +        break;
  21.130 +    }
  21.131 +
  21.132 +    hdr[34] = bits16 ? 0x10 : 0x08;
  21.133 +    hw->freq = 44100;
  21.134 +    hw->nchannels = stereo ? 2 : 1;
  21.135 +    hw->fmt = bits16 ? AUD_FMT_S16 : AUD_FMT_U8;
  21.136 +    hw->bufsize = 4096;
  21.137 +    wav->pcm_buf = qemu_mallocz (hw->bufsize);
  21.138 +    if (!wav->pcm_buf)
  21.139 +        return -1;
  21.140 +
  21.141 +    le_store (hdr + 22, hw->nchannels, 2);
  21.142 +    le_store (hdr + 24, hw->freq, 4);
  21.143 +    le_store (hdr + 28, hw->freq << (bits16 + stereo), 4);
  21.144 +    le_store (hdr + 32, 1 << (bits16 + stereo), 2);
  21.145 +
  21.146 +    wav->f = fopen (conf.wav_path, "wb");
  21.147 +    if (!wav->f) {
  21.148 +        dolog ("failed to open wave file `%s'\nReason: %s\n",
  21.149 +               conf.wav_path, strerror (errno));
  21.150 +        qemu_free (wav->pcm_buf);
  21.151 +        wav->pcm_buf = NULL;
  21.152 +        return -1;
  21.153 +    }
  21.154 +
  21.155 +    qemu_put_buffer (wav->f, hdr, sizeof (hdr));
  21.156 +    return 0;
  21.157 +}
  21.158 +
  21.159 +static void wav_hw_fini (HWVoice *hw)
  21.160 +{
  21.161 +    WAVVoice *wav = (WAVVoice *) hw;
  21.162 +    int stereo = hw->nchannels == 2;
  21.163 +    uint8_t rlen[4];
  21.164 +    uint8_t dlen[4];
  21.165 +    uint32_t rifflen = (wav->total_samples << stereo) + 36;
  21.166 +    uint32_t datalen = wav->total_samples << stereo;
  21.167 +
  21.168 +    if (!wav->f || !hw->active)
  21.169 +        return;
  21.170 +
  21.171 +    le_store (rlen, rifflen, 4);
  21.172 +    le_store (dlen, datalen, 4);
  21.173 +
  21.174 +    qemu_fseek (wav->f, 4, SEEK_SET);
  21.175 +    qemu_put_buffer (wav->f, rlen, 4);
  21.176 +
  21.177 +    qemu_fseek (wav->f, 32, SEEK_CUR);
  21.178 +    qemu_put_buffer (wav->f, dlen, 4);
  21.179 +
  21.180 +    fclose (wav->f);
  21.181 +    wav->f = NULL;
  21.182 +
  21.183 +    qemu_free (wav->pcm_buf);
  21.184 +    wav->pcm_buf = NULL;
  21.185 +}
  21.186 +
  21.187 +static int wav_hw_ctl (HWVoice *hw, int cmd, ...)
  21.188 +{
  21.189 +    (void) hw;
  21.190 +    (void) cmd;
  21.191 +    return 0;
  21.192 +}
  21.193 +
  21.194 +static void *wav_audio_init (void)
  21.195 +{
  21.196 +    return &conf;
  21.197 +}
  21.198 +
  21.199 +static void wav_audio_fini (void *opaque)
  21.200 +{
  21.201 +    ldebug ("wav_fini");
  21.202 +}
  21.203 +
  21.204 +struct pcm_ops wav_pcm_ops = {
  21.205 +    wav_hw_init,
  21.206 +    wav_hw_fini,
  21.207 +    wav_hw_run,
  21.208 +    wav_hw_write,
  21.209 +    wav_hw_ctl
  21.210 +};
  21.211 +
  21.212 +struct audio_output_driver wav_output_driver = {
  21.213 +    "wav",
  21.214 +    wav_audio_init,
  21.215 +    wav_audio_fini,
  21.216 +    &wav_pcm_ops,
  21.217 +    1,
  21.218 +    1,
  21.219 +    sizeof (WAVVoice)
  21.220 +};
    22.1 --- a/tools/ioemu/cpu-all.h	Tue Dec 20 17:16:15 2005 +0000
    22.2 +++ b/tools/ioemu/cpu-all.h	Tue Dec 20 17:16:24 2005 +0000
    22.3 @@ -668,7 +668,7 @@ static __inline__ void atomic_clear_bit(
    22.4  #endif
    22.5  /* memory API */
    22.6  
    22.7 -extern int phys_ram_size;
    22.8 +extern uint64_t phys_ram_size;
    22.9  extern int phys_ram_fd;
   22.10  extern uint8_t *phys_ram_base;
   22.11  extern uint8_t *phys_ram_dirty;
    23.1 --- a/tools/ioemu/exec.c	Tue Dec 20 17:16:15 2005 +0000
    23.2 +++ b/tools/ioemu/exec.c	Tue Dec 20 17:16:24 2005 +0000
    23.3 @@ -61,7 +61,7 @@ spinlock_t tb_lock = SPIN_LOCK_UNLOCKED;
    23.4  uint8_t code_gen_buffer[CODE_GEN_BUFFER_SIZE];
    23.5  uint8_t *code_gen_ptr;
    23.6  
    23.7 -int phys_ram_size;
    23.8 +uint64_t phys_ram_size;
    23.9  int phys_ram_fd;
   23.10  uint8_t *phys_ram_base;
   23.11  uint8_t *phys_ram_dirty;
    24.1 --- a/tools/ioemu/hw/pc.c	Tue Dec 20 17:16:15 2005 +0000
    24.2 +++ b/tools/ioemu/hw/pc.c	Tue Dec 20 17:16:24 2005 +0000
    24.3 @@ -119,7 +119,7 @@ static void cmos_init_hd(int type_ofs, i
    24.4  }
    24.5  
    24.6  /* hd_table must contain 4 block drivers */
    24.7 -static void cmos_init(int ram_size, int boot_device, BlockDriverState **hd_table)
    24.8 +static void cmos_init(uint64_t ram_size, int boot_device, BlockDriverState **hd_table)
    24.9  {
   24.10      RTCState *s = rtc_state;
   24.11      int val;
   24.12 @@ -375,7 +375,7 @@ static int serial_irq[MAX_SERIAL_PORTS] 
   24.13  #define NOBIOS 1
   24.14  
   24.15  /* PC hardware initialisation */
   24.16 -void pc_init(int ram_size, int vga_ram_size, int boot_device,
   24.17 +void pc_init(uint64_t ram_size, int vga_ram_size, int boot_device,
   24.18               DisplayState *ds, const char **fd_filename, int snapshot,
   24.19               const char *kernel_filename, const char *kernel_cmdline,
   24.20               const char *initrd_filename)
   24.21 @@ -563,6 +563,15 @@ void pc_init(int ram_size, int vga_ram_s
   24.22  
   24.23      kbd_init();
   24.24      DMA_init(0);
   24.25 +   
   24.26 +    if (audio_enabled) {
   24.27 +        AUD_init();
   24.28 +#ifdef USE_SB16
   24.29 +        if (sb16_enabled)
   24.30 +            SB16_init();
   24.31 +#endif
   24.32 +    }
   24.33 +    
   24.34  
   24.35      floppy_controller = fdctrl_init(6, 2, 0, 0x3f0, fd_table);
   24.36  
    25.1 --- a/tools/ioemu/hw/pcnet.h	Tue Dec 20 17:16:15 2005 +0000
    25.2 +++ b/tools/ioemu/hw/pcnet.h	Tue Dec 20 17:16:24 2005 +0000
    25.3 @@ -92,7 +92,7 @@
    25.4  #define CSR_NRBA(S)      ((S)->csr[22] | ((S)->csr[23] << 16))
    25.5  #define CSR_BADR(S)      ((S)->csr[24] | ((S)->csr[25] << 16))
    25.6  #define CSR_NRDA(S)      ((S)->csr[26] | ((S)->csr[27] << 16))
    25.7 -#define CSR_CRDA(S)      ((S)->csr[28] | ((S)->csr[29] << 16))
    25.8 +#define CSR_CRDA(S)      ((S)->csr[28] | (((uint32_t)((S)->csr[29])) << 16))
    25.9  #define CSR_BADX(S)      ((S)->csr[30] | ((S)->csr[31] << 16))
   25.10  #define CSR_NXDA(S)      ((S)->csr[32] | ((S)->csr[33] << 16))
   25.11  #define CSR_CXDA(S)      ((S)->csr[34] | ((S)->csr[35] << 16))
   25.12 @@ -102,7 +102,7 @@
   25.13  #define CSR_NXBA(S)      ((S)->csr[64] | ((S)->csr[65] << 16))
   25.14  
   25.15  #define PHYSADDR(S,A) \
   25.16 -  (BCR_SSIZE32(S) ? (A) : (A) | ((0xff00 & (uint32_t)(s)->csr[2])<<16))
   25.17 +  (BCR_SSIZE32(S) ? (A) : (A) | ((0xff00 & (uint32_t)(S)->csr[2])<<16))
   25.18  
   25.19  struct pcnet_initblk16 {
   25.20      uint16_t mode;
    26.1 --- a/tools/ioemu/target-i386-dm/Makefile	Tue Dec 20 17:16:15 2005 +0000
    26.2 +++ b/tools/ioemu/target-i386-dm/Makefile	Tue Dec 20 17:16:24 2005 +0000
    26.3 @@ -272,6 +272,7 @@ endif
    26.4  VL_OBJS+= ide.o ne2000.o pckbd.o vga.o dma.o
    26.5  VL_OBJS+= fdc.o mc146818rtc.o serial.o i8259_stub.o i8254.o pc.o port-e9.o
    26.6  VL_OBJS+= cirrus_vga.o pcnet.o
    26.7 +VL_OBJS+= $(SOUND_HW) $(AUDIODRV) mixeng.o
    26.8  
    26.9  ifeq ($(TARGET_ARCH), ppc)
   26.10  VL_OBJS+= ppc.o ide.o ne2000.o pckbd.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
    27.1 --- a/tools/ioemu/vl.c	Tue Dec 20 17:16:15 2005 +0000
    27.2 +++ b/tools/ioemu/vl.c	Tue Dec 20 17:16:24 2005 +0000
    27.3 @@ -119,7 +119,7 @@ const char* vncconnect; /* do a reverse 
    27.4  const char* keyboard_layout = 0;
    27.5  int64_t ticks_per_sec;
    27.6  int boot_device = 'c';
    27.7 -int ram_size;
    27.8 +uint64_t ram_size;
    27.9  int domid = -1;
   27.10  static char network_script[1024];
   27.11  int pit_min_timer_count = 0;
   27.12 @@ -2906,7 +2906,7 @@ int main(int argc, char **argv)
   27.13                  help();
   27.14                  break;
   27.15              case QEMU_OPTION_m:
   27.16 -                ram_size = atoi(optarg) * 1024 * 1024;
   27.17 +                ram_size = atol(optarg) * 1024 * 1024;
   27.18                  if (ram_size <= 0)
   27.19                      help();
   27.20                  break;
    28.1 --- a/tools/ioemu/vl.h	Tue Dec 20 17:16:15 2005 +0000
    28.2 +++ b/tools/ioemu/vl.h	Tue Dec 20 17:16:24 2005 +0000
    28.3 @@ -37,6 +37,7 @@
    28.4  #include <unistd.h>
    28.5  #include <fcntl.h>
    28.6  #include <sys/stat.h>
    28.7 +#include "audio/audio.h"
    28.8  
    28.9  #ifndef O_LARGEFILE
   28.10  #define O_LARGEFILE 0
   28.11 @@ -116,7 +117,7 @@ extern int audio_enabled;
   28.12  extern int sb16_enabled;
   28.13  extern int adlib_enabled;
   28.14  extern int gus_enabled;
   28.15 -extern int ram_size;
   28.16 +extern uint64_t ram_size;
   28.17  extern int bios_size;
   28.18  extern int rtc_utc;
   28.19  extern int cirrus_vga_enabled;
   28.20 @@ -649,7 +650,7 @@ int pit_get_gate(PITState *pit, int chan
   28.21  int pit_get_out(PITState *pit, int channel, int64_t current_time);
   28.22  
   28.23  /* pc.c */
   28.24 -void pc_init(int ram_size, int vga_ram_size, int boot_device,
   28.25 +void pc_init(uint64_t ram_size, int vga_ram_size, int boot_device,
   28.26               DisplayState *ds, const char **fd_filename, int snapshot,
   28.27               const char *kernel_filename, const char *kernel_cmdline,
   28.28               const char *initrd_filename);
    29.1 --- a/tools/libxc/xc_domain.c	Tue Dec 20 17:16:15 2005 +0000
    29.2 +++ b/tools/libxc/xc_domain.c	Tue Dec 20 17:16:24 2005 +0000
    29.3 @@ -380,6 +380,30 @@ int xc_domain_ioport_permission(int xc_h
    29.4      return do_dom0_op(xc_handle, &op);
    29.5  }
    29.6  
    29.7 +int xc_domain_setinfo(int xc_handle,
    29.8 +                      uint32_t domid,
    29.9 +                      uint32_t vcpu,
   29.10 +                      vcpu_guest_context_t *ctxt)
   29.11 +{
   29.12 +    dom0_op_t op;
   29.13 +    int rc;
   29.14 +
   29.15 +    op.cmd = DOM0_SETDOMAININFO;
   29.16 +    op.u.setdomaininfo.domain = domid;
   29.17 +    op.u.setdomaininfo.vcpu = vcpu;
   29.18 +    op.u.setdomaininfo.ctxt = ctxt;
   29.19 +
   29.20 +    if ( (rc = mlock(ctxt, sizeof(*ctxt))) != 0 )
   29.21 +        return rc;
   29.22 +
   29.23 +    rc = do_dom0_op(xc_handle, &op);
   29.24 +
   29.25 +    safe_munlock(ctxt, sizeof(*ctxt));
   29.26 +
   29.27 +    return rc;
   29.28 +
   29.29 +}
   29.30 +
   29.31  /*
   29.32   * Local variables:
   29.33   * mode: C
    30.1 --- a/tools/libxc/xc_ptrace.c	Tue Dec 20 17:16:15 2005 +0000
    30.2 +++ b/tools/libxc/xc_ptrace.c	Tue Dec 20 17:16:24 2005 +0000
    30.3 @@ -1,138 +1,141 @@
    30.4 +#define XC_PTRACE_PRIVATE
    30.5 +
    30.6 +
    30.7  #include <sys/ptrace.h>
    30.8  #include <sys/wait.h>
    30.9 -#include "xc_private.h"
   30.10 -#include "xg_private.h"
   30.11  #include <time.h>
   30.12  
   30.13 -#define X86_CR0_PE              0x00000001 /* Enable Protected Mode    (RW) */
   30.14 -#define X86_CR0_PG              0x80000000 /* Paging                   (RW) */
   30.15 -#define BSD_PAGE_MASK (PAGE_SIZE-1)
   30.16 -#define PDRSHIFT        22
   30.17 -#define PSL_T  0x00000100 /* trace enable bit */
   30.18 -#define VCPU            0               /* XXX */
   30.19 -
   30.20 -char * ptrace_names[] = {
   30.21 -    "PTRACE_TRACEME",
   30.22 -    "PTRACE_PEEKTEXT",
   30.23 -    "PTRACE_PEEKDATA",
   30.24 -    "PTRACE_PEEKUSER",
   30.25 -    "PTRACE_POKETEXT",
   30.26 -    "PTRACE_POKEDATA",
   30.27 -    "PTRACE_POKEUSER",
   30.28 -    "PTRACE_CONT",
   30.29 -    "PTRACE_KILL",
   30.30 -    "PTRACE_SINGLESTEP",
   30.31 -    "PTRACE_INVALID",
   30.32 -    "PTRACE_INVALID",
   30.33 -    "PTRACE_GETREGS",
   30.34 -    "PTRACE_SETREGS",
   30.35 -    "PTRACE_GETFPREGS",
   30.36 -    "PTRACE_SETFPREGS",
   30.37 -    "PTRACE_ATTACH",
   30.38 -    "PTRACE_DETACH",
   30.39 -    "PTRACE_GETFPXREGS",
   30.40 -    "PTRACE_SETFPXREGS",
   30.41 -    "PTRACE_INVALID",
   30.42 -    "PTRACE_INVALID",
   30.43 -    "PTRACE_INVALID",
   30.44 -    "PTRACE_INVALID",
   30.45 -    "PTRACE_SYSCALL",
   30.46 -};
   30.47 +#include "xc_private.h"
   30.48 +#include "xg_private.h"
   30.49 +#include <thread_db.h>
   30.50 +#include "xc_ptrace.h"
   30.51  
   30.52 -struct gdb_regs {
   30.53 -    long ebx; /* 0 */
   30.54 -    long ecx; /* 4 */
   30.55 -    long edx; /* 8 */
   30.56 -    long esi; /* 12 */
   30.57 -    long edi; /* 16 */
   30.58 -    long ebp; /* 20 */
   30.59 -    long eax; /* 24 */ 
   30.60 -    int  xds; /* 28 */
   30.61 -    int  xes; /* 32 */
   30.62 -    int  xfs; /* 36 */
   30.63 -    int  xgs; /* 40 */
   30.64 -    long orig_eax; /* 44 */
   30.65 -    long eip;    /* 48 */
   30.66 -    int  xcs;    /* 52 */
   30.67 -    long eflags; /* 56 */
   30.68 -    long esp;    /* 60 */     
   30.69 -    int  xss;    /* 64 */
   30.70 -};
   30.71  
   30.72 -#define FETCH_REGS(cpu)                                         \
   30.73 -    if (!regs_valid[cpu])                                       \
   30.74 -    {                                                           \
   30.75 -        int retval = xc_domain_get_vcpu_context(                \
   30.76 -            xc_handle, domid, cpu, &ctxt[cpu]);                 \
   30.77 -        if (retval)                                             \
   30.78 -            goto error_out;                                     \
   30.79 -        cr3[cpu] = ctxt[cpu].ctrlreg[3]; /* physical address */ \
   30.80 -        regs_valid[cpu] = 1;                                    \
   30.81 -    }
   30.82 +/* XXX application state */
   30.83 +static long                     nr_pages = 0;
   30.84 +static unsigned long           *page_array = NULL;
   30.85 +static int                      current_domid = -1;
   30.86  
   30.87 -#define printval(x) printf("%s = %lx\n", #x, (long)x);
   30.88 -#define SET_PT_REGS(pt, xc)                     \
   30.89 -{                                               \
   30.90 -    pt.ebx = xc.ebx;                            \
   30.91 -    pt.ecx = xc.ecx;                            \
   30.92 -    pt.edx = xc.edx;                            \
   30.93 -    pt.esi = xc.esi;                            \
   30.94 -    pt.edi = xc.edi;                            \
   30.95 -    pt.ebp = xc.ebp;                            \
   30.96 -    pt.eax = xc.eax;                            \
   30.97 -    pt.eip = xc.eip;                            \
   30.98 -    pt.xcs = xc.cs;                             \
   30.99 -    pt.eflags = xc.eflags;                      \
  30.100 -    pt.esp = xc.esp;                            \
  30.101 -    pt.xss = xc.ss;                             \
  30.102 -    pt.xes = xc.es;                             \
  30.103 -    pt.xds = xc.ds;                             \
  30.104 -    pt.xfs = xc.fs;                             \
  30.105 -    pt.xgs = xc.gs;                             \
  30.106 +static cpumap_t                 online_cpumap;
  30.107 +static cpumap_t                 regs_valid;
  30.108 +static vcpu_guest_context_t     ctxt[MAX_VIRT_CPUS];
  30.109 +
  30.110 +extern int ffsll(long long int);
  30.111 +#define FOREACH_CPU(cpumap, i)  for ( cpumap = online_cpumap; (i = ffsll(cpumap)); cpumap &= ~(1 << (index - 1)) ) 
  30.112 +
  30.113 +
  30.114 +static int
  30.115 +fetch_regs(int xc_handle, int cpu, int *online)
  30.116 +{
  30.117 +    xc_vcpuinfo_t info;
  30.118 +    int retval = 0;
  30.119 +
  30.120 +    if (online)
  30.121 +        *online = 0;
  30.122 +    if ( !(regs_valid & (1 << cpu)) ) { 
  30.123 +        retval = xc_domain_get_vcpu_context(xc_handle, current_domid, 
  30.124 +						cpu, &ctxt[cpu]);
  30.125 +        if ( retval ) 
  30.126 +            goto done;
  30.127 +	regs_valid |= (1 << cpu);
  30.128 +
  30.129 +    }
  30.130 +	if ( online == NULL )
  30.131 +	    goto done;
  30.132 +
  30.133 +	retval = xc_domain_get_vcpu_info(xc_handle, current_domid,
  30.134 +					 cpu, &info);
  30.135 +	*online = info.online;
  30.136 +    
  30.137 + done:
  30.138 +    return retval;    
  30.139  }
  30.140  
  30.141 -#define SET_XC_REGS(pt, xc)                     \
  30.142 -{                                               \
  30.143 -    xc.ebx = pt->ebx;                           \
  30.144 -    xc.ecx = pt->ecx;                           \
  30.145 -    xc.edx = pt->edx;                           \
  30.146 -    xc.esi = pt->esi;                           \
  30.147 -    xc.edi = pt->edi;                           \
  30.148 -    xc.ebp = pt->ebp;                           \
  30.149 -    xc.eax = pt->eax;                           \
  30.150 -    xc.eip = pt->eip;                           \
  30.151 -    xc.cs = pt->xcs;                            \
  30.152 -    xc.eflags = pt->eflags;                     \
  30.153 -    xc.esp = pt->esp;                           \
  30.154 -    xc.ss = pt->xss;                            \
  30.155 -    xc.es = pt->xes;                            \
  30.156 -    xc.ds = pt->xds;                            \
  30.157 -    xc.fs = pt->xfs;                            \
  30.158 -    xc.gs = pt->xgs;                            \
  30.159 +#define FETCH_REGS(cpu) if (fetch_regs(xc_handle, cpu, NULL)) goto error_out;
  30.160 +
  30.161 +
  30.162 +static struct thr_ev_handlers {
  30.163 +    thr_ev_handler_t td_create;
  30.164 +    thr_ev_handler_t td_death;
  30.165 +} handlers;
  30.166 +
  30.167 +void 
  30.168 +xc_register_event_handler(thr_ev_handler_t h, 
  30.169 +                          td_event_e e)
  30.170 +{
  30.171 +    switch (e) {
  30.172 +    case TD_CREATE:
  30.173 +        handlers.td_create = h;
  30.174 +        break;
  30.175 +    case TD_DEATH:
  30.176 +        handlers.td_death = h;
  30.177 +        break;
  30.178 +    default:
  30.179 +        abort(); /* XXX */
  30.180 +    }
  30.181  }
  30.182  
  30.183 -#define vtopdi(va) ((va) >> PDRSHIFT)
  30.184 -#define vtopti(va) (((va) >> PAGE_SHIFT) & 0x3ff)
  30.185 -
  30.186 -/* XXX application state */
  30.187 -static long   nr_pages = 0;
  30.188 -unsigned long   *page_array = NULL;
  30.189 -static int                      regs_valid[MAX_VIRT_CPUS];
  30.190 -static unsigned long            cr3[MAX_VIRT_CPUS];
  30.191 -static vcpu_guest_context_t ctxt[MAX_VIRT_CPUS];
  30.192 -
  30.193 -static inline int paging_enabled(vcpu_guest_context_t *v)
  30.194 +static inline int 
  30.195 +paging_enabled(vcpu_guest_context_t *v)
  30.196  {
  30.197      unsigned long cr0 = v->ctrlreg[0];
  30.198      return (cr0 & X86_CR0_PE) && (cr0 & X86_CR0_PG);
  30.199  }
  30.200  
  30.201 +/*
  30.202 + * Fetch registers for all online cpus and set the cpumap
  30.203 + * to indicate which cpus are online
  30.204 + *
  30.205 + */
  30.206 +
  30.207 +static int
  30.208 +get_online_cpumap(int xc_handle, dom0_getdomaininfo_t *d, cpumap_t *cpumap)
  30.209 +{
  30.210 +    int i, online, retval;
  30.211 +    
  30.212 +    *cpumap = 0;
  30.213 +    for (i = 0; i <= d->max_vcpu_id; i++) {
  30.214 +        if ((retval = fetch_regs(xc_handle, i, &online)))
  30.215 +            goto error_out;        
  30.216 +        if (online)
  30.217 +            *cpumap |= (1 << i);            
  30.218 +    }
  30.219 +    
  30.220 +    return 0;
  30.221 + error_out:
  30.222 +    return retval;
  30.223 +}
  30.224 +
  30.225 +/* 
  30.226 + * Notify GDB of any vcpus that have come online or gone offline
  30.227 + * update online_cpumap
  30.228 + *
  30.229 + */
  30.230 +
  30.231 +static void
  30.232 +online_vcpus_changed(cpumap_t cpumap)
  30.233 +{
  30.234 +    cpumap_t changed_cpumap = cpumap ^ online_cpumap;
  30.235 +    int index;
  30.236 +    
  30.237 +    while ( (index = ffsll(changed_cpumap)) ) {
  30.238 +        if ( cpumap & (1 << (index - 1)) ) {
  30.239 +            if (handlers.td_create) handlers.td_create(index - 1);
  30.240 +        } else {
  30.241 +            printf("thread death: %d\n", index - 1);
  30.242 +            if (handlers.td_death) handlers.td_death(index - 1);
  30.243 +        }
  30.244 +        changed_cpumap &= ~(1 << (index - 1));
  30.245 +    }
  30.246 +    online_cpumap = cpumap;
  30.247 +    
  30.248 +}
  30.249 +
  30.250  /* --------------------- */
  30.251  
  30.252  static void *
  30.253  map_domain_va_pae(
  30.254      int xc_handle,
  30.255 -    unsigned long domid,
  30.256      int cpu,
  30.257      void *guest_va,
  30.258      int perm)
  30.259 @@ -144,24 +147,24 @@ map_domain_va_pae(
  30.260      FETCH_REGS(cpu);
  30.261  
  30.262      l3 = xc_map_foreign_range(
  30.263 -        xc_handle, domid, PAGE_SIZE, PROT_READ, cr3[cpu] >> PAGE_SHIFT);
  30.264 +        xc_handle, current_domid, PAGE_SIZE, PROT_READ, ctxt[cpu].ctrlreg[3] >> PAGE_SHIFT);
  30.265      if ( l3 == NULL )
  30.266          goto error_out;
  30.267  
  30.268      l2p = l3[l3_table_offset_pae(va)] >> PAGE_SHIFT;
  30.269 -    l2 = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE, PROT_READ, l2p);
  30.270 +    l2 = xc_map_foreign_range(xc_handle, current_domid, PAGE_SIZE, PROT_READ, l2p);
  30.271      if ( l2 == NULL )
  30.272          goto error_out;
  30.273  
  30.274      l1p = l2[l2_table_offset_pae(va)] >> PAGE_SHIFT;
  30.275 -    l1 = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE, perm, l1p);
  30.276 +    l1 = xc_map_foreign_range(xc_handle, current_domid, PAGE_SIZE, perm, l1p);
  30.277      if ( l1 == NULL )
  30.278          goto error_out;
  30.279  
  30.280      p = l1[l1_table_offset_pae(va)] >> PAGE_SHIFT;
  30.281      if ( v != NULL )
  30.282          munmap(v, PAGE_SIZE);
  30.283 -    v = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE, perm, p);
  30.284 +    v = xc_map_foreign_range(xc_handle, current_domid, PAGE_SIZE, perm, p);
  30.285      if ( v == NULL )
  30.286          goto error_out;
  30.287  
  30.288 @@ -174,16 +177,17 @@ map_domain_va_pae(
  30.289  static void *
  30.290  map_domain_va(
  30.291      int xc_handle,
  30.292 -    unsigned long domid,
  30.293      int cpu,
  30.294      void *guest_va,
  30.295      int perm)
  30.296  {
  30.297 +
  30.298      unsigned long pde, page;
  30.299      unsigned long va = (unsigned long)guest_va;
  30.300 -    long npgs = xc_get_tot_pages(xc_handle, domid);
  30.301 +    long npgs = xc_get_tot_pages(xc_handle, current_domid);
  30.302  
  30.303 -    static unsigned long  cr3_phys[MAX_VIRT_CPUS];
  30.304 +
  30.305 +    static uint32_t  cr3_phys[MAX_VIRT_CPUS];
  30.306      static unsigned long *cr3_virt[MAX_VIRT_CPUS];
  30.307      static unsigned long  pde_phys[MAX_VIRT_CPUS];
  30.308      static unsigned long *pde_virt[MAX_VIRT_CPUS];
  30.309 @@ -202,7 +206,7 @@ map_domain_va(
  30.310      }
  30.311  
  30.312      if ( mode == MODE_PAE )
  30.313 -        return map_domain_va_pae(xc_handle, domid, cpu, guest_va, perm);
  30.314 +        return map_domain_va_pae(xc_handle, cpu, guest_va, perm);
  30.315  
  30.316      if ( nr_pages != npgs )
  30.317      {
  30.318 @@ -214,7 +218,7 @@ map_domain_va(
  30.319              printf("Could not allocate memory\n");
  30.320              goto error_out;
  30.321          }
  30.322 -        if ( xc_get_pfn_list(xc_handle, domid,
  30.323 +        if ( xc_get_pfn_list(xc_handle, current_domid,
  30.324                               page_array, nr_pages) != nr_pages )
  30.325          {
  30.326              printf("Could not get the page frame list\n");
  30.327 @@ -224,13 +228,13 @@ map_domain_va(
  30.328  
  30.329      FETCH_REGS(cpu);
  30.330  
  30.331 -    if ( cr3[cpu] != cr3_phys[cpu] )
  30.332 +    if ( ctxt[cpu].ctrlreg[3] != cr3_phys[cpu] )
  30.333      {
  30.334 -        cr3_phys[cpu] = cr3[cpu];
  30.335 +        cr3_phys[cpu] = ctxt[cpu].ctrlreg[3];
  30.336          if ( cr3_virt[cpu] )
  30.337              munmap(cr3_virt[cpu], PAGE_SIZE);
  30.338          cr3_virt[cpu] = xc_map_foreign_range(
  30.339 -            xc_handle, domid, PAGE_SIZE, PROT_READ,
  30.340 +            xc_handle, current_domid, PAGE_SIZE, PROT_READ,
  30.341              cr3_phys[cpu] >> PAGE_SHIFT);
  30.342          if ( cr3_virt[cpu] == NULL )
  30.343              goto error_out;
  30.344 @@ -245,7 +249,7 @@ map_domain_va(
  30.345          if ( pde_virt[cpu] )
  30.346              munmap(pde_virt[cpu], PAGE_SIZE);
  30.347          pde_virt[cpu] = xc_map_foreign_range(
  30.348 -            xc_handle, domid, PAGE_SIZE, PROT_READ,
  30.349 +            xc_handle, current_domid, PAGE_SIZE, PROT_READ,
  30.350              pde_phys[cpu] >> PAGE_SHIFT);
  30.351          if ( pde_virt[cpu] == NULL )
  30.352              goto error_out;
  30.353 @@ -260,7 +264,7 @@ map_domain_va(
  30.354          if ( page_virt[cpu] )
  30.355              munmap(page_virt[cpu], PAGE_SIZE);
  30.356          page_virt[cpu] = xc_map_foreign_range(
  30.357 -            xc_handle, domid, PAGE_SIZE, perm,
  30.358 +            xc_handle, current_domid, PAGE_SIZE, perm,
  30.359              page_phys[cpu] >> PAGE_SHIFT);
  30.360          if ( page_virt[cpu] == NULL )
  30.361          {
  30.362 @@ -286,12 +290,15 @@ xc_waitdomain(
  30.363      DECLARE_DOM0_OP;
  30.364      int retval;
  30.365      struct timespec ts;
  30.366 +    cpumap_t cpumap;
  30.367 +
  30.368      ts.tv_sec = 0;
  30.369      ts.tv_nsec = 10*1000*1000;
  30.370  
  30.371      op.cmd = DOM0_GETDOMAININFO;
  30.372      op.u.getdomaininfo.domain = domain;
  30.373 -
  30.374 +    
  30.375 +    
  30.376   retry:
  30.377      retval = do_dom0_op(xc_handle, &op);
  30.378      if ( retval || (op.u.getdomaininfo.domain != domain) )
  30.379 @@ -309,17 +316,22 @@ xc_waitdomain(
  30.380          nanosleep(&ts,NULL);
  30.381          goto retry;
  30.382      }
  30.383 -
  30.384 +    /* XXX check for ^C here */
  30.385   done:
  30.386 +    if (get_online_cpumap(xc_handle, &op.u.getdomaininfo, &cpumap))
  30.387 +        printf("get_online_cpumap failed\n");
  30.388 +    if (online_cpumap != cpumap)
  30.389 +        online_vcpus_changed(cpumap);
  30.390      return retval;
  30.391  
  30.392  }
  30.393  
  30.394 +
  30.395  long
  30.396  xc_ptrace(
  30.397      int xc_handle,
  30.398      enum __ptrace_request request,
  30.399 -    uint32_t domid,
  30.400 +    uint32_t domid_tid,
  30.401      long eaddr,
  30.402      long edata)
  30.403  {
  30.404 @@ -328,18 +340,19 @@ xc_ptrace(
  30.405      struct gdb_regs pt;
  30.406      long            retval = 0;
  30.407      unsigned long  *guest_va;
  30.408 -    int             cpu = VCPU;
  30.409 +    cpumap_t        cpumap;
  30.410 +    int             cpu, index;
  30.411      void           *addr = (char *)eaddr;
  30.412      void           *data = (char *)edata;
  30.413  
  30.414 -    op.interface_version = DOM0_INTERFACE_VERSION;
  30.415 +    cpu = (request != PTRACE_ATTACH) ? domid_tid : 0;
  30.416      
  30.417      switch ( request )
  30.418      { 
  30.419      case PTRACE_PEEKTEXT:
  30.420      case PTRACE_PEEKDATA:
  30.421          guest_va = (unsigned long *)map_domain_va(
  30.422 -            xc_handle, domid, cpu, addr, PROT_READ);
  30.423 +            xc_handle, cpu, addr, PROT_READ);
  30.424          if ( guest_va == NULL )
  30.425          {
  30.426              status = EFAULT;
  30.427 @@ -350,10 +363,10 @@ xc_ptrace(
  30.428  
  30.429      case PTRACE_POKETEXT:
  30.430      case PTRACE_POKEDATA:
  30.431 +        /* XXX assume that all CPUs have the same address space */
  30.432          guest_va = (unsigned long *)map_domain_va(
  30.433 -            xc_handle, domid, cpu, addr, PROT_READ|PROT_WRITE);
  30.434 -        if ( guest_va == NULL )
  30.435 -        {
  30.436 +                            xc_handle, cpu, addr, PROT_READ|PROT_WRITE);
  30.437 +        if ( guest_va == NULL ) {
  30.438              status = EFAULT;
  30.439              goto error_out;
  30.440          }
  30.441 @@ -363,6 +376,7 @@ xc_ptrace(
  30.442      case PTRACE_GETREGS:
  30.443      case PTRACE_GETFPREGS:
  30.444      case PTRACE_GETFPXREGS:
  30.445 +        
  30.446          FETCH_REGS(cpu);
  30.447          if ( request == PTRACE_GETREGS )
  30.448          {
  30.449 @@ -380,44 +394,18 @@ xc_ptrace(
  30.450          break;
  30.451  
  30.452      case PTRACE_SETREGS:
  30.453 -        op.cmd = DOM0_SETDOMAININFO;
  30.454 -        SET_XC_REGS(((struct gdb_regs *)data), ctxt[VCPU].user_regs);
  30.455 -        op.u.setdomaininfo.domain = domid;
  30.456 -        /* XXX need to understand multiple vcpus */
  30.457 -        op.u.setdomaininfo.vcpu = cpu;
  30.458 -        op.u.setdomaininfo.ctxt = &ctxt[cpu];
  30.459 -        retval = do_dom0_op(xc_handle, &op);
  30.460 +        SET_XC_REGS(((struct gdb_regs *)data), ctxt[cpu].user_regs);
  30.461 +        retval = xc_domain_setinfo(xc_handle, current_domid, cpu, &ctxt[cpu]);
  30.462          if (retval)
  30.463              goto error_out;
  30.464          break;
  30.465  
  30.466 -    case PTRACE_ATTACH:
  30.467 -        op.cmd = DOM0_GETDOMAININFO;
  30.468 -        op.u.getdomaininfo.domain = domid;
  30.469 -        retval = do_dom0_op(xc_handle, &op);
  30.470 -        if ( retval || (op.u.getdomaininfo.domain != domid) )
  30.471 -        {
  30.472 -            perror("dom0 op failed");
  30.473 -            goto error_out;
  30.474 -        }
  30.475 -        if ( op.u.getdomaininfo.flags & DOMFLAGS_PAUSED )
  30.476 -        {
  30.477 -            printf("domain currently paused\n");
  30.478 -            goto error_out;
  30.479 -        }
  30.480 -        printf("domain not currently paused\n");
  30.481 -        op.cmd = DOM0_PAUSEDOMAIN;
  30.482 -        op.u.pausedomain.domain = domid;
  30.483 -        retval = do_dom0_op(xc_handle, &op);
  30.484 -        break;
  30.485 -
  30.486      case PTRACE_SINGLESTEP:
  30.487 -        ctxt[VCPU].user_regs.eflags |= PSL_T;
  30.488 -        op.cmd = DOM0_SETDOMAININFO;
  30.489 -        op.u.setdomaininfo.domain = domid;
  30.490 -        op.u.setdomaininfo.vcpu = 0;
  30.491 -        op.u.setdomaininfo.ctxt = &ctxt[cpu];
  30.492 -        retval = do_dom0_op(xc_handle, &op); 
  30.493 +        /*  XXX we can still have problems if the user switches threads
  30.494 +         *  during single-stepping - but that just seems retarded
  30.495 +         */
  30.496 +        ctxt[cpu].user_regs.eflags |= PSL_T; 
  30.497 +        retval = xc_domain_setinfo(xc_handle, current_domid, cpu, &ctxt[cpu]);
  30.498          if ( retval )
  30.499          {
  30.500              perror("dom0 op failed");
  30.501 @@ -429,27 +417,56 @@ xc_ptrace(
  30.502      case PTRACE_DETACH:
  30.503          if ( request != PTRACE_SINGLESTEP )
  30.504          {
  30.505 -            FETCH_REGS(cpu);
  30.506 -            /* Clear trace flag */
  30.507 -            if ( ctxt[cpu].user_regs.eflags & PSL_T )
  30.508 -            {
  30.509 -                ctxt[cpu].user_regs.eflags &= ~PSL_T;
  30.510 -                op.cmd = DOM0_SETDOMAININFO;
  30.511 -                op.u.setdomaininfo.domain = domid;
  30.512 -                op.u.setdomaininfo.vcpu = cpu;
  30.513 -                op.u.setdomaininfo.ctxt = &ctxt[cpu];
  30.514 -                retval = do_dom0_op(xc_handle, &op); 
  30.515 -                if ( retval )
  30.516 -                {
  30.517 -                    perror("dom0 op failed");
  30.518 -                    goto error_out;
  30.519 +            FOREACH_CPU(cpumap, index) {
  30.520 +                cpu = index - 1;
  30.521 +                FETCH_REGS(cpu);
  30.522 +                /* Clear trace flag */
  30.523 +                if ( ctxt[cpu].user_regs.eflags & PSL_T ) {
  30.524 +                    ctxt[cpu].user_regs.eflags &= ~PSL_T;
  30.525 +                    retval = xc_domain_setinfo(xc_handle, current_domid, 
  30.526 +                                               cpu, &ctxt[cpu]);
  30.527 +                    if ( retval ) {
  30.528 +                        perror("dom0 op failed");
  30.529 +                        goto error_out;
  30.530 +                    }
  30.531                  }
  30.532              }
  30.533          }
  30.534 -        regs_valid[cpu] = 0;
  30.535 -        op.cmd = DOM0_UNPAUSEDOMAIN;
  30.536 -        op.u.unpausedomain.domain = domid > 0 ? domid : -domid;
  30.537 +        if ( request == PTRACE_DETACH )
  30.538 +        {
  30.539 +            op.cmd = DOM0_SETDEBUGGING;
  30.540 +            op.u.setdebugging.domain = current_domid;
  30.541 +            op.u.setdebugging.enable = 0;
  30.542 +            retval = do_dom0_op(xc_handle, &op);
  30.543 +        }
  30.544 +        regs_valid = 0;
  30.545 +        xc_domain_unpause(xc_handle, current_domid > 0 ? current_domid : -current_domid);
  30.546 +        break;
  30.547 +
  30.548 +    case PTRACE_ATTACH:
  30.549 +        current_domid = domid_tid;
  30.550 +        op.cmd = DOM0_GETDOMAININFO;
  30.551 +        op.u.getdomaininfo.domain = current_domid;
  30.552          retval = do_dom0_op(xc_handle, &op);
  30.553 +        if ( retval || (op.u.getdomaininfo.domain != current_domid) )
  30.554 +        {
  30.555 +            perror("dom0 op failed");
  30.556 +            goto error_out;
  30.557 +        }
  30.558 +        if ( op.u.getdomaininfo.flags & DOMFLAGS_PAUSED )
  30.559 +        {
  30.560 +            printf("domain currently paused\n");
  30.561 +        } else
  30.562 +            retval = xc_domain_pause(xc_handle, current_domid);
  30.563 +        op.cmd = DOM0_SETDEBUGGING;
  30.564 +        op.u.setdebugging.domain = current_domid;
  30.565 +        op.u.setdebugging.enable = 1;
  30.566 +        retval = do_dom0_op(xc_handle, &op);
  30.567 +
  30.568 +        if (get_online_cpumap(xc_handle, &op.u.getdomaininfo, &cpumap))
  30.569 +            printf("get_online_cpumap failed\n");
  30.570 +        if (online_cpumap != cpumap)
  30.571 +            online_vcpus_changed(cpumap);
  30.572          break;
  30.573  
  30.574      case PTRACE_SETFPREGS:
    31.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    31.2 +++ b/tools/libxc/xc_ptrace.h	Tue Dec 20 17:16:24 2005 +0000
    31.3 @@ -0,0 +1,124 @@
    31.4 +#ifndef XC_PTRACE_
    31.5 +#define XC_PTRACE_
    31.6 +
    31.7 +#ifdef XC_PTRACE_PRIVATE
    31.8 +#define X86_CR0_PE              0x00000001 /* Enable Protected Mode    (RW) */
    31.9 +#define X86_CR0_PG              0x80000000 /* Paging                   (RW) */
   31.10 +#define BSD_PAGE_MASK (PAGE_SIZE-1)
   31.11 +#define PDRSHIFT        22
   31.12 +#define PSL_T  0x00000100 /* trace enable bit */
   31.13 +
   31.14 +char * ptrace_names[] = {
   31.15 +    "PTRACE_TRACEME",
   31.16 +    "PTRACE_PEEKTEXT",
   31.17 +    "PTRACE_PEEKDATA",
   31.18 +    "PTRACE_PEEKUSER",
   31.19 +    "PTRACE_POKETEXT",
   31.20 +    "PTRACE_POKEDATA",
   31.21 +    "PTRACE_POKEUSER",
   31.22 +    "PTRACE_CONT",
   31.23 +    "PTRACE_KILL",
   31.24 +    "PTRACE_SINGLESTEP",
   31.25 +    "PTRACE_INVALID",
   31.26 +    "PTRACE_INVALID",
   31.27 +    "PTRACE_GETREGS",
   31.28 +    "PTRACE_SETREGS",
   31.29 +    "PTRACE_GETFPREGS",
   31.30 +    "PTRACE_SETFPREGS",
   31.31 +    "PTRACE_ATTACH",
   31.32 +    "PTRACE_DETACH",
   31.33 +    "PTRACE_GETFPXREGS",
   31.34 +    "PTRACE_SETFPXREGS",
   31.35 +    "PTRACE_INVALID",
   31.36 +    "PTRACE_INVALID",
   31.37 +    "PTRACE_INVALID",
   31.38 +    "PTRACE_INVALID",
   31.39 +    "PTRACE_SYSCALL",
   31.40 +};
   31.41 +
   31.42 +struct gdb_regs {
   31.43 +    long ebx; /* 0 */
   31.44 +    long ecx; /* 4 */
   31.45 +    long edx; /* 8 */
   31.46 +    long esi; /* 12 */
   31.47 +    long edi; /* 16 */
   31.48 +    long ebp; /* 20 */
   31.49 +    long eax; /* 24 */ 
   31.50 +    int  xds; /* 28 */
   31.51 +    int  xes; /* 32 */
   31.52 +    int  xfs; /* 36 */
   31.53 +    int  xgs; /* 40 */
   31.54 +    long orig_eax; /* 44 */
   31.55 +    long eip;    /* 48 */
   31.56 +    int  xcs;    /* 52 */
   31.57 +    long eflags; /* 56 */
   31.58 +    long esp;    /* 60 */     
   31.59 +    int  xss;    /* 64 */
   31.60 +};
   31.61 +
   31.62 +
   31.63 +#define printval(x) printf("%s = %lx\n", #x, (long)x);
   31.64 +#define SET_PT_REGS(pt, xc)                     \
   31.65 +{                                               \
   31.66 +    pt.ebx = xc.ebx;                            \
   31.67 +    pt.ecx = xc.ecx;                            \
   31.68 +    pt.edx = xc.edx;                            \
   31.69 +    pt.esi = xc.esi;                            \
   31.70 +    pt.edi = xc.edi;                            \
   31.71 +    pt.ebp = xc.ebp;                            \
   31.72 +    pt.eax = xc.eax;                            \
   31.73 +    pt.eip = xc.eip;                            \
   31.74 +    pt.xcs = xc.cs;                             \
   31.75 +    pt.eflags = xc.eflags;                      \
   31.76 +    pt.esp = xc.esp;                            \
   31.77 +    pt.xss = xc.ss;                             \
   31.78 +    pt.xes = xc.es;                             \
   31.79 +    pt.xds = xc.ds;                             \
   31.80 +    pt.xfs = xc.fs;                             \
   31.81 +    pt.xgs = xc.gs;                             \
   31.82 +}
   31.83 +
   31.84 +#define SET_XC_REGS(pt, xc)                     \
   31.85 +{                                               \
   31.86 +    xc.ebx = pt->ebx;                           \
   31.87 +    xc.ecx = pt->ecx;                           \
   31.88 +    xc.edx = pt->edx;                           \
   31.89 +    xc.esi = pt->esi;                           \
   31.90 +    xc.edi = pt->edi;                           \
   31.91 +    xc.ebp = pt->ebp;                           \
   31.92 +    xc.eax = pt->eax;                           \
   31.93 +    xc.eip = pt->eip;                           \
   31.94 +    xc.cs = pt->xcs;                            \
   31.95 +    xc.eflags = pt->eflags;                     \
   31.96 +    xc.esp = pt->esp;                           \
   31.97 +    xc.ss = pt->xss;                            \
   31.98 +    xc.es = pt->xes;                            \
   31.99 +    xc.ds = pt->xds;                            \
  31.100 +    xc.fs = pt->xfs;                            \
  31.101 +    xc.gs = pt->xgs;                            \
  31.102 +}
  31.103 +
  31.104 +#define vtopdi(va) ((va) >> PDRSHIFT)
  31.105 +#define vtopti(va) (((va) >> PAGE_SHIFT) & 0x3ff)
  31.106 +#endif
  31.107 +
  31.108 +typedef void (*thr_ev_handler_t)(long);
  31.109 +
  31.110 +void xc_register_event_handler(
  31.111 +    thr_ev_handler_t h, 
  31.112 +    td_event_e e);
  31.113 +
  31.114 +long xc_ptrace(
  31.115 +    int xc_handle,
  31.116 +    enum __ptrace_request request, 
  31.117 +    uint32_t  domid,
  31.118 +    long addr, 
  31.119 +    long data);
  31.120 +
  31.121 +int xc_waitdomain(
  31.122 +    int xc_handle,
  31.123 +    int domain, 
  31.124 +    int *status, 
  31.125 +    int options);
  31.126 +
  31.127 +#endif /* XC_PTRACE */
    32.1 --- a/tools/libxc/xc_vmx_build.c	Tue Dec 20 17:16:15 2005 +0000
    32.2 +++ b/tools/libxc/xc_vmx_build.c	Tue Dec 20 17:16:24 2005 +0000
    32.3 @@ -288,11 +288,11 @@ static int setup_guest(int xc_handle,
    32.4      l2_pgentry_t *vl2tab=NULL, *vl2e=NULL;
    32.5      unsigned long *page_array = NULL;
    32.6  #ifdef __x86_64__
    32.7 -    l3_pgentry_t *vl3tab=NULL, *vl3e=NULL;
    32.8 +    l3_pgentry_t *vl3tab=NULL;
    32.9      unsigned long l3tab;
   32.10  #endif
   32.11 -    unsigned long l2tab;
   32.12 -    unsigned long l1tab;
   32.13 +    unsigned long l2tab = 0;
   32.14 +    unsigned long l1tab = 0;
   32.15      unsigned long count, i;
   32.16      shared_info_t *shared_info;
   32.17      void *e820_page;
   32.18 @@ -323,7 +323,7 @@ static int setup_guest(int xc_handle,
   32.19      }
   32.20  
   32.21      /* memsize is in megabytes */
   32.22 -    v_end              = memsize << 20;
   32.23 +    v_end              = (unsigned long)memsize << 20;
   32.24  
   32.25  #ifdef __i386__
   32.26      nr_pt_pages = 1 + ((memsize + 3) >> 2);
   32.27 @@ -435,15 +435,16 @@ static int setup_guest(int xc_handle,
   32.28              goto error_out;
   32.29          memset(vl2tab, 0, PAGE_SIZE);
   32.30          munmap(vl2tab, PAGE_SIZE);
   32.31 +        vl2tab = NULL;
   32.32          vl3tab[i] = l2tab | L3_PROT;
   32.33      }
   32.34  
   32.35 -    vl3e = &vl3tab[l3_table_offset(0)];
   32.36      for ( count = 0; count < (v_end >> PAGE_SHIFT); count++ )
   32.37      {
   32.38 -        if (!(count & (1 << (L3_PAGETABLE_SHIFT - L1_PAGETABLE_SHIFT)))){
   32.39 +        if ( !(count & ((1 << (L3_PAGETABLE_SHIFT - L1_PAGETABLE_SHIFT)) - 1)) )
   32.40 +        {
   32.41              l2tab = vl3tab[count >> (L3_PAGETABLE_SHIFT - L1_PAGETABLE_SHIFT)]
   32.42 -                & PAGE_MASK;
   32.43 +                    & PAGE_MASK;
   32.44  
   32.45              if (vl2tab != NULL)
   32.46                  munmap(vl2tab, PAGE_SIZE);
    33.1 --- a/tools/libxc/xenctrl.h	Tue Dec 20 17:16:15 2005 +0000
    33.2 +++ b/tools/libxc/xenctrl.h	Tue Dec 20 17:16:24 2005 +0000
    33.3 @@ -94,13 +94,6 @@ typedef struct xc_core_header {
    33.4  } xc_core_header_t;
    33.5  
    33.6  
    33.7 -long xc_ptrace(
    33.8 -    int xc_handle,
    33.9 -    enum __ptrace_request request, 
   33.10 -    uint32_t  domid,
   33.11 -    long addr, 
   33.12 -    long data);
   33.13 -
   33.14  long xc_ptrace_core(
   33.15      int xc_handle,
   33.16      enum __ptrace_request request, 
   33.17 @@ -108,12 +101,6 @@ long xc_ptrace_core(
   33.18      long addr, 
   33.19      long data);
   33.20  
   33.21 -int xc_waitdomain(
   33.22 -    int xc_handle,
   33.23 -    int domain, 
   33.24 -    int *status, 
   33.25 -    int options);
   33.26 -
   33.27  int xc_waitdomain_core(
   33.28      int xc_handle,
   33.29      int domain, 
   33.30 @@ -219,6 +206,20 @@ int xc_domain_getinfo(int xc_handle,
   33.31                        unsigned int max_doms,
   33.32                        xc_dominfo_t *info);
   33.33  
   33.34 +
   33.35 +/**
   33.36 + * This function will set the vcpu context for the specified domain.
   33.37 + *
   33.38 + * @parm xc_handle a handle to an open hypervisor interface
   33.39 + * @parm domid the domain to set the vcpu context for
   33.40 + * @parm vcpu the vcpu number for the context
   33.41 + * @parm ctxt pointer to the the cpu context with the values to set
   33.42 + * @return the number of domains enumerated or -1 on error
   33.43 + */
   33.44 +int xc_domain_setinfo(int xc_handle,
   33.45 +                      uint32_t domid,
   33.46 +                      uint32_t vcpu,
   33.47 +                      vcpu_guest_context_t *ctxt);
   33.48  /**
   33.49   * This function will return information about one or more domains, using a
   33.50   * single hypercall.  The domain information will be stored into the supplied
    34.1 --- a/tools/python/xen/xend/image.py	Tue Dec 20 17:16:15 2005 +0000
    34.2 +++ b/tools/python/xen/xend/image.py	Tue Dec 20 17:16:24 2005 +0000
    34.3 @@ -237,7 +237,7 @@ class VmxImageHandler(ImageHandler):
    34.4      # Return a list of cmd line args to the device models based on the
    34.5      # xm config file
    34.6      def parseDeviceModelArgs(self, imageConfig, deviceConfig):
    34.7 -        dmargs = [ 'cdrom', 'boot', 'fda', 'fdb', 'ne2000', 
    34.8 +        dmargs = [ 'cdrom', 'boot', 'fda', 'fdb', 'ne2000', 'audio',
    34.9                     'localtime', 'serial', 'stdvga', 'isa', 'vcpus']
   34.10          ret = []
   34.11          for a in dmargs:
   34.12 @@ -246,9 +246,10 @@ class VmxImageHandler(ImageHandler):
   34.13              # python doesn't allow '-' in variable names
   34.14              if a == 'stdvga': a = 'std-vga'
   34.15              if a == 'ne2000': a = 'nic-ne2000'
   34.16 +            if a == 'audio': a = 'enable-audio'
   34.17  
   34.18              # Handle booleans gracefully
   34.19 -            if a in ['localtime', 'std-vga', 'isa', 'nic-ne2000']:
   34.20 +            if a in ['localtime', 'std-vga', 'isa', 'nic-ne2000', 'enable-audio']:
   34.21                  if v != None: v = int(v)
   34.22                  if v: ret.append("-%s" % a)
   34.23              else:
    35.1 --- a/tools/python/xen/xm/create.py	Tue Dec 20 17:16:15 2005 +0000
    35.2 +++ b/tools/python/xen/xm/create.py	Tue Dec 20 17:16:24 2005 +0000
    35.3 @@ -372,6 +372,10 @@ gopts.var('ne2000', val='no|yes',
    35.4            fn=set_bool, default=0,
    35.5            use="Should device models use ne2000?")
    35.6  
    35.7 +gopts.var('audio', val='no|yes',
    35.8 +          fn=set_bool, default=0,
    35.9 +          use="Should device models enable audio?")
   35.10 +
   35.11  gopts.var('vnc', val='',
   35.12            fn=set_value, default=None,
   35.13            use="""Should the device model use VNC?""")
   35.14 @@ -521,7 +525,7 @@ def configure_vmx(config_image, vals):
   35.15      """Create the config for VMX devices.
   35.16      """
   35.17      args = [ 'device_model', 'vcpus', 'cdrom', 'boot', 'fda', 'fdb',
   35.18 -             'localtime', 'serial', 'stdvga', 'isa', 'nographic',
   35.19 +             'localtime', 'serial', 'stdvga', 'isa', 'nographic', 'audio',
   35.20               'vnc', 'vncviewer', 'sdl', 'display', 'ne2000', 'lapic']
   35.21      for a in args:
   35.22          if (vals.__dict__[a]):
    36.1 --- a/tools/vtpm_manager/manager/securestorage.c	Tue Dec 20 17:16:15 2005 +0000
    36.2 +++ b/tools/vtpm_manager/manager/securestorage.c	Tue Dec 20 17:16:24 2005 +0000
    36.3 @@ -54,31 +54,28 @@
    36.4  #include "buffer.h"
    36.5  #include "log.h"
    36.6  
    36.7 -TPM_RESULT VTPM_Handle_Save_NVM(VTPM_DMI_RESOURCE *myDMI, 
    36.8 -				const buffer_t *inbuf, 
    36.9 -				buffer_t *outbuf) {
   36.10 -  
   36.11 +TPM_RESULT envelope_encrypt(const buffer_t     *inbuf,
   36.12 +                            CRYPTO_INFO  *asymkey,
   36.13 +                            buffer_t           *sealed_data) {
   36.14    TPM_RESULT status = TPM_SUCCESS;
   36.15    symkey_t    symkey;
   36.16 -  buffer_t    state_cipher = NULL_BUF,
   36.17 +  buffer_t    data_cipher = NULL_BUF,
   36.18                symkey_cipher = NULL_BUF;
   36.19 -  int fh;
   36.20 -  long bytes_written;
   36.21 -  BYTE *sealed_NVM=NULL;
   36.22 -  UINT32 sealed_NVM_size, i;
   36.23 -  struct pack_constbuf_t symkey_cipher32, state_cipher32;
   36.24    
   36.25 -  vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Save_NVMing[%d]: 0x", buffer_len(inbuf));
   36.26 +  UINT32 i;
   36.27 +  struct pack_constbuf_t symkey_cipher32, data_cipher32;
   36.28 +  
   36.29 +  vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Enveloping[%d]: 0x", buffer_len(inbuf));
   36.30    for (i=0; i< buffer_len(inbuf); i++)
   36.31      vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", inbuf->bytes[i]);
   36.32    vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
   36.33    
   36.34    // Generate a sym key and encrypt state with it
   36.35    TPMTRY(TPM_ENCRYPT_ERROR, Crypto_symcrypto_genkey (&symkey) );
   36.36 -  TPMTRY(TPM_ENCRYPT_ERROR, Crypto_symcrypto_encrypt (&symkey, inbuf, &state_cipher) );
   36.37 +  TPMTRY(TPM_ENCRYPT_ERROR, Crypto_symcrypto_encrypt (&symkey, inbuf, &data_cipher) );
   36.38    
   36.39    // Encrypt symmetric key
   36.40 -  TPMTRYRETURN( VTSP_Bind(    &vtpm_globals->storageKey, 
   36.41 +  TPMTRYRETURN( VTSP_Bind(    asymkey, 
   36.42  			      &symkey.key, 
   36.43  			      &symkey_cipher) );
   36.44    
   36.45 @@ -87,15 +84,108 @@ TPM_RESULT VTPM_Handle_Save_NVM(VTPM_DMI
   36.46    symkey_cipher32.size = buffer_len(&symkey_cipher);
   36.47    symkey_cipher32.data = symkey_cipher.bytes;
   36.48    
   36.49 -  state_cipher32.size = buffer_len(&state_cipher);
   36.50 -  state_cipher32.data = state_cipher.bytes;
   36.51 +  data_cipher32.size = buffer_len(&data_cipher);
   36.52 +  data_cipher32.data = data_cipher.bytes;
   36.53    
   36.54 -  sealed_NVM = (BYTE *) malloc( 2 * sizeof(UINT32) + symkey_cipher32.size + state_cipher32.size);
   36.55 +  TPMTRYRETURN( buffer_init(sealed_data, 2 * sizeof(UINT32) + symkey_cipher32.size + data_cipher32.size, NULL));
   36.56    
   36.57 -  sealed_NVM_size = BSG_PackList(sealed_NVM, 2,
   36.58 -				 BSG_TPM_SIZE32_DATA, &symkey_cipher32,
   36.59 -				 BSG_TPM_SIZE32_DATA, &state_cipher32);
   36.60 +  BSG_PackList(sealed_data->bytes, 2,
   36.61 +	       BSG_TPM_SIZE32_DATA, &symkey_cipher32,
   36.62 +	       BSG_TPM_SIZE32_DATA, &data_cipher32);
   36.63 +
   36.64 +  vtpmloginfo(VTPM_LOG_VTPM, "Saved %d bytes of E(symkey) + %d bytes of E(data)\n", buffer_len(&symkey_cipher), buffer_len(&data_cipher));
   36.65 +  goto egress;
   36.66 +
   36.67 + abort_egress:
   36.68 +  vtpmlogerror(VTPM_LOG_VTPM, "Failed to envelope encrypt\n.");
   36.69    
   36.70 + egress:
   36.71 +  
   36.72 +  buffer_free ( &data_cipher);
   36.73 +  buffer_free ( &symkey_cipher);
   36.74 +  Crypto_symcrypto_freekey (&symkey);
   36.75 +  
   36.76 +  return status;
   36.77 +}
   36.78 +
   36.79 +TPM_RESULT envelope_decrypt(const long         cipher_size,
   36.80 +                            const BYTE         *cipher,
   36.81 +                            TCS_CONTEXT_HANDLE TCSContext,
   36.82 +			    TPM_HANDLE         keyHandle,
   36.83 +			    const TPM_AUTHDATA *key_usage_auth,
   36.84 +                            buffer_t           *unsealed_data) {
   36.85 +
   36.86 +  TPM_RESULT status = TPM_SUCCESS;
   36.87 +  symkey_t    symkey;
   36.88 +  buffer_t    data_cipher = NULL_BUF, 
   36.89 +              symkey_clear = NULL_BUF, 
   36.90 +              symkey_cipher = NULL_BUF;
   36.91 +  struct pack_buf_t symkey_cipher32, data_cipher32;
   36.92 +  int i;
   36.93 +
   36.94 +  memset(&symkey, 0, sizeof(symkey_t));
   36.95 +
   36.96 +  vtpmloginfo(VTPM_LOG_VTPM_DEEP, "envelope decrypting[%ld]: 0x", cipher_size);
   36.97 +  for (i=0; i< cipher_size; i++)
   36.98 +    vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", cipher[i]);
   36.99 +  vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
  36.100 +  
  36.101 +  BSG_UnpackList(cipher, 2,
  36.102 +		 BSG_TPM_SIZE32_DATA, &symkey_cipher32,
  36.103 +		 BSG_TPM_SIZE32_DATA, &data_cipher32);
  36.104 +  
  36.105 +  TPMTRYRETURN( buffer_init_convert (&symkey_cipher, 
  36.106 +				     symkey_cipher32.size, 
  36.107 +				     symkey_cipher32.data) );
  36.108 +  
  36.109 +  TPMTRYRETURN( buffer_init_convert (&data_cipher, 
  36.110 +				     data_cipher32.size, 
  36.111 +				     data_cipher32.data) );
  36.112 +
  36.113 +  // Decrypt Symmetric Key
  36.114 +  TPMTRYRETURN( VTSP_Unbind(  TCSContext,
  36.115 +			      keyHandle,
  36.116 +			      &symkey_cipher,
  36.117 +			      key_usage_auth,
  36.118 +			      &symkey_clear,
  36.119 +			      &(vtpm_globals->keyAuth) ) );
  36.120 +  
  36.121 +  // create symmetric key using saved bits
  36.122 +  Crypto_symcrypto_initkey (&symkey, &symkey_clear);
  36.123 +  
  36.124 +  // Decrypt State
  36.125 +  TPMTRY(TPM_DECRYPT_ERROR, Crypto_symcrypto_decrypt (&symkey, &data_cipher, unsealed_data) );
  36.126 +  
  36.127 +  goto egress;
  36.128 +  
  36.129 + abort_egress:
  36.130 +  vtpmlogerror(VTPM_LOG_VTPM, "Failed to envelope decrypt data\n.");
  36.131 +  
  36.132 + egress:
  36.133 +  buffer_free ( &data_cipher);
  36.134 +  buffer_free ( &symkey_clear);
  36.135 +  buffer_free ( &symkey_cipher);
  36.136 +  Crypto_symcrypto_freekey (&symkey);
  36.137 +  
  36.138 +  return status;
  36.139 +}
  36.140 +
  36.141 +TPM_RESULT VTPM_Handle_Save_NVM(VTPM_DMI_RESOURCE *myDMI, 
  36.142 +				const buffer_t *inbuf, 
  36.143 +				buffer_t *outbuf) {
  36.144 +  
  36.145 +  TPM_RESULT status = TPM_SUCCESS;
  36.146 +  int fh;
  36.147 +  long bytes_written;
  36.148 +  buffer_t sealed_NVM;
  36.149 +  
  36.150 +  
  36.151 +  vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Save_NVMing[%d]: 0x\n", buffer_len(inbuf));
  36.152 +
  36.153 +  TPMTRYRETURN( envelope_encrypt(inbuf,
  36.154 +                                 &vtpm_globals->storageKey,
  36.155 +                                 &sealed_NVM) );
  36.156 +				  
  36.157    // Mark DMI Table so new save state info will get pushed to disk on return.
  36.158    vtpm_globals->DMI_table_dirty = TRUE;
  36.159    
  36.160 @@ -104,28 +194,22 @@ TPM_RESULT VTPM_Handle_Save_NVM(VTPM_DMI
  36.161    //       after writing the file? We can't get the old one back.
  36.162    // TODO: Backup old file and try and recover that way.
  36.163    fh = open(myDMI->NVMLocation, O_WRONLY | O_CREAT, S_IREAD | S_IWRITE);
  36.164 -  if ( (bytes_written = write(fh, sealed_NVM, sealed_NVM_size) ) != (long) sealed_NVM_size) {
  36.165 -    vtpmlogerror(VTPM_LOG_VTPM, "We just overwrote a DMI_NVM and failed to finish. %ld/%ld bytes.\n", bytes_written, (long)sealed_NVM_size);
  36.166 +  if ( (bytes_written = write(fh, sealed_NVM.bytes, buffer_len(&sealed_NVM) ) != (long) buffer_len(&sealed_NVM))) {
  36.167 +    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));
  36.168      status = TPM_IOERROR;
  36.169      goto abort_egress;
  36.170    }
  36.171    close(fh);
  36.172    
  36.173 -  Crypto_SHA1Full (sealed_NVM, sealed_NVM_size, (BYTE *) &myDMI->NVM_measurement);   
  36.174 +  Crypto_SHA1Full (sealed_NVM.bytes, buffer_len(&sealed_NVM), (BYTE *) &myDMI->NVM_measurement);   
  36.175    
  36.176 -  vtpmloginfo(VTPM_LOG_VTPM, "Saved %d bytes of E(symkey) + %d bytes of E(NVM)\n", buffer_len(&symkey_cipher), buffer_len(&state_cipher));
  36.177    goto egress;
  36.178    
  36.179   abort_egress:
  36.180 -  vtpmlogerror(VTPM_LOG_VTPM, "Failed to load NVM\n.");
  36.181 +  vtpmlogerror(VTPM_LOG_VTPM, "Failed to save NVM\n.");
  36.182    
  36.183   egress:
  36.184 -  
  36.185 -  buffer_free ( &state_cipher);
  36.186 -  buffer_free ( &symkey_cipher);
  36.187 -  free(sealed_NVM);
  36.188 -  Crypto_symcrypto_freekey (&symkey);
  36.189 -  
  36.190 +  buffer_free(&sealed_NVM);
  36.191    return status;
  36.192  }
  36.193  
  36.194 @@ -136,11 +220,7 @@ TPM_RESULT VTPM_Handle_Load_NVM(VTPM_DMI
  36.195  				buffer_t *outbuf) {
  36.196    
  36.197    TPM_RESULT status = TPM_SUCCESS;
  36.198 -  symkey_t    symkey;
  36.199 -  buffer_t    state_cipher = NULL_BUF, 
  36.200 -              symkey_clear = NULL_BUF, 
  36.201 -              symkey_cipher = NULL_BUF;
  36.202 -  struct pack_buf_t symkey_cipher32, state_cipher32;
  36.203 +
  36.204    
  36.205    UINT32 sealed_NVM_size;
  36.206    BYTE *sealed_NVM = NULL;
  36.207 @@ -148,9 +228,7 @@ TPM_RESULT VTPM_Handle_Load_NVM(VTPM_DMI
  36.208    int fh, stat_ret, i;
  36.209    struct stat file_stat;
  36.210    TPM_DIGEST sealedNVMHash;
  36.211 -  
  36.212 -  memset(&symkey, 0, sizeof(symkey_t));
  36.213 -  
  36.214 +   
  36.215    if (myDMI->NVMLocation == NULL) {
  36.216      vtpmlogerror(VTPM_LOG_VTPM, "Unable to load NVM because the file name NULL.\n");
  36.217      status = TPM_AUTHFAIL;
  36.218 @@ -168,28 +246,14 @@ TPM_RESULT VTPM_Handle_Load_NVM(VTPM_DMI
  36.219    }
  36.220    
  36.221    sealed_NVM = (BYTE *) malloc(fh_size);
  36.222 +  sealed_NVM_size = (UINT32) fh_size;
  36.223    if (read(fh, sealed_NVM, fh_size) != fh_size) {
  36.224      status = TPM_IOERROR;
  36.225      goto abort_egress;
  36.226    }
  36.227    close(fh);
  36.228    
  36.229 -  vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Load_NVMing[%ld]: 0x", fh_size);
  36.230 -  for (i=0; i< fh_size; i++)
  36.231 -    vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "%x ", sealed_NVM[i]);
  36.232 -  vtpmloginfomore(VTPM_LOG_VTPM_DEEP, "\n");
  36.233 -  
  36.234 -  sealed_NVM_size = BSG_UnpackList(sealed_NVM, 2,
  36.235 -				   BSG_TPM_SIZE32_DATA, &symkey_cipher32,
  36.236 -				   BSG_TPM_SIZE32_DATA, &state_cipher32);
  36.237 -  
  36.238 -  TPMTRYRETURN( buffer_init_convert (&symkey_cipher, 
  36.239 -				     symkey_cipher32.size, 
  36.240 -				     symkey_cipher32.data) );
  36.241 -  
  36.242 -  TPMTRYRETURN( buffer_init_convert (&state_cipher, 
  36.243 -				     state_cipher32.size, 
  36.244 -				     state_cipher32.data) );
  36.245 +  vtpmloginfo(VTPM_LOG_VTPM_DEEP, "Load_NVMing[%ld],\n", fh_size);
  36.246    
  36.247    Crypto_SHA1Full(sealed_NVM, sealed_NVM_size, (BYTE *) &sealedNVMHash);    
  36.248    
  36.249 @@ -210,32 +274,19 @@ TPM_RESULT VTPM_Handle_Load_NVM(VTPM_DMI
  36.250      goto abort_egress;
  36.251    }
  36.252    
  36.253 -  // Decrypt Symmetric Key
  36.254 -  TPMTRYRETURN( VTSP_Unbind(  myDMI->TCSContext,
  36.255 -			      vtpm_globals->storageKeyHandle,
  36.256 -			      &symkey_cipher,
  36.257 -			      (const TPM_AUTHDATA*)&vtpm_globals->storage_key_usage_auth,
  36.258 -			      &symkey_clear,
  36.259 -			      &(vtpm_globals->keyAuth) ) );
  36.260 -  
  36.261 -  // create symmetric key using saved bits
  36.262 -  Crypto_symcrypto_initkey (&symkey, &symkey_clear);
  36.263 -  
  36.264 -  // Decrypt State
  36.265 -  TPMTRY(TPM_DECRYPT_ERROR, Crypto_symcrypto_decrypt (&symkey, &state_cipher, outbuf) );
  36.266 -  
  36.267 +    TPMTRYRETURN( envelope_decrypt(fh_size,
  36.268 +                                 sealed_NVM,
  36.269 +                                 myDMI->TCSContext,
  36.270 +		        	 vtpm_globals->storageKeyHandle,
  36.271 +			         (const TPM_AUTHDATA*)&vtpm_globals->storage_key_usage_auth,
  36.272 +                                 outbuf) );  
  36.273    goto egress;
  36.274    
  36.275   abort_egress:
  36.276    vtpmlogerror(VTPM_LOG_VTPM, "Failed to load NVM\n.");
  36.277    
  36.278   egress:
  36.279 -  
  36.280 -  buffer_free ( &state_cipher);
  36.281 -  buffer_free ( &symkey_clear);
  36.282 -  buffer_free ( &symkey_cipher);
  36.283    free( sealed_NVM );
  36.284 -  Crypto_symcrypto_freekey (&symkey);
  36.285    
  36.286    return status;
  36.287  }
    37.1 --- a/tools/xm-test/README	Tue Dec 20 17:16:15 2005 +0000
    37.2 +++ b/tools/xm-test/README	Tue Dec 20 17:16:24 2005 +0000
    37.3 @@ -55,6 +55,26 @@ you should not attempt to use a ramdisk 
    37.4  of xm-test (i.e., don't use a ramdisk from 0.4.0 with 0.5.0.  0.5.0
    37.5  should work for 0.5.3 though)
    37.6  
    37.7 +If you'd like to build and run this with hardware virtual machine assist
    37.8 +(HVM) support to test fully virtualized disk images on VMX hardware, 
    37.9 +please add the --enable-vmx-support option to configure:
   37.10 +
   37.11 +  # ./autogen
   37.12 +  # ./configure --enable-vmx-support
   37.13 +  # make
   37.14 +
   37.15 +The ramdisk/bin/create_disk_image script, which builds the full virt
   37.16 +disk.img, requires Lilo 22.7+ to be installed on the system. Lilo is 
   37.17 +used to install the bootloader on the disk.img.
   37.18 +
   37.19 +If HVM / VMX support is enabled, the ramdisk/bin/create_disk_image script
   37.20 +will be run to create a full virt disk.img in the ramdisk directory. The
   37.21 +script, by default, will look in /boot for the first non-Xen kernel it
   37.22 +runs across. If you wish to use a different kernel or the script fails
   37.23 +to find a kernel, please run the script manually to make a disk.img 
   37.24 +using the -k option. Xm-test will look for disk.img in the ramdisk
   37.25 +directory when run by default.
   37.26 +
   37.27  
   37.28  Running
   37.29  =======
    38.1 --- a/tools/xm-test/ramdisk/Makefile.am	Tue Dec 20 17:16:15 2005 +0000
    38.2 +++ b/tools/xm-test/ramdisk/Makefile.am	Tue Dec 20 17:16:24 2005 +0000
    38.3 @@ -45,7 +45,7 @@ initrd.img: $(XMTEST_VER_IMG)
    38.4  
    38.5  disk.img: $(XMTEST_VER_IMG)
    38.6  	chmod a+x $(VMX_SCRIPT)
    38.7 -	$(VMX_SCRIPT) -r $(XMTEST_VER_IMG) -i disk.img
    38.8 +	$(VMX_SCRIPT) -r $(XMTEST_VER_IMG)
    38.9  
   38.10  existing:
   38.11  	@[ -f $(XMTEST_VER_IMG) ] && ln -sf $(XMTEST_VER_IMG) initrd.img || \
    39.1 --- a/tools/xm-test/ramdisk/bin/create_disk_image	Tue Dec 20 17:16:15 2005 +0000
    39.2 +++ b/tools/xm-test/ramdisk/bin/create_disk_image	Tue Dec 20 17:16:24 2005 +0000
    39.3 @@ -77,7 +77,7 @@ function check_dependencies()
    39.4  function initialize_globals()
    39.5  {
    39.6  	PROGNAME="create_disk_image"
    39.7 -	IMAGE="hvm.img"
    39.8 +	IMAGE="disk.img"
    39.9  	KERNEL=""
   39.10  	LCONF="lilo.conf"
   39.11  	LOOPD=""    # Loop device for entire disk image
    40.1 --- a/xen/Rules.mk	Tue Dec 20 17:16:15 2005 +0000
    40.2 +++ b/xen/Rules.mk	Tue Dec 20 17:16:24 2005 +0000
    40.3 @@ -6,7 +6,6 @@ verbose     ?= n
    40.4  debug       ?= n
    40.5  perfc       ?= n
    40.6  perfc_arrays?= n
    40.7 -domu_debug  ?= n
    40.8  crash_debug ?= n
    40.9  
   40.10  XEN_ROOT=$(BASEDIR)/..
   40.11 @@ -54,10 +53,6 @@ else
   40.12  CFLAGS += -g -DVERBOSE
   40.13  endif
   40.14  
   40.15 -ifeq ($(domu_debug),y)
   40.16 -CFLAGS += -DDOMU_DEBUG
   40.17 -endif
   40.18 -
   40.19  ifeq ($(crash_debug),y)
   40.20  CFLAGS += -g -DCRASH_DEBUG
   40.21  endif
    41.1 --- a/xen/arch/x86/audit.c	Tue Dec 20 17:16:15 2005 +0000
    41.2 +++ b/xen/arch/x86/audit.c	Tue Dec 20 17:16:24 2005 +0000
    41.3 @@ -61,7 +61,7 @@ int audit_adjust_pgtables(struct domain 
    41.4  #ifdef __i386__
    41.5  #ifdef CONFIG_X86_PAE
    41.6          /* 32b PAE */
    41.7 -        if ( (( frame_table[mfn].u.inuse.type_info & PGT_va_mask ) 
    41.8 +        if ( (( pfn_to_page(mfn)->u.inuse.type_info & PGT_va_mask ) 
    41.9  	    >> PGT_va_shift) == 3 )
   41.10              return l2_table_offset(HYPERVISOR_VIRT_START); 
   41.11          else
   41.12 @@ -364,7 +364,7 @@ int audit_adjust_pgtables(struct domain 
   41.13              {
   41.14                  gmfn = __gpfn_to_mfn(d, a->gpfn_and_flags & PGT_mfn_mask);
   41.15                  smfn = a->smfn;
   41.16 -                page = &frame_table[smfn];
   41.17 +                page = pfn_to_page(smfn);
   41.18  
   41.19                  switch ( a->gpfn_and_flags & PGT_type_mask ) {
   41.20                  case PGT_writable_pred:
   41.21 @@ -433,11 +433,13 @@ int audit_adjust_pgtables(struct domain 
   41.22          for_each_vcpu(d, v)
   41.23          {
   41.24              if ( pagetable_get_paddr(v->arch.guest_table) )
   41.25 -                adjust(&frame_table[pagetable_get_pfn(v->arch.guest_table)], !shadow_mode_refcounts(d));
   41.26 +                adjust(pfn_to_page(pagetable_get_pfn(v->arch.guest_table)),
   41.27 +                       !shadow_mode_refcounts(d));
   41.28              if ( pagetable_get_paddr(v->arch.shadow_table) )
   41.29 -                adjust(&frame_table[pagetable_get_pfn(v->arch.shadow_table)], 0);
   41.30 +                adjust(pfn_to_page(pagetable_get_pfn(v->arch.shadow_table)),
   41.31 +                       0);
   41.32              if ( v->arch.monitor_shadow_ref )
   41.33 -                adjust(&frame_table[v->arch.monitor_shadow_ref], 0);
   41.34 +                adjust(pfn_to_page(v->arch.monitor_shadow_ref), 0);
   41.35          }
   41.36      }
   41.37  
   41.38 @@ -617,7 +619,7 @@ void _audit_domain(struct domain *d, int
   41.39      void scan_for_pfn_in_mfn(struct domain *d, unsigned long xmfn,
   41.40                               unsigned long mfn)
   41.41      {
   41.42 -        struct pfn_info *page = &frame_table[mfn];
   41.43 +        struct pfn_info *page = pfn_to_page(mfn);
   41.44          l1_pgentry_t *pt = map_domain_page(mfn);
   41.45          int i;
   41.46  
    42.1 --- a/xen/arch/x86/dom0_ops.c	Tue Dec 20 17:16:15 2005 +0000
    42.2 +++ b/xen/arch/x86/dom0_ops.c	Tue Dec 20 17:16:24 2005 +0000
    42.3 @@ -210,7 +210,7 @@ long arch_do_dom0_op(dom0_op_t *op, dom0
    42.4               unlikely((d = find_domain_by_id(dom)) == NULL) )
    42.5              break;
    42.6  
    42.7 -        page = &frame_table[pfn];
    42.8 +        page = pfn_to_page(pfn);
    42.9  
   42.10          if ( likely(get_page(page, d)) )
   42.11          {
   42.12 @@ -285,7 +285,7 @@ long arch_do_dom0_op(dom0_op_t *op, dom0
   42.13                  struct pfn_info *page;
   42.14                  unsigned long mfn = l_arr[j];
   42.15  
   42.16 -                page = &frame_table[mfn];
   42.17 +                page = pfn_to_page(mfn);
   42.18  
   42.19                  if ( likely(pfn_valid(mfn) && get_page(page, d)) ) 
   42.20                  {
   42.21 @@ -350,15 +350,14 @@ long arch_do_dom0_op(dom0_op_t *op, dom0
   42.22              list_ent = d->page_list.next;
   42.23              for ( i = 0; (i < max_pfns) && (list_ent != &d->page_list); i++ )
   42.24              {
   42.25 -                pfn = list_entry(list_ent, struct pfn_info, list) - 
   42.26 -                    frame_table;
   42.27 +                pfn = page_to_pfn(list_entry(list_ent, struct pfn_info, list));
   42.28                  if ( put_user(pfn, buffer) )
   42.29                  {
   42.30                      ret = -EFAULT;
   42.31                      break;
   42.32                  }
   42.33                  buffer++;
   42.34 -                list_ent = frame_table[pfn].list.next;
   42.35 +                list_ent = pfn_to_page(pfn)->list.next;
   42.36              }
   42.37              spin_unlock(&d->page_alloc_lock);
   42.38  
    43.1 --- a/xen/arch/x86/domain.c	Tue Dec 20 17:16:15 2005 +0000
    43.2 +++ b/xen/arch/x86/domain.c	Tue Dec 20 17:16:24 2005 +0000
    43.3 @@ -190,7 +190,7 @@ void dump_pageframe_info(struct domain *
    43.4          list_for_each_entry ( page, &d->page_list, list )
    43.5          {
    43.6              printk("Page %p: mfn=%p, caf=%08x, taf=%" PRtype_info "\n",
    43.7 -                   _p(page_to_phys(page)), _p(page - frame_table),
    43.8 +                   _p(page_to_phys(page)), _p(page_to_pfn(page)),
    43.9                     page->count_info, page->u.inuse.type_info);
   43.10          }
   43.11      }
   43.12 @@ -198,13 +198,13 @@ void dump_pageframe_info(struct domain *
   43.13      list_for_each_entry ( page, &d->xenpage_list, list )
   43.14      {
   43.15          printk("XenPage %p: mfn=%p, caf=%08x, taf=%" PRtype_info "\n",
   43.16 -               _p(page_to_phys(page)), _p(page - frame_table),
   43.17 +               _p(page_to_phys(page)), _p(page_to_pfn(page)),
   43.18                 page->count_info, page->u.inuse.type_info);
   43.19      }
   43.20  
   43.21      page = virt_to_page(d->shared_info);
   43.22      printk("Shared_info@%p: mfn=%p, caf=%08x, taf=%" PRtype_info "\n",
   43.23 -           _p(page_to_phys(page)), _p(page - frame_table), page->count_info,
   43.24 +           _p(page_to_phys(page)), _p(page_to_pfn(page)), page->count_info,
   43.25             page->u.inuse.type_info);
   43.26  }
   43.27  
   43.28 @@ -391,19 +391,19 @@ int arch_set_info_guest(
   43.29  
   43.30      if ( shadow_mode_refcounts(d) )
   43.31      {
   43.32 -        if ( !get_page(&frame_table[phys_basetab>>PAGE_SHIFT], d) )
   43.33 +        if ( !get_page(pfn_to_page(phys_basetab>>PAGE_SHIFT), d) )
   43.34              return -EINVAL;
   43.35      }
   43.36      else if ( !(c->flags & VGCF_VMX_GUEST) )
   43.37      {
   43.38 -        if ( !get_page_and_type(&frame_table[phys_basetab>>PAGE_SHIFT], d,
   43.39 +        if ( !get_page_and_type(pfn_to_page(phys_basetab>>PAGE_SHIFT), d,
   43.40                                  PGT_base_page_table) )
   43.41              return -EINVAL;
   43.42      }
   43.43  
   43.44      if ( (rc = (int)set_gdt(v, c->gdt_frames, c->gdt_ents)) != 0 )
   43.45      {
   43.46 -        put_page_and_type(&frame_table[phys_basetab>>PAGE_SHIFT]);
   43.47 +        put_page_and_type(pfn_to_page(phys_basetab>>PAGE_SHIFT));
   43.48          return rc;
   43.49      }
   43.50  
    44.1 --- a/xen/arch/x86/domain_build.c	Tue Dec 20 17:16:15 2005 +0000
    44.2 +++ b/xen/arch/x86/domain_build.c	Tue Dec 20 17:16:24 2005 +0000
    44.3 @@ -405,7 +405,7 @@ int construct_dom0(struct domain *d,
    44.4          *l1tab = l1e_from_pfn(mfn, L1_PROT);
    44.5          l1tab++;
    44.6          
    44.7 -        page = &frame_table[mfn];
    44.8 +        page = pfn_to_page(mfn);
    44.9          if ( !get_page_and_type(page, d, PGT_writable_page) )
   44.10              BUG();
   44.11  
   44.12 @@ -418,7 +418,7 @@ int construct_dom0(struct domain *d,
   44.13      l1tab += l1_table_offset(vpt_start);
   44.14      for ( count = 0; count < nr_pt_pages; count++ ) 
   44.15      {
   44.16 -        page = &frame_table[l1e_get_pfn(*l1tab)];
   44.17 +        page = pfn_to_page(l1e_get_pfn(*l1tab));
   44.18          if ( !opt_dom0_shadow )
   44.19              l1e_remove_flags(*l1tab, _PAGE_RW);
   44.20          else
   44.21 @@ -548,7 +548,7 @@ int construct_dom0(struct domain *d,
   44.22          *l1tab = l1e_from_pfn(mfn, L1_PROT);
   44.23          l1tab++;
   44.24  
   44.25 -        page = &frame_table[mfn];
   44.26 +        page = pfn_to_page(mfn);
   44.27          if ( (page->u.inuse.type_info == 0) &&
   44.28               !get_page_and_type(page, d, PGT_writable_page) )
   44.29              BUG();
   44.30 @@ -567,7 +567,7 @@ int construct_dom0(struct domain *d,
   44.31      for ( count = 0; count < nr_pt_pages; count++ ) 
   44.32      {
   44.33          l1e_remove_flags(*l1tab, _PAGE_RW);
   44.34 -        page = &frame_table[l1e_get_pfn(*l1tab)];
   44.35 +        page = pfn_to_page(l1e_get_pfn(*l1tab));
   44.36  
   44.37          /* Read-only mapping + PGC_allocated + page-table page. */
   44.38          page->count_info         = PGC_allocated | 3;
    45.1 --- a/xen/arch/x86/mm.c	Tue Dec 20 17:16:15 2005 +0000
    45.2 +++ b/xen/arch/x86/mm.c	Tue Dec 20 17:16:24 2005 +0000
    45.3 @@ -202,7 +202,7 @@ void arch_init_memory(void)
    45.4      /* First 1MB of RAM is historically marked as I/O. */
    45.5      for ( i = 0; i < 0x100; i++ )
    45.6      {
    45.7 -        page = &frame_table[i];
    45.8 +        page = pfn_to_page(i);
    45.9          page->count_info        = PGC_allocated | 1;
   45.10          page->u.inuse.type_info = PGT_writable_page | PGT_validated | 1;
   45.11          page_set_owner(page, dom_io);
   45.12 @@ -216,10 +216,10 @@ void arch_init_memory(void)
   45.13          /* Every page from cursor to start of next RAM region is I/O. */
   45.14          rstart_pfn = PFN_UP(e820.map[i].addr);
   45.15          rend_pfn   = PFN_DOWN(e820.map[i].addr + e820.map[i].size);
   45.16 -        while ( pfn < rstart_pfn )
   45.17 +        for ( ; pfn < rstart_pfn; pfn++ )
   45.18          {
   45.19              BUG_ON(!pfn_valid(pfn));
   45.20 -            page = &frame_table[pfn++];
   45.21 +            page = pfn_to_page(pfn);
   45.22              page->count_info        = PGC_allocated | 1;
   45.23              page->u.inuse.type_info = PGT_writable_page | PGT_validated | 1;
   45.24              page_set_owner(page, dom_io);
   45.25 @@ -253,7 +253,7 @@ void invalidate_shadow_ldt(struct vcpu *
   45.26          pfn = l1e_get_pfn(v->arch.perdomain_ptes[i]);
   45.27          if ( pfn == 0 ) continue;
   45.28          v->arch.perdomain_ptes[i] = l1e_empty();
   45.29 -        page = &frame_table[pfn];
   45.30 +        page = pfn_to_page(pfn);
   45.31          ASSERT_PAGE_IS_TYPE(page, PGT_ldt_page);
   45.32          ASSERT_PAGE_IS_DOMAIN(page, v->domain);
   45.33          put_page_and_type(page);
   45.34 @@ -320,13 +320,13 @@ int map_ldt_shadow_page(unsigned int off
   45.35      if ( unlikely(!VALID_MFN(gmfn)) )
   45.36          return 0;
   45.37  
   45.38 -    res = get_page_and_type(&frame_table[gmfn], d, PGT_ldt_page);
   45.39 +    res = get_page_and_type(pfn_to_page(gmfn), d, PGT_ldt_page);
   45.40  
   45.41      if ( !res && unlikely(shadow_mode_refcounts(d)) )
   45.42      {
   45.43          shadow_lock(d);
   45.44          shadow_remove_all_write_access(d, gpfn, gmfn);
   45.45 -        res = get_page_and_type(&frame_table[gmfn], d, PGT_ldt_page);
   45.46 +        res = get_page_and_type(pfn_to_page(gmfn), d, PGT_ldt_page);
   45.47          shadow_unlock(d);
   45.48      }
   45.49  
   45.50 @@ -344,7 +344,7 @@ int map_ldt_shadow_page(unsigned int off
   45.51  
   45.52  static int get_page_from_pagenr(unsigned long page_nr, struct domain *d)
   45.53  {
   45.54 -    struct pfn_info *page = &frame_table[page_nr];
   45.55 +    struct pfn_info *page = pfn_to_page(page_nr);
   45.56  
   45.57      if ( unlikely(!pfn_valid(page_nr)) || unlikely(!get_page(page, d)) )
   45.58      {
   45.59 @@ -360,7 +360,7 @@ static int get_page_and_type_from_pagenr
   45.60                                           unsigned long type,
   45.61                                           struct domain *d)
   45.62  {
   45.63 -    struct pfn_info *page = &frame_table[page_nr];
   45.64 +    struct pfn_info *page = pfn_to_page(page_nr);
   45.65  
   45.66      if ( unlikely(!get_page_from_pagenr(page_nr, d)) )
   45.67          return 0;
   45.68 @@ -412,7 +412,7 @@ get_linear_pagetable(
   45.69           * Make sure that the mapped frame is an already-validated L2 table. 
   45.70           * If so, atomically increment the count (checking for overflow).
   45.71           */
   45.72 -        page = &frame_table[pfn];
   45.73 +        page = pfn_to_page(pfn);
   45.74          y = page->u.inuse.type_info;
   45.75          do {
   45.76              x = y;
   45.77 @@ -435,7 +435,7 @@ get_page_from_l1e(
   45.78      l1_pgentry_t l1e, struct domain *d)
   45.79  {
   45.80      unsigned long mfn = l1e_get_pfn(l1e);
   45.81 -    struct pfn_info *page = &frame_table[mfn];
   45.82 +    struct pfn_info *page = pfn_to_page(mfn);
   45.83      int okay;
   45.84      extern int domain_iomem_in_pfn(struct domain *d, unsigned long pfn);
   45.85  
   45.86 @@ -587,7 +587,7 @@ get_page_from_l4e(
   45.87  void put_page_from_l1e(l1_pgentry_t l1e, struct domain *d)
   45.88  {
   45.89      unsigned long    pfn  = l1e_get_pfn(l1e);
   45.90 -    struct pfn_info *page = &frame_table[pfn];
   45.91 +    struct pfn_info *page = pfn_to_page(pfn);
   45.92      struct domain   *e;
   45.93      struct vcpu     *v;
   45.94  
   45.95 @@ -645,7 +645,7 @@ static void put_page_from_l2e(l2_pgentry
   45.96  {
   45.97      if ( (l2e_get_flags(l2e) & _PAGE_PRESENT) && 
   45.98           (l2e_get_pfn(l2e) != pfn) )
   45.99 -        put_page_and_type(&frame_table[l2e_get_pfn(l2e)]);
  45.100 +        put_page_and_type(pfn_to_page(l2e_get_pfn(l2e)));
  45.101  }
  45.102  
  45.103  
  45.104 @@ -655,7 +655,7 @@ static void put_page_from_l3e(l3_pgentry
  45.105  {
  45.106      if ( (l3e_get_flags(l3e) & _PAGE_PRESENT) && 
  45.107           (l3e_get_pfn(l3e) != pfn) )
  45.108 -        put_page_and_type(&frame_table[l3e_get_pfn(l3e)]);
  45.109 +        put_page_and_type(pfn_to_page(l3e_get_pfn(l3e)));
  45.110  }
  45.111  
  45.112  #endif
  45.113 @@ -666,7 +666,7 @@ static void put_page_from_l4e(l4_pgentry
  45.114  {
  45.115      if ( (l4e_get_flags(l4e) & _PAGE_PRESENT) && 
  45.116           (l4e_get_pfn(l4e) != pfn) )
  45.117 -        put_page_and_type(&frame_table[l4e_get_pfn(l4e)]);
  45.118 +        put_page_and_type(pfn_to_page(l4e_get_pfn(l4e)));
  45.119  }
  45.120  
  45.121  #endif
  45.122 @@ -1584,9 +1584,9 @@ int new_guest_cr3(unsigned long mfn)
  45.123          write_ptbase(v);
  45.124  
  45.125          if ( shadow_mode_refcounts(d) )
  45.126 -            put_page(&frame_table[old_base_mfn]);
  45.127 +            put_page(pfn_to_page(old_base_mfn));
  45.128          else
  45.129 -            put_page_and_type(&frame_table[old_base_mfn]);
  45.130 +            put_page_and_type(pfn_to_page(old_base_mfn));
  45.131  
  45.132          /* CR3 also holds a ref to its shadow... */
  45.133          if ( shadow_mode_enabled(d) )
  45.134 @@ -1595,7 +1595,7 @@ int new_guest_cr3(unsigned long mfn)
  45.135                  put_shadow_ref(v->arch.monitor_shadow_ref);
  45.136              v->arch.monitor_shadow_ref =
  45.137                  pagetable_get_pfn(v->arch.monitor_table);
  45.138 -            ASSERT(!page_get_owner(&frame_table[v->arch.monitor_shadow_ref]));
  45.139 +            ASSERT(!page_get_owner(pfn_to_page(v->arch.monitor_shadow_ref)));
  45.140              get_shadow_ref(v->arch.monitor_shadow_ref);
  45.141          }
  45.142      }
  45.143 @@ -1763,7 +1763,7 @@ int do_mmuext_op(
  45.144  
  45.145          okay = 1;
  45.146          mfn  = op.arg1.mfn;
  45.147 -        page = &frame_table[mfn];
  45.148 +        page = pfn_to_page(mfn);
  45.149  
  45.150          switch ( op.cmd )
  45.151          {
  45.152 @@ -1845,7 +1845,7 @@ int do_mmuext_op(
  45.153                      pagetable_get_pfn(v->arch.guest_table_user);
  45.154                  v->arch.guest_table_user = mk_pagetable(mfn << PAGE_SHIFT);
  45.155                  if ( old_mfn != 0 )
  45.156 -                    put_page_and_type(&frame_table[old_mfn]);
  45.157 +                    put_page_and_type(pfn_to_page(old_mfn));
  45.158              }
  45.159              break;
  45.160  #endif
  45.161 @@ -2145,7 +2145,7 @@ int do_mmu_update(
  45.162              va = map_domain_page_with_cache(mfn, &mapcache);
  45.163              va = (void *)((unsigned long)va +
  45.164                            (unsigned long)(req.ptr & ~PAGE_MASK));
  45.165 -            page = &frame_table[mfn];
  45.166 +            page = pfn_to_page(mfn);
  45.167  
  45.168              switch ( (type_info = page->u.inuse.type_info) & PGT_type_mask )
  45.169              {
  45.170 @@ -2285,7 +2285,7 @@ int do_mmu_update(
  45.171  
  45.172              mark_dirty(FOREIGNDOM, mfn);
  45.173  
  45.174 -            put_page(&frame_table[mfn]);
  45.175 +            put_page(pfn_to_page(mfn));
  45.176              break;
  45.177  
  45.178          default:
  45.179 @@ -2728,7 +2728,7 @@ void destroy_gdt(struct vcpu *v)
  45.180      for ( i = 0; i < FIRST_RESERVED_GDT_PAGE; i++ )
  45.181      {
  45.182          if ( (pfn = l1e_get_pfn(v->arch.perdomain_ptes[i])) != 0 )
  45.183 -            put_page_and_type(&frame_table[pfn]);
  45.184 +            put_page_and_type(pfn_to_page(pfn));
  45.185          v->arch.perdomain_ptes[i] = l1e_empty();
  45.186          v->arch.guest_context.gdt_frames[i] = 0;
  45.187      }
  45.188 @@ -2753,7 +2753,7 @@ long set_gdt(struct vcpu *v,
  45.189      for ( i = 0; i < nr_pages; i++ ) {
  45.190          pfn = frames[i];
  45.191          if ((pfn >= max_page) ||
  45.192 -            !get_page_and_type(&frame_table[pfn], d, PGT_gdt_page) )
  45.193 +            !get_page_and_type(pfn_to_page(pfn), d, PGT_gdt_page) )
  45.194              goto fail;
  45.195      }
  45.196  
  45.197 @@ -2773,7 +2773,7 @@ long set_gdt(struct vcpu *v,
  45.198  
  45.199   fail:
  45.200      while ( i-- > 0 )
  45.201 -        put_page_and_type(&frame_table[frames[i]]);
  45.202 +        put_page_and_type(pfn_to_page(frames[i]));
  45.203      return -EINVAL;
  45.204  }
  45.205  
  45.206 @@ -2827,7 +2827,7 @@ long do_update_descriptor(u64 pa, u64 de
  45.207          return -EINVAL;
  45.208      }
  45.209  
  45.210 -    page = &frame_table[mfn];
  45.211 +    page = pfn_to_page(mfn);
  45.212      if ( unlikely(!get_page(page, dom)) )
  45.213      {
  45.214          UNLOCK_BIGLOCK(dom);
  45.215 @@ -3037,7 +3037,7 @@ int revalidate_l1(
  45.216          if ( likely(l1e_get_intpte(ol1e) == (l1e_get_intpte(nl1e)|_PAGE_RW)) )
  45.217          {
  45.218              if ( likely(l1e_get_flags(nl1e) & _PAGE_PRESENT) )
  45.219 -                put_page_type(&frame_table[l1e_get_pfn(nl1e)]);
  45.220 +                put_page_type(pfn_to_page(l1e_get_pfn(nl1e)));
  45.221              continue;
  45.222          }
  45.223  
  45.224 @@ -3220,7 +3220,7 @@ static int ptwr_emulated_update(
  45.225      }
  45.226  
  45.227      pfn  = l1e_get_pfn(pte);
  45.228 -    page = &frame_table[pfn];
  45.229 +    page = pfn_to_page(pfn);
  45.230  
  45.231      /* We are looking only for read-only mappings of p.t. pages. */
  45.232      if ( ((l1e_get_flags(pte) & (_PAGE_RW|_PAGE_PRESENT)) != _PAGE_PRESENT) ||
  45.233 @@ -3331,7 +3331,7 @@ int ptwr_do_page_fault(struct domain *d,
  45.234      }
  45.235  
  45.236      pfn  = l1e_get_pfn(pte);
  45.237 -    page = &frame_table[pfn];
  45.238 +    page = pfn_to_page(pfn);
  45.239  
  45.240  #ifdef CONFIG_X86_64
  45.241  #define WRPT_PTE_FLAGS (_PAGE_RW | _PAGE_PRESENT | _PAGE_USER)
    46.1 --- a/xen/arch/x86/setup.c	Tue Dec 20 17:16:15 2005 +0000
    46.2 +++ b/xen/arch/x86/setup.c	Tue Dec 20 17:16:24 2005 +0000
    46.3 @@ -264,7 +264,7 @@ void __init __start_xen(multiboot_info_t
    46.4      unsigned long _initrd_start = 0, _initrd_len = 0;
    46.5      unsigned int initrdidx = 1;
    46.6      physaddr_t s, e;
    46.7 -    int i, e820_raw_nr = 0, bytes = 0;
    46.8 +    int i, e820_warn = 0, e820_raw_nr = 0, bytes = 0;
    46.9      struct ns16550_defaults ns16550 = {
   46.10          .data_bits = 8,
   46.11          .parity    = 'n',
   46.12 @@ -313,6 +313,22 @@ void __init __start_xen(multiboot_info_t
   46.13          while ( bytes < mbi->mmap_length )
   46.14          {
   46.15              memory_map_t *map = __va(mbi->mmap_addr + bytes);
   46.16 +
   46.17 +            /*
   46.18 +             * This is a gross workaround for a BIOS bug. Some bootloaders do
   46.19 +             * not write e820 map entries into pre-zeroed memory. This is
   46.20 +             * okay if the BIOS fills in all fields of the map entry, but
   46.21 +             * some broken BIOSes do not bother to write the high word of
   46.22 +             * the length field if the length is smaller than 4GB. We
   46.23 +             * detect and fix this by flagging sections below 4GB that
   46.24 +             * appear to be larger than 4GB in size.
   46.25 +             */
   46.26 +            if ( (map->base_addr_high == 0) && (map->length_high != 0) )
   46.27 +            {
   46.28 +                e820_warn = 1;
   46.29 +                map->length_high = 0;
   46.30 +            }
   46.31 +
   46.32              e820_raw[e820_raw_nr].addr = 
   46.33                  ((u64)map->base_addr_high << 32) | (u64)map->base_addr_low;
   46.34              e820_raw[e820_raw_nr].size = 
   46.35 @@ -320,6 +336,7 @@ void __init __start_xen(multiboot_info_t
   46.36              e820_raw[e820_raw_nr].type = 
   46.37                  (map->type > E820_SHARED_PAGE) ? E820_RESERVED : map->type;
   46.38              e820_raw_nr++;
   46.39 +
   46.40              bytes += map->size + 4;
   46.41          }
   46.42      }
   46.43 @@ -339,6 +356,10 @@ void __init __start_xen(multiboot_info_t
   46.44          for ( ; ; ) ;
   46.45      }
   46.46  
   46.47 +    if ( e820_warn )
   46.48 +        printk("WARNING: Buggy e820 map detected and fixed "
   46.49 +               "(truncated length fields).\n");
   46.50 +
   46.51      max_page = init_e820(e820_raw, &e820_raw_nr);
   46.52  
   46.53      modules_length = mod[mbi->mods_count-1].mod_end - mod[0].mod_start;
    47.1 --- a/xen/arch/x86/shadow.c	Tue Dec 20 17:16:15 2005 +0000
    47.2 +++ b/xen/arch/x86/shadow.c	Tue Dec 20 17:16:24 2005 +0000
    47.3 @@ -504,7 +504,7 @@ static unsigned long shadow_l2_table(
    47.4              l2e_from_pfn(smfn, __PAGE_HYPERVISOR);
    47.5  
    47.6          spl2e[l2_table_offset(PERDOMAIN_VIRT_START)] =
    47.7 -            l2e_from_paddr(__pa(page_get_owner(&frame_table[gmfn])->arch.mm_perdomain_pt),
    47.8 +            l2e_from_paddr(__pa(page_get_owner(pfn_to_page(gmfn))->arch.mm_perdomain_pt),
    47.9                              __PAGE_HYPERVISOR);
   47.10  
   47.11          if ( shadow_mode_translate(d) ) // NB: not external
   47.12 @@ -670,7 +670,7 @@ static void shadow_map_l1_into_current_l
   47.13              set_guest_back_ptr(d, sl1e, sl1mfn, i);
   47.14          }
   47.15  
   47.16 -        frame_table[sl1mfn].tlbflush_timestamp =
   47.17 +        pfn_to_page(sl1mfn)->tlbflush_timestamp =
   47.18              SHADOW_ENCODE_MIN_MAX(min, max);
   47.19  
   47.20          unmap_domain_page(gpl1e);
   47.21 @@ -907,7 +907,7 @@ shadow_make_snapshot(
   47.22      u32 min_max = 0;
   47.23      int min, max, length;
   47.24  
   47.25 -    if ( test_and_set_bit(_PGC_out_of_sync, &frame_table[gmfn].count_info) )
   47.26 +    if ( test_and_set_bit(_PGC_out_of_sync, &pfn_to_page(gmfn)->count_info) )
   47.27      {
   47.28          ASSERT(__shadow_status(d, gpfn, PGT_snapshot));
   47.29          return SHADOW_SNAPSHOT_ELSEWHERE;
   47.30 @@ -953,7 +953,7 @@ static struct out_of_sync_entry *
   47.31                               unsigned long mfn)
   47.32  {
   47.33      struct domain *d = v->domain;
   47.34 -    struct pfn_info *page = &frame_table[mfn];
   47.35 +    struct pfn_info *page = pfn_to_page(mfn);
   47.36      struct out_of_sync_entry *entry = shadow_alloc_oos_entry(d);
   47.37  
   47.38      ASSERT(shadow_lock_is_acquired(d));
   47.39 @@ -1174,7 +1174,7 @@ static int is_out_of_sync(struct vcpu *v
   47.40                  && i == PAGING_L4)
   47.41                  continue;       /* skip the top-level for 3-level */
   47.42  
   47.43 -            if ( page_out_of_sync(&frame_table[gmfn]) &&
   47.44 +            if ( page_out_of_sync(pfn_to_page(gmfn)) &&
   47.45                   !snapshot_entry_matches(
   47.46                       d, guest_pt, gpfn, table_offset_64(va, i)) )
   47.47              {
   47.48 @@ -1200,7 +1200,7 @@ static int is_out_of_sync(struct vcpu *v
   47.49          }
   47.50  
   47.51          /* L2 */
   47.52 -        if ( page_out_of_sync(&frame_table[gmfn]) &&
   47.53 +        if ( page_out_of_sync(pfn_to_page(gmfn)) &&
   47.54               !snapshot_entry_matches(d, guest_pt, gpfn, l2_table_offset(va)) )
   47.55          {
   47.56              unmap_and_return (1);
   47.57 @@ -1214,7 +1214,7 @@ static int is_out_of_sync(struct vcpu *v
   47.58  #undef unmap_and_return
   47.59  #endif /* CONFIG_PAGING_LEVELS >= 3 */
   47.60      {
   47.61 -        if ( page_out_of_sync(&frame_table[l2mfn]) &&
   47.62 +        if ( page_out_of_sync(pfn_to_page(l2mfn)) &&
   47.63               !snapshot_entry_matches(d, (guest_l1_pgentry_t *)v->arch.guest_vtable,
   47.64                                       l2pfn, guest_l2_table_offset(va)) )
   47.65              return 1;
   47.66 @@ -1234,7 +1234,7 @@ static int is_out_of_sync(struct vcpu *v
   47.67  
   47.68      guest_pt = (guest_l1_pgentry_t *) map_domain_page(l1mfn);
   47.69  
   47.70 -    if ( page_out_of_sync(&frame_table[l1mfn]) &&
   47.71 +    if ( page_out_of_sync(pfn_to_page(l1mfn)) &&
   47.72           !snapshot_entry_matches(
   47.73               d, guest_pt, l1pfn, guest_l1_table_offset(va)) ) 
   47.74      {
   47.75 @@ -1324,18 +1324,18 @@ static u32 remove_all_write_access_in_pt
   47.76      int i;
   47.77      u32 found = 0;
   47.78      int is_l1_shadow =
   47.79 -        ((frame_table[pt_mfn].u.inuse.type_info & PGT_type_mask) ==
   47.80 +        ((pfn_to_page(pt_mfn)->u.inuse.type_info & PGT_type_mask) ==
   47.81           PGT_l1_shadow);
   47.82  #if CONFIG_PAGING_LEVELS == 4
   47.83      is_l1_shadow |=
   47.84 -      ((frame_table[pt_mfn].u.inuse.type_info & PGT_type_mask) ==
   47.85 +      ((pfn_to_page(pt_mfn)->u.inuse.type_info & PGT_type_mask) ==
   47.86                  PGT_fl1_shadow);
   47.87  #endif
   47.88  
   47.89      match = l1e_from_pfn(readonly_gmfn, flags);
   47.90  
   47.91      if ( shadow_mode_external(d) ) {
   47.92 -        i = (frame_table[readonly_gmfn].u.inuse.type_info & PGT_va_mask)
   47.93 +        i = (pfn_to_page(readonly_gmfn)->u.inuse.type_info & PGT_va_mask)
   47.94              >> PGT_va_shift;
   47.95  
   47.96          if ( (i >= 0 && i < L1_PAGETABLE_ENTRIES) &&
   47.97 @@ -1373,7 +1373,7 @@ static int remove_all_write_access(
   47.98  
   47.99      // If it's not a writable page, then no writable refs can be outstanding.
  47.100      //
  47.101 -    if ( (frame_table[readonly_gmfn].u.inuse.type_info & PGT_type_mask) !=
  47.102 +    if ( (pfn_to_page(readonly_gmfn)->u.inuse.type_info & PGT_type_mask) !=
  47.103           PGT_writable_page )
  47.104      {
  47.105          perfc_incrc(remove_write_not_writable);
  47.106 @@ -1383,7 +1383,7 @@ static int remove_all_write_access(
  47.107      // How many outstanding writable PTEs for this page are there?
  47.108      //
  47.109      write_refs =
  47.110 -        (frame_table[readonly_gmfn].u.inuse.type_info & PGT_count_mask);
  47.111 +        (pfn_to_page(readonly_gmfn)->u.inuse.type_info & PGT_count_mask);
  47.112      if ( write_refs && MFN_PINNED(readonly_gmfn) )
  47.113      {
  47.114          write_refs--;
  47.115 @@ -1401,7 +1401,7 @@ static int remove_all_write_access(
  47.116  
  47.117           // Use the back pointer to locate the shadow page that can contain
  47.118           // the PTE of interest
  47.119 -         if ( (predicted_smfn = frame_table[readonly_gmfn].tlbflush_timestamp) ) {
  47.120 +         if ( (predicted_smfn = pfn_to_page(readonly_gmfn)->tlbflush_timestamp) ) {
  47.121               found += remove_all_write_access_in_ptpage(
  47.122                   d, predicted_smfn, predicted_smfn, readonly_gpfn, readonly_gmfn, write_refs, 0);
  47.123               if ( found == write_refs )
  47.124 @@ -1670,7 +1670,7 @@ static int resync_all(struct domain *d, 
  47.125                      if ( !(entry_get_flags(guest_pt[i]) & _PAGE_PRESENT) &&
  47.126                           unlikely(entry_get_value(guest_pt[i]) != 0) &&
  47.127                           !unshadow &&
  47.128 -                         (frame_table[smfn].u.inuse.type_info & PGT_pinned) )
  47.129 +                         (pfn_to_page(smfn)->u.inuse.type_info & PGT_pinned) )
  47.130                          unshadow = 1;
  47.131                  }
  47.132  #endif
  47.133 @@ -1718,7 +1718,7 @@ static int resync_all(struct domain *d, 
  47.134                  if ( !(guest_root_get_flags(new_root_e) & _PAGE_PRESENT) &&
  47.135                       unlikely(guest_root_get_intpte(new_root_e) != 0) &&
  47.136                       !unshadow &&
  47.137 -                     (frame_table[smfn].u.inuse.type_info & PGT_pinned) )
  47.138 +                     (pfn_to_page(smfn)->u.inuse.type_info & PGT_pinned) )
  47.139                      unshadow = 1;
  47.140              }
  47.141              if ( max == -1 )
  47.142 @@ -2401,7 +2401,7 @@ static int check_pte(
  47.143      {
  47.144          printk("eff_guest_pfn=%lx eff_guest_mfn=%lx shadow_mfn=%lx t=0x%08lx page_table_page=%d\n",
  47.145                 eff_guest_pfn, eff_guest_mfn, shadow_mfn,
  47.146 -               frame_table[eff_guest_mfn].u.inuse.type_info,
  47.147 +               pfn_to_page(eff_guest_mfn)->u.inuse.type_info,
  47.148                 page_table_page);
  47.149          FAIL("RW coherence");
  47.150      }
  47.151 @@ -2412,7 +2412,7 @@ static int check_pte(
  47.152      {
  47.153          printk("eff_guest_pfn=%lx eff_guest_mfn=%lx shadow_mfn=%lx t=0x%08lx page_table_page=%d\n",
  47.154                 eff_guest_pfn, eff_guest_mfn, shadow_mfn,
  47.155 -               frame_table[eff_guest_mfn].u.inuse.type_info,
  47.156 +               pfn_to_page(eff_guest_mfn)->u.inuse.type_info,
  47.157                 page_table_page);
  47.158          FAIL("RW2 coherence");
  47.159      }
  47.160 @@ -2781,7 +2781,7 @@ static unsigned long shadow_l3_table(
  47.161           * When we free L2 pages, we need to tell if the page contains
  47.162           * Xen private mappings. Use the va_mask part.
  47.163           */
  47.164 -        frame_table[s2mfn].u.inuse.type_info |= 
  47.165 +        pfn_to_page(s2mfn)->u.inuse.type_info |= 
  47.166              (unsigned long) 3 << PGT_score_shift; 
  47.167  
  47.168          memset(spl2e, 0, 
  47.169 @@ -2794,7 +2794,7 @@ static unsigned long shadow_l3_table(
  47.170          for ( i = 0; i < PDPT_L2_ENTRIES; i++ )
  47.171              spl2e[l2_table_offset(PERDOMAIN_VIRT_START) + i] =
  47.172                  l2e_from_page(
  47.173 -                    virt_to_page(page_get_owner(&frame_table[gmfn])->arch.mm_perdomain_pt) + i, 
  47.174 +                    virt_to_page(page_get_owner(pfn_to_page(gmfn))->arch.mm_perdomain_pt) + i, 
  47.175                      __PAGE_HYPERVISOR);
  47.176          for ( i = 0; i < (LINEARPT_MBYTES >> (L2_PAGETABLE_SHIFT - 20)); i++ )
  47.177              spl2e[l2_table_offset(LINEAR_PT_VIRT_START) + i] =
  47.178 @@ -2896,7 +2896,7 @@ static unsigned long shadow_l4_table(
  47.179             ROOT_PAGETABLE_XEN_SLOTS * sizeof(l4_pgentry_t));
  47.180  
  47.181          spl4e[l4_table_offset(PERDOMAIN_VIRT_START)] =
  47.182 -            l4e_from_paddr(__pa(page_get_owner(&frame_table[gmfn])->arch.mm_perdomain_l3),
  47.183 +            l4e_from_paddr(__pa(page_get_owner(pfn_to_page(gmfn))->arch.mm_perdomain_l3),
  47.184                              __PAGE_HYPERVISOR);
  47.185  
  47.186          if ( shadow_mode_translate(d) ) // NB: not external
    48.1 --- a/xen/arch/x86/shadow32.c	Tue Dec 20 17:16:15 2005 +0000
    48.2 +++ b/xen/arch/x86/shadow32.c	Tue Dec 20 17:16:24 2005 +0000
    48.3 @@ -30,7 +30,7 @@
    48.4  #include <xen/sched.h>
    48.5  #include <xen/trace.h>
    48.6  
    48.7 -#define MFN_PINNED(_x) (frame_table[_x].u.inuse.type_info & PGT_pinned)
    48.8 +#define MFN_PINNED(_x) (pfn_to_page(_x)->u.inuse.type_info & PGT_pinned)
    48.9  #define va_to_l1mfn(_ed, _va) \
   48.10      (l2e_get_pfn(linear_l2_table(_ed)[_va>>L2_PAGETABLE_SHIFT]))
   48.11  
   48.12 @@ -144,11 +144,11 @@ shadow_demote(struct domain *d, unsigned
   48.13      if ( !shadow_mode_refcounts(d) )
   48.14          return;
   48.15  
   48.16 -    ASSERT(frame_table[gmfn].count_info & PGC_page_table);
   48.17 +    ASSERT(pfn_to_page(gmfn)->count_info & PGC_page_table);
   48.18  
   48.19      if ( shadow_max_pgtable_type(d, gpfn, NULL) == PGT_none )
   48.20      {
   48.21 -        clear_bit(_PGC_page_table, &frame_table[gmfn].count_info);
   48.22 +        clear_bit(_PGC_page_table, &pfn_to_page(gmfn)->count_info);
   48.23  
   48.24          if ( page_out_of_sync(pfn_to_page(gmfn)) )
   48.25          {
   48.26 @@ -380,7 +380,7 @@ free_shadow_l2_table(struct domain *d, u
   48.27  
   48.28  void free_shadow_page(unsigned long smfn)
   48.29  {
   48.30 -    struct pfn_info *page = &frame_table[smfn];
   48.31 +    struct pfn_info *page = pfn_to_page(smfn);
   48.32      unsigned long gmfn = page->u.inuse.type_info & PGT_mfn_mask;
   48.33      struct domain *d = page_get_owner(pfn_to_page(gmfn));
   48.34      unsigned long gpfn = __mfn_to_gpfn(d, gmfn);
   48.35 @@ -465,8 +465,8 @@ release_out_of_sync_entry(struct domain 
   48.36  {
   48.37      struct pfn_info *page;
   48.38  
   48.39 -    page = &frame_table[entry->gmfn];
   48.40 -        
   48.41 +    page = pfn_to_page(entry->gmfn);
   48.42 +
   48.43      // Decrement ref count of guest & shadow pages
   48.44      //
   48.45      put_page(page);
   48.46 @@ -795,7 +795,7 @@ void free_monitor_pagetable(struct vcpu 
   48.47       */
   48.48      mfn = pagetable_get_pfn(v->arch.monitor_table);
   48.49      unmap_domain_page(v->arch.monitor_vtable);
   48.50 -    free_domheap_page(&frame_table[mfn]);
   48.51 +    free_domheap_page(pfn_to_page(mfn));
   48.52  
   48.53      v->arch.monitor_table = mk_pagetable(0);
   48.54      v->arch.monitor_vtable = 0;
   48.55 @@ -1018,8 +1018,8 @@ int __shadow_mode_enable(struct domain *
   48.56          {
   48.57              // external guests provide their own memory for their P2M maps.
   48.58              //
   48.59 -            ASSERT( d == page_get_owner(
   48.60 -                        &frame_table[pagetable_get_pfn(d->arch.phys_table)]) );
   48.61 +            ASSERT(d == page_get_owner(pfn_to_page(pagetable_get_pfn(
   48.62 +                d->arch.phys_table))));
   48.63          }
   48.64      }
   48.65  
   48.66 @@ -1543,7 +1543,7 @@ static unsigned long shadow_l2_table(
   48.67              l2e_from_pfn(smfn, __PAGE_HYPERVISOR);
   48.68  
   48.69          spl2e[l2_table_offset(PERDOMAIN_VIRT_START)] =
   48.70 -            l2e_from_paddr(__pa(page_get_owner(&frame_table[gmfn])->arch.mm_perdomain_pt),
   48.71 +            l2e_from_paddr(__pa(page_get_owner(pfn_to_page(gmfn))->arch.mm_perdomain_pt),
   48.72                              __PAGE_HYPERVISOR);
   48.73  
   48.74          if ( shadow_mode_translate(d) ) // NB: not external
   48.75 @@ -1675,7 +1675,7 @@ void shadow_map_l1_into_current_l2(unsig
   48.76              set_guest_back_ptr(d, sl1e, sl1mfn, i);
   48.77          }
   48.78  
   48.79 -        frame_table[sl1mfn].tlbflush_timestamp =
   48.80 +        pfn_to_page(sl1mfn)->tlbflush_timestamp =
   48.81              SHADOW_ENCODE_MIN_MAX(min, max);
   48.82      }
   48.83  }
   48.84 @@ -1758,7 +1758,7 @@ shadow_make_snapshot(
   48.85      u32 min_max = 0;
   48.86      int min, max, length;
   48.87  
   48.88 -    if ( test_and_set_bit(_PGC_out_of_sync, &frame_table[gmfn].count_info) )
   48.89 +    if ( test_and_set_bit(_PGC_out_of_sync, &pfn_to_page(gmfn)->count_info) )
   48.90      {
   48.91          ASSERT(__shadow_status(d, gpfn, PGT_snapshot));
   48.92          return SHADOW_SNAPSHOT_ELSEWHERE;
   48.93 @@ -1809,7 +1809,7 @@ shadow_free_snapshot(struct domain *d, s
   48.94  
   48.95      // Clear the out_of_sync bit.
   48.96      //
   48.97 -    clear_bit(_PGC_out_of_sync, &frame_table[entry->gmfn].count_info);
   48.98 +    clear_bit(_PGC_out_of_sync, &pfn_to_page(entry->gmfn)->count_info);
   48.99  
  48.100      // XXX Need to think about how to protect the domain's
  48.101      // information less expensively.
  48.102 @@ -1826,7 +1826,7 @@ struct out_of_sync_entry *
  48.103                               unsigned long mfn)
  48.104  {
  48.105      struct domain *d = v->domain;
  48.106 -    struct pfn_info *page = &frame_table[mfn];
  48.107 +    struct pfn_info *page = pfn_to_page(mfn);
  48.108      struct out_of_sync_entry *entry = shadow_alloc_oos_entry(d);
  48.109  
  48.110      ASSERT(shadow_lock_is_acquired(d));
  48.111 @@ -1992,7 +1992,7 @@ int __shadow_out_of_sync(struct vcpu *v,
  48.112  
  48.113      perfc_incrc(shadow_out_of_sync_calls);
  48.114  
  48.115 -    if ( page_out_of_sync(&frame_table[l2mfn]) &&
  48.116 +    if ( page_out_of_sync(pfn_to_page(l2mfn)) &&
  48.117           !snapshot_entry_matches(d, (l1_pgentry_t *)v->arch.guest_vtable,
  48.118                                   l2pfn, l2_table_offset(va)) )
  48.119          return 1;
  48.120 @@ -2008,7 +2008,7 @@ int __shadow_out_of_sync(struct vcpu *v,
  48.121      if ( !VALID_MFN(l1mfn) )
  48.122          return 0;
  48.123  
  48.124 -    if ( page_out_of_sync(&frame_table[l1mfn]) &&
  48.125 +    if ( page_out_of_sync(pfn_to_page(l1mfn)) &&
  48.126           !snapshot_entry_matches(
  48.127               d, &linear_pg_table[l1_linear_offset(va) & ~(L1_PAGETABLE_ENTRIES-1)],
  48.128               l1pfn, l1_table_offset(va)) )
  48.129 @@ -2136,13 +2136,13 @@ static u32 remove_all_write_access_in_pt
  48.130      int i;
  48.131      u32 found = 0;
  48.132      int is_l1_shadow =
  48.133 -        ((frame_table[pt_mfn].u.inuse.type_info & PGT_type_mask) ==
  48.134 +        ((pfn_to_page(pt_mfn)->u.inuse.type_info & PGT_type_mask) ==
  48.135           PGT_l1_shadow);
  48.136  
  48.137      match = l1e_from_pfn(readonly_gmfn, flags);
  48.138  
  48.139      if ( shadow_mode_external(d) ) {
  48.140 -        i = (frame_table[readonly_gmfn].u.inuse.type_info & PGT_va_mask) 
  48.141 +        i = (pfn_to_page(readonly_gmfn)->u.inuse.type_info & PGT_va_mask) 
  48.142              >> PGT_va_shift;
  48.143  
  48.144          if ( (i >= 0 && i < L1_PAGETABLE_ENTRIES) &&
  48.145 @@ -2180,7 +2180,7 @@ int shadow_remove_all_write_access(
  48.146  
  48.147      // If it's not a writable page, then no writable refs can be outstanding.
  48.148      //
  48.149 -    if ( (frame_table[readonly_gmfn].u.inuse.type_info & PGT_type_mask) !=
  48.150 +    if ( (pfn_to_page(readonly_gmfn)->u.inuse.type_info & PGT_type_mask) !=
  48.151           PGT_writable_page )
  48.152      {
  48.153          perfc_incrc(remove_write_not_writable);
  48.154 @@ -2190,7 +2190,7 @@ int shadow_remove_all_write_access(
  48.155      // How many outstanding writable PTEs for this page are there?
  48.156      //
  48.157      write_refs =
  48.158 -        (frame_table[readonly_gmfn].u.inuse.type_info & PGT_count_mask);
  48.159 +        (pfn_to_page(readonly_gmfn)->u.inuse.type_info & PGT_count_mask);
  48.160      if ( write_refs && MFN_PINNED(readonly_gmfn) )
  48.161      {
  48.162          write_refs--;
  48.163 @@ -2208,7 +2208,7 @@ int shadow_remove_all_write_access(
  48.164  
  48.165           // Use the back pointer to locate the shadow page that can contain
  48.166           // the PTE of interest
  48.167 -         if ( (predicted_smfn = frame_table[readonly_gmfn].tlbflush_timestamp) ) {
  48.168 +         if ( (predicted_smfn = pfn_to_page(readonly_gmfn)->tlbflush_timestamp) ) {
  48.169               found += remove_all_write_access_in_ptpage(
  48.170                   d, predicted_smfn, predicted_smfn, readonly_gpfn, readonly_gmfn, write_refs, 0);
  48.171               if ( found == write_refs )
  48.172 @@ -2249,7 +2249,7 @@ static u32 remove_all_access_in_page(
  48.173      int i;
  48.174      u32 count = 0;
  48.175      int is_l1_shadow =
  48.176 -        ((frame_table[l1mfn].u.inuse.type_info & PGT_type_mask) ==
  48.177 +        ((pfn_to_page(l1mfn)->u.inuse.type_info & PGT_type_mask) ==
  48.178           PGT_l1_shadow);
  48.179  
  48.180      match = l1e_from_pfn(forbidden_gmfn, flags);
  48.181 @@ -2266,7 +2266,7 @@ static u32 remove_all_access_in_page(
  48.182          if ( is_l1_shadow )
  48.183              shadow_put_page_from_l1e(ol2e, d);
  48.184          else /* must be an hl2 page */
  48.185 -            put_page(&frame_table[forbidden_gmfn]);
  48.186 +            put_page(pfn_to_page(forbidden_gmfn));
  48.187      }
  48.188  
  48.189      unmap_domain_page(pl1e);
  48.190 @@ -2982,6 +2982,23 @@ void __update_pagetables(struct vcpu *v)
  48.191      }
  48.192  }
  48.193  
  48.194 +void clear_all_shadow_status(struct domain *d)
  48.195 +{
  48.196 +    shadow_lock(d);
  48.197 +    free_shadow_pages(d);
  48.198 +    free_shadow_ht_entries(d);
  48.199 +    d->arch.shadow_ht = 
  48.200 +        xmalloc_array(struct shadow_status, shadow_ht_buckets);
  48.201 +    if ( d->arch.shadow_ht == NULL ) {
  48.202 +        printk("clear all shadow status:xmalloc fail\n");
  48.203 +        domain_crash_synchronous();
  48.204 +    }
  48.205 +    memset(d->arch.shadow_ht, 0,
  48.206 +           shadow_ht_buckets * sizeof(struct shadow_status));
  48.207 +
  48.208 +    free_out_of_sync_entries(d);
  48.209 +    shadow_unlock(d);
  48.210 +}
  48.211  
  48.212  /************************************************************************/
  48.213  /************************************************************************/
  48.214 @@ -3139,7 +3156,7 @@ static int check_pte(
  48.215      {
  48.216          printk("eff_guest_pfn=%lx eff_guest_mfn=%lx shadow_mfn=%lx t=%lx page_table_page=%d\n",
  48.217                 eff_guest_pfn, eff_guest_mfn, shadow_mfn,
  48.218 -               frame_table[eff_guest_mfn].u.inuse.type_info,
  48.219 +               pfn_to_page(eff_guest_mfn)->u.inuse.type_info,
  48.220                 page_table_page);
  48.221          FAIL("RW coherence");
  48.222      }
  48.223 @@ -3150,7 +3167,7 @@ static int check_pte(
  48.224      {
  48.225          printk("eff_guest_pfn=%lx eff_guest_mfn=%lx shadow_mfn=%lx t=%lx page_table_page=%d\n",
  48.226                 eff_guest_pfn, eff_guest_mfn, shadow_mfn,
  48.227 -               frame_table[eff_guest_mfn].u.inuse.type_info,
  48.228 +               pfn_to_page(eff_guest_mfn)->u.inuse.type_info,
  48.229                 page_table_page);
  48.230          FAIL("RW2 coherence");
  48.231      }
    49.1 --- a/xen/arch/x86/shadow_public.c	Tue Dec 20 17:16:15 2005 +0000
    49.2 +++ b/xen/arch/x86/shadow_public.c	Tue Dec 20 17:16:24 2005 +0000
    49.3 @@ -168,14 +168,14 @@ free_shadow_tables(struct domain *d, uns
    49.4  #if CONFIG_PAGING_LEVELS >=3
    49.5      if ( d->arch.ops->guest_paging_levels == PAGING_L2 )
    49.6      {
    49.7 -        struct pfn_info *page = &frame_table[smfn];
    49.8 +        struct pfn_info *page = pfn_to_page(smfn);
    49.9          for ( i = 0; i < PDP_ENTRIES; i++ )
   49.10          {
   49.11              if ( entry_get_flags(ple[i]) & _PAGE_PRESENT )
   49.12                  free_fake_shadow_l2(d,entry_get_pfn(ple[i]));
   49.13          }
   49.14  
   49.15 -        page = &frame_table[entry_get_pfn(ple[0])];
   49.16 +        page = pfn_to_page(entry_get_pfn(ple[0]));
   49.17          free_domheap_pages(page, SL2_ORDER);
   49.18          unmap_domain_page(ple);
   49.19      }
   49.20 @@ -208,7 +208,7 @@ free_shadow_tables(struct domain *d, uns
   49.21                      break;
   49.22                  if ( level == PAGING_L2 )
   49.23                  {
   49.24 -                    struct pfn_info *page = &frame_table[smfn]; 
   49.25 +                    struct pfn_info *page = pfn_to_page(smfn);
   49.26                      if ( is_xen_l2_slot(page->u.inuse.type_info, i) )
   49.27                          continue;
   49.28                  }
   49.29 @@ -299,7 +299,7 @@ void free_monitor_pagetable(struct vcpu 
   49.30       */
   49.31      mfn = pagetable_get_pfn(v->arch.monitor_table);
   49.32      unmap_domain_page(v->arch.monitor_vtable);
   49.33 -    free_domheap_page(&frame_table[mfn]);
   49.34 +    free_domheap_page(pfn_to_page(mfn));
   49.35  
   49.36      v->arch.monitor_table = mk_pagetable(0);
   49.37      v->arch.monitor_vtable = 0;
   49.38 @@ -394,7 +394,7 @@ void free_monitor_pagetable(struct vcpu 
   49.39       */
   49.40      mfn = pagetable_get_pfn(v->arch.monitor_table);
   49.41      unmap_domain_page(v->arch.monitor_vtable);
   49.42 -    free_domheap_page(&frame_table[mfn]);
   49.43 +    free_domheap_page(pfn_to_page(mfn));
   49.44  
   49.45      v->arch.monitor_table = mk_pagetable(0);
   49.46      v->arch.monitor_vtable = 0;
   49.47 @@ -411,7 +411,7 @@ shadow_free_snapshot(struct domain *d, s
   49.48  
   49.49      // Clear the out_of_sync bit.
   49.50      //
   49.51 -    clear_bit(_PGC_out_of_sync, &frame_table[entry->gmfn].count_info);
   49.52 +    clear_bit(_PGC_out_of_sync, &pfn_to_page(entry->gmfn)->count_info);
   49.53  
   49.54      // XXX Need to think about how to protect the domain's
   49.55      // information less expensively.
   49.56 @@ -428,7 +428,7 @@ release_out_of_sync_entry(struct domain 
   49.57  {
   49.58      struct pfn_info *page;
   49.59  
   49.60 -    page = &frame_table[entry->gmfn];
   49.61 +    page = pfn_to_page(entry->gmfn);
   49.62          
   49.63      // Decrement ref count of guest & shadow pages
   49.64      //
   49.65 @@ -501,11 +501,11 @@ shadow_demote(struct domain *d, unsigned
   49.66      if ( !shadow_mode_refcounts(d) )
   49.67          return;
   49.68  
   49.69 -    ASSERT(frame_table[gmfn].count_info & PGC_page_table);
   49.70 +    ASSERT(pfn_to_page(gmfn)->count_info & PGC_page_table);
   49.71  
   49.72      if ( shadow_max_pgtable_type(d, gpfn, NULL) == PGT_none )
   49.73      {
   49.74 -        clear_bit(_PGC_page_table, &frame_table[gmfn].count_info);
   49.75 +        clear_bit(_PGC_page_table, &pfn_to_page(gmfn)->count_info);
   49.76  
   49.77          if ( page_out_of_sync(pfn_to_page(gmfn)) )
   49.78          {
   49.79 @@ -600,7 +600,7 @@ void free_fake_shadow_l2(struct domain *
   49.80  
   49.81  void free_shadow_page(unsigned long smfn)
   49.82  {
   49.83 -    struct pfn_info *page = &frame_table[smfn];
   49.84 +    struct pfn_info *page = pfn_to_page(smfn);
   49.85  
   49.86      unsigned long gmfn = page->u.inuse.type_info & PGT_mfn_mask;
   49.87      struct domain *d = page_get_owner(pfn_to_page(gmfn));
   49.88 @@ -1067,8 +1067,8 @@ int __shadow_mode_enable(struct domain *
   49.89          {
   49.90              // external guests provide their own memory for their P2M maps.
   49.91              //
   49.92 -            ASSERT( d == page_get_owner(
   49.93 -                &frame_table[pagetable_get_pfn(d->arch.phys_table)]) );
   49.94 +            ASSERT(d == page_get_owner(pfn_to_page(pagetable_get_pfn(
   49.95 +                d->arch.phys_table))));
   49.96          }
   49.97      }
   49.98  
   49.99 @@ -1643,7 +1643,7 @@ static u32 remove_all_access_in_page(
  49.100      int i;
  49.101      u32 count = 0;
  49.102      int is_l1_shadow =
  49.103 -        ((frame_table[l1mfn].u.inuse.type_info & PGT_type_mask) ==
  49.104 +        ((pfn_to_page(l1mfn)->u.inuse.type_info & PGT_type_mask) ==
  49.105           PGT_l1_shadow);
  49.106  
  49.107      match = l1e_from_pfn(forbidden_gmfn, flags);
  49.108 @@ -1660,7 +1660,7 @@ static u32 remove_all_access_in_page(
  49.109          if ( is_l1_shadow )
  49.110              shadow_put_page_from_l1e(ol2e, d);
  49.111          else /* must be an hl2 page */
  49.112 -            put_page(&frame_table[forbidden_gmfn]);
  49.113 +            put_page(pfn_to_page(forbidden_gmfn));
  49.114      }
  49.115  
  49.116      unmap_domain_page(pl1e);
  49.117 @@ -1747,6 +1747,24 @@ void shadow_sync_and_drop_references(
  49.118      shadow_unlock(d);
  49.119  }
  49.120  
  49.121 +void clear_all_shadow_status(struct domain *d)
  49.122 +{
  49.123 +    shadow_lock(d);
  49.124 +    free_shadow_pages(d);
  49.125 +    free_shadow_ht_entries(d);
  49.126 +    d->arch.shadow_ht = 
  49.127 +        xmalloc_array(struct shadow_status, shadow_ht_buckets);
  49.128 +    if ( d->arch.shadow_ht == NULL ) {
  49.129 +        printk("clear all shadow status:xmalloc fail\n");
  49.130 +        domain_crash_synchronous();
  49.131 +    }
  49.132 +    memset(d->arch.shadow_ht, 0,
  49.133 +           shadow_ht_buckets * sizeof(struct shadow_status));
  49.134 +
  49.135 +    free_out_of_sync_entries(d);
  49.136 +    shadow_unlock(d);
  49.137 +}
  49.138 +
  49.139  /*
  49.140   * Local variables:
  49.141   * mode: C
    50.1 --- a/xen/arch/x86/traps.c	Tue Dec 20 17:16:15 2005 +0000
    50.2 +++ b/xen/arch/x86/traps.c	Tue Dec 20 17:16:24 2005 +0000
    50.3 @@ -1074,29 +1074,35 @@ asmlinkage int do_general_protection(str
    50.4      return 0;
    50.5  }
    50.6  
    50.7 -unsigned long nmi_softirq_reason;
    50.8 -static void nmi_softirq(void)
    50.9 +
   50.10 +/* Defer dom0 notification to softirq context (unsafe in NMI context). */
   50.11 +static unsigned long nmi_dom0_softirq_reason;
   50.12 +#define NMI_DOM0_PARITY_ERR 0
   50.13 +#define NMI_DOM0_IO_ERR     1
   50.14 +#define NMI_DOM0_UNKNOWN    2
   50.15 +
   50.16 +static void nmi_dom0_softirq(void)
   50.17  {
   50.18      if ( dom0 == NULL )
   50.19          return;
   50.20  
   50.21 -    if ( test_and_clear_bit(0, &nmi_softirq_reason) )
   50.22 +    if ( test_and_clear_bit(NMI_DOM0_PARITY_ERR, &nmi_dom0_softirq_reason) )
   50.23          send_guest_virq(dom0->vcpu[0], VIRQ_PARITY_ERR);
   50.24  
   50.25 -    if ( test_and_clear_bit(1, &nmi_softirq_reason) )
   50.26 +    if ( test_and_clear_bit(NMI_DOM0_IO_ERR, &nmi_dom0_softirq_reason) )
   50.27          send_guest_virq(dom0->vcpu[0], VIRQ_IO_ERR);
   50.28 +
   50.29 +    if ( test_and_clear_bit(NMI_DOM0_UNKNOWN, &nmi_dom0_softirq_reason) )
   50.30 +        send_guest_virq(dom0->vcpu[0], VIRQ_NMI);
   50.31  }
   50.32  
   50.33  asmlinkage void mem_parity_error(struct cpu_user_regs *regs)
   50.34  {
   50.35 -    /* Clear and disable the parity-error line. */
   50.36 -    outb((inb(0x61)&15)|4,0x61);
   50.37 -
   50.38      switch ( opt_nmi[0] )
   50.39      {
   50.40      case 'd': /* 'dom0' */
   50.41 -        set_bit(0, &nmi_softirq_reason);
   50.42 -        raise_softirq(NMI_SOFTIRQ);
   50.43 +        set_bit(NMI_DOM0_PARITY_ERR, &nmi_dom0_softirq_reason);
   50.44 +        raise_softirq(NMI_DOM0_SOFTIRQ);
   50.45      case 'i': /* 'ignore' */
   50.46          break;
   50.47      default:  /* 'fatal' */
   50.48 @@ -1104,18 +1110,19 @@ asmlinkage void mem_parity_error(struct 
   50.49          printk("\n\nNMI - MEMORY ERROR\n");
   50.50          fatal_trap(TRAP_nmi, regs);
   50.51      }
   50.52 +
   50.53 +    outb((inb(0x61) & 0x0f) | 0x04, 0x61); /* clear-and-disable parity check */
   50.54 +    mdelay(1);
   50.55 +    outb((inb(0x61) & 0x0b) | 0x00, 0x61); /* enable parity check */
   50.56  }
   50.57  
   50.58  asmlinkage void io_check_error(struct cpu_user_regs *regs)
   50.59  {
   50.60 -    /* Clear and disable the I/O-error line. */
   50.61 -    outb((inb(0x61)&15)|8,0x61);
   50.62 -
   50.63      switch ( opt_nmi[0] )
   50.64      {
   50.65      case 'd': /* 'dom0' */
   50.66 -        set_bit(0, &nmi_softirq_reason);
   50.67 -        raise_softirq(NMI_SOFTIRQ);
   50.68 +        set_bit(NMI_DOM0_IO_ERR, &nmi_dom0_softirq_reason);
   50.69 +        raise_softirq(NMI_DOM0_SOFTIRQ);
   50.70      case 'i': /* 'ignore' */
   50.71          break;
   50.72      default:  /* 'fatal' */
   50.73 @@ -1123,43 +1130,59 @@ asmlinkage void io_check_error(struct cp
   50.74          printk("\n\nNMI - I/O ERROR\n");
   50.75          fatal_trap(TRAP_nmi, regs);
   50.76      }
   50.77 +
   50.78 +    outb((inb(0x61) & 0x0f) | 0x08, 0x61); /* clear-and-disable IOCK */
   50.79 +    mdelay(1);
   50.80 +    outb((inb(0x61) & 0x07) | 0x00, 0x61); /* enable IOCK */
   50.81  }
   50.82  
   50.83  static void unknown_nmi_error(unsigned char reason)
   50.84  {
   50.85 -    printk("Uhhuh. NMI received for unknown reason %02x.\n", reason);
   50.86 -    printk("Dazed and confused, but trying to continue\n");
   50.87 -    printk("Do you have a strange power saving mode enabled?\n");
   50.88 -}
   50.89 -
   50.90 -static void default_do_nmi(struct cpu_user_regs *regs, unsigned long reason)
   50.91 -{
   50.92 -    if ( nmi_watchdog )
   50.93 -        nmi_watchdog_tick(regs);
   50.94 -
   50.95 -    if ( reason & 0x80 )
   50.96 -        mem_parity_error(regs);
   50.97 -    else if ( reason & 0x40 )
   50.98 -        io_check_error(regs);
   50.99 -    else if ( !nmi_watchdog )
  50.100 -        unknown_nmi_error((unsigned char)(reason&0xff));
  50.101 +    switch ( opt_nmi[0] )
  50.102 +    {
  50.103 +    case 'd': /* 'dom0' */
  50.104 +        set_bit(NMI_DOM0_UNKNOWN, &nmi_dom0_softirq_reason);
  50.105 +        raise_softirq(NMI_DOM0_SOFTIRQ);
  50.106 +    case 'i': /* 'ignore' */
  50.107 +        break;
  50.108 +    default:  /* 'fatal' */
  50.109 +        printk("Uhhuh. NMI received for unknown reason %02x.\n", reason);
  50.110 +        printk("Dazed and confused, but trying to continue\n");
  50.111 +        printk("Do you have a strange power saving mode enabled?\n");
  50.112 +    }
  50.113  }
  50.114  
  50.115  static int dummy_nmi_callback(struct cpu_user_regs *regs, int cpu)
  50.116  {
  50.117 -	return 0;
  50.118 +    return 0;
  50.119  }
  50.120   
  50.121  static nmi_callback_t nmi_callback = dummy_nmi_callback;
  50.122   
  50.123 -asmlinkage void do_nmi(struct cpu_user_regs *regs, unsigned long reason)
  50.124 +asmlinkage void do_nmi(struct cpu_user_regs *regs)
  50.125  {
  50.126      unsigned int cpu = smp_processor_id();
  50.127 +    unsigned char reason;
  50.128  
  50.129      ++nmi_count(cpu);
  50.130  
  50.131 -	if ( !nmi_callback(regs, cpu) )
  50.132 -		default_do_nmi(regs, reason);
  50.133 +    if ( nmi_callback(regs, cpu) )
  50.134 +        return;
  50.135 +
  50.136 +    if ( nmi_watchdog )
  50.137 +        nmi_watchdog_tick(regs);
  50.138 +
  50.139 +    /* Only the BSP gets external NMIs from the system. */
  50.140 +    if ( cpu == 0 )
  50.141 +    {
  50.142 +        reason = inb(0x61);
  50.143 +        if ( reason & 0x80 )
  50.144 +            mem_parity_error(regs);
  50.145 +        else if ( reason & 0x40 )
  50.146 +            io_check_error(regs);
  50.147 +        else if ( !nmi_watchdog )
  50.148 +            unknown_nmi_error((unsigned char)(reason&0xff));
  50.149 +    }
  50.150  }
  50.151  
  50.152  void set_nmi_callback(nmi_callback_t callback)
  50.153 @@ -1169,7 +1192,7 @@ void set_nmi_callback(nmi_callback_t cal
  50.154  
  50.155  void unset_nmi_callback(void)
  50.156  {
  50.157 -	nmi_callback = dummy_nmi_callback;
  50.158 +    nmi_callback = dummy_nmi_callback;
  50.159  }
  50.160  
  50.161  asmlinkage int math_state_restore(struct cpu_user_regs *regs)
  50.162 @@ -1318,7 +1341,7 @@ void __init trap_init(void)
  50.163  
  50.164      cpu_init();
  50.165  
  50.166 -    open_softirq(NMI_SOFTIRQ, nmi_softirq);
  50.167 +    open_softirq(NMI_DOM0_SOFTIRQ, nmi_dom0_softirq);
  50.168  }
  50.169  
  50.170  
    51.1 --- a/xen/arch/x86/vmx.c	Tue Dec 20 17:16:15 2005 +0000
    51.2 +++ b/xen/arch/x86/vmx.c	Tue Dec 20 17:16:24 2005 +0000
    51.3 @@ -102,7 +102,8 @@ void vmx_relinquish_resources(struct vcp
    51.4      if (v->vcpu_id == 0) {
    51.5          /* unmap IO shared page */
    51.6          struct domain *d = v->domain;
    51.7 -        unmap_domain_page((void *)d->arch.vmx_platform.shared_page_va);
    51.8 +        if ( d->arch.vmx_platform.shared_page_va )
    51.9 +            unmap_domain_page((void *)d->arch.vmx_platform.shared_page_va);
   51.10      }
   51.11  
   51.12      destroy_vmcs(&v->arch.arch_vmx);
   51.13 @@ -110,12 +111,12 @@ void vmx_relinquish_resources(struct vcp
   51.14      vpit = &v->domain->arch.vmx_platform.vmx_pit;
   51.15      if ( active_ac_timer(&(vpit->pit_timer)) )
   51.16          rem_ac_timer(&vpit->pit_timer);
   51.17 -    if ( active_ac_timer(&v->arch.arch_vmx.hlt_timer) ) {
   51.18 +    if ( active_ac_timer(&v->arch.arch_vmx.hlt_timer) )
   51.19          rem_ac_timer(&v->arch.arch_vmx.hlt_timer);
   51.20 -    }
   51.21 -    if ( vmx_apic_support(v->domain) ) {
   51.22 -        rem_ac_timer( &(VLAPIC(v)->vlapic_timer) );
   51.23 -        xfree( VLAPIC(v) );
   51.24 +    if ( vmx_apic_support(v->domain) && (VLAPIC(v) != NULL) )
   51.25 +    {
   51.26 +        rem_ac_timer(&VLAPIC(v)->vlapic_timer);
   51.27 +        xfree(VLAPIC(v));
   51.28      }
   51.29  }
   51.30  
   51.31 @@ -334,7 +335,7 @@ static inline int  long_mode_do_msr_writ
   51.32  
   51.33  extern long evtchn_send(int lport);
   51.34  extern long do_block(void);
   51.35 -void do_nmi(struct cpu_user_regs *, unsigned long);
   51.36 +void do_nmi(struct cpu_user_regs *);
   51.37  
   51.38  static int check_vmx_controls(ctrls, msr)
   51.39  {
   51.40 @@ -543,6 +544,13 @@ static void vmx_vmexit_do_cpuid(unsigned
   51.41          clear_bit(X86_FEATURE_VMXE & 31, &ecx);
   51.42          clear_bit(X86_FEATURE_MWAIT & 31, &ecx);
   51.43      }
   51.44 +#ifdef __i386__
   51.45 +    else if ( input == 0x80000001 )
   51.46 +    {
   51.47 +        /* Mask feature for Intel ia32e or AMD long mode. */
   51.48 +        clear_bit(X86_FEATURE_LM & 31, &edx);
   51.49 +    }
   51.50 +#endif
   51.51  
   51.52      regs->eax = (unsigned long) eax;
   51.53      regs->ebx = (unsigned long) ebx;
   51.54 @@ -1223,6 +1231,7 @@ static int vmx_set_cr0(unsigned long val
   51.55              }
   51.56          }
   51.57  
   51.58 +        clear_all_shadow_status(v->domain);
   51.59          if (vmx_assist(v, VMX_ASSIST_INVOKE)) {
   51.60              set_bit(VMX_CPU_STATE_ASSIST_ENABLED, &v->arch.arch_vmx.cpu_state);
   51.61              __vmread(GUEST_RIP, &eip);
   51.62 @@ -1841,7 +1850,7 @@ asmlinkage void vmx_vmexit_handler(struc
   51.63              break;
   51.64          }
   51.65          case TRAP_nmi:
   51.66 -            do_nmi(&regs, 0);
   51.67 +            do_nmi(&regs);
   51.68              break;
   51.69          default:
   51.70              vmx_reflect_exception(v);
    52.1 --- a/xen/arch/x86/vmx_intercept.c	Tue Dec 20 17:16:15 2005 +0000
    52.2 +++ b/xen/arch/x86/vmx_intercept.c	Tue Dec 20 17:16:24 2005 +0000
    52.3 @@ -203,6 +203,12 @@ static void pit_cal_count(struct vmx_vir
    52.4      u64 nsec_delta = (unsigned int)((NOW() - vpit->inject_point));
    52.5      if (nsec_delta > vpit->period)
    52.6          VMX_DBG_LOG(DBG_LEVEL_1, "VMX_PIT:long time has passed from last injection!");
    52.7 +    if(vpit->init_val == 0)
    52.8 +    {
    52.9 +        printk("PIT init value == 0!\n");
   52.10 +        domain_crash_synchronous();
   52.11 +    }
   52.12 +
   52.13      vpit->count = vpit->init_val - ((nsec_delta * PIT_FREQ / 1000000000ULL) % vpit->init_val );
   52.14  }
   52.15  
    53.1 --- a/xen/arch/x86/x86_32/entry.S	Tue Dec 20 17:16:15 2005 +0000
    53.2 +++ b/xen/arch/x86/x86_32/entry.S	Tue Dec 20 17:16:24 2005 +0000
    53.3 @@ -601,15 +601,7 @@ ENTRY(nmi)
    53.4  	pushl %eax
    53.5  	SAVE_ALL_NOSEGREGS(a)
    53.6  
    53.7 -        # Check for hardware problems.
    53.8 -        inb   $0x61,%al
    53.9 -        testb $0x80,%al
   53.10 -        jne   nmi_parity_err
   53.11 -        testb $0x40,%al
   53.12 -        jne   nmi_io_err
   53.13 -        movl  %eax,%ebx
   53.14 -        
   53.15 -        # Okay, its almost a normal NMI tick. We can only process it if:
   53.16 +        # We can only process the NMI if:
   53.17          #  A. We are the outermost Xen activation (in which case we have
   53.18          #     the selectors safely saved on our stack)
   53.19          #  B. DS and ES contain sane Xen values.
   53.20 @@ -619,7 +611,7 @@ ENTRY(nmi)
   53.21          movl  UREGS_eflags(%esp),%eax
   53.22          movb  UREGS_cs(%esp),%al
   53.23          testl $(3|X86_EFLAGS_VM),%eax
   53.24 -        jnz   do_watchdog_tick
   53.25 +        jnz   continue_nmi
   53.26          movl  %ds,%eax
   53.27          cmpw  $(__HYPERVISOR_DS),%ax
   53.28          jne   defer_nmi
   53.29 @@ -627,15 +619,14 @@ ENTRY(nmi)
   53.30          cmpw  $(__HYPERVISOR_DS),%ax
   53.31          jne   defer_nmi
   53.32  
   53.33 -do_watchdog_tick:
   53.34 +continue_nmi:
   53.35          movl  $(__HYPERVISOR_DS),%edx
   53.36          movl  %edx,%ds
   53.37          movl  %edx,%es
   53.38          movl  %esp,%edx
   53.39 -        pushl %ebx   # reason
   53.40 -        pushl %edx   # regs
   53.41 +        pushl %edx
   53.42          call  do_nmi
   53.43 -        addl  $8,%esp
   53.44 +        addl  $4,%esp
   53.45          jmp   ret_from_intr
   53.46  
   53.47  defer_nmi:
   53.48 @@ -649,55 +640,6 @@ 1:      movl  %ss:APIC_ICR(%eax),%ebx
   53.49                  TRAP_deferred_nmi),%ss:APIC_ICR(%eax)
   53.50          jmp   restore_all_xen
   53.51  
   53.52 -nmi_parity_err:
   53.53 -        # Clear and disable the parity-error line
   53.54 -        andb $0xf,%al
   53.55 -        orb  $0x4,%al
   53.56 -        outb %al,$0x61
   53.57 -        cmpb $'i',%ss:opt_nmi # nmi=ignore
   53.58 -        je   nmi_out
   53.59 -        bts  $0,%ss:nmi_softirq_reason
   53.60 -        bts  $NMI_SOFTIRQ,%ss:irq_stat
   53.61 -        cmpb $'d',%ss:opt_nmi # nmi=dom0
   53.62 -        je   nmi_out
   53.63 -        movl $(__HYPERVISOR_DS),%edx       # nmi=fatal
   53.64 -        movl %edx,%ds
   53.65 -        movl %edx,%es
   53.66 -        movl %esp,%edx
   53.67 -        push %edx
   53.68 -        call mem_parity_error
   53.69 -        addl $4,%esp
   53.70 -nmi_out:movl  %ss:UREGS_eflags(%esp),%eax
   53.71 -        movb  %ss:UREGS_cs(%esp),%al
   53.72 -        testl $(3|X86_EFLAGS_VM),%eax
   53.73 -        jz    restore_all_xen
   53.74 -        movl  $(__HYPERVISOR_DS),%edx
   53.75 -        movl  %edx,%ds
   53.76 -        movl  %edx,%es
   53.77 -        GET_CURRENT(%ebx)
   53.78 -        jmp   test_all_events
   53.79 -                
   53.80 -nmi_io_err: 
   53.81 -        # Clear and disable the I/O-error line
   53.82 -        andb $0xf,%al
   53.83 -        orb  $0x8,%al
   53.84 -        outb %al,$0x61
   53.85 -        cmpb $'i',%ss:opt_nmi # nmi=ignore
   53.86 -        je   nmi_out
   53.87 -        bts  $1,%ss:nmi_softirq_reason
   53.88 -        bts  $NMI_SOFTIRQ,%ss:irq_stat
   53.89 -        cmpb $'d',%ss:opt_nmi # nmi=dom0
   53.90 -        je   nmi_out
   53.91 -        movl $(__HYPERVISOR_DS),%edx       # nmi=fatal
   53.92 -        movl %edx,%ds
   53.93 -        movl %edx,%es
   53.94 -        movl %esp,%edx
   53.95 -        push %edx
   53.96 -        call io_check_error                        
   53.97 -        addl $4,%esp
   53.98 -        jmp  nmi_out
   53.99 -
  53.100 -
  53.101  ENTRY(setup_vm86_frame)
  53.102          # Copies the entire stack frame forwards by 16 bytes.
  53.103          .macro copy_vm86_words count=18
    54.1 --- a/xen/arch/x86/x86_32/mm.c	Tue Dec 20 17:16:15 2005 +0000
    54.2 +++ b/xen/arch/x86/x86_32/mm.c	Tue Dec 20 17:16:24 2005 +0000
    54.3 @@ -177,10 +177,11 @@ void subarch_init_memory(struct domain *
    54.4              idle_pg_table_l2[l2_linear_offset(RDWR_MPT_VIRT_START) + i]);
    54.5          for ( j = 0; j < L2_PAGETABLE_ENTRIES; j++ )
    54.6          {
    54.7 -            frame_table[m2p_start_mfn+j].count_info = PGC_allocated | 1;
    54.8 +            struct pfn_info *page = pfn_to_page(m2p_start_mfn + j);
    54.9 +            page->count_info = PGC_allocated | 1;
   54.10              /* Ensure it's only mapped read-only by domains. */
   54.11 -            frame_table[m2p_start_mfn+j].u.inuse.type_info = PGT_gdt_page | 1;
   54.12 -            page_set_owner(&frame_table[m2p_start_mfn+j], dom_xen);
   54.13 +            page->u.inuse.type_info = PGT_gdt_page | 1;
   54.14 +            page_set_owner(page, dom_xen);
   54.15          }
   54.16      }
   54.17  }
    55.1 --- a/xen/arch/x86/x86_32/traps.c	Tue Dec 20 17:16:15 2005 +0000
    55.2 +++ b/xen/arch/x86/x86_32/traps.c	Tue Dec 20 17:16:24 2005 +0000
    55.3 @@ -160,9 +160,9 @@ asmlinkage void do_double_fault(void)
    55.4  BUILD_SMP_INTERRUPT(deferred_nmi, TRAP_deferred_nmi)
    55.5  asmlinkage void smp_deferred_nmi(struct cpu_user_regs regs)
    55.6  {
    55.7 -    asmlinkage void do_nmi(struct cpu_user_regs *, unsigned long);
    55.8 +    asmlinkage void do_nmi(struct cpu_user_regs *);
    55.9      ack_APIC_irq();
   55.10 -    do_nmi(&regs, 0);
   55.11 +    do_nmi(&regs);
   55.12  }
   55.13  
   55.14  void __init percpu_traps_init(void)
    56.1 --- a/xen/arch/x86/x86_64/entry.S	Tue Dec 20 17:16:15 2005 +0000
    56.2 +++ b/xen/arch/x86/x86_64/entry.S	Tue Dec 20 17:16:24 2005 +0000
    56.3 @@ -567,9 +567,7 @@ ENTRY(double_fault)
    56.4  ENTRY(nmi)
    56.5          pushq $0
    56.6          SAVE_ALL
    56.7 -        inb   $0x61,%al
    56.8 -        movl  %eax,%esi # reason
    56.9 -        movq  %rsp,%rdi # regs
   56.10 +        movq  %rsp,%rdi
   56.11          call  do_nmi
   56.12  	jmp   restore_all_xen
   56.13  
    57.1 --- a/xen/arch/x86/x86_64/mm.c	Tue Dec 20 17:16:15 2005 +0000
    57.2 +++ b/xen/arch/x86/x86_64/mm.c	Tue Dec 20 17:16:24 2005 +0000
    57.3 @@ -166,11 +166,12 @@ void subarch_init_memory(struct domain *
    57.4  
    57.5          for ( i = 0; i < L1_PAGETABLE_ENTRIES; i++ )
    57.6          {
    57.7 -            frame_table[m2p_start_mfn+i].count_info = PGC_allocated | 1;
    57.8 +            struct pfn_info *page = pfn_to_page(m2p_start_mfn + i);
    57.9 +            page->count_info = PGC_allocated | 1;
   57.10              /* gdt to make sure it's only mapped read-only by non-privileged
   57.11                 domains. */
   57.12 -            frame_table[m2p_start_mfn+i].u.inuse.type_info = PGT_gdt_page | 1;
   57.13 -            page_set_owner(&frame_table[m2p_start_mfn+i], dom_xen);
   57.14 +            page->u.inuse.type_info = PGT_gdt_page | 1;
   57.15 +            page_set_owner(page, dom_xen);
   57.16          }
   57.17      }
   57.18  }
    58.1 --- a/xen/common/dom0_ops.c	Tue Dec 20 17:16:15 2005 +0000
    58.2 +++ b/xen/common/dom0_ops.c	Tue Dec 20 17:16:24 2005 +0000
    58.3 @@ -358,12 +358,17 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
    58.4      case DOM0_GETDOMAININFO:
    58.5      { 
    58.6          struct domain *d;
    58.7 +        domid_t dom;
    58.8 +
    58.9 +        dom = op->u.getdomaininfo.domain;
   58.10 +        if ( dom == DOMID_SELF )
   58.11 +            dom = current->domain->domain_id;
   58.12  
   58.13          read_lock(&domlist_lock);
   58.14  
   58.15          for_each_domain ( d )
   58.16          {
   58.17 -            if ( d->domain_id >= op->u.getdomaininfo.domain )
   58.18 +            if ( d->domain_id >= dom )
   58.19                  break;
   58.20          }
   58.21  
   58.22 @@ -577,6 +582,22 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
   58.23          }
   58.24      }
   58.25      break;
   58.26 +    case DOM0_SETDEBUGGING:
   58.27 +    {
   58.28 +        struct domain *d; 
   58.29 +        ret = -ESRCH;
   58.30 +        d = find_domain_by_id(op->u.setdebugging.domain);
   58.31 +        if ( d != NULL )
   58.32 +        {
   58.33 +            if ( op->u.setdebugging.enable )
   58.34 +                set_bit(_DOMF_debugging, &d->domain_flags);
   58.35 +            else
   58.36 +                clear_bit(_DOMF_debugging, &d->domain_flags);
   58.37 +            put_domain(d);
   58.38 +            ret = 0;
   58.39 +        }
   58.40 +    }
   58.41 +    break;
   58.42  
   58.43  #ifdef PERF_COUNTERS
   58.44      case DOM0_PERFCCONTROL:
    59.1 --- a/xen/common/grant_table.c	Tue Dec 20 17:16:15 2005 +0000
    59.2 +++ b/xen/common/grant_table.c	Tue Dec 20 17:16:24 2005 +0000
    59.3 @@ -238,8 +238,8 @@ static int
    59.4  
    59.5          if ( unlikely(!pfn_valid(frame)) ||
    59.6               unlikely(!((dev_hst_ro_flags & GNTMAP_readonly) ?
    59.7 -                        get_page(&frame_table[frame], rd) :
    59.8 -                        get_page_and_type(&frame_table[frame], rd,
    59.9 +                        get_page(pfn_to_page(frame), rd) :
   59.10 +                        get_page_and_type(pfn_to_page(frame), rd,
   59.11                                            PGT_writable_page))) )
   59.12          {
   59.13              clear_bit(_GTF_writing, &sha->flags);
   59.14 @@ -301,7 +301,7 @@ static int
   59.15                  sflags = prev_sflags;
   59.16              }
   59.17  
   59.18 -            if ( unlikely(!get_page_type(&frame_table[frame],
   59.19 +            if ( unlikely(!get_page_type(pfn_to_page(frame),
   59.20                                           PGT_writable_page)) )
   59.21              {
   59.22                  clear_bit(_GTF_writing, &sha->flags);
   59.23 @@ -347,14 +347,14 @@ static int
   59.24                  if ( (act->pin & (GNTPIN_hstw_mask|GNTPIN_devw_mask)) == 0 )
   59.25                  {
   59.26                      clear_bit(_GTF_writing, &sha->flags);
   59.27 -                    put_page_type(&frame_table[frame]);
   59.28 +                    put_page_type(pfn_to_page(frame));
   59.29                  }
   59.30              }
   59.31  
   59.32              if ( act->pin == 0 )
   59.33              {
   59.34                  clear_bit(_GTF_reading, &sha->flags);
   59.35 -                put_page(&frame_table[frame]);
   59.36 +                put_page(pfn_to_page(frame));
   59.37              }
   59.38  
   59.39              spin_unlock(&rd->grant_table->lock);
   59.40 @@ -500,14 +500,14 @@ static int
   59.41           !(flags & GNTMAP_readonly) )
   59.42      {
   59.43          clear_bit(_GTF_writing, &sha->flags);
   59.44 -        put_page_type(&frame_table[frame]);
   59.45 +        put_page_type(pfn_to_page(frame));
   59.46      }
   59.47  
   59.48      if ( act->pin == 0 )
   59.49      {
   59.50          act->frame = 0xdeadbeef;
   59.51          clear_bit(_GTF_reading, &sha->flags);
   59.52 -        put_page(&frame_table[frame]);
   59.53 +        put_page(pfn_to_page(frame));
   59.54      }
   59.55  
   59.56   unmap_out:
   59.57 @@ -691,7 +691,7 @@ gnttab_transfer(
   59.58          }
   59.59  
   59.60          /* Check the passed page frame for basic validity. */
   59.61 -        page = &frame_table[gop.mfn];
   59.62 +        page = pfn_to_page(gop.mfn);
   59.63          if ( unlikely(!pfn_valid(gop.mfn) || IS_XEN_HEAP_FRAME(page)) )
   59.64          { 
   59.65              DPRINTK("gnttab_transfer: out-of-range or xen frame %lx\n",
   59.66 @@ -1016,14 +1016,14 @@ gnttab_release_mappings(
   59.67              if ( (act->pin & (GNTPIN_devw_mask|GNTPIN_hstw_mask)) == 0 )
   59.68              {
   59.69                  clear_bit(_GTF_writing, &sha->flags);
   59.70 -                put_page_type(&frame_table[act->frame]);
   59.71 +                put_page_type(pfn_to_page(act->frame));
   59.72              }
   59.73          }
   59.74  
   59.75          if ( act->pin == 0 )
   59.76          {
   59.77              clear_bit(_GTF_reading, &sha->flags);
   59.78 -            put_page(&frame_table[act->frame]);
   59.79 +            put_page(pfn_to_page(act->frame));
   59.80          }
   59.81  
   59.82          spin_unlock(&rd->grant_table->lock);
    60.1 --- a/xen/common/memory.c	Tue Dec 20 17:16:15 2005 +0000
    60.2 +++ b/xen/common/memory.c	Tue Dec 20 17:16:24 2005 +0000
    60.3 @@ -102,7 +102,7 @@ decrease_reservation(
    60.4                  return i;
    60.5              }
    60.6              
    60.7 -            page = &frame_table[mpfn + j];
    60.8 +            page = pfn_to_page(mpfn + j);
    60.9              if ( unlikely(!get_page(page, d)) )
   60.10              {
   60.11                  DPRINTK("Bad page free for domain %u\n", d->domain_id);
    61.1 --- a/xen/include/asm-x86/debugger.h	Tue Dec 20 17:16:15 2005 +0000
    61.2 +++ b/xen/include/asm-x86/debugger.h	Tue Dec 20 17:16:24 2005 +0000
    61.3 @@ -30,6 +30,8 @@
    61.4  #ifndef __X86_DEBUGGER_H__
    61.5  #define __X86_DEBUGGER_H__
    61.6  
    61.7 +#include <xen/sched.h>
    61.8 +#include <asm/regs.h>
    61.9  #include <asm/processor.h>
   61.10  
   61.11  /* The main trap handlers use these helper macros which include early bail. */
   61.12 @@ -41,9 +43,10 @@
   61.13  #if defined(CRASH_DEBUG)
   61.14  
   61.15  extern int __trap_to_cdb(struct cpu_user_regs *r);
   61.16 -#define debugger_trap_entry(_v, _r) (0)
   61.17  
   61.18 -static inline int debugger_trap_fatal(
   61.19 +#define __debugger_trap_entry(_v, _r) (0)
   61.20 +
   61.21 +static inline int __debugger_trap_fatal(
   61.22      unsigned int vector, struct cpu_user_regs *regs)
   61.23  {
   61.24      (void)__trap_to_cdb(regs);
   61.25 @@ -51,60 +54,52 @@ static inline int debugger_trap_fatal(
   61.26  }
   61.27  
   61.28  /* Int3 is a trivial way to gather cpu_user_regs context. */
   61.29 -#define debugger_trap_immediate() __asm__ __volatile__ ( "int3" );
   61.30 +#define __debugger_trap_immediate() __asm__ __volatile__ ( "int3" );
   61.31  
   61.32 -#elif defined(DOMU_DEBUG)
   61.33 +#elif 0
   61.34  
   61.35 -#include <xen/sched.h>
   61.36 -#include <asm/regs.h>
   61.37 +extern int kdb_trap(int, int, struct cpu_user_regs *);
   61.38 +
   61.39 +static inline int __debugger_trap_entry(
   61.40 +    unsigned int vector, struct cpu_user_regs *regs)
   61.41 +{
   61.42 +    return 0;
   61.43 +}
   61.44 +
   61.45 +static inline int __debugger_trap_fatal(
   61.46 +    unsigned int vector, struct cpu_user_regs *regs)
   61.47 +{
   61.48 +    return kdb_trap(vector, 0, regs);
   61.49 +}
   61.50 +
   61.51 +/* Int3 is a trivial way to gather cpu_user_regs context. */
   61.52 +#define __debugger_trap_immediate() __asm__ __volatile__ ( "int3" )
   61.53 +
   61.54 +#else
   61.55 +
   61.56 +#define __debugger_trap_entry(_v, _r) (0)
   61.57 +#define __debugger_trap_fatal(_v, _r) (0)
   61.58 +#define __debugger_trap_immediate()   ((void)0)
   61.59 +
   61.60 +#endif
   61.61  
   61.62  static inline int debugger_trap_entry(
   61.63      unsigned int vector, struct cpu_user_regs *regs)
   61.64  {
   61.65      struct vcpu *v = current;
   61.66  
   61.67 -    if ( !KERNEL_MODE(v, regs) || (v->domain->domain_id == 0) )
   61.68 -        return 0;
   61.69 -    
   61.70 -    switch ( vector )
   61.71 +    if ( KERNEL_MODE(v, regs) &&
   61.72 +         test_bit(_DOMF_debugging, &v->domain->domain_flags) &&
   61.73 +         ((vector == TRAP_int3) || (vector == TRAP_debug)) )
   61.74      {
   61.75 -    case TRAP_int3:
   61.76 -    case TRAP_debug:
   61.77          domain_pause_for_debugger();
   61.78          return 1;
   61.79      }
   61.80  
   61.81 -    return 0;
   61.82 -}
   61.83 -
   61.84 -#define debugger_trap_fatal(_v, _r) (0)
   61.85 -#define debugger_trap_immediate()
   61.86 -
   61.87 -#elif 0
   61.88 -
   61.89 -extern int kdb_trap(int, int, struct cpu_user_regs *);
   61.90 -
   61.91 -static inline int debugger_trap_entry(
   61.92 -    unsigned int vector, struct cpu_user_regs *regs)
   61.93 -{
   61.94 -    return 0;
   61.95 +    return __debugger_trap_entry(vector, regs);
   61.96  }
   61.97  
   61.98 -static inline int debugger_trap_fatal(
   61.99 -    unsigned int vector, struct cpu_user_regs *regs)
  61.100 -{
  61.101 -    return kdb_trap(vector, 0, regs);
  61.102 -}
  61.103 -
  61.104 -/* Int3 is a trivial way to gather cpu_user_regs context. */
  61.105 -#define debugger_trap_immediate() __asm__ __volatile__ ( "int3" );
  61.106 -
  61.107 -#else
  61.108 -
  61.109 -#define debugger_trap_entry(_v, _r) (0)
  61.110 -#define debugger_trap_fatal(_v, _r) (0)
  61.111 -#define debugger_trap_immediate()
  61.112 -
  61.113 -#endif
  61.114 +#define debugger_trap_fatal(v, r) (__debugger_trap_fatal(v, r))
  61.115 +#define debugger_trap_immediate() (__debugger_trap_immediate())
  61.116  
  61.117  #endif /* __X86_DEBUGGER_H__ */
    62.1 --- a/xen/include/asm-x86/shadow.h	Tue Dec 20 17:16:15 2005 +0000
    62.2 +++ b/xen/include/asm-x86/shadow.h	Tue Dec 20 17:16:24 2005 +0000
    62.3 @@ -493,9 +493,9 @@ static inline void __mark_dirty(struct d
    62.4          SH_VLOG("mark_dirty OOR! mfn=%x pfn=%lx max=%x (dom %p)",
    62.5                 mfn, pfn, d->arch.shadow_dirty_bitmap_size, d);
    62.6          SH_VLOG("dom=%p caf=%08x taf=%" PRtype_info, 
    62.7 -               page_get_owner(&frame_table[mfn]),
    62.8 -               frame_table[mfn].count_info, 
    62.9 -               frame_table[mfn].u.inuse.type_info );
   62.10 +                page_get_owner(pfn_to_page(mfn)),
   62.11 +                pfn_to_page(mfn)->count_info, 
   62.12 +                pfn_to_page(mfn)->u.inuse.type_info );
   62.13      }
   62.14  #endif
   62.15  }
   62.16 @@ -648,20 +648,20 @@ get_shadow_ref(unsigned long smfn)
   62.17  
   62.18      ASSERT(pfn_valid(smfn));
   62.19  
   62.20 -    x = frame_table[smfn].count_info;
   62.21 +    x = pfn_to_page(smfn)->count_info;
   62.22      nx = x + 1;
   62.23  
   62.24      if ( unlikely(nx == 0) )
   62.25      {
   62.26          printk("get_shadow_ref overflow, gmfn=%" PRtype_info  " smfn=%lx\n",
   62.27 -               frame_table[smfn].u.inuse.type_info & PGT_mfn_mask,
   62.28 +               pfn_to_page(smfn)->u.inuse.type_info & PGT_mfn_mask,
   62.29                 smfn);
   62.30          BUG();
   62.31      }
   62.32      
   62.33      // Guarded by the shadow lock...
   62.34      //
   62.35 -    frame_table[smfn].count_info = nx;
   62.36 +    pfn_to_page(smfn)->count_info = nx;
   62.37  
   62.38      return 1;
   62.39  }
   62.40 @@ -678,7 +678,7 @@ put_shadow_ref(unsigned long smfn)
   62.41  
   62.42      ASSERT(pfn_valid(smfn));
   62.43  
   62.44 -    x = frame_table[smfn].count_info;
   62.45 +    x = pfn_to_page(smfn)->count_info;
   62.46      nx = x - 1;
   62.47  
   62.48      if ( unlikely(x == 0) )
   62.49 @@ -686,14 +686,14 @@ put_shadow_ref(unsigned long smfn)
   62.50          printk("put_shadow_ref underflow, smfn=%lx oc=%08x t=%" 
   62.51                 PRtype_info "\n",
   62.52                 smfn,
   62.53 -               frame_table[smfn].count_info,
   62.54 -               frame_table[smfn].u.inuse.type_info);
   62.55 +               pfn_to_page(smfn)->count_info,
   62.56 +               pfn_to_page(smfn)->u.inuse.type_info);
   62.57          BUG();
   62.58      }
   62.59  
   62.60      // Guarded by the shadow lock...
   62.61      //
   62.62 -    frame_table[smfn].count_info = nx;
   62.63 +    pfn_to_page(smfn)->count_info = nx;
   62.64  
   62.65      if ( unlikely(nx == 0) )
   62.66      {
   62.67 @@ -704,9 +704,9 @@ put_shadow_ref(unsigned long smfn)
   62.68  static inline void
   62.69  shadow_pin(unsigned long smfn)
   62.70  {
   62.71 -    ASSERT( !(frame_table[smfn].u.inuse.type_info & PGT_pinned) );
   62.72 +    ASSERT( !(pfn_to_page(smfn)->u.inuse.type_info & PGT_pinned) );
   62.73  
   62.74 -    frame_table[smfn].u.inuse.type_info |= PGT_pinned;
   62.75 +    pfn_to_page(smfn)->u.inuse.type_info |= PGT_pinned;
   62.76      if ( unlikely(!get_shadow_ref(smfn)) )
   62.77          BUG();
   62.78  }
   62.79 @@ -714,9 +714,9 @@ shadow_pin(unsigned long smfn)
   62.80  static inline void
   62.81  shadow_unpin(unsigned long smfn)
   62.82  {
   62.83 -    ASSERT( (frame_table[smfn].u.inuse.type_info & PGT_pinned) );
   62.84 +    ASSERT( (pfn_to_page(smfn)->u.inuse.type_info & PGT_pinned) );
   62.85  
   62.86 -    frame_table[smfn].u.inuse.type_info &= ~PGT_pinned;
   62.87 +    pfn_to_page(smfn)->u.inuse.type_info &= ~PGT_pinned;
   62.88      put_shadow_ref(smfn);
   62.89  }
   62.90  
   62.91 @@ -732,9 +732,9 @@ static inline void set_guest_back_ptr(
   62.92  
   62.93          ASSERT(shadow_lock_is_acquired(d));
   62.94          gmfn = l1e_get_pfn(spte);
   62.95 -        frame_table[gmfn].tlbflush_timestamp = smfn;
   62.96 -        frame_table[gmfn].u.inuse.type_info &= ~PGT_va_mask;
   62.97 -        frame_table[gmfn].u.inuse.type_info |= (unsigned long) index << PGT_va_shift;
   62.98 +        pfn_to_page(gmfn)->tlbflush_timestamp = smfn;
   62.99 +        pfn_to_page(gmfn)->u.inuse.type_info &= ~PGT_va_mask;
  62.100 +        pfn_to_page(gmfn)->u.inuse.type_info |= (unsigned long) index << PGT_va_shift;
  62.101      }
  62.102  }
  62.103  
  62.104 @@ -941,7 +941,7 @@ validate_pte_change(
  62.105              //
  62.106              perfc_incrc(validate_pte_changes2);
  62.107              if ( likely(l1e_get_flags(new_spte) & _PAGE_PRESENT) )
  62.108 -                shadow_put_page_type(d, &frame_table[l1e_get_pfn(new_spte)]);
  62.109 +                shadow_put_page_type(d, pfn_to_page(l1e_get_pfn(new_spte)));
  62.110          }
  62.111          else if ( ((l1e_get_flags(old_spte) | l1e_get_flags(new_spte)) &
  62.112                     _PAGE_PRESENT ) &&
  62.113 @@ -1216,8 +1216,8 @@ static inline unsigned long __shadow_sta
  62.114              printk("d->id=%d gpfn=%lx gmfn=%lx stype=%lx c=%x t=%" PRtype_info " "
  62.115                     "mfn_out_of_sync(gmfn)=%d mfn_is_page_table(gmfn)=%d\n",
  62.116                     d->domain_id, gpfn, gmfn, stype,
  62.117 -                   frame_table[gmfn].count_info,
  62.118 -                   frame_table[gmfn].u.inuse.type_info,
  62.119 +                   pfn_to_page(gmfn)->count_info,
  62.120 +                   pfn_to_page(gmfn)->u.inuse.type_info,
  62.121                     mfn_out_of_sync(gmfn), mfn_is_page_table(gmfn));
  62.122              BUG();
  62.123          }
  62.124 @@ -1597,7 +1597,7 @@ shadow_mode_page_writable(unsigned long 
  62.125      struct vcpu *v = current;
  62.126      struct domain *d = v->domain;
  62.127      unsigned long mfn = __gpfn_to_mfn(d, gpfn);
  62.128 -    u32 type = frame_table[mfn].u.inuse.type_info & PGT_type_mask;
  62.129 +    u32 type = pfn_to_page(mfn)->u.inuse.type_info & PGT_type_mask;
  62.130  
  62.131      if ( shadow_mode_refcounts(d) &&
  62.132           (type == PGT_writable_page) )
  62.133 @@ -1707,6 +1707,8 @@ static inline void update_pagetables(str
  62.134      }
  62.135  }
  62.136  
  62.137 +void clear_all_shadow_status(struct domain *d);
  62.138 +
  62.139  #if SHADOW_DEBUG
  62.140  extern int _check_pagetable(struct vcpu *v, char *s);
  62.141  extern int _check_all_pagetables(struct vcpu *v, char *s);
    63.1 --- a/xen/include/asm-x86/shadow_public.h	Tue Dec 20 17:16:15 2005 +0000
    63.2 +++ b/xen/include/asm-x86/shadow_public.h	Tue Dec 20 17:16:24 2005 +0000
    63.3 @@ -22,7 +22,7 @@
    63.4  #ifndef _XEN_SHADOW_PUBLIC_H
    63.5  #define _XEN_SHADOW_PUBLIC_H
    63.6  #if CONFIG_PAGING_LEVELS >= 3
    63.7 -#define MFN_PINNED(_x) (frame_table[_x].u.inuse.type_info & PGT_pinned)
    63.8 +#define MFN_PINNED(_x) (pfn_to_page(_x)->u.inuse.type_info & PGT_pinned)
    63.9  
   63.10  extern int alloc_p2m_table(struct domain *d);
   63.11  
    64.1 --- a/xen/include/public/acm.h	Tue Dec 20 17:16:15 2005 +0000
    64.2 +++ b/xen/include/public/acm.h	Tue Dec 20 17:16:24 2005 +0000
    64.3 @@ -1,25 +1,8 @@
    64.4 -/****************************************************************
    64.5 - * acm.h
    64.6 - * 
    64.7 - * Copyright (C) 2005 IBM Corporation
    64.8 - *
    64.9 - * Author:
   64.10 - * Reiner Sailer <sailer@watson.ibm.com>
   64.11 +/*
   64.12 + * acm.h: Xen access control module interface defintions
   64.13   *
   64.14 - * Contributors:
   64.15 - * Stefan Berger <stefanb@watson.ibm.com> 
   64.16 - * added network byte order support for binary policies
   64.17 - *
   64.18 - * This program is free software; you can redistribute it and/or
   64.19 - * modify it under the terms of the GNU General Public License as
   64.20 - * published by the Free Software Foundation, version 2 of the
   64.21 - * License.
   64.22 - *
   64.23 - * sHype general access control module header file.
   64.24 - *     here are all definitions that are shared between
   64.25 - *     xen-core, guest-kernels, and applications.
   64.26 - *
   64.27 - * todo: move from static policy choice to compile option.
   64.28 + * Reiner Sailer <sailer@watson.ibm.com>
   64.29 + * Copyright (c) 2005, International Business Machines Corporation.
   64.30   */
   64.31  
   64.32  #ifndef _XEN_PUBLIC_ACM_H
    65.1 --- a/xen/include/public/acm_ops.h	Tue Dec 20 17:16:15 2005 +0000
    65.2 +++ b/xen/include/public/acm_ops.h	Tue Dec 20 17:16:24 2005 +0000
    65.3 @@ -1,19 +1,8 @@
    65.4 -/******************************************************************************
    65.5 - * acm_ops.h
    65.6 - *
    65.7 - * Copyright (C) 2005 IBM Corporation
    65.8 - *
    65.9 - * Author:
   65.10 - * Reiner Sailer <sailer@watson.ibm.com>
   65.11 +/*
   65.12 + * acm_ops.h: Xen access control module hypervisor commands
   65.13   *
   65.14 - * This program is free software; you can redistribute it and/or
   65.15 - * modify it under the terms of the GNU General Public License as
   65.16 - * published by the Free Software Foundation, version 2 of the
   65.17 - * License.
   65.18 - *
   65.19 - * Process acm policy command requests from guest OS.
   65.20 - * access checked by policy; not restricted to DOM0
   65.21 - *
   65.22 + * Reiner Sailer <sailer@watson.ibm.com>
   65.23 + * Copyright (c) 2005, International Business Machines Corporation.
   65.24   */
   65.25  
   65.26  #ifndef __XEN_PUBLIC_ACM_OPS_H__
    66.1 --- a/xen/include/public/dom0_ops.h	Tue Dec 20 17:16:15 2005 +0000
    66.2 +++ b/xen/include/public/dom0_ops.h	Tue Dec 20 17:16:24 2005 +0000
    66.3 @@ -404,6 +404,12 @@ typedef struct {
    66.4      xen_domain_handle_t handle;
    66.5  } dom0_setdomainhandle_t;
    66.6  
    66.7 +#define DOM0_SETDEBUGGING 45
    66.8 +typedef struct {
    66.9 +    domid_t domain;
   66.10 +    uint8_t enable;
   66.11 +} dom0_setdebugging_t;
   66.12 +
   66.13  typedef struct {
   66.14      uint32_t cmd;
   66.15      uint32_t interface_version; /* DOM0_INTERFACE_VERSION */
   66.16 @@ -440,7 +446,8 @@ typedef struct {
   66.17          dom0_platform_quirk_t    platform_quirk;
   66.18          dom0_physical_memory_map_t physical_memory_map;
   66.19          dom0_max_vcpus_t         max_vcpus;
   66.20 -        dom0_setdomainhandle_t   setdomainhandle;
   66.21 +        dom0_setdomainhandle_t   setdomainhandle;        
   66.22 +        dom0_setdebugging_t      setdebugging;
   66.23          uint8_t                  pad[128];
   66.24      } u;
   66.25  } dom0_op_t;
    67.1 --- a/xen/include/public/vmx_assist.h	Tue Dec 20 17:16:15 2005 +0000
    67.2 +++ b/xen/include/public/vmx_assist.h	Tue Dec 20 17:16:24 2005 +0000
    67.3 @@ -3,21 +3,8 @@
    67.4   *
    67.5   * Leendert van Doorn, leendert@watson.ibm.com
    67.6   * Copyright (c) 2005, International Business Machines Corporation.
    67.7 - *
    67.8 - * This program is free software; you can redistribute it and/or modify it
    67.9 - * under the terms and conditions of the GNU General Public License,
   67.10 - * version 2, as published by the Free Software Foundation.
   67.11 - *
   67.12 - * This program is distributed in the hope it will be useful, but WITHOUT
   67.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   67.14 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
   67.15 - * more details.
   67.16 - *
   67.17 - * You should have received a copy of the GNU General Public License along with
   67.18 - * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
   67.19 - * Place - Suite 330, Boston, MA 02111-1307 USA.
   67.20 - *
   67.21   */
   67.22 +
   67.23  #ifndef _VMX_ASSIST_H_
   67.24  #define _VMX_ASSIST_H_
   67.25  
    68.1 --- a/xen/include/public/xen.h	Tue Dec 20 17:16:15 2005 +0000
    68.2 +++ b/xen/include/public/xen.h	Tue Dec 20 17:16:24 2005 +0000
    68.3 @@ -67,12 +67,13 @@
    68.4   */
    68.5  #define VIRQ_TIMER      0  /* Timebase update, and/or requested timeout.  */
    68.6  #define VIRQ_DEBUG      1  /* Request guest to dump debug info.           */
    68.7 -#define VIRQ_CONSOLE    2  /* (DOM0) bytes received on emergency console. */
    68.8 +#define VIRQ_CONSOLE    2  /* (DOM0) Bytes received on emergency console. */
    68.9  #define VIRQ_DOM_EXC    3  /* (DOM0) Exceptional event for some domain.   */
   68.10 -#define VIRQ_PARITY_ERR 4  /* (DOM0) NMI parity error.                    */
   68.11 -#define VIRQ_IO_ERR     5  /* (DOM0) NMI I/O error.                       */
   68.12 +#define VIRQ_PARITY_ERR 4  /* (DOM0) NMI parity error (port 0x61, bit 7). */
   68.13 +#define VIRQ_IO_ERR     5  /* (DOM0) NMI I/O error    (port 0x61, bit 6). */
   68.14  #define VIRQ_DEBUGGER   6  /* (DOM0) A domain has paused for debugging.   */
   68.15 -#define NR_VIRQS        7
   68.16 +#define VIRQ_NMI        7  /* (DOM0) Unknown NMI (not from ISA port 0x61).*/
   68.17 +#define NR_VIRQS        8
   68.18  
   68.19  /*
   68.20   * MMU-UPDATE REQUESTS
    69.1 --- a/xen/include/xen/sched.h	Tue Dec 20 17:16:15 2005 +0000
    69.2 +++ b/xen/include/xen/sched.h	Tue Dec 20 17:16:24 2005 +0000
    69.3 @@ -393,6 +393,10 @@ extern struct domain *domain_list;
    69.4   /* Domain is paused by controller software. */
    69.5  #define _DOMF_ctrl_pause       6
    69.6  #define DOMF_ctrl_pause        (1UL<<_DOMF_ctrl_pause)
    69.7 + /* Domain is being debugged by controller software. */
    69.8 +#define _DOMF_debugging        7
    69.9 +#define DOMF_debugging         (1UL<<_DOMF_debugging)
   69.10 +
   69.11  
   69.12  static inline int domain_runnable(struct vcpu *v)
   69.13  {
    70.1 --- a/xen/include/xen/softirq.h	Tue Dec 20 17:16:15 2005 +0000
    70.2 +++ b/xen/include/xen/softirq.h	Tue Dec 20 17:16:24 2005 +0000
    70.3 @@ -6,7 +6,7 @@
    70.4  #define SCHEDULE_SOFTIRQ                  1
    70.5  #define NEW_TLBFLUSH_CLOCK_PERIOD_SOFTIRQ 2
    70.6  #define KEYPRESS_SOFTIRQ                  3
    70.7 -#define NMI_SOFTIRQ                       4
    70.8 +#define NMI_DOM0_SOFTIRQ                  4
    70.9  #define PAGE_SCRUB_SOFTIRQ                5
   70.10  #define DOMAIN_SHUTDOWN_FINALISE_SOFTIRQ  6
   70.11  #define NR_SOFTIRQS                       7