[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] Merge with latest xen-unstable
# HG changeset patch # User djm@xxxxxxxxxxxxxxx # Node ID b35215021b32c41a5c14e9fc42bc786652c4744a # Parent d4d880fcef2860ebe3fd54b391147a57db06a5c7 # Parent e7c7196fa329a91c745c3e40546dc8b588ea0abb Merge with latest xen-unstable diff -r d4d880fcef28 -r b35215021b32 .hgignore --- a/.hgignore Fri Sep 9 16:31:36 2005 +++ b/.hgignore Tue Sep 13 16:14:16 2005 @@ -19,6 +19,7 @@ ^docs/.*\.toc$ ^docs/figs/xenserver\.eps$ ^docs/html/.*$ +^docs/api/.*$ ^docs/interface/WARNINGS$ ^docs/interface/images\.pl$ ^docs/interface/images\.tex$ @@ -60,8 +61,6 @@ ^pristine-.*$ ^ref-.*$ ^tools/.*/build/lib.*/.*\.py$ -^tools/Makefile\.smh$ -^tools/balloon/balloon$ ^tools/blktap/Makefile\.smh$ ^tools/blktap/blkcow$ ^tools/blktap/blkcowgnbd$ @@ -85,8 +84,7 @@ ^tools/blktap/ublkback/ublkback$ ^tools/blktap/xen/.*$ ^tools/check/\..*$ -^tools/cmdline/.*$ -^tools/cmdline/xen/.*$ +^tools/examples/xmexample\.vmx$ ^tools/console/xenconsoled$ ^tools/console/xenconsole$ ^tools/debugger/pdb/pdb$ @@ -109,8 +107,6 @@ ^tools/firmware/vmxassist/roms\.h$ ^tools/firmware/vmxassist/vmxassist$ ^tools/firmware/vmxassist/vmxloader$ -^tools/gdb/gdb-6\.2\.1-linux-i386-xen/.*$ -^tools/gdb/gdb-6\.2\.1/.*$ ^tools/ioemu/config-host\..*$ ^tools/ioemu/keysym_adapter_sdl\.h$ ^tools/ioemu/keysym_adapter_vnc\.h$ @@ -141,20 +137,18 @@ ^tools/vnet/vnet-module/\..*\.cmd$ ^tools/vnet/vnet-module/\.tmp_versions/.*$ ^tools/vnet/vnet-module/vnet_module\.mod\..*$ -^tools/vnetd/vnetd$ ^tools/vtpm/vtpm* ^tools/vtpm/tpm_emulator-* ^tools/vtpm_manager/manager/vtpm_managerd -^tools/web-shutdown\.tap$ -^tools/x2d2/minixend$ ^tools/xcutils/xc_restore$ ^tools/xcutils/xc_save$ ^tools/xenstat/xentop/xentop$ ^tools/xenstore/testsuite/tmp/.*$ ^tools/xenstore/xen$ -^tools/xenstore/xenbus_dev.h$ ^tools/xenstore/xenstored$ ^tools/xenstore/xenstored_test$ +^tools/xenstore/xenstore-exists$ +^tools/xenstore/xenstore-list$ ^tools/xenstore/xenstore-read$ ^tools/xenstore/xenstore-rm$ ^tools/xenstore/xenstore-write$ diff -r d4d880fcef28 -r b35215021b32 Makefile --- a/Makefile Fri Sep 9 16:31:36 2005 +++ b/Makefile Tue Sep 13 16:14:16 2005 @@ -35,8 +35,8 @@ export pae=y endif -.PHONY: all dist install xen kernels tools docs world clean mkpatches mrproper -.PHONY: kbuild kdelete kclean +.PHONY: all dist install xen kernels tools dev-docs docs world clean +.PHONY: mkpatches mrproper kbuild kdelete kclean # build and install everything into the standard system directories install: install-xen install-kernels install-tools install-docs @@ -65,6 +65,9 @@ docs: sh ./docs/check_pkgs && $(MAKE) -C docs install || true + +dev-docs: + $(MAKE) -C docs dev-docs # Build all the various kernels and modules kbuild: kernels @@ -123,7 +126,7 @@ @echo ' install-xen - build and install the Xen hypervisor' @echo ' install-tools - build and install the control tools' @echo ' install-kernels - build and install guest kernels' - @echo ' install-docs - build and install documentation' + @echo ' install-docs - build and install user documentation' @echo '' @echo 'Building targets:' @echo ' dist - build and install everything into local dist directory' @@ -133,7 +136,8 @@ @echo ' tools - build and install tools' @echo ' kernels - build and install guest kernels' @echo ' kbuild - synonym for make kernels' - @echo ' docs - build and install docs' + @echo ' docs - build and install user documentation' + @echo ' dev-docs - build developer-only documentation' @echo '' @echo 'Cleaning targets:' @echo ' clean - clean the Xen, tools and docs (but not' diff -r d4d880fcef28 -r b35215021b32 docs/Makefile --- a/docs/Makefile Fri Sep 9 16:31:36 2005 +++ b/docs/Makefile Tue Sep 13 16:14:16 2005 @@ -8,6 +8,7 @@ LATEX := latex FIG2DEV := fig2dev LATEX2HTML := latex2html +DOXYGEN := doxygen pkgdocdir := /usr/share/doc/xen @@ -18,9 +19,13 @@ GFX = $(patsubst %.fig, %.eps, $(wildcard figs/*.fig)) +.PHONY: all build dev-docs python-dev-docs ps pdf html clean install + all: build build: ps pdf html rm -f *.aux *.dvi *.bbl *.blg *.glo *.idx *.ilg *.log *.ind *.toc + +dev-docs: python-dev-docs ps: $(DOC_PS) @@ -30,10 +35,18 @@ @if which $(LATEX2HTML) 1>/dev/null 2>/dev/null; then \ $(MAKE) $(DOC_HTML); fi +python-dev-docs: + mkdir -p api/tools/python + @if which $(DOXYGEN) 1>/dev/null 2>/dev/null; then \ + echo "Running doxygen to generate Python tools APIs ... "; \ + $(DOXYGEN) Doxyfile; \ + $(MAKE) -C api/tools/python/latex ; fi + clean: rm -rf .word_count *.aux *.dvi *.bbl *.blg *.glo *.idx *~ rm -rf *.ilg *.log *.ind *.toc *.bak core rm -rf $(GFX) ps pdf html + rm -rf api install: all rm -rf $(DESTDIR)$(pkgdocdir) diff -r d4d880fcef28 -r b35215021b32 extras/mini-os/include/hypervisor.h --- a/extras/mini-os/include/hypervisor.h Fri Sep 9 16:31:36 2005 +++ b/extras/mini-os/include/hypervisor.h Tue Sep 13 16:14:16 2005 @@ -414,15 +414,15 @@ static inline int HYPERVISOR_xen_version( - int cmd) -{ - int ret; - unsigned long ignore; - - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret), "=b" (ignore) - : "0" (__HYPERVISOR_xen_version), "1" (cmd) + int cmd, void *arg) +{ + int ret; + unsigned long ignore, ign2; + + __asm__ __volatile__ ( + TRAP_INSTR + : "=a" (ret), "=b" (ignore), "=c" (ign2) + : "0" (__HYPERVISOR_xen_version), "1" (cmd), "2" (arg) : "memory" ); return ret; diff -r d4d880fcef28 -r b35215021b32 linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c Fri Sep 9 16:31:36 2005 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c Tue Sep 13 16:14:16 2005 @@ -543,7 +543,7 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { s64 delta, delta_cpu; - int cpu = smp_processor_id(); + int i, cpu = smp_processor_id(); struct shadow_time_info *shadow = &per_cpu(shadow_time, cpu); write_seqlock(&xtime_lock); @@ -566,9 +566,9 @@ (s64)get_nsec_offset(shadow), processed_system_time, per_cpu(processed_system_time, cpu)); - for (cpu = 0; cpu < num_online_cpus(); cpu++) - printk(" %d: %lld\n", cpu, - per_cpu(processed_system_time, cpu)); + for (i = 0; i < num_online_cpus(); i++) + printk(" %d: %lld\n", i, + per_cpu(processed_system_time, i)); } /* System-wide jiffy work. */ diff -r d4d880fcef28 -r b35215021b32 linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c --- a/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c Fri Sep 9 16:31:36 2005 +++ b/linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c Tue Sep 13 16:14:16 2005 @@ -37,7 +37,7 @@ #include <asm/atomic.h> #include <asm/system.h> #include <asm/ptrace.h> -#include <asm-xen/synch_bitops.h> +#include <asm/synch_bitops.h> #include <asm-xen/xen-public/event_channel.h> #include <asm-xen/xen-public/physdev.h> #include <asm-xen/hypervisor.h> @@ -123,7 +123,7 @@ */ void force_evtchn_callback(void) { - (void)HYPERVISOR_xen_version(0); + (void)HYPERVISOR_xen_version(0, NULL); } EXPORT_SYMBOL(force_evtchn_callback); diff -r d4d880fcef28 -r b35215021b32 linux-2.6-xen-sparse/arch/xen/kernel/gnttab.c --- a/linux-2.6-xen-sparse/arch/xen/kernel/gnttab.c Fri Sep 9 16:31:36 2005 +++ b/linux-2.6-xen-sparse/arch/xen/kernel/gnttab.c Tue Sep 13 16:14:16 2005 @@ -19,7 +19,7 @@ #include <asm-xen/xen_proc.h> #include <asm-xen/linux-public/privcmd.h> #include <asm-xen/gnttab.h> -#include <asm-xen/synch_bitops.h> +#include <asm/synch_bitops.h> #if 1 #define ASSERT(_p) \ diff -r d4d880fcef28 -r b35215021b32 linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c --- a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c Fri Sep 9 16:31:36 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c Tue Sep 13 16:14:16 2005 @@ -65,7 +65,6 @@ /* If other end is gone, delete ourself. */ if (node && !xenbus_exists(be->frontpath, "")) { - xenbus_rm(be->dev->nodename, ""); device_unregister(&be->dev->dev); return; } diff -r d4d880fcef28 -r b35215021b32 linux-2.6-xen-sparse/drivers/xen/console/console.c --- a/linux-2.6-xen-sparse/drivers/xen/console/console.c Fri Sep 9 16:31:36 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/console/console.c Tue Sep 13 16:14:16 2005 @@ -182,9 +182,9 @@ #endif static struct console kcons_info = { - device: kcons_device, - flags: CON_PRINTBUFFER, - index: -1 + .device = kcons_device, + .flags = CON_PRINTBUFFER, + .index = -1, }; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) diff -r d4d880fcef28 -r b35215021b32 linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c --- a/linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c Fri Sep 9 16:31:36 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c Tue Sep 13 16:14:16 2005 @@ -356,14 +356,14 @@ } static struct file_operations evtchn_fops = { - owner: THIS_MODULE, - read: evtchn_read, - write: evtchn_write, - ioctl: evtchn_ioctl, - poll: evtchn_poll, - fasync: evtchn_fasync, - open: evtchn_open, - release: evtchn_release + .owner = THIS_MODULE, + .read = evtchn_read, + .write = evtchn_write, + .ioctl = evtchn_ioctl, + .poll = evtchn_poll, + .fasync = evtchn_fasync, + .open = evtchn_open, + .release = evtchn_release, }; static struct miscdevice evtchn_miscdev = { diff -r d4d880fcef28 -r b35215021b32 linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c --- a/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c Fri Sep 9 16:31:36 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c Tue Sep 13 16:14:16 2005 @@ -241,8 +241,8 @@ } static struct file_operations privcmd_file_ops = { - ioctl : privcmd_ioctl, - mmap: privcmd_mmap + .ioctl = privcmd_ioctl, + .mmap = privcmd_mmap, }; diff -r d4d880fcef28 -r b35215021b32 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c Fri Sep 9 16:31:36 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c Tue Sep 13 16:14:16 2005 @@ -5,6 +5,7 @@ * to xenstore. * * Copyright (c) 2005, Christian Limpach + * Copyright (c) 2005, Rusty Russell, IBM Corporation * * This file may be distributed separately from the Linux kernel, or * incorporated into other software packages, subject to the following license: @@ -36,109 +37,104 @@ #include <linux/wait.h> #include <linux/fs.h> -#include "xenstored.h" #include "xenbus_comms.h" #include <asm/uaccess.h> #include <asm-xen/xenbus.h> -#include <asm-xen/linux-public/xenbus_dev.h> #include <asm-xen/xen_proc.h> +#include <asm-xen/linux-public/xenstored.h> struct xenbus_dev_data { - int in_transaction; + /* Are there bytes left to be read in this message? */ + int bytes_left; + /* Are we still waiting for the reply to a message we wrote? */ + int awaiting_reply; + /* Buffer for outgoing messages. */ + unsigned int len; + union { + struct xsd_sockmsg msg; + char buffer[PAGE_SIZE]; + } u; }; static struct proc_dir_entry *xenbus_dev_intf; -void *xs_talkv(enum xsd_sockmsg_type type, const struct kvec *iovec, - unsigned int num_vecs, unsigned int *len); +/* Reply can be long (dir, getperm): don't buffer, just examine + * headers so we can discard rest if they die. */ +static ssize_t xenbus_dev_read(struct file *filp, + char __user *ubuf, + size_t len, loff_t *ppos) +{ + struct xenbus_dev_data *data = filp->private_data; + struct xsd_sockmsg msg; + int err; -static int xenbus_dev_talkv(struct xenbus_dev_data *u, unsigned long data) -{ - struct xenbus_dev_talkv xt; - unsigned int len; - void *resp, *base; - struct kvec *iovec; - int ret = -EFAULT, v = 0; + /* Refill empty buffer? */ + if (data->bytes_left == 0) { + if (len < sizeof(msg)) + return -EINVAL; - if (copy_from_user(&xt, (void *)data, sizeof(xt))) - return -EFAULT; - - iovec = kmalloc(xt.num_vecs * sizeof(struct kvec), GFP_KERNEL); - if (iovec == NULL) - return -ENOMEM; - - if (copy_from_user(iovec, xt.iovec, - xt.num_vecs * sizeof(struct kvec))) - goto out; - - for (v = 0; v < xt.num_vecs; v++) { - base = iovec[v].iov_base; - iovec[v].iov_base = kmalloc(iovec[v].iov_len, GFP_KERNEL); - if (iovec[v].iov_base == NULL || - copy_from_user(iovec[v].iov_base, base, iovec[v].iov_len)) - { - if (iovec[v].iov_base) - kfree(iovec[v].iov_base); - else - ret = -ENOMEM; - v--; - goto out; - } + err = xb_read(&msg, sizeof(msg)); + if (err) + return err; + data->bytes_left = msg.len; + if (ubuf && copy_to_user(ubuf, &msg, sizeof(msg)) != 0) + return -EFAULT; + /* We can receive spurious XS_WATCH_EVENT messages. */ + if (msg.type != XS_WATCH_EVENT) + data->awaiting_reply = 0; + return sizeof(msg); } - resp = xs_talkv(xt.type, iovec, xt.num_vecs, &len); - if (IS_ERR(resp)) { - ret = PTR_ERR(resp); - goto out; - } + /* Don't read over next header, or over temporary buffer. */ + if (len > sizeof(data->u.buffer)) + len = sizeof(data->u.buffer); + if (len > data->bytes_left) + len = data->bytes_left; - switch (xt.type) { - case XS_TRANSACTION_START: - u->in_transaction = 1; - break; - case XS_TRANSACTION_END: - u->in_transaction = 0; - break; - default: - break; - } + err = xb_read(data->u.buffer, len); + if (err) + return err; - ret = len; - if (len > xt.len) - len = xt.len; - - if (copy_to_user(xt.buf, resp, len)) - ret = -EFAULT; - - kfree(resp); - out: - while (v-- > 0) - kfree(iovec[v].iov_base); - kfree(iovec); - return ret; + data->bytes_left -= len; + if (ubuf && copy_to_user(ubuf, data->u.buffer, len) != 0) + return -EFAULT; + return len; } -static int xenbus_dev_ioctl(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long data) +/* We do v. basic sanity checking so they don't screw up kernel later. */ +static ssize_t xenbus_dev_write(struct file *filp, + const char __user *ubuf, + size_t len, loff_t *ppos) { - struct xenbus_dev_data *u = filp->private_data; - int ret = -ENOSYS; + struct xenbus_dev_data *data = filp->private_data; + int err; - switch (cmd) { - case IOCTL_XENBUS_DEV_TALKV: - ret = xenbus_dev_talkv(u, data); - break; - default: - ret = -EINVAL; - break; + /* We gather data in buffer until we're ready to send it. */ + if (len > data->len + sizeof(data->u)) + return -EINVAL; + if (copy_from_user(data->u.buffer + data->len, ubuf, len) != 0) + return -EFAULT; + data->len += len; + if (data->len >= sizeof(data->u.msg) + data->u.msg.len) { + err = xb_write(data->u.buffer, data->len); + if (err) + return err; + data->len = 0; + data->awaiting_reply = 1; } - return ret; + return len; } static int xenbus_dev_open(struct inode *inode, struct file *filp) { struct xenbus_dev_data *u; + + if (xen_start_info->store_evtchn == 0) + return -ENOENT; + + /* Don't try seeking. */ + nonseekable_open(inode, filp); u = kmalloc(sizeof(*u), GFP_KERNEL); if (u == NULL) @@ -155,22 +151,27 @@ static int xenbus_dev_release(struct inode *inode, struct file *filp) { - struct xenbus_dev_data *u = filp->private_data; + struct xenbus_dev_data *data = filp->private_data; - if (u->in_transaction) - xenbus_transaction_end(1); + /* Discard any unread replies. */ + while (data->bytes_left || data->awaiting_reply) + xenbus_dev_read(filp, NULL, sizeof(data->u.buffer), NULL); + + /* Harmless if no transaction in progress. */ + xenbus_transaction_end(1); up(&xenbus_lock); - kfree(u); + kfree(data); return 0; } static struct file_operations xenbus_dev_file_ops = { - ioctl: xenbus_dev_ioctl, - open: xenbus_dev_open, - release: xenbus_dev_release + .read = xenbus_dev_read, + .write = xenbus_dev_write, + .open = xenbus_dev_open, + .release = xenbus_dev_release, }; static int __init diff -r d4d880fcef28 -r b35215021b32 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Fri Sep 9 16:31:36 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Tue Sep 13 16:14:16 2005 @@ -166,6 +166,10 @@ buffer, buffer_size, &length, "XENBUS_TYPE=%s", xdev->devicetype); + add_hotplug_env_var(envp, num_envp, &i, + buffer, buffer_size, &length, + "XENBUS_PATH=%s", xdev->nodename); + /* terminate, set to next free slot, shrink available space */ envp[i] = NULL; envp = &envp[i]; diff -r d4d880fcef28 -r b35215021b32 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c Fri Sep 9 16:31:36 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c Tue Sep 13 16:14:16 2005 @@ -38,7 +38,7 @@ #include <linux/fcntl.h> #include <linux/kthread.h> #include <asm-xen/xenbus.h> -#include "xenstored.h" +#include <asm-xen/linux-public/xenstored.h> #include "xenbus_comms.h" #define streq(a, b) (strcmp((a), (b)) == 0) @@ -106,10 +106,10 @@ } /* Send message to xs, get kmalloc'ed reply. ERR_PTR() on error. */ -void *xs_talkv(enum xsd_sockmsg_type type, - const struct kvec *iovec, - unsigned int num_vecs, - unsigned int *len) +static void *xs_talkv(enum xsd_sockmsg_type type, + const struct kvec *iovec, + unsigned int num_vecs, + unsigned int *len) { struct xsd_sockmsg msg; void *ret = NULL; diff -r d4d880fcef28 -r b35215021b32 linux-2.6-xen-sparse/include/asm-xen/asm-i386/hypercall.h --- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/hypercall.h Fri Sep 9 16:31:36 2005 +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/hypercall.h Tue Sep 13 16:14:16 2005 @@ -270,9 +270,9 @@ static inline int HYPERVISOR_xen_version( - int cmd) -{ - return _hypercall1(int, xen_version, cmd); + int cmd, void *arg) +{ + return _hypercall2(int, xen_version, cmd, arg); } static inline int diff -r d4d880fcef28 -r b35215021b32 linux-2.6-xen-sparse/include/asm-xen/asm-i386/system.h --- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/system.h Fri Sep 9 16:31:36 2005 +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/system.h Tue Sep 13 16:14:16 2005 @@ -4,7 +4,7 @@ #include <linux/config.h> #include <linux/kernel.h> #include <linux/bitops.h> -#include <asm-xen/synch_bitops.h> +#include <asm/synch_bitops.h> #include <asm/segment.h> #include <asm/cpufeature.h> #include <asm-xen/hypervisor.h> diff -r d4d880fcef28 -r b35215021b32 linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/hypercall.h --- a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/hypercall.h Fri Sep 9 16:31:36 2005 +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/hypercall.h Tue Sep 13 16:14:16 2005 @@ -260,9 +260,9 @@ static inline int HYPERVISOR_xen_version( - int cmd) -{ - return _hypercall1(int, xen_version, cmd); + int cmd, void *arg) +{ + return _hypercall2(int, xen_version, cmd, arg); } static inline int diff -r d4d880fcef28 -r b35215021b32 linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/system.h --- a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/system.h Fri Sep 9 16:31:36 2005 +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/system.h Tue Sep 13 16:14:16 2005 @@ -4,7 +4,7 @@ #include <linux/config.h> #include <linux/kernel.h> #include <asm/segment.h> -#include <asm-xen/synch_bitops.h> +#include <asm/synch_bitops.h> #include <asm-xen/hypervisor.h> #include <asm-xen/xen-public/arch-x86_64.h> diff -r d4d880fcef28 -r b35215021b32 linux-2.6-xen-sparse/include/asm-xen/evtchn.h --- a/linux-2.6-xen-sparse/include/asm-xen/evtchn.h Fri Sep 9 16:31:36 2005 +++ b/linux-2.6-xen-sparse/include/asm-xen/evtchn.h Tue Sep 13 16:14:16 2005 @@ -35,7 +35,7 @@ #include <linux/interrupt.h> #include <asm-xen/hypervisor.h> #include <asm/ptrace.h> -#include <asm-xen/synch_bitops.h> +#include <asm/synch_bitops.h> #include <asm-xen/xen-public/event_channel.h> #include <linux/smp.h> diff -r d4d880fcef28 -r b35215021b32 linux-2.6-xen-sparse/mkbuildtree --- a/linux-2.6-xen-sparse/mkbuildtree Fri Sep 9 16:31:36 2005 +++ b/linux-2.6-xen-sparse/mkbuildtree Tue Sep 13 16:14:16 2005 @@ -108,5 +108,5 @@ cd ${AD}/include/asm-xen/xen-public relative_lndir ../../../${RS}/../xen/include/public -cd ${AD}/drivers/xen/xenbus +cd ${AD}/include/asm-xen/linux-public ln -sf ../../../${RS}/../tools/xenstore/xenstored.h diff -r d4d880fcef28 -r b35215021b32 tools/console/daemon/io.c --- a/tools/console/daemon/io.c Fri Sep 9 16:31:36 2005 +++ b/tools/console/daemon/io.c Tue Sep 13 16:14:16 2005 @@ -87,6 +87,7 @@ struct buffer *buffer = &dom->buffer; struct ring_head *ring = (struct ring_head *)dom->page; size_t size; + u32 oldcons; while ((size = ring->prod - ring->cons) != 0) { if ((buffer->capacity - buffer->size) < size) { @@ -98,7 +99,8 @@ } } - while (ring->cons < ring->prod) { + oldcons = ring->cons; + while (ring->cons < (oldcons + size)) { buffer->data[buffer->size] = ring->buf[XENCONS_IDX(ring->cons)]; buffer->size++; diff -r d4d880fcef28 -r b35215021b32 tools/console/daemon/main.c --- a/tools/console/daemon/main.c Fri Sep 9 16:31:36 2005 +++ b/tools/console/daemon/main.c Tue Sep 13 16:14:16 2005 @@ -30,6 +30,12 @@ #include "utils.h" #include "io.h" +void usage(char *prg) +{ + fprintf(stderr, + "usage: %s [-h] [-V] [-v] [-i]\n", prg); +} + int main(int argc, char **argv) { const char *sopts = "hVvi"; @@ -49,7 +55,7 @@ while ((ch = getopt_long(argc, argv, sopts, lopts, &opt_ind)) != -1) { switch (ch) { case 'h': - //usage(argv[0]); + usage(argv[0]); exit(0); case 'V': //version(argv[0]); diff -r d4d880fcef28 -r b35215021b32 tools/console/daemon/utils.c --- a/tools/console/daemon/utils.c Fri Sep 9 16:31:36 2005 +++ b/tools/console/daemon/utils.c Tue Sep 13 16:14:16 2005 @@ -105,7 +105,8 @@ close(fd); umask(027); - chdir("/"); + if (chdir("/") < 0) + exit (1); fd = open(pidfile, O_RDWR | O_CREAT); if (fd == -1) { @@ -117,7 +118,8 @@ } len = sprintf(buf, "%d\n", getpid()); - write(fd, buf, len); + if (write(fd, buf, len) < 0) + exit(1); signal(SIGCHLD, child_exit); signal(SIGTSTP, SIG_IGN); diff -r d4d880fcef28 -r b35215021b32 tools/examples/Makefile --- a/tools/examples/Makefile Fri Sep 9 16:31:36 2005 +++ b/tools/examples/Makefile Tue Sep 13 16:14:16 2005 @@ -21,10 +21,11 @@ XEN_SCRIPT_DIR = /etc/xen/scripts XEN_SCRIPTS = network-bridge vif-bridge XEN_SCRIPTS += network-route vif-route +XEN_SCRIPTS += block-phy XEN_SCRIPTS += block-file XEN_SCRIPTS += block-enbd -XEN_BOOT_DIR = /usr/lib/xen/boot +XEN_BOOT_DIR = /usr/$(LIBDIR)/xen/boot XEN_BOOT = mem-map.sxp XEN_HOTPLUG_DIR = /etc/hotplug @@ -36,12 +37,15 @@ install: all install-initd install-configs install-scripts install-boot \ install-hotplug +xmexample.vmx: xmexample.vmx.in + sed -e 's/@@LIBDIR@@/$(LIBDIR)/' < $< > $@ + install-initd: [ -d $(DESTDIR)/etc/init.d ] || $(INSTALL_DIR) $(DESTDIR)/etc/init.d $(INSTALL_PROG) $(XEND_INITD) $(DESTDIR)/etc/init.d $(INSTALL_PROG) $(XENDOMAINS_INITD) $(DESTDIR)/etc/init.d -install-configs: +install-configs: $(XEN_CONFIGS) [ -d $(DESTDIR)$(XEN_CONFIG_DIR) ] || \ $(INSTALL_DIR) $(DESTDIR)$(XEN_CONFIG_DIR) [ -d $(DESTDIR)$(XEN_CONFIG_DIR)/auto ] || \ @@ -76,3 +80,4 @@ done clean: + $(RM) xmexample.vmx diff -r d4d880fcef28 -r b35215021b32 tools/examples/block-enbd --- a/tools/examples/block-enbd Fri Sep 9 16:31:36 2005 +++ b/tools/examples/block-enbd Tue Sep 13 16:14:16 2005 @@ -3,31 +3,31 @@ # Usage: block-enbd [bind server ctl_port |unbind node] # # The file argument to the bind command is the file we are to bind to a -# loop device. We print the path to the loop device node to stdout. +# loop device. # # The node argument to unbind is the name of the device node we are to # unbind. # # This assumes you're running a correctly configured server at the other end! +set -e + case $1 in - bind) - for dev in /dev/nd*; do - if nbd-client $2:$3 $dev; then - echo $dev - exit 0 - fi - done - exit 1 - ;; - - unbind) - nbd-client -d $2 - exit 0 - ;; - - *) - echo 'Unknown command: ' $1 >&2 - echo 'Valid commands are: bind, unbind' >&2 - exit 1 + bind) + for dev in /dev/nd*; do + if nbd-client $2:$3 $dev; then + major=$(stat -L -c %t "$dev") + minor=$(stat -L -c %T "$dev") + pdev=$(printf "0x%02x%02x" 0x$major 0x$minor) + xenstore-write "$XENBUS_PATH"/physical-device $pdev \ + "$XENBUS_PATH"/node $dev + exit 0 + fi + done + exit 1 + ;; + unbind) + nbd-client -d $2 + exit 0 + ;; esac diff -r d4d880fcef28 -r b35215021b32 tools/examples/block-file --- a/tools/examples/block-file Fri Sep 9 16:31:36 2005 +++ b/tools/examples/block-file Tue Sep 13 16:14:16 2005 @@ -3,29 +3,29 @@ # Usage: block_loop [bind file|unbind node] # # The file argument to the bind command is the file we are to bind to a -# loop device. We print the path to the loop device node to stdout. +# loop device. # # The node argument to unbind is the name of the device node we are to # unbind. +set -e + case $1 in - bind) - for dev in /dev/loop*; do - if losetup $dev $2; then - echo $dev - exit 0 - fi - done - exit 1 - ;; - - unbind) - losetup -d $2 - exit 0 - ;; - - *) - echo 'Unknown command: ' $1 >&2 - echo 'Valid commands are: bind, unbind' >&2 - exit 1 + bind) + for dev in /dev/loop*; do + if losetup $dev $2; then + major=$(stat -L -c %t "$dev") + minor=$(stat -L -c %T "$dev") + pdev=$(printf "0x%02x%02x" 0x$major 0x$minor) + xenstore-write "$XENBUS_PATH"/physical-device $pdev \ + "$XENBUS_PATH"/node $dev + exit 0 + fi + done + exit 1 + ;; + unbind) + losetup -d $2 + exit 0 + ;; esac diff -r d4d880fcef28 -r b35215021b32 tools/examples/xen-backend.agent --- a/tools/examples/xen-backend.agent Fri Sep 9 16:31:36 2005 +++ b/tools/examples/xen-backend.agent Tue Sep 13 16:14:16 2005 @@ -9,8 +9,26 @@ case "$ACTION" in add) + case "$XENBUS_TYPE" in + vbd) + t=$(xenstore-read "$XENBUS_PATH"/type) + params=$(xenstore-read "$XENBUS_PATH"/params) + [ -x /etc/xen/scripts/block-"$t" ] && \ + /etc/xen/scripts/block-"$t" bind $params + ;; + esac ;; remove) + case "$XENBUS_TYPE" in + vbd) + t=$(xenstore-read "$XENBUS_PATH"/type) + node=$(xenstore-read "$XENBUS_PATH"/node) + [ -x /etc/xen/scripts/block-"$t" ] && \ + /etc/xen/scripts/block-"$t" unbind $node + ;; + esac + # remove device backend store entries + xenstore-rm "$XENBUS_PATH" ;; online) case "$PHYSDEVDRIVER" in diff -r d4d880fcef28 -r b35215021b32 tools/ioemu/hw/pcnet.c --- a/tools/ioemu/hw/pcnet.c Fri Sep 9 16:31:36 2005 +++ b/tools/ioemu/hw/pcnet.c Tue Sep 13 16:14:16 2005 @@ -380,10 +380,13 @@ return sizeof(s->buffer)-16; } +#define MIN_BUF_SIZE 60 + static void pcnet_receive(void *opaque, const uint8_t *buf, int size) { PCNetState *s = opaque; int is_padr = 0, is_bcast = 0, is_ladr = 0; + uint8_t buf1[60]; if (CSR_DRX(s) || CSR_STOP(s) || CSR_SPND(s) || !size) return; @@ -391,6 +394,14 @@ #ifdef PCNET_DEBUG printf("pcnet_receive size=%d\n", size); #endif + + /* if too small buffer, then expand it */ + if (size < MIN_BUF_SIZE) { + memcpy(buf1, buf, size); + memset(buf1 + size, 0, MIN_BUF_SIZE - size); + buf = buf1; + size = MIN_BUF_SIZE; + } if (CSR_PROM(s) || (is_padr=padr_match(s, buf, size)) diff -r d4d880fcef28 -r b35215021b32 tools/ioemu/target-i386-dm/Makefile --- a/tools/ioemu/target-i386-dm/Makefile Fri Sep 9 16:31:36 2005 +++ b/tools/ioemu/target-i386-dm/Makefile Tue Sep 13 16:14:16 2005 @@ -3,7 +3,7 @@ include config.mak override TARGET_ARCH=i386 -INSTALL_DIR := $(DESTDIR)/usr/lib/xen/bin +INSTALL_DIR := $(DESTDIR)/usr/$(LIBDIR)/xen/bin TARGET_PATH=$(SRC_PATH)/target-$(TARGET_ARCH) VPATH=$(SRC_PATH):$(TARGET_PATH):$(SRC_PATH)/hw:$(SRC_PATH)/audio DEFINES=-I. -I$(TARGET_PATH) -I$(SRC_PATH) -I$(XEN_ROOT)/xen/include/public diff -r d4d880fcef28 -r b35215021b32 tools/libxc/xc_linux_restore.c --- a/tools/libxc/xc_linux_restore.c Fri Sep 9 16:31:36 2005 +++ b/tools/libxc/xc_linux_restore.c Tue Sep 13 16:14:16 2005 @@ -42,18 +42,18 @@ unsigned char *b = buf; while (r < count) { - s = read(fd, &b[r], count - r); - if (s <= 0) - break; - r += s; + s = read(fd, &b[r], count - r); + if (s <= 0) + break; + r += s; } return r; } int xc_linux_restore(int xc_handle, int io_fd, u32 dom, unsigned long nr_pfns, - unsigned int store_evtchn, unsigned long *store_mfn, - unsigned int console_evtchn, unsigned long *console_mfn) + unsigned int store_evtchn, unsigned long *store_mfn, + unsigned int console_evtchn, unsigned long *console_mfn) { dom0_op_t op; int rc = 1, i, n, k; @@ -91,6 +91,8 @@ /* A temporary mapping of the guest's start_info page. */ start_info_t *start_info; + int pt_levels = 2; /* XXX auto-detect this */ + char *region_base; xc_mmu_t *mmu = NULL; @@ -112,8 +114,8 @@ } if (read_exact(io_fd, pfn_to_mfn_frame_list, PAGE_SIZE) != PAGE_SIZE) { - ERR("read pfn_to_mfn_frame_list failed"); - goto out; + ERR("read pfn_to_mfn_frame_list failed"); + goto out; } /* We want zeroed memory so use calloc rather than malloc. */ @@ -289,10 +291,10 @@ if ( xpfn >= nr_pfns ) { ERR("Frame number in type %lu page " - "table is out of range. i=%d k=%d " - "pfn=0x%lx nr_pfns=%lu", - region_pfn_type[i]>>28, i, - k, xpfn, nr_pfns); + "table is out of range. i=%d k=%d " + "pfn=0x%lx nr_pfns=%lu", + region_pfn_type[i]>>28, i, + k, xpfn, nr_pfns); goto out; } @@ -317,10 +319,10 @@ if ( xpfn >= nr_pfns ) { ERR("Frame number in type %lu page" - " table is out of range. i=%d k=%d " - "pfn=%lu nr_pfns=%lu", - region_pfn_type[i]>>28, i, k, - xpfn, nr_pfns); + " table is out of range. i=%d k=%d " + "pfn=%lu nr_pfns=%lu", + region_pfn_type[i]>>28, i, k, + xpfn, nr_pfns); goto out; } @@ -334,8 +336,8 @@ default: ERR("Bogus page type %lx page table is " - "out of range. i=%d nr_pfns=%lu", - region_pfn_type[i], i, nr_pfns); + "out of range. i=%d nr_pfns=%lu", + region_pfn_type[i], i, nr_pfns); goto out; } /* end of page type switch statement */ @@ -362,8 +364,8 @@ } if ( xc_add_mmu_update(xc_handle, mmu, - (mfn<<PAGE_SHIFT) | MMU_MACHPHYS_UPDATE, - pfn) ) + (mfn<<PAGE_SHIFT) | MMU_MACHPHYS_UPDATE, + pfn) ) { printf("machpys mfn=%ld pfn=%ld\n",mfn,pfn); goto out; @@ -376,6 +378,33 @@ } DPRINTF("Received all pages\n"); + + if ( pt_levels == 3 ) + { + /* Get all PGDs below 4GB. */ + for ( i = 0; i < nr_pfns; i++ ) + { + if ( ((pfn_type[i] & LTABTYPE_MASK) == L3TAB) && + (pfn_to_mfn_table[i] > 0xfffffUL) ) + { + unsigned long new_mfn = xc_make_page_below_4G( + xc_handle, dom, pfn_to_mfn_table[i]); + if ( new_mfn == 0 ) + { + fprintf(stderr, "Couldn't get a page below 4GB :-(\n"); + goto out; + } + pfn_to_mfn_table[i] = new_mfn; + if ( xc_add_mmu_update( + xc_handle, mmu, (new_mfn << PAGE_SHIFT) | + MMU_MACHPHYS_UPDATE, i) ) + { + fprintf(stderr, "Couldn't m2p on PAE root pgdir\n"); + goto out; + } + } + } + } if ( xc_finish_mmu_updates(xc_handle, mmu) ) goto out; @@ -410,57 +439,57 @@ /* Get the list of PFNs that are not in the psuedo-phys map */ { - unsigned int count; + unsigned int count; unsigned long *pfntab; - int rc; - - if ( read_exact(io_fd, &count, sizeof(count)) != sizeof(count) ) - { - ERR("Error when reading pfn count"); - goto out; - } - - pfntab = malloc( sizeof(unsigned int) * count ); - if ( pfntab == NULL ) - { - ERR("Out of memory"); - goto out; - } - - if ( read_exact(io_fd, pfntab, sizeof(unsigned int)*count) != + int rc; + + if ( read_exact(io_fd, &count, sizeof(count)) != sizeof(count) ) + { + ERR("Error when reading pfn count"); + goto out; + } + + pfntab = malloc( sizeof(unsigned int) * count ); + if ( pfntab == NULL ) + { + ERR("Out of memory"); + goto out; + } + + if ( read_exact(io_fd, pfntab, sizeof(unsigned int)*count) != sizeof(unsigned int)*count ) - { - ERR("Error when reading pfntab"); - goto out; - } - - for ( i = 0; i < count; i++ ) - { - unsigned long pfn = pfntab[i]; - pfntab[i]=pfn_to_mfn_table[pfn]; - pfn_to_mfn_table[pfn] = 0x80000001; // not in pmap - } - - if ( count > 0 ) - { + { + ERR("Error when reading pfntab"); + goto out; + } + + for ( i = 0; i < count; i++ ) + { + unsigned long pfn = pfntab[i]; + pfntab[i]=pfn_to_mfn_table[pfn]; + pfn_to_mfn_table[pfn] = 0x80000001; // not in pmap + } + + if ( count > 0 ) + { struct xen_memory_reservation reservation = { .extent_start = pfntab, .nr_extents = count, .extent_order = 0, .domid = dom }; - if ( (rc = xc_memory_op(xc_handle, + if ( (rc = xc_memory_op(xc_handle, XENMEM_decrease_reservation, &reservation)) != count ) - { - ERR("Could not decrease reservation : %d",rc); - goto out; - } - else - { - printf("Decreased reservation by %d pages\n", count); - } - } + { + ERR("Could not decrease reservation : %d",rc); + goto out; + } + else + { + printf("Decreased reservation by %d pages\n", count); + } + } } if ( read_exact(io_fd, &ctxt, sizeof(ctxt)) != sizeof(ctxt) || @@ -484,10 +513,10 @@ start_info->shared_info = shared_info_frame << PAGE_SHIFT; start_info->flags = 0; *store_mfn = start_info->store_mfn = - pfn_to_mfn_table[start_info->store_mfn]; + pfn_to_mfn_table[start_info->store_mfn]; start_info->store_evtchn = store_evtchn; *console_mfn = start_info->console_mfn = - pfn_to_mfn_table[start_info->console_mfn]; + pfn_to_mfn_table[start_info->console_mfn]; start_info->console_evtchn = console_evtchn; munmap(start_info, PAGE_SIZE); @@ -522,7 +551,7 @@ /* clear any pending events and the selector */ memset(&(shared_info->evtchn_pending[0]), 0, - sizeof (shared_info->evtchn_pending)); + sizeof (shared_info->evtchn_pending)); for ( i = 0; i < MAX_VIRT_CPUS; i++ ) shared_info->vcpu_data[i].evtchn_pending_sel = 0; @@ -548,7 +577,7 @@ } if ( (live_pfn_to_mfn_table = - xc_map_foreign_batch(xc_handle, dom, + xc_map_foreign_batch(xc_handle, dom, PROT_WRITE, pfn_to_mfn_frame_list, (nr_pfns+1023)/1024 )) == 0 ) diff -r d4d880fcef28 -r b35215021b32 tools/libxc/xc_private.c --- a/tools/libxc/xc_private.c Fri Sep 9 16:31:36 2005 +++ b/tools/libxc/xc_private.c Tue Sep 13 16:14:16 2005 @@ -425,23 +425,49 @@ int xc_version(int xc_handle, int cmd, void *arg) { - return do_xen_version(xc_handle, cmd, arg); -} - -unsigned long xc_make_page_below_4G(int xc_handle, u32 domid, - unsigned long mfn) + int rc, argsize = 0; + + switch ( cmd ) + { + case XENVER_extraversion: argsize = sizeof(xen_extraversion_t); break; + case XENVER_compile_info: argsize = sizeof(xen_compile_info_t); break; + case XENVER_capabilities: argsize = sizeof(xen_capabilities_info_t); break; + case XENVER_changeset: argsize = sizeof(xen_changeset_info_t); break; + case XENVER_parameters: argsize = sizeof(xen_parameters_info_t); break; + } + + if ( (argsize != 0) && (mlock(arg, argsize) != 0) ) + { + PERROR("Could not lock memory for version hypercall"); + return -ENOMEM; + } + + rc = do_xen_version(xc_handle, cmd, arg); + + if ( argsize != 0 ) + safe_munlock(arg, argsize); + + return rc; +} + +unsigned long xc_make_page_below_4G( + int xc_handle, u32 domid, unsigned long mfn) { unsigned long new_mfn; + if ( xc_domain_memory_decrease_reservation( - xc_handle, domid, 1, 0, &mfn ) != 1 ) + xc_handle, domid, 1, 0, &mfn) != 1 ) { fprintf(stderr,"xc_make_page_below_4G decrease failed. mfn=%lx\n",mfn); return 0; } - if ( xc_domain_memory_increase_reservation( xc_handle, domid, 1, 0, 32, &new_mfn ) != 1 ) + + if ( xc_domain_memory_increase_reservation( + xc_handle, domid, 1, 0, 32, &new_mfn) != 1 ) { fprintf(stderr,"xc_make_page_below_4G increase failed. mfn=%lx\n",mfn); return 0; } + return new_mfn; } diff -r d4d880fcef28 -r b35215021b32 tools/libxc/xc_vmx_build.c --- a/tools/libxc/xc_vmx_build.c Fri Sep 9 16:31:36 2005 +++ b/tools/libxc/xc_vmx_build.c Tue Sep 13 16:14:16 2005 @@ -578,15 +578,6 @@ sp->sp_global.eport = control_evtchn; munmap(sp, PAGE_SIZE); - /* - * Pin down l2tab addr as page dir page - causes hypervisor to provide - * correct protection for the page - */ -#ifdef __i386__ - if ( pin_table(xc_handle, MMUEXT_PIN_L2_TABLE, l2tab>>PAGE_SHIFT, dom) ) - goto error_out; -#endif - /* Send the page update requests down to the hypervisor. */ if ( xc_finish_mmu_updates(xc_handle, mmu) ) goto error_out; diff -r d4d880fcef28 -r b35215021b32 tools/python/Makefile --- a/tools/python/Makefile Fri Sep 9 16:31:36 2005 +++ b/tools/python/Makefile Tue Sep 13 16:14:16 2005 @@ -1,6 +1,7 @@ - XEN_ROOT = ../.. include $(XEN_ROOT)/tools/Rules.mk + +.PHONY: all build install clean all: build build: diff -r d4d880fcef28 -r b35215021b32 tools/python/xen/lowlevel/xc/xc.c --- a/tools/python/xen/lowlevel/xc/xc.c Fri Sep 9 16:31:36 2005 +++ b/tools/python/xen/lowlevel/xc/xc.c Tue Sep 13 16:14:16 2005 @@ -756,7 +756,7 @@ "xen_major", xen_version >> 16, "xen_minor", (xen_version & 0xffff), "xen_extra", xen_extra, - "xen_caps", xen_caps.caps, + "xen_caps", xen_caps, "xen_params", str, "xen_changeset", xen_chgset, "cc_compiler", xen_cc.compiler, diff -r d4d880fcef28 -r b35215021b32 tools/python/xen/sv/DomInfo.py --- a/tools/python/xen/sv/DomInfo.py Fri Sep 9 16:31:36 2005 +++ b/tools/python/xen/sv/DomInfo.py Tue Sep 13 16:14:16 2005 @@ -75,7 +75,7 @@ class DomGenTab( GeneralTab ): - def __init__( self, urlWriter ): + def __init__( self, _ ): titles = {} @@ -103,7 +103,7 @@ class DomSXPTab( PreTab ): - def __init__( self, urlWriter ): + def __init__( self, _ ): self.dom = 0 PreTab.__init__( self, "" ) @@ -126,7 +126,7 @@ class DomActionTab( ActionTab ): - def __init__( self, urlWriter ): + def __init__( self, _ ): actions = { "shutdown" : "Shutdown", "reboot" : "Reboot", "pause" : "Pause", @@ -188,19 +188,19 @@ title = "Device List" - def __init__( self, urlWriter ): + def __init__( self, _ ): pass class DomDeviceOptionsTab( NullTab ): title = "Device Options" - def __init__( self, urlWriter ): + def __init__( self, _ ): pass class DomDeviceActionTab( ActionTab ): - def __init__( self, urlWriter ): + def __init__( self, _ ): ActionTab.__init__( self, { "addvcpu" : "Add VCPU", "addvbd" : "Add VBD", "addvif" : "Add VIF" } ) class DomMigrateTab( CompositeTab ): @@ -218,7 +218,7 @@ class DomMigrateActionTab( ActionTab ): - def __init__( self, urlWriter ): + def __init__( self, _ ): actions = { "migrate" : "Migrate" } ActionTab.__init__( self, actions ) @@ -249,7 +249,7 @@ class DomSaveActionTab( ActionTab ): - def __init__( self, urlWriter ): + def __init__( self, _ ): actions = { "save" : "Save" } ActionTab.__init__( self, actions ) diff -r d4d880fcef28 -r b35215021b32 tools/python/xen/xend/XendDomainInfo.py --- a/tools/python/xen/xend/XendDomainInfo.py Fri Sep 9 16:31:36 2005 +++ b/tools/python/xen/xend/XendDomainInfo.py Tue Sep 13 16:14:16 2005 @@ -47,6 +47,7 @@ from xen.xend.uuid import getUuid from xen.xend.xenstore import DBVar, XenNode, DBMap +from xen.xend.xenstore.xstransact import xstransact """Shutdown code for poweroff.""" DOMAIN_POWEROFF = 0 @@ -101,34 +102,6 @@ """ return shutdown_reasons.get(code, "?") -config_handlers = {} - -def add_config_handler(name, h): - """Add a handler for a config field. - - @param name: field name - @param h: handler: fn(vm, config, field, index) - """ - config_handlers[name] = h - -def get_config_handler(name): - """Get a handler for a config field. - - returns handler or None - """ - return config_handlers.get(name) - -"""Table of handlers for devices. -Indexed by device type. -""" -device_handlers = {} - -def add_device_handler(name, type): - device_handlers[name] = type - -def get_device_handler(name): - return device_handlers[name] - def dom_get(dom): """Get info from xen for an existing domain. @@ -156,7 +129,8 @@ """ uuid = getUuid() db = parentdb.addChild(uuid) - vm = cls(db) + path = parentdb.getPath() + vm = cls(uuid, path, db) vm.construct(config) vm.saveToDB(sync=True) @@ -171,7 +145,8 @@ @param info: domain info from xc """ dom = info['dom'] - vm = cls(db) + path = "/".join(db.getPath().split("/")[0:-1]) + vm = cls(db.getName(), path, db) vm.setdom(dom) db.readDB() vm.importFromDB() @@ -206,7 +181,8 @@ if not uuid: uuid = getUuid() db = parentdb.addChild(uuid) - vm = cls(db) + path = parentdb.getPath() + vm = cls(uuid, path, db) ssidref = int(sxp.child_value(config, 'ssidref')) log.debug('restoring with ssidref='+str(ssidref)) id = xc.domain_create(ssidref = ssidref) @@ -239,9 +215,10 @@ DBVar('device_model_pid', ty='int'), ] - def __init__(self, db): + def __init__(self, uuid, path, db): + self.uuid = uuid + self.path = path + "/" + uuid self.db = db - self.uuid = db.getName() self.recreate = 0 self.restore = 0 @@ -364,12 +341,6 @@ __repr__ = __str__ - def getDeviceTypes(self): - return self.controllers.keys() - - def getDeviceControllers(self): - return self.controllers.values() - def getDeviceController(self, type, error=True): ctrl = self.controllers.get(type) if not ctrl and error: @@ -392,35 +363,28 @@ typedev = sxp.child_value(devconfig, 'dev') if re.match('^ioemu:', typedev): return; + backdom = domain_exists(sxp.child_value(devconfig, 'backend', '0')) devnum = blkdev_name_to_number(sxp.child_value(devconfig, 'dev')) - # create backend db - backdb = backdom.db.addChild("/backend/%s/%s/%d" % - (type, self.uuid, devnum)) - - # create frontend db - db = self.db.addChild("/device/%s/%d" % (type, devnum)) - - db['virtual-device'] = "%i" % devnum - #db['backend'] = sxp.child_value(devconfig, 'backend', '0') - db['backend'] = backdb.getPath() - db['backend-id'] = "%i" % backdom.id - - backdb['frontend'] = db.getPath() - (type, params) = string.split(sxp.child_value(devconfig, 'uname'), ':', 1) - node = Blkctl.block('bind', type, params) - backdb['frontend-id'] = "%i" % self.id - backdb['physical-device'] = "%li" % blkdev_name_to_number(node) - backdb.saveDB(save=True) - - # Ok, super gross, this really doesn't belong in the frontend db... - db['type'] = type - db['node'] = node - db['params'] = params - db.saveDB(save=True) - + backpath = "%s/backend/%s/%s/%d" % (backdom.path, type, + self.uuid, devnum) + frontpath = "%s/device/%s/%d" % (self.path, type, devnum) + + front = { 'backend' : backpath, + 'backend-id' : "%i" % backdom.id, + 'virtual-device' : "%i" % devnum } + xstransact.Write(frontpath, front) + + (type, params) = string.split(sxp.child_value(devconfig, + 'uname'), ':', 1) + back = { 'type' : type, + 'params' : params, + 'frontend' : frontpath, + 'frontend-id' : "%i" % self.id } + xstransact.Write(backpath, back) + return if type == 'vif': @@ -435,8 +399,6 @@ backdom = domain_exists(sxp.child_value(devconfig, 'backend', '0')) - log.error(devconfig) - devnum = self.netif_idx self.netif_idx += 1 @@ -448,30 +410,26 @@ mac = sxp.child_value(devconfig, 'mac') ipaddr = _get_config_ipaddr(devconfig) - # create backend db - backdb = backdom.db.addChild("/backend/%s/%s/%d" % - (type, self.uuid, devnum)) - - # create frontend db - db = self.db.addChild("/device/%s/%d" % (type, devnum)) - - backdb['script'] = script - backdb['domain'] = self.name - backdb['mac'] = mac - backdb['bridge'] = bridge + backpath = "%s/backend/%s/%s/%d" % (backdom.path, type, + self.uuid, devnum) + frontpath = "%s/device/%s/%d" % (self.path, type, devnum) + + front = { 'backend' : backpath, + 'backend-id' : "%i" % backdom.id, + 'handle' : "%i" % devnum, + 'mac' : mac } + xstransact.Write(frontpath, front) + + back = { 'script' : script, + 'domain' : self.name, + 'mac' : mac, + 'bridge' : bridge, + 'frontend' : frontpath, + 'frontend-id' : "%i" % self.id, + 'handle' : "%i" % devnum } if ipaddr: - backdb['ip'] = ' '.join(ipaddr) - backdb['frontend'] = db.getPath() - backdb['frontend-id'] = "%i" % self.id - backdb['handle'] = "%i" % devnum - backdb.saveDB(save=True) - - db['backend'] = backdb.getPath() - db['backend-id'] = "%i" % backdom.id - db['handle'] = "%i" % devnum - db['mac'] = mac - - db.saveDB(save=True) + back['ip'] = ' '.join(ipaddr) + xstransact.Write(backpath, back) return @@ -481,22 +439,19 @@ devnum = int(sxp.child_value(devconfig, 'instance', '0')) log.error("The domain has a TPM with instance %d." % devnum) - # create backend db - backdb = backdom.db.addChild("/backend/%s/%s/%d" % - (type, self.uuid, devnum)) - # create frontend db - db = self.db.addChild("/device/%s/%d" % (type, devnum)) - - backdb['frontend'] = db.getPath() - backdb['frontend-id'] = "%i" % self.id - backdb['instance'] = sxp.child_value(devconfig, 'instance', '0') - backdb.saveDB(save=True) - - db['handle'] = "%i" % devnum - db['backend'] = backdb.getPath() - db['backend-id'] = "%i" % int(sxp.child_value(devconfig, - 'backend', '0')) - db.saveDB(save=True) + backpath = "%s/backend/%s/%s/%d" % (backdom.path, type, + self.uuid, devnum) + frontpath = "%s/device/%s/%d" % (self.path, type, devnum) + + front = { 'backend' : backpath, + 'backend-id' : "%i" % backdom.id, + 'handle' : "%i" % devnum } + xstransact.Write(frontpath, front) + + back = { 'instance' : "%i" % devnum, + 'frontend' : frontpath, + 'frontend-id' : "%i" % self.id } + xstransact.Write(backpath, back) return @@ -594,7 +549,7 @@ def sxpr_devices(self): sxpr = [] - for ty in self.getDeviceTypes(): + for ty in self.controllers.keys(): devs = self.getDeviceSxprs(ty) sxpr += devs if sxpr: @@ -795,29 +750,17 @@ """Release all vm devices. """ reboot = self.restart_pending() - for ctrl in self.getDeviceControllers(): + for ctrl in self.controllers.values(): if ctrl.isDestroyed(): continue ctrl.destroyController(reboot=reboot) - ddb = self.db.addChild("/device") - for type in ddb.keys(): - if type == 'vbd': - typedb = ddb.addChild(type) - for dev in typedb.keys(): - devdb = typedb.addChild(str(dev)) - Blkctl.block('unbind', devdb['type'].getData(), - devdb['node'].getData()) - typedb[dev].delete() - typedb.saveDB(save=True) - if type == 'vif': - typedb = ddb.addChild(type) - for dev in typedb.keys(): - typedb[dev].delete() - typedb.saveDB(save=True) - if type == 'vtpm': - typedb = ddb.addChild(type) - for dev in typedb.keys(): - typedb[dev].delete() - typedb.saveDB(save=True) + t = xstransact("%s/device" % self.path) + for d in t.list("vbd"): + t.remove(d) + for d in t.list("vif"): + t.remove(d) + for d in t.list("vtpm"): + t.remove(d) + t.commit() def show(self): """Print virtual machine info. @@ -874,6 +817,7 @@ self.store_channel = self.eventChannelOld("store_channel") self.console_channel = self.eventChannel("console", "port") + def create_configured_devices(self): devices = sxp.children(self.config, 'device') for d in devices: @@ -881,18 +825,20 @@ if dev_config is None: raise VmError('invalid device') dev_type = sxp.name(dev_config) - ctrl_type = get_device_handler(dev_type) - if ctrl_type is None: + + if not controller.isDevControllerClass(dev_type): raise VmError('unknown device type: ' + dev_type) - self.createDevice(ctrl_type, dev_config) - + + self.createDevice(dev_type, dev_config) + + def create_devices(self): """Create the devices for a vm. @raise: VmError for invalid devices """ if self.rebooting(): - for ctrl in self.getDeviceControllers(): + for ctrl in self.controllers.values(): ctrl.initController(reboot=True) else: self.create_configured_devices() @@ -1043,7 +989,7 @@ msg = "Had a bootloader specified, but can't find disk" log.error(msg) raise VmError(msg) - config = sxp.merge(['vm', blconfig ], self.config) + config = sxp.merge(['vm', blcfg ], self.config) return config def configure_backends(self): @@ -1092,7 +1038,7 @@ for field in sxp.children(self.config): field_name = sxp.name(field) field_index = index.get(field_name, 0) - field_handler = get_config_handler(field_name) + field_handler = config_handlers.get(field_name) # Ignore unknown fields. Warn? if field_handler: v = field_handler(self, self.config, field, field_index) @@ -1161,23 +1107,17 @@ # get run-time value of vcpus and update store self.exportVCPUSToDB(dom_get(self.id)['vcpus']) -def vm_field_ignore(vm, config, val, index): + +def vm_field_ignore(_, _1, _2, _3): """Dummy config field handler used for fields with built-in handling. - - @param vm: virtual machine - @param config: vm config - @param val: config field - @param index: field index + Matches the signature required by config_handlers. """ pass -def vm_field_maxmem(vm, config, val, index): - """Configure vm memory limit. - - @param vm: virtual machine - @param config: vm config - @param val: config field - @param index: field index + +def vm_field_maxmem(vm, _1, val, _2): + """Config field handler to configure vm memory limit. Matches the + signature required by config_handlers. """ maxmem = sxp.child0(val) if maxmem is None: @@ -1188,8 +1128,10 @@ raise VmError("invalid maxmem: " + str(maxmem)) xc.domain_setmaxmem(vm.id, maxmem_kb = maxmem * 1024) + #============================================================================ # Register image handlers. + from image import \ addImageHandlerClass, \ ImageHandler, \ @@ -1199,43 +1141,38 @@ addImageHandlerClass(LinuxImageHandler) addImageHandlerClass(VmxImageHandler) -# Ignore the fields we already handle. -add_config_handler('name', vm_field_ignore) -add_config_handler('memory', vm_field_ignore) -add_config_handler('ssidref', vm_field_ignore) -add_config_handler('cpu', vm_field_ignore) -add_config_handler('cpu_weight', vm_field_ignore) -add_config_handler('restart', vm_field_ignore) -add_config_handler('image', vm_field_ignore) -add_config_handler('device', vm_field_ignore) -add_config_handler('backend', vm_field_ignore) -add_config_handler('vcpus', vm_field_ignore) -add_config_handler('bootloader', vm_field_ignore) - -# Register other config handlers. -add_config_handler('maxmem', vm_field_maxmem) + +"""Table of handlers for field configuration. + +field_name[String]: fn(vm, config, field, index) -> value(ignored) +""" +config_handlers = { + + # Ignore the fields we already handle. + + 'name': vm_field_ignore, + 'memory': vm_field_ignore, + 'ssidref': vm_field_ignore, + 'cpu': vm_field_ignore, + 'cpu_weight': vm_field_ignore, + 'restart': vm_field_ignore, + 'image': vm_field_ignore, + 'device': vm_field_ignore, + 'backend': vm_field_ignore, + 'vcpus': vm_field_ignore, + 'bootloader': vm_field_ignore, + + # Register other config handlers. + 'maxmem': vm_field_maxmem + } + #============================================================================ # Register device controllers and their device config types. -from server import blkif -controller.addDevControllerClass("vbd", blkif.BlkifController) -add_device_handler("vbd", "vbd") - -from server import netif -controller.addDevControllerClass("vif", netif.NetifController) -add_device_handler("vif", "vif") - -from server import tpmif +from xen.xend.server import blkif, netif, tpmif, pciif, usbif +controller.addDevControllerClass("vbd", blkif.BlkifController) +controller.addDevControllerClass("vif", netif.NetifController) controller.addDevControllerClass("vtpm", tpmif.TPMifController) -add_device_handler("vtpm", "vtpm") - -from server import pciif -controller.addDevControllerClass("pci", pciif.PciController) -add_device_handler("pci", "pci") - -from xen.xend.server import usbif -controller.addDevControllerClass("usb", usbif.UsbifController) -add_device_handler("usb", "usb") - -#============================================================================ +controller.addDevControllerClass("pci", pciif.PciController) +controller.addDevControllerClass("usb", usbif.UsbifController) diff -r d4d880fcef28 -r b35215021b32 tools/python/xen/xend/XendVnet.py --- a/tools/python/xen/xend/XendVnet.py Fri Sep 9 16:31:36 2005 +++ b/tools/python/xen/xend/XendVnet.py Tue Sep 13 16:14:16 2005 @@ -145,7 +145,7 @@ def vnet_get(self, id): """Get a vnet. - @param id: vnet id + @param id vnet id """ id = str(id) return self.vnet.get(id) diff -r d4d880fcef28 -r b35215021b32 tools/python/xen/xend/scheduler.py --- a/tools/python/xen/xend/scheduler.py Fri Sep 9 16:31:36 2005 +++ b/tools/python/xen/xend/scheduler.py Tue Sep 13 16:14:16 2005 @@ -20,8 +20,8 @@ def later(delay, fn, args=(), kwargs={}): """Schedule a function to be called later. - @param _delay: delay in seconds - @param _fn: function + @param delay: delay in seconds + @param fn: function @param args: arguments (list) @param kwargs keyword arguments (map) """ @@ -32,7 +32,7 @@ def now(fn, args=(), kwargs={}): """Schedule a function to be called now. - @param _fn: function + @param fn: function @param args: arguments (list) @param kwargs keyword arguments (map) """ diff -r d4d880fcef28 -r b35215021b32 tools/python/xen/xend/server/controller.py --- a/tools/python/xen/xend/server/controller.py Fri Sep 9 16:31:36 2005 +++ b/tools/python/xen/xend/server/controller.py Tue Sep 13 16:14:16 2005 @@ -62,6 +62,13 @@ """ cls.type = name getDevControllerTable().addDevControllerClass(cls) + + +def isDevControllerClass(name): + """@return True if a device controller class has been registered with + the controller table under the given name.""" + return name in getDevControllerTable().controllerClasses + def createDevController(name, vm, recreate=False): return getDevControllerTable().createDevController(name, vm, recreate=recreate) diff -r d4d880fcef28 -r b35215021b32 tools/python/xen/xend/xenstore/xstransact.py --- a/tools/python/xen/xend/xenstore/xstransact.py Fri Sep 9 16:31:36 2005 +++ b/tools/python/xen/xend/xenstore/xstransact.py Tue Sep 13 16:14:16 2005 @@ -4,6 +4,7 @@ # Public License. See the file "COPYING" in the main directory of # this archive for more details. +import errno import threading from xen.lowlevel import xs @@ -18,9 +19,18 @@ class xstransact: def __init__(self, path): + self.in_transaction = False self.path = path.rstrip("/") - xshandle().transaction_start(path) - self.in_transaction = True + while True: + try: + xshandle().transaction_start(path) + self.in_transaction = True + return + except RuntimeError, ex: + if ex.args[0] == errno.ENOENT and path != "/": + path = "/".join(path.split("/")[0:-1]) or "/" + else: + raise def __del__(self): if self.in_transaction: @@ -78,36 +88,81 @@ else: raise TypeError + def _remove(self, key): + path = "%s/%s" % (self.path, key) + return xshandle().rm(path) + + def remove(self, *args): + if len(args) == 0: + raise TypeError + for key in args: + self._remove(key) + + def _list(self, key): + path = "%s/%s" % (self.path, key) + return map(lambda x: key + "/" + x, xshandle().ls(path)) + + def list(self, *args): + if len(args) == 0: + raise TypeError + ret = [] + for key in args: + ret.extend(self._list(key)) + return ret + + def Read(cls, path, *args): - t = cls(path) - v = t.read(*args) - t.commit() - return v + while True: + try: + t = cls(path) + v = t.read(*args) + t.commit() + return v + except RuntimeError, ex: + if ex.args[0] == errno.ETIMEDOUT: + pass + raise Read = classmethod(Read) def Write(cls, path, *args, **opts): - t = cls(path) - t.write(*args, **opts) - t.commit() + while True: + try: + t = cls(path) + t.write(*args, **opts) + t.commit() + return + except RuntimeError, ex: + if ex.args[0] == errno.ETIMEDOUT: + pass + raise Write = classmethod(Write) - def SafeRead(cls, path, *args): + def Remove(cls, *args): while True: try: - return cls.Read(path, *args) + t = cls(path) + t.remove(*args) + t.commit() + return except RuntimeError, ex: - pass + if ex.args[0] == errno.ETIMEDOUT: + pass + raise - SafeRead = classmethod(SafeRead) + Remove = classmethod(Remove) - def SafeWrite(cls, path, *args, **opts): + def List(cls, path, *args): while True: try: - cls.Write(path, *args, **opts) - return + t = cls(path) + v = t.list(*args) + t.commit() + return v except RuntimeError, ex: - pass + if ex.args[0] == errno.ETIMEDOUT: + pass + raise - SafeWrite = classmethod(SafeWrite) + List = classmethod(List) diff -r d4d880fcef28 -r b35215021b32 tools/python/xen/xm/create.py --- a/tools/python/xen/xm/create.py Fri Sep 9 16:31:36 2005 +++ b/tools/python/xen/xm/create.py Tue Sep 13 16:14:16 2005 @@ -772,30 +772,33 @@ """Balloon out memory from dom0 if necessary""" SLACK = 4 timeout = 20 # 2s - ret = 0 + ret = 1 xc = xen.lowlevel.xc.new() - pinfo = xc.physinfo() - free_mem = pinfo['free_pages'] / 256 + free_mem = xc.physinfo()['free_pages'] / 256 domU_need_mem = opts.vals.memory + SLACK + + # we already have enough free memory, return success + if free_mem >= domU_need_mem: + del xc + return 0 dom0_cur_alloc = get_dom0_alloc() dom0_new_alloc = dom0_cur_alloc - (domU_need_mem - free_mem) - - if free_mem < domU_need_mem and dom0_new_alloc < dom0_min_mem: - ret = 1 - if free_mem < domU_need_mem and ret == 0: - - server.xend_domain_mem_target_set(0, dom0_new_alloc) - - while dom0_cur_alloc > dom0_new_alloc and timeout > 0: - time.sleep(0.1) # sleep 100ms - dom0_cur_alloc = get_dom0_alloc() - timeout -= 1 - - if dom0_cur_alloc > dom0_new_alloc: - ret = 1 - + if dom0_new_alloc < dom0_min_mem: + dom0_new_alloc = dom0_min_mem + + server.xend_domain_mem_target_set(0, dom0_new_alloc) + + while timeout > 0: + time.sleep(0.1) # sleep 100ms + + free_mem = xc.physinfo()['free_pages'] / 256 + if free_mem >= domU_need_mem: + ret = 0 + break + timeout -= 1 + del xc return ret diff -r d4d880fcef28 -r b35215021b32 tools/python/xen/xm/main.py --- a/tools/python/xen/xm/main.py Fri Sep 9 16:31:36 2005 +++ b/tools/python/xen/xm/main.py Tue Sep 13 16:14:16 2005 @@ -450,7 +450,10 @@ info = server.xend_node() for x in info[1:]: - print "%-23s:" % x[0], x[1] + if len(x) < 2: + print "%-23s: (none)" % x[0] + else: + print "%-23s:" % x[0], x[1] # TODO: remove as soon as console server shows up def xm_console(args): diff -r d4d880fcef28 -r b35215021b32 tools/xenstore/Makefile --- a/tools/xenstore/Makefile Fri Sep 9 16:31:36 2005 +++ b/tools/xenstore/Makefile Tue Sep 13 16:14:16 2005 @@ -17,15 +17,15 @@ BASECFLAGS+= -I$(XEN_ROOT)/tools/libxc BASECFLAGS+= -I$(XEN_ROOT)/xen/include/public BASECFLAGS+= -I. -BASECFLAGS+= -I$(XEN_ROOT)/linux-2.6-xen-sparse/include/asm-xen/linux-public CFLAGS += $(BASECFLAGS) LDFLAGS += $(PROFILE) -L$(XEN_LIBXC) -TESTDIR = `pwd`/testsuite/tmp +TESTDIR = testsuite/tmp TESTFLAGS= -DTESTING TESTENV = XENSTORED_ROOTDIR=$(TESTDIR) XENSTORED_RUNDIR=$(TESTDIR) -CLIENTS := xenstore-read xenstore-rm xenstore-write +CLIENTS := xenstore-exists xenstore-list xenstore-read xenstore-rm +CLIENTS += xenstore-write CLIENTS_OBJS := $(patsubst xenstore-%,xenstore_%.o,$(CLIENTS)) all: libxenstore.so xenstored $(CLIENTS) @@ -80,10 +80,13 @@ fullcheck: testsuite-run randomcheck stresstest -testsuite-run: xenstored_test xs_test +$(TESTDIR): + mkdir $@ + +testsuite-run: xenstored_test xs_test $(TESTDIR) $(TESTENV) testsuite/test.sh && echo -testsuite-fast: xenstored_test xs_test +testsuite-fast: xenstored_test xs_test $(TESTDIR) @$(TESTENV) testsuite/test.sh --fast testsuite-clean: @@ -92,21 +95,21 @@ # Make this visible so they can see repeat tests without --fast if they # fail. RANDSEED=$(shell date +%s) -randomcheck: xs_random xenstored_test +randomcheck: xs_random xenstored_test $(TESTDIR) $(TESTENV) ./xs_random --simple --fast /tmp/xs_random 200000 $(RANDSEED) && echo $(TESTENV) ./xs_random --fast /tmp/xs_random 100000 $(RANDSEED) && echo $(TESTENV) ./xs_random --fail /tmp/xs_random 10000 $(RANDSEED) -crashme: xs_crashme xenstored_test +crashme: xs_crashme xenstored_test $(TESTDIR) rm -rf $(TESTDIR)/store $(TESTDIR)/transactions /tmp/xs_crashme.vglog* /tmp/trace export $(TESTENV); ./xs_crashme 5000 $(RANDSEED) 2>/dev/null if [ -n "`cat /tmp/xs_crashme.vglog*`" ]; then echo Valgrind complained; cat /tmp/xs_crashme.vglog*; exit 1; fi rm -rf $(TESTDIR)/store $(TESTDIR)/transactions /tmp/xs_crashme.vglog* /tmp/trace -randomcheck-fast: xs_random xenstored_test +randomcheck-fast: xs_random xenstored_test $(TESTDIR) @$(TESTENV) ./xs_random --fast /tmp/xs_random 2000 $(RANDSEED) -stresstest: xs_stress xenstored_test +stresstest: xs_stress xenstored_test $(TESTDIR) rm -rf $(TESTDIR)/store $(TESTDIR)/transactions export $(TESTENV); PID=`./xenstored_test --output-pid --trace-file=/tmp/trace`; ./xs_stress 5000; ret=$$?; kill $$PID; exit $$ret diff -r d4d880fcef28 -r b35215021b32 tools/xenstore/fake_libxc.c --- a/tools/xenstore/fake_libxc.c Fri Sep 9 16:31:36 2005 +++ b/tools/xenstore/fake_libxc.c Tue Sep 13 16:14:16 2005 @@ -83,6 +83,39 @@ return 0; } +int xc_domain_getinfo(int xc_handle __attribute__((unused)), + u32 first_domid, unsigned int max_doms, + xc_dominfo_t *info) +{ + assert(max_doms == 1); + info->domid = first_domid; + + info->dying = 0; + info->shutdown = 0; + info->paused = 0; + info->blocked = 0; + info->running = 1; + + info->shutdown_reason = 0; + + if ( info->shutdown && (info->shutdown_reason == SHUTDOWN_crash) ) + { + info->shutdown = 0; + info->crashed = 1; + } + + return 1; +} + +int xc_evtchn_bind_virq(int xc_handle __attribute__((unused)), + int virq __attribute__((unused)), + int *port) +{ + if (port) + *port = 0; + return 0; +} + static void send_to_fd(int signo __attribute__((unused))) { int saved_errno = errno; diff -r d4d880fcef28 -r b35215021b32 tools/xenstore/testsuite/07watch.test --- a/tools/xenstore/testsuite/07watch.test Fri Sep 9 16:31:36 2005 +++ b/tools/xenstore/testsuite/07watch.test Tue Sep 13 16:14:16 2005 @@ -34,12 +34,13 @@ 1 close 2 close -# We don't get a watch from our own commands. -watch /dir token -mkdir /dir/newdir -expect waitwatch failed: Connection timed out -waitwatch -close +# Changed in b594bb976a743d509f1ffabb5bc698874ab90d8f +## We don't get a watch from our own commands. +#watch /dir token +#mkdir /dir/newdir +#expect waitwatch failed: Connection timed out +#waitwatch +#close # ignore watches while doing commands, should work. watch /dir token diff -r d4d880fcef28 -r b35215021b32 tools/xenstore/testsuite/14complexperms.test --- a/tools/xenstore/testsuite/14complexperms.test Fri Sep 9 16:31:36 2005 +++ b/tools/xenstore/testsuite/14complexperms.test Tue Sep 13 16:14:16 2005 @@ -30,10 +30,8 @@ expect *Permission denied setperm /dir/file 0 NONE watch /dir/file token -setid 0 -write /dir/file create contents -rm /dir/file -setid 1 +1 write /dir/file create contents +1 rm /dir/file expect waitwatch failed: Connection timed out waitwatch unwatch /dir/file token @@ -78,10 +76,8 @@ expect *Permission denied setperm /dir/file 0 NONE watch /dir/file token -setid 0 -write /dir/file create contents -rm /dir/file -setid 1 +1 write /dir/file create contents +1 rm /dir/file expect waitwatch failed: Connection timed out waitwatch unwatch /dir/file token diff -r d4d880fcef28 -r b35215021b32 tools/xenstore/xenstore_client.c --- a/tools/xenstore/xenstore_client.c Fri Sep 9 16:31:36 2005 +++ b/tools/xenstore/xenstore_client.c Tue Sep 13 16:14:16 2005 @@ -22,7 +22,7 @@ errx(1, "Usage: %s [-h] [-p] key [...]", progname); #elif defined(CLIENT_write) errx(1, "Usage: %s [-h] key value [...]", progname); -#elif defined(CLIENT_rm) +#elif defined(CLIENT_rm) || defined(CLIENT_exists) || defined(CLIENT_list) errx(1, "Usage: %s [-h] key [...]", progname); #endif } @@ -33,8 +33,7 @@ struct xs_handle *xsh; bool success; int ret = 0; -#if defined(CLIENT_read) - char *val; +#if defined(CLIENT_read) || defined(CLIENT_list) int prefix = 0; #endif @@ -46,14 +45,14 @@ int c, index = 0; static struct option long_options[] = { {"help", 0, 0, 'h'}, -#if defined(CLIENT_read) +#if defined(CLIENT_read) || defined(CLIENT_list) {"prefix", 0, 0, 'p'}, #endif {0, 0, 0, 0} }; c = getopt_long(argc, argv, "h" -#if defined(CLIENT_read) +#if defined(CLIENT_read) || defined(CLIENT_list) "p" #endif , long_options, &index); @@ -64,7 +63,7 @@ case 'h': usage(argv[0]); /* NOTREACHED */ -#if defined(CLIENT_read) +#if defined(CLIENT_read) || defined(CLIENT_list) case 'p': prefix = 1; break; @@ -77,7 +76,7 @@ /* NOTREACHED */ } #if defined(CLIENT_write) - if ((argc - optind) % 1) { + if ((argc - optind) % 2 == 1) { usage(argv[0]); /* NOTREACHED */ } @@ -90,7 +89,7 @@ while (optind < argc) { #if defined(CLIENT_read) - val = xs_read(xsh, argv[optind], NULL); + char *val = xs_read(xsh, argv[optind], NULL); if (val == NULL) { warnx("couldn't read path %s", argv[optind]); ret = 1; @@ -118,6 +117,29 @@ goto out; } optind++; +#elif defined(CLIENT_exists) + char *val = xs_read(xsh, argv[optind], NULL); + if (val == NULL) { + ret = 1; + goto out; + } + free(val); + optind++; +#elif defined(CLIENT_list) + unsigned int i, num; + char **list = xs_directory(xsh, argv[optind], &num); + if (list == NULL) { + warnx("could not list path %s", argv[optind]); + ret = 1; + goto out; + } + for (i = 0; i < num; i++) { + if (prefix) + printf("%s/", argv[optind]); + printf("%s\n", list[i]); + } + free(list); + optind++; #endif } diff -r d4d880fcef28 -r b35215021b32 tools/xenstore/xenstored_core.c --- a/tools/xenstore/xenstored_core.c Fri Sep 9 16:31:36 2005 +++ b/tools/xenstore/xenstored_core.c Tue Sep 13 16:14:16 2005 @@ -1640,8 +1640,10 @@ /* Session leader so ^C doesn't whack us. */ setsid(); +#ifndef TESTING /* Relative paths for socket names */ /* Move off any mount points we might be in. */ chdir("/"); +#endif /* Discard our parent's old-fashioned umask prejudices. */ umask(0); } diff -r d4d880fcef28 -r b35215021b32 tools/xenstore/xenstored_domain.c --- a/tools/xenstore/xenstored_domain.c Fri Sep 9 16:31:36 2005 +++ b/tools/xenstore/xenstored_domain.c Tue Sep 13 16:14:16 2005 @@ -216,6 +216,26 @@ munmap(domain->page, getpagesize()); return 0; +} + +static void domain_cleanup(void) +{ + xc_dominfo_t dominfo; + struct domain *domain, *tmp; + int released = 0; + + list_for_each_entry_safe(domain, tmp, &domains, list) { + if (xc_domain_getinfo(*xc_handle, domain->domid, 1, + &dominfo) == 1 && + dominfo.domid == domain->domid && + !dominfo.dying && !dominfo.crashed && !dominfo.shutdown) + continue; + talloc_free(domain->conn); + released++; + } + + if (released) + fire_watches(NULL, "@releaseDomain", false); } /* We scan all domains rather than use the information given here. */ @@ -371,26 +391,6 @@ send_ack(conn, XS_RELEASE); } -void domain_cleanup(void) -{ - xc_dominfo_t dominfo; - struct domain *domain, *tmp; - int released = 0; - - list_for_each_entry_safe(domain, tmp, &domains, list) { - if (xc_domain_getinfo(*xc_handle, domain->domid, 1, - &dominfo) == 1 && - dominfo.domid == domain->domid && - !dominfo.dying && !dominfo.crashed && !dominfo.shutdown) - continue; - talloc_free(domain->conn); - released++; - } - - if (released) - fire_watches(NULL, "@releaseDomain", false); -} - void do_get_domain_path(struct connection *conn, const char *domid_str) { struct domain *domain; @@ -457,6 +457,7 @@ #ifdef TESTING eventchn_fd = fake_open_eventchn(); + (void)&st; #else /* Make sure any existing device file links to correct device. */ if ((lstat(EVTCHN_DEV_NAME, &st) != 0) || !S_ISCHR(st.st_mode) || diff -r d4d880fcef28 -r b35215021b32 tools/xenstore/xenstored_domain.h --- a/tools/xenstore/xenstored_domain.h Fri Sep 9 16:31:36 2005 +++ b/tools/xenstore/xenstored_domain.h Tue Sep 13 16:14:16 2005 @@ -28,10 +28,6 @@ /* domid */ void do_release(struct connection *conn, const char *domid_str); -/* Enumerate domains and release connections for non-existant or dying - * domains. */ -void domain_cleanup(void); - /* domid */ void do_get_domain_path(struct connection *conn, const char *domid_str); diff -r d4d880fcef28 -r b35215021b32 tools/xenstore/xenstored_watch.c --- a/tools/xenstore/xenstored_watch.c Fri Sep 9 16:31:36 2005 +++ b/tools/xenstore/xenstored_watch.c Tue Sep 13 16:14:16 2005 @@ -105,7 +105,6 @@ */ if (!check_node_perms(conn, node, XS_PERM_READ|XS_PERM_ENOENT_OK) && !check_event_node(node)) { - fprintf(stderr, "No permission for %s\n", node); return; } @@ -135,11 +134,8 @@ if (conn && conn->transaction) return; - /* Create an event for each watch. Don't send to self. */ + /* Create an event for each watch. */ list_for_each_entry(i, &connections, list) { - if (i == conn) - continue; - list_for_each_entry(watch, &i->watches, list) { if (is_child(node, watch->node)) add_event(i, watch, node); diff -r d4d880fcef28 -r b35215021b32 tools/xenstore/xs.c --- a/tools/xenstore/xs.c Fri Sep 9 16:31:36 2005 +++ b/tools/xenstore/xs.c Tue Sep 13 16:14:16 2005 @@ -36,12 +36,10 @@ #include "xenstored.h" #include "xs_lib.h" #include "utils.h" -#include "xenbus_dev.h" struct xs_handle { int fd; - enum { SOCK, DEV } type; }; /* Get the socket from the store daemon handle. @@ -68,7 +66,6 @@ h = malloc(sizeof(*h)); if (h) { h->fd = sock; - h->type = SOCK; return h; } } @@ -82,16 +79,15 @@ static struct xs_handle *get_dev(const char *connect_to) { int fd, saved_errno; - struct xs_handle *h = NULL; - - fd = open(connect_to, O_RDONLY); + struct xs_handle *h; + + fd = open(connect_to, O_RDWR); if (fd < 0) return NULL; h = malloc(sizeof(*h)); if (h) { h->fd = fd; - h->type = DEV; return h; } @@ -101,19 +97,32 @@ return NULL; } +static struct xs_handle *get_handle(const char *connect_to) +{ + struct stat buf; + + if (stat(connect_to, &buf) != 0) + return NULL; + + if (S_ISSOCK(buf.st_mode)) + return get_socket(connect_to); + else + return get_dev(connect_to); +} + struct xs_handle *xs_daemon_open(void) { - return get_socket(xs_daemon_socket()); + return get_handle(xs_daemon_socket()); } struct xs_handle *xs_daemon_open_readonly(void) { - return get_socket(xs_daemon_socket_ro()); + return get_handle(xs_daemon_socket_ro()); } struct xs_handle *xs_domain_open(void) { - return get_dev(xs_domain_dev()); + return get_handle(xs_domain_dev()); } void xs_daemon_close(struct xs_handle *h) @@ -190,9 +199,9 @@ } /* Send message to xs, get malloc'ed reply. NULL and set errno on error. */ -static void *xs_talkv_sock(struct xs_handle *h, enum xsd_sockmsg_type type, - const struct iovec *iovec, unsigned int num_vecs, - unsigned int *len) +static void *xs_talkv(struct xs_handle *h, enum xsd_sockmsg_type type, + const struct iovec *iovec, unsigned int num_vecs, + unsigned int *len) { struct xsd_sockmsg msg; void *ret = NULL; @@ -250,54 +259,6 @@ close(h->fd); h->fd = -1; errno = saved_errno; - return NULL; -} - -/* Send message to xs, get malloc'ed reply. NULL and set errno on error. */ -static void *xs_talkv_dev(struct xs_handle *h, enum xsd_sockmsg_type type, - const struct iovec *iovec, unsigned int num_vecs, - unsigned int *len) -{ - struct xenbus_dev_talkv dt; - char *buf; - int err, buflen = 1024; - - again: - buf = malloc(buflen); - if (buf == NULL) { - errno = ENOMEM; - return NULL; - } - dt.type = type; - dt.iovec = (struct kvec *)iovec; - dt.num_vecs = num_vecs; - dt.buf = buf; - dt.len = buflen; - err = ioctl(h->fd, IOCTL_XENBUS_DEV_TALKV, &dt); - if (err < 0) { - free(buf); - errno = err; - return NULL; - } - if (err > buflen) { - free(buf); - buflen = err; - goto again; - } - if (len) - *len = err; - return buf; -} - -/* Send message to xs, get malloc'ed reply. NULL and set errno on error. */ -static void *xs_talkv(struct xs_handle *h, enum xsd_sockmsg_type type, - const struct iovec *iovec, unsigned int num_vecs, - unsigned int *len) -{ - if (h->type == SOCK) - return xs_talkv_sock(h, type, iovec, num_vecs, len); - if (h->type == DEV) - return xs_talkv_dev(h, type, iovec, num_vecs, len); return NULL; } diff -r d4d880fcef28 -r b35215021b32 tools/xenstore/xs_lib.c --- a/tools/xenstore/xs_lib.c Fri Sep 9 16:31:36 2005 +++ b/tools/xenstore/xs_lib.c Tue Sep 13 16:14:16 2005 @@ -38,37 +38,55 @@ return (s ? s : "/var/run/xenstored"); } +static const char *xs_daemon_path(void) +{ + static char buf[PATH_MAX]; + char *s = getenv("XENSTORED_PATH"); + if (s) + return s; + if (snprintf(buf, PATH_MAX, "%s/socket", + xs_daemon_rundir()) >= PATH_MAX) + return NULL; + return buf; +} + const char *xs_daemon_socket(void) { - static char buf[PATH_MAX]; - sprintf(buf, "%s/socket", xs_daemon_rundir()); - return buf; + return xs_daemon_path(); } const char *xs_daemon_socket_ro(void) { static char buf[PATH_MAX]; - sprintf(buf, "%s/socket_ro", xs_daemon_rundir()); + const char *s = xs_daemon_path(); + if (s == NULL) + return NULL; + if (snprintf(buf, PATH_MAX, "%s_ro", s) >= PATH_MAX) + return NULL; return buf; } const char *xs_daemon_store(void) { static char buf[PATH_MAX]; - sprintf(buf, "%s/store", xs_daemon_rootdir()); + if (snprintf(buf, PATH_MAX, "%s/store", + xs_daemon_rootdir()) >= PATH_MAX) + return NULL; return buf; } const char *xs_daemon_transactions(void) { static char buf[PATH_MAX]; - sprintf(buf, "%s/transactions", xs_daemon_rootdir()); + if (snprintf(buf, PATH_MAX, "%s/transactions", + xs_daemon_rootdir()) >= PATH_MAX) + return NULL; return buf; } const char *xs_domain_dev(void) { - char *s = getenv("XENSTORED_DOMAIN_DEV"); + char *s = getenv("XENSTORED_PATH"); return (s ? s : "/proc/xen/xenbus"); } diff -r d4d880fcef28 -r b35215021b32 tools/xenstore/xs_test.c --- a/tools/xenstore/xs_test.c Fri Sep 9 16:31:36 2005 +++ b/tools/xenstore/xs_test.c Tue Sep 13 16:14:16 2005 @@ -43,7 +43,7 @@ static struct xs_handle *handles[10] = { NULL }; -static unsigned int timeout_ms = 200; +static unsigned int timeout_ms = 500; static bool timeout_suppressed = true; static bool readonly = false; static bool print_input = false; diff -r d4d880fcef28 -r b35215021b32 xen/Makefile --- a/xen/Makefile Fri Sep 9 16:31:36 2005 +++ b/xen/Makefile Tue Sep 13 16:14:16 2005 @@ -31,11 +31,11 @@ install: $(TARGET).gz [ -d $(DESTDIR)/boot ] || $(INSTALL_DIR) $(DESTDIR)/boot - $(INSTALL_DATA) $(TARGET).gz $(DESTDIR)/boot/$(notdir $(TARGET))-$(XEN_VERSION).$(XEN_SUBVERSION)$(XEN_EXTRAVERSION).gz - ln -f -s $(notdir $(TARGET))-$(XEN_VERSION).$(XEN_SUBVERSION)$(XEN_EXTRAVERSION).gz $(DESTDIR)/boot/$(notdir $(TARGET))-$(XEN_VERSION).$(XEN_SUBVERSION).gz - ln -f -s $(notdir $(TARGET))-$(XEN_VERSION).$(XEN_SUBVERSION)$(XEN_EXTRAVERSION).gz $(DESTDIR)/boot/$(notdir $(TARGET))-$(XEN_VERSION).gz - ln -f -s $(notdir $(TARGET))-$(XEN_VERSION).$(XEN_SUBVERSION)$(XEN_EXTRAVERSION).gz $(DESTDIR)/boot/$(notdir $(TARGET)).gz - $(INSTALL_DATA) $(TARGET)-syms $(DESTDIR)/boot/$(notdir $(TARGET))-syms-$(XEN_VERSION).$(XEN_SUBVERSION)$(XEN_EXTRAVERSION) + $(INSTALL_DATA) $(TARGET).gz $(DESTDIR)/boot/$(notdir $(TARGET))-$(XEN_FULLVERSION).gz + ln -f -s $(notdir $(TARGET))-$(XEN_FULLVERSION).gz $(DESTDIR)/boot/$(notdir $(TARGET))-$(XEN_VERSION).$(XEN_SUBVERSION).gz + ln -f -s $(notdir $(TARGET))-$(XEN_FULLVERSION).gz $(DESTDIR)/boot/$(notdir $(TARGET))-$(XEN_VERSION).gz + ln -f -s $(notdir $(TARGET))-$(XEN_FULLVERSION).gz $(DESTDIR)/boot/$(notdir $(TARGET)).gz + $(INSTALL_DATA) $(TARGET)-syms $(DESTDIR)/boot/$(notdir $(TARGET))-syms-$(XEN_FULLVERSION) [ -d $(DESTDIR)/usr/include/xen/io ] || \ $(INSTALL_DIR) $(DESTDIR)/usr/include/xen/io $(INSTALL_DATA) include/public/*.h $(DESTDIR)/usr/include/xen diff -r d4d880fcef28 -r b35215021b32 xen/arch/ia64/xen/xensetup.c --- a/xen/arch/ia64/xen/xensetup.c Fri Sep 9 16:31:36 2005 +++ b/xen/arch/ia64/xen/xensetup.c Tue Sep 13 16:14:16 2005 @@ -386,16 +386,17 @@ startup_cpu_idle_loop(); } -void arch_get_xen_caps(xen_capabilities_info_t *info) -{ - char *p=info->caps; +void arch_get_xen_caps(xen_capabilities_info_t info) +{ + char *p=info; *p=0; p+=sprintf(p,"xen_%d.%d_ia64 ",XEN_VERSION,XEN_SUBVERSION); - BUG_ON((p-info->caps)>sizeof(*info)); - - if(p>info->caps) *(p-1) = 0; -} - + *(p-1) = 0; + + BUG_ON((p-info)>sizeof(xen_capabilities_info_t)); + +} + diff -r d4d880fcef28 -r b35215021b32 xen/arch/x86/dom0_ops.c --- a/xen/arch/x86/dom0_ops.c Fri Sep 9 16:31:36 2005 +++ b/xen/arch/x86/dom0_ops.c Tue Sep 13 16:14:16 2005 @@ -35,13 +35,13 @@ static void write_msr_for(void *unused) { - if (((1 << current->processor) & msr_cpu_mask)) + if ( ((1 << current->processor) & msr_cpu_mask) ) (void)wrmsr_user(msr_addr, msr_lo, msr_hi); } static void read_msr_for(void *unused) { - if (((1 << current->processor) & msr_cpu_mask)) + if ( ((1 << current->processor) & msr_cpu_mask) ) (void)rdmsr_user(msr_addr, msr_lo, msr_hi); } @@ -189,11 +189,11 @@ pi->total_pages = max_page; pi->free_pages = avail_domheap_pages(); pi->cpu_khz = cpu_khz; - memset( pi->hw_cap, 0, sizeof(pi->hw_cap) ); - memcpy( pi->hw_cap, boot_cpu_data.x86_capability, NCAPINTS*4 ); + memset(pi->hw_cap, 0, sizeof(pi->hw_cap)); + memcpy(pi->hw_cap, boot_cpu_data.x86_capability, NCAPINTS*4); ret = 0; - if( copy_to_user(u_dom0_op, op, sizeof(*op)) ) - ret = -EINVAL; + if ( copy_to_user(u_dom0_op, op, sizeof(*op)) ) + ret = -EFAULT; } break; diff -r d4d880fcef28 -r b35215021b32 xen/arch/x86/domain.c --- a/xen/arch/x86/domain.c Fri Sep 9 16:31:36 2005 +++ b/xen/arch/x86/domain.c Tue Sep 13 16:14:16 2005 @@ -461,14 +461,11 @@ if ( !get_page(&frame_table[phys_basetab>>PAGE_SHIFT], d) ) return -EINVAL; } - else - { -#ifdef __x86_64__ - if ( !(c->flags & VGCF_VMX_GUEST) ) -#endif - if ( !get_page_and_type(&frame_table[phys_basetab>>PAGE_SHIFT], d, - PGT_base_page_table) ) - return -EINVAL; + else if ( !(c->flags & VGCF_VMX_GUEST) ) + { + if ( !get_page_and_type(&frame_table[phys_basetab>>PAGE_SHIFT], d, + PGT_base_page_table) ) + return -EINVAL; } if ( (rc = (int)set_gdt(v, c->gdt_frames, c->gdt_ents)) != 0 ) @@ -677,10 +674,10 @@ if ( VMX_DOMAIN(v) ) rdmsrl(MSR_SHADOW_GS_BASE, v->arch.arch_vmx.msr_content.shadow_gs); - __asm__ __volatile__ ( "movl %%ds,%0" : "=m" (regs->ds) ); - __asm__ __volatile__ ( "movl %%es,%0" : "=m" (regs->es) ); - __asm__ __volatile__ ( "movl %%fs,%0" : "=m" (regs->fs) ); - __asm__ __volatile__ ( "movl %%gs,%0" : "=m" (regs->gs) ); + __asm__ __volatile__ ( "mov %%ds,%0" : "=m" (regs->ds) ); + __asm__ __volatile__ ( "mov %%es,%0" : "=m" (regs->es) ); + __asm__ __volatile__ ( "mov %%fs,%0" : "=m" (regs->fs) ); + __asm__ __volatile__ ( "mov %%gs,%0" : "=m" (regs->gs) ); if ( regs->ds ) dirty_segment_mask |= DIRTY_DS; diff -r d4d880fcef28 -r b35215021b32 xen/arch/x86/setup.c --- a/xen/arch/x86/setup.c Fri Sep 9 16:31:36 2005 +++ b/xen/arch/x86/setup.c Tue Sep 13 16:14:16 2005 @@ -93,8 +93,6 @@ #endif EXPORT_SYMBOL(mmu_cr4_features); -int hvm_enabled = 0; /* can we run unmodified guests */ - struct vcpu *idle_task[NR_CPUS] = { &idle0_vcpu }; int acpi_disabled; @@ -533,43 +531,44 @@ startup_cpu_idle_loop(); } -void arch_get_xen_caps(xen_capabilities_info_t *info) +void arch_get_xen_caps(xen_capabilities_info_t info) { - char *p=info->caps; - - *p=0; - -#ifdef CONFIG_X86_32 - -#ifndef CONFIG_X86_PAE - p+=sprintf(p,"xen_%d.%d_x86_32 ",XEN_VERSION,XEN_SUBVERSION); - if(hvm_enabled) - { - p+=sprintf(p,"hvm_%d.%d_x86_32 ",XEN_VERSION,XEN_SUBVERSION); - } + char *p = info; + +#if defined(CONFIG_X86_32) && !defined(CONFIG_X86_PAE) + + p += sprintf(p, "xen_%d.%d_x86_32 ", XEN_VERSION, XEN_SUBVERSION); + if ( hvm_enabled ) + p += sprintf(p, "hvm_%d.%d_x86_32 ", XEN_VERSION, XEN_SUBVERSION); + +#elif defined(CONFIG_X86_32) && defined(CONFIG_X86_PAE) + + p += sprintf(p, "xen_%d.%d_x86_32p ", XEN_VERSION, XEN_SUBVERSION); + if ( hvm_enabled ) + { + //p += sprintf(p, "hvm_%d.%d_x86_32 ", XEN_VERSION, XEN_SUBVERSION); + //p += sprintf(p, "hvm_%d.%d_x86_32p ", XEN_VERSION, XEN_SUBVERSION); + } + +#elif defined(CONFIG_X86_64) + + p += sprintf(p, "xen_%d.%d_x86_64 ", XEN_VERSION, XEN_SUBVERSION); + if ( hvm_enabled ) + { + //p += sprintf(p, "hvm_%d.%d_x86_32 ", XEN_VERSION, XEN_SUBVERSION); + //p += sprintf(p, "hvm_%d.%d_x86_32p ", XEN_VERSION, XEN_SUBVERSION); + p += sprintf(p, "hvm_%d.%d_x86_64 ", XEN_VERSION, XEN_SUBVERSION); + } + #else - p+=sprintf(p,"xen_%d.%d_x86_32p ",XEN_VERSION,XEN_SUBVERSION); - if(hvm_enabled) - { - //p+=sprintf(p,"hvm_%d.%d_x86_32 ",XEN_VERSION,XEN_SUBVERSION); - //p+=sprintf(p,"hvm_%d.%d_x86_32p ",XEN_VERSION,XEN_SUBVERSION); - } - -#endif - -#else /* !CONFIG_X86_32 */ - p+=sprintf(p,"xen_%d.%d_x86_64 ",XEN_VERSION,XEN_SUBVERSION); - if(hvm_enabled) - { - //p+=sprintf(p,"hvm_%d.%d_x86_32 ",XEN_VERSION,XEN_SUBVERSION); - //p+=sprintf(p,"hvm_%d.%d_x86_32p ",XEN_VERSION,XEN_SUBVERSION); - p+=sprintf(p,"hvm_%d.%d_x86_64 ",XEN_VERSION,XEN_SUBVERSION); - } + + p++; + #endif - BUG_ON((p-info->caps)>sizeof(*info)); - - if(p>info->caps) *(p-1) = 0; + *(p-1) = 0; + + BUG_ON((p - info) > sizeof(xen_capabilities_info_t)); } /* diff -r d4d880fcef28 -r b35215021b32 xen/arch/x86/shadow.c --- a/xen/arch/x86/shadow.c Fri Sep 9 16:31:36 2005 +++ b/xen/arch/x86/shadow.c Tue Sep 13 16:14:16 2005 @@ -54,7 +54,7 @@ static void shadow_map_into_current(struct vcpu *v, unsigned long va, unsigned int from, unsigned int to); static inline void validate_bl2e_change( struct domain *d, - guest_root_pgentry_t *new_gle_p, pgentry_64_t *shadow_l3, int index); + guest_root_pgentry_t *new_gle_p, pgentry_64_t *shadow_l3, int index); #endif diff -r d4d880fcef28 -r b35215021b32 xen/arch/x86/shadow32.c --- a/xen/arch/x86/shadow32.c Fri Sep 9 16:31:36 2005 +++ b/xen/arch/x86/shadow32.c Tue Sep 13 16:14:16 2005 @@ -2214,7 +2214,7 @@ struct domain *d, unsigned long l1mfn, unsigned long forbidden_gmfn) { l1_pgentry_t *pl1e = map_domain_page(l1mfn); - l1_pgentry_t match; + l1_pgentry_t match, ol2e; unsigned long flags = _PAGE_PRESENT; int i; u32 count = 0; @@ -2226,17 +2226,17 @@ for (i = 0; i < L1_PAGETABLE_ENTRIES; i++) { - if ( unlikely(!l1e_has_changed(pl1e[i], match, flags) == 0) ) - { - l1_pgentry_t ol2e = pl1e[i]; - pl1e[i] = l1e_empty(); - count++; - - if ( is_l1_shadow ) - shadow_put_page_from_l1e(ol2e, d); - else /* must be an hl2 page */ - put_page(&frame_table[forbidden_gmfn]); - } + if ( l1e_has_changed(pl1e[i], match, flags) ) + continue; + + ol2e = pl1e[i]; + pl1e[i] = l1e_empty(); + count++; + + if ( is_l1_shadow ) + shadow_put_page_from_l1e(ol2e, d); + else /* must be an hl2 page */ + put_page(&frame_table[forbidden_gmfn]); } unmap_domain_page(pl1e); diff -r d4d880fcef28 -r b35215021b32 xen/arch/x86/shadow_public.c --- a/xen/arch/x86/shadow_public.c Fri Sep 9 16:31:36 2005 +++ b/xen/arch/x86/shadow_public.c Tue Sep 13 16:14:16 2005 @@ -54,24 +54,24 @@ switch(levels) { #if CONFIG_PAGING_LEVELS >= 4 case 4: - if ( d->arch.ops != &MODE_F_HANDLER ) - d->arch.ops = &MODE_F_HANDLER; - shadow_unlock(d); + if ( d->arch.ops != &MODE_F_HANDLER ) + d->arch.ops = &MODE_F_HANDLER; + shadow_unlock(d); return 1; #endif case 3: case 2: #if CONFIG_PAGING_LEVELS == 2 - if ( d->arch.ops != &MODE_A_HANDLER ) - d->arch.ops = &MODE_A_HANDLER; + if ( d->arch.ops != &MODE_A_HANDLER ) + d->arch.ops = &MODE_A_HANDLER; #elif CONFIG_PAGING_LEVELS == 4 - if ( d->arch.ops != &MODE_D_HANDLER ) - d->arch.ops = &MODE_D_HANDLER; + if ( d->arch.ops != &MODE_D_HANDLER ) + d->arch.ops = &MODE_D_HANDLER; #endif - shadow_unlock(d); + shadow_unlock(d); return 1; - default: - shadow_unlock(d); + default: + shadow_unlock(d); return 0; } } @@ -115,10 +115,10 @@ struct out_of_sync_entry * shadow_mark_mfn_out_of_sync(struct vcpu *v, unsigned long gpfn, - unsigned long mfn) -{ - struct domain *d = v->domain; - return d->arch.ops->mark_mfn_out_of_sync(v, gpfn, mfn); + unsigned long mfn) +{ + struct domain *d = v->domain; + return d->arch.ops->mark_mfn_out_of_sync(v, gpfn, mfn); } /* @@ -181,7 +181,7 @@ l4_pgentry_t *mpl4e; struct pfn_info *mmfn_info; struct domain *d = v->domain; - pagetable_t phys_table; + pagetable_t phys_table; ASSERT(!pagetable_get_paddr(v->arch.monitor_table)); /* we should only get called once */ @@ -192,13 +192,13 @@ mpl4e = (l4_pgentry_t *) map_domain_page(mmfn); memcpy(mpl4e, &idle_pg_table[0], PAGE_SIZE); mpl4e[l4_table_offset(PERDOMAIN_VIRT_START)] = - l4e_from_paddr(__pa(d->arch.mm_perdomain_l3), __PAGE_HYPERVISOR); + l4e_from_paddr(__pa(d->arch.mm_perdomain_l3), __PAGE_HYPERVISOR); /* map the phys_to_machine map into the per domain Read-Only MPT space */ phys_table = page_table_convert(d); mpl4e[l4_table_offset(RO_MPT_VIRT_START)] = - l4e_from_paddr(pagetable_get_paddr(phys_table), - __PAGE_HYPERVISOR); + l4e_from_paddr(pagetable_get_paddr(phys_table), + __PAGE_HYPERVISOR); v->arch.monitor_table = mk_pagetable(mmfn << PAGE_SHIFT); v->arch.monitor_vtable = (l2_pgentry_t *) mpl4e; } @@ -245,7 +245,7 @@ for ( i = 0; i < PAGETABLE_ENTRIES; i++ ) if ( external || is_guest_l4_slot(i) ) if ( entry_get_flags(ple[i]) & _PAGE_PRESENT ) - put_shadow_ref(entry_get_pfn(ple[i])); + put_shadow_ref(entry_get_pfn(ple[i])); unmap_domain_page(ple); } @@ -306,12 +306,12 @@ mpl2e[l2_table_offset(PERDOMAIN_VIRT_START)] = l2e_from_paddr(__pa(d->arch.mm_perdomain_pt), - __PAGE_HYPERVISOR); + __PAGE_HYPERVISOR); // map the phys_to_machine map into the Read-Only MPT space for this domain mpl2e[l2_table_offset(RO_MPT_VIRT_START)] = l2e_from_paddr(pagetable_get_paddr(d->arch.phys_table), - __PAGE_HYPERVISOR); + __PAGE_HYPERVISOR); // Don't (yet) have mappings for these... // Don't want to accidentally see the idle_pg_table's linear mapping. @@ -365,7 +365,7 @@ v->arch.monitor_table = mk_pagetable(0); v->arch.monitor_vtable = 0; } -#endif +#endif static void shadow_free_snapshot(struct domain *d, struct out_of_sync_entry *entry) @@ -850,16 +850,16 @@ perfc_decr(free_l1_pages); struct pfn_info *page = list_entry(list_ent, struct pfn_info, list); - if (d->arch.ops->guest_paging_levels == PAGING_L2) - { + if (d->arch.ops->guest_paging_levels == PAGING_L2) + { #if CONFIG_PAGING_LEVELS >=4 - free_domheap_pages(page, SL1_ORDER); + free_domheap_pages(page, SL1_ORDER); #else - free_domheap_page(page); + free_domheap_page(page); #endif - } - else - free_domheap_page(page); + } + else + free_domheap_page(page); } shadow_audit(d, 0); @@ -930,9 +930,9 @@ #if defined(CONFIG_PAGING_LEVELS) if(!shadow_set_guest_paging_levels(d, - CONFIG_PAGING_LEVELS)) { - printk("Unsupported guest paging levels\n"); - domain_crash_synchronous(); /* need to take a clean path */ + CONFIG_PAGING_LEVELS)) { + printk("Unsupported guest paging levels\n"); + domain_crash_synchronous(); /* need to take a clean path */ } #endif @@ -1004,7 +1004,7 @@ goto nomem; memset(d->arch.shadow_ht, 0, - shadow_ht_buckets * sizeof(struct shadow_status)); + shadow_ht_buckets * sizeof(struct shadow_status)); } if ( new_modes & SHM_log_dirty ) @@ -1013,7 +1013,7 @@ d->arch.shadow_dirty_bitmap_size = (d->max_pages + 63) & ~63; d->arch.shadow_dirty_bitmap = xmalloc_array(unsigned long, d->arch.shadow_dirty_bitmap_size / - (8 * sizeof(unsigned long))); + (8 * sizeof(unsigned long))); if ( d->arch.shadow_dirty_bitmap == NULL ) { d->arch.shadow_dirty_bitmap_size = 0; @@ -1039,7 +1039,7 @@ // external guests provide their own memory for their P2M maps. // ASSERT( d == page_get_owner( - &frame_table[pagetable_get_pfn(d->arch.phys_table)]) ); + &frame_table[pagetable_get_pfn(d->arch.phys_table)]) ); } } @@ -1188,9 +1188,9 @@ chunk : (d->max_pages - i)) + 7) / 8; if (copy_to_user( - sc->dirty_bitmap + (i/(8*sizeof(unsigned long))), - d->arch.shadow_dirty_bitmap +(i/(8*sizeof(unsigned long))), - bytes)) + sc->dirty_bitmap + (i/(8*sizeof(unsigned long))), + d->arch.shadow_dirty_bitmap +(i/(8*sizeof(unsigned long))), + bytes)) { // copy_to_user can fail when copying to guest app memory. // app should zero buffer after mallocing, and pin it @@ -1474,8 +1474,8 @@ spl3e = (pgentry_64_t *) map_domain_page_with_cache(sl3mfn, cache); validate_entry_change(d, (pgentry_64_t *) &gpde, - &spl3e[(pa & ~PAGE_MASK) / sizeof(l3_pgentry_t)], - shadow_type_to_level(PGT_l3_shadow)); + &spl3e[(pa & ~PAGE_MASK) / sizeof(l3_pgentry_t)], + shadow_type_to_level(PGT_l3_shadow)); unmap_domain_page_with_cache(spl3e, cache); } @@ -1502,8 +1502,8 @@ spl4e = (pgentry_64_t *)map_domain_page_with_cache(sl4mfn, cache); validate_entry_change(d, (pgentry_64_t *)&gpde, - &spl4e[(pa & ~PAGE_MASK) / sizeof(l4_pgentry_t)], - shadow_type_to_level(PGT_l4_shadow)); + &spl4e[(pa & ~PAGE_MASK) / sizeof(l4_pgentry_t)], + shadow_type_to_level(PGT_l4_shadow)); unmap_domain_page_with_cache(spl4e, cache); } @@ -1619,32 +1619,32 @@ } static u32 remove_all_access_in_page( - struct domain *d, unsigned long l1mfn, unsigned long forbidden_gmfn) + struct domain *d, unsigned long l1mfn, unsigned long forbidden_gmfn) { l1_pgentry_t *pl1e = map_domain_page(l1mfn); - l1_pgentry_t match; + l1_pgentry_t match, ol2e; unsigned long flags = _PAGE_PRESENT; int i; u32 count = 0; int is_l1_shadow = - ((frame_table[l1mfn].u.inuse.type_info & PGT_type_mask) == - PGT_l1_shadow); + ((frame_table[l1mfn].u.inuse.type_info & PGT_type_mask) == + PGT_l1_shadow); match = l1e_from_pfn(forbidden_gmfn, flags); for (i = 0; i < L1_PAGETABLE_ENTRIES; i++) { - if ( unlikely(!l1e_has_changed(pl1e[i], match, flags) == 0) ) - { - l1_pgentry_t ol2e = pl1e[i]; - pl1e[i] = l1e_empty(); - count++; - - if ( is_l1_shadow ) - shadow_put_page_from_l1e(ol2e, d); - else /* must be an hl2 page */ - put_page(&frame_table[forbidden_gmfn]); - } + if ( l1e_has_changed(pl1e[i], match, flags) ) + continue; + + ol2e = pl1e[i]; + pl1e[i] = l1e_empty(); + count++; + + if ( is_l1_shadow ) + shadow_put_page_from_l1e(ol2e, d); + else /* must be an hl2 page */ + put_page(&frame_table[forbidden_gmfn]); } unmap_domain_page(pl1e); @@ -1671,19 +1671,19 @@ { switch (a->gpfn_and_flags & PGT_type_mask) { - case PGT_l1_shadow: - case PGT_l2_shadow: - case PGT_l3_shadow: - case PGT_l4_shadow: - case PGT_hl2_shadow: - count += remove_all_access_in_page(d, a->smfn, forbidden_gmfn); - break; - case PGT_snapshot: - case PGT_writable_pred: - // these can't hold refs to the forbidden page - break; - default: - BUG(); + case PGT_l1_shadow: + case PGT_l2_shadow: + case PGT_l3_shadow: + case PGT_l4_shadow: + case PGT_hl2_shadow: + count += remove_all_access_in_page(d, a->smfn, forbidden_gmfn); + break; + case PGT_snapshot: + case PGT_writable_pred: + // these can't hold refs to the forbidden page + break; + default: + BUG(); } a = a->next; @@ -1694,29 +1694,29 @@ } void shadow_drop_references( - struct domain *d, struct pfn_info *page) + struct domain *d, struct pfn_info *page) { if ( likely(!shadow_mode_refcounts(d)) || - ((page->u.inuse.type_info & PGT_count_mask) == 0) ) + ((page->u.inuse.type_info & PGT_count_mask) == 0) ) return; /* XXX This needs more thought... */ printk("%s: needing to call __shadow_remove_all_access for mfn=%lx\n", - __func__, page_to_pfn(page)); + __func__, page_to_pfn(page)); printk("Before: mfn=%lx c=%08x t=%" PRtype_info "\n", page_to_pfn(page), - page->count_info, page->u.inuse.type_info); + page->count_info, page->u.inuse.type_info); shadow_lock(d); __shadow_remove_all_access(d, page_to_pfn(page)); shadow_unlock(d); printk("After: mfn=%lx c=%08x t=%" PRtype_info "\n", page_to_pfn(page), - page->count_info, page->u.inuse.type_info); + page->count_info, page->u.inuse.type_info); } /* XXX Needs more thought. Neither pretty nor fast: a place holder. */ void shadow_sync_and_drop_references( - struct domain *d, struct pfn_info *page) + struct domain *d, struct pfn_info *page) { if ( likely(!shadow_mode_refcounts(d)) ) return; @@ -1730,3 +1730,13 @@ shadow_unlock(d); } + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff -r d4d880fcef28 -r b35215021b32 xen/arch/x86/traps.c --- a/xen/arch/x86/traps.c Fri Sep 9 16:31:36 2005 +++ b/xen/arch/x86/traps.c Tue Sep 13 16:14:16 2005 @@ -106,7 +106,7 @@ #define ESP_BEFORE_EXCEPTION(regs) ((unsigned long *)®s->esp) #else #define stack_words_per_line 4 -#define ESP_BEFORE_EXCEPTION(regs) ((unsigned long *)regs->esp) +#define ESP_BEFORE_EXCEPTION(regs) ((unsigned long *)regs->rsp) #endif int is_kernel_text(unsigned long addr) @@ -238,7 +238,7 @@ unsigned long *stack = ESP_BEFORE_EXCEPTION(regs), addr; int i; - if ( GUEST_MODE(regs) ) + if ( GUEST_CONTEXT(current, regs) ) return show_guest_stack(regs); printk("Xen stack trace from "__OP"sp=%p:\n ", stack); diff -r d4d880fcef28 -r b35215021b32 xen/arch/x86/vmx.c --- a/xen/arch/x86/vmx.c Fri Sep 9 16:31:36 2005 +++ b/xen/arch/x86/vmx.c Tue Sep 13 16:14:16 2005 @@ -44,13 +44,13 @@ #include <public/io/ioreq.h> +int hvm_enabled; + #ifdef CONFIG_VMX int vmcs_size; unsigned int opt_vmx_debug_level = 0; integer_param("vmx_debug", opt_vmx_debug_level); - -extern int hvm_enabled; #ifdef TRACE_BUFFER static unsigned long trace_values[NR_CPUS][4]; @@ -122,37 +122,37 @@ struct vcpu *vc = current; struct msr_state * msr = &vc->arch.arch_vmx.msr_content; switch(regs->ecx){ - case MSR_EFER: - msr_content = msr->msr_items[VMX_INDEX_MSR_EFER]; - VMX_DBG_LOG(DBG_LEVEL_2, "EFER msr_content %llx\n", (unsigned long long)msr_content); - if (test_bit(VMX_CPU_STATE_LME_ENABLED, - &vc->arch.arch_vmx.cpu_state)) - msr_content |= 1 << _EFER_LME; - - if (VMX_LONG_GUEST(vc)) - msr_content |= 1 << _EFER_LMA; - break; - case MSR_FS_BASE: - if (!(VMX_LONG_GUEST(vc))) - /* XXX should it be GP fault */ - domain_crash(); - __vmread(GUEST_FS_BASE, &msr_content); - break; - case MSR_GS_BASE: - if (!(VMX_LONG_GUEST(vc))) - domain_crash(); - __vmread(GUEST_GS_BASE, &msr_content); - break; - case MSR_SHADOW_GS_BASE: - msr_content = msr->shadow_gs; - break; + case MSR_EFER: + msr_content = msr->msr_items[VMX_INDEX_MSR_EFER]; + VMX_DBG_LOG(DBG_LEVEL_2, "EFER msr_content %llx\n", (unsigned long long)msr_content); + if (test_bit(VMX_CPU_STATE_LME_ENABLED, + &vc->arch.arch_vmx.cpu_state)) + msr_content |= 1 << _EFER_LME; + + if (VMX_LONG_GUEST(vc)) + msr_content |= 1 << _EFER_LMA; + break; + case MSR_FS_BASE: + if (!(VMX_LONG_GUEST(vc))) + /* XXX should it be GP fault */ + domain_crash(); + __vmread(GUEST_FS_BASE, &msr_content); + break; + case MSR_GS_BASE: + if (!(VMX_LONG_GUEST(vc))) + domain_crash(); + __vmread(GUEST_GS_BASE, &msr_content); + break; + case MSR_SHADOW_GS_BASE: + msr_content = msr->shadow_gs; + break; CASE_READ_MSR(STAR); CASE_READ_MSR(LSTAR); CASE_READ_MSR(CSTAR); CASE_READ_MSR(SYSCALL_MASK); - default: - return 0; + default: + return 0; } VMX_DBG_LOG(DBG_LEVEL_2, "mode_do_msr_read: msr_content: %lx\n", msr_content); regs->eax = msr_content & 0xffffffff; @@ -166,68 +166,68 @@ struct vcpu *vc = current; struct msr_state * msr = &vc->arch.arch_vmx.msr_content; struct msr_state * host_state = - &percpu_msr[smp_processor_id()]; + &percpu_msr[smp_processor_id()]; VMX_DBG_LOG(DBG_LEVEL_1, " mode_do_msr_write msr %lx msr_content %lx\n", regs->ecx, msr_content); switch (regs->ecx){ - case MSR_EFER: - if ((msr_content & EFER_LME) ^ - test_bit(VMX_CPU_STATE_LME_ENABLED, - &vc->arch.arch_vmx.cpu_state)){ - if (test_bit(VMX_CPU_STATE_PG_ENABLED, - &vc->arch.arch_vmx.cpu_state) || - !test_bit(VMX_CPU_STATE_PAE_ENABLED, - &vc->arch.arch_vmx.cpu_state)){ - vmx_inject_exception(vc, TRAP_gp_fault, 0); - } + case MSR_EFER: + if ((msr_content & EFER_LME) ^ + test_bit(VMX_CPU_STATE_LME_ENABLED, + &vc->arch.arch_vmx.cpu_state)){ + if (test_bit(VMX_CPU_STATE_PG_ENABLED, + &vc->arch.arch_vmx.cpu_state) || + !test_bit(VMX_CPU_STATE_PAE_ENABLED, + &vc->arch.arch_vmx.cpu_state)){ + vmx_inject_exception(vc, TRAP_gp_fault, 0); } - if (msr_content & EFER_LME) - set_bit(VMX_CPU_STATE_LME_ENABLED, - &vc->arch.arch_vmx.cpu_state); - /* No update for LME/LMA since it have no effect */ - msr->msr_items[VMX_INDEX_MSR_EFER] = - msr_content; - if (msr_content & ~(EFER_LME | EFER_LMA)){ - msr->msr_items[VMX_INDEX_MSR_EFER] = msr_content; - if (!test_bit(VMX_INDEX_MSR_EFER, &msr->flags)){ - rdmsrl(MSR_EFER, - host_state->msr_items[VMX_INDEX_MSR_EFER]); - set_bit(VMX_INDEX_MSR_EFER, &host_state->flags); - set_bit(VMX_INDEX_MSR_EFER, &msr->flags); - wrmsrl(MSR_EFER, msr_content); - } + } + if (msr_content & EFER_LME) + set_bit(VMX_CPU_STATE_LME_ENABLED, + &vc->arch.arch_vmx.cpu_state); + /* No update for LME/LMA since it have no effect */ + msr->msr_items[VMX_INDEX_MSR_EFER] = + msr_content; + if (msr_content & ~(EFER_LME | EFER_LMA)){ + msr->msr_items[VMX_INDEX_MSR_EFER] = msr_content; + if (!test_bit(VMX_INDEX_MSR_EFER, &msr->flags)){ + rdmsrl(MSR_EFER, + host_state->msr_items[VMX_INDEX_MSR_EFER]); + set_bit(VMX_INDEX_MSR_EFER, &host_state->flags); + set_bit(VMX_INDEX_MSR_EFER, &msr->flags); + wrmsrl(MSR_EFER, msr_content); } - break; - - case MSR_FS_BASE: - case MSR_GS_BASE: - if (!(VMX_LONG_GUEST(vc))) - domain_crash(); - if (!IS_CANO_ADDRESS(msr_content)){ - VMX_DBG_LOG(DBG_LEVEL_1, "Not cano address of msr write\n"); - vmx_inject_exception(vc, TRAP_gp_fault, 0); - } - if (regs->ecx == MSR_FS_BASE) - __vmwrite(GUEST_FS_BASE, msr_content); - else - __vmwrite(GUEST_GS_BASE, msr_content); - break; - - case MSR_SHADOW_GS_BASE: - if (!(VMX_LONG_GUEST(vc))) - domain_crash(); - vc->arch.arch_vmx.msr_content.shadow_gs = msr_content; - wrmsrl(MSR_SHADOW_GS_BASE, msr_content); - break; - - CASE_WRITE_MSR(STAR); - CASE_WRITE_MSR(LSTAR); - CASE_WRITE_MSR(CSTAR); - CASE_WRITE_MSR(SYSCALL_MASK); - default: - return 0; + } + break; + + case MSR_FS_BASE: + case MSR_GS_BASE: + if (!(VMX_LONG_GUEST(vc))) + domain_crash(); + if (!IS_CANO_ADDRESS(msr_content)){ + VMX_DBG_LOG(DBG_LEVEL_1, "Not cano address of msr write\n"); + vmx_inject_exception(vc, TRAP_gp_fault, 0); + } + if (regs->ecx == MSR_FS_BASE) + __vmwrite(GUEST_FS_BASE, msr_content); + else + __vmwrite(GUEST_GS_BASE, msr_content); + break; + + case MSR_SHADOW_GS_BASE: + if (!(VMX_LONG_GUEST(vc))) + domain_crash(); + vc->arch.arch_vmx.msr_content.shadow_gs = msr_content; + wrmsrl(MSR_SHADOW_GS_BASE, msr_content); + break; + + CASE_WRITE_MSR(STAR); + CASE_WRITE_MSR(LSTAR); + CASE_WRITE_MSR(CSTAR); + CASE_WRITE_MSR(SYSCALL_MASK); + default: + return 0; } return 1; } @@ -252,8 +252,8 @@ i = find_first_set_bit(guest_flags); VMX_DBG_LOG(DBG_LEVEL_2, - "restore guest's index %d msr %lx with %lx\n", - i, (unsigned long) msr_data_index[i], (unsigned long) guest_state->msr_items[i]); + "restore guest's index %d msr %lx with %lx\n", + i, (unsigned long) msr_data_index[i], (unsigned long) guest_state->msr_items[i]); set_bit(i, &host_state->flags); wrmsrl(msr_data_index[i], guest_state->msr_items[i]); clear_bit(i, &guest_flags); @@ -309,8 +309,8 @@ if (eax & IA32_FEATURE_CONTROL_MSR_LOCK) { if ((eax & IA32_FEATURE_CONTROL_MSR_ENABLE_VMXON) == 0x0) { - printk("VMX disabled by Feature Control MSR.\n"); - return 0; + printk("VMX disabled by Feature Control MSR.\n"); + return 0; } } else { @@ -320,16 +320,16 @@ } if (!check_vmx_controls(MONITOR_PIN_BASED_EXEC_CONTROLS, - MSR_IA32_VMX_PINBASED_CTLS_MSR)) + MSR_IA32_VMX_PINBASED_CTLS_MSR)) return 0; if (!check_vmx_controls(MONITOR_CPU_BASED_EXEC_CONTROLS, - MSR_IA32_VMX_PROCBASED_CTLS_MSR)) + MSR_IA32_VMX_PROCBASED_CTLS_MSR)) return 0; if (!check_vmx_controls(MONITOR_VM_EXIT_CONTROLS, - MSR_IA32_VMX_EXIT_CTLS_MSR)) + MSR_IA32_VMX_EXIT_CTLS_MSR)) return 0; if (!check_vmx_controls(MONITOR_VM_ENTRY_CONTROLS, - MSR_IA32_VMX_ENTRY_CTLS_MSR)) + MSR_IA32_VMX_ENTRY_CTLS_MSR)) return 0; set_in_cr4(X86_CR4_VMXE); /* Enable VMXE */ @@ -385,8 +385,8 @@ { __vmread(GUEST_RIP, &eip); VMX_DBG_LOG(DBG_LEVEL_VMMU, - "vmx_do_page_fault = 0x%lx, eip = %lx, error_code = %lx", - va, eip, (unsigned long)regs->error_code); + "vmx_do_page_fault = 0x%lx, eip = %lx, error_code = %lx", + va, eip, (unsigned long)regs->error_code); } #endif @@ -478,8 +478,8 @@ regs->edx = (unsigned long) edx; VMX_DBG_LOG(DBG_LEVEL_1, - "vmx_vmexit_do_cpuid: eip: %lx, input: %lx, out:eax=%x, ebx=%x, ecx=%x, edx=%x", - eip, input, eax, ebx, ecx, edx); + "vmx_vmexit_do_cpuid: eip: %lx, input: %lx, out:eax=%x, ebx=%x, ecx=%x, edx=%x", + eip, input, eax, ebx, ecx, edx); } @@ -607,7 +607,7 @@ } void send_pio_req(struct cpu_user_regs *regs, unsigned long port, - unsigned long count, int size, long value, int dir, int pvalid) + unsigned long count, int size, long value, int dir, int pvalid) { struct vcpu *v = current; vcpu_iodata_t *vio; @@ -620,8 +620,8 @@ } if (test_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags)) { - printf("VMX I/O has not yet completed\n"); - domain_crash_synchronous(); + printf("VMX I/O has not yet completed\n"); + domain_crash_synchronous(); } set_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags); @@ -656,7 +656,7 @@ } static void vmx_io_instruction(struct cpu_user_regs *regs, - unsigned long exit_qualification, unsigned long inst_len) + unsigned long exit_qualification, unsigned long inst_len) { struct mi_per_cpu_info *mpcip; unsigned long eip, cs, eflags; @@ -686,10 +686,10 @@ dir = test_bit(3, &exit_qualification); /* direction */ if (test_bit(4, &exit_qualification)) { /* string instruction */ - unsigned long addr, count = 1; - int sign = regs->eflags & EF_DF ? -1 : 1; - - __vmread(GUEST_LINEAR_ADDRESS, &addr); + unsigned long addr, count = 1; + int sign = regs->eflags & EF_DF ? -1 : 1; + + __vmread(GUEST_LINEAR_ADDRESS, &addr); /* * In protected mode, guest linear address is invalid if the @@ -699,35 +699,35 @@ addr = dir == IOREQ_WRITE ? regs->esi : regs->edi; if (test_bit(5, &exit_qualification)) { /* "rep" prefix */ - mpcip->flags |= REPZ; - count = vm86 ? regs->ecx & 0xFFFF : regs->ecx; - } - - /* - * Handle string pio instructions that cross pages or that - * are unaligned. See the comments in vmx_platform.c/handle_mmio() - */ - if ((addr & PAGE_MASK) != ((addr + size - 1) & PAGE_MASK)) { - unsigned long value = 0; - - mpcip->flags |= OVERLAP; - if (dir == IOREQ_WRITE) - vmx_copy(&value, addr, size, VMX_COPY_IN); - send_pio_req(regs, port, 1, size, value, dir, 0); - } else { - if ((addr & PAGE_MASK) != ((addr + count * size - 1) & PAGE_MASK)) { + mpcip->flags |= REPZ; + count = vm86 ? regs->ecx & 0xFFFF : regs->ecx; + } + + /* + * Handle string pio instructions that cross pages or that + * are unaligned. See the comments in vmx_platform.c/handle_mmio() + */ + if ((addr & PAGE_MASK) != ((addr + size - 1) & PAGE_MASK)) { + unsigned long value = 0; + + mpcip->flags |= OVERLAP; + if (dir == IOREQ_WRITE) + vmx_copy(&value, addr, size, VMX_COPY_IN); + send_pio_req(regs, port, 1, size, value, dir, 0); + } else { + if ((addr & PAGE_MASK) != ((addr + count * size - 1) & PAGE_MASK)) { if (sign > 0) count = (PAGE_SIZE - (addr & ~PAGE_MASK)) / size; else count = (addr & ~PAGE_MASK) / size; - } else - __update_guest_eip(inst_len); - - send_pio_req(regs, port, count, size, addr, dir, 1); - } + } else + __update_guest_eip(inst_len); + + send_pio_req(regs, port, count, size, addr, dir, 1); + } } else { __update_guest_eip(inst_len); - send_pio_req(regs, port, 1, size, regs->eax, dir, 0); + send_pio_req(regs, port, 1, size, regs->eax, dir, 0); } } @@ -739,30 +739,30 @@ int count; while (size > 0) { - count = PAGE_SIZE - (laddr & ~PAGE_MASK); - if (count > size) - count = size; - - if (vmx_paging_enabled(current)) { - gpa = gva_to_gpa(laddr); - mfn = get_mfn_from_pfn(gpa >> PAGE_SHIFT); - } else - mfn = get_mfn_from_pfn(laddr >> PAGE_SHIFT); - if (mfn == INVALID_MFN) - return 0; - - addr = (char *)map_domain_page(mfn) + (laddr & ~PAGE_MASK); - - if (dir == VMX_COPY_IN) - memcpy(buf, addr, count); - else - memcpy(addr, buf, count); - - unmap_domain_page(addr); - - laddr += count; - buf += count; - size -= count; + count = PAGE_SIZE - (laddr & ~PAGE_MASK); + if (count > size) + count = size; + + if (vmx_paging_enabled(current)) { + gpa = gva_to_gpa(laddr); + mfn = get_mfn_from_pfn(gpa >> PAGE_SHIFT); + } else + mfn = get_mfn_from_pfn(laddr >> PAGE_SHIFT); + if (mfn == INVALID_MFN) + return 0; + + addr = (char *)map_domain_page(mfn) + (laddr & ~PAGE_MASK); + + if (dir == VMX_COPY_IN) + memcpy(buf, addr, count); + else + memcpy(addr, buf, count); + + unmap_domain_page(addr); + + laddr += count; + buf += count; + size -= count; } return 1; @@ -846,47 +846,47 @@ error |= __vmwrite(CR0_READ_SHADOW, c->cr0); if (!vmx_paging_enabled(d)) { - VMX_DBG_LOG(DBG_LEVEL_VMMU, "switching to vmxassist. use phys table"); - __vmwrite(GUEST_CR3, pagetable_get_paddr(d->domain->arch.phys_table)); + VMX_DBG_LOG(DBG_LEVEL_VMMU, "switching to vmxassist. use phys table"); + __vmwrite(GUEST_CR3, pagetable_get_paddr(d->domain->arch.phys_table)); goto skip_cr3; } if (c->cr3 == d->arch.arch_vmx.cpu_cr3) { - /* - * This is simple TLB flush, implying the guest has - * removed some translation or changed page attributes. - * We simply invalidate the shadow. - */ - mfn = get_mfn_from_pfn(c->cr3 >> PAGE_SHIFT); - if (mfn != pagetable_get_pfn(d->arch.guest_table)) { - printk("Invalid CR3 value=%x", c->cr3); - domain_crash_synchronous(); - return 0; - } - shadow_sync_all(d->domain); + /* + * This is simple TLB flush, implying the guest has + * removed some translation or changed page attributes. + * We simply invalidate the shadow. + */ + mfn = get_mfn_from_pfn(c->cr3 >> PAGE_SHIFT); + if (mfn != pagetable_get_pfn(d->arch.guest_table)) { + printk("Invalid CR3 value=%x", c->cr3); + domain_crash_synchronous(); + return 0; + } + shadow_sync_all(d->domain); } else { - /* - * If different, make a shadow. Check if the PDBR is valid - * first. - */ - VMX_DBG_LOG(DBG_LEVEL_VMMU, "CR3 c->cr3 = %x", c->cr3); - if ((c->cr3 >> PAGE_SHIFT) > d->domain->max_pages) { - printk("Invalid CR3 value=%x", c->cr3); - domain_crash_synchronous(); - return 0; - } - mfn = get_mfn_from_pfn(c->cr3 >> PAGE_SHIFT); - d->arch.guest_table = mk_pagetable(mfn << PAGE_SHIFT); - update_pagetables(d); - /* - * arch.shadow_table should now hold the next CR3 for shadow - */ - d->arch.arch_vmx.cpu_cr3 = c->cr3; - VMX_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %x", c->cr3); - __vmwrite(GUEST_CR3, pagetable_get_paddr(d->arch.shadow_table)); - } - -skip_cr3: + /* + * If different, make a shadow. Check if the PDBR is valid + * first. + */ + VMX_DBG_LOG(DBG_LEVEL_VMMU, "CR3 c->cr3 = %x", c->cr3); + if ((c->cr3 >> PAGE_SHIFT) > d->domain->max_pages) { + printk("Invalid CR3 value=%x", c->cr3); + domain_crash_synchronous(); + return 0; + } + mfn = get_mfn_from_pfn(c->cr3 >> PAGE_SHIFT); + d->arch.guest_table = mk_pagetable(mfn << PAGE_SHIFT); + update_pagetables(d); + /* + * arch.shadow_table should now hold the next CR3 for shadow + */ + d->arch.arch_vmx.cpu_cr3 = c->cr3; + VMX_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %x", c->cr3); + __vmwrite(GUEST_CR3, pagetable_get_paddr(d->arch.shadow_table)); + } + + skip_cr3: error |= __vmread(CR4_READ_SHADOW, &old_cr4); error |= __vmwrite(GUEST_CR4, (c->cr4 | VMX_CR4_HOST_MASK)); @@ -952,59 +952,59 @@ /* make sure vmxassist exists (this is not an error) */ if (!vmx_copy(&magic, VMXASSIST_MAGIC_OFFSET, sizeof(magic), VMX_COPY_IN)) - return 0; + return 0; if (magic != VMXASSIST_MAGIC) - return 0; + return 0; switch (mode) { - /* - * Transfer control to vmxassist. - * Store the current context in VMXASSIST_OLD_CONTEXT and load - * the new VMXASSIST_NEW_CONTEXT context. This context was created - * by vmxassist and will transfer control to it. - */ + /* + * Transfer control to vmxassist. + * Store the current context in VMXASSIST_OLD_CONTEXT and load + * the new VMXASSIST_NEW_CONTEXT context. This context was created + * by vmxassist and will transfer control to it. + */ case VMX_ASSIST_INVOKE: - /* save the old context */ - if (!vmx_copy(&cp, VMXASSIST_OLD_CONTEXT, sizeof(cp), VMX_COPY_IN)) - goto error; - if (cp != 0) { - if (!vmx_world_save(d, &c)) - goto error; - if (!vmx_copy(&c, cp, sizeof(c), VMX_COPY_OUT)) - goto error; - } - - /* restore the new context, this should activate vmxassist */ - if (!vmx_copy(&cp, VMXASSIST_NEW_CONTEXT, sizeof(cp), VMX_COPY_IN)) - goto error; - if (cp != 0) { + /* save the old context */ + if (!vmx_copy(&cp, VMXASSIST_OLD_CONTEXT, sizeof(cp), VMX_COPY_IN)) + goto error; + if (cp != 0) { + if (!vmx_world_save(d, &c)) + goto error; + if (!vmx_copy(&c, cp, sizeof(c), VMX_COPY_OUT)) + goto error; + } + + /* restore the new context, this should activate vmxassist */ + if (!vmx_copy(&cp, VMXASSIST_NEW_CONTEXT, sizeof(cp), VMX_COPY_IN)) + goto error; + if (cp != 0) { if (!vmx_copy(&c, cp, sizeof(c), VMX_COPY_IN)) - goto error; - if (!vmx_world_restore(d, &c)) - goto error; - return 1; - } - break; - - /* - * Restore the VMXASSIST_OLD_CONTEXT that was saved by VMX_ASSIST_INVOKE - * above. - */ + goto error; + if (!vmx_world_restore(d, &c)) + goto error; + return 1; + } + break; + + /* + * Restore the VMXASSIST_OLD_CONTEXT that was saved by VMX_ASSIST_INVOKE + * above. + */ case VMX_ASSIST_RESTORE: - /* save the old context */ - if (!vmx_copy(&cp, VMXASSIST_OLD_CONTEXT, sizeof(cp), VMX_COPY_IN)) - goto error; - if (cp != 0) { + /* save the old context */ + if (!vmx_copy(&cp, VMXASSIST_OLD_CONTEXT, sizeof(cp), VMX_COPY_IN)) + goto error; + if (cp != 0) { if (!vmx_copy(&c, cp, sizeof(c), VMX_COPY_IN)) - goto error; - if (!vmx_world_restore(d, &c)) - goto error; - return 1; - } - break; - } - -error: + goto error; + if (!vmx_world_restore(d, &c)) + goto error; + return 1; + } + break; + } + + error: printf("Failed to transfer to vmxassist\n"); domain_crash_synchronous(); return 0; @@ -1031,7 +1031,7 @@ * The guest CR3 must be pointing to the guest physical. */ if ( !VALID_MFN(mfn = get_mfn_from_pfn( - d->arch.arch_vmx.cpu_cr3 >> PAGE_SHIFT)) || + d->arch.arch_vmx.cpu_cr3 >> PAGE_SHIFT)) || !get_page(pfn_to_page(mfn), d->domain) ) { printk("Invalid CR3 value = %lx", d->arch.arch_vmx.cpu_cr3); @@ -1040,18 +1040,18 @@ #if defined(__x86_64__) if (test_bit(VMX_CPU_STATE_LME_ENABLED, - &d->arch.arch_vmx.cpu_state) && - !test_bit(VMX_CPU_STATE_PAE_ENABLED, - &d->arch.arch_vmx.cpu_state)){ + &d->arch.arch_vmx.cpu_state) && + !test_bit(VMX_CPU_STATE_PAE_ENABLED, + &d->arch.arch_vmx.cpu_state)){ VMX_DBG_LOG(DBG_LEVEL_1, "Enable paging before PAE enable\n"); vmx_inject_exception(d, TRAP_gp_fault, 0); } if (test_bit(VMX_CPU_STATE_LME_ENABLED, - &d->arch.arch_vmx.cpu_state)){ + &d->arch.arch_vmx.cpu_state)){ /* Here the PAE is should to be opened */ VMX_DBG_LOG(DBG_LEVEL_1, "Enable the Long mode\n"); set_bit(VMX_CPU_STATE_LMA_ENABLED, - &d->arch.arch_vmx.cpu_state); + &d->arch.arch_vmx.cpu_state); __vmread(VM_ENTRY_CONTROLS, &vm_entry_value); vm_entry_value |= VM_ENTRY_CONTROLS_IA32E_MODE; __vmwrite(VM_ENTRY_CONTROLS, vm_entry_value); @@ -1073,20 +1073,15 @@ #endif } - unsigned long crn; + unsigned long crn; /* update CR4's PAE if needed */ __vmread(GUEST_CR4, &crn); if ( (!(crn & X86_CR4_PAE)) && - test_bit(VMX_CPU_STATE_PAE_ENABLED, - &d->arch.arch_vmx.cpu_state)){ + test_bit(VMX_CPU_STATE_PAE_ENABLED, + &d->arch.arch_vmx.cpu_state)){ VMX_DBG_LOG(DBG_LEVEL_1, "enable PAE on cr4\n"); __vmwrite(GUEST_CR4, crn | X86_CR4_PAE); } -#elif defined( __i386__) - unsigned long old_base_mfn; - old_base_mfn = pagetable_get_pfn(d->arch.guest_table); - if (old_base_mfn) - put_page(pfn_to_page(old_base_mfn)); #endif /* * Now arch.guest_table points to machine physical. @@ -1095,14 +1090,14 @@ update_pagetables(d); VMX_DBG_LOG(DBG_LEVEL_VMMU, "New arch.guest_table = %lx", - (unsigned long) (mfn << PAGE_SHIFT)); + (unsigned long) (mfn << PAGE_SHIFT)); __vmwrite(GUEST_CR3, pagetable_get_paddr(d->arch.shadow_table)); /* * arch->shadow_table should hold the next CR3 for shadow */ VMX_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %lx, mfn = %lx", - d->arch.arch_vmx.cpu_cr3, mfn); + d->arch.arch_vmx.cpu_cr3, mfn); } /* @@ -1129,29 +1124,29 @@ __vmwrite(VM_ENTRY_CONTROLS, vm_entry_value); } } - __vmread(GUEST_RIP, &eip); - VMX_DBG_LOG(DBG_LEVEL_1, - "Disabling CR0.PE at %%eip 0x%lx\n", eip); - if (vmx_assist(d, VMX_ASSIST_INVOKE)) { - set_bit(VMX_CPU_STATE_ASSIST_ENABLED, &d->arch.arch_vmx.cpu_state); - __vmread(GUEST_RIP, &eip); - VMX_DBG_LOG(DBG_LEVEL_1, - "Transfering control to vmxassist %%eip 0x%lx\n", eip); - return 0; /* do not update eip! */ - } + __vmread(GUEST_RIP, &eip); + VMX_DBG_LOG(DBG_LEVEL_1, + "Disabling CR0.PE at %%eip 0x%lx\n", eip); + if (vmx_assist(d, VMX_ASSIST_INVOKE)) { + set_bit(VMX_CPU_STATE_ASSIST_ENABLED, &d->arch.arch_vmx.cpu_state); + __vmread(GUEST_RIP, &eip); + VMX_DBG_LOG(DBG_LEVEL_1, + "Transfering control to vmxassist %%eip 0x%lx\n", eip); + return 0; /* do not update eip! */ + } } else if (test_bit(VMX_CPU_STATE_ASSIST_ENABLED, - &d->arch.arch_vmx.cpu_state)) { - __vmread(GUEST_RIP, &eip); - VMX_DBG_LOG(DBG_LEVEL_1, - "Enabling CR0.PE at %%eip 0x%lx\n", eip); - if (vmx_assist(d, VMX_ASSIST_RESTORE)) { - clear_bit(VMX_CPU_STATE_ASSIST_ENABLED, - &d->arch.arch_vmx.cpu_state); - __vmread(GUEST_RIP, &eip); - VMX_DBG_LOG(DBG_LEVEL_1, - "Restoring to %%eip 0x%lx\n", eip); - return 0; /* do not update eip! */ - } + &d->arch.arch_vmx.cpu_state)) { + __vmread(GUEST_RIP, &eip); + VMX_DBG_LOG(DBG_LEVEL_1, + "Enabling CR0.PE at %%eip 0x%lx\n", eip); + if (vmx_assist(d, VMX_ASSIST_RESTORE)) { + clear_bit(VMX_CPU_STATE_ASSIST_ENABLED, + &d->arch.arch_vmx.cpu_state); + __vmread(GUEST_RIP, &eip); + VMX_DBG_LOG(DBG_LEVEL_1, + "Restoring to %%eip 0x%lx\n", eip); + return 0; /* do not update eip! */ + } } return 1; @@ -1198,8 +1193,8 @@ CASE_GET_REG(ESI, esi); CASE_GET_REG(EDI, edi); CASE_EXTEND_GET_REG - case REG_ESP: - __vmread(GUEST_RSP, &value); + case REG_ESP: + __vmread(GUEST_RSP, &value); break; default: printk("invalid gp: %d\n", gp); @@ -1212,7 +1207,7 @@ switch(cr) { case 0: { - return vmx_set_cr0(value); + return vmx_set_cr0(value); } case 3: { @@ -1262,7 +1257,7 @@ */ d->arch.arch_vmx.cpu_cr3 = value; VMX_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %lx", - value); + value); __vmwrite(GUEST_CR3, pagetable_get_paddr(d->arch.shadow_table)); } break; @@ -1332,8 +1327,8 @@ CASE_SET_REG(ESI, esi); CASE_SET_REG(EDI, edi); CASE_EXTEND_SET_REG - case REG_ESP: - __vmwrite(GUEST_RSP, value); + case REG_ESP: + __vmwrite(GUEST_RSP, value); regs->esp = value; break; default: @@ -1381,9 +1376,9 @@ case TYPE_LMSW: TRACE_VMEXIT(1,TYPE_LMSW); __vmread(CR0_READ_SHADOW, &value); - value = (value & ~0xF) | - (((exit_qualification & LMSW_SOURCE_DATA) >> 16) & 0xF); - return vmx_set_cr0(value); + value = (value & ~0xF) | + (((exit_qualification & LMSW_SOURCE_DATA) >> 16) & 0xF); + return vmx_set_cr0(value); break; default: __vmx_bug(regs); @@ -1394,28 +1389,30 @@ static inline void vmx_do_msr_read(struct cpu_user_regs *regs) { + u64 msr_content = 0; + VMX_DBG_LOG(DBG_LEVEL_1, "vmx_do_msr_read: ecx=%lx, eax=%lx, edx=%lx", (unsigned long)regs->ecx, (unsigned long)regs->eax, (unsigned long)regs->edx); switch (regs->ecx) { - case MSR_IA32_SYSENTER_CS: - __vmread(GUEST_SYSENTER_CS, ®s->eax); - regs->edx = 0; - break; - case MSR_IA32_SYSENTER_ESP: - __vmread(GUEST_SYSENTER_ESP, ®s->eax); - regs->edx = 0; - break; - case MSR_IA32_SYSENTER_EIP: - __vmread(GUEST_SYSENTER_EIP, ®s->eax); - regs->edx = 0; - break; - default: - if(long_mode_do_msr_read(regs)) - return; - rdmsr_user(regs->ecx, regs->eax, regs->edx); - break; - } + case MSR_IA32_SYSENTER_CS: + __vmread(GUEST_SYSENTER_CS, (u32 *)&msr_content); + break; + case MSR_IA32_SYSENTER_ESP: + __vmread(GUEST_SYSENTER_ESP, &msr_content); + break; + case MSR_IA32_SYSENTER_EIP: + __vmread(GUEST_SYSENTER_EIP, &msr_content); + break; + default: + if(long_mode_do_msr_read(regs)) + return; + rdmsr_user(regs->ecx, regs->eax, regs->edx); + break; + } + + regs->eax = msr_content & 0xFFFFFFFF; + regs->edx = msr_content >> 32; VMX_DBG_LOG(DBG_LEVEL_1, "vmx_do_msr_read returns: " "ecx=%lx, eax=%lx, edx=%lx", @@ -1425,22 +1422,27 @@ static inline void vmx_do_msr_write(struct cpu_user_regs *regs) { + u64 msr_content; + VMX_DBG_LOG(DBG_LEVEL_1, "vmx_do_msr_write: ecx=%lx, eax=%lx, edx=%lx", (unsigned long)regs->ecx, (unsigned long)regs->eax, (unsigned long)regs->edx); + + msr_content = (regs->eax & 0xFFFFFFFF) | ((u64)regs->edx << 32); + switch (regs->ecx) { - case MSR_IA32_SYSENTER_CS: - __vmwrite(GUEST_SYSENTER_CS, regs->eax); - break; - case MSR_IA32_SYSENTER_ESP: - __vmwrite(GUEST_SYSENTER_ESP, regs->eax); - break; - case MSR_IA32_SYSENTER_EIP: - __vmwrite(GUEST_SYSENTER_EIP, regs->eax); - break; - default: - long_mode_do_msr_write(regs); - break; + case MSR_IA32_SYSENTER_CS: + __vmwrite(GUEST_SYSENTER_CS, msr_content); + break; + case MSR_IA32_SYSENTER_ESP: + __vmwrite(GUEST_SYSENTER_ESP, msr_content); + break; + case MSR_IA32_SYSENTER_EIP: + __vmwrite(GUEST_SYSENTER_EIP, msr_content); + break; + default: + long_mode_do_msr_write(regs); + break; } VMX_DBG_LOG(DBG_LEVEL_1, "vmx_do_msr_write returns: " @@ -1484,28 +1486,28 @@ local_irq_disable(); switch(vector) { - case LOCAL_TIMER_VECTOR: - smp_apic_timer_interrupt(regs); - break; - case EVENT_CHECK_VECTOR: - smp_event_check_interrupt(); - break; - case INVALIDATE_TLB_VECTOR: - smp_invalidate_interrupt(); - break; - case CALL_FUNCTION_VECTOR: - smp_call_function_interrupt(); - break; - case SPURIOUS_APIC_VECTOR: - smp_spurious_interrupt(regs); - break; - case ERROR_APIC_VECTOR: - smp_error_interrupt(regs); - break; - default: - regs->entry_vector = vector; - do_IRQ(regs); - break; + case LOCAL_TIMER_VECTOR: + smp_apic_timer_interrupt(regs); + break; + case EVENT_CHECK_VECTOR: + smp_event_check_interrupt(); + break; + case INVALIDATE_TLB_VECTOR: + smp_invalidate_interrupt(); + break; + case CALL_FUNCTION_VECTOR: + smp_call_function_interrupt(); + break; + case SPURIOUS_APIC_VECTOR: + smp_spurious_interrupt(regs); + break; + case ERROR_APIC_VECTOR: + smp_error_interrupt(regs); + break; + default: + regs->entry_vector = vector; + do_IRQ(regs); + break; } } @@ -1597,17 +1599,17 @@ __vmread(IDT_VECTORING_INFO_FIELD, &idtv_info_field); if (idtv_info_field & INTR_INFO_VALID_MASK) { - __vmwrite(VM_ENTRY_INTR_INFO_FIELD, idtv_info_field); - - __vmread(VM_EXIT_INSTRUCTION_LEN, &inst_len); - if (inst_len >= 1 && inst_len <= 15) - __vmwrite(VM_ENTRY_INSTRUCTION_LEN, inst_len); - - if (idtv_info_field & 0x800) { /* valid error code */ - unsigned long error_code; - __vmread(IDT_VECTORING_ERROR_CODE, &error_code); - __vmwrite(VM_ENTRY_EXCEPTION_ERROR_CODE, error_code); - } + __vmwrite(VM_ENTRY_INTR_INFO_FIELD, idtv_info_field); + + __vmread(VM_EXIT_INSTRUCTION_LEN, &inst_len); + if (inst_len >= 1 && inst_len <= 15) + __vmwrite(VM_ENTRY_INSTRUCTION_LEN, inst_len); + + if (idtv_info_field & 0x800) { /* valid error code */ + unsigned long error_code; + __vmread(IDT_VECTORING_ERROR_CODE, &error_code); + __vmwrite(VM_ENTRY_EXCEPTION_ERROR_CODE, error_code); + } VMX_DBG_LOG(DBG_LEVEL_1, "idtv_info_field=%x", idtv_info_field); } @@ -1645,7 +1647,7 @@ __vmx_bug(®s); vector &= 0xff; - TRACE_VMEXIT(1,vector); + TRACE_VMEXIT(1,vector); perfc_incra(cause_vector, vector); TRACE_3D(TRC_VMX_VECTOR, v->domain->domain_id, eip, vector); @@ -1691,8 +1693,8 @@ __vmread(EXIT_QUALIFICATION, &va); __vmread(VM_EXIT_INTR_ERROR_CODE, ®s.error_code); - TRACE_VMEXIT(3,regs.error_code); - TRACE_VMEXIT(4,va); + TRACE_VMEXIT(3,regs.error_code); + TRACE_VMEXIT(4,va); VMX_DBG_LOG(DBG_LEVEL_VMMU, "eax=%lx, ebx=%lx, ecx=%lx, edx=%lx, esi=%lx, edi=%lx", @@ -1725,7 +1727,7 @@ break; case EXIT_REASON_PENDING_INTERRUPT: __vmwrite(CPU_BASED_VM_EXEC_CONTROL, - MONITOR_CPU_BASED_EXEC_CONTROLS); + MONITOR_CPU_BASED_EXEC_CONTROLS); break; case EXIT_REASON_TASK_SWITCH: __vmx_bug(®s); @@ -1765,10 +1767,10 @@ __vmread(EXIT_QUALIFICATION, &exit_qualification); VMX_DBG_LOG(DBG_LEVEL_1, "eip = %lx, inst_len =%lx, exit_qualification = %lx", - eip, inst_len, exit_qualification); + eip, inst_len, exit_qualification); if (vmx_cr_access(exit_qualification, ®s)) - __update_guest_eip(inst_len); - TRACE_VMEXIT(3,regs.error_code); + __update_guest_eip(inst_len); + TRACE_VMEXIT(3,regs.error_code); TRACE_VMEXIT(4,exit_qualification); break; } @@ -1821,8 +1823,8 @@ asmlinkage void trace_vmentry (void) { TRACE_5D(TRC_VMENTRY,trace_values[current->processor][0], - trace_values[current->processor][1],trace_values[current->processor][2], - trace_values[current->processor][3],trace_values[current->processor][4]); + trace_values[current->processor][1],trace_values[current->processor][2], + trace_values[current->processor][3],trace_values[current->processor][4]); TRACE_VMEXIT(0,9); TRACE_VMEXIT(1,9); TRACE_VMEXIT(2,9); diff -r d4d880fcef28 -r b35215021b32 xen/arch/x86/vmx_intercept.c --- a/xen/arch/x86/vmx_intercept.c Fri Sep 9 16:31:36 2005 +++ b/xen/arch/x86/vmx_intercept.c Tue Sep 13 16:14:16 2005 @@ -45,8 +45,8 @@ addr = handler->hdl_list[i].addr; offset = handler->hdl_list[i].offset; if (p->addr >= addr && - p->addr < addr + offset) - return handler->hdl_list[i].action(p); + p->addr < addr + offset) + return handler->hdl_list[i].action(p); } return 0; } @@ -172,22 +172,22 @@ if (p->size != 1 || p->pdata_valid || - p->type != IOREQ_TYPE_PIO) + p->type != IOREQ_TYPE_PIO) return 0; if (p->addr == PIT_MODE && - p->dir == 0 && /* write */ - ((p->u.data >> 4) & 0x3) == 0 && /* latch command */ + p->dir == 0 && /* write */ + ((p->u.data >> 4) & 0x3) == 0 && /* latch command */ ((p->u.data >> 6) & 0x3) == (vpit->channel)) {/* right channel */ pit_latch_io(vpit); - return 1; + return 1; } if (p->addr == (PIT_CH0 + vpit->channel) && - p->dir == 1) { /* read */ + p->dir == 1) { /* read */ p->u.data = pit_read_io(vpit); resume_pit_io(p); - return 1; + return 1; } return 0; @@ -253,8 +253,8 @@ vpit->channel = ((p->u.data >> 24) & 0x3); vpit->first_injected = 0; - vpit->count_LSB_latched = 0; - vpit->count_MSB_latched = 0; + vpit->count_LSB_latched = 0; + vpit->count_MSB_latched = 0; rw_mode = ((p->u.data >> 26) & 0x3); switch(rw_mode) { @@ -280,9 +280,19 @@ /*restore the state*/ p->state = STATE_IORESP_READY; - /* register handler to intercept the PIT io when vm_exit */ + /* register handler to intercept the PIT io when vm_exit */ if (!reinit) - register_portio_handler(0x40, 4, intercept_pit_io); + register_portio_handler(0x40, 4, intercept_pit_io); } } #endif /* CONFIG_VMX */ + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff -r d4d880fcef28 -r b35215021b32 xen/arch/x86/vmx_io.c --- a/xen/arch/x86/vmx_io.c Fri Sep 9 16:31:36 2005 +++ b/xen/arch/x86/vmx_io.c Tue Sep 13 16:14:16 2005 @@ -16,6 +16,7 @@ * Place - Suite 330, Boston, MA 02111-1307 USA. * */ + #include <xen/config.h> #include <xen/init.h> #include <xen/mm.h> @@ -99,7 +100,6 @@ printk("Error: size:%x, index:%x are invalid!\n", size, index); domain_crash_synchronous(); break; - } break; case WORD: @@ -199,24 +199,24 @@ static inline void __set_reg_value(unsigned long *reg, int size, long value) { switch (size) { - case BYTE_64: - *reg &= ~0xFF; - *reg |= (value & 0xFF); - break; - case WORD: - *reg &= ~0xFFFF; - *reg |= (value & 0xFFFF); - break; - case LONG: - *reg &= ~0xFFFFFFFF; - *reg |= (value & 0xFFFFFFFF); - break; - case QUAD: - *reg = value; - break; - default: - printk("Error: <__set_reg_value> : Unknown size for register\n"); - domain_crash_synchronous(); + case BYTE_64: + *reg &= ~0xFF; + *reg |= (value & 0xFF); + break; + case WORD: + *reg &= ~0xFFFF; + *reg |= (value & 0xFFFF); + break; + case LONG: + *reg &= ~0xFFFFFFFF; + *reg |= (value & 0xFFFFFFFF); + break; + case QUAD: + *reg = value; + break; + default: + printk("Error: <__set_reg_value>: size:%x is invalid\n", size); + domain_crash_synchronous(); } } @@ -224,98 +224,98 @@ { if (size == BYTE) { switch (index) { - case 0: - regs->rax &= ~0xFF; - regs->rax |= (value & 0xFF); - break; - case 1: - regs->rcx &= ~0xFF; - regs->rcx |= (value & 0xFF); - break; - case 2: - regs->rdx &= ~0xFF; - regs->rdx |= (value & 0xFF); - break; - case 3: - regs->rbx &= ~0xFF; - regs->rbx |= (value & 0xFF); - break; - case 4: - regs->rax &= 0xFFFFFFFFFFFF00FF; - regs->rax |= ((value & 0xFF) << 8); - break; - case 5: - regs->rcx &= 0xFFFFFFFFFFFF00FF; - regs->rcx |= ((value & 0xFF) << 8); - break; - case 6: - regs->rdx &= 0xFFFFFFFFFFFF00FF; - regs->rdx |= ((value & 0xFF) << 8); - break; - case 7: - regs->rbx &= 0xFFFFFFFFFFFF00FF; - regs->rbx |= ((value & 0xFF) << 8); - break; - default: - printk("Error: size:%x, index:%x are invalid!\n", size, index); - domain_crash_synchronous(); - break; - } - + case 0: + regs->rax &= ~0xFF; + regs->rax |= (value & 0xFF); + break; + case 1: + regs->rcx &= ~0xFF; + regs->rcx |= (value & 0xFF); + break; + case 2: + regs->rdx &= ~0xFF; + regs->rdx |= (value & 0xFF); + break; + case 3: + regs->rbx &= ~0xFF; + regs->rbx |= (value & 0xFF); + break; + case 4: + regs->rax &= 0xFFFFFFFFFFFF00FF; + regs->rax |= ((value & 0xFF) << 8); + break; + case 5: + regs->rcx &= 0xFFFFFFFFFFFF00FF; + regs->rcx |= ((value & 0xFF) << 8); + break; + case 6: + regs->rdx &= 0xFFFFFFFFFFFF00FF; + regs->rdx |= ((value & 0xFF) << 8); + break; + case 7: + regs->rbx &= 0xFFFFFFFFFFFF00FF; + regs->rbx |= ((value & 0xFF) << 8); + break; + default: + printk("Error: size:%x, index:%x are invalid!\n", size, index); + domain_crash_synchronous(); + break; + } + return; } switch (index) { - case 0: - __set_reg_value(®s->rax, size, value); - break; - case 1: - __set_reg_value(®s->rcx, size, value); - break; - case 2: - __set_reg_value(®s->rdx, size, value); - break; - case 3: - __set_reg_value(®s->rbx, size, value); - break; - case 4: - __set_reg_value(®s->rsp, size, value); - break; - case 5: - __set_reg_value(®s->rbp, size, value); - break; - case 6: - __set_reg_value(®s->rsi, size, value); - break; - case 7: - __set_reg_value(®s->rdi, size, value); - break; - case 8: - __set_reg_value(®s->r8, size, value); - break; - case 9: - __set_reg_value(®s->r9, size, value); - break; - case 10: - __set_reg_value(®s->r10, size, value); - break; - case 11: - __set_reg_value(®s->r11, size, value); - break; - case 12: - __set_reg_value(®s->r12, size, value); - break; - case 13: - __set_reg_value(®s->r13, size, value); - break; - case 14: - __set_reg_value(®s->r14, size, value); - break; - case 15: - __set_reg_value(®s->r15, size, value); - break; - default: - printk("Error: <set_reg_value> Invalid index\n"); - domain_crash_synchronous(); + case 0: + __set_reg_value(®s->rax, size, value); + break; + case 1: + __set_reg_value(®s->rcx, size, value); + break; + case 2: + __set_reg_value(®s->rdx, size, value); + break; + case 3: + __set_reg_value(®s->rbx, size, value); + break; + case 4: + __set_reg_value(®s->rsp, size, value); + break; + case 5: + __set_reg_value(®s->rbp, size, value); + break; + case 6: + __set_reg_value(®s->rsi, size, value); + break; + case 7: + __set_reg_value(®s->rdi, size, value); + break; + case 8: + __set_reg_value(®s->r8, size, value); + break; + case 9: + __set_reg_value(®s->r9, size, value); + break; + case 10: + __set_reg_value(®s->r10, size, value); + break; + case 11: + __set_reg_value(®s->r11, size, value); + break; + case 12: + __set_reg_value(®s->r12, size, value); + break; + case 13: + __set_reg_value(®s->r13, size, value); + break; + case 14: + __set_reg_value(®s->r14, size, value); + break; + case 15: + __set_reg_value(®s->r15, size, value); + break; + default: + printk("Error: <set_reg_value> Invalid index\n"); + domain_crash_synchronous(); } return; } @@ -324,44 +324,44 @@ extern long get_reg_value(int size, int index, int seg, struct cpu_user_regs *regs); static inline void set_eflags_CF(int size, unsigned long v1, - unsigned long v2, struct cpu_user_regs *regs) + unsigned long v2, struct cpu_user_regs *regs) { unsigned long mask = (1 << (8 * size)) - 1; if ((v1 & mask) > (v2 & mask)) - regs->eflags |= X86_EFLAGS_CF; + regs->eflags |= X86_EFLAGS_CF; else - regs->eflags &= ~X86_EFLAGS_CF; + regs->eflags &= ~X86_EFLAGS_CF; } static inline void set_eflags_OF(int size, unsigned long v1, - unsigned long v2, unsigned long v3, struct cpu_user_regs *regs) + unsigned long v2, unsigned long v3, struct cpu_user_regs *regs) { if ((v3 ^ v2) & (v3 ^ v1) & (1 << ((8 * size) - 1))) - regs->eflags |= X86_EFLAGS_OF; + regs->eflags |= X86_EFLAGS_OF; } static inline void set_eflags_AF(int size, unsigned long v1, - unsigned long v2, unsigned long v3, struct cpu_user_regs *regs) + unsigned long v2, unsigned long v3, struct cpu_user_regs *regs) { if ((v1 ^ v2 ^ v3) & 0x10) - regs->eflags |= X86_EFLAGS_AF; + regs->eflags |= X86_EFLAGS_AF; } static inline void set_eflags_ZF(int size, unsigned long v1, - struct cpu_user_regs *regs) + struct cpu_user_regs *regs) { unsigned long mask = (1 << (8 * size)) - 1; if ((v1 & mask) == 0) - regs->eflags |= X86_EFLAGS_ZF; + regs->eflags |= X86_EFLAGS_ZF; } static inline void set_eflags_SF(int size, unsigned long v1, - struct cpu_user_regs *regs) + struct cpu_user_regs *regs) { if (v1 & (1 << ((8 * size) - 1))) - regs->eflags |= X86_EFLAGS_SF; + regs->eflags |= X86_EFLAGS_SF; } static char parity_table[256] = { @@ -384,14 +384,14 @@ }; static inline void set_eflags_PF(int size, unsigned long v1, - struct cpu_user_regs *regs) + struct cpu_user_regs *regs) { if (parity_table[v1 & 0xFF]) - regs->eflags |= X86_EFLAGS_PF; + regs->eflags |= X86_EFLAGS_PF; } static void vmx_pio_assist(struct cpu_user_regs *regs, ioreq_t *p, - struct mi_per_cpu_info *mpcip) + struct mi_per_cpu_info *mpcip) { unsigned long old_eax; int sign = p->df ? -1 : 1; @@ -399,28 +399,28 @@ if (p->dir == IOREQ_WRITE) { if (p->pdata_valid) { regs->esi += sign * p->count * p->size; - if (mpcip->flags & REPZ) - regs->ecx -= p->count; + if (mpcip->flags & REPZ) + regs->ecx -= p->count; } } else { - if (mpcip->flags & OVERLAP) { - unsigned long addr; + if (mpcip->flags & OVERLAP) { + unsigned long addr; regs->edi += sign * p->count * p->size; - if (mpcip->flags & REPZ) - regs->ecx -= p->count; - - addr = regs->edi; - if (sign > 0) - addr -= p->size; - vmx_copy(&p->u.data, addr, p->size, VMX_COPY_OUT); - } else if (p->pdata_valid) { + if (mpcip->flags & REPZ) + regs->ecx -= p->count; + + addr = regs->edi; + if (sign > 0) + addr -= p->size; + vmx_copy(&p->u.data, addr, p->size, VMX_COPY_OUT); + } else if (p->pdata_valid) { regs->edi += sign * p->count * p->size; - if (mpcip->flags & REPZ) - regs->ecx -= p->count; + if (mpcip->flags & REPZ) + regs->ecx -= p->count; } else { - old_eax = regs->eax; - switch (p->size) { + old_eax = regs->eax; + switch (p->size) { case 1: regs->eax = (old_eax & 0xffffff00) | (p->u.data & 0xff); break; @@ -431,15 +431,15 @@ regs->eax = (p->u.data & 0xffffffff); break; default: - printk("Error: %s unknown port size\n", __FUNCTION__); - domain_crash_synchronous(); - } - } + printk("Error: %s unknown port size\n", __FUNCTION__); + domain_crash_synchronous(); + } + } } } static void vmx_mmio_assist(struct cpu_user_regs *regs, ioreq_t *p, - struct mi_per_cpu_info *mpcip) + struct mi_per_cpu_info *mpcip) { int sign = p->df ? -1 : 1; int size = -1, index = -1; @@ -452,178 +452,178 @@ switch (mpcip->instr) { case INSTR_MOV: - if (dst & REGISTER) { - index = operand_index(dst); - set_reg_value(size, index, 0, regs, p->u.data); - } - break; + if (dst & REGISTER) { + index = operand_index(dst); + set_reg_value(size, index, 0, regs, p->u.data); + } + break; case INSTR_MOVZ: - if (dst & REGISTER) { - index = operand_index(dst); - switch (size) { - case BYTE: p->u.data = p->u.data & 0xFFULL; break; - case WORD: p->u.data = p->u.data & 0xFFFFULL; break; - case LONG: p->u.data = p->u.data & 0xFFFFFFFFULL; break; - } - set_reg_value(operand_size(dst), index, 0, regs, p->u.data); - } - break; + if (dst & REGISTER) { + index = operand_index(dst); + switch (size) { + case BYTE: p->u.data = p->u.data & 0xFFULL; break; + case WORD: p->u.data = p->u.data & 0xFFFFULL; break; + case LONG: p->u.data = p->u.data & 0xFFFFFFFFULL; break; + } + set_reg_value(operand_size(dst), index, 0, regs, p->u.data); + } + break; case INSTR_MOVS: - sign = p->df ? -1 : 1; - regs->esi += sign * p->count * p->size; - regs->edi += sign * p->count * p->size; - - if ((mpcip->flags & OVERLAP) && p->dir == IOREQ_READ) { - unsigned long addr = regs->edi; - - if (sign > 0) - addr -= p->size; - vmx_copy(&p->u.data, addr, p->size, VMX_COPY_OUT); - } - - if (mpcip->flags & REPZ) - regs->ecx -= p->count; - break; + sign = p->df ? -1 : 1; + regs->esi += sign * p->count * p->size; + regs->edi += sign * p->count * p->size; + + if ((mpcip->flags & OVERLAP) && p->dir == IOREQ_READ) { + unsigned long addr = regs->edi; + + if (sign > 0) + addr -= p->size; + vmx_copy(&p->u.data, addr, p->size, VMX_COPY_OUT); + } + + if (mpcip->flags & REPZ) + regs->ecx -= p->count; + break; case INSTR_STOS: - sign = p->df ? -1 : 1; - regs->edi += sign * p->count * p->size; - if (mpcip->flags & REPZ) - regs->ecx -= p->count; - break; + sign = p->df ? -1 : 1; + regs->edi += sign * p->count * p->size; + if (mpcip->flags & REPZ) + regs->ecx -= p->count; + break; case INSTR_AND: - if (src & REGISTER) { - index = operand_index(src); - value = get_reg_value(size, index, 0, regs); - diff = (unsigned long) p->u.data & value; - } else if (src & IMMEDIATE) { - value = mpcip->immediate; - diff = (unsigned long) p->u.data & value; - } else if (src & MEMORY) { - index = operand_index(dst); - value = get_reg_value(size, index, 0, regs); - diff = (unsigned long) p->u.data & value; - set_reg_value(size, index, 0, regs, diff); - } - - /* - * The OF and CF flags are cleared; the SF, ZF, and PF - * flags are set according to the result. The state of - * the AF flag is undefined. - */ - regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF| - X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF); - set_eflags_ZF(size, diff, regs); - set_eflags_SF(size, diff, regs); - set_eflags_PF(size, diff, regs); - break; + if (src & REGISTER) { + index = operand_index(src); + value = get_reg_value(size, index, 0, regs); + diff = (unsigned long) p->u.data & value; + } else if (src & IMMEDIATE) { + value = mpcip->immediate; + diff = (unsigned long) p->u.data & value; + } else if (src & MEMORY) { + index = operand_index(dst); + value = get_reg_value(size, index, 0, regs); + diff = (unsigned long) p->u.data & value; + set_reg_value(size, index, 0, regs, diff); + } + + /* + * The OF and CF flags are cleared; the SF, ZF, and PF + * flags are set according to the result. The state of + * the AF flag is undefined. + */ + regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF| + X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF); + set_eflags_ZF(size, diff, regs); + set_eflags_SF(size, diff, regs); + set_eflags_PF(size, diff, regs); + break; case INSTR_OR: - if (src & REGISTER) { - index = operand_index(src); - value = get_reg_value(size, index, 0, regs); - diff = (unsigned long) p->u.data | value; - } else if (src & IMMEDIATE) { - value = mpcip->immediate; - diff = (unsigned long) p->u.data | value; - } else if (src & MEMORY) { - index = operand_index(dst); - value = get_reg_value(size, index, 0, regs); - diff = (unsigned long) p->u.data | value; - set_reg_value(size, index, 0, regs, diff); - } - - /* - * The OF and CF flags are cleared; the SF, ZF, and PF - * flags are set according to the result. The state of - * the AF flag is undefined. - */ - regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF| - X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF); - set_eflags_ZF(size, diff, regs); - set_eflags_SF(size, diff, regs); - set_eflags_PF(size, diff, regs); - break; + if (src & REGISTER) { + index = operand_index(src); + value = get_reg_value(size, index, 0, regs); + diff = (unsigned long) p->u.data | value; + } else if (src & IMMEDIATE) { + value = mpcip->immediate; + diff = (unsigned long) p->u.data | value; + } else if (src & MEMORY) { + index = operand_index(dst); + value = get_reg_value(size, index, 0, regs); + diff = (unsigned long) p->u.data | value; + set_reg_value(size, index, 0, regs, diff); + } + + /* + * The OF and CF flags are cleared; the SF, ZF, and PF + * flags are set according to the result. The state of + * the AF flag is undefined. + */ + regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF| + X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF); + set_eflags_ZF(size, diff, regs); + set_eflags_SF(size, diff, regs); + set_eflags_PF(size, diff, regs); + break; case INSTR_XOR: - if (src & REGISTER) { - index = operand_index(src); - value = get_reg_value(size, index, 0, regs); - diff = (unsigned long) p->u.data ^ value; - } else if (src & IMMEDIATE) { - value = mpcip->immediate; - diff = (unsigned long) p->u.data ^ value; - } else if (src & MEMORY) { - index = operand_index(dst); - value = get_reg_value(size, index, 0, regs); - diff = (unsigned long) p->u.data ^ value; - set_reg_value(size, index, 0, regs, diff); - } - - /* - * The OF and CF flags are cleared; the SF, ZF, and PF - * flags are set according to the result. The state of - * the AF flag is undefined. - */ - regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF| - X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF); - set_eflags_ZF(size, diff, regs); - set_eflags_SF(size, diff, regs); - set_eflags_PF(size, diff, regs); - break; + if (src & REGISTER) { + index = operand_index(src); + value = get_reg_value(size, index, 0, regs); + diff = (unsigned long) p->u.data ^ value; + } else if (src & IMMEDIATE) { + value = mpcip->immediate; + diff = (unsigned long) p->u.data ^ value; + } else if (src & MEMORY) { + index = operand_index(dst); + value = get_reg_value(size, index, 0, regs); + diff = (unsigned long) p->u.data ^ value; + set_reg_value(size, index, 0, regs, diff); + } + + /* + * The OF and CF flags are cleared; the SF, ZF, and PF + * flags are set according to the result. The state of + * the AF flag is undefined. + */ + regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF| + X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF); + set_eflags_ZF(size, diff, regs); + set_eflags_SF(size, diff, regs); + set_eflags_PF(size, diff, regs); + break; case INSTR_CMP: - if (src & REGISTER) { - index = operand_index(src); - value = get_reg_value(size, index, 0, regs); - diff = (unsigned long) p->u.data - value; - } else if (src & IMMEDIATE) { - value = mpcip->immediate; - diff = (unsigned long) p->u.data - value; - } else if (src & MEMORY) { - index = operand_index(dst); - value = get_reg_value(size, index, 0, regs); - diff = value - (unsigned long) p->u.data; - } - - /* - * The CF, OF, SF, ZF, AF, and PF flags are set according - * to the result - */ - regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|X86_EFLAGS_AF| - X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF); - set_eflags_CF(size, value, (unsigned long) p->u.data, regs); - set_eflags_OF(size, diff, value, (unsigned long) p->u.data, regs); - set_eflags_AF(size, diff, value, (unsigned long) p->u.data, regs); - set_eflags_ZF(size, diff, regs); - set_eflags_SF(size, diff, regs); - set_eflags_PF(size, diff, regs); - break; + if (src & REGISTER) { + index = operand_index(src); + value = get_reg_value(size, index, 0, regs); + diff = (unsigned long) p->u.data - value; + } else if (src & IMMEDIATE) { + value = mpcip->immediate; + diff = (unsigned long) p->u.data - value; + } else if (src & MEMORY) { + index = operand_index(dst); + value = get_reg_value(size, index, 0, regs); + diff = value - (unsigned long) p->u.data; + } + + /* + * The CF, OF, SF, ZF, AF, and PF flags are set according + * to the result + */ + regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|X86_EFLAGS_AF| + X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF); + set_eflags_CF(size, value, (unsigned long) p->u.data, regs); + set_eflags_OF(size, diff, value, (unsigned long) p->u.data, regs); + set_eflags_AF(size, diff, value, (unsigned long) p->u.data, regs); + set_eflags_ZF(size, diff, regs); + set_eflags_SF(size, diff, regs); + set_eflags_PF(size, diff, regs); + break; case INSTR_TEST: - if (src & REGISTER) { - index = operand_index(src); - value = get_reg_value(size, index, 0, regs); - } else if (src & IMMEDIATE) { - value = mpcip->immediate; - } else if (src & MEMORY) { - index = operand_index(dst); - value = get_reg_value(size, index, 0, regs); - } - diff = (unsigned long) p->u.data & value; - - /* - * Sets the SF, ZF, and PF status flags. CF and OF are set to 0 - */ - regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF| - X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF); - set_eflags_ZF(size, diff, regs); - set_eflags_SF(size, diff, regs); - set_eflags_PF(size, diff, regs); - break; + if (src & REGISTER) { + index = operand_index(src); + value = get_reg_value(size, index, 0, regs); + } else if (src & IMMEDIATE) { + value = mpcip->immediate; + } else if (src & MEMORY) { + index = operand_index(dst); + value = get_reg_value(size, index, 0, regs); + } + diff = (unsigned long) p->u.data & value; + + /* + * Sets the SF, ZF, and PF status flags. CF and OF are set to 0 + */ + regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF| + X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF); + set_eflags_ZF(size, diff, regs); + set_eflags_SF(size, diff, regs); + set_eflags_PF(size, diff, regs); + break; } load_cpu_user_regs(regs); @@ -645,7 +645,7 @@ if (vio == 0) { VMX_DBG_LOG(DBG_LEVEL_1, "bad shared page: %lx", (unsigned long) vio); - printf("bad shared page: %lx\n", (unsigned long) vio); + printf("bad shared page: %lx\n", (unsigned long) vio); domain_crash_synchronous(); } @@ -656,15 +656,15 @@ /* clear IO wait VMX flag */ if (test_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags)) { if (p->state == STATE_IORESP_READY) { - p->state = STATE_INVALID; + p->state = STATE_INVALID; clear_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags); - if (p->type == IOREQ_TYPE_PIO) - vmx_pio_assist(regs, p, mpci_p); - else - vmx_mmio_assist(regs, p, mpci_p); - } - /* else an interrupt send event raced us */ + if (p->type == IOREQ_TYPE_PIO) + vmx_pio_assist(regs, p, mpci_p); + else + vmx_mmio_assist(regs, p, mpci_p); + } + /* else an interrupt send event raced us */ } } @@ -731,7 +731,7 @@ return word ? bit : -1; } #else -#define __fls(x) generic_fls(x) +#define __fls(x) generic_fls(x) static __inline__ int generic_fls(u32 x) { int r = 31; @@ -840,23 +840,23 @@ struct vmx_virpit_t *vpit = &(v->domain->arch.vmx_platform.vmx_pit); switch(type) { - case VLAPIC_DELIV_MODE_EXT: - if (vpit->pending_intr_nr && vector == vpit->vector) - vpit->pending_intr_nr--; - else - clear_highest_bit(v, vector); - - if (vector == vpit->vector && !vpit->first_injected){ - vpit->first_injected = 1; - vpit->pending_intr_nr = 0; - } - if (vector == vpit->vector) - vpit->inject_point = NOW(); - break; - - default: - printk("Not support interrupt type\n"); - break; + case VLAPIC_DELIV_MODE_EXT: + if (vpit->pending_intr_nr && vector == vpit->vector) + vpit->pending_intr_nr--; + else + clear_highest_bit(v, vector); + + if (vector == vpit->vector && !vpit->first_injected){ + vpit->first_injected = 1; + vpit->pending_intr_nr = 0; + } + if (vector == vpit->vector) + vpit->inject_point = NOW(); + break; + + default: + printk("Not support interrupt type\n"); + break; } } @@ -898,51 +898,51 @@ return; } - __vmread(VM_ENTRY_INTR_INFO_FIELD, &intr_fields); - - if (intr_fields & INTR_INFO_VALID_MASK) { - VMX_DBG_LOG(DBG_LEVEL_1, "vmx_intr_assist: intr_fields: %lx", - intr_fields); - return; - } - - __vmread(GUEST_INTERRUPTIBILITY_INFO, &interruptibility); - - if (interruptibility) { - enable_irq_window(cpu_exec_control); - VMX_DBG_LOG(DBG_LEVEL_1, "guesting pending: %x, interruptibility: %lx", - highest_vector, interruptibility); - return; - } - - __vmread(GUEST_RFLAGS, &eflags); - - switch (intr_type) { - case VLAPIC_DELIV_MODE_EXT: - if (irq_masked(eflags)) { - enable_irq_window(cpu_exec_control); - VMX_DBG_LOG(DBG_LEVEL_1, "guesting pending: %x, eflags: %lx", - highest_vector, eflags); - return; - } - - vmx_inject_extint(v, highest_vector, VMX_INVALID_ERROR_CODE); - TRACE_3D(TRC_VMX_INT, v->domain->domain_id, highest_vector, 0); - break; - case VLAPIC_DELIV_MODE_FIXED: - case VLAPIC_DELIV_MODE_LPRI: - case VLAPIC_DELIV_MODE_SMI: - case VLAPIC_DELIV_MODE_NMI: - case VLAPIC_DELIV_MODE_INIT: - case VLAPIC_DELIV_MODE_STARTUP: - default: - printk("Unsupported interrupt type\n"); - BUG(); - break; - } - - interrupt_post_injection(v, highest_vector, intr_type); - return; + __vmread(VM_ENTRY_INTR_INFO_FIELD, &intr_fields); + + if (intr_fields & INTR_INFO_VALID_MASK) { + VMX_DBG_LOG(DBG_LEVEL_1, "vmx_intr_assist: intr_fields: %lx", + intr_fields); + return; + } + + __vmread(GUEST_INTERRUPTIBILITY_INFO, &interruptibility); + + if (interruptibility) { + enable_irq_window(cpu_exec_control); + VMX_DBG_LOG(DBG_LEVEL_1, "guesting pending: %x, interruptibility: %lx", + highest_vector, interruptibility); + return; + } + + __vmread(GUEST_RFLAGS, &eflags); + + switch (intr_type) { + case VLAPIC_DELIV_MODE_EXT: + if (irq_masked(eflags)) { + enable_irq_window(cpu_exec_control); + VMX_DBG_LOG(DBG_LEVEL_1, "guesting pending: %x, eflags: %lx", + highest_vector, eflags); + return; + } + + vmx_inject_extint(v, highest_vector, VMX_INVALID_ERROR_CODE); + TRACE_3D(TRC_VMX_INT, v->domain->domain_id, highest_vector, 0); + break; + case VLAPIC_DELIV_MODE_FIXED: + case VLAPIC_DELIV_MODE_LPRI: + case VLAPIC_DELIV_MODE_SMI: + case VLAPIC_DELIV_MODE_NMI: + case VLAPIC_DELIV_MODE_INIT: + case VLAPIC_DELIV_MODE_STARTUP: + default: + printk("Unsupported interrupt type\n"); + BUG(); + break; + } + + interrupt_post_injection(v, highest_vector, intr_type); + return; } void vmx_do_resume(struct vcpu *d) diff -r d4d880fcef28 -r b35215021b32 xen/arch/x86/vmx_platform.c --- a/xen/arch/x86/vmx_platform.c Fri Sep 9 16:31:36 2005 +++ b/xen/arch/x86/vmx_platform.c Tue Sep 13 16:14:16 2005 @@ -55,17 +55,17 @@ static inline long __get_reg_value(unsigned long reg, int size) { switch(size) { - case BYTE_64: - return (char)(reg & 0xFF); - case WORD: - return (short)(reg & 0xFFFF); - case LONG: - return (int)(reg & 0xFFFFFFFF); - case QUAD: - return (long)(reg); - default: - printf("Error: (__get_reg_value) Invalid reg size\n"); - domain_crash_synchronous(); + case BYTE_64: + return (char)(reg & 0xFF); + case WORD: + return (short)(reg & 0xFFFF); + case LONG: + return (int)(reg & 0xFFFFFFFF); + case QUAD: + return (long)(reg); + default: + printf("Error: (__get_reg_value) Invalid reg size\n"); + domain_crash_synchronous(); } } @@ -73,48 +73,49 @@ { if (size == BYTE) { switch (index) { - case 0: /* %al */ - return (char)(regs->rax & 0xFF); - case 1: /* %cl */ - return (char)(regs->rcx & 0xFF); - case 2: /* %dl */ - return (char)(regs->rdx & 0xFF); - case 3: /* %bl */ - return (char)(regs->rbx & 0xFF); - case 4: /* %ah */ - return (char)((regs->rax & 0xFF00) >> 8); - case 5: /* %ch */ - return (char)((regs->rcx & 0xFF00) >> 8); - case 6: /* %dh */ - return (char)((regs->rdx & 0xFF00) >> 8); - case 7: /* %bh */ - return (char)((regs->rbx & 0xFF00) >> 8); - default: - printf("Error: (get_reg_value) Invalid index value\n"); - domain_crash_synchronous(); + case 0: /* %al */ + return (char)(regs->rax & 0xFF); + case 1: /* %cl */ + return (char)(regs->rcx & 0xFF); + case 2: /* %dl */ + return (char)(regs->rdx & 0xFF); + case 3: /* %bl */ + return (char)(regs->rbx & 0xFF); + case 4: /* %ah */ + return (char)((regs->rax & 0xFF00) >> 8); + case 5: /* %ch */ + return (char)((regs->rcx & 0xFF00) >> 8); + case 6: /* %dh */ + return (char)((regs->rdx & 0xFF00) >> 8); + case 7: /* %bh */ + return (char)((regs->rbx & 0xFF00) >> 8); + default: + printf("Error: (get_reg_value) Invalid index value\n"); + domain_crash_synchronous(); } + /* NOTREACHED */ } switch (index) { - case 0: return __get_reg_value(regs->rax, size); - case 1: return __get_reg_value(regs->rcx, size); - case 2: return __get_reg_value(regs->rdx, size); - case 3: return __get_reg_value(regs->rbx, size); - case 4: return __get_reg_value(regs->rsp, size); - case 5: return __get_reg_value(regs->rbp, size); - case 6: return __get_reg_value(regs->rsi, size); - case 7: return __get_reg_value(regs->rdi, size); - case 8: return __get_reg_value(regs->r8, size); - case 9: return __get_reg_value(regs->r9, size); - case 10: return __get_reg_value(regs->r10, size); - case 11: return __get_reg_value(regs->r11, size); - case 12: return __get_reg_value(regs->r12, size); - case 13: return __get_reg_value(regs->r13, size); - case 14: return __get_reg_value(regs->r14, size); - case 15: return __get_reg_value(regs->r15, size); - default: - printf("Error: (get_reg_value) Invalid index value\n"); - domain_crash_synchronous(); + case 0: return __get_reg_value(regs->rax, size); + case 1: return __get_reg_value(regs->rcx, size); + case 2: return __get_reg_value(regs->rdx, size); + case 3: return __get_reg_value(regs->rbx, size); + case 4: return __get_reg_value(regs->rsp, size); + case 5: return __get_reg_value(regs->rbp, size); + case 6: return __get_reg_value(regs->rsi, size); + case 7: return __get_reg_value(regs->rdi, size); + case 8: return __get_reg_value(regs->r8, size); + case 9: return __get_reg_value(regs->r9, size); + case 10: return __get_reg_value(regs->r10, size); + case 11: return __get_reg_value(regs->r11, size); + case 12: return __get_reg_value(regs->r12, size); + case 13: return __get_reg_value(regs->r13, size); + case 14: return __get_reg_value(regs->r14, size); + case 15: return __get_reg_value(regs->r15, size); + default: + printf("Error: (get_reg_value) Invalid index value\n"); + domain_crash_synchronous(); } } #elif defined (__i386__) @@ -133,12 +134,12 @@ { switch(size) { case WORD: - return (short)(reg & 0xFFFF); + return (short)(reg & 0xFFFF); case LONG: - return (int)(reg & 0xFFFFFFFF); + return (int)(reg & 0xFFFFFFFF); default: - printf("Error: (__get_reg_value) Invalid reg size\n"); - domain_crash_synchronous(); + printf("Error: (__get_reg_value) Invalid reg size\n"); + domain_crash_synchronous(); } } @@ -146,29 +147,29 @@ { if (size == BYTE) { switch (index) { - case 0: /* %al */ + case 0: /* %al */ return (char)(regs->eax & 0xFF); - case 1: /* %cl */ + case 1: /* %cl */ return (char)(regs->ecx & 0xFF); - case 2: /* %dl */ + case 2: /* %dl */ return (char)(regs->edx & 0xFF); - case 3: /* %bl */ + case 3: /* %bl */ return (char)(regs->ebx & 0xFF); - case 4: /* %ah */ + case 4: /* %ah */ return (char)((regs->eax & 0xFF00) >> 8); - case 5: /* %ch */ + case 5: /* %ch */ return (char)((regs->ecx & 0xFF00) >> 8); - case 6: /* %dh */ + case 6: /* %dh */ return (char)((regs->edx & 0xFF00) >> 8); - case 7: /* %bh */ + case 7: /* %bh */ return (char)((regs->ebx & 0xFF00) >> 8); default: - printf("Error: (get_reg_value) Invalid index value\n"); + printf("Error: (get_reg_value) Invalid index value\n"); domain_crash_synchronous(); } - } - - switch (index) { + } + + switch (index) { case 0: return __get_reg_value(regs->eax, size); case 1: return __get_reg_value(regs->ecx, size); case 2: return __get_reg_value(regs->edx, size); @@ -178,46 +179,46 @@ case 6: return __get_reg_value(regs->esi, size); case 7: return __get_reg_value(regs->edi, size); default: - printf("Error: (get_reg_value) Invalid index value\n"); + printf("Error: (get_reg_value) Invalid index value\n"); domain_crash_synchronous(); } } #endif static inline unsigned char *check_prefix(unsigned char *inst, - struct instruction *thread_inst, unsigned char *rex_p) + struct instruction *thread_inst, unsigned char *rex_p) { while (1) { switch (*inst) { - /* rex prefix for em64t instructions */ - case 0x40 ... 0x4e: - *rex_p = *inst; - break; + /* rex prefix for em64t instructions */ + case 0x40 ... 0x4e: + *rex_p = *inst; + break; case 0xf3: /* REPZ */ - thread_inst->flags = REPZ; - break; + thread_inst->flags = REPZ; + break; case 0xf2: /* REPNZ */ - thread_inst->flags = REPNZ; - break; + thread_inst->flags = REPNZ; + break; case 0xf0: /* LOCK */ - break; + break; case 0x2e: /* CS */ case 0x36: /* SS */ case 0x3e: /* DS */ case 0x26: /* ES */ case 0x64: /* FS */ case 0x65: /* GS */ - thread_inst->seg_sel = *inst; - break; + thread_inst->seg_sel = *inst; + break; case 0x66: /* 32bit->16bit */ - thread_inst->op_size = WORD; - break; - case 0x67: - printf("Error: Not handling 0x67 (yet)\n"); - domain_crash_synchronous(); - break; - default: - return inst; + thread_inst->op_size = WORD; + break; + case 0x67: + printf("Error: Not handling 0x67 (yet)\n"); + domain_crash_synchronous(); + break; + default: + return inst; } inst++; } @@ -239,23 +240,23 @@ } switch(mod) { - case 0: - if (rm == 5 || rm == 4) { - if (op16) - inst = inst + 2; //disp16, skip 2 bytes - else - inst = inst + 4; //disp32, skip 4 bytes - } - break; - case 1: - inst++; //disp8, skip 1 byte - break; - case 2: + case 0: + if (rm == 5 || rm == 4) { if (op16) inst = inst + 2; //disp16, skip 2 bytes else inst = inst + 4; //disp32, skip 4 bytes - break; + } + break; + case 1: + inst++; //disp8, skip 1 byte + break; + case 2: + if (op16) + inst = inst + 2; //disp16, skip 2 bytes + else + inst = inst + 4; //disp32, skip 4 bytes + break; } if (op_size == QUAD) @@ -303,19 +304,19 @@ } #define GET_OP_SIZE_FOR_BYTE(op_size) \ - do { \ - if (rex) \ - op_size = BYTE_64; \ - else \ - op_size = BYTE; \ + do { \ + if (rex) \ + op_size = BYTE_64; \ + else \ + op_size = BYTE; \ } while(0) #define GET_OP_SIZE_FOR_NONEBYTE(op_size) \ - do { \ - if (rex & 0x8) \ - op_size = QUAD; \ - else if (op_size != WORD) \ - op_size = LONG; \ + do { \ + if (rex & 0x8) \ + op_size = QUAD; \ + else if (op_size != WORD) \ + op_size = LONG; \ } while(0) @@ -343,7 +344,7 @@ * Decode mem,reg operands (as in <opcode> r32/16, m32/16) */ static int mem_reg(unsigned char size, unsigned char *opcode, - struct instruction *instr, unsigned char rex) + struct instruction *instr, unsigned char rex) { int index = get_index(opcode + 1, rex); @@ -356,7 +357,7 @@ * Decode reg,mem operands (as in <opcode> m32/16, r32/16) */ static int reg_mem(unsigned char size, unsigned char *opcode, - struct instruction *instr, unsigned char rex) + struct instruction *instr, unsigned char rex) { int index = get_index(opcode + 1, rex); @@ -381,205 +382,210 @@ vm86 = 1; if (vm86) { /* meaning is reversed */ - if (instr->op_size == WORD) - instr->op_size = LONG; - else if (instr->op_size == LONG) - instr->op_size = WORD; - else if (instr->op_size == 0) - instr->op_size = WORD; + if (instr->op_size == WORD) + instr->op_size = LONG; + else if (instr->op_size == LONG) + instr->op_size = WORD; + else if (instr->op_size == 0) + instr->op_size = WORD; } switch (*opcode) { case 0x0B: /* or m32/16, r32/16 */ - instr->instr = INSTR_OR; - GET_OP_SIZE_FOR_NONEBYTE(instr->op_size); - return mem_reg(instr->op_size, opcode, instr, rex); + instr->instr = INSTR_OR; + GET_OP_SIZE_FOR_NONEBYTE(instr->op_size); + return mem_reg(instr->op_size, opcode, instr, rex); case 0x20: /* and r8, m8 */ - instr->instr = INSTR_AND; - GET_OP_SIZE_FOR_BYTE(instr->op_size); - return reg_mem(instr->op_size, opcode, instr, rex); + instr->instr = INSTR_AND; + GET_OP_SIZE_FOR_BYTE(instr->op_size); + return reg_mem(instr->op_size, opcode, instr, rex); case 0x21: /* and r32/16, m32/16 */ - instr->instr = INSTR_AND; - GET_OP_SIZE_FOR_NONEBYTE(instr->op_size); - return reg_mem(instr->op_size, opcode, instr, rex); + instr->instr = INSTR_AND; + GET_OP_SIZE_FOR_NONEBYTE(instr->op_size); + return reg_mem(instr->op_size, opcode, instr, rex); case 0x23: /* and m32/16, r32/16 */ - instr->instr = INSTR_AND; - GET_OP_SIZE_FOR_NONEBYTE(instr->op_size); - return mem_reg(instr->op_size, opcode, instr, rex); + instr->instr = INSTR_AND; + GET_OP_SIZE_FOR_NONEBYTE(instr->op_size); + return mem_reg(instr->op_size, opcode, instr, rex); case 0x30: /* xor r8, m8 */ - instr->instr = INSTR_XOR; - GET_OP_SIZE_FOR_BYTE(instr->op_size); - return reg_mem(instr->op_size, opcode, instr, rex); + instr->instr = INSTR_XOR; + GET_OP_SIZE_FOR_BYTE(instr->op_size); + return reg_mem(instr->op_size, opcode, instr, rex); case 0x31: /* xor r32/16, m32/16 */ - instr->instr = INSTR_XOR; - GET_OP_SIZE_FOR_NONEBYTE(instr->op_size); - return reg_mem(instr->op_size, opcode, instr, rex); + instr->instr = INSTR_XOR; + GET_OP_SIZE_FOR_NONEBYTE(instr->op_size); + return reg_mem(instr->op_size, opcode, instr, rex); case 0x39: /* cmp r32/16, m32/16 */ - instr->instr = INSTR_CMP; - GET_OP_SIZE_FOR_NONEBYTE(instr->op_size); - return reg_mem(instr->op_size, opcode, instr, rex); - + instr->instr = INSTR_CMP; + GET_OP_SIZE_FOR_NONEBYTE(instr->op_size); + return reg_mem(instr->op_size, opcode, instr, rex); + + case 0x80: case 0x81: - if (((opcode[1] >> 3) & 7) == 7) { /* cmp $imm, m32/16 */ - instr->instr = INSTR_CMP; - GET_OP_SIZE_FOR_NONEBYTE(instr->op_size); - - instr->operand[0] = mk_operand(instr->op_size, 0, 0, IMMEDIATE); - instr->immediate = get_immediate(vm86, opcode+1, BYTE); - instr->operand[1] = mk_operand(instr->op_size, 0, 0, MEMORY); + if (((opcode[1] >> 3) & 7) == 7) { /* cmp $imm, m32/16 */ + instr->instr = INSTR_CMP; + + if (opcode[0] == 0x80) + GET_OP_SIZE_FOR_BYTE(instr->op_size); + else + GET_OP_SIZE_FOR_NONEBYTE(instr->op_size); + + instr->operand[0] = mk_operand(instr->op_size, 0, 0, IMMEDIATE); + instr->immediate = get_immediate(vm86, opcode+1, BYTE); + instr->operand[1] = mk_operand(instr->op_size, 0, 0, MEMORY); return DECODE_success; - } else - return DECODE_failure; + } else + return DECODE_failure; case 0x84: /* test m8, r8 */ - instr->instr = INSTR_TEST; - instr->op_size = BYTE; - GET_OP_SIZE_FOR_BYTE(tmp_size); - return mem_reg(tmp_size, opcode, instr, rex); + instr->instr = INSTR_TEST; + instr->op_size = BYTE; + GET_OP_SIZE_FOR_BYTE(tmp_size); + return mem_reg(tmp_size, opcode, instr, rex); case 0x88: /* mov r8, m8 */ - instr->instr = INSTR_MOV; - instr->op_size = BYTE; + instr->instr = INSTR_MOV; + instr->op_size = BYTE; GET_OP_SIZE_FOR_BYTE(tmp_size); - return reg_mem(tmp_size, opcode, instr, rex); + return reg_mem(tmp_size, opcode, instr, rex); case 0x89: /* mov r32/16, m32/16 */ - instr->instr = INSTR_MOV; - GET_OP_SIZE_FOR_NONEBYTE(instr->op_size); - return reg_mem(instr->op_size, opcode, instr, rex); + instr->instr = INSTR_MOV; + GET_OP_SIZE_FOR_NONEBYTE(instr->op_size); + return reg_mem(instr->op_size, opcode, instr, rex); case 0x8A: /* mov m8, r8 */ - instr->instr = INSTR_MOV; - instr->op_size = BYTE; + instr->instr = INSTR_MOV; + instr->op_size = BYTE; GET_OP_SIZE_FOR_BYTE(tmp_size); - return mem_reg(tmp_size, opcode, instr, rex); + return mem_reg(tmp_size, opcode, instr, rex); case 0x8B: /* mov m32/16, r32/16 */ - instr->instr = INSTR_MOV; - GET_OP_SIZE_FOR_NONEBYTE(instr->op_size); - return mem_reg(instr->op_size, opcode, instr, rex); + instr->instr = INSTR_MOV; + GET_OP_SIZE_FOR_NONEBYTE(instr->op_size); + return mem_reg(instr->op_size, opcode, instr, rex); case 0xA0: /* mov <addr>, al */ - instr->instr = INSTR_MOV; - instr->op_size = BYTE; + instr->instr = INSTR_MOV; + instr->op_size = BYTE; GET_OP_SIZE_FOR_BYTE(tmp_size); - return mem_acc(tmp_size, instr); + return mem_acc(tmp_size, instr); case 0xA1: /* mov <addr>, ax/eax */ - instr->instr = INSTR_MOV; - GET_OP_SIZE_FOR_NONEBYTE(instr->op_size); - return mem_acc(instr->op_size, instr); + instr->instr = INSTR_MOV; + GET_OP_SIZE_FOR_NONEBYTE(instr->op_size); + return mem_acc(instr->op_size, instr); case 0xA2: /* mov al, <addr> */ - instr->instr = INSTR_MOV; - instr->op_size = BYTE; + instr->instr = INSTR_MOV; + instr->op_size = BYTE; GET_OP_SIZE_FOR_BYTE(tmp_size); - return acc_mem(tmp_size, instr); + return acc_mem(tmp_size, instr); case 0xA3: /* mov ax/eax, <addr> */ - instr->instr = INSTR_MOV; - GET_OP_SIZE_FOR_NONEBYTE(instr->op_size); - return acc_mem(instr->op_size, instr); + instr->instr = INSTR_MOV; + GET_OP_SIZE_FOR_NONEBYTE(instr->op_size); + return acc_mem(instr->op_size, instr); case 0xA4: /* movsb */ - instr->instr = INSTR_MOVS; - instr->op_size = BYTE; + instr->instr = INSTR_MOVS; + instr->op_size = BYTE; return DECODE_success; case 0xA5: /* movsw/movsl */ - instr->instr = INSTR_MOVS; - GET_OP_SIZE_FOR_NONEBYTE(instr->op_size); - return DECODE_success; + instr->instr = INSTR_MOVS; + GET_OP_SIZE_FOR_NONEBYTE(instr->op_size); + return DECODE_success; case 0xAA: /* stosb */ - instr->instr = INSTR_STOS; - instr->op_size = BYTE; + instr->instr = INSTR_STOS; + instr->op_size = BYTE; return DECODE_success; case 0xAB: /* stosw/stosl */ - instr->instr = INSTR_STOS; - GET_OP_SIZE_FOR_NONEBYTE(instr->op_size); - return DECODE_success; + instr->instr = INSTR_STOS; + GET_OP_SIZE_FOR_NONEBYTE(instr->op_size); + return DECODE_success; case 0xC6: - if (((opcode[1] >> 3) & 7) == 0) { /* mov $imm8, m8 */ - instr->instr = INSTR_MOV; - instr->op_size = BYTE; - - instr->operand[0] = mk_operand(instr->op_size, 0, 0, IMMEDIATE); - instr->immediate = get_immediate(vm86, opcode+1, instr->op_size); - instr->operand[1] = mk_operand(instr->op_size, 0, 0, MEMORY); + if (((opcode[1] >> 3) & 7) == 0) { /* mov $imm8, m8 */ + instr->instr = INSTR_MOV; + instr->op_size = BYTE; + + instr->operand[0] = mk_operand(instr->op_size, 0, 0, IMMEDIATE); + instr->immediate = get_immediate(vm86, opcode+1, instr->op_size); + instr->operand[1] = mk_operand(instr->op_size, 0, 0, MEMORY); return DECODE_success; - } else - return DECODE_failure; + } else + return DECODE_failure; case 0xC7: - if (((opcode[1] >> 3) & 7) == 0) { /* mov $imm16/32, m16/32 */ - instr->instr = INSTR_MOV; - GET_OP_SIZE_FOR_NONEBYTE(instr->op_size); - - instr->operand[0] = mk_operand(instr->op_size, 0, 0, IMMEDIATE); - instr->immediate = get_immediate(vm86, opcode+1, instr->op_size); - instr->operand[1] = mk_operand(instr->op_size, 0, 0, MEMORY); + if (((opcode[1] >> 3) & 7) == 0) { /* mov $imm16/32, m16/32 */ + instr->instr = INSTR_MOV; + GET_OP_SIZE_FOR_NONEBYTE(instr->op_size); + + instr->operand[0] = mk_operand(instr->op_size, 0, 0, IMMEDIATE); + instr->immediate = get_immediate(vm86, opcode+1, instr->op_size); + instr->operand[1] = mk_operand(instr->op_size, 0, 0, MEMORY); return DECODE_success; - } else - return DECODE_failure; + } else + return DECODE_failure; case 0xF6: - if (((opcode[1] >> 3) & 7) == 0) { /* testb $imm8, m8 */ - instr->instr = INSTR_TEST; - instr->op_size = BYTE; - - instr->operand[0] = mk_operand(instr->op_size, 0, 0, IMMEDIATE); - instr->immediate = get_immediate(vm86, opcode+1, instr->op_size); - instr->operand[1] = mk_operand(instr->op_size, 0, 0, MEMORY); - - return DECODE_success; - } else - return DECODE_failure; + if (((opcode[1] >> 3) & 7) == 0) { /* testb $imm8, m8 */ + instr->instr = INSTR_TEST; + instr->op_size = BYTE; + + instr->operand[0] = mk_operand(instr->op_size, 0, 0, IMMEDIATE); + instr->immediate = get_immediate(vm86, opcode+1, instr->op_size); + instr->operand[1] = mk_operand(instr->op_size, 0, 0, MEMORY); + + return DECODE_success; + } else + return DECODE_failure; case 0x0F: - break; + break; default: - printf("%x, This opcode isn't handled yet!\n", *opcode); + printf("%x, This opcode isn't handled yet!\n", *opcode); return DECODE_failure; } switch (*++opcode) { case 0xB6: /* movz m8, r16/r32 */ - instr->instr = INSTR_MOVZ; - GET_OP_SIZE_FOR_NONEBYTE(instr->op_size); - index = get_index(opcode + 1, rex); - instr->operand[0] = mk_operand(BYTE, 0, 0, MEMORY); - instr->operand[1] = mk_operand(instr->op_size, index, 0, REGISTER); - return DECODE_success; + instr->instr = INSTR_MOVZ; + GET_OP_SIZE_FOR_NONEBYTE(instr->op_size); + index = get_index(opcode + 1, rex); + instr->operand[0] = mk_operand(BYTE, 0, 0, MEMORY); + instr->operand[1] = mk_operand(instr->op_size, index, 0, REGISTER); + return DECODE_success; case 0xB7: /* movz m16, r32 */ - instr->instr = INSTR_MOVZ; - index = get_index(opcode + 1, rex); - if (rex & 0x8) { - instr->op_size = LONG; - instr->operand[1] = mk_operand(QUAD, index, 0, REGISTER); - } else { - instr->op_size = WORD; - instr->operand[1] = mk_operand(LONG, index, 0, REGISTER); - } - instr->operand[0] = mk_operand(instr->op_size, 0, 0, MEMORY); - return DECODE_success; + instr->instr = INSTR_MOVZ; + index = get_index(opcode + 1, rex); + if (rex & 0x8) { + instr->op_size = LONG; + instr->operand[1] = mk_operand(QUAD, index, 0, REGISTER); + } else { + instr->op_size = WORD; + instr->operand[1] = mk_operand(LONG, index, 0, REGISTER); + } + instr->operand[0] = mk_operand(instr->op_size, 0, 0, MEMORY); + return DECODE_success; default: - printf("0f %x, This opcode isn't handled yet\n", *opcode); - return DECODE_failure; + printf("0f %x, This opcode isn't handled yet\n", *opcode); + return DECODE_failure; } } @@ -593,7 +599,7 @@ } void send_mmio_req(unsigned char type, unsigned long gpa, - unsigned long count, int size, long value, int dir, int pvalid) + unsigned long count, int size, long value, int dir, int pvalid) { struct vcpu *d = current; vcpu_iodata_t *vio; @@ -630,12 +636,12 @@ p->df = regs->eflags & EF_DF ? 1 : 0; if (pvalid) { - if (vmx_paging_enabled(current)) - p->u.pdata = (void *) gva_to_gpa(value); + if (vmx_paging_enabled(current)) + p->u.pdata = (void *) gva_to_gpa(value); else - p->u.pdata = (void *) value; /* guest VA == guest PA */ + p->u.pdata = (void *) value; /* guest VA == guest PA */ } else - p->u.data = value; + p->u.data = value; p->state = STATE_IOREQ_READY; @@ -650,7 +656,7 @@ } static void mmio_operands(int type, unsigned long gpa, struct instruction *inst, - struct mi_per_cpu_info *mpcip, struct cpu_user_regs *regs) + struct mi_per_cpu_info *mpcip, struct cpu_user_regs *regs) { unsigned long value = 0; int index, size; @@ -663,24 +669,24 @@ mpcip->operand[1] = inst->operand[1]; /* destination */ if (inst->operand[0] & REGISTER) { /* dest is memory */ - index = operand_index(inst->operand[0]); - value = get_reg_value(size, index, 0, regs); - send_mmio_req(type, gpa, 1, size, value, IOREQ_WRITE, 0); + index = operand_index(inst->operand[0]); + value = get_reg_value(size, index, 0, regs); + send_mmio_req(type, gpa, 1, size, value, IOREQ_WRITE, 0); } else if (inst->operand[0] & IMMEDIATE) { /* dest is memory */ - value = inst->immediate; - send_mmio_req(type, gpa, 1, size, value, IOREQ_WRITE, 0); + value = inst->immediate; + send_mmio_req(type, gpa, 1, size, value, IOREQ_WRITE, 0); } else if (inst->operand[0] & MEMORY) { /* dest is register */ - /* send the request and wait for the value */ - send_mmio_req(type, gpa, 1, size, 0, IOREQ_READ, 0); + /* send the request and wait for the value */ + send_mmio_req(type, gpa, 1, size, 0, IOREQ_READ, 0); } else { - printf("mmio_operands: invalid operand\n"); - domain_crash_synchronous(); + printf("mmio_operands: invalid operand\n"); + domain_crash_synchronous(); } } #define GET_REPEAT_COUNT() \ (mmio_inst.flags & REPZ ? (vm86 ? regs->ecx & 0xFFFF : regs->ecx) : 1) - + void handle_mmio(unsigned long va, unsigned long gpa) { unsigned long eip, eflags, cs; @@ -715,11 +721,11 @@ init_instruction(&mmio_inst); if (vmx_decode(inst, &mmio_inst) == DECODE_failure) { - printf("mmio opcode: va 0x%lx, gpa 0x%lx, len %ld:", - va, gpa, inst_len); - for (i = 0; i < inst_len; i++) - printf(" %02x", inst[i] & 0xFF); - printf("\n"); + printf("mmio opcode: va 0x%lx, gpa 0x%lx, len %ld:", + va, gpa, inst_len); + for (i = 0; i < inst_len; i++) + printf(" %02x", inst[i] & 0xFF); + printf("\n"); domain_crash_synchronous(); } @@ -728,116 +734,116 @@ switch (mmio_inst.instr) { case INSTR_MOV: - mmio_operands(IOREQ_TYPE_COPY, gpa, &mmio_inst, mpcip, regs); - break; + mmio_operands(IOREQ_TYPE_COPY, gpa, &mmio_inst, mpcip, regs); + break; case INSTR_MOVS: { - unsigned long count = GET_REPEAT_COUNT(); - unsigned long size = mmio_inst.op_size; - int sign = regs->eflags & EF_DF ? -1 : 1; - unsigned long addr = 0; - int dir; - - /* determine non-MMIO address */ - if (vm86) { - unsigned long seg; - - __vmread(GUEST_ES_SELECTOR, &seg); - if (((seg << 4) + (regs->edi & 0xFFFF)) == va) { - dir = IOREQ_WRITE; - __vmread(GUEST_DS_SELECTOR, &seg); - addr = (seg << 4) + (regs->esi & 0xFFFF); - } else { - dir = IOREQ_READ; - addr = (seg << 4) + (regs->edi & 0xFFFF); - } - } else { - if (va == regs->edi) { - dir = IOREQ_WRITE; - addr = regs->esi; - } else { - dir = IOREQ_READ; - addr = regs->edi; - } - } - - mpcip->flags = mmio_inst.flags; - mpcip->instr = mmio_inst.instr; - - /* - * In case of a movs spanning multiple pages, we break the accesses - * up into multiple pages (the device model works with non-continguous - * physical guest pages). To copy just one page, we adjust %ecx and - * do not advance %eip so that the next "rep movs" copies the next page. - * Unaligned accesses, for example movsl starting at PGSZ-2, are - * turned into a single copy where we handle the overlapping memory - * copy ourself. After this copy succeeds, "rep movs" is executed - * again. - */ - if ((addr & PAGE_MASK) != ((addr + size - 1) & PAGE_MASK)) { - unsigned long value = 0; - - mpcip->flags |= OVERLAP; - - regs->eip -= inst_len; /* do not advance %eip */ - - if (dir == IOREQ_WRITE) - vmx_copy(&value, addr, size, VMX_COPY_IN); - send_mmio_req(IOREQ_TYPE_COPY, gpa, 1, size, value, dir, 0); - } else { - if ((addr & PAGE_MASK) != ((addr + count * size - 1) & PAGE_MASK)) { - regs->eip -= inst_len; /* do not advance %eip */ - - if (sign > 0) - count = (PAGE_SIZE - (addr & ~PAGE_MASK)) / size; - else - count = (addr & ~PAGE_MASK) / size; - } - - send_mmio_req(IOREQ_TYPE_COPY, gpa, count, size, addr, dir, 1); - } + unsigned long count = GET_REPEAT_COUNT(); + unsigned long size = mmio_inst.op_size; + int sign = regs->eflags & EF_DF ? -1 : 1; + unsigned long addr = 0; + int dir; + + /* determine non-MMIO address */ + if (vm86) { + unsigned long seg; + + __vmread(GUEST_ES_SELECTOR, &seg); + if (((seg << 4) + (regs->edi & 0xFFFF)) == va) { + dir = IOREQ_WRITE; + __vmread(GUEST_DS_SELECTOR, &seg); + addr = (seg << 4) + (regs->esi & 0xFFFF); + } else { + dir = IOREQ_READ; + addr = (seg << 4) + (regs->edi & 0xFFFF); + } + } else { + if (va == regs->edi) { + dir = IOREQ_WRITE; + addr = regs->esi; + } else { + dir = IOREQ_READ; + addr = regs->edi; + } + } + + mpcip->flags = mmio_inst.flags; + mpcip->instr = mmio_inst.instr; + + /* + * In case of a movs spanning multiple pages, we break the accesses + * up into multiple pages (the device model works with non-continguous + * physical guest pages). To copy just one page, we adjust %ecx and + * do not advance %eip so that the next "rep movs" copies the next page. + * Unaligned accesses, for example movsl starting at PGSZ-2, are + * turned into a single copy where we handle the overlapping memory + * copy ourself. After this copy succeeds, "rep movs" is executed + * again. + */ + if ((addr & PAGE_MASK) != ((addr + size - 1) & PAGE_MASK)) { + unsigned long value = 0; + + mpcip->flags |= OVERLAP; + + regs->eip -= inst_len; /* do not advance %eip */ + + if (dir == IOREQ_WRITE) + vmx_copy(&value, addr, size, VMX_COPY_IN); + send_mmio_req(IOREQ_TYPE_COPY, gpa, 1, size, value, dir, 0); + } else { + if ((addr & PAGE_MASK) != ((addr + count * size - 1) & PAGE_MASK)) { + regs->eip -= inst_len; /* do not advance %eip */ + + if (sign > 0) + count = (PAGE_SIZE - (addr & ~PAGE_MASK)) / size; + else + count = (addr & ~PAGE_MASK) / size; + } + + send_mmio_req(IOREQ_TYPE_COPY, gpa, count, size, addr, dir, 1); + } break; } case INSTR_MOVZ: - mmio_operands(IOREQ_TYPE_COPY, gpa, &mmio_inst, mpcip, regs); - break; + mmio_operands(IOREQ_TYPE_COPY, gpa, &mmio_inst, mpcip, regs); + break; case INSTR_STOS: - /* - * Since the destination is always in (contiguous) mmio space we don't - * need to break it up into pages. - */ - mpcip->flags = mmio_inst.flags; - mpcip->instr = mmio_inst.instr; + /* + * Since the destination is always in (contiguous) mmio space we don't + * need to break it up into pages. + */ + mpcip->flags = mmio_inst.flags; + mpcip->instr = mmio_inst.instr; send_mmio_req(IOREQ_TYPE_COPY, gpa, - GET_REPEAT_COUNT(), mmio_inst.op_size, regs->eax, IOREQ_WRITE, 0); - break; + GET_REPEAT_COUNT(), mmio_inst.op_size, regs->eax, IOREQ_WRITE, 0); + break; case INSTR_OR: - mmio_operands(IOREQ_TYPE_OR, gpa, &mmio_inst, mpcip, regs); - break; + mmio_operands(IOREQ_TYPE_OR, gpa, &mmio_inst, mpcip, regs); + break; case INSTR_AND: - mmio_operands(IOREQ_TYPE_AND, gpa, &mmio_inst, mpcip, regs); - break; + mmio_operands(IOREQ_TYPE_AND, gpa, &mmio_inst, mpcip, regs); + break; case INSTR_XOR: - mmio_operands(IOREQ_TYPE_XOR, gpa, &mmio_inst, mpcip, regs); - break; + mmio_operands(IOREQ_TYPE_XOR, gpa, &mmio_inst, mpcip, regs); + break; case INSTR_CMP: - mmio_operands(IOREQ_TYPE_COPY, gpa, &mmio_inst, mpcip, regs); - break; + mmio_operands(IOREQ_TYPE_COPY, gpa, &mmio_inst, mpcip, regs); + break; case INSTR_TEST: - mmio_operands(IOREQ_TYPE_COPY, gpa, &mmio_inst, mpcip, regs); - break; + mmio_operands(IOREQ_TYPE_COPY, gpa, &mmio_inst, mpcip, regs); + break; default: - printf("Unhandled MMIO instruction\n"); - domain_crash_synchronous(); + printf("Unhandled MMIO instruction\n"); + domain_crash_synchronous(); } } diff -r d4d880fcef28 -r b35215021b32 xen/arch/x86/vmx_vmcs.c --- a/xen/arch/x86/vmx_vmcs.c Fri Sep 9 16:31:36 2005 +++ b/xen/arch/x86/vmx_vmcs.c Tue Sep 13 16:14:16 2005 @@ -179,10 +179,10 @@ p = map_domain_page(mpfn); d->domain->arch.vmx_platform.shared_page_va = (unsigned long)p; - VMX_DBG_LOG(DBG_LEVEL_1, "eport: %x\n", iopacket_port(d->domain)); - - clear_bit(iopacket_port(d->domain), - &d->domain->shared_info->evtchn_mask[0]); + VMX_DBG_LOG(DBG_LEVEL_1, "eport: %x\n", iopacket_port(d->domain)); + + clear_bit(iopacket_port(d->domain), + &d->domain->shared_info->evtchn_mask[0]); return 0; } @@ -497,7 +497,7 @@ __vmptrst(old_phys_ptr); if ((error = load_vmcs(arch_vmx, vmcs_phys_ptr))) { printk("modify_vmcs: load_vmcs failed: VMCS = %lx\n", - (unsigned long) vmcs_phys_ptr); + (unsigned long) vmcs_phys_ptr); return -EINVAL; } load_cpu_user_regs(regs); diff -r d4d880fcef28 -r b35215021b32 xen/arch/x86/x86_32/entry.S --- a/xen/arch/x86/x86_32/entry.S Fri Sep 9 16:31:36 2005 +++ b/xen/arch/x86/x86_32/entry.S Tue Sep 13 16:14:16 2005 @@ -834,7 +834,7 @@ .byte 4 /* do_update_va_mapping */ .byte 2 /* do_set_timer_op */ /* 15 */ .byte 1 /* do_event_channel_op */ - .byte 1 /* do_xen_version */ + .byte 2 /* do_xen_version */ .byte 3 /* do_console_io */ .byte 1 /* do_physdev_op */ .byte 3 /* do_grant_table_op */ /* 20 */ diff -r d4d880fcef28 -r b35215021b32 xen/arch/x86/x86_64/entry.S --- a/xen/arch/x86/x86_64/entry.S Fri Sep 9 16:31:36 2005 +++ b/xen/arch/x86/x86_64/entry.S Tue Sep 13 16:14:16 2005 @@ -655,7 +655,7 @@ .byte 3 /* do_update_va_mapping */ .byte 1 /* do_set_timer_op */ /* 15 */ .byte 1 /* do_event_channel_op */ - .byte 1 /* do_xen_version */ + .byte 2 /* do_xen_version */ .byte 3 /* do_console_io */ .byte 1 /* do_physdev_op */ .byte 3 /* do_grant_table_op */ /* 20 */ diff -r d4d880fcef28 -r b35215021b32 xen/arch/x86/x86_64/traps.c --- a/xen/arch/x86/x86_64/traps.c Fri Sep 9 16:31:36 2005 +++ b/xen/arch/x86/x86_64/traps.c Tue Sep 13 16:14:16 2005 @@ -12,25 +12,51 @@ #include <asm/current.h> #include <asm/flushtlb.h> #include <asm/msr.h> +#include <asm/vmx.h> void show_registers(struct cpu_user_regs *regs) { - printk("CPU: %d\nRIP: %04x:[<%016lx>]", - smp_processor_id(), 0xffff & regs->cs, regs->rip); + unsigned long rip, rsp, rflags, cs, cr0, cr3; + const char *context; + + if ( VMX_DOMAIN(current) && (regs->eflags == 0) ) + { + __vmread(GUEST_RIP, &rip); + __vmread(GUEST_RSP, &rsp); + __vmread(GUEST_RFLAGS, &rflags); + __vmread(GUEST_CS_SELECTOR, &cs); + __vmread(CR0_READ_SHADOW, &cr0); + __vmread(GUEST_CR3, &cr3); + context = "vmx guest"; + } + else + { + rip = regs->rip; + rflags = regs->rflags; + cr0 = read_cr0(); + cr3 = read_cr3(); + rsp = regs->rsp; + cs = regs->cs & 0xffff; + context = GUEST_MODE(regs) ? "guest" : "hypervisor"; + } + + printk("CPU: %d\nRIP: %04lx:[<%016lx>]", + smp_processor_id(), cs, rip); if ( !GUEST_MODE(regs) ) - print_symbol(" %s", regs->rip); - printk("\nRFLAGS: %016lx\n", regs->eflags); + print_symbol(" %s", rip); + printk("\nRFLAGS: %016lx CONTEXT: %s\n", rflags, context); printk("rax: %016lx rbx: %016lx rcx: %016lx\n", regs->rax, regs->rbx, regs->rcx); printk("rdx: %016lx rsi: %016lx rdi: %016lx\n", regs->rdx, regs->rsi, regs->rdi); printk("rbp: %016lx rsp: %016lx r8: %016lx\n", - regs->rbp, regs->rsp, regs->r8); + regs->rbp, rsp, regs->r8); printk("r9: %016lx r10: %016lx r11: %016lx\n", regs->r9, regs->r10, regs->r11); printk("r12: %016lx r13: %016lx r14: %016lx\n", regs->r12, regs->r13, regs->r14); - printk("r15: %016lx\n", regs->r15); + printk("r15: %016lx cr0: %016lx cr3: %016lx\n", + regs->r15, cr0, cr3); show_stack(regs); } @@ -194,3 +220,13 @@ return 0; } + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff -r d4d880fcef28 -r b35215021b32 xen/common/Makefile --- a/xen/common/Makefile Fri Sep 9 16:31:36 2005 +++ b/xen/common/Makefile Tue Sep 13 16:14:16 2005 @@ -19,3 +19,6 @@ clean: rm -f *.o *~ core + +# Object file contains changeset and compiler information. +kernel.o: $(BASEDIR)/include/xen/compile.h diff -r d4d880fcef28 -r b35215021b32 xen/common/kernel.c --- a/xen/common/kernel.c Fri Sep 9 16:31:36 2005 +++ b/xen/common/kernel.c Tue Sep 13 16:14:16 2005 @@ -114,12 +114,12 @@ case XENVER_capabilities: { xen_capabilities_info_t info; - extern void arch_get_xen_caps(xen_capabilities_info_t * info); - - memset(&info, 0, sizeof(info)); - arch_get_xen_caps(&info); + extern void arch_get_xen_caps(xen_capabilities_info_t info); - if ( copy_to_user(arg, &info, sizeof(info)) ) + memset(info, 0, sizeof(info)); + arch_get_xen_caps(info); + + if ( copy_to_user(arg, info, sizeof(info)) ) return -EFAULT; return 0; } @@ -127,7 +127,6 @@ case XENVER_parameters: { xen_parameters_info_t info = { .virt_start = HYPERVISOR_VIRT_START }; - if ( copy_to_user(arg, &info, sizeof(info)) ) return -EFAULT; return 0; diff -r d4d880fcef28 -r b35215021b32 xen/common/memory.c --- a/xen/common/memory.c Fri Sep 9 16:31:36 2005 +++ b/xen/common/memory.c Tue Sep 13 16:14:16 2005 @@ -29,7 +29,7 @@ int *preempted) { struct pfn_info *page; - unsigned long i; + unsigned int i; if ( (extent_list != NULL) && !array_access_ok(extent_list, nr_extents, sizeof(*extent_list)) ) @@ -37,7 +37,7 @@ if ( (extent_order != 0) && !IS_CAPABLE_PHYSDEV(current->domain) ) { - DPRINTK("Only I/O-capable domains may allocate > order-0 memory.\n"); + DPRINTK("Only I/O-capable domains may allocate multi-page extents.\n"); return 0; } @@ -52,8 +52,9 @@ if ( unlikely((page = alloc_domheap_pages( d, extent_order, flags)) == NULL) ) { - DPRINTK("Could not allocate order=%d extent: id=%d flags=%x\n", - extent_order, d->domain_id, flags); + DPRINTK("Could not allocate order=%d extent: " + "id=%d flags=%x (%d of %d)\n", + extent_order, d->domain_id, flags, i, nr_extents); return i; } diff -r d4d880fcef28 -r b35215021b32 xen/drivers/char/Makefile --- a/xen/drivers/char/Makefile Fri Sep 9 16:31:36 2005 +++ b/xen/drivers/char/Makefile Tue Sep 13 16:14:16 2005 @@ -8,4 +8,5 @@ clean: rm -f *.o *~ core +# Object file contains changeset and compiler information. console.o: $(BASEDIR)/include/xen/compile.h diff -r d4d880fcef28 -r b35215021b32 xen/include/asm-x86/mm.h --- a/xen/include/asm-x86/mm.h Fri Sep 9 16:31:36 2005 +++ b/xen/include/asm-x86/mm.h Tue Sep 13 16:14:16 2005 @@ -98,9 +98,10 @@ /* 16-bit count of uses of this frame as its current type. */ #define PGT_count_mask ((1U<<16)-1) -#define PGT_mfn_mask ((1U<<20)-1) /* mfn mask for shadow types */ - -#define PGT_score_shift 20 + /* 23-bit mfn mask for shadow types: good for up to 32GB RAM. */ +#define PGT_mfn_mask ((1U<<23)-1) + +#define PGT_score_shift 23 #define PGT_score_mask (((1U<<4)-1)<<PGT_score_shift) /* Cleared when the owning guest 'frees' this page. */ diff -r d4d880fcef28 -r b35215021b32 xen/include/asm-x86/shadow_64.h --- a/xen/include/asm-x86/shadow_64.h Fri Sep 9 16:31:36 2005 +++ b/xen/include/asm-x86/shadow_64.h Tue Sep 13 16:14:16 2005 @@ -353,7 +353,7 @@ entry_remove_flags(sle, _PAGE_PSE); if ( shadow_mode_log_dirty(d) || - !(entry_get_flags(gle) & _PAGE_DIRTY) ) + !(entry_get_flags(gle) & _PAGE_DIRTY) ) { pgentry_64_t *l1_p; int i; @@ -365,8 +365,9 @@ unmap_domain_page(l1_p); } } else { - sle = entry_from_pfn(smfn, - (entry_get_flags(gle) | _PAGE_RW | _PAGE_ACCESSED) & ~_PAGE_AVAIL); + sle = entry_from_pfn( + smfn, + (entry_get_flags(gle) | _PAGE_RW | _PAGE_ACCESSED) & ~_PAGE_AVAIL); entry_add_flags(gle, _PAGE_ACCESSED); } // XXX mafetter: Hmm... diff -r d4d880fcef28 -r b35215021b32 xen/include/asm-x86/shadow_ops.h --- a/xen/include/asm-x86/shadow_ops.h Fri Sep 9 16:31:36 2005 +++ b/xen/include/asm-x86/shadow_ops.h Tue Sep 13 16:14:16 2005 @@ -127,4 +127,4 @@ #define guest_va_to_l1mfn va_to_l1mfn #endif -#endif /* _XEN_SHADOW_OPS_H */ +#endif /* _XEN_SHADOW_OPS_H */ diff -r d4d880fcef28 -r b35215021b32 xen/include/asm-x86/vmx.h --- a/xen/include/asm-x86/vmx.h Fri Sep 9 16:31:36 2005 +++ b/xen/include/asm-x86/vmx.h Tue Sep 13 16:14:16 2005 @@ -28,6 +28,8 @@ #include <public/io/ioreq.h> +extern int hvm_enabled; + extern void vmx_asm_vmexit_handler(struct cpu_user_regs); extern void vmx_asm_do_resume(void); extern void vmx_asm_do_launch(void); @@ -148,9 +150,9 @@ #define TYPE_MOV_TO_CR (0 << 4) #define TYPE_MOV_FROM_CR (1 << 4) #define TYPE_CLTS (2 << 4) -#define TYPE_LMSW (3 << 4) +#define TYPE_LMSW (3 << 4) #define CONTROL_REG_ACCESS_REG 0xf00 /* 10:8, general purpose register */ -#define LMSW_SOURCE_DATA (0xFFFF << 16) /* 16:31 lmsw source */ +#define LMSW_SOURCE_DATA (0xFFFF << 16) /* 16:31 lmsw source */ #define REG_EAX (0 << 8) #define REG_ECX (1 << 8) #define REG_EDX (2 << 8) diff -r d4d880fcef28 -r b35215021b32 xen/include/asm-x86/vmx_platform.h --- a/xen/include/asm-x86/vmx_platform.h Fri Sep 9 16:31:36 2005 +++ b/xen/include/asm-x86/vmx_platform.h Tue Sep 13 16:14:16 2005 @@ -16,6 +16,7 @@ * Place - Suite 330, Boston, MA 02111-1307 USA. * */ + #ifndef __ASM_X86_VMX_PLATFORM_H__ #define __ASM_X86_VMX_PLATFORM_H__ @@ -52,19 +53,19 @@ #define REPNZ 0x2 #define OVERLAP 0x4 -#define INSTR_PIO 1 -#define INSTR_OR 2 -#define INSTR_AND 3 -#define INSTR_XOR 4 -#define INSTR_CMP 5 -#define INSTR_MOV 6 -#define INSTR_MOVS 7 -#define INSTR_MOVZ 8 -#define INSTR_STOS 9 -#define INSTR_TEST 10 +#define INSTR_PIO 1 +#define INSTR_OR 2 +#define INSTR_AND 3 +#define INSTR_XOR 4 +#define INSTR_CMP 5 +#define INSTR_MOV 6 +#define INSTR_MOVS 7 +#define INSTR_MOVZ 8 +#define INSTR_STOS 9 +#define INSTR_TEST 10 struct instruction { - __s8 instr; /* instruction type */ + __s8 instr; /* instruction type */ __s16 op_size; /* the operand's bit size, e.g. 16-bit or 32-bit */ __u64 immediate; __u16 seg_sel; /* segmentation selector */ @@ -76,18 +77,18 @@ struct mi_per_cpu_info { int flags; - int instr; /* instruction */ - unsigned long operand[2]; /* operands */ - unsigned long immediate; /* immediate portion */ - struct cpu_user_regs *inst_decoder_regs; /* current context */ + int instr; /* instruction */ + unsigned long operand[2]; /* operands */ + unsigned long immediate; /* immediate portion */ + struct cpu_user_regs *inst_decoder_regs; /* current context */ }; struct virtual_platform_def { - unsigned long *real_mode_data; /* E820, etc. */ + unsigned long *real_mode_data; /* E820, etc. */ unsigned long shared_page_va; struct vmx_virpit_t vmx_pit; struct vmx_handler_t vmx_handler; - struct mi_per_cpu_info mpci; /* MMIO */ + struct mi_per_cpu_info mpci; /* MMIO */ }; extern void handle_mmio(unsigned long, unsigned long); diff -r d4d880fcef28 -r b35215021b32 xen/include/asm-x86/vmx_virpit.h --- a/xen/include/asm-x86/vmx_virpit.h Fri Sep 9 16:31:36 2005 +++ b/xen/include/asm-x86/vmx_virpit.h Tue Sep 13 16:14:16 2005 @@ -1,5 +1,6 @@ #ifndef _VMX_VIRPIT_H #define _VMX_VIRPIT_H + #include <xen/config.h> #include <xen/init.h> #include <xen/lib.h> @@ -17,14 +18,14 @@ struct vmx_virpit_t { /* for simulation of counter 0 in mode 2*/ - int vector; /* the pit irq vector */ - unsigned int period; /* the frequency. e.g. 10ms*/ + int vector; /* the pit irq vector */ + unsigned int period; /* the frequency. e.g. 10ms*/ s_time_t scheduled; /* scheduled timer interrupt */ - unsigned int channel; /* the pit channel, counter 0~2 */ + unsigned int channel; /* the pit channel, counter 0~2 */ u64 *intr_bitmap; - unsigned int pending_intr_nr; /* the couner for pending timer interrupts */ - unsigned long long inject_point; /* the time inject virt intr */ - struct ac_timer pit_timer; /* periodic timer for mode 2*/ + unsigned int pending_intr_nr; /* the couner for pending timer interrupts */ + unsigned long long inject_point; /* the time inject virt intr */ + struct ac_timer pit_timer; /* periodic timer for mode 2*/ int first_injected; /* flag to prevent shadow window */ /* virtual PIT state for handle related I/O */ @@ -32,8 +33,8 @@ int count_LSB_latched; int count_MSB_latched; - unsigned int count; /* the 16 bit channel count */ - unsigned int init_val; /* the init value for the counter */ + unsigned int count; /* the 16 bit channel count */ + unsigned int init_val; /* the init value for the counter */ } ; diff -r d4d880fcef28 -r b35215021b32 xen/include/public/version.h --- a/xen/include/public/version.h Fri Sep 9 16:31:36 2005 +++ b/xen/include/public/version.h Tue Sep 13 16:14:16 2005 @@ -29,16 +29,14 @@ } xen_compile_info_t; #define XENVER_capabilities 3 -typedef struct xen_capabilities_info { - char caps[1024]; -} xen_capabilities_info_t; +typedef char xen_capabilities_info_t[1024]; #define XENVER_changeset 4 typedef char xen_changeset_info_t[64]; #define XENVER_parameters 5 -typedef struct xen_paramaters_info { -unsigned long virt_start; +typedef struct xen_parameters_info { + unsigned long virt_start; } xen_parameters_info_t; #endif /* __XEN_PUBLIC_VERSION_H__ */ diff -r d4d880fcef28 -r b35215021b32 docs/Doxyfile --- /dev/null Fri Sep 9 16:31:36 2005 +++ b/docs/Doxyfile Tue Sep 13 16:14:16 2005 @@ -0,0 +1,1218 @@ +# Doxyfile 1.4.2 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = Xen Python Tools + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = api/tools/python + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, +# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese, +# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian, +# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, +# Swedish, and Ukrainian. + +OUTPUT_LANGUAGE = English + +# This tag can be used to specify the encoding used in the generated output. +# The encoding is not always determined by the language that is chosen, +# but also whether or not the output is meant for Windows or non-Windows users. +# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES +# forces the Windows encoding (this is the default for the Windows binary), +# whereas setting the tag to NO uses a Unix-style encoding (the default for +# all platforms other than Windows). + +USE_WINDOWS_ENCODING = NO + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like the Qt-style comments (thus requiring an +# explicit @brief command for a brief description. + +JAVADOC_AUTOBRIEF = YES + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the DETAILS_AT_TOP tag is set to YES then Doxygen +# will output the detailed description near the top, like JavaDoc. +# If set to NO, the detailed description appears after the member +# documentation. + +DETAILS_AT_TOP = YES + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources +# only. Doxygen will then generate output that is more tailored for Java. +# For instance, namespaces will be presented as packages, qualified scopes +# will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = YES + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = YES + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. + +SHOW_DIRECTORIES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from the +# version control system). Doxygen will invoke the program by executing (via +# popen()) the command <command> <input-file>, where <command> is the value of +# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file +# provided by doxygen. Whatever the progam writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = YES + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be abled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = ../tools/python/xen/ + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm + +FILE_PATTERNS = *.py *.c + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. + +EXCLUDE_PATTERNS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command <filter> <input-file>, where <filter> +# is the value of the INPUT_FILTER tag, and <input-file> is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = "sh ./Doxyfilter ../tools/python" + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = YES + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES (the default) +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES (the default) +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be +# generated containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, +# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are +# probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = YES + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_PREDEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option is superseded by the HAVE_DOT option below. This is only a +# fallback. It is recommended to install and use dot, since it yields more +# powerful graphs. + +CLASS_DIAGRAMS = YES + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will +# generate a call dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable call graphs for selected +# functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_WIDTH = 1024 + +# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_HEIGHT = 1024 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that a graph may be further truncated if the graph's +# image dimensions are not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH +# and MAX_DOT_GRAPH_HEIGHT). If 0 is used for the depth value (the default), +# the graph is not depth-constrained. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, which results in a white background. +# Warning: Depending on the platform used, enabling this option may lead to +# badly anti-aliased labels on the edges of a graph (i.e. they become hard to +# read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO diff -r d4d880fcef28 -r b35215021b32 docs/Doxyfilter --- /dev/null Fri Sep 9 16:31:36 2005 +++ b/docs/Doxyfilter Tue Sep 13 16:14:16 2005 @@ -0,0 +1,16 @@ +#!/bin/sh + +# +# Doxyfilter <source-root> <filename> +# + +dir=$(dirname "$0") + +PYFILTER="$dir/pythfilter.py" + +if [ "${2/.py/}" != "$2" ] +then + python "$PYFILTER" -r "$1" -f "$2" +else + cat "$2" +fi diff -r d4d880fcef28 -r b35215021b32 docs/pythfilter.py --- /dev/null Fri Sep 9 16:31:36 2005 +++ b/docs/pythfilter.py Tue Sep 13 16:14:16 2005 @@ -0,0 +1,658 @@ +#!/usr/bin/env python + +# pythfilter.py v1.5.5, written by Matthias Baas (baas@xxxxxxxxxx) + +# Doxygen filter which can be used to document Python source code. +# Classes (incl. methods) and functions can be documented. +# Every comment that begins with ## is literally turned into an +# Doxygen comment. Consecutive comment lines are turned into +# comment blocks (-> /** ... */). +# All the stuff is put inside a namespace with the same name as +# the source file. + +# Conversions: +# ============ +# ##-blocks -> /** ... */ +# "class name(base): ..." -> "class name : public base {...}" +# "def name(params): ..." -> "name(params) {...}" + +# Changelog: +# 21.01.2003: Raw (r"") or unicode (u"") doc string will now be properly +# handled. (thanks to Richard Laager for the patch) +# 22.12.2003: Fixed a bug where no function names would be output for "def" +# blocks that were not in a class. +# (thanks to Richard Laager for the patch) +# 12.12.2003: Implemented code to handle static and class methods with +# this logic: Methods with "self" as the first argument are +# non-static. Methods with "cls" are Python class methods, +# which translate into static methods for Doxygen. Other +# methods are assumed to be static methods. As should be +# obvious, this logic doesn't take into account if the method +# is actually setup as a classmethod() or a staticmethod(), +# just if it follows the normal conventions. +# (thanks to Richard Laager for the patch) +# 11.12.2003: Corrected #includes to use os.path.sep instead of ".". Corrected +# namespace code to use "::" instead of ".". +# (thanks to Richard Laager for the patch) +# 11.12.2003: Methods beginning with two underscores that end with +# something other than two underscores are considered private +# and are handled accordingly. +# (thanks to Richard Laager for the patch) +# 03.12.2003: The first parameter of class methods (self) is removed from +# the documentation. +# 03.11.2003: The module docstring will be used as namespace documentation +# (thanks to Joe Bronkema for the patch) +# 08.07.2003: Namespaces get a default documentation so that the namespace +# and its contents will show up in the generated documentation. +# 05.02.2003: Directories will be delted during synchronization. +# 31.01.2003: -f option & filtering entire directory trees. +# 10.08.2002: In base classes the '.' will be replaced by '::' +# 18.07.2002: * and ** will be translated into arguments +# 18.07.2002: Argument lists may contain default values using constructors. +# 18.06.2002: Support for ## public: +# 21.01.2002: from ... import will be translated to "using namespace ...;" +# TODO: "from ... import *" vs "from ... import names" +# TODO: Using normal imports: name.name -> name::name +# 20.01.2002: #includes will be placed in front of the namespace + +###################################################################### + +# The program is written as a state machine with the following states: +# +# - OUTSIDE The current position is outside any comment, +# class definition or function. +# +# - BUILD_COMMENT Begins with first "##". +# Ends with the first token that is no "##" +# at the same column as before. +# +# - BUILD_CLASS_DECL Begins with "class". +# Ends with ":" +# - BUILD_CLASS_BODY Begins just after BUILD_CLASS_DECL. +# The first following token (which is no comment) +# determines indentation depth. +# Ends with a token that has a smaller indendation. +# +# - BUILD_DEF_DECL Begins with "def". +# Ends with ":". +# - BUILD_DEF_BODY Begins just after BUILD_DEF_DECL. +# The first following token (which is no comment) +# determines indentation depth. +# Ends with a token that has a smaller indendation. + +import getopt +import glob +import os.path +import re +import shutil +import string +import sys +import token +import tokenize + +from stat import * + +OUTSIDE = 0 +BUILD_COMMENT = 1 +BUILD_CLASS_DECL = 2 +BUILD_CLASS_BODY = 3 +BUILD_DEF_DECL = 4 +BUILD_DEF_BODY = 5 +IMPORT = 6 +IMPORT_OP = 7 +IMPORT_APPEND = 8 + +# Output file stream +outfile = sys.stdout + +# Output buffer +outbuffer = [] + +out_row = 1 +out_col = 0 + +# Variables used by rec_name_n_param() +name = "" +param = "" +doc_string = "" +record_state = 0 +bracket_counter = 0 + +# Tuple: (row,column) +class_spos = (0,0) +def_spos = (0,0) +import_spos = (0,0) + +# Which import was used? ("import" or "from") +import_token = "" + +# Comment block buffer +comment_block = [] +comment_finished = 0 + +# Imported modules +modules = [] + +# Program state +stateStack = [OUTSIDE] + +# Keep track of whether module has a docstring +module_has_docstring = False + +# Keep track of member protection +protection_level = "public" +private_member = False + +# Keep track of the module namespace +namespace = "" + +###################################################################### +# Output string s. '\n' may only be at the end of the string (not +# somewhere in the middle). +# +# In: s - String +# spos - Startpos +###################################################################### +def output(s,spos, immediate=0): + global outbuffer, out_row, out_col, outfile + + os = string.rjust(s,spos[1]-out_col+len(s)) + + if immediate: + outfile.write(os) + else: + outbuffer.append(os) + + assert -1 == string.find(s[0:-2], "\n"), s + + if (s[-1:]=="\n"): + out_row = out_row+1 + out_col = 0 + else: + out_col = spos[1]+len(s) + + +###################################################################### +# Records a name and parameters. The name is either a class name or +# a function name. Then the parameter is either the base class or +# the function parameters. +# The name is stored in the global variable "name", the parameters +# in "param". +# The variable "record_state" holds the current state of this internal +# state machine. +# The recording is started by calling start_recording(). +# +# In: type, tok +###################################################################### +def rec_name_n_param(type, tok): + global record_state,name,param,doc_string,bracket_counter + s = record_state + # State 0: Do nothing. + if (s==0): + return + # State 1: Remember name. + elif (s==1): + name = tok + record_state = 2 + # State 2: Wait for opening bracket or colon + elif (s==2): + if (tok=='('): + bracket_counter = 1 + record_state=3 + if (tok==':'): record_state=4 + # State 3: Store parameter (or base class) and wait for an ending bracket + elif (s==3): + if (tok=='*' or tok=='**'): + tok='' + if (tok=='('): + bracket_counter = bracket_counter+1 + if (tok==')'): + bracket_counter = bracket_counter-1 + if bracket_counter==0: + record_state=4 + else: + param=param+tok + # State 4: Look for doc string + elif (s==4): + if (type==token.NEWLINE or type==token.INDENT or type==token.SLASHEQUAL): + return + elif (tok==":"): + return + elif (type==token.STRING): + while tok[:1]=='r' or tok[:1]=='u': + tok=tok[1:] + while tok[:1]=='"': + tok=tok[1:] + while tok[-1:]=='"': + tok=tok[:-1] + doc_string=tok + record_state=0 + +###################################################################### +# Starts the recording of a name & param part. +# The function rec_name_n_param() has to be fed with tokens. After +# the necessary tokens are fed the name and parameters can be found +# in the global variables "name" und "param". +###################################################################### +def start_recording(): + global record_state,param,name, doc_string + record_state=1 + name="" + param="" + doc_string="" + +###################################################################### +# Test if recording is finished +###################################################################### +def is_recording_finished(): + global record_state + return record_state==0 + +###################################################################### +## Gather comment block +###################################################################### +def gather_comment(type,tok,spos): + global comment_block,comment_finished + if (type!=tokenize.COMMENT): + comment_finished = 1 + else: + # Output old comment block if a new one is started. + if (comment_finished): + print_comment(spos) + comment_finished=0 + if (tok[0:2]=="##" and tok[0:3]!="###"): + append_comment_lines(tok[2:]) + +###################################################################### +## Output comment block and empty buffer. +###################################################################### +def print_comment(spos): + global comment_block,comment_finished + if (comment_block!=[]): + output("/** ",spos) + for c in comment_block: + output(c,spos) + output("*/\n",spos) + comment_block = [] + comment_finished = 0 + +###################################################################### +def set_state(s): + global stateStack + stateStack[len(stateStack)-1]=s + +###################################################################### +def get_state(): + global stateStack + return stateStack[len(stateStack)-1] + +###################################################################### +def push_state(s): + global stateStack + stateStack.append(s) + +###################################################################### +def pop_state(): + global stateStack + stateStack.pop() + + +###################################################################### +def tok_eater(type, tok, spos, epos, line): + global stateStack,name,param,class_spos,def_spos,import_spos + global doc_string, modules, import_token, module_has_docstring + global protection_level, private_member + global out_row + + while out_row + 1 < spos[0]: + output("\n", (0, 0)) + + rec_name_n_param(type,tok) + if (string.replace(string.strip(tok)," ","")=="##private:"): + protection_level = "private" + output("private:\n",spos) + elif (string.replace(string.strip(tok)," ","")=="##protected:"): + protection_level = "protected" + output("protected:\n",spos) + elif (string.replace(string.strip(tok)," ","")=="##public:"): + protection_level = "public" + output("public:\n",spos) + else: + gather_comment(type,tok,spos) + + state = get_state() + +# sys.stderr.write("%d: %s\n"%(state, tok)) + + # OUTSIDE + if (state==OUTSIDE): + if (tok=="class"): + start_recording() + class_spos = spos + push_state(BUILD_CLASS_DECL) + elif (tok=="def"): + start_recording() + def_spos = spos + push_state(BUILD_DEF_DECL) + elif (tok=="import") or (tok=="from"): + import_token = tok + import_spos = spos + modules = [] + push_state(IMPORT) + elif (spos[1] == 0 and tok[:3] == '"""'): + # Capture module docstring as namespace documentation + module_has_docstring = True + append_comment_lines("\\namespace %s\n" % namespace) + append_comment_lines(tok[3:-3]) + print_comment(spos) + + # IMPORT + elif (state==IMPORT): + if (type==token.NAME): + modules.append(tok) + set_state(IMPORT_OP) + # IMPORT_OP + elif (state==IMPORT_OP): + if (tok=="."): + set_state(IMPORT_APPEND) + elif (tok==","): + set_state(IMPORT) + else: + for m in modules: + output('#include "'+m.replace('.',os.path.sep)+'.py"\n', import_spos, immediate=1) + if import_token=="from": + output('using namespace '+m.replace('.', '::')+';\n', import_spos) + pop_state() + # IMPORT_APPEND + elif (state==IMPORT_APPEND): + if (type==token.NAME): + modules[len(modules)-1]+="."+tok + set_state(IMPORT_OP) + # BUILD_CLASS_DECL + elif (state==BUILD_CLASS_DECL): + if (is_recording_finished()): + s = "class "+name + if (param!=""): s = s+" : public "+param.replace('.','::') + if (doc_string!=""): + append_comment_lines(doc_string) + print_comment(class_spos) + output(s+"\n",class_spos) + output("{\n",(class_spos[0]+1,class_spos[1])) + protection_level = "public" + output(" public:\n",(class_spos[0]+2,class_spos[1])) + set_state(BUILD_CLASS_BODY) + # BUILD_CLASS_BODY + elif (state==BUILD_CLASS_BODY): + if (type!=token.INDENT and type!=token.NEWLINE and type!=40 and + type!=tokenize.NL and type!=tokenize.COMMENT and + (spos[1]<=class_spos[1])): + output("}; // end of class\n",(out_row+1,class_spos[1])) + pop_state() + elif (tok=="def"): + start_recording() + def_spos = spos + push_state(BUILD_DEF_DECL) + # BUILD_DEF_DECL + elif (state==BUILD_DEF_DECL): + if (is_recording_finished()): + param = param.replace("\n", " ") + param = param.replace("=", " = ") + params = param.split(",") + if BUILD_CLASS_BODY in stateStack: + if len(name) > 1 \ + and name[0:2] == '__' \ + and name[len(name)-2:len(name)] != '__' \ + and protection_level != 'private': + private_member = True + output(" private:\n",(def_spos[0]+2,def_spos[1])) + + if (doc_string != ""): + append_comment_lines(doc_string) + + print_comment(def_spos) + + output_function_decl(name, params) +# output("{\n",(def_spos[0]+1,def_spos[1])) + set_state(BUILD_DEF_BODY) + # BUILD_DEF_BODY + elif (state==BUILD_DEF_BODY): + if (type!=token.INDENT and type!=token.NEWLINE \ + and type!=40 and type!=tokenize.NL \ + and (spos[1]<=def_spos[1])): +# output("} // end of method/function\n",(out_row+1,def_spos[1])) + if private_member and protection_level != 'private': + private_member = False + output(" " + protection_level + ":\n",(def_spos[0]+2,def_spos[1])) + pop_state() +# else: +# output(tok,spos) + + +def output_function_decl(name, params): + global def_spos + + # Do we document a class method? then remove the 'self' parameter + if params[0] == 'self': + preamble = '' + params = params[1:] + else: + preamble = 'static ' + if params[0] == 'cls': + params = params[1:] + + param_string = string.join(params, ", Type ") + + if param_string == '': + param_string = '(' + param_string + ');\n' + else: + param_string = '(Type ' + param_string + ');\n' + + output(preamble, def_spos) + output(name, def_spos) + output(param_string, def_spos) + + +def append_comment_lines(lines): + map(append_comment_line, doc_string.split('\n')) + +paramRE = re.compile(r'(@param \w+):') + +def append_comment_line(line): + global paramRE + + comment_block.append(paramRE.sub(r'\1', line) + '\n') + +def dump(filename): + f = open(filename) + r = f.readlines() + for s in r: + sys.stdout.write(s) + +def filter(filename): + global name, module_has_docstring, source_root + + path,name = os.path.split(filename) + root,ext = os.path.splitext(name) + + if source_root and path.find(source_root) == 0: + path = path[len(source_root):] + + if path[0] == os.sep: + path = path[1:] + + ns = path.split(os.sep) + else: + ns = [] + + ns.append(root) + + for n in ns: + output("namespace " + n + " {\n",(0,0)) + + # set module name for tok_eater to use if there's a module doc string + name = root + +# sys.stderr.write('Filtering "'+filename+'"...') + f = open(filename) + tokenize.tokenize(f.readline, tok_eater) + f.close() + print_comment((0,0)) + + output("\n",(0,0)) + + for n in ns: + output("} // end of namespace\n",(0,0)) + + if not module_has_docstring: + # Put in default namespace documentation + output('/** \\namespace '+root+' \n',(0,0)) + output(' \\brief Module "%s" */\n'%(root),(0,0)) + + for s in outbuffer: + outfile.write(s) + + +def filterFile(filename, out=sys.stdout): + global outfile + + outfile = out + + try: + root,ext = os.path.splitext(filename) + + if ext==".py": + filter(filename) + else: + dump(filename) + +# sys.stderr.write("OK\n") + except IOError,e: + sys.stderr.write(e[1]+"\n") + + +###################################################################### + +# preparePath +def preparePath(path): + """Prepare a path. + + Checks if the path exists and creates it if it does not exist. + """ + if not os.path.exists(path): + parent = os.path.dirname(path) + if parent!="": + preparePath(parent) + os.mkdir(path) + +# isNewer +def isNewer(file1,file2): + """Check if file1 is newer than file2. + + file1 must be an existing file. + """ + if not os.path.exists(file2): + return True + return os.stat(file1)[ST_MTIME]>os.stat(file2)[ST_MTIME] + +# convert +def convert(srcpath, destpath): + """Convert a Python source tree into a C+ stub tree. + + All *.py files in srcpath (including sub-directories) are filtered + and written to destpath. If destpath exists, only the files + that have been modified are filtered again. Files that were deleted + from srcpath are also deleted in destpath if they are still present. + The function returns the number of processed *.py files. + """ + count=0 + sp = os.path.join(srcpath,"*") + sfiles = glob.glob(sp) + dp = os.path.join(destpath,"*") + dfiles = glob.glob(dp) + leftovers={} + for df in dfiles: + leftovers[os.path.basename(df)]=1 + + for srcfile in sfiles: + basename = os.path.basename(srcfile) + if basename in leftovers: + del leftovers[basename] + + # Is it a subdirectory? + if os.path.isdir(srcfile): + sdir = os.path.join(srcpath,basename) + ddir = os.path.join(destpath,basename) + count+=convert(sdir, ddir) + continue + # Check the extension (only *.py will be converted) + root, ext = os.path.splitext(srcfile) + if ext.lower()!=".py": + continue + + destfile = os.path.join(destpath,basename) + if destfile==srcfile: + print "WARNING: Input and output names are identical!" + sys.exit(1) + + count+=1 +# sys.stdout.write("%s\015"%(srcfile)) + + if isNewer(srcfile, destfile): + preparePath(os.path.dirname(destfile)) +# out=open(destfile,"w") +# filterFile(srcfile, out) +# out.close() + os.system("python %s -f %s>%s"%(sys.argv[0],srcfile,destfile)) + + # Delete obsolete files in destpath + for df in leftovers: + dname=os.path.join(destpath,df) + if os.path.isdir(dname): + try: + shutil.rmtree(dname) + except: + print "Can't remove obsolete directory '%s'"%dname + else: + try: + os.remove(dname) + except: + print "Can't remove obsolete file '%s'"%dname + + return count + + +###################################################################### +###################################################################### +###################################################################### + +filter_file = False +source_root = None + +try: + opts, args = getopt.getopt(sys.argv[1:], "hfr:", ["help"]) +except getopt.GetoptError,e: + print e + sys.exit(1) + +for o,a in opts: + if o=="-f": + filter_file = True + + if o=="-r": + source_root = os.path.abspath(a) + +if filter_file: + # Filter the specified file and print the result to stdout + filename = string.join(args) + filterFile(os.path.abspath(filename)) +else: + + if len(args)!=2: + sys.stderr.write("%s options input output\n"%(os.path.basename(sys.argv[0]))) + sys.exit(1) + + # Filter an entire Python source tree + print '"%s" -> "%s"\n'%(args[0],args[1]) + c=convert(args[0],args[1]) + print "%d files"%(c) + diff -r d4d880fcef28 -r b35215021b32 linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/synch_bitops.h --- /dev/null Fri Sep 9 16:31:36 2005 +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/synch_bitops.h Tue Sep 13 16:14:16 2005 @@ -0,0 +1,2 @@ + +#include <asm-i386/synch_bitops.h> diff -r d4d880fcef28 -r b35215021b32 tools/examples/block-phy --- /dev/null Fri Sep 9 16:31:36 2005 +++ b/tools/examples/block-phy Tue Sep 13 16:14:16 2005 @@ -0,0 +1,30 @@ +#! /bin/sh + +set -e + +expand_dev() { + local dev + case $1 in + /*) + dev=$1 + ;; + *) + dev=/dev/$1 + ;; + esac + echo -n $dev +} + +case $1 in + bind) + dev=$(expand_dev $2) + major=$(stat -L -c %t "$dev") + minor=$(stat -L -c %T "$dev") + pdev=$(printf "0x%02x%02x" 0x$major 0x$minor) + xenstore-write "$XENBUS_PATH"/physical-device $pdev \ + "$XENBUS_PATH"/node $dev + exit 0 + ;; + unbind) + ;; +esac diff -r d4d880fcef28 -r b35215021b32 tools/examples/xmexample.vmx.in --- /dev/null Fri Sep 9 16:31:36 2005 +++ b/tools/examples/xmexample.vmx.in Tue Sep 13 16:14:16 2005 @@ -0,0 +1,96 @@ +# -*- mode: python; -*- +#============================================================================ +# Python configuration setup for 'xm create'. +# This script sets the parameters used when a domain is created using 'xm create'. +# You use a separate script for each domain you want to create, or +# you can set the parameters for the domain on the xm command line. +#============================================================================ + +#---------------------------------------------------------------------------- +# Kernel image file. +kernel = "/usr/@@LIBDIR@@/xen/boot/vmxloader" + +# The domain build function. VMX domain uses 'vmx'. +builder='vmx' + +# Initial memory allocation (in megabytes) for the new domain. +memory = 128 + +# A name for your domain. All domains must have different names. +name = "ExampleVMXDomain" + +# Which CPU to start domain on? +#cpu = -1 # leave to Xen to pick + +# Optionally define mac and/or bridge for the network interfaces. +# Random MACs are assigned if not given. +#vif = [ 'mac=aa:00:00:00:00:11, bridge=xen-br0' ] + +#---------------------------------------------------------------------------- +# Define the disk devices you want the domain to have access to, and +# what you want them accessible as. +# Each disk entry is of the form phy:UNAME,DEV,MODE +# where UNAME is the device, DEV is the device name the domain will see, +# and MODE is r for read-only, w for read-write. + +#disk = [ 'phy:hda1,hda1,r' ] +disk = [ 'file:/var/images/min-el3-i386.img,ioemu:hda,w' ] + +#---------------------------------------------------------------------------- +# Set according to whether you want the domain restarted when it exits. +# The default is 'onreboot', which restarts the domain when it shuts down +# with exit code reboot. +# Other values are 'always', and 'never'. + +#restart = 'onreboot' + +#============================================================================ + + +# New stuff +device_model = '/usr/@@LIBDIR@@/xen/bin/qemu-dm' + +# Advanced users only. Don't touch if you don't know what you're doing +memmap = '/usr/@@LIBDIR@@/xen/boot/mem-map.sxp' + +#----------------------------------------------------------------------------- +# Disk image for +#cdrom= + +#----------------------------------------------------------------------------- +# boot on floppy (a), hard disk (c) or CD-ROM (d) +#boot=[a|c|d] +#----------------------------------------------------------------------------- +# write to temporary files instead of disk image files +#snapshot=1 + +#---------------------------------------------------------------------------- +# enable SDL library for graphics, default = 0 +sdl=0 + +#---------------------------------------------------------------------------- +# enable VNC library for graphics, default = 1 +vnc=1 + +#---------------------------------------------------------------------------- +# enable spawning vncviewer(only valid when vnc=1), default = 1 +vncviewer=1 + +#---------------------------------------------------------------------------- +# no graphics, use serial port +#nographic=0 + + +#----------------------------------------------------------------------------- +# enable audio support +#enable-audio=1 + + +#----------------------------------------------------------------------------- +# set the real time clock to local time [default=0 i.e. set to utc] +#localtime=1 + + +#----------------------------------------------------------------------------- +# start in full screen +#full-screen=1 diff -r d4d880fcef28 -r b35215021b32 tools/python/pylintrc --- /dev/null Fri Sep 9 16:31:36 2005 +++ b/tools/python/pylintrc Tue Sep 13 16:14:16 2005 @@ -0,0 +1,307 @@ +# lint Python modules using external checkers. +# +# This is the main checker controling the other ones and the reports +# generation. It is itself both a raw checker and an astng checker in order +# to: +# * handle message activation / deactivation at the module level +# * handle some basic but necessary stats'data (number of classes, methods...) +# +# This checker also defines the following reports: +# * R0001: Total errors / warnings +# * R0002: % errors / warnings by module +# * R0003: Messages +# * R0004: Global evaluation +# +[MASTER] +# Add <file or directory> to the black list. It should be a base name, not a +# path. You may set this option multiple times. +ignore=CVS + +# Pickle collected data for later comparisons. +persistent=yes + +# Set the cache size for astng objects. +cache-size=500 + + + +[REPORTS] +# Tells wether to display a full report or only the messages +reports=yes + +# Use HTML as output format instead of text +html=no + +# Use a parseable text output format, so your favorite text editor will be able +# to jump to the line corresponding to a message. +parseable=no + +# Colorizes text output using ansi escape codes +color=no + +# Put messages in a separate file for each module / package specified on the +# command line instead of printing them on stdout. Reports (if any) will be +# written in a file name "pylint_global.[txt|html]". +files-output=no + +# Python expression which should return a note less than 10 (10 is the highest +# note).You have access to the variables errors warning, statement which +# respectivly contain the number of errors / warnings messages and the total +# number of statements analyzed. This is used by the global evaluation report +# (R0004). +evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) + +# Add a comment according to your evaluation note. This is used by the global +# evaluation report (R0004). +comment=no + +# Include message's id in output +include-ids=yes + + + +# checks for +# * unused variables / imports +# * undefined variables +# * redefinition of variable from builtins or from an outer scope +# * use of variable before assigment +# +[VARIABLES] +# Enable / disable this checker +enable-variables=yes + +# Tells wether we should check for unused import in __init__ files. +init-import=no + +# List of variable names used for dummy variables (i.e. not used). +dummy-variables=_,dummy + + + +# checks for : +# * doc strings +# * modules / classes / functions / methods / arguments / variables name +# * number of arguments, local variables, branchs, returns and statements in +# functions, methods +# * required module attributes +# * dangerous default values as arguments +# * redefinition of function / method / class +# * uses of the global statement +# +# This checker also defines the following reports: +# * R0101: Statistics by type +# +[BASIC] +# Enable / disable this checker +enable-basic=yes + +# Required attributes for module, separated by a comma +required-attributes= + +# Regular expression which should only match functions or classes name which do +# not require a docstring +no-docstring-rgx=.* + +# Minimal length for module / class / function / method / argument / variable +# names +min-name-length=1 + +# Regular expression which should only match correct module names +module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ + +# Regular expression which should only match correct class names +class-rgx=[A-Z_][a-zA-Z0-9]+$ + +# Regular expression which should only match correct function names +function-rgx=[a-z_][A-Za-z0-9_]*$ + +# Regular expression which should only match correct method names +method-rgx=[a-z_][A-Za-z0-9_]*$ + +# Regular expression which should only match correct argument names +argument-rgx=[a-z_][A-Za-z0-9_]*$ + +# Regular expression which should only match correct variable names +variable-rgx=[a-z_][A-Za-z0-9_]*$ + +# Good variable names which should always be accepted, separated by a comma +good-names=i,j,k,ex,Run,_ + +# Bad variable names which should always be refused, separated by a comma +bad-names=foo,bar,baz,toto,tutu,tata + +# List of builtins function names that should not be used, separated by a comma +bad-functions=map,filter,apply,input + + + +# checks for sign of poor/misdesign: +# * number of methods, attributes, local variables... +# * size, complexity of functions, methods +# +[DESIGN] +# Enable / disable this checker +enable-design=yes + +# Maximum number of arguments for function / method +max-args=15 + +# Maximum number of locals for function / method body +max-locals=15 + +# Maximum number of return / yield for function / method body +max-returns=6 + +# Maximum number of branch for function / method body +max-branchs=12 + +# Maximum number of statements in function / method body +max-statements=50 + +# Maximum number of parents for a class (see R0901). +max-parents=7 + +# Maximum number of attributes for a class (see R0902). +max-attributes=7 + +# Minimum number of public methods for a class (see R0903). +min-public-methods=2 + +# Maximum number of public methods for a class (see R0904). +max-public-methods=20 + + + +# checks for : +# * methods without self as first argument +# * overriden methods signature +# * access only to existant members via self +# * attributes not defined in the __init__ method +# * supported interfaces implementation +# * unreachable code +# +[CLASSES] +# Enable / disable this checker +enable-classes=yes + +# List of interface methods to ignore, separated by a comma. This is used for +# instance to not check methods defines in Zope's Interface base class. +ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by + +# Tells wether missing members accessed in mixin class should be ignored. A +# mixin class is detected if its name ends with "mixin" (case insensitive). +ignore-mixin-members=yes + + + +# checks for +# * external modules dependencies +# * relative / wildcard imports +# * cyclic imports +# * uses of deprecated modules +# +# This checker also defines the following reports: +# * R0401: External dependencies +# * R0402: Modules dependencies graph +# +[IMPORTS] +# Enable / disable this checker +enable-imports=no + +# Deprecated modules which should not be used, separated by a comma +deprecated-modules=regsub,string,TERMIOS,Bastion,rexec + +# Create a graph of every (i.e. internal and external) dependencies in the given +# file (report R0402 must not be disabled) +import-graph= + +# Create a graph of external dependencies in the given file (report R0402 must +# not be disabled) +ext-import-graph= + +# Create a graph of internal dependencies in the given file (report R0402 must +# not be disabled) +int-import-graph= + + + +# checks for +# * excepts without exception filter +# * string exceptions +# +[EXCEPTIONS] +# Enable / disable this checker +enable-exceptions=yes + + + +# checks for : +# * unauthorized constructions +# * strict indentation +# * line length +# * use of <> instead of != +# +[FORMAT] +# Enable / disable this checker +enable-format=no + +# Maximum number of characters on a single line. +max-line-length=80 + +# Maximum number of lines in a module +max-module-lines=1000 + +# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 tab). +indent-string=' ' + + + +# does not check anything but gives some raw metrics : +# * total number of lines +# * total number of code lines +# * total number of docstring lines +# * total number of comments lines +# * total number of empty lines +# +# This checker also defines the following reports: +# * R0701: Raw metrics +# +[METRICS] +# Enable / disable this checker +enable-metrics=yes + + + +# checks for: +# * warning notes in the code like FIXME, XXX +# * PEP 263: source code with non ascii character but no encoding declaration +# +[MISCELLANEOUS] +# Enable / disable this checker +enable-miscellaneous=yes + +# List of note tags to take in consideration, separated by a comma. Default to +# FIXME, XXX, TODO +notes=FIXME,XXX,TODO + + + +# checks for similarities and duplicated code. This computation may be +# memory / CPU intensive, so you should disable it if you experiments some +# problems. +# +# This checker also defines the following reports: +# * R0801: Duplication +# +[SIMILARITIES] +# Enable / disable this checker +enable-similarities=yes + +# Minimum lines number of a similarity. +min-similarity-lines=4 + +# Ignore comments when computing similarities. +ignore-comments=yes + + + diff -r d4d880fcef28 -r b35215021b32 tools/vnet/Make.env --- /dev/null Fri Sep 9 16:31:36 2005 +++ b/tools/vnet/Make.env Tue Sep 13 16:14:16 2005 @@ -0,0 +1,20 @@ +# -*- mode: Makefile; -*- + +export XEN_ROOT = $(shell cd $(VNET_ROOT)/../.. && pwd) +export LINUX_SERIES ?= 2.6 + +DISTDIR ?= $(XEN_ROOT)/dist +export DESTDIR ?= $(DISTDIR)/install + +export VNET_MODULE_DIR = $(VNET_ROOT)/vnet-module +export VNETD_DIR = $(VNET_ROOT)/vnetd +export LIBXUTIL_DIR = $(VNET_ROOT)/libxutil + +export GC_DIR = $(VNET_ROOT)/build/gc +export GC_INCLUDE = $(GC_DIR)/include +export GC_LIB_DIR = $(GC_DIR)/lib +export GC_LIB_A = $(GC_LIB_DIR)/libgc.a +export GC_LIB_SO = $(GC_LIB_DIR)/libgc.so + +#$(warning XEN_ROOT = $(XEN_ROOT)) +#$(warning DESTDIR = $(DESTDIR)) diff -r d4d880fcef28 -r b35215021b32 tools/vnet/examples/vnet-insert --- /dev/null Fri Sep 9 16:31:36 2005 +++ b/tools/vnet/examples/vnet-insert Tue Sep 13 16:14:16 2005 @@ -0,0 +1,28 @@ +#!/bin/bash + +# Insert the vnet module if it can be found and +# it's not already there. +vnet_insert () { + local module="vnet_module" + local mod_dir=/lib/modules/$(uname -r) + local mod_obj="" + + if lsmod | grep -q ${module} ; then + echo "VNET: ${module} loaded" + return + fi + local mods=$(find ${mod_dir} -name "${module}.*o") + if [[ ${mods} ]] ; then + for mod_obj in ${mods} ; do + break + done + fi + if [ -z "${mod_obj}" ] ; then + echo "VNET: ${module} not found" + exit 1 + fi + echo "VNET: Loading ${module} from ${mod_obj}" + insmod ${mod_obj} "$@" +} + +vnet_insert "$@" diff -r d4d880fcef28 -r b35215021b32 tools/vnet/libxutil/mem_stream.c --- /dev/null Fri Sep 9 16:31:36 2005 +++ b/tools/vnet/libxutil/mem_stream.c Tue Sep 13 16:14:16 2005 @@ -0,0 +1,319 @@ +/* + * Copyright (C) 2005 Mike Wray <mike.wray@xxxxxx> + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/** @file + * IOStream subtype for input and output to memory. + * Usable from user or kernel code (with __KERNEL__ defined). + */ + +#include "sys_string.h" +#include "mem_stream.h" +#include "allocate.h" + +/** Internal state for a memory stream. + * + * The memory stream buffer is treated as a circular buffer. + * The lo and hi markers indicate positions in the buffer, but + * are not reduced modulo the buffer size. This avoids the ambiguity + * between a full and empty buffer when using reduced values. + * + * If x is a marker, then buf + (x % buf_n) is the corresponding + * pointer into the buffer. When the buffer is empty, lo == hi, + * and the corresponding pointers are equal. When the buffer is + * full, hi == lo + buf_n, and the corresponding pointers + * are also equal. + * + * Data is written after the high pointer and read from the lo pointer. + * The value hi - lo is the number of bytes in the buffer. + */ +typedef struct MemData { + /** Data buffer. */ + char *buf; + /** Low marker - start of readable area. */ + unsigned long lo; + /** High marker - end of readable area, start of writeable area. */ + unsigned long hi; + /** Size of the buffer. */ + unsigned int buf_n; + /** Maximum size the buffer can grow to. */ + unsigned int buf_max; + /** Error code. */ + int err; +} MemData; + +/** Get number of bytes available to read. + * + * @param data mem stream + * @return bytes + */ +static inline int mem_len(struct MemData *data){ + return data->hi - data->lo; +} + +/** Get available space left in the buffer. + * + * @param data mem stream + * @return bytes + */ +static inline int mem_room(struct MemData *data){ + return data->buf_n - mem_len(data); +} + +/** Get a pointer to the start of the data in the buffer. + * + * @param data mem stream + * @return lo pointer + */ +static inline char * mem_lo(struct MemData *data){ + return data->buf + (data->lo % data->buf_n); +} + +/** Get a pointer to the end of the data in the buffer. + * + * @param data mem stream + * @return hi pointer + */ +static inline char * mem_hi(struct MemData *data){ + return data->buf + (data->hi % data->buf_n); +} + +/** Get a pointer to the end of the buffer. + * + * @param data mem stream + * @return end pointer + */ +static inline char * mem_end(struct MemData *data){ + return data->buf + data->buf_n; +} + +static int mem_error(IOStream *io); +static int mem_close(IOStream *io); +static void mem_free(IOStream *io); +static int mem_write(IOStream *io, const void *msg, size_t n); +static int mem_read(IOStream *io, void *buf, size_t n); + +/** Minimum delta used to increment the buffer. */ +static int delta_min = 256; + +/** Methods for a memory stream. */ +static IOMethods mem_methods = { + read: mem_read, + write: mem_write, + error: mem_error, + close: mem_close, + free: mem_free, +}; + +/** Get the memory stream state. + * + * @param io memory stream + * @return state + */ +static inline MemData *get_mem_data(IOStream *io){ + return (MemData*)io->data; +} + +/** Get the number of bytes available to read. + * + * @param io memory stream + * @return number of bytes + */ +int mem_stream_avail(IOStream *io){ + MemData *data = get_mem_data(io); + return (data->err ? -data->err : mem_len(data)); +} + +/** Copy bytes from a memory stream into a buffer. + * + * @param data mem stream + * @param buf buffer + * @param n number of bytes to copy + */ +static void mem_get(MemData *data, char *buf, size_t n){ + char *start = mem_lo(data); + char *end = mem_end(data); + if (start + n < end) { + memcpy(buf, start, n); + } else { + int k = end - start; + memcpy(buf, start, k); + memcpy(buf + k, data->buf, n - k); + } +} + +/** Copy bytes from a buffer into a memory stream. + * + * @param data mem stream + * @param buf buffer + * @param n number of bytes to copy + */ +static void mem_put(MemData *data, const char *buf, size_t n){ + char *start = mem_hi(data); + char *end = mem_end(data); + if(start + n < end){ + memcpy(start, buf, n); + } else { + int k = end - start; + memcpy(start, buf, k); + memcpy(data->buf, buf + k, n - k); + } +} + +/** Expand the buffer used by a memory stream. + * + * @param data mem stream + * @param extra number of bytes to expand by + * @return 0 on success, negative error otherwise + */ +static int mem_expand(MemData *data, size_t extra){ + int err = -ENOMEM; + int delta = (extra < delta_min ? delta_min : extra); + if(data->buf_max > 0){ + int delta_max = data->buf_max - data->buf_n; + if(delta > delta_max){ + delta = extra; + if(delta > delta_max) goto exit; + } + } + int buf_n = data->buf_n + delta; + char *buf = allocate(buf_n); + if(!buf) goto exit; + mem_get(data, buf, mem_len(data)); + data->hi = mem_len(data); + data->lo = 0; + deallocate(data->buf); + data->buf = buf; + data->buf_n = buf_n; + err = 0; + exit: + if(err){ + data->err = -err; + } + return err; +} + +/** Write bytes from a buffer into a memory stream. + * The internal buffer is expanded as needed to hold the data, + * up to the stream maximum (if specified). If the buffer cannot + * be expanded -ENOMEM is returned. + * + * @param io mem stream + * @param buf buffer + * @param n number of bytes to write + * @return number of bytes written on success, negative error code otherwise + */ +static int mem_write(IOStream *io, const void *msg, size_t n){ + MemData *data = get_mem_data(io); + if(data->err) return -data->err; + int room = mem_room(data); + if(n > room){ + int err = mem_expand(data, n - room); + if(err) return err; + } + mem_put(data, msg, n); + data->hi += n; + return n; +} + +/** Read bytes from a memory stream into a buffer. + * + * @param io mem stream + * @param buf buffer + * @param n maximum number of bytes to read + * @return number of bytes read on success, negative error code otherwise + */ +static int mem_read(IOStream *io, void *buf, size_t n){ + MemData *data = get_mem_data(io); + if(data->err) return -data->err; + int k = mem_len(data); + if(n > k){ + n = k; + } + mem_get(data, buf, n); + data->lo += n; + return n; +} + +/** Test if a memory stream has an error. + * + * @param io mem stream + * @return 0 if ok, error code otherwise + */ +static int mem_error(IOStream *io){ + MemData *data = get_mem_data(io); + return data->err; +} + +/** Close a memory stream. + * + * @param io mem stream + * @return 0 + */ +static int mem_close(IOStream *io){ + MemData *data = get_mem_data(io); + if(!data->err){ + data->err = ENOTCONN; + } + return 0; +} + +/** Free a memory stream. + * + * @param io mem stream + */ +static void mem_free(IOStream *io){ + MemData *data = get_mem_data(io); + deallocate(data->buf); + memzero(data, sizeof(*data)); + deallocate(data); +} + +/** Allocate and initialise a memory stream. + * + * @param buf_n initial buffer size (0 means default) + * @param buf_max maximum buffer size (0 means no max) + * @return new stream (free using IOStream_close) + */ +IOStream *mem_stream_new_size(size_t buf_n, size_t buf_max){ + int err = -ENOMEM; + MemData *data = ALLOCATE(MemData); + if(!data) goto exit; + IOStream *io = ALLOCATE(IOStream); + if(!io) goto exit; + if(buf_n <= delta_min){ + buf_n = delta_min; + } + if(buf_max > 0 && buf_max < buf_n){ + buf_max = buf_n; + } + data->buf = allocate(buf_n); + if(!data->buf) goto exit; + data->buf_n = buf_n; + data->buf_max = buf_max; + io->methods = &mem_methods; + io->data = data; + io->nofree = 0; + err = 0; + exit: + if(err){ + deallocate(data); + deallocate(io); + io = NULL; + } + return io; +} diff -r d4d880fcef28 -r b35215021b32 tools/vnet/libxutil/mem_stream.h --- /dev/null Fri Sep 9 16:31:36 2005 +++ b/tools/vnet/libxutil/mem_stream.h Tue Sep 13 16:14:16 2005 @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2005 Mike Wray <mike.wray@xxxxxx> + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _XUTIL_MEM_STREAM_H_ +#define _XUTIL_MEM_STREAM_H_ + +#include "iostream.h" + +extern IOStream *mem_stream_new_size(size_t buf_n, size_t buf_max); + +extern int mem_stream_avail(IOStream *io); + +static inline IOStream *mem_stream_new(void){ + return mem_stream_new_size(0, 0); +} + +#endif /* !_XUTIL_MEM_STREAM_H_ */ diff -r d4d880fcef28 -r b35215021b32 tools/vnet/vnet-module/varp_util.c --- /dev/null Fri Sep 9 16:31:36 2005 +++ b/tools/vnet/vnet-module/varp_util.c Tue Sep 13 16:14:16 2005 @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2005 Mike Wray <mike.wray@xxxxxx> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free software Foundation, Inc., + * 59 Temple Place, suite 330, Boston, MA 02111-1307 USA + * + */ + +static int hex16(char *s, uint16_t *val) +{ + int err = -EINVAL; + uint16_t v = 0; + + for( ; *s; s++){ + v <<= 4; + if('0' <= *s && *s <= '9'){ + v |= *s - '0'; + } else if('A' <= *s && *s <= 'F'){ + v |= *s - 'A' + 10; + } else if('a' <= *s && *s <= 'f'){ + v |= *s - 'a' + 10; + } else { + goto exit; + } + } + err = 0; + exit: + *val = (err ? 0 : v); + return err; +} + +int VnetId_aton(const char *s, VnetId *vnet){ + int err = -EINVAL; + const char *p, *q; + uint16_t v; + char buf[5]; + int buf_n = sizeof(buf) - 1; + int i, n; + const int elts_n = 8; + + q = s; + p = strchr(q, ':'); + i = (p ? 0 : elts_n - 1); + do { + if(!p){ + if(i < elts_n - 1) goto exit; + p = s + strlen(s); + } + n = p - q; + if(n > buf_n) goto exit; + memcpy(buf, q, n); + buf[n] = '\0'; + err = hex16(buf, &v); + if(err) goto exit; + vnet->u.vnet16[i] = htons(v); + q = p+1; + p = strchr(q, ':'); + i++; + } while(i < elts_n); + err = 0; + exit: + if(err){ + *vnet = (VnetId){}; + } + return err; +} diff -r d4d880fcef28 -r b35215021b32 tools/vnet/vnet-module/varp_util.h --- /dev/null Fri Sep 9 16:31:36 2005 +++ b/tools/vnet/vnet-module/varp_util.h Tue Sep 13 16:14:16 2005 @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2004 Mike Wray <mike.wray@xxxxxx> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free software Foundation, Inc., + * 59 Temple Place, suite 330, Boston, MA 02111-1307 USA + * + */ +#ifndef _VNET_VARP_UTIL_H +#define _VNET_VARP_UTIL_H + +#include "hash_table.h" + +/** Size of a string buffer to store a varp address. */ +#define VARP_ADDR_BUF 56 + +/** Size of a string buffer to store a vnet id. */ +#define VNET_ID_BUF 56 + +#ifndef NIPQUAD +#define NIPQUAD(addr) \ + ((unsigned char *)&addr)[0], \ + ((unsigned char *)&addr)[1], \ + ((unsigned char *)&addr)[2], \ + ((unsigned char *)&addr)[3] +#endif + +#ifndef NIP6 +#define NIP6(addr) \ + ntohs((addr).s6_addr16[0]), \ + ntohs((addr).s6_addr16[1]), \ + ntohs((addr).s6_addr16[2]), \ + ntohs((addr).s6_addr16[3]), \ + ntohs((addr).s6_addr16[4]), \ + ntohs((addr).s6_addr16[5]), \ + ntohs((addr).s6_addr16[6]), \ + ntohs((addr).s6_addr16[7]) +#endif + + +static inline const char *VarpAddr_ntoa(VarpAddr *addr, char buf[VARP_ADDR_BUF]) +{ + switch(addr->family){ + default: + case AF_INET: + sprintf(buf, "%u.%u.%u.%u", + NIPQUAD(addr->u.ip4)); + break; + case AF_INET6: + sprintf(buf, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", + NIP6(addr->u.ip6)); + break; + } + return buf; +} + +static inline const char *VnetId_ntoa(VnetId *vnet, char buf[VNET_ID_BUF]) +{ + sprintf(buf, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", + ntohs(vnet->u.vnet16[0]), \ + ntohs(vnet->u.vnet16[1]), \ + ntohs(vnet->u.vnet16[2]), \ + ntohs(vnet->u.vnet16[3]), \ + ntohs(vnet->u.vnet16[4]), \ + ntohs(vnet->u.vnet16[5]), \ + ntohs(vnet->u.vnet16[6]), \ + ntohs(vnet->u.vnet16[7])); + return buf; +} + +extern int VnetId_aton(const char *s, VnetId *vnet); + +/** Convert an unsigned in host order to a vnet id. + */ +static inline struct VnetId toVnetId(uint32_t vnetid){ + struct VnetId vnet = {}; + vnet.u.vnet32[3] = htonl(vnetid); + return vnet; +} + +static inline uint32_t VnetId_hash(uint32_t h, VnetId *vnet) +{ + h = hash_hul(h, vnet->u.vnet32[0]); + h = hash_hul(h, vnet->u.vnet32[1]); + h = hash_hul(h, vnet->u.vnet32[2]); + h = hash_hul(h, vnet->u.vnet32[3]); + return h; +} + +static inline int VnetId_eq(VnetId *vnet1, VnetId *vnet2) +{ + return memcmp(vnet1, vnet2, sizeof(VnetId)) == 0; +} + +static inline uint32_t VarpAddr_hash(uint32_t h, VarpAddr *addr) +{ + h = hash_hul(h, addr->family); + if(addr->family == AF_INET6){ + h = hash_hul(h, addr->u.ip6.s6_addr32[0]); + h = hash_hul(h, addr->u.ip6.s6_addr32[1]); + h = hash_hul(h, addr->u.ip6.s6_addr32[2]); + h = hash_hul(h, addr->u.ip6.s6_addr32[3]); + } else { + h = hash_hul(h, addr->u.ip4.s_addr); + } + return h; +} + +static inline int VarpAddr_eq(VarpAddr *addr1, VarpAddr*addr2) +{ + return memcmp(addr1, addr2, sizeof(VarpAddr)) == 0; +} + +static inline uint32_t Vmac_hash(uint32_t h, Vmac *vmac) +{ + h = hash_hul(h, + (vmac->mac[0] << 24) | + (vmac->mac[1] << 16) | + (vmac->mac[2] << 8) | + (vmac->mac[3] )); + h = hash_hul(h, + (vmac->mac[4] << 8) | + (vmac->mac[5] )); + return h; +} + +static inline int Vmac_eq(Vmac *vmac1, Vmac *vmac2) +{ + return memcmp(vmac1, vmac2, sizeof(Vmac)) == 0; +} + +#endif /* _VNET_VARP_UTIL_H */ diff -r d4d880fcef28 -r b35215021b32 linux-2.6-xen-sparse/include/asm-xen/linux-public/xenbus_dev.h --- a/linux-2.6-xen-sparse/include/asm-xen/linux-public/xenbus_dev.h Fri Sep 9 16:31:36 2005 +++ /dev/null Tue Sep 13 16:14:16 2005 @@ -1,47 +0,0 @@ -/* - * xenbus_dev.h - * - * Copyright (c) 2005, Christian Limpach - * - * This file may be distributed separately from the Linux kernel, or - * incorporated into other software packages, subject to the following license: - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this source file (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 _XENBUS_DEV_H_ -#define _XENBUS_DEV_H_ - -struct xenbus_dev_talkv { - enum xsd_sockmsg_type type; - const struct kvec *iovec; - unsigned int num_vecs; - char *buf; - unsigned int len; -}; - -/* - * @cmd: IOCTL_XENBUS_DEV_TALKV - * @arg: struct xenbus_dev_talkv - * Return: 0 on success, error code on failure. - */ -#define IOCTL_XENBUS_DEV_TALKV \ - _IOC(_IOC_NONE, 'X', 0, sizeof(struct xenbus_dev_talkv)) - -#endif /* _XENBUS_DEV_H_ */ diff -r d4d880fcef28 -r b35215021b32 linux-2.6-xen-sparse/include/asm-xen/synch_bitops.h --- a/linux-2.6-xen-sparse/include/asm-xen/synch_bitops.h Fri Sep 9 16:31:36 2005 +++ /dev/null Tue Sep 13 16:14:16 2005 @@ -1,2 +0,0 @@ - -#include <asm-i386/synch_bitops.h> diff -r d4d880fcef28 -r b35215021b32 tools/examples/xmexample.vmx --- a/tools/examples/xmexample.vmx Fri Sep 9 16:31:36 2005 +++ /dev/null Tue Sep 13 16:14:16 2005 @@ -1,96 +0,0 @@ -# -*- mode: python; -*- -#============================================================================ -# Python configuration setup for 'xm create'. -# This script sets the parameters used when a domain is created using 'xm create'. -# You use a separate script for each domain you want to create, or -# you can set the parameters for the domain on the xm command line. -#============================================================================ - -#---------------------------------------------------------------------------- -# Kernel image file. -kernel = "/usr/lib/xen/boot/vmxloader" - -# The domain build function. VMX domain uses 'vmx'. -builder='vmx' - -# Initial memory allocation (in megabytes) for the new domain. -memory = 128 - -# A name for your domain. All domains must have different names. -name = "ExampleVMXDomain" - -# Which CPU to start domain on? -#cpu = -1 # leave to Xen to pick - -# Optionally define mac and/or bridge for the network interfaces. -# Random MACs are assigned if not given. -#vif = [ 'mac=aa:00:00:00:00:11, bridge=xen-br0' ] - -#---------------------------------------------------------------------------- -# Define the disk devices you want the domain to have access to, and -# what you want them accessible as. -# Each disk entry is of the form phy:UNAME,DEV,MODE -# where UNAME is the device, DEV is the device name the domain will see, -# and MODE is r for read-only, w for read-write. - -#disk = [ 'phy:hda1,hda1,r' ] -disk = [ 'file:/var/images/min-el3-i386.img,ioemu:hda,w' ] - -#---------------------------------------------------------------------------- -# Set according to whether you want the domain restarted when it exits. -# The default is 'onreboot', which restarts the domain when it shuts down -# with exit code reboot. -# Other values are 'always', and 'never'. - -#restart = 'onreboot' - -#============================================================================ - - -# New stuff -device_model = '/usr/lib/xen/bin/qemu-dm' - -# Advanced users only. Don't touch if you don't know what you're doing -memmap = '/usr/lib/xen/boot/mem-map.sxp' - -#----------------------------------------------------------------------------- -# Disk image for -#cdrom= - -#----------------------------------------------------------------------------- -# boot on floppy (a), hard disk (c) or CD-ROM (d) -#boot=[a|c|d] -#----------------------------------------------------------------------------- -# write to temporary files instead of disk image files -#snapshot=1 - -#---------------------------------------------------------------------------- -# enable SDL library for graphics, default = 0 -sdl=0 - -#---------------------------------------------------------------------------- -# enable VNC library for graphics, default = 1 -vnc=1 - -#---------------------------------------------------------------------------- -# enable spawning vncviewer(only valid when vnc=1), default = 1 -vncviewer=1 - -#---------------------------------------------------------------------------- -# no graphics, use serial port -#nographic=0 - - -#----------------------------------------------------------------------------- -# enable audio support -#enable-audio=1 - - -#----------------------------------------------------------------------------- -# set the real time clock to local time [default=0 i.e. set to utc] -#localtime=1 - - -#----------------------------------------------------------------------------- -# start in full screen -#full-screen=1 _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |