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