[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] merge with xen-unstable.hg
# HG changeset patch # User awilliam@xxxxxxxxxxx # Node ID 2bfd19fc1b79c6a6712c99f875f1fbf883af3f35 # Parent 914c44d10c8d1dc0fd279f6aa1f9ab7d8a65cfcb # Parent 02311d8aba867e2107cdc0c6448c55556def97ad merge with xen-unstable.hg --- tools/debugger/pdb/Domain.ml | 61 tools/debugger/pdb/Domain.mli | 39 tools/debugger/pdb/Intel.ml | 66 tools/debugger/pdb/Makefile | 57 tools/debugger/pdb/OCamlMakefile | 1149 ----------------- tools/debugger/pdb/PDB.ml | 342 ----- tools/debugger/pdb/Process.ml | 79 - tools/debugger/pdb/Process.mli | 41 tools/debugger/pdb/Util.ml | 165 -- tools/debugger/pdb/Xen_domain.ml | 43 tools/debugger/pdb/Xen_domain.mli | 25 tools/debugger/pdb/debugger.ml | 372 ----- tools/debugger/pdb/evtchn.ml | 40 tools/debugger/pdb/evtchn.mli | 19 tools/debugger/pdb/linux-2.6-module/Makefile | 21 tools/debugger/pdb/linux-2.6-module/debug.c | 851 ------------ tools/debugger/pdb/linux-2.6-module/module.c | 337 ---- tools/debugger/pdb/linux-2.6-module/pdb_debug.h | 47 tools/debugger/pdb/linux-2.6-module/pdb_module.h | 142 -- tools/debugger/pdb/linux-2.6-patches/Makefile | 11 tools/debugger/pdb/linux-2.6-patches/i386_ksyms.patch | 18 tools/debugger/pdb/linux-2.6-patches/kdebug.patch | 10 tools/debugger/pdb/linux-2.6-patches/makefile.patch | 10 tools/debugger/pdb/linux-2.6-patches/ptrace.patch | 10 tools/debugger/pdb/linux-2.6-patches/traps.patch | 19 tools/debugger/pdb/pdb_caml_domain.c | 527 ------- tools/debugger/pdb/pdb_caml_evtchn.c | 186 -- tools/debugger/pdb/pdb_caml_process.c | 587 -------- tools/debugger/pdb/pdb_caml_xc.c | 170 -- tools/debugger/pdb/pdb_caml_xcs.c | 307 ---- tools/debugger/pdb/pdb_caml_xen.h | 39 tools/debugger/pdb/pdb_xen.c | 75 - tools/debugger/pdb/readme | 96 - tools/debugger/pdb/server.ml | 241 --- tools/debugger/pdb/xcs.ml | 85 - tools/debugger/pdb/xcs.mli | 13 linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c | 10 linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c | 260 +-- linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c | 1 linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c | 3 linux-2.6-xen-sparse/drivers/xen/netback/loopback.c | 64 linux-2.6-xen-sparse/drivers/xen/netback/netback.c | 2 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c | 14 linux-2.6-xen-sparse/include/xen/public/evtchn.h | 3 tools/blktap/drivers/Makefile | 2 tools/blktap/drivers/blktapctrl.c | 22 tools/blktap/drivers/tapdisk.c | 9 tools/blktap/lib/blktaplib.h | 3 tools/examples/init.d/xendomains | 8 tools/examples/xen-backend.rules | 1 tools/firmware/vmxassist/vm86.c | 34 tools/ioemu/target-i386-dm/helper2.c | 4 tools/libxc/xc_linux.c | 82 + tools/libxc/xenctrl.h | 10 tools/pygrub/src/pygrub | 20 tools/python/xen/util/blkif.py | 2 tools/python/xen/xend/image.py | 3 tools/python/xen/xm/addlabel.py | 72 - tools/python/xen/xm/cfgbootpolicy.py | 73 - tools/python/xen/xm/create.py | 2 tools/python/xen/xm/dry-run.py | 41 tools/python/xen/xm/dumppolicy.py | 20 tools/python/xen/xm/getlabel.py | 29 tools/python/xen/xm/loadpolicy.py | 17 tools/python/xen/xm/main.py | 30 tools/python/xen/xm/makepolicy.py | 15 tools/python/xen/xm/resources.py | 21 tools/python/xen/xm/rmlabel.py | 31 tools/xm-test/tests/vtpm/vtpm_utils.py | 6 xen/arch/ia64/Makefile | 15 xen/arch/powerpc/Makefile | 3 xen/arch/x86/Makefile | 13 xen/arch/x86/domain.c | 11 xen/arch/x86/hvm/hvm.c | 88 - xen/arch/x86/hvm/i8259.c | 66 xen/arch/x86/hvm/instrlen.c | 72 - xen/arch/x86/hvm/intercept.c | 16 xen/arch/x86/hvm/io.c | 7 xen/arch/x86/hvm/platform.c | 14 xen/arch/x86/hvm/svm/emulate.c | 6 xen/arch/x86/hvm/svm/intr.c | 21 xen/arch/x86/hvm/svm/svm.c | 198 +- xen/arch/x86/hvm/svm/x86_32/exits.S | 3 xen/arch/x86/hvm/svm/x86_64/exits.S | 1 xen/arch/x86/hvm/vioapic.c | 22 xen/arch/x86/hvm/vmx/io.c | 14 xen/arch/x86/hvm/vmx/vmx.c | 131 + xen/arch/x86/hvm/vmx/x86_32/exits.S | 3 xen/arch/x86/hvm/vmx/x86_64/exits.S | 1 xen/arch/x86/mm.c | 206 +-- xen/arch/x86/mm/shadow/common.c | 165 +- xen/arch/x86/mm/shadow/multi.c | 433 ++++-- xen/arch/x86/mm/shadow/multi.h | 7 xen/arch/x86/mm/shadow/private.h | 49 xen/arch/x86/mm/shadow/types.h | 31 xen/arch/x86/smp.c | 2 xen/arch/x86/traps.c | 2 xen/arch/x86/x86_32/entry.S | 18 xen/arch/x86/x86_emulate.c | 37 xen/common/gdbstub.c | 30 xen/common/symbols-dummy.c | 16 xen/common/symbols.c | 13 xen/include/asm-x86/debugger.h | 43 xen/include/asm-x86/domain.h | 2 xen/include/asm-x86/guest_access.h | 20 xen/include/asm-x86/hvm/io.h | 1 xen/include/asm-x86/hvm/support.h | 22 xen/include/asm-x86/hvm/vioapic.h | 2 xen/include/asm-x86/hvm/vpic.h | 8 xen/include/asm-x86/mm.h | 2 xen/include/asm-x86/shadow.h | 87 + 111 files changed, 1630 insertions(+), 7485 deletions(-) diff -r 914c44d10c8d -r 2bfd19fc1b79 linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c Sun Oct 01 11:39:41 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c Sun Oct 01 19:10:18 2006 -0600 @@ -273,7 +273,7 @@ static void backend_changed(struct xenbu xenbus_dev_fatal(dev, -ENODEV, "bdget failed"); down(&bd->bd_sem); - if (info->users > 0 && system_state == SYSTEM_RUNNING) + if (info->users > 0) xenbus_dev_error(dev, -EBUSY, "Device in use; refusing to close"); else @@ -355,8 +355,10 @@ static void blkfront_closing(struct xenb blk_stop_queue(info->rq); /* No more gnttab callback work. */ gnttab_cancel_free_callback(&info->callback); + spin_unlock_irqrestore(&blkif_io_lock, flags); + + /* Flush gnttab callback work. Must be done with no locks held. */ flush_scheduled_work(); - spin_unlock_irqrestore(&blkif_io_lock, flags); xlvbd_del(info); @@ -714,8 +716,10 @@ static void blkif_free(struct blkfront_i blk_stop_queue(info->rq); /* No more gnttab callback work. */ gnttab_cancel_free_callback(&info->callback); + spin_unlock_irq(&blkif_io_lock); + + /* Flush gnttab callback work. Must be done with no locks held. */ flush_scheduled_work(); - spin_unlock_irq(&blkif_io_lock); /* Free resources associated with old device channel. */ if (info->ring_ref != GRANT_INVALID_REF) { diff -r 914c44d10c8d -r 2bfd19fc1b79 linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c --- a/linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c Sun Oct 01 11:39:41 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c Sun Oct 01 19:10:18 2006 -0600 @@ -44,7 +44,6 @@ #include <linux/kernel.h> #include <linux/fs.h> #include <linux/mm.h> -#include <linux/miscdevice.h> #include <linux/errno.h> #include <linux/major.h> #include <linux/gfp.h> @@ -54,6 +53,30 @@ #define MAX_TAP_DEV 100 /*the maximum number of tapdisk ring devices */ #define MAX_DEV_NAME 100 /*the max tapdisk ring device name e.g. blktap0 */ + + +struct class *xen_class; +EXPORT_SYMBOL_GPL(xen_class); + +/* + * Setup the xen class. This should probably go in another file, but + * since blktap is the only user of it so far, it gets to keep it. + */ +int setup_xen_class(void) +{ + int ret; + + if (xen_class) + return 0; + + xen_class = class_create(THIS_MODULE, "xen"); + if ((ret = IS_ERR(xen_class))) { + xen_class = NULL; + return ret; + } + + return 0; +} /* * The maximum number of requests that can be outstanding at any time @@ -100,19 +123,14 @@ typedef struct tap_blkif { unsigned long *idx_map; /*Record the user ring id to kern [req id, idx] tuple */ blkif_t *blkif; /*Associate blkif with tapdev */ + int sysfs_set; /*Set if it has a class device. */ } tap_blkif_t; - -/*Private data struct associated with the inode*/ -typedef struct private_info { - int idx; -} private_info_t; /*Data struct handed back to userspace for tapdisk device to VBD mapping*/ typedef struct domid_translate { unsigned short domid; unsigned short busid; } domid_translate_t ; - static domid_translate_t translate_domid[MAX_TAP_DEV]; static tap_blkif_t *tapfds[MAX_TAP_DEV]; @@ -200,14 +218,12 @@ static struct grant_handle_pair + (_i)]) -static int blktap_read_ufe_ring(int idx); /*local prototypes*/ - -#define BLKTAP_MINOR 0 /*/dev/xen/blktap resides at device number - major=254, minor numbers begin at 0 */ -#define BLKTAP_DEV_MAJOR 254 /* TODO: Make major number dynamic * - * and create devices in the kernel * - */ +static int blktap_read_ufe_ring(tap_blkif_t *info); /*local prototypes*/ + +#define BLKTAP_MINOR 0 /*/dev/xen/blktap has a dynamic major */ #define BLKTAP_DEV_DIR "/dev/xen" + +static int blktap_major; /* blktap IOCTLs: */ #define BLKTAP_IOCTL_KICK_FE 1 @@ -264,7 +280,8 @@ static inline int GET_NEXT_REQ(unsigned { int i; for (i = 0; i < MAX_PENDING_REQS; i++) - if (idx_map[i] == INVALID_REQ) return i; + if (idx_map[i] == INVALID_REQ) + return i; return INVALID_REQ; } @@ -311,8 +328,6 @@ static int blktap_ioctl(struct inode *in unsigned int cmd, unsigned long arg); static unsigned int blktap_poll(struct file *file, poll_table *wait); -struct miscdevice *set_misc(int minor, char *name, int dev); - static struct file_operations blktap_fops = { .owner = THIS_MODULE, .poll = blktap_poll, @@ -344,6 +359,16 @@ static int get_next_free_dev(void) done: spin_unlock_irqrestore(&pending_free_lock, flags); + + /* + * We are protected by having the dev_pending set. + */ + if (!tapfds[i]->sysfs_set && xen_class) { + class_device_create(xen_class, NULL, + MKDEV(blktap_major, ret), NULL, + "blktap%d", ret); + tapfds[i]->sysfs_set = 1; + } return ret; } @@ -369,9 +394,8 @@ void signal_tapdisk(int idx) info = tapfds[idx]; if ( (idx > 0) && (idx < MAX_TAP_DEV) && (info->pid > 0) ) { ptask = find_task_by_pid(info->pid); - if (ptask) { + if (ptask) info->status = CLEANSHUTDOWN; - } } info->blkif = NULL; return; @@ -382,7 +406,6 @@ static int blktap_open(struct inode *ino blkif_sring_t *sring; int idx = iminor(inode) - BLKTAP_MINOR; tap_blkif_t *info; - private_info_t *prv; int i; if (tapfds[idx] == NULL) { @@ -410,9 +433,7 @@ static int blktap_open(struct inode *ino SHARED_RING_INIT(sring); FRONT_RING_INIT(&info->ufe_ring, sring, PAGE_SIZE); - prv = kzalloc(sizeof(private_info_t),GFP_KERNEL); - prv->idx = idx; - filp->private_data = prv; + filp->private_data = info; info->vma = NULL; info->idx_map = kmalloc(sizeof(unsigned long) * MAX_PENDING_REQS, @@ -433,17 +454,16 @@ static int blktap_open(struct inode *ino static int blktap_release(struct inode *inode, struct file *filp) { - int idx = iminor(inode) - BLKTAP_MINOR; - tap_blkif_t *info; - - if (tapfds[idx] == NULL) { + tap_blkif_t *info = filp->private_data; + + /* can this ever happen? - sdr */ + if (!info) { WPRINTK("Trying to free device that doesn't exist " - "[/dev/xen/blktap%d]\n",idx); - return -1; - } - info = tapfds[idx]; + "[/dev/xen/blktap%d]\n",iminor(inode) - BLKTAP_MINOR); + return -EBADF; + } info->dev_inuse = 0; - DPRINTK("Freeing device [/dev/xen/blktap%d]\n",idx); + DPRINTK("Freeing device [/dev/xen/blktap%d]\n",info->minor); /* Free the ring page. */ ClearPageReserved(virt_to_page(info->ufe_ring.sring)); @@ -457,8 +477,6 @@ static int blktap_release(struct inode * info->vma = NULL; } - if (filp->private_data) kfree(filp->private_data); - if ( (info->status != CLEANSHUTDOWN) && (info->blkif != NULL) ) { kthread_stop(info->blkif->xenblkd); info->blkif->xenblkd = NULL; @@ -491,16 +509,12 @@ static int blktap_mmap(struct file *filp int size; struct page **map; int i; - private_info_t *prv; - tap_blkif_t *info; - - /*Retrieve the dev info*/ - prv = (private_info_t *)filp->private_data; - if (prv == NULL) { + tap_blkif_t *info = filp->private_data; + + if (info == NULL) { WPRINTK("blktap: mmap, retrieving idx failed\n"); return -ENOMEM; } - info = tapfds[prv->idx]; vma->vm_flags |= VM_RESERVED; vma->vm_ops = &blktap_vm_ops; @@ -556,20 +570,17 @@ static int blktap_ioctl(struct inode *in static int blktap_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { - int idx = iminor(inode) - BLKTAP_MINOR; + tap_blkif_t *info = filp->private_data; + switch(cmd) { case BLKTAP_IOCTL_KICK_FE: { /* There are fe messages to process. */ - return blktap_read_ufe_ring(idx); + return blktap_read_ufe_ring(info); } case BLKTAP_IOCTL_SETMODE: { - tap_blkif_t *info = tapfds[idx]; - - if ( (idx > 0) && (idx < MAX_TAP_DEV) - && (tapfds[idx] != NULL) ) - { + if (info) { if (BLKTAP_MODE_VALID(arg)) { info->mode = arg; /* XXX: may need to flush rings here. */ @@ -582,11 +593,7 @@ static int blktap_ioctl(struct inode *in } case BLKTAP_IOCTL_PRINT_IDXS: { - tap_blkif_t *info = tapfds[idx]; - - if ( (idx > 0) && (idx < MAX_TAP_DEV) - && (tapfds[idx] != NULL) ) - { + if (info) { printk("User Rings: \n-----------\n"); printk("UF: rsp_cons: %2d, req_prod_prv: %2d " "| req_prod: %2d, rsp_prod: %2d\n", @@ -599,11 +606,7 @@ static int blktap_ioctl(struct inode *in } case BLKTAP_IOCTL_SENDPID: { - tap_blkif_t *info = tapfds[idx]; - - if ( (idx > 0) && (idx < MAX_TAP_DEV) - && (tapfds[idx] != NULL) ) - { + if (info) { info->pid = (pid_t)arg; DPRINTK("blktap: pid received %d\n", info->pid); @@ -631,26 +634,38 @@ static int blktap_ioctl(struct inode *in case BLKTAP_IOCTL_FREEINTF: { unsigned long dev = arg; - tap_blkif_t *info = NULL; - - if ( (dev > 0) && (dev < MAX_TAP_DEV) ) info = tapfds[dev]; - + unsigned long flags; + + /* Looking at another device */ + info = NULL; + + if ( (dev > 0) && (dev < MAX_TAP_DEV) ) + info = tapfds[dev]; + + spin_lock_irqsave(&pending_free_lock, flags); if ( (info != NULL) && (info->dev_pending) ) info->dev_pending = 0; + spin_unlock_irqrestore(&pending_free_lock, flags); + return 0; } case BLKTAP_IOCTL_MINOR: { unsigned long dev = arg; - tap_blkif_t *info = NULL; + + /* Looking at another device */ + info = NULL; - if ( (dev > 0) && (dev < MAX_TAP_DEV) ) info = tapfds[dev]; + if ( (dev > 0) && (dev < MAX_TAP_DEV) ) + info = tapfds[dev]; - if (info != NULL) return info->minor; - else return -1; + if (info != NULL) + return info->minor; + else + return -1; } case BLKTAP_IOCTL_MAJOR: - return BLKTAP_DEV_MAJOR; + return blktap_major; case BLKTAP_QUERY_ALLOC_REQS: { @@ -662,25 +677,21 @@ static int blktap_ioctl(struct inode *in return -ENOIOCTLCMD; } -static unsigned int blktap_poll(struct file *file, poll_table *wait) -{ - private_info_t *prv; - tap_blkif_t *info; - - /*Retrieve the dev info*/ - prv = (private_info_t *)file->private_data; - if (prv == NULL) { +static unsigned int blktap_poll(struct file *filp, poll_table *wait) +{ + tap_blkif_t *info = filp->private_data; + + if (!info) { WPRINTK(" poll, retrieving idx failed\n"); return 0; } - - if (prv->idx == 0) return 0; - - info = tapfds[prv->idx]; - - poll_wait(file, &info->wait, wait); + + /* do not work on the control device */ + if (!info->minor) + return 0; + + poll_wait(filp, &info->wait, wait); if (info->ufe_ring.req_prod_pvt != info->ufe_ring.sring->req_prod) { - flush_tlb_all(); RING_PUSH_REQUESTS(&info->ufe_ring); return POLLIN | POLLRDNORM; } @@ -691,11 +702,14 @@ void blktap_kick_user(int idx) { tap_blkif_t *info; - if (idx == 0) return; + if (idx == 0) + return; info = tapfds[idx]; - if (info != NULL) wake_up_interruptible(&info->wait); + if (info != NULL) + wake_up_interruptible(&info->wait); + return; } @@ -713,10 +727,7 @@ static int req_increase(void) { int i, j; struct page *page; - unsigned long flags; int ret; - - spin_lock_irqsave(&pending_free_lock, flags); ret = -EINVAL; if (mmap_alloc >= MAX_PENDING_REQS || mmap_lock) @@ -782,8 +793,7 @@ static int req_increase(void) mmap_alloc++; DPRINTK("# MMAPs increased to %d\n",mmap_alloc); - done: - spin_unlock_irqrestore(&pending_free_lock, flags); +done: return ret; } @@ -811,36 +821,6 @@ static void mmap_req_del(int mmap) mmap_lock = 0; DPRINTK("# MMAPs decreased to %d\n",mmap_alloc); mmap_alloc--; -} - -/*N.B. Currently unused - will be accessed via sysfs*/ -static void req_decrease(void) -{ - pending_req_t *req; - int i; - unsigned long flags; - - spin_lock_irqsave(&pending_free_lock, flags); - - DPRINTK("Req decrease called.\n"); - if (mmap_lock || mmap_alloc == 1) - goto done; - - mmap_lock = 1; - mmap_inuse = MAX_PENDING_REQS; - - /*Go through reqs and remove any that aren't in use*/ - for (i = 0; i < MAX_PENDING_REQS ; i++) { - req = &pending_reqs[mmap_alloc-1][i]; - if (req->inuse == 0) { - list_del(&req->free_list); - mmap_inuse--; - } - } - if (mmap_inuse == 0) mmap_req_del(mmap_alloc-1); - done: - spin_unlock_irqrestore(&pending_free_lock, flags); - return; } static pending_req_t* alloc_req(void) @@ -1002,7 +982,7 @@ int tap_blkif_schedule(void *arg) * COMPLETION CALLBACK -- Called by user level ioctl() */ -static int blktap_read_ufe_ring(int idx) +static int blktap_read_ufe_ring(tap_blkif_t *info) { /* This is called to read responses from the UFE ring. */ RING_IDX i, j, rp; @@ -1010,12 +990,9 @@ static int blktap_read_ufe_ring(int idx) blkif_t *blkif=NULL; int pending_idx, usr_idx, mmap_idx; pending_req_t *pending_req; - tap_blkif_t *info; - - info = tapfds[idx]; - if (info == NULL) { + + if (!info) return 0; - } /* We currently only forward packets in INTERCEPT_FE mode. */ if (!(info->mode & BLKTAP_MODE_INTERCEPT_FE)) @@ -1063,7 +1040,7 @@ static int blktap_read_ufe_ring(int idx) >> PAGE_SHIFT; map[offset] = NULL; } - fast_flush_area(pending_req, pending_idx, usr_idx, idx); + fast_flush_area(pending_req, pending_idx, usr_idx, info->minor); make_response(blkif, pending_req->id, resp->operation, resp->status); info->idx_map[usr_idx] = INVALID_REQ; @@ -1416,7 +1393,8 @@ static int __init blkif_init(void) /*Create the blktap devices, but do not map memory or waitqueue*/ for(i = 0; i < MAX_TAP_DEV; i++) translate_domid[i].domid = 0xFFFF; - ret = register_chrdev(BLKTAP_DEV_MAJOR,"blktap",&blktap_fops); + /* Dynamically allocate a major for this device */ + ret = register_chrdev(0, "blktap", &blktap_fops); blktap_dir = devfs_mk_dir(NULL, "xen", 0, NULL); if ( (ret < 0)||(blktap_dir < 0) ) { @@ -1424,22 +1402,44 @@ static int __init blkif_init(void) return -ENOMEM; } + blktap_major = ret; + for(i = 0; i < MAX_TAP_DEV; i++ ) { info = tapfds[i] = kzalloc(sizeof(tap_blkif_t),GFP_KERNEL); - if(tapfds[i] == NULL) return -ENOMEM; + if(tapfds[i] == NULL) + return -ENOMEM; info->minor = i; info->pid = 0; info->blkif = NULL; - ret = devfs_mk_cdev(MKDEV(BLKTAP_DEV_MAJOR, i), + ret = devfs_mk_cdev(MKDEV(blktap_major, i), S_IFCHR|S_IRUGO|S_IWUSR, "xen/blktap%d", i); - if(ret != 0) return -ENOMEM; + if(ret != 0) + return -ENOMEM; info->dev_pending = info->dev_inuse = 0; DPRINTK("Created misc_dev [/dev/xen/blktap%d]\n",i); } + /* Make sure the xen class exists */ + if (!setup_xen_class()) { + /* + * This will allow udev to create the blktap ctrl device. + * We only want to create blktap0 first. We don't want + * to flood the sysfs system with needless blktap devices. + * We only create the device when a request of a new device is + * made. + */ + class_device_create(xen_class, NULL, + MKDEV(blktap_major, 0), NULL, + "blktap0"); + tapfds[0]->sysfs_set = 1; + } else { + /* this is bad, but not fatal */ + WPRINTK("blktap: sysfs xen_class not created\n"); + } + DPRINTK("Blktap device successfully created\n"); return 0; diff -r 914c44d10c8d -r 2bfd19fc1b79 linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c --- a/linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c Sun Oct 01 11:39:41 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c Sun Oct 01 19:10:18 2006 -0600 @@ -273,7 +273,6 @@ static void tap_frontend_changed(struct kthread_stop(be->blkif->xenblkd); be->blkif->xenblkd = NULL; } - tap_blkif_unmap(be->blkif); xenbus_switch_state(dev, XenbusStateClosing); break; diff -r 914c44d10c8d -r 2bfd19fc1b79 linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c --- a/linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c Sun Oct 01 11:39:41 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c Sun Oct 01 19:10:18 2006 -0600 @@ -419,10 +419,9 @@ static struct file_operations evtchn_fop }; static struct miscdevice evtchn_miscdev = { - .minor = EVTCHN_MINOR, + .minor = MISC_DYNAMIC_MINOR, .name = "evtchn", .fops = &evtchn_fops, - .devfs_name = "misc/evtchn", }; static int __init evtchn_init(void) diff -r 914c44d10c8d -r 2bfd19fc1b79 linux-2.6-xen-sparse/drivers/xen/netback/loopback.c --- a/linux-2.6-xen-sparse/drivers/xen/netback/loopback.c Sun Oct 01 11:39:41 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/loopback.c Sun Oct 01 19:10:18 2006 -0600 @@ -53,8 +53,10 @@ #include <linux/skbuff.h> #include <linux/ethtool.h> #include <net/dst.h> - -static int nloopbacks = 8; +#include <net/xfrm.h> /* secpath_reset() */ +#include <asm/hypervisor.h> /* is_initial_xendomain() */ + +static int nloopbacks = -1; module_param(nloopbacks, int, 0); MODULE_PARM_DESC(nloopbacks, "Number of netback-loopback devices to create"); @@ -77,9 +79,59 @@ static int loopback_close(struct net_dev return 0; } +#ifdef CONFIG_X86 +static int is_foreign(unsigned long pfn) +{ + /* NB. Play it safe for auto-translation mode. */ + return (xen_feature(XENFEAT_auto_translated_physmap) || + (phys_to_machine_mapping[pfn] & FOREIGN_FRAME_BIT)); +} +#else +/* How to detect a foreign mapping? Play it safe. */ +#define is_foreign(pfn) (1) +#endif + +static int skb_remove_foreign_references(struct sk_buff *skb) +{ + struct page *page; + unsigned long pfn; + int i, off; + char *vaddr; + + BUG_ON(skb_shinfo(skb)->frag_list); + + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + pfn = page_to_pfn(skb_shinfo(skb)->frags[i].page); + if (!is_foreign(pfn)) + continue; + + page = alloc_page(GFP_ATOMIC | __GFP_NOWARN); + if (unlikely(!page)) + return 0; + + vaddr = kmap_skb_frag(&skb_shinfo(skb)->frags[i]); + off = skb_shinfo(skb)->frags[i].page_offset; + memcpy(page_address(page) + off, + vaddr + off, + skb_shinfo(skb)->frags[i].size); + kunmap_skb_frag(vaddr); + + put_page(skb_shinfo(skb)->frags[i].page); + skb_shinfo(skb)->frags[i].page = page; + } + + return 1; +} + static int loopback_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct net_private *np = netdev_priv(dev); + + if (!skb_remove_foreign_references(skb)) { + np->stats.tx_dropped++; + dev_kfree_skb(skb); + return 0; + } dst_release(skb->dst); skb->dst = NULL; @@ -110,6 +162,11 @@ static int loopback_start_xmit(struct sk skb->protocol = eth_type_trans(skb, dev); skb->dev = dev; dev->last_rx = jiffies; + + /* Flush netfilter context: rx'ed skbuffs not expected to have any. */ + nf_reset(skb); + secpath_reset(skb); + netif_rx(skb); return 0; @@ -239,6 +296,9 @@ static int __init loopback_init(void) { int i, err = 0; + if (nloopbacks == -1) + nloopbacks = is_initial_xendomain() ? 4 : 0; + for (i = 0; i < nloopbacks; i++) if ((err = make_loopback(i)) != 0) break; diff -r 914c44d10c8d -r 2bfd19fc1b79 linux-2.6-xen-sparse/drivers/xen/netback/netback.c --- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Sun Oct 01 11:39:41 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Sun Oct 01 19:10:18 2006 -0600 @@ -217,7 +217,7 @@ static struct sk_buff *netbk_copy_skb(st copy = len >= PAGE_SIZE ? PAGE_SIZE : len; zero = len >= PAGE_SIZE ? 0 : __GFP_ZERO; - page = alloc_page(GFP_ATOMIC | zero); + page = alloc_page(GFP_ATOMIC | __GFP_NOWARN | zero); if (unlikely(!page)) goto err_free; diff -r 914c44d10c8d -r 2bfd19fc1b79 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Sun Oct 01 11:39:41 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Sun Oct 01 19:10:18 2006 -0600 @@ -322,6 +322,20 @@ static void otherend_changed(struct xenb DPRINTK("state is %d (%s), %s, %s", state, xenbus_strstate(state), dev->otherend_watch.node, vec[XS_WATCH_PATH]); + /* + * Ignore xenbus transitions during shutdown. This prevents us doing + * work that can fail e.g., when the rootfs is gone. + */ + if (system_state > SYSTEM_RUNNING) { + struct xen_bus_type *bus = bus; + bus = container_of(dev->dev.bus, struct xen_bus_type, bus); + /* If we're frontend, drive the state machine to Closed. */ + /* This should cause the backend to release our resources. */ + if ((bus == &xenbus_frontend) && (state == XenbusStateClosing)) + xenbus_frontend_closed(dev); + return; + } + if (drv->otherend_changed) drv->otherend_changed(dev, state); } diff -r 914c44d10c8d -r 2bfd19fc1b79 linux-2.6-xen-sparse/include/xen/public/evtchn.h --- a/linux-2.6-xen-sparse/include/xen/public/evtchn.h Sun Oct 01 11:39:41 2006 -0600 +++ b/linux-2.6-xen-sparse/include/xen/public/evtchn.h Sun Oct 01 19:10:18 2006 -0600 @@ -32,9 +32,6 @@ #ifndef __LINUX_PUBLIC_EVTCHN_H__ #define __LINUX_PUBLIC_EVTCHN_H__ - -/* /dev/xen/evtchn resides at device number major=10, minor=201 */ -#define EVTCHN_MINOR 201 /* * Bind a fresh port to VIRQ @virq. diff -r 914c44d10c8d -r 2bfd19fc1b79 tools/blktap/drivers/Makefile --- a/tools/blktap/drivers/Makefile Sun Oct 01 11:39:41 2006 -0600 +++ b/tools/blktap/drivers/Makefile Sun Oct 01 19:10:18 2006 -0600 @@ -28,7 +28,7 @@ THREADLIB := -lpthread -lz THREADLIB := -lpthread -lz LIBS := -L. -L.. -L../lib LIBS += -L$(XEN_LIBXC) -LIBS += -lblktap +LIBS += -lblktap -lxenctrl LIBS += -lcrypto LIBS += -lz LIBS += -L$(XEN_XENSTORE) -lxenstore diff -r 914c44d10c8d -r 2bfd19fc1b79 tools/blktap/drivers/blktapctrl.c --- a/tools/blktap/drivers/blktapctrl.c Sun Oct 01 11:39:41 2006 -0600 +++ b/tools/blktap/drivers/blktapctrl.c Sun Oct 01 19:10:18 2006 -0600 @@ -67,6 +67,8 @@ int max_timeout = MAX_TIMEOUT; int max_timeout = MAX_TIMEOUT; int ctlfd = 0; +int blktap_major; + static int open_ctrl_socket(char *devname); static int write_msg(int fd, int msgtype, void *ptr, void *ptr2); static int read_msg(int fd, int msgtype, void *ptr); @@ -108,7 +110,18 @@ static void make_blktap_dev(char *devnam if (mknod(devname, S_IFCHR|0600, makedev(major, minor)) == 0) DPRINTF("Created %s device\n",devname); - } else DPRINTF("%s device already exists\n",devname); + } else { + DPRINTF("%s device already exists\n",devname); + /* it already exists, but is it the same major number */ + if (((st.st_rdev>>8) & 0xff) != major) { + DPRINTF("%s has old major %d\n", + devname, + (unsigned int)((st.st_rdev >> 8) & 0xff)); + /* only try again if we succed in deleting it */ + if (!unlink(devname)) + make_blktap_dev(devname, major, minor); + } + } } static int get_new_dev(int *major, int *minor, blkif_t *blkif) @@ -644,9 +657,12 @@ int main(int argc, char *argv[]) register_new_devmap_hook(map_new_blktapctrl); register_new_unmap_hook(unmap_blktapctrl); - /*Attach to blktap0 */ + /* Attach to blktap0 */ asprintf(&devname,"%s/%s0", BLKTAP_DEV_DIR, BLKTAP_DEV_NAME); - make_blktap_dev(devname,254,0); + if ((ret = xc_find_device_number("blktap0")) < 0) + goto open_failed; + blktap_major = major(ret); + make_blktap_dev(devname,blktap_major,0); ctlfd = open(devname, O_RDWR); if (ctlfd == -1) { DPRINTF("blktap0 open failed\n"); diff -r 914c44d10c8d -r 2bfd19fc1b79 tools/blktap/drivers/tapdisk.c --- a/tools/blktap/drivers/tapdisk.c Sun Oct 01 11:39:41 2006 -0600 +++ b/tools/blktap/drivers/tapdisk.c Sun Oct 01 19:10:18 2006 -0600 @@ -271,7 +271,6 @@ static int read_msg(char *buf) int length, len, msglen, tap_fd, *io_fd; char *ptr, *path; image_t *img; - struct timeval timeout; msg_hdr_t *msg; msg_newdev_t *msg_dev; msg_pid_t *msg_pid; @@ -579,8 +578,7 @@ int main(int argc, char *argv[]) { int len, msglen, ret; char *p, *buf; - fd_set readfds, writefds; - struct timeval timeout; + fd_set readfds, writefds; fd_list_entry_t *ptr; struct tap_disk *drv; struct td_state *s; @@ -622,12 +620,9 @@ int main(int argc, char *argv[]) /*Set all tap fds*/ LOCAL_FD_SET(&readfds); - timeout.tv_sec = 0; - timeout.tv_usec = 1000; - /*Wait for incoming messages*/ ret = select(maxfds + 1, &readfds, (fd_set *) 0, - (fd_set *) 0, &timeout); + (fd_set *) 0, NULL); if (ret > 0) { diff -r 914c44d10c8d -r 2bfd19fc1b79 tools/blktap/lib/blktaplib.h --- a/tools/blktap/lib/blktaplib.h Sun Oct 01 11:39:41 2006 -0600 +++ b/tools/blktap/lib/blktaplib.h Sun Oct 01 19:10:18 2006 -0600 @@ -80,8 +80,9 @@ static inline int BLKTAP_MODE_VALID(unsi #define MAX_PENDING_REQS 64 #define BLKTAP_DEV_DIR "/dev/xen" #define BLKTAP_DEV_NAME "blktap" -#define BLKTAP_DEV_MAJOR 254 #define BLKTAP_DEV_MINOR 0 + +extern int blktap_major; #define BLKTAP_RING_PAGES 1 /* Front */ #define BLKTAP_MMAP_REGION_SIZE (BLKTAP_RING_PAGES + MMAP_PAGES) diff -r 914c44d10c8d -r 2bfd19fc1b79 tools/examples/init.d/xendomains --- a/tools/examples/init.d/xendomains Sun Oct 01 11:39:41 2006 -0600 +++ b/tools/examples/init.d/xendomains Sun Oct 01 19:10:18 2006 -0600 @@ -352,9 +352,9 @@ stop() if test $? -ne 0; then rc_failed $? echo -n '!' - kill $WDOG_PIG >/dev/null 2>&1 - else - kill $WDOG_PIG >/dev/null 2>&1 + kill $WDOG_PID >/dev/null 2>&1 + else + kill $WDOG_PID >/dev/null 2>&1 continue fi fi @@ -368,7 +368,7 @@ stop() rc_failed $? echo -n '!' fi - kill $WDOG_PIG >/dev/null 2>&1 + kill $WDOG_PID >/dev/null 2>&1 fi done < <(xm list | grep -v '^Name') diff -r 914c44d10c8d -r 2bfd19fc1b79 tools/examples/xen-backend.rules --- a/tools/examples/xen-backend.rules Sun Oct 01 11:39:41 2006 -0600 +++ b/tools/examples/xen-backend.rules Sun Oct 01 19:10:18 2006 -0600 @@ -5,3 +5,4 @@ SUBSYSTEM=="xen-backend", KERNEL=="vif*" SUBSYSTEM=="xen-backend", KERNEL=="vif*", ACTION=="offline", RUN+="$env{script} offline" SUBSYSTEM=="xen-backend", ACTION=="remove", RUN+="/etc/xen/scripts/xen-hotplug-cleanup" KERNEL=="evtchn", NAME="xen/%k" +KERNEL=="blktap[0-9]*", NAME="xen/%k" diff -r 914c44d10c8d -r 2bfd19fc1b79 tools/firmware/vmxassist/vm86.c --- a/tools/firmware/vmxassist/vm86.c Sun Oct 01 11:39:41 2006 -0600 +++ b/tools/firmware/vmxassist/vm86.c Sun Oct 01 19:10:18 2006 -0600 @@ -68,7 +68,7 @@ guest_linear_to_real(uint32_t base) return base; if (!(oldctx.cr4 & CR4_PAE)) { - l1_mfn = ((uint32_t *)gcr3)[(base >> 22) & 0x3ff]; + l1_mfn = ((uint32_t *)(long)gcr3)[(base >> 22) & 0x3ff]; if (!(l1_mfn & PT_ENTRY_PRESENT)) panic("l2 entry not present\n"); @@ -79,19 +79,19 @@ guest_linear_to_real(uint32_t base) l1_mfn &= 0xfffff000; - l0_mfn = ((uint32_t *)l1_mfn)[(base >> 12) & 0x3ff]; + l0_mfn = ((uint32_t *)(long)l1_mfn)[(base >> 12) & 0x3ff]; if (!(l0_mfn & PT_ENTRY_PRESENT)) panic("l1 entry not present\n"); l0_mfn &= 0xfffff000; return l0_mfn + (base & 0xfff); } else { - l2_mfn = ((uint64_t *)gcr3)[(base >> 30) & 0x3]; + l2_mfn = ((uint64_t *)(long)gcr3)[(base >> 30) & 0x3]; if (!(l2_mfn & PT_ENTRY_PRESENT)) panic("l3 entry not present\n"); l2_mfn &= 0x3fffff000ULL; - l1_mfn = ((uint64_t *)l2_mfn)[(base >> 21) & 0x1ff]; + l1_mfn = ((uint64_t *)(long)l2_mfn)[(base >> 21) & 0x1ff]; if (!(l1_mfn & PT_ENTRY_PRESENT)) panic("l2 entry not present\n"); @@ -102,7 +102,7 @@ guest_linear_to_real(uint32_t base) l1_mfn &= 0x3fffff000ULL; - l0_mfn = ((uint64_t *)l1_mfn)[(base >> 12) & 0x1ff]; + l0_mfn = ((uint64_t *)(long)l1_mfn)[(base >> 12) & 0x1ff]; if (!(l0_mfn & PT_ENTRY_PRESENT)) panic("l1 entry not present\n"); l0_mfn &= 0x3fffff000ULL; @@ -1230,6 +1230,18 @@ pushrm(struct regs *regs, int prefix, un enum { OPC_INVALID, OPC_EMULATED }; +#define rdmsr(msr,val1,val2) \ + __asm__ __volatile__( \ + "rdmsr" \ + : "=a" (val1), "=d" (val2) \ + : "c" (msr)) + +#define wrmsr(msr,val1,val2) \ + __asm__ __volatile__( \ + "wrmsr" \ + : /* no outputs */ \ + : "c" (msr), "a" (val1), "d" (val2)) + /* * Emulate a single instruction, including all its prefixes. We only implement * a small subset of the opcodes, and not all opcodes are implemented for each @@ -1288,6 +1300,12 @@ opcode(struct regs *regs) if (!movcr(regs, prefix, opc)) goto invalid; return OPC_EMULATED; + case 0x30: /* WRMSR */ + wrmsr(regs->ecx, regs->eax, regs->edx); + return OPC_EMULATED; + case 0x32: /* RDMSR */ + rdmsr(regs->ecx, regs->eax, regs->edx); + return OPC_EMULATED; default: goto invalid; } @@ -1412,12 +1430,14 @@ opcode(struct regs *regs) { int addr, data; int seg = segment(prefix, regs, regs->vds); + int offset = prefix & ADDR32? fetch32(regs) : fetch16(regs); + if (prefix & DATA32) { - addr = address(regs, seg, fetch32(regs)); + addr = address(regs, seg, offset); data = read32(addr); setreg32(regs, 0, data); } else { - addr = address(regs, seg, fetch16(regs)); + addr = address(regs, seg, offset); data = read16(addr); setreg16(regs, 0, data); } diff -r 914c44d10c8d -r 2bfd19fc1b79 tools/ioemu/target-i386-dm/helper2.c --- a/tools/ioemu/target-i386-dm/helper2.c Sun Oct 01 11:39:41 2006 -0600 +++ b/tools/ioemu/target-i386-dm/helper2.c Sun Oct 01 19:10:18 2006 -0600 @@ -520,8 +520,8 @@ int main_loop(void) } } - /* Wait up to 100 msec. */ - main_loop_wait(100); + /* Wait up to 10 msec. */ + main_loop_wait(10); if (env->send_event) { env->send_event = 0; diff -r 914c44d10c8d -r 2bfd19fc1b79 tools/libxc/xc_linux.c --- a/tools/libxc/xc_linux.c Sun Oct 01 11:39:41 2006 -0600 +++ b/tools/libxc/xc_linux.c Sun Oct 01 19:10:18 2006 -0600 @@ -133,27 +133,95 @@ int do_xen_hypercall(int xc_handle, priv (unsigned long)hypercall); } +#define MTAB "/proc/mounts" +#define MAX_PATH 255 +#define _STR(x) #x +#define STR(x) _STR(x) + +static int find_sysfsdir(char *sysfsdir) +{ + FILE *fp; + char type[MAX_PATH + 1]; + + if ( (fp = fopen(MTAB, "r")) == NULL ) + return -1; + + while ( fscanf(fp, "%*s %" + STR(MAX_PATH) + "s %" + STR(MAX_PATH) + "s %*s %*d %*d\n", + sysfsdir, type) == 2 ) + { + if ( strncmp(type, "sysfs", 5) == 0 ) + break; + } + + fclose(fp); + + return ((strncmp(type, "sysfs", 5) == 0) ? 0 : -1); +} + +int xc_find_device_number(const char *name) +{ + FILE *fp; + int i, major, minor; + char sysfsdir[MAX_PATH + 1]; + static char *classlist[] = { "xen", "misc" }; + + for ( i = 0; i < (sizeof(classlist) / sizeof(classlist[0])); i++ ) + { + if ( find_sysfsdir(sysfsdir) < 0 ) + goto not_found; + + /* <base>/class/<classname>/<devname>/dev */ + strncat(sysfsdir, "/class/", MAX_PATH); + strncat(sysfsdir, classlist[i], MAX_PATH); + strncat(sysfsdir, "/", MAX_PATH); + strncat(sysfsdir, name, MAX_PATH); + strncat(sysfsdir, "/dev", MAX_PATH); + + if ( (fp = fopen(sysfsdir, "r")) != NULL ) + goto found; + } + + not_found: + errno = -ENOENT; + return -1; + + found: + if ( fscanf(fp, "%d:%d", &major, &minor) != 2 ) + { + fclose(fp); + goto not_found; + } + + fclose(fp); + + return makedev(major, minor); +} + #define EVTCHN_DEV_NAME "/dev/xen/evtchn" -#define EVTCHN_DEV_MAJOR 10 -#define EVTCHN_DEV_MINOR 201 int xc_evtchn_open(void) { struct stat st; int fd; + int devnum; + + devnum = xc_find_device_number("evtchn"); /* Make sure any existing device file links to correct device. */ - if ((lstat(EVTCHN_DEV_NAME, &st) != 0) || !S_ISCHR(st.st_mode) || - (st.st_rdev != makedev(EVTCHN_DEV_MAJOR, EVTCHN_DEV_MINOR))) + if ( (lstat(EVTCHN_DEV_NAME, &st) != 0) || !S_ISCHR(st.st_mode) || + (st.st_rdev != devnum) ) (void)unlink(EVTCHN_DEV_NAME); -reopen: + reopen: if ( (fd = open(EVTCHN_DEV_NAME, O_RDWR)) == -1 ) { if ( (errno == ENOENT) && ((mkdir("/dev/xen", 0755) == 0) || (errno == EEXIST)) && - (mknod(EVTCHN_DEV_NAME, S_IFCHR|0600, - makedev(EVTCHN_DEV_MAJOR, EVTCHN_DEV_MINOR)) == 0) ) + (mknod(EVTCHN_DEV_NAME, S_IFCHR|0600, devnum) == 0) ) goto reopen; PERROR("Could not open event channel interface"); diff -r 914c44d10c8d -r 2bfd19fc1b79 tools/libxc/xenctrl.h --- a/tools/libxc/xenctrl.h Sun Oct 01 11:39:41 2006 -0600 +++ b/tools/libxc/xenctrl.h Sun Oct 01 19:10:18 2006 -0600 @@ -92,6 +92,16 @@ int xc_interface_close(int xc_handle); int xc_interface_close(int xc_handle); /* + * KERNEL INTERFACES + */ + +/* + * Resolve a kernel device name (e.g., "evtchn", "blktap0") into a kernel + * device number. Returns -1 on error (and sets errno). + */ +int xc_find_device_number(const char *name); + +/* * DOMAIN DEBUGGING FUNCTIONS */ diff -r 914c44d10c8d -r 2bfd19fc1b79 tools/pygrub/src/pygrub --- a/tools/pygrub/src/pygrub Sun Oct 01 11:39:41 2006 -0600 +++ b/tools/pygrub/src/pygrub Sun Oct 01 19:10:18 2006 -0600 @@ -25,7 +25,18 @@ import grub.GrubConf import grub.GrubConf import grub.fsys -PYGRUB_VER = 0.4 +PYGRUB_VER = 0.5 + +def enable_cursor(ison): + if ison: + val = 2 + else: + val = 0 + + try: + curses.curs_set(val) + except _curses.error: + pass def is_disk_image(file): fd = os.open(file, os.O_RDONLY) @@ -141,10 +152,7 @@ class Grub: self.screen.timeout(1000) if hasattr(curses, 'use_default_colors'): curses.use_default_colors() - try: - curses.curs_set(0) - except _curses.error: - pass + enable_cursor(False) self.entry_win = curses.newwin(10, 74, 2, 1) self.text_win = curses.newwin(10, 70, 12, 5) @@ -247,6 +255,7 @@ class Grub: self.screen.refresh() t = GrubLineEditor(self.screen, 5, 2, line) + enable_cursor(True) ret = t.edit() if ret: return ret @@ -262,6 +271,7 @@ class Grub: lines = [] while 1: t = GrubLineEditor(self.screen, y, 2) + enable_cursor(True) ret = t.edit() if ret: if ret in ("quit", "return"): diff -r 914c44d10c8d -r 2bfd19fc1b79 tools/python/xen/util/blkif.py --- a/tools/python/xen/util/blkif.py Sun Oct 01 11:39:41 2006 -0600 +++ b/tools/python/xen/util/blkif.py Sun Oct 01 19:10:18 2006 -0600 @@ -67,6 +67,8 @@ def blkdev_uname_to_file(uname): (typ, fn) = uname.split(":") if typ == "phy" and not fn.startswith("/"): fn = "/dev/%s" %(fn,) + if typ == "tap": + (typ, fn) = fn.split(":", 1) return fn def mount_mode(name): diff -r 914c44d10c8d -r 2bfd19fc1b79 tools/python/xen/xend/image.py --- a/tools/python/xen/xend/image.py Sun Oct 01 11:39:41 2006 -0600 +++ b/tools/python/xen/xend/image.py Sun Oct 01 19:10:18 2006 -0600 @@ -244,7 +244,8 @@ class HVMImageHandler(ImageHandler): info = xc.xeninfo() if not 'hvm' in info['xen_caps']: - raise VmError("Not an HVM capable platform, we stop creating!") + raise VmError("HVM guest support is unavailable: is VT/AMD-V " + "supported by your CPU and enabled in your BIOS?") self.dmargs = self.parseDeviceModelArgs(imageConfig, deviceConfig) self.device_model = sxp.child_value(imageConfig, 'device_model') diff -r 914c44d10c8d -r 2bfd19fc1b79 tools/python/xen/xm/addlabel.py --- a/tools/python/xen/xm/addlabel.py Sun Oct 01 11:39:41 2006 -0600 +++ b/tools/python/xen/xm/addlabel.py Sun Oct 01 19:10:18 2006 -0600 @@ -115,43 +115,45 @@ def add_domain_label(label, configfile, config_fd.close() -def main (argv): +def main(argv): + policyref = None + if len(argv) not in (4, 5): + raise OptionError('Needs either 2 or 3 arguments') + + label = argv[1] + + if len(argv) == 5: + policyref = argv[4] + elif security.on(): + policyref = security.active_policy + else: + raise OptionError("No active policy. Must specify policy on the " + "command line.") + + if argv[2].lower() == "dom": + configfile = argv[3] + if configfile[0] != '/': + for prefix in [".", "/etc/xen"]: + configfile = prefix + "/" + configfile + if os.path.isfile(configfile): + break + if not validate_config_file(configfile): + raise OptionError('Invalid config file') + else: + add_domain_label(label, configfile, policyref) + elif argv[2].lower() == "res": + resource = argv[3] + add_resource_label(label, resource, policyref) + else: + raise OptionError('Need to specify either "dom" or "res" as ' + 'object to add label to.') + +if __name__ == '__main__': try: - policyref = None - if len(argv) not in (4, 5): - raise OptionError('Needs either 2 or 3 arguments') - - label = argv[1] - - if len(argv) == 5: - policyref = argv[4] - elif security.on(): - policyref = security.active_policy - else: - security.err("No active policy. Policy must be specified in command line.") - - if argv[2].lower() == "dom": - configfile = argv[3] - if configfile[0] != '/': - for prefix in [".", "/etc/xen"]: - configfile = prefix + "/" + configfile - if os.path.isfile(configfile): - break - if not validate_config_file(configfile): - raise OptionError('Invalid config file') - else: - add_domain_label(label, configfile, policyref) - elif argv[2].lower() == "res": - resource = argv[3] - add_resource_label(label, resource, policyref) - else: - raise OptionError('Need to specify either "dom" or "res" as object to add label to.') - - except security.ACMError: + main(sys.argv) + except Exception, e: + sys.stderr.write('Error: %s\n' % str(e)) sys.exit(-1) - -if __name__ == '__main__': - main(sys.argv) diff -r 914c44d10c8d -r 2bfd19fc1b79 tools/python/xen/xm/cfgbootpolicy.py --- a/tools/python/xen/xm/cfgbootpolicy.py Sun Oct 01 11:39:41 2006 -0600 +++ b/tools/python/xen/xm/cfgbootpolicy.py Sun Oct 01 19:10:18 2006 -0600 @@ -140,44 +140,41 @@ def insert_policy(boot_file, kernel_vers def main(argv): - try: - user_kver = None - policy = None - if len(argv) == 2: - policy = argv[1] - elif len(argv) == 3: - policy = argv[1] - user_kver = argv[2] + user_kver = None + policy = None + if len(argv) == 2: + policy = argv[1] + elif len(argv) == 3: + policy = argv[1] + user_kver = argv[2] + else: + raise OptionError('Invalid number of arguments') + + if not policy_name_re.match(policy): + raise OptionError("Illegal policy name: '%s'" % policy) + + policy_file = '/'.join([policy_dir_prefix] + policy.split('.')) + src_binary_policy_file = policy_file + ".bin" + #check if .bin exists or if policy file exists + if not os.path.isfile(src_binary_policy_file): + if not os.path.isfile(policy_file + "-security_policy.xml"): + raise OptionError("Unknown policy '%s'" % policy) else: - raise OptionError('Invalid number of arguments') - - if not policy_name_re.match(policy): - err("Illegal policy name \'" + policy + "\'") - - policy_file = policy_dir_prefix + "/" + string.join(string.split(policy, "."), "/") - src_binary_policy_file = policy_file + ".bin" - #check if .bin exists or if policy file exists - if not os.path.isfile(src_binary_policy_file): - if not os.path.isfile(policy_file + "-security_policy.xml"): - err("Unknown policy \'" + policy +"\'") - else: - err("Cannot find binary file for policy \'" + policy + - "\'. Please use makepolicy to create binary file.") - dst_binary_policy_file = "/boot/" + policy + ".bin" - shutil.copyfile(src_binary_policy_file, dst_binary_policy_file) - - kernel_version = determine_kernelversion(user_kver) - insert_policy(boot_filename, kernel_version, policy) - print "Boot entry created and \'%s\' copied to /boot" % (policy + ".bin") - - except ACMError: - sys.exit(-1) - except: - traceback.print_exc(limit=1) - sys.exit(-1) - - + err_msg = "Cannot find binary file for policy '%s'." % policy + err_msg += " Please use makepolicy to create binary file." + raise OptionError(err_msg) + + dst_binary_policy_file = "/boot/" + policy + ".bin" + shutil.copyfile(src_binary_policy_file, dst_binary_policy_file) + + kernel_version = determine_kernelversion(user_kver) + insert_policy(boot_filename, kernel_version, policy) + print "Boot entry created and \'%s\' copied to /boot" % (policy + ".bin") if __name__ == '__main__': - main(sys.argv) - + try: + main(sys.argv) + except Exception, e: + sys.stderr.write('Error: ' + str(e) + '\n') + sys.exit(-1) + diff -r 914c44d10c8d -r 2bfd19fc1b79 tools/python/xen/xm/create.py --- a/tools/python/xen/xm/create.py Sun Oct 01 11:39:41 2006 -0600 +++ b/tools/python/xen/xm/create.py Sun Oct 01 19:10:18 2006 -0600 @@ -693,7 +693,7 @@ def make_config(vals): config_image = run_bootloader(vals, config_image) config.append(['bootloader', vals.bootloader]) if vals.bootargs: - config.append(['bootloader_args'], vals.bootargs) + config.append(['bootloader_args', vals.bootargs]) config.append(['image', config_image]) config_devs = [] diff -r 914c44d10c8d -r 2bfd19fc1b79 tools/python/xen/xm/dry-run.py --- a/tools/python/xen/xm/dry-run.py Sun Oct 01 11:39:41 2006 -0600 +++ b/tools/python/xen/xm/dry-run.py Sun Oct 01 19:10:18 2006 -0600 @@ -32,27 +32,26 @@ def help(): individually along with the final security decision.""" def main (argv): - try: - if len(argv) != 2: - raise OptionError('Invalid number of arguments') - - passed = 0 - (opts, config) = create.parseCommandLine(argv) - if create.check_domain_label(config, verbose=1): - if create.config_security_check(config, verbose=1): - passed = 1 - else: - print "Checking resources: (skipped)" - - if passed: - print "Dry Run: PASSED" - else: - print "Dry Run: FAILED" - sys.exit(-1) - - except security.ACMError: + if len(argv) != 2: + raise OptionError('Invalid number of arguments') + + passed = 0 + (opts, config) = create.parseCommandLine(argv) + if create.check_domain_label(config, verbose=1): + if create.config_security_check(config, verbose=1): + passed = 1 + else: + print "Checking resources: (skipped)" + + if passed: + print "Dry Run: PASSED" + else: + print "Dry Run: FAILED" sys.exit(-1) - if __name__ == '__main__': - main(sys.argv) + try: + main(sys.argv) + except Exception, e: + sys.stderr.write('Error: %s\n' % str(e)) + sys.exit(-1) diff -r 914c44d10c8d -r 2bfd19fc1b79 tools/python/xen/xm/dumppolicy.py --- a/tools/python/xen/xm/dumppolicy.py Sun Oct 01 11:39:41 2006 -0600 +++ b/tools/python/xen/xm/dumppolicy.py Sun Oct 01 19:10:18 2006 -0600 @@ -19,7 +19,7 @@ """ import sys from xen.util.security import ACMError, err, dump_policy - +from xen.xm.opts import OptionError def help(): return """ @@ -27,16 +27,16 @@ def help(): (low-level).""" def main(argv): + if len(argv) != 1: + raise OptionError("No arguments expected.") + + dump_policy() + +if __name__ == '__main__': try: - if len(argv) != 1: - usage() - - dump_policy() - except ACMError: + main(sys.argv) + except Exception, e: + sys.stderr.write('Error: %s\n' % str(e)) sys.exit(-1) -if __name__ == '__main__': - main(sys.argv) - - diff -r 914c44d10c8d -r 2bfd19fc1b79 tools/python/xen/xm/getlabel.py --- a/tools/python/xen/xm/getlabel.py Sun Oct 01 11:39:41 2006 -0600 +++ b/tools/python/xen/xm/getlabel.py Sun Oct 01 19:10:18 2006 -0600 @@ -25,8 +25,9 @@ from xen.xm.opts import OptionError def help(): return """ - Usage: xm getlabel dom <configfile>" - xm getlabel res <resource>\n" + Usage: xm getlabel dom <configfile> + xm getlabel res <resource> + This program shows the label for a domain or resource.""" def get_resource_label(resource): @@ -37,7 +38,7 @@ def get_resource_label(resource): try: access_control = dictio.dict_read("resources", file) except: - security.err("Resource label file not found") + raise OptionError("Resource label file not found") # get the entry and print label if access_control.has_key(resource): @@ -45,23 +46,22 @@ def get_resource_label(resource): label = access_control[resource][1] print "policy="+policy+",label="+label else: - security.err("Resource not labeled") + raise security.ACMError("Resource not labeled") def get_domain_label(configfile): # open the domain config file fd = None - file = None if configfile[0] == '/': fd = open(configfile, "rb") else: for prefix in [".", "/etc/xen"]: - file = prefix + "/" + configfile - if os.path.isfile(file): - fd = open(file, "rb") + abs_file = prefix + "/" + configfile + if os.path.isfile(abs_file): + fd = open(abs_file, "rb") break if not fd: - security.err("Configuration file '"+configfile+"' not found.") + raise OptionError("Configuration file '%s' not found." % configfile) # read in the domain config file, finding the label line ac_entry_re = re.compile("^access_control\s*=.*", re.IGNORECASE) @@ -79,7 +79,7 @@ def get_domain_label(configfile): # send error message if we didn't find anything if acline == "": - security.err("Domain not labeled") + raise security.ACMError("Domain not labeled") # print out the label (title, data) = acline.split("=", 1) @@ -89,7 +89,7 @@ def get_domain_label(configfile): print data -def main (argv): +def main(argv): if len(argv) != 3: raise OptionError('Requires 2 arguments') @@ -103,6 +103,11 @@ def main (argv): raise OptionError('First subcommand argument must be "dom" or "res"') if __name__ == '__main__': - main(sys.argv) + try: + main(sys.argv) + except Exception, e: + sys.stderr.write('Error: %s\n' % str(e)) + sys.exit(-1) + diff -r 914c44d10c8d -r 2bfd19fc1b79 tools/python/xen/xm/loadpolicy.py --- a/tools/python/xen/xm/loadpolicy.py Sun Oct 01 11:39:41 2006 -0600 +++ b/tools/python/xen/xm/loadpolicy.py Sun Oct 01 19:10:18 2006 -0600 @@ -31,15 +31,12 @@ def main(argv): if len(argv) != 2: raise OptionError('No policy defined') - try: - load_policy(argv[1]) - - except ACMError: - sys.exit(-1) - except: - traceback.print_exc(limit = 1) + load_policy(argv[1]) if __name__ == '__main__': - main(sys.argv) - - + try: + main(sys.argv) + except Exception, e: + sys.stderr.write('Error: %s\n' % str(e)) + sys.exit(-1) + diff -r 914c44d10c8d -r 2bfd19fc1b79 tools/python/xen/xm/main.py --- a/tools/python/xen/xm/main.py Sun Oct 01 11:39:41 2006 -0600 +++ b/tools/python/xen/xm/main.py Sun Oct 01 19:10:18 2006 -0600 @@ -526,7 +526,7 @@ def parse_sedf_info(info): return t(sxp.child_value(info, n, d)) return { - 'domid' : get_info('domid', int, -1), + 'domid' : get_info('domain', int, -1), 'period' : get_info('period', int, -1), 'slice' : get_info('slice', int, -1), 'latency' : get_info('latency', int, -1), @@ -979,7 +979,7 @@ def xm_uptime(args): for dom in doms: d = parse_doms_info(dom) - if d['dom'] > 0: + if d['domid'] > 0: uptime = int(round(d['up_time'])) else: f=open('/proc/uptime', 'r') @@ -1006,10 +1006,10 @@ def xm_uptime(args): if short_mode: now = datetime.datetime.now() upstring = now.strftime(" %H:%M:%S") + " up " + upstring - upstring += ", " + d['name'] + " (" + str(d['dom']) + ")" + upstring += ", " + d['name'] + " (" + str(d['domid']) + ")" else: upstring += ':%(seconds)02d' % vars() - upstring = ("%(name)-32s %(dom)3d " % d) + upstring + upstring = ("%(name)-32s %(domid)3d " % d) + upstring print upstring @@ -1374,7 +1374,7 @@ IMPORTED_COMMANDS = [ 'cfgbootpolicy', 'makepolicy', 'loadpolicy', - 'dumppolicy' + 'dumppolicy', 'rmlabel', 'getlabel', 'dry-run', @@ -1423,13 +1423,14 @@ def main(argv=sys.argv): if len(argv) < 2: usage() - # intercept --help and output our own help - if '--help' in argv[1:]: - if '--help' == argv[1]: - longHelp() - else: - usage(argv[1]) - sys.exit(0) + # intercept --help(-h) and output our own help + for help in ['--help', '-h']: + if help in argv[1:]: + if help == argv[1]: + longHelp() + else: + usage(argv[1]) + sys.exit(0) cmd = xm_lookup_cmd(argv[1]) @@ -1477,10 +1478,15 @@ def main(argv=sys.argv): except (ValueError, OverflowError): err("Invalid argument.") usage(argv[1]) + sys.exit(1) except OptionError, e: err(str(e)) usage(argv[1]) print e.usage() + sys.exit(1) + except security.ACMError, e: + err(str(e)) + sys.exit(1) except: print "Unexpected error:", sys.exc_info()[0] print diff -r 914c44d10c8d -r 2bfd19fc1b79 tools/python/xen/xm/makepolicy.py --- a/tools/python/xen/xm/makepolicy.py Sun Oct 01 11:39:41 2006 -0600 +++ b/tools/python/xen/xm/makepolicy.py Sun Oct 01 19:10:18 2006 -0600 @@ -33,16 +33,13 @@ def main(argv): if len(argv) != 2: raise OptionError('No XML policy file specified') + make_policy(argv[1]) + +if __name__ == '__main__': try: - make_policy(argv[1]) - except ACMError: - sys.exit(-1) - except: - traceback.print_exc(limit=1) + main(sys.argv) + except Exception, e: + sys.stderr.write('Error: %s\n' % str(e)) sys.exit(-1) -if __name__ == '__main__': - main(sys.argv) - - diff -r 914c44d10c8d -r 2bfd19fc1b79 tools/python/xen/xm/resources.py --- a/tools/python/xen/xm/resources.py Sun Oct 01 11:39:41 2006 -0600 +++ b/tools/python/xen/xm/resources.py Sun Oct 01 19:10:18 2006 -0600 @@ -24,7 +24,7 @@ from xen.xm.opts import OptionError from xen.xm.opts import OptionError def help(): - return """Usage: xm resource + return """ This program lists information for each resource in the global resource label file.""" @@ -45,18 +45,13 @@ def main (argv): filename = security.res_label_filename access_control = dictio.dict_read("resources", filename) except: - print "Resource file not found." - return + raise OptionError("Resource file not found") - try: - file = security.res_label_filename - access_control = dictio.dict_read("resources", file) - except: - security.err("Error reading resource file.") - - print_resource_data(access_control) + print_resource_data(access_control) if __name__ == '__main__': - main(sys.argv) - - + try: + main(sys.argv) + except Exception, e: + sys.stderr.write('Error: %s\n' % str(e)) + sys.exit(-1) diff -r 914c44d10c8d -r 2bfd19fc1b79 tools/python/xen/xm/rmlabel.py --- a/tools/python/xen/xm/rmlabel.py Sun Oct 01 11:39:41 2006 -0600 +++ b/tools/python/xen/xm/rmlabel.py Sun Oct 01 19:10:18 2006 -0600 @@ -42,14 +42,14 @@ def rm_resource_label(resource): try: access_control = dictio.dict_read("resources", file) except: - security.err("Resource file not found, cannot remove label!") + raise security.ACMError("Resource file not found, cannot remove label!") # remove the entry and update file if access_control.has_key(resource): del access_control[resource] dictio.dict_write(access_control, "resources", file) else: - security.err("Resource not labeled.") + raise security.ACMError("Resource not labeled") def rm_domain_label(configfile): @@ -65,8 +65,8 @@ def rm_domain_label(configfile): fd = open(file, "rb") break if not fd: - security.err("Configuration file '"+configfile+"' not found.") - + raise OptionError("Configuration file '%s' not found." % configfile) + # read in the domain config file, removing label ac_entry_re = re.compile("^access_control\s*=.*", re.IGNORECASE) ac_exit_re = re.compile(".*'\].*") @@ -86,7 +86,7 @@ def rm_domain_label(configfile): # send error message if we didn't find anything to remove if not removed: - security.err("Domain not labeled.") + raise security.ACMError('Domain not labeled') # write the data back out to the file fd = open(file, "wb") @@ -102,17 +102,18 @@ def main (argv): if argv[1].lower() not in ('dom', 'res'): raise OptionError('Unrecognised type argument: %s' % argv[1]) - try: - if argv[1].lower() == "dom": - configfile = argv[2] - rm_domain_label(configfile) - elif argv[1].lower() == "res": - resource = argv[2] - rm_resource_label(resource) - except security.ACMError: - sys.exit(-1) + if argv[1].lower() == "dom": + configfile = argv[2] + rm_domain_label(configfile) + elif argv[1].lower() == "res": + resource = argv[2] + rm_resource_label(resource) if __name__ == '__main__': - main(sys.argv) + try: + main(sys.argv) + except Exception, e: + sys.stderr.write('Error: %s\n' % str(e)) + sys.exit(-1) diff -r 914c44d10c8d -r 2bfd19fc1b79 tools/xm-test/tests/vtpm/vtpm_utils.py --- a/tools/xm-test/tests/vtpm/vtpm_utils.py Sun Oct 01 11:39:41 2006 -0600 +++ b/tools/xm-test/tests/vtpm/vtpm_utils.py Sun Oct 01 19:10:18 2006 -0600 @@ -8,12 +8,10 @@ if ENABLE_HVM_SUPPORT: if ENABLE_HVM_SUPPORT: SKIP("vtpm tests not supported for HVM domains") -if not os.path.exists("/dev/tpm0"): - SKIP("This machine has no hardware TPM; cannot run this test") - status, output = traceCommand("ps aux | grep vtpm_manager | grep -v grep") if output == "": - FAIL("virtual TPM manager must be started to run this test") + SKIP("virtual TPM manager must be started to run this test; might " + "need /dev/tpm0") def vtpm_cleanup(domName): traceCommand("/etc/xen/scripts/vtpm-delete %s" % domName) diff -r 914c44d10c8d -r 2bfd19fc1b79 xen/arch/ia64/Makefile --- a/xen/arch/ia64/Makefile Sun Oct 01 11:39:41 2006 -0600 +++ b/xen/arch/ia64/Makefile Sun Oct 01 19:10:18 2006 -0600 @@ -4,22 +4,27 @@ subdir-y += linux-xen subdir-y += linux-xen $(TARGET)-syms: linux-xen/head.o $(ALL_OBJS) xen.lds.s + $(MAKE) -f $(BASEDIR)/Rules.mk $(BASEDIR)/common/symbols-dummy.o $(LD) $(LDFLAGS) -T xen.lds.s -N \ - -Map map.out linux-xen/head.o $(ALL_OBJS) -o $@ + -Map map.out linux-xen/head.o $(ALL_OBJS) \ + $(BASEDIR)/common/symbols-dummy.o -o $@ $(NM) -n $@ | $(BASEDIR)/tools/symbols > $(BASEDIR)/xen-syms.S $(MAKE) -f $(BASEDIR)/Rules.mk $(BASEDIR)/xen-syms.o $(LD) $(LDFLAGS) -T xen.lds.s -N \ - -Map map.out linux-xen/head.o $(ALL_OBJS) $(BASEDIR)/xen-syms.o -o $@ + -Map map.out linux-xen/head.o $(ALL_OBJS) \ + $(BASEDIR)/xen-syms.o -o $@ $(NM) -n $@ | $(BASEDIR)/tools/symbols >$(BASEDIR)/xen-syms.S $(MAKE) -f $(BASEDIR)/Rules.mk $(BASEDIR)/xen-syms.o $(LD) $(LDFLAGS) -T xen.lds.s -N \ - -Map map.out linux-xen/head.o $(ALL_OBJS) $(BASEDIR)/xen-syms.o -o $@ + -Map map.out linux-xen/head.o $(ALL_OBJS) \ + $(BASEDIR)/xen-syms.o -o $@ rm -f $(BASEDIR)/xen-syms.S $(BASEDIR)/xen-syms.o $(TARGET): $(TARGET)-syms $(OBJCOPY) -R .note -R .comment -S $(TARGET)-syms $@ - $(NM) -n $(TARGET)-syms | grep -v '\( [aUw] \)\|\(__crc_\)\|\( \$[adt]\)'\ - > $(BASEDIR)/System.map + $(NM) -n $(TARGET)-syms | \ + grep -v '\( [aUw] \)\|\(__crc_\)\|\( \$[adt]\)' \ + > $(BASEDIR)/System.map # Headers do not depend on auto-generated header, but object files do. HDRS := $(subst $(BASEDIR)/include/asm-ia64/asm-xsi-offsets.h,,$(HDRS)) diff -r 914c44d10c8d -r 2bfd19fc1b79 xen/arch/powerpc/Makefile --- a/xen/arch/powerpc/Makefile Sun Oct 01 11:39:41 2006 -0600 +++ b/xen/arch/powerpc/Makefile Sun Oct 01 19:10:18 2006 -0600 @@ -101,7 +101,8 @@ TARGET_OPTS += start.o $(ALL_OBJS) TARGET_OPTS += start.o $(ALL_OBJS) .xen-syms: start.o $(ALL_OBJS) xen.lds - $(CC) $(CFLAGS) $(TARGET_OPTS) -o $@ + $(MAKE) -f $(BASEDIR)/Rules.mk $(BASEDIR)/common/symbols-dummy.o + $(CC) $(CFLAGS) $(TARGET_OPTS) $(BASEDIR)/common/symbols-dummy.o -o $@ NM=$(CROSS_COMPILE)nm new_nm := $(shell if $(NM) --help 2>&1 | grep -- '--synthetic' > /dev/null; then echo y; else echo n; fi) diff -r 914c44d10c8d -r 2bfd19fc1b79 xen/arch/x86/Makefile --- a/xen/arch/x86/Makefile Sun Oct 01 11:39:41 2006 -0600 +++ b/xen/arch/x86/Makefile Sun Oct 01 19:10:18 2006 -0600 @@ -46,19 +46,24 @@ obj-$(crash_debug) += gdbstub.o $(TARGET): $(TARGET)-syms boot/mkelf32 ./boot/mkelf32 $(TARGET)-syms $(TARGET) 0x100000 \ - `$(NM) $(TARGET)-syms | sort | tail -n 1 | sed -e 's/^\([^ ]*\).*/0x\1/'` + `$(NM) $(TARGET)-syms | sort | tail -n 1 | \ + sed -e 's/^\([^ ]*\).*/0x\1/'` $(TARGET)-syms: boot/$(TARGET_SUBARCH).o $(ALL_OBJS) xen.lds + $(MAKE) -f $(BASEDIR)/Rules.mk $(BASEDIR)/common/symbols-dummy.o $(LD) $(LDFLAGS) -T xen.lds -N \ - boot/$(TARGET_SUBARCH).o $(ALL_OBJS) -o $@ + boot/$(TARGET_SUBARCH).o $(ALL_OBJS) \ + $(BASEDIR)/common/symbols-dummy.o -o $@ $(NM) -n $@ | $(BASEDIR)/tools/symbols >$(BASEDIR)/xen-syms.S $(MAKE) -f $(BASEDIR)/Rules.mk $(BASEDIR)/xen-syms.o $(LD) $(LDFLAGS) -T xen.lds -N \ - boot/$(TARGET_SUBARCH).o $(ALL_OBJS) $(BASEDIR)/xen-syms.o -o $@ + boot/$(TARGET_SUBARCH).o $(ALL_OBJS) \ + $(BASEDIR)/xen-syms.o -o $@ $(NM) -n $@ | $(BASEDIR)/tools/symbols >$(BASEDIR)/xen-syms.S $(MAKE) -f $(BASEDIR)/Rules.mk $(BASEDIR)/xen-syms.o $(LD) $(LDFLAGS) -T xen.lds -N \ - boot/$(TARGET_SUBARCH).o $(ALL_OBJS) $(BASEDIR)/xen-syms.o -o $@ + boot/$(TARGET_SUBARCH).o $(ALL_OBJS) \ + $(BASEDIR)/xen-syms.o -o $@ rm -f $(BASEDIR)/xen-syms.S $(BASEDIR)/xen-syms.o asm-offsets.s: $(TARGET_SUBARCH)/asm-offsets.c $(HDRS) diff -r 914c44d10c8d -r 2bfd19fc1b79 xen/arch/x86/domain.c --- a/xen/arch/x86/domain.c Sun Oct 01 11:39:41 2006 -0600 +++ b/xen/arch/x86/domain.c Sun Oct 01 19:10:18 2006 -0600 @@ -334,8 +334,10 @@ int arch_set_info_guest( } else { - if ( !get_page_and_type(mfn_to_page(cr3_pfn), d, - PGT_base_page_table) ) + if ( shadow_mode_refcounts(d) + ? !get_page(mfn_to_page(cr3_pfn), d) + : !get_page_and_type(mfn_to_page(cr3_pfn), d, + PGT_base_page_table) ) { destroy_gdt(v); return -EINVAL; @@ -952,7 +954,10 @@ void domain_relinquish_resources(struct pfn = pagetable_get_pfn(v->arch.guest_table_user); if ( pfn != 0 ) { - put_page_and_type(mfn_to_page(pfn)); + if ( shadow_mode_refcounts(d) ) + put_page(mfn_to_page(pfn)); + else + put_page_and_type(mfn_to_page(pfn)); v->arch.guest_table_user = pagetable_null(); } #endif diff -r 914c44d10c8d -r 2bfd19fc1b79 xen/arch/x86/hvm/hvm.c --- a/xen/arch/x86/hvm/hvm.c Sun Oct 01 11:39:41 2006 -0600 +++ b/xen/arch/x86/hvm/hvm.c Sun Oct 01 19:10:18 2006 -0600 @@ -389,42 +389,68 @@ void hvm_hlt(unsigned long rflags) } /* - * Copy from/to guest virtual. + * __hvm_copy(): + * @buf = hypervisor buffer + * @addr = guest virtual or physical address to copy to/from + * @size = number of bytes to copy + * @dir = copy *to* guest (TRUE) or *from* guest (FALSE)? + * @phy = interpret addr as physical (TRUE) or virtual (FALSE) address? + * Returns number of bytes failed to copy (0 == complete success). */ -int hvm_copy(void *buf, unsigned long vaddr, int size, int dir) +static int __hvm_copy( + void *buf, unsigned long addr, int size, int dir, int phy) { struct vcpu *v = current; - unsigned long gfn; unsigned long mfn; - char *addr; - int count; - - while (size > 0) { - count = PAGE_SIZE - (vaddr & ~PAGE_MASK); - if (count > size) - count = size; - - gfn = shadow_gva_to_gfn(v, vaddr); - mfn = mfn_x(sh_vcpu_gfn_to_mfn(v, gfn)); - - if (mfn == INVALID_MFN) - return 0; - - addr = (char *)map_domain_page(mfn) + (vaddr & ~PAGE_MASK); - - if (dir == HVM_COPY_IN) - memcpy(buf, addr, count); + char *p; + int count, todo; + + todo = size; + while ( todo > 0 ) + { + count = min_t(int, PAGE_SIZE - (addr & ~PAGE_MASK), todo); + + mfn = phy ? + get_mfn_from_gpfn(addr >> PAGE_SHIFT) : + mfn_x(sh_vcpu_gfn_to_mfn(v, shadow_gva_to_gfn(v, addr))); + if ( mfn == INVALID_MFN ) + return todo; + + p = (char *)map_domain_page(mfn) + (addr & ~PAGE_MASK); + + if ( dir ) + memcpy(p, buf, count); /* dir == TRUE: *to* guest */ else - memcpy(addr, buf, count); - - unmap_domain_page(addr); - - vaddr += count; - buf += count; - size -= count; - } - - return 1; + memcpy(buf, p, count); /* dir == FALSE: *from guest */ + + unmap_domain_page(p); + + addr += count; + buf += count; + todo -= count; + } + + return 0; +} + +int hvm_copy_to_guest_phys(unsigned long paddr, void *buf, int size) +{ + return __hvm_copy(buf, paddr, size, 1, 1); +} + +int hvm_copy_from_guest_phys(void *buf, unsigned long paddr, int size) +{ + return __hvm_copy(buf, paddr, size, 0, 1); +} + +int hvm_copy_to_guest_virt(unsigned long vaddr, void *buf, int size) +{ + return __hvm_copy(buf, vaddr, size, 1, 0); +} + +int hvm_copy_from_guest_virt(void *buf, unsigned long vaddr, int size) +{ + return __hvm_copy(buf, vaddr, size, 0, 0); } /* diff -r 914c44d10c8d -r 2bfd19fc1b79 xen/arch/x86/hvm/i8259.c --- a/xen/arch/x86/hvm/i8259.c Sun Oct 01 11:39:41 2006 -0600 +++ b/xen/arch/x86/hvm/i8259.c Sun Oct 01 19:10:18 2006 -0600 @@ -86,7 +86,7 @@ static int pic_get_irq(PicState *s) ASSERT(spin_is_locked(&s->pics_state->lock)); - mask = s->irr & ~s->imr; + mask = (s->irr|s->irr_xen) & ~s->imr; priority = get_priority(s, mask); if (priority == 8) return -1; @@ -128,6 +128,32 @@ void pic_update_irq(struct hvm_virpic *s } } +void pic_set_xen_irq(void *opaque, int irq, int level) +{ + struct hvm_virpic *s = opaque; + unsigned long flags; + PicState *ps; + + spin_lock_irqsave(&s->lock, flags); + + hvm_vioapic_set_xen_irq(current->domain, irq, level); + + /* Set it on the 8259s */ + ps = &s->pics[irq >> 3]; + if (!(ps->elcr & (1 << (irq & 7)))) { + DPRINTK("edge-triggered override IRQ?\n"); + domain_crash(current->domain); + } + if (level) { + ps->irr_xen |= 1 << (irq & 7); + } else { + ps->irr_xen &= ~(1 << (irq & 7)); + } + + pic_update_irq(s); + spin_unlock_irqrestore(&s->lock, flags); +} + void pic_set_irq_new(void *opaque, int irq, int level) { struct hvm_virpic *s = opaque; @@ -136,9 +162,6 @@ void pic_set_irq_new(void *opaque, int i spin_lock_irqsave(&s->lock, flags); hvm_vioapic_set_irq(current->domain, irq, level); pic_set_irq1(&s->pics[irq >> 3], irq & 7, level); - /* used for IOAPIC irqs */ - if (s->alt_irq_func) - s->alt_irq_func(s->alt_irq_opaque, irq, level); pic_update_irq(s); spin_unlock_irqrestore(&s->lock, flags); } @@ -371,6 +394,7 @@ static uint32_t pic_poll_read (PicState s->pics_state->pics[0].irr &= ~(1 << 2); } s->irr &= ~(1 << ret); + s->irr_xen &= ~(1 << ret); s->isr &= ~(1 << ret); if (addr1 >> 7 || ret != 2) pic_update_irq(s->pics_state); @@ -400,7 +424,7 @@ static uint32_t pic_ioport_read(void *op if (s->read_reg_select) ret = s->isr; else - ret = s->irr; + ret = s->irr | s->irr_xen; } else { ret = s->imr; } @@ -472,18 +496,6 @@ void pic_init(struct hvm_virpic *s, void s->irq_request_opaque = irq_request_opaque; } -void pic_set_alt_irq_func(struct hvm_virpic *s, - void (*alt_irq_func)(void *, int, int), - void *alt_irq_opaque) -{ - unsigned long flags; - - spin_lock_irqsave(&s->lock, flags); - s->alt_irq_func = alt_irq_func; - s->alt_irq_opaque = alt_irq_opaque; - spin_unlock_irqrestore(&s->lock, flags); -} - static int intercept_pic_io(ioreq_t *p) { struct hvm_virpic *pic; @@ -497,8 +509,9 @@ static int intercept_pic_io(ioreq_t *p) } pic = &v->domain->arch.hvm_domain.vpic; if ( p->dir == 0 ) { - if(p->pdata_valid) - hvm_copy(&data, (unsigned long)p->u.pdata, p->size, HVM_COPY_IN); + if (p->pdata_valid) + (void)hvm_copy_from_guest_virt( + &data, (unsigned long)p->u.pdata, p->size); else data = p->u.data; spin_lock_irqsave(&pic->lock, flags); @@ -511,8 +524,9 @@ static int intercept_pic_io(ioreq_t *p) data = pic_ioport_read( (void*)&pic->pics[p->addr>>7], (uint32_t) p->addr); spin_unlock_irqrestore(&pic->lock, flags); - if(p->pdata_valid) - hvm_copy(&data, (unsigned long)p->u.pdata, p->size, HVM_COPY_OUT); + if (p->pdata_valid) + (void)hvm_copy_to_guest_virt( + (unsigned long)p->u.pdata, &data, p->size); else p->u.data = (u64)data; } @@ -533,8 +547,9 @@ static int intercept_elcr_io(ioreq_t *p) s = &v->domain->arch.hvm_domain.vpic; if ( p->dir == 0 ) { - if(p->pdata_valid) - hvm_copy(&data, (unsigned long)p->u.pdata, p->size, HVM_COPY_IN); + if (p->pdata_valid) + (void)hvm_copy_from_guest_virt( + &data, (unsigned long)p->u.pdata, p->size); else data = p->u.data; spin_lock_irqsave(&s->lock, flags); @@ -547,8 +562,9 @@ static int intercept_elcr_io(ioreq_t *p) else { data = (u64) elcr_ioport_read( (void*)&s->pics[p->addr&1], (uint32_t) p->addr); - if(p->pdata_valid) - hvm_copy(&data, (unsigned long)p->u.pdata, p->size, HVM_COPY_OUT); + if (p->pdata_valid) + (void)hvm_copy_to_guest_virt( + (unsigned long)p->u.pdata, &data, p->size); else p->u.data = (u64)data; diff -r 914c44d10c8d -r 2bfd19fc1b79 xen/arch/x86/hvm/instrlen.c --- a/xen/arch/x86/hvm/instrlen.c Sun Oct 01 11:39:41 2006 -0600 +++ b/xen/arch/x86/hvm/instrlen.c Sun Oct 01 19:10:18 2006 -0600 @@ -196,26 +196,17 @@ static uint8_t twobyte_table[256] = { /* * insn_fetch - fetch the next 1 to 4 bytes from instruction stream - * * @_type: u8, u16, u32, s8, s16, or s32 * @_size: 1, 2, or 4 bytes - * @_eip: address to fetch from guest memory - * @_length: increments the current instruction length counter by _size - * - * This is used internally by hvm_instruction_length to fetch the next byte, - * word, or dword from guest memory at location _eip. we currently use a local - * unsigned long as the storage buffer since the most bytes we're gonna get - * is limited to 4. - */ -#define insn_fetch(_type, _size, _eip, _length) \ -({ unsigned long _x; \ - if ((rc = inst_copy_from_guest((unsigned char *)(&(_x)), \ - (unsigned long)(_eip), _size)) \ - != _size) \ - goto done; \ - (_eip) += (_size); \ - (_length) += (_size); \ - (_type)_x; \ + */ +#define insn_fetch(_type, _size) \ +({ unsigned long _x, _ptr = _regs.eip; \ + if ( mode == X86EMUL_MODE_REAL ) _ptr += _regs.cs << 4; \ + rc = inst_copy_from_guest((unsigned char *)(&(_x)), _ptr, _size); \ + if ( rc != _size ) goto done; \ + _regs.eip += (_size); \ + length += (_size); \ + (_type)_x; \ }) /** @@ -231,17 +222,13 @@ int hvm_instruction_length(struct cpu_us { uint8_t b, d, twobyte = 0, rex_prefix = 0; uint8_t modrm, modrm_mod = 0, modrm_reg = 0, modrm_rm = 0; - unsigned int op_bytes, ad_bytes, lock_prefix = 0, rep_prefix = 0, i; + unsigned int op_bytes, ad_bytes, i; int rc = 0; int length = 0; unsigned int tmp; /* Shadow copy of register state. Committed on successful emulation. */ struct cpu_user_regs _regs = *regs; - - /* include CS for 16-bit modes */ - if (mode == X86EMUL_MODE_REAL || mode == X86EMUL_MODE_PROT16) - _regs.eip += (_regs.cs << 4); switch ( mode ) { @@ -265,7 +252,7 @@ int hvm_instruction_length(struct cpu_us /* Legacy prefixes. */ for ( i = 0; i < 8; i++ ) { - switch ( b = insn_fetch(uint8_t, 1, _regs.eip, length) ) + switch ( b = insn_fetch(uint8_t, 1) ) { case 0x66: /* operand-size override */ op_bytes ^= 6; /* switch between 2/4 bytes */ @@ -282,13 +269,8 @@ int hvm_instruction_length(struct cpu_us case 0x64: /* FS override */ case 0x65: /* GS override */ case 0x36: /* SS override */ - break; case 0xf0: /* LOCK */ - lock_prefix = 1; - break; case 0xf3: /* REP/REPE/REPZ */ - rep_prefix = 1; - break; case 0xf2: /* REPNE/REPNZ */ break; default: @@ -296,12 +278,6 @@ int hvm_instruction_length(struct cpu_us } } done_prefixes: - - /* Note quite the same as 80386 real mode, but hopefully good enough. */ - if ( (mode == X86EMUL_MODE_REAL) && (ad_bytes != 2) ) { - printf("sonofabitch!! we don't support 32-bit addresses in realmode\n"); - goto cannot_emulate; - } /* REX prefix. */ if ( (mode == X86EMUL_MODE_PROT64) && ((b & 0xf0) == 0x40) ) @@ -311,7 +287,7 @@ done_prefixes: op_bytes = 8; /* REX.W */ modrm_reg = (b & 4) << 1; /* REX.R */ /* REX.B and REX.X do not need to be decoded. */ - b = insn_fetch(uint8_t, 1, _regs.eip, length); + b = insn_fetch(uint8_t, 1); } /* Opcode byte(s). */ @@ -322,7 +298,7 @@ done_prefixes: if ( b == 0x0f ) { twobyte = 1; - b = insn_fetch(uint8_t, 1, _regs.eip, length); + b = insn_fetch(uint8_t, 1); d = twobyte_table[b]; } @@ -334,7 +310,7 @@ done_prefixes: /* ModRM and SIB bytes. */ if ( d & ModRM ) { - modrm = insn_fetch(uint8_t, 1, _regs.eip, length); + modrm = insn_fetch(uint8_t, 1); modrm_mod |= (modrm & 0xc0) >> 6; modrm_reg |= (modrm & 0x38) >> 3; modrm_rm |= (modrm & 0x07); @@ -374,7 +350,7 @@ done_prefixes: { case 0: if ( (modrm_rm == 4) && - (((insn_fetch(uint8_t, 1, _regs.eip, length)) & 7) + (((insn_fetch(uint8_t, 1)) & 7) == 5) ) { length += 4; @@ -389,7 +365,7 @@ done_prefixes: case 1: if ( modrm_rm == 4 ) { - insn_fetch(uint8_t, 1, _regs.eip, length); + insn_fetch(uint8_t, 1); } length += 1; _regs.eip += 1; /* skip disp8 */ @@ -397,7 +373,7 @@ done_prefixes: case 2: if ( modrm_rm == 4 ) { - insn_fetch(uint8_t, 1, _regs.eip, length); + insn_fetch(uint8_t, 1); } length += 4; _regs.eip += 4; /* skip disp32 */ @@ -423,13 +399,13 @@ done_prefixes: /* NB. Immediates are sign-extended as necessary. */ switch ( tmp ) { - case 1: insn_fetch(int8_t, 1, _regs.eip, length); break; - case 2: insn_fetch(int16_t, 2, _regs.eip, length); break; - case 4: insn_fetch(int32_t, 4, _regs.eip, length); break; + case 1: insn_fetch(int8_t, 1); break; + case 2: insn_fetch(int16_t, 2); break; + case 4: insn_fetch(int32_t, 4); break; } break; case SrcImmByte: - insn_fetch(int8_t, 1, _regs.eip, length); + insn_fetch(int8_t, 1); break; } @@ -455,9 +431,9 @@ done_prefixes: if ( tmp == 8 ) tmp = 4; switch ( tmp ) { - case 1: insn_fetch(int8_t, 1, _regs.eip, length); break; - case 2: insn_fetch(int16_t, 2, _regs.eip, length); break; - case 4: insn_fetch(int32_t, 4, _regs.eip, length); break; + case 1: insn_fetch(int8_t, 1); break; + case 2: insn_fetch(int16_t, 2); break; + case 4: insn_fetch(int32_t, 4); break; } goto done; } diff -r 914c44d10c8d -r 2bfd19fc1b79 xen/arch/x86/hvm/intercept.c --- a/xen/arch/x86/hvm/intercept.c Sun Oct 01 11:39:41 2006 -0600 +++ b/xen/arch/x86/hvm/intercept.c Sun Oct 01 19:10:18 2006 -0600 @@ -90,17 +90,17 @@ static inline void hvm_mmio_access(struc data = read_handler(v, req->addr + (sign * i * req->size), req->size); - hvm_copy(&data, - (unsigned long)p->u.pdata + (sign * i * req->size), - p->size, - HVM_COPY_OUT); + (void)hvm_copy_to_guest_virt( + (unsigned long)p->u.pdata + (sign * i * req->size), + &data, + p->size); } } else { /* !req->dir == IOREQ_READ */ for (i = 0; i < req->count; i++) { - hvm_copy(&data, - (unsigned long)p->u.pdata + (sign * i * req->size), - p->size, - HVM_COPY_IN); + (void)hvm_copy_from_guest_virt( + &data, + (unsigned long)p->u.pdata + (sign * i * req->size), + p->size); write_handler(v, req->addr + (sign * i * req->size), req->size, data); diff -r 914c44d10c8d -r 2bfd19fc1b79 xen/arch/x86/hvm/io.c --- a/xen/arch/x86/hvm/io.c Sun Oct 01 11:39:41 2006 -0600 +++ b/xen/arch/x86/hvm/io.c Sun Oct 01 19:10:18 2006 -0600 @@ -379,7 +379,7 @@ static void hvm_pio_assist(struct cpu_us addr += regs->es << 4; if (sign > 0) addr -= p->size; - hvm_copy(&p->u.data, addr, p->size, HVM_COPY_OUT); + (void)hvm_copy_to_guest_virt(addr, &p->u.data, p->size); } } else /* p->dir == IOREQ_WRITE */ @@ -493,7 +493,7 @@ static void hvm_mmio_assist(struct cpu_u if (sign > 0) addr -= p->size; - hvm_copy(&p->u.data, addr, p->size, HVM_COPY_OUT); + (void)hvm_copy_to_guest_virt(addr, &p->u.data, p->size); } if (mmio_opp->flags & REPZ) @@ -596,6 +596,7 @@ static void hvm_mmio_assist(struct cpu_u break; case INSTR_CMP: + case INSTR_SUB: if (src & REGISTER) { index = operand_index(src); value = get_reg_value(size, index, 0, regs); @@ -607,6 +608,8 @@ static void hvm_mmio_assist(struct cpu_u index = operand_index(dst); value = get_reg_value(size, index, 0, regs); diff = value - (unsigned long) p->u.data; + if ( mmio_opp->instr == INSTR_SUB ) + set_reg_value(size, index, 0, regs, diff); } /* diff -r 914c44d10c8d -r 2bfd19fc1b79 xen/arch/x86/hvm/platform.c --- a/xen/arch/x86/hvm/platform.c Sun Oct 01 11:39:41 2006 -0600 +++ b/xen/arch/x86/hvm/platform.c Sun Oct 01 19:10:18 2006 -0600 @@ -394,6 +394,11 @@ static int hvm_decode(int realmode, unsi GET_OP_SIZE_FOR_NONEBYTE(instr->op_size); return mem_reg(instr->op_size, opcode, instr, rex); + case 0x2B: /* sub m32/16, r32/16 */ + instr->instr = INSTR_SUB; + 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; instr->op_size = BYTE; @@ -689,7 +694,7 @@ int inst_copy_from_guest(unsigned char * { if (inst_len > MAX_INST_LEN || inst_len <= 0) return 0; - if (!hvm_copy(buf, guest_eip, inst_len, HVM_COPY_IN)) + if (hvm_copy_from_guest_virt(buf, guest_eip, inst_len)) return 0; return inst_len; } @@ -953,7 +958,7 @@ void handle_mmio(unsigned long va, unsig regs->eip -= inst_len; /* do not advance %eip */ if (dir == IOREQ_WRITE) - hvm_copy(&value, addr, size, HVM_COPY_IN); + (void)hvm_copy_from_guest_virt(&value, addr, size); send_mmio_req(IOREQ_TYPE_COPY, gpa, 1, size, value, dir, 0); } else { if ((addr & PAGE_MASK) != ((addr + sign * (count * size - 1)) & PAGE_MASK)) { @@ -1011,6 +1016,7 @@ void handle_mmio(unsigned long va, unsig case INSTR_CMP: /* Pass through */ case INSTR_TEST: + case INSTR_SUB: mmio_opp->flags = mmio_inst.flags; mmio_opp->instr = mmio_inst.instr; mmio_opp->operand[0] = mmio_inst.operand[0]; /* source */ @@ -1094,7 +1100,7 @@ unsigned long copy_to_user_hvm(void *to, return 0; } - return !hvm_copy((void *)from, (unsigned long)to, len, HVM_COPY_OUT); + return hvm_copy_to_guest_virt((unsigned long)to, (void *)from, len); } unsigned long copy_from_user_hvm(void *to, const void *from, unsigned len) @@ -1105,7 +1111,7 @@ unsigned long copy_from_user_hvm(void *t return 0; } - return !hvm_copy(to, (unsigned long)from, len, HVM_COPY_IN); + return hvm_copy_from_guest_virt(to, (unsigned long)from, len); } /* diff -r 914c44d10c8d -r 2bfd19fc1b79 xen/arch/x86/hvm/svm/emulate.c --- a/xen/arch/x86/hvm/svm/emulate.c Sun Oct 01 11:39:41 2006 -0600 +++ b/xen/arch/x86/hvm/svm/emulate.c Sun Oct 01 19:10:18 2006 -0600 @@ -341,7 +341,11 @@ unsigned long svm_rip2pointer(struct vmc * %cs is update, but fortunately, base contain the valid base address * no matter what kind of addressing is used. */ - return vmcb->cs.base + vmcb->rip; + unsigned long p = vmcb->cs.base + vmcb->rip; + if (!(vmcb->cs.attributes.fields.l && vmcb->efer & EFER_LMA)) + return (u32)p; /* mask to 32 bits */ + /* NB. Should mask to 16 bits if in real mode or 16-bit protected mode. */ + return p; } diff -r 914c44d10c8d -r 2bfd19fc1b79 xen/arch/x86/hvm/svm/intr.c --- a/xen/arch/x86/hvm/svm/intr.c Sun Oct 01 11:39:41 2006 -0600 +++ b/xen/arch/x86/hvm/svm/intr.c Sun Oct 01 19:10:18 2006 -0600 @@ -74,7 +74,6 @@ asmlinkage void svm_intr_assist(void) int intr_type = APIC_DM_EXTINT; int intr_vector = -1; int re_injecting = 0; - unsigned long rflags; ASSERT(vmcb); @@ -87,14 +86,6 @@ asmlinkage void svm_intr_assist(void) re_injecting = 1; } - /* Guest's interrputs masked? */ - rflags = vmcb->rflags; - if (irq_masked(rflags)) { - HVM_DBG_LOG(DBG_LEVEL_1, "Guest IRQs masked: rflags: %lx", rflags); - /* bail out, we won't be injecting an interrupt this time */ - return; - } - /* Previous interrupt still pending? */ if (vmcb->vintr.fields.irq) { // printk("Re-injecting IRQ from Vintr\n"); @@ -121,13 +112,11 @@ asmlinkage void svm_intr_assist(void) pic_set_irq(pic, pt->irq, 1); } - callback_irq = v->domain->arch.hvm_domain.params[HVM_PARAM_CALLBACK_IRQ]; - if ( callback_irq != 0 && - local_events_need_delivery() ) { - /*inject para-device call back irq*/ - v->vcpu_info->evtchn_upcall_mask = 1; - pic_set_irq(pic, callback_irq, 0); - pic_set_irq(pic, callback_irq, 1); + if (v->vcpu_id == 0) { + callback_irq = + v->domain->arch.hvm_domain.params[HVM_PARAM_CALLBACK_IRQ]; + if ( callback_irq != 0) + pic_set_xen_irq(pic, callback_irq, local_events_need_delivery()); } if ( cpu_has_pending_irq(v) ) diff -r 914c44d10c8d -r 2bfd19fc1b79 xen/arch/x86/hvm/svm/svm.c --- a/xen/arch/x86/hvm/svm/svm.c Sun Oct 01 11:39:41 2006 -0600 +++ b/xen/arch/x86/hvm/svm/svm.c Sun Oct 01 19:10:18 2006 -0600 @@ -57,7 +57,7 @@ extern void do_nmi(struct cpu_user_regs extern void do_nmi(struct cpu_user_regs *, unsigned long); extern int inst_copy_from_guest(unsigned char *buf, unsigned long guest_eip, int inst_len); - extern uint32_t vlapic_update_ppr(struct vlapic *vlapic); +extern uint32_t vlapic_update_ppr(struct vlapic *vlapic); extern asmlinkage void do_IRQ(struct cpu_user_regs *); extern void send_pio_req(struct cpu_user_regs *regs, unsigned long port, unsigned long count, int size, long value, int dir, int pvalid); @@ -282,7 +282,7 @@ static inline int long_mode_do_msr_read( switch (regs->ecx) { case MSR_EFER: - msr_content = vmcb->efer; + msr_content = vmcb->efer; msr_content &= ~EFER_SVME; break; @@ -320,14 +320,14 @@ static inline int long_mode_do_msr_read( HVM_DBG_LOG(DBG_LEVEL_2, "mode_do_msr_read: msr_content: %"PRIx64"\n", msr_content); - regs->eax = msr_content & 0xffffffff; - regs->edx = msr_content >> 32; + regs->eax = (u32)(msr_content >> 0); + regs->edx = (u32)(msr_content >> 32); return 1; } static inline int long_mode_do_msr_write(struct cpu_user_regs *regs) { - u64 msr_content = regs->eax | ((u64)regs->edx << 32); + u64 msr_content = (u32)regs->eax | ((u64)regs->edx << 32); struct vcpu *vc = current; struct vmcb_struct *vmcb = vc->arch.hvm_svm.vmcb; @@ -342,7 +342,8 @@ static inline int long_mode_do_msr_write /* offending reserved bit will cause #GP */ if ( msr_content & ~(EFER_LME | EFER_LMA | EFER_NX | EFER_SCE) ) { - printk("trying to set reserved bit in EFER\n"); + printk("Trying to set reserved bit in EFER: %"PRIx64"\n", + msr_content); svm_inject_exception(vc, TRAP_gp_fault, 1, 0); return 0; } @@ -355,7 +356,7 @@ static inline int long_mode_do_msr_write !test_bit(SVM_CPU_STATE_PAE_ENABLED, &vc->arch.hvm_svm.cpu_state) ) { - printk("trying to set LME bit when " + printk("Trying to set LME bit when " "in paging mode or PAE bit is not set\n"); svm_inject_exception(vc, TRAP_gp_fault, 1, 0); return 0; @@ -903,9 +904,9 @@ static void svm_relinquish_guest_resourc destroy_vmcb(&v->arch.hvm_svm); kill_timer(&v->arch.hvm_vcpu.hlt_timer); - if ( hvm_apic_support(v->domain) && (VLAPIC(v) != NULL) ) - { - kill_timer( &(VLAPIC(v)->vlapic_timer) ); + if ( VLAPIC(v) != NULL ) + { + kill_timer(&VLAPIC(v)->vlapic_timer); unmap_domain_page_global(VLAPIC(v)->regs); free_domheap_page(VLAPIC(v)->regs_page); xfree(VLAPIC(v)); @@ -929,12 +930,13 @@ static void svm_migrate_timers(struct vc struct periodic_time *pt = &(v->domain->arch.hvm_domain.pl_time.periodic_tm); - if ( pt->enabled ) { - migrate_timer( &pt->timer, v->processor ); - migrate_timer( &v->arch.hvm_vcpu.hlt_timer, v->processor ); - } - if ( hvm_apic_support(v->domain) && VLAPIC( v )) - migrate_timer( &(VLAPIC(v)->vlapic_timer ), v->processor ); + if ( pt->enabled ) + { + migrate_timer(&pt->timer, v->processor); + migrate_timer(&v->arch.hvm_vcpu.hlt_timer, v->processor); + } + if ( VLAPIC(v) != NULL ) + migrate_timer(&VLAPIC(v)->vlapic_timer, v->processor); } @@ -1075,9 +1077,6 @@ static void svm_vmexit_do_cpuid(struct v clear_bit(X86_FEATURE_NX & 31, &edx); } clear_bit(X86_FEATURE_PSE36, &edx); - /* Disable machine check architecture */ - clear_bit(X86_FEATURE_MCA, &edx); - clear_bit(X86_FEATURE_MCE, &edx); if (input == 0x00000001 ) { /* Clear out reserved bits. */ @@ -1470,7 +1469,7 @@ static void svm_io_instruction(struct vc pio_opp->flags |= OVERLAP; if (dir == IOREQ_WRITE) - hvm_copy(&value, addr, size, HVM_COPY_IN); + (void)hvm_copy_from_guest_virt(&value, addr, size); send_pio_req(regs, port, 1, size, value, dir, 0); } @@ -1636,9 +1635,11 @@ static void mov_from_cr(int cr, int gp, case 4: value = (unsigned long) v->arch.hvm_svm.cpu_shadow_cr4; if (svm_dbg_on) - printk( "CR4 read=%lx\n", value ); + printk("CR4 read=%lx\n", value); break; case 8: + if ( vlapic == NULL ) + break; value = (unsigned long)vlapic_get_reg(vlapic, APIC_TASKPRI); value = (value & 0xF0) >> 4; break; @@ -1816,6 +1817,8 @@ static int mov_to_cr(int gpreg, int cr, case 8: { + if ( vlapic == NULL ) + break; vlapic_set_reg(vlapic, APIC_TASKPRI, ((value & 0x0F) << 4)); vlapic_update_ppr(vlapic); break; @@ -1997,7 +2000,7 @@ static inline void svm_do_msr_access( else { inst_len = __get_instruction_length(vmcb, INSTR_WRMSR, NULL); - msr_content = (regs->eax & 0xFFFFFFFF) | ((u64)regs->edx << 32); + msr_content = (u32)regs->eax | ((u64)regs->edx << 32); switch (regs->ecx) { @@ -2324,7 +2327,7 @@ void svm_dump_inst(unsigned long eip) ptr = eip & ~0xff; len = 0; - if (hvm_copy(opcode, ptr, sizeof(opcode), HVM_COPY_IN)) + if (hvm_copy_from_guest_virt(opcode, ptr, sizeof(opcode)) == 0) len = sizeof(opcode); printf("Code bytes around(len=%d) %lx:", len, eip); @@ -2563,9 +2566,7 @@ void walk_shadow_and_guest_pt(unsigned l #endif /* SVM_WALK_GUEST_PAGES */ - - -asmlinkage void svm_vmexit_handler(struct cpu_user_regs regs) +asmlinkage void svm_vmexit_handler(struct cpu_user_regs *regs) { unsigned int exit_reason; unsigned long eip; @@ -2577,7 +2578,7 @@ asmlinkage void svm_vmexit_handler(struc ASSERT(vmcb); exit_reason = vmcb->exitcode; - save_svm_cpu_user_regs(v, ®s); + save_svm_cpu_user_regs(v, regs); vmcb->tlb_control = 1; @@ -2601,26 +2602,26 @@ asmlinkage void svm_vmexit_handler(struc if (svm_paging_enabled(v) && !mmio_space(shadow_gva_to_gpa(current, vmcb->exitinfo2))) { - printk("I%08ld,ExC=%s(%d),IP=%x:%llx," - "I1=%llx,I2=%llx,INT=%llx, " - "gpa=%llx\n", intercepts_counter, - exit_reasons[exit_reason], exit_reason, regs.cs, - (unsigned long long) regs.rip, - (unsigned long long) vmcb->exitinfo1, - (unsigned long long) vmcb->exitinfo2, - (unsigned long long) vmcb->exitintinfo.bytes, - (unsigned long long) shadow_gva_to_gpa(current, vmcb->exitinfo2)); + printk("I%08ld,ExC=%s(%d),IP=%x:%"PRIx64"," + "I1=%"PRIx64",I2=%"PRIx64",INT=%"PRIx64", " + "gpa=%"PRIx64"\n", intercepts_counter, + exit_reasons[exit_reason], exit_reason, regs->cs, + (u64)regs->rip, + (u64)vmcb->exitinfo1, + (u64)vmcb->exitinfo2, + (u64)vmcb->exitintinfo.bytes, + (u64)shadow_gva_to_gpa(current, vmcb->exitinfo2)); } else { - printk("I%08ld,ExC=%s(%d),IP=%x:%llx," - "I1=%llx,I2=%llx,INT=%llx\n", + printk("I%08ld,ExC=%s(%d),IP=%x:%"PRIx64"," + "I1=%"PRIx64",I2=%"PRIx64",INT=%"PRIx64"\n", intercepts_counter, - exit_reasons[exit_reason], exit_reason, regs.cs, - (unsigned long long) regs.rip, - (unsigned long long) vmcb->exitinfo1, - (unsigned long long) vmcb->exitinfo2, - (unsigned long long) vmcb->exitintinfo.bytes ); + exit_reasons[exit_reason], exit_reason, regs->cs, + (u64)regs->rip, + (u64)vmcb->exitinfo1, + (u64)vmcb->exitinfo2, + (u64)vmcb->exitintinfo.bytes ); } } else if ( svm_dbg_on @@ -2630,24 +2631,24 @@ asmlinkage void svm_vmexit_handler(struc if (exit_reasons[exit_reason]) { - printk("I%08ld,ExC=%s(%d),IP=%x:%llx," - "I1=%llx,I2=%llx,INT=%llx\n", + printk("I%08ld,ExC=%s(%d),IP=%x:%"PRIx64"," + "I1=%"PRIx64",I2=%"PRIx64",INT=%"PRIx64"\n", intercepts_counter, - exit_reasons[exit_reason], exit_reason, regs.cs, - (unsigned long long) regs.rip, - (unsigned long long) vmcb->exitinfo1, - (unsigned long long) vmcb->exitinfo2, - (unsigned long long) vmcb->exitintinfo.bytes); + exit_reasons[exit_reason], exit_reason, regs->cs, + (u64)regs->rip, + (u64)vmcb->exitinfo1, + (u64)vmcb->exitinfo2, + (u64)vmcb->exitintinfo.bytes); } else { - printk("I%08ld,ExC=%d(0x%x),IP=%x:%llx," - "I1=%llx,I2=%llx,INT=%llx\n", - intercepts_counter, exit_reason, exit_reason, regs.cs, - (unsigned long long) regs.rip, - (unsigned long long) vmcb->exitinfo1, - (unsigned long long) vmcb->exitinfo2, - (unsigned long long) vmcb->exitintinfo.bytes); + printk("I%08ld,ExC=%d(0x%x),IP=%x:%"PRIx64"," + "I1=%"PRIx64",I2=%"PRIx64",INT=%"PRIx64"\n", + intercepts_counter, exit_reason, exit_reason, regs->cs, + (u64)regs->rip, + (u64)vmcb->exitinfo1, + (u64)vmcb->exitinfo2, + (u64)vmcb->exitintinfo.bytes); } } @@ -2679,7 +2680,7 @@ asmlinkage void svm_vmexit_handler(struc (int) v->arch.shadow_table.pfn); svm_dump_vmcb(__func__, vmcb); - svm_dump_regs(__func__, ®s); + svm_dump_regs(__func__, regs); svm_dump_inst(svm_rip2pointer(vmcb)); } @@ -2709,18 +2710,18 @@ asmlinkage void svm_vmexit_handler(struc case VMEXIT_EXCEPTION_DB: { #ifdef XEN_DEBUGGER - svm_debug_save_cpu_user_regs(®s); - pdb_handle_exception(1, ®s, 1); - svm_debug_restore_cpu_user_regs(®s); + svm_debug_save_cpu_user_regs(regs); + pdb_handle_exception(1, regs, 1); + svm_debug_restore_cpu_user_regs(regs); #else - svm_store_cpu_user_regs(®s, v); + svm_store_cpu_user_regs(regs, v); domain_pause_for_debugger(); #endif } break; case VMEXIT_NMI: - do_nmi(®s, 0); + do_nmi(regs, 0); break; case VMEXIT_SMI: @@ -2740,9 +2741,9 @@ asmlinkage void svm_vmexit_handler(struc case VMEXIT_EXCEPTION_BP: #ifdef XEN_DEBUGGER - svm_debug_save_cpu_user_regs(®s); - pdb_handle_exception(3, ®s, 1); - svm_debug_restore_cpu_user_regs(®s); + svm_debug_save_cpu_user_regs(regs); + pdb_handle_exception(3, regs, 1); + svm_debug_restore_cpu_user_regs(regs); #else if ( test_bit(_DOMF_debugging, &v->domain->domain_flags) ) domain_pause_for_debugger(); @@ -2757,25 +2758,25 @@ asmlinkage void svm_vmexit_handler(struc case VMEXIT_EXCEPTION_GP: /* This should probably not be trapped in the future */ - regs.error_code = vmcb->exitinfo1; - svm_do_general_protection_fault(v, ®s); + regs->error_code = vmcb->exitinfo1; + svm_do_general_protection_fault(v, regs); break; case VMEXIT_EXCEPTION_PF: { unsigned long va; va = vmcb->exitinfo2; - regs.error_code = vmcb->exitinfo1; + regs->error_code = vmcb->exitinfo1; HVM_DBG_LOG(DBG_LEVEL_VMMU, "eax=%lx, ebx=%lx, ecx=%lx, edx=%lx, esi=%lx, edi=%lx", - (unsigned long)regs.eax, (unsigned long)regs.ebx, - (unsigned long)regs.ecx, (unsigned long)regs.edx, - (unsigned long)regs.esi, (unsigned long)regs.edi); - - if (!(error = svm_do_page_fault(va, ®s))) + (unsigned long)regs->eax, (unsigned long)regs->ebx, + (unsigned long)regs->ecx, (unsigned long)regs->edx, + (unsigned long)regs->esi, (unsigned long)regs->edi); + + if (!(error = svm_do_page_fault(va, regs))) { /* Inject #PG using Interruption-Information Fields */ - svm_inject_exception(v, TRAP_page_fault, 1, regs.error_code); + svm_inject_exception(v, TRAP_page_fault, 1, regs->error_code); v->arch.hvm_svm.cpu_cr2 = va; vmcb->cr2 = va; @@ -2788,7 +2789,7 @@ asmlinkage void svm_vmexit_handler(struc case VMEXIT_EXCEPTION_DF: /* Debug info to hopefully help debug WHY the guest double-faulted. */ svm_dump_vmcb(__func__, vmcb); - svm_dump_regs(__func__, ®s); + svm_dump_regs(__func__, regs); svm_dump_inst(svm_rip2pointer(vmcb)); svm_inject_exception(v, TRAP_double_fault, 1, 0); break; @@ -2805,11 +2806,11 @@ asmlinkage void svm_vmexit_handler(struc break; case VMEXIT_TASK_SWITCH: - __hvm_bug(®s); + __hvm_bug(regs); break; case VMEXIT_CPUID: - svm_vmexit_do_cpuid(vmcb, regs.eax, ®s); + svm_vmexit_do_cpuid(vmcb, regs->eax, regs); break; case VMEXIT_HLT: @@ -2817,60 +2818,60 @@ asmlinkage void svm_vmexit_handler(struc break; case VMEXIT_INVLPG: - svm_handle_invlpg(0, ®s); + svm_handle_invlpg(0, regs); break; case VMEXIT_INVLPGA: - svm_handle_invlpg(1, ®s); + svm_handle_invlpg(1, regs); break; case VMEXIT_VMMCALL: - svm_do_vmmcall(v, ®s); + svm_do_vmmcall(v, regs); break; case VMEXIT_CR0_READ: - svm_cr_access(v, 0, TYPE_MOV_FROM_CR, ®s); + svm_cr_access(v, 0, TYPE_MOV_FROM_CR, regs); break; case VMEXIT_CR2_READ: - svm_cr_access(v, 2, TYPE_MOV_FROM_CR, ®s); + svm_cr_access(v, 2, TYPE_MOV_FROM_CR, regs); break; case VMEXIT_CR3_READ: - svm_cr_access(v, 3, TYPE_MOV_FROM_CR, ®s); + svm_cr_access(v, 3, TYPE_MOV_FROM_CR, regs); break; case VMEXIT_CR4_READ: - svm_cr_access(v, 4, TYPE_MOV_FROM_CR, ®s); + svm_cr_access(v, 4, TYPE_MOV_FROM_CR, regs); break; case VMEXIT_CR8_READ: - svm_cr_access(v, 8, TYPE_MOV_FROM_CR, ®s); + svm_cr_access(v, 8, TYPE_MOV_FROM_CR, regs); break; case VMEXIT_CR0_WRITE: - svm_cr_access(v, 0, TYPE_MOV_TO_CR, ®s); + svm_cr_access(v, 0, TYPE_MOV_TO_CR, regs); break; case VMEXIT_CR2_WRITE: - svm_cr_access(v, 2, TYPE_MOV_TO_CR, ®s); + svm_cr_access(v, 2, TYPE_MOV_TO_CR, regs); break; case VMEXIT_CR3_WRITE: - svm_cr_access(v, 3, TYPE_MOV_TO_CR, ®s); + svm_cr_access(v, 3, TYPE_MOV_TO_CR, regs); local_flush_tlb(); break; case VMEXIT_CR4_WRITE: - svm_cr_access(v, 4, TYPE_MOV_TO_CR, ®s); + svm_cr_access(v, 4, TYPE_MOV_TO_CR, regs); break; case VMEXIT_CR8_WRITE: - svm_cr_access(v, 8, TYPE_MOV_TO_CR, ®s); + svm_cr_access(v, 8, TYPE_MOV_TO_CR, regs); break; case VMEXIT_DR0_WRITE ... VMEXIT_DR7_WRITE: - svm_dr_access(v, ®s); + svm_dr_access(v, regs); break; case VMEXIT_IOIO: @@ -2878,7 +2879,7 @@ asmlinkage void svm_vmexit_handler(struc break; case VMEXIT_MSR: - svm_do_msr_access(v, ®s); + svm_do_msr_access(v, regs); break; case VMEXIT_SHUTDOWN: @@ -2887,11 +2888,10 @@ asmlinkage void svm_vmexit_handler(struc break; default: - printk("unexpected VMEXIT: exit reason = 0x%x, exitinfo1 = %llx, " - "exitinfo2 = %llx\n", exit_reason, - (unsigned long long)vmcb->exitinfo1, - (unsigned long long)vmcb->exitinfo2); - __hvm_bug(®s); /* should not happen */ + printk("unexpected VMEXIT: exit reason = 0x%x, exitinfo1 = %"PRIx64", " + "exitinfo2 = %"PRIx64"\n", exit_reason, + (u64)vmcb->exitinfo1, (u64)vmcb->exitinfo2); + __hvm_bug(regs); /* should not happen */ break; } @@ -2899,7 +2899,7 @@ asmlinkage void svm_vmexit_handler(struc if (do_debug) { printk("%s: Done switch on vmexit_code\n", __func__); - svm_dump_regs(__func__, ®s); + svm_dump_regs(__func__, regs); } if (do_debug) diff -r 914c44d10c8d -r 2bfd19fc1b79 xen/arch/x86/hvm/svm/x86_32/exits.S --- a/xen/arch/x86/hvm/svm/x86_32/exits.S Sun Oct 01 11:39:41 2006 -0600 +++ b/xen/arch/x86/hvm/svm/x86_32/exits.S Sun Oct 01 19:10:18 2006 -0600 @@ -126,7 +126,10 @@ ENTRY(svm_asm_do_launch) HVM_SAVE_ALL_NOSEGREGS STGI + movl %esp,%eax + push %eax call svm_vmexit_handler + addl $4,%esp jmp svm_asm_do_resume ALIGN diff -r 914c44d10c8d -r 2bfd19fc1b79 xen/arch/x86/hvm/svm/x86_64/exits.S --- a/xen/arch/x86/hvm/svm/x86_64/exits.S Sun Oct 01 11:39:41 2006 -0600 +++ b/xen/arch/x86/hvm/svm/x86_64/exits.S Sun Oct 01 19:10:18 2006 -0600 @@ -144,6 +144,7 @@ ENTRY(svm_asm_do_launch) VMLOAD STGI + movq %rsp,%rdi call svm_vmexit_handler jmp svm_asm_do_resume diff -r 914c44d10c8d -r 2bfd19fc1b79 xen/arch/x86/hvm/vioapic.c --- a/xen/arch/x86/hvm/vioapic.c Sun Oct 01 11:39:41 2006 -0600 +++ b/xen/arch/x86/hvm/vioapic.c Sun Oct 01 19:10:18 2006 -0600 @@ -479,7 +479,7 @@ static void ioapic_deliver(hvm_vioapic_t static int ioapic_get_highest_irq(hvm_vioapic_t *s) { - uint32_t irqs = s->irr & ~s->isr & ~s->imr; + uint32_t irqs = (s->irr | s->irr_xen) & ~s->isr & ~s->imr; return fls(irqs) - 1; } @@ -501,6 +501,7 @@ static void service_ioapic(hvm_vioapic_t } s->irr &= ~(1 << irqno); + s->irr_xen &= ~(1 << irqno); } } @@ -524,6 +525,25 @@ void hvm_vioapic_do_irqs_clear(struct do s->irr &= ~irqs; service_ioapic(s); +} + +void hvm_vioapic_set_xen_irq(struct domain *d, int irq, int level) +{ + hvm_vioapic_t *s = &d->arch.hvm_domain.vioapic; + + if (!hvm_apic_support(d) || !IOAPICEnabled(s) || + s->redirtbl[irq].RedirForm.mask) + return; + + if (s->redirtbl[irq].RedirForm.trigmod != IOAPIC_LEVEL_TRIGGER) { + DPRINTK("Forcing edge triggered APIC irq %d?\n", irq); + domain_crash(d); + } + + if (level) + s->irr_xen |= 1 << irq; + else + s->irr_xen &= ~(1 << irq); } void hvm_vioapic_set_irq(struct domain *d, int irq, int level) diff -r 914c44d10c8d -r 2bfd19fc1b79 xen/arch/x86/hvm/vmx/io.c --- a/xen/arch/x86/hvm/vmx/io.c Sun Oct 01 11:39:41 2006 -0600 +++ b/xen/arch/x86/hvm/vmx/io.c Sun Oct 01 19:10:18 2006 -0600 @@ -78,7 +78,6 @@ asmlinkage void vmx_intr_assist(void) struct hvm_domain *plat=&v->domain->arch.hvm_domain; struct periodic_time *pt = &plat->pl_time.periodic_tm; struct hvm_virpic *pic= &plat->vpic; - int callback_irq; unsigned int idtv_info_field; unsigned long inst_len; int has_ext_irq; @@ -91,13 +90,12 @@ asmlinkage void vmx_intr_assist(void) pic_set_irq(pic, pt->irq, 1); } - callback_irq = v->domain->arch.hvm_domain.params[HVM_PARAM_CALLBACK_IRQ]; - if ( callback_irq != 0 && - local_events_need_delivery() ) { - /*inject para-device call back irq*/ - v->vcpu_info->evtchn_upcall_mask = 1; - pic_set_irq(pic, callback_irq, 0); - pic_set_irq(pic, callback_irq, 1); + if (v->vcpu_id == 0) { + int callback_irq; + callback_irq = + v->domain->arch.hvm_domain.params[HVM_PARAM_CALLBACK_IRQ]; + if ( callback_irq != 0 ) + pic_set_xen_irq(pic, callback_irq, local_events_need_delivery()); } has_ext_irq = cpu_has_pending_irq(v); diff -r 914c44d10c8d -r 2bfd19fc1b79 xen/arch/x86/hvm/vmx/vmx.c --- a/xen/arch/x86/hvm/vmx/vmx.c Sun Oct 01 11:39:41 2006 -0600 +++ b/xen/arch/x86/hvm/vmx/vmx.c Sun Oct 01 19:10:18 2006 -0600 @@ -135,7 +135,7 @@ static void vmx_relinquish_guest_resourc if ( !test_bit(_VCPUF_initialised, &v->vcpu_flags) ) continue; kill_timer(&v->arch.hvm_vcpu.hlt_timer); - if ( hvm_apic_support(v->domain) && (VLAPIC(v) != NULL) ) + if ( VLAPIC(v) != NULL ) { kill_timer(&VLAPIC(v)->vlapic_timer); unmap_domain_page_global(VLAPIC(v)->regs); @@ -269,15 +269,15 @@ static inline int long_mode_do_msr_read( HVM_DBG_LOG(DBG_LEVEL_2, "msr_content: 0x%"PRIx64, msr_content); - regs->eax = msr_content & 0xffffffff; - regs->edx = msr_content >> 32; + regs->eax = (u32)(msr_content >> 0); + regs->edx = (u32)(msr_content >> 32); return 1; } static inline int long_mode_do_msr_write(struct cpu_user_regs *regs) { - u64 msr_content = regs->eax | ((u64)regs->edx << 32); + u64 msr_content = (u32)regs->eax | ((u64)regs->edx << 32); struct vcpu *v = current; struct vmx_msr_state *msr = &v->arch.hvm_vmx.msr_content; struct vmx_msr_state *host_state = &this_cpu(percpu_msr); @@ -290,7 +290,8 @@ static inline int long_mode_do_msr_write /* offending reserved bit will cause #GP */ if ( msr_content & ~(EFER_LME | EFER_LMA | EFER_NX | EFER_SCE) ) { - printk("trying to set reserved bit in EFER\n"); + printk("Trying to set reserved bit in EFER: %"PRIx64"\n", + msr_content); vmx_inject_hw_exception(v, TRAP_gp_fault, 0); return 0; } @@ -303,7 +304,7 @@ static inline int long_mode_do_msr_write !test_bit(VMX_CPU_STATE_PAE_ENABLED, &v->arch.hvm_vmx.cpu_state) ) { - printk("trying to set LME bit when " + printk("Trying to set LME bit when " "in paging mode or PAE bit is not set\n"); vmx_inject_hw_exception(v, TRAP_gp_fault, 0); return 0; @@ -484,20 +485,23 @@ static void vmx_ctxt_switch_to(struct vc static void stop_vmx(void) { - if (read_cr4() & X86_CR4_VMXE) - __vmxoff(); + if ( !(read_cr4() & X86_CR4_VMXE) ) + return; + __vmxoff(); + clear_in_cr4(X86_CR4_VMXE); } void vmx_migrate_timers(struct vcpu *v) { struct periodic_time *pt = &(v->domain->arch.hvm_domain.pl_time.periodic_tm); - if ( pt->enabled ) { + if ( pt->enabled ) + { migrate_timer(&pt->timer, v->processor); migrate_timer(&v->arch.hvm_vcpu.hlt_timer, v->processor); } - if ( hvm_apic_support(v->domain) && VLAPIC(v)) - migrate_timer(&(VLAPIC(v)->vlapic_timer), v->processor); + if ( VLAPIC(v) != NULL ) + migrate_timer(&VLAPIC(v)->vlapic_timer, v->processor); } static void vmx_store_cpu_guest_regs( @@ -805,12 +809,14 @@ int start_vmx(void) if ( (vmcs = vmx_alloc_host_vmcs()) == NULL ) { + clear_in_cr4(X86_CR4_VMXE); printk("Failed to allocate host VMCS\n"); return 0; } if ( __vmxon(virt_to_maddr(vmcs)) ) { + clear_in_cr4(X86_CR4_VMXE); printk("VMXON failed\n"); vmx_free_host_vmcs(vmcs); return 0; @@ -1163,7 +1169,7 @@ static void vmx_io_instruction(unsigned pio_opp->flags |= OVERLAP; if (dir == IOREQ_WRITE) - hvm_copy(&value, addr, size, HVM_COPY_IN); + (void)hvm_copy_from_guest_virt(&value, addr, size); send_pio_req(regs, port, 1, size, value, dir, 0); } else { if ((addr & PAGE_MASK) != ((addr + count * size - 1) & PAGE_MASK)) { @@ -1370,7 +1376,8 @@ static int vmx_assist(struct vcpu *v, in u32 cp; /* make sure vmxassist exists (this is not an error) */ - if (!hvm_copy(&magic, VMXASSIST_MAGIC_OFFSET, sizeof(magic), HVM_COPY_IN)) + if (hvm_copy_from_guest_phys(&magic, VMXASSIST_MAGIC_OFFSET, + sizeof(magic))) return 0; if (magic != VMXASSIST_MAGIC) return 0; @@ -1384,20 +1391,20 @@ static int vmx_assist(struct vcpu *v, in */ case VMX_ASSIST_INVOKE: /* save the old context */ - if (!hvm_copy(&cp, VMXASSIST_OLD_CONTEXT, sizeof(cp), HVM_COPY_IN)) + if (hvm_copy_from_guest_phys(&cp, VMXASSIST_OLD_CONTEXT, sizeof(cp))) goto error; if (cp != 0) { if (!vmx_world_save(v, &c)) goto error; - if (!hvm_copy(&c, cp, sizeof(c), HVM_COPY_OUT)) + if (hvm_copy_to_guest_phys(cp, &c, sizeof(c))) goto error; } /* restore the new context, this should activate vmxassist */ - if (!hvm_copy(&cp, VMXASSIST_NEW_CONTEXT, sizeof(cp), HVM_COPY_IN)) + if (hvm_copy_from_guest_phys(&cp, VMXASSIST_NEW_CONTEXT, sizeof(cp))) goto error; if (cp != 0) { - if (!hvm_copy(&c, cp, sizeof(c), HVM_COPY_IN)) + if (hvm_copy_from_guest_phys(&c, cp, sizeof(c))) goto error; if (!vmx_world_restore(v, &c)) goto error; @@ -1411,10 +1418,10 @@ static int vmx_assist(struct vcpu *v, in */ case VMX_ASSIST_RESTORE: /* save the old context */ - if (!hvm_copy(&cp, VMXASSIST_OLD_CONTEXT, sizeof(cp), HVM_COPY_IN)) + if (hvm_copy_from_guest_phys(&cp, VMXASSIST_OLD_CONTEXT, sizeof(cp))) goto error; if (cp != 0) { - if (!hvm_copy(&c, cp, sizeof(c), HVM_COPY_IN)) + if (hvm_copy_from_guest_phys(&c, cp, sizeof(c))) goto error; if (!vmx_world_restore(v, &c)) goto error; @@ -1761,6 +1768,8 @@ static int mov_to_cr(int gp, int cr, str } case 8: { + if ( vlapic == NULL ) + break; vlapic_set_reg(vlapic, APIC_TASKPRI, ((value & 0x0F) << 4)); vlapic_update_ppr(vlapic); break; @@ -1782,15 +1791,19 @@ static void mov_from_cr(int cr, int gp, struct vcpu *v = current; struct vlapic *vlapic = VLAPIC(v); - if ( cr != 3 && cr != 8) - __hvm_bug(regs); - - if ( cr == 3 ) - value = (unsigned long) v->arch.hvm_vmx.cpu_cr3; - else if ( cr == 8 ) - { + switch ( cr ) + { + case 3: + value = (unsigned long)v->arch.hvm_vmx.cpu_cr3; + break; + case 8: + if ( vlapic == NULL ) + break; value = (unsigned long)vlapic_get_reg(vlapic, APIC_TASKPRI); value = (value & 0xF0) >> 4; + break; + default: + __hvm_bug(regs); } switch ( gp ) { @@ -1924,7 +1937,7 @@ static inline void vmx_do_msr_write(stru (unsigned long)regs->ecx, (unsigned long)regs->eax, (unsigned long)regs->edx); - msr_content = (regs->eax & 0xFFFFFFFF) | ((u64)regs->edx << 32); + msr_content = (u32)regs->eax | ((u64)regs->edx << 32); switch (regs->ecx) { case MSR_IA32_TIME_STAMP_COUNTER: @@ -2110,7 +2123,7 @@ static void vmx_reflect_exception(struct } } -asmlinkage void vmx_vmexit_handler(struct cpu_user_regs regs) +asmlinkage void vmx_vmexit_handler(struct cpu_user_regs *regs) { unsigned int exit_reason; unsigned long exit_qualification, rip, inst_len = 0; @@ -2181,16 +2194,16 @@ asmlinkage void vmx_vmexit_handler(struc #ifdef XEN_DEBUGGER case TRAP_debug: { - save_cpu_user_regs(®s); - pdb_handle_exception(1, ®s, 1); - restore_cpu_user_regs(®s); + save_cpu_user_regs(regs); + pdb_handle_exception(1, regs, 1); + restore_cpu_user_regs(regs); break; } case TRAP_int3: { - save_cpu_user_regs(®s); - pdb_handle_exception(3, ®s, 1); - restore_cpu_user_regs(®s); + save_cpu_user_regs(regs); + pdb_handle_exception(3, regs, 1); + restore_cpu_user_regs(regs); break; } #else @@ -2200,7 +2213,7 @@ asmlinkage void vmx_vmexit_handler(struc if ( test_bit(_DOMF_debugging, &v->domain->domain_flags) ) { - store_cpu_user_regs(®s); + store_cpu_user_regs(regs); domain_pause_for_debugger(); __vm_clear_bit(GUEST_PENDING_DBG_EXCEPTIONS, PENDING_DEBUG_EXC_BS); @@ -2231,29 +2244,29 @@ asmlinkage void vmx_vmexit_handler(struc case TRAP_page_fault: { __vmread(EXIT_QUALIFICATION, &va); - __vmread(VM_EXIT_INTR_ERROR_CODE, ®s.error_code); - - TRACE_VMEXIT(3,regs.error_code); - TRACE_VMEXIT(4,va); + __vmread(VM_EXIT_INTR_ERROR_CODE, ®s->error_code); + + TRACE_VMEXIT(3, regs->error_code); + TRACE_VMEXIT(4, va); HVM_DBG_LOG(DBG_LEVEL_VMMU, "eax=%lx, ebx=%lx, ecx=%lx, edx=%lx, esi=%lx, edi=%lx", - (unsigned long)regs.eax, (unsigned long)regs.ebx, - (unsigned long)regs.ecx, (unsigned long)regs.edx, - (unsigned long)regs.esi, (unsigned long)regs.edi); - - if ( !vmx_do_page_fault(va, ®s) ) { - /* - * Inject #PG using Interruption-Information Fields - */ - vmx_inject_hw_exception(v, TRAP_page_fault, regs.error_code); + (unsigned long)regs->eax, (unsigned long)regs->ebx, + (unsigned long)regs->ecx, (unsigned long)regs->edx, + (unsigned long)regs->esi, (unsigned long)regs->edi); + + if ( !vmx_do_page_fault(va, regs) ) + { + /* Inject #PG using Interruption-Information Fields. */ + vmx_inject_hw_exception(v, TRAP_page_fault, regs->error_code); v->arch.hvm_vmx.cpu_cr2 = va; - TRACE_3D(TRC_VMX_INT, v->domain->domain_id, TRAP_page_fault, va); + TRACE_3D(TRC_VMX_INT, v->domain->domain_id, + TRAP_page_fault, va); } break; } case TRAP_nmi: - do_nmi(®s); + do_nmi(regs); break; default: vmx_reflect_exception(v); @@ -2262,7 +2275,7 @@ asmlinkage void vmx_vmexit_handler(struc break; } case EXIT_REASON_EXTERNAL_INTERRUPT: - vmx_vmexit_do_extint(®s); + vmx_vmexit_do_extint(regs); break; case EXIT_REASON_TRIPLE_FAULT: domain_crash_synchronous(); @@ -2279,7 +2292,7 @@ asmlinkage void vmx_vmexit_handler(struc case EXIT_REASON_CPUID: inst_len = __get_instruction_length(); /* Safe: CPUID */ __update_guest_eip(inst_len); - vmx_vmexit_do_cpuid(®s); + vmx_vmexit_do_cpuid(regs); break; case EXIT_REASON_HLT: inst_len = __get_instruction_length(); /* Safe: HLT */ @@ -2301,7 +2314,7 @@ asmlinkage void vmx_vmexit_handler(struc __update_guest_eip(inst_len); __vmread(GUEST_RIP, &rip); __vmread(EXIT_QUALIFICATION, &exit_qualification); - hvm_do_hypercall(®s); + hvm_do_hypercall(regs); break; } case EXIT_REASON_CR_ACCESS: @@ -2309,15 +2322,15 @@ asmlinkage void vmx_vmexit_handler(struc __vmread(GUEST_RIP, &rip); __vmread(EXIT_QUALIFICATION, &exit_qualification); inst_len = __get_instruction_length(); /* Safe: MOV Cn, LMSW, CLTS */ - if ( vmx_cr_access(exit_qualification, ®s) ) + if ( vmx_cr_access(exit_qualification, regs) ) __update_guest_eip(inst_len); - TRACE_VMEXIT(3,regs.error_code); - TRACE_VMEXIT(4,exit_qualification); + TRACE_VMEXIT(3, regs->error_code); + TRACE_VMEXIT(4, exit_qualification); break; } case EXIT_REASON_DR_ACCESS: __vmread(EXIT_QUALIFICATION, &exit_qualification); - vmx_dr_access(exit_qualification, ®s); + vmx_dr_access(exit_qualification, regs); break; case EXIT_REASON_IO_INSTRUCTION: __vmread(EXIT_QUALIFICATION, &exit_qualification); @@ -2328,12 +2341,12 @@ asmlinkage void vmx_vmexit_handler(struc case EXIT_REASON_MSR_READ: inst_len = __get_instruction_length(); /* Safe: RDMSR */ __update_guest_eip(inst_len); - vmx_do_msr_read(®s); + vmx_do_msr_read(regs); break; case EXIT_REASON_MSR_WRITE: inst_len = __get_instruction_length(); /* Safe: WRMSR */ __update_guest_eip(inst_len); - vmx_do_msr_write(®s); + vmx_do_msr_write(regs); break; case EXIT_REASON_MWAIT_INSTRUCTION: case EXIT_REASON_MONITOR_INSTRUCTION: diff -r 914c44d10c8d -r 2bfd19fc1b79 xen/arch/x86/hvm/vmx/x86_32/exits.S --- a/xen/arch/x86/hvm/vmx/x86_32/exits.S Sun Oct 01 11:39:41 2006 -0600 +++ b/xen/arch/x86/hvm/vmx/x86_32/exits.S Sun Oct 01 19:10:18 2006 -0600 @@ -82,7 +82,10 @@ ENTRY(vmx_asm_vmexit_handler) /* selectors are restored/saved by VMX */ HVM_SAVE_ALL_NOSEGREGS call vmx_trace_vmexit + movl %esp,%eax + push %eax call vmx_vmexit_handler + addl $4,%esp jmp vmx_asm_do_vmentry ALIGN diff -r 914c44d10c8d -r 2bfd19fc1b79 xen/arch/x86/hvm/vmx/x86_64/exits.S --- a/xen/arch/x86/hvm/vmx/x86_64/exits.S Sun Oct 01 11:39:41 2006 -0600 +++ b/xen/arch/x86/hvm/vmx/x86_64/exits.S Sun Oct 01 19:10:18 2006 -0600 @@ -93,6 +93,7 @@ ENTRY(vmx_asm_vmexit_handler) /* selectors are restored/saved by VMX */ HVM_SAVE_ALL_NOSEGREGS call vmx_trace_vmexit + movq %rsp,%rdi call vmx_vmexit_handler jmp vmx_asm_do_vmentry diff -r 914c44d10c8d -r 2bfd19fc1b79 xen/arch/x86/mm.c --- a/xen/arch/x86/mm.c Sun Oct 01 11:39:41 2006 -0600 +++ b/xen/arch/x86/mm.c Sun Oct 01 19:10:18 2006 -0600 @@ -427,23 +427,11 @@ int map_ldt_shadow_page(unsigned int off unsigned long gmfn, mfn; l1_pgentry_t l1e, nl1e; unsigned long gva = v->arch.guest_context.ldt_base + (off << PAGE_SHIFT); - int res; - -#if defined(__x86_64__) - /* If in user mode, switch to kernel mode just to read LDT mapping. */ - int user_mode = !(v->arch.flags & TF_kernel_mode); -#define TOGGLE_MODE() if ( user_mode ) toggle_guest_mode(v) -#elif defined(__i386__) -#define TOGGLE_MODE() ((void)0) -#endif + int okay; BUG_ON(unlikely(in_irq())); - TOGGLE_MODE(); - __copy_from_user(&l1e, &linear_pg_table[l1_linear_offset(gva)], - sizeof(l1e)); - TOGGLE_MODE(); - + guest_get_eff_kern_l1e(v, gva, &l1e); if ( unlikely(!(l1e_get_flags(l1e) & _PAGE_PRESENT)) ) return 0; @@ -452,17 +440,17 @@ int map_ldt_shadow_page(unsigned int off if ( unlikely(!VALID_MFN(mfn)) ) return 0; - res = get_page_and_type(mfn_to_page(mfn), d, PGT_ldt_page); - - if ( !res && unlikely(shadow_mode_refcounts(d)) ) + okay = get_page_and_type(mfn_to_page(mfn), d, PGT_ldt_page); + + if ( !okay && unlikely(shadow_mode_refcounts(d)) ) { shadow_lock(d); shadow_remove_write_access(d->vcpu[0], _mfn(mfn), 0, 0); - res = get_page_and_type(mfn_to_page(mfn), d, PGT_ldt_page); + okay = get_page_and_type(mfn_to_page(mfn), d, PGT_ldt_page); shadow_unlock(d); } - if ( unlikely(!res) ) + if ( unlikely(!okay) ) return 0; nl1e = l1e_from_pfn(mfn, l1e_get_flags(l1e) | _PAGE_RW); @@ -1233,7 +1221,7 @@ static inline int update_l1e(l1_pgentry_ } } #endif - if ( unlikely(shadow_mode_enabled(v->domain)) ) + if ( unlikely(shadow_mode_enabled(v->domain)) && rv ) { shadow_validate_guest_entry(v, _mfn(gl1mfn), pl1e); shadow_unlock(v->domain); @@ -1251,6 +1239,9 @@ static int mod_l1_entry(l1_pgentry_t *pl if ( unlikely(__copy_from_user(&ol1e, pl1e, sizeof(ol1e)) != 0) ) return 0; + + if ( unlikely(shadow_mode_refcounts(d)) ) + return update_l1e(pl1e, ol1e, nl1e, gl1mfn, current); if ( l1e_get_flags(nl1e) & _PAGE_PRESENT ) { @@ -1544,9 +1535,7 @@ void free_page_type(struct page_info *pa gmfn = mfn_to_gmfn(owner, page_to_mfn(page)); ASSERT(VALID_M2P(gmfn)); - shadow_lock(owner); shadow_remove_all_shadows(owner->vcpu[0], _mfn(gmfn)); - shadow_unlock(owner); } } @@ -1618,8 +1607,8 @@ void put_page_type(struct page_info *pag * 2. Shadow mode reuses this field for shadowed page tables to * store flags info -- we don't want to conflict with that. */ - if ( !shadow_mode_enabled(page_get_owner(page)) || - ((nx & PGT_type_mask) == PGT_writable_page) ) + if ( !(shadow_mode_enabled(page_get_owner(page)) && + (page->count_info & PGC_page_table)) ) page->tlbflush_timestamp = tlbflush_current_time(); } } @@ -1644,6 +1633,12 @@ int get_page_type(struct page_info *page } else if ( unlikely((x & PGT_count_mask) == 0) ) { + struct domain *d = page_get_owner(page); + + /* Never allow a shadowed frame to go from type count 0 to 1 */ + if ( d && shadow_mode_enabled(d) ) + shadow_remove_all_shadows(d->vcpu[0], _mfn(page_to_mfn(page))); + ASSERT(!(x & PGT_pae_xen_l2)); if ( (x & PGT_type_mask) != type ) { @@ -1652,8 +1647,9 @@ int get_page_type(struct page_info *page * may be unnecessary (e.g., page was GDT/LDT) but those * circumstances should be very rare. */ - cpumask_t mask = - page_get_owner(page)->domain_dirty_cpumask; + cpumask_t mask = d->domain_dirty_cpumask; + + /* Don't flush if the timestamp is old enough */ tlbflush_filter(mask, page->tlbflush_timestamp); if ( unlikely(!cpus_empty(mask)) && @@ -1866,6 +1862,14 @@ static int set_foreigndom(domid_t domid) } } + if ( unlikely(shadow_mode_translate(d)) ) + { + MEM_LOG("%s: can not mix foreign mappings with translated domains", + __func__); + info->foreign = NULL; + okay = 0; + } + out: return okay; } @@ -1897,7 +1901,7 @@ int do_mmuext_op( { struct mmuext_op op; int rc = 0, i = 0, okay; - unsigned long mfn, type; + unsigned long mfn = 0, gmfn = 0, type; unsigned int done = 0; struct page_info *page; struct vcpu *v = current; @@ -1942,7 +1946,8 @@ int do_mmuext_op( } okay = 1; - mfn = op.arg1.mfn; + gmfn = op.arg1.mfn; + mfn = gmfn_to_mfn(FOREIGNDOM, gmfn); page = mfn_to_page(mfn); switch ( op.cmd ) @@ -2017,7 +2022,6 @@ int do_mmuext_op( break; case MMUEXT_NEW_BASEPTR: - mfn = gmfn_to_mfn(current->domain, mfn); okay = new_guest_cr3(mfn); this_cpu(percpu_mm_info).deferred_ops &= ~DOP_FLUSH_TLB; break; @@ -2026,8 +2030,13 @@ int do_mmuext_op( case MMUEXT_NEW_USER_BASEPTR: okay = 1; if (likely(mfn != 0)) - okay = get_page_and_type_from_pagenr( - mfn, PGT_root_page_table, d); + { + if ( shadow_mode_refcounts(d) ) + okay = get_page_from_pagenr(mfn, d); + else + okay = get_page_and_type_from_pagenr( + mfn, PGT_root_page_table, d); + } if ( unlikely(!okay) ) { MEM_LOG("Error while installing new mfn %lx", mfn); @@ -2038,7 +2047,12 @@ int do_mmuext_op( pagetable_get_pfn(v->arch.guest_table_user); v->arch.guest_table_user = pagetable_from_pfn(mfn); if ( old_mfn != 0 ) - put_page_and_type(mfn_to_page(old_mfn)); + { + if ( shadow_mode_refcounts(d) ) + put_page(mfn_to_page(old_mfn)); + else + put_page_and_type(mfn_to_page(old_mfn)); + } } break; #endif @@ -2499,17 +2513,26 @@ static int create_grant_va_mapping( { l1_pgentry_t *pl1e, ol1e; struct domain *d = v->domain; + unsigned long gl1mfn; + int okay; ASSERT(spin_is_locked(&d->big_lock)); adjust_guest_l1e(nl1e); - pl1e = &linear_pg_table[l1_linear_offset(va)]; - - if ( unlikely(__copy_from_user(&ol1e, pl1e, sizeof(ol1e)) != 0) || - !update_l1e(pl1e, ol1e, nl1e, - l2e_get_pfn(__linear_l2_table[l2_linear_offset(va)]), v) ) + pl1e = guest_map_l1e(v, va, &gl1mfn); + if ( !pl1e ) + { + MEM_LOG("Could not find L1 PTE for address %lx", va); return GNTST_general_error; + } + ol1e = *pl1e; + okay = update_l1e(pl1e, ol1e, nl1e, gl1mfn, v); + guest_unmap_l1e(v, pl1e); + pl1e = NULL; + + if ( !okay ) + return GNTST_general_error; if ( !shadow_mode_refcounts(d) ) put_page_from_l1e(ol1e, d); @@ -2518,17 +2541,19 @@ static int create_grant_va_mapping( } static int destroy_grant_va_mapping( - unsigned long addr, unsigned long frame, struct domain *d) + unsigned long addr, unsigned long frame, struct vcpu *v) { l1_pgentry_t *pl1e, ol1e; + unsigned long gl1mfn; + int rc = 0; - pl1e = &linear_pg_table[l1_linear_offset(addr)]; - - if ( unlikely(__get_user(ol1e.l1, &pl1e->l1) != 0) ) - { - MEM_LOG("Could not find PTE entry for address %lx", addr); + pl1e = guest_map_l1e(v, addr, &gl1mfn); + if ( !pl1e ) + { + MEM_LOG("Could not find L1 PTE for address %lx", addr); return GNTST_general_error; } + ol1e = *pl1e; /* * Check that the virtual address supplied is actually mapped to @@ -2538,19 +2563,21 @@ static int destroy_grant_va_mapping( { MEM_LOG("PTE entry %lx for address %lx doesn't match frame %lx", l1e_get_pfn(ol1e), addr, frame); - return GNTST_general_error; + rc = GNTST_general_error; + goto out; } /* Delete pagetable entry. */ - if ( unlikely(!update_l1e(pl1e, ol1e, l1e_empty(), - l2e_get_pfn(__linear_l2_table[l2_linear_offset(addr)]), - d->vcpu[0] /* Change for per-vcpu shadows */)) ) + if ( unlikely(!update_l1e(pl1e, ol1e, l1e_empty(), gl1mfn, v)) ) { MEM_LOG("Cannot delete PTE entry at %p", (unsigned long *)pl1e); - return GNTST_general_error; - } - - return 0; + rc = GNTST_general_error; + goto out; // this is redundant & unnecessary, but informative + } + + out: + guest_unmap_l1e(v, pl1e); + return rc; } int create_grant_host_mapping( @@ -2573,7 +2600,7 @@ int destroy_grant_host_mapping( { if ( flags & GNTMAP_contains_pte ) return destroy_grant_pte_mapping(addr, frame, current->domain); - return destroy_grant_va_mapping(addr, frame, current->domain); + return destroy_grant_va_mapping(addr, frame, current); } int steal_page( @@ -2629,7 +2656,8 @@ int do_update_va_mapping(unsigned long v l1_pgentry_t val = l1e_from_intpte(val64); struct vcpu *v = current; struct domain *d = v->domain; - unsigned long vmask, bmap_ptr; + l1_pgentry_t *pl1e; + unsigned long vmask, bmap_ptr, gl1mfn; cpumask_t pmask; int rc = 0; @@ -2638,35 +2666,17 @@ int do_update_va_mapping(unsigned long v if ( unlikely(!__addr_ok(va) && !shadow_mode_external(d)) ) return -EINVAL; - if ( unlikely(shadow_mode_refcounts(d)) ) - { - DPRINTK("Grant op on a shadow-refcounted domain\n"); - return -EINVAL; - } - LOCK_BIGLOCK(d); - if ( likely(rc == 0) && unlikely(shadow_mode_enabled(d)) ) - { - if ( unlikely(this_cpu(percpu_mm_info).foreign && - (shadow_mode_translate(d) || - shadow_mode_translate( - this_cpu(percpu_mm_info).foreign))) ) - { - /* - * The foreign domain's pfn's are in a different namespace. There's - * not enough information in just a gpte to figure out how to - * (re-)shadow this entry. - */ - domain_crash(d); - } - } - - if ( unlikely(!mod_l1_entry( - &linear_pg_table[l1_linear_offset(va)], val, - l2e_get_pfn(__linear_l2_table[l2_linear_offset(va)]))) ) + pl1e = guest_map_l1e(v, va, &gl1mfn); + + if ( unlikely(!pl1e || !mod_l1_entry(pl1e, val, gl1mfn)) ) rc = -EINVAL; - + + if ( pl1e ) + guest_unmap_l1e(v, pl1e); + pl1e = NULL; + switch ( flags & UVMF_FLUSHTYPE_MASK ) { case UVMF_TLB_FLUSH: @@ -3028,7 +3038,7 @@ static int ptwr_emulated_update( unsigned int bytes, unsigned int do_cmpxchg) { - unsigned long pfn; + unsigned long gmfn, mfn; struct page_info *page; l1_pgentry_t pte, ol1e, nl1e, *pl1e; struct vcpu *v = current; @@ -3068,15 +3078,17 @@ static int ptwr_emulated_update( } /* Read the PTE that maps the page being updated. */ - if ( __copy_from_user(&pte, &linear_pg_table[l1_linear_offset(addr)], - sizeof(pte)) ) - { - MEM_LOG("ptwr_emulate: Cannot read thru linear_pg_table"); + guest_get_eff_l1e(v, addr, &pte); + if ( unlikely(!(l1e_get_flags(pte) & _PAGE_PRESENT)) ) + { + MEM_LOG("%s: Cannot get L1 PTE for guest address %lx", + __func__, addr); return X86EMUL_UNHANDLEABLE; } - pfn = l1e_get_pfn(pte); - page = mfn_to_page(pfn); + gmfn = l1e_get_pfn(pte); + mfn = gmfn_to_mfn(d, gmfn); + page = mfn_to_page(mfn); /* We are looking only for read-only mappings of p.t. pages. */ ASSERT((l1e_get_flags(pte) & (_PAGE_RW|_PAGE_PRESENT)) == _PAGE_PRESENT); @@ -3086,7 +3098,7 @@ static int ptwr_emulated_update( /* Check the new PTE. */ nl1e = l1e_from_intpte(val); - if ( unlikely(!get_page_from_l1e(nl1e, d)) ) + if ( unlikely(!get_page_from_l1e(gl1e_to_ml1e(d, nl1e), d)) ) { if ( (CONFIG_PAGING_LEVELS == 3) && (bytes == 4) && @@ -3125,13 +3137,13 @@ static int ptwr_emulated_update( if ( shadow_mode_enabled(d) ) shadow_unlock(d); unmap_domain_page(pl1e); - put_page_from_l1e(nl1e, d); + put_page_from_l1e(gl1e_to_ml1e(d, nl1e), d); return X86EMUL_CMPXCHG_FAILED; } - if ( unlikely(shadow_mode_enabled(v->domain)) ) + if ( unlikely(shadow_mode_enabled(d)) ) { shadow_validate_guest_entry(v, _mfn(page_to_mfn(page)), pl1e); - shadow_unlock(v->domain); + shadow_unlock(d); } } else @@ -3144,7 +3156,7 @@ static int ptwr_emulated_update( unmap_domain_page(pl1e); /* Finally, drop the old PTE. */ - put_page_from_l1e(ol1e, d); + put_page_from_l1e(gl1e_to_ml1e(d, ol1e), d); return X86EMUL_CONTINUE; } @@ -3193,13 +3205,13 @@ static struct x86_emulate_ops ptwr_emula }; /* Write page fault handler: check if guest is trying to modify a PTE. */ -int ptwr_do_page_fault(struct domain *d, unsigned long addr, +int ptwr_do_page_fault(struct vcpu *v, unsigned long addr, struct cpu_user_regs *regs) { + struct domain *d = v->domain; unsigned long pfn; struct page_info *page; l1_pgentry_t pte; - l2_pgentry_t *pl2e, l2e; struct x86_emulate_ctxt emul_ctxt; LOCK_BIGLOCK(d); @@ -3208,13 +3220,9 @@ int ptwr_do_page_fault(struct domain *d, * Attempt to read the PTE that maps the VA being accessed. By checking for * PDE validity in the L2 we avoid many expensive fixups in __get_user(). */ - pl2e = &__linear_l2_table[l2_linear_offset(addr)]; - if ( __copy_from_user(&l2e, pl2e, sizeof(l2e)) || - !(l2e_get_flags(l2e) & _PAGE_PRESENT) || - __copy_from_user(&pte, &linear_pg_table[l1_linear_offset(addr)], - sizeof(pte)) ) + guest_get_eff_l1e(v, addr, &pte); + if ( !(l1e_get_flags(pte) & _PAGE_PRESENT) ) goto bail; - pfn = l1e_get_pfn(pte); page = mfn_to_page(pfn); diff -r 914c44d10c8d -r 2bfd19fc1b79 xen/arch/x86/mm/shadow/common.c --- a/xen/arch/x86/mm/shadow/common.c Sun Oct 01 11:39:41 2006 -0600 +++ b/xen/arch/x86/mm/shadow/common.c Sun Oct 01 19:10:18 2006 -0600 @@ -75,35 +75,27 @@ sh_x86_emulate_read_std(unsigned long ad unsigned int bytes, struct x86_emulate_ctxt *ctxt) { - struct vcpu *v = current; - if ( hvm_guest(v) ) - { - *val = 0; - // XXX -- this is WRONG. - // It entirely ignores the permissions in the page tables. - // In this case, that is only a user vs supervisor access check. - // - if ( hvm_copy(val, addr, bytes, HVM_COPY_IN) ) - { + *val = 0; + // XXX -- this is WRONG. + // It entirely ignores the permissions in the page tables. + // In this case, that is only a user vs supervisor access check. + // + if ( hvm_copy_from_guest_virt(val, addr, bytes) == 0 ) + { #if 0 - SHADOW_PRINTK("d=%u v=%u a=%#lx v=%#lx bytes=%u\n", - v->domain->domain_id, v->vcpu_id, - addr, *val, bytes); -#endif - return X86EMUL_CONTINUE; - } - - /* If we got here, there was nothing mapped here, or a bad GFN - * was mapped here. This should never happen: we're here because - * of a write fault at the end of the instruction we're emulating. */ - SHADOW_PRINTK("read failed to va %#lx\n", addr); - return X86EMUL_PROPAGATE_FAULT; - } - else - { - SHADOW_PRINTK("this operation is not emulated yet\n"); - return X86EMUL_UNHANDLEABLE; - } + struct vcpu *v = current; + SHADOW_PRINTK("d=%u v=%u a=%#lx v=%#lx bytes=%u\n", + v->domain->domain_id, v->vcpu_id, + addr, *val, bytes); +#endif + return X86EMUL_CONTINUE; + } + + /* If we got here, there was nothing mapped here, or a bad GFN + * was mapped here. This should never happen: we're here because + * of a write fault at the end of the instruction we're emulating. */ + SHADOW_PRINTK("read failed to va %#lx\n", addr); + return X86EMUL_PROPAGATE_FAULT; } static int @@ -112,33 +104,26 @@ sh_x86_emulate_write_std(unsigned long a unsigned int bytes, struct x86_emulate_ctxt *ctxt) { +#if 0 struct vcpu *v = current; -#if 0 SHADOW_PRINTK("d=%u v=%u a=%#lx v=%#lx bytes=%u\n", v->domain->domain_id, v->vcpu_id, addr, val, bytes); #endif - if ( hvm_guest(v) ) - { - // XXX -- this is WRONG. - // It entirely ignores the permissions in the page tables. - // In this case, that includes user vs supervisor, and - // write access. - // - if ( hvm_copy(&val, addr, bytes, HVM_COPY_OUT) ) - return X86EMUL_CONTINUE; - - /* If we got here, there was nothing mapped here, or a bad GFN - * was mapped here. This should never happen: we're here because - * of a write fault at the end of the instruction we're emulating, - * which should be handled by sh_x86_emulate_write_emulated. */ - SHADOW_PRINTK("write failed to va %#lx\n", addr); - return X86EMUL_PROPAGATE_FAULT; - } - else - { - SHADOW_PRINTK("this operation is not emulated yet\n"); - return X86EMUL_UNHANDLEABLE; - } + + // XXX -- this is WRONG. + // It entirely ignores the permissions in the page tables. + // In this case, that includes user vs supervisor, and + // write access. + // + if ( hvm_copy_to_guest_virt(addr, &val, bytes) == 0 ) + return X86EMUL_CONTINUE; + + /* If we got here, there was nothing mapped here, or a bad GFN + * was mapped here. This should never happen: we're here because + * of a write fault at the end of the instruction we're emulating, + * which should be handled by sh_x86_emulate_write_emulated. */ + SHADOW_PRINTK("write failed to va %#lx\n", addr); + return X86EMUL_PROPAGATE_FAULT; } static int @@ -152,15 +137,7 @@ sh_x86_emulate_write_emulated(unsigned l SHADOW_PRINTK("d=%u v=%u a=%#lx v=%#lx bytes=%u\n", v->domain->domain_id, v->vcpu_id, addr, val, bytes); #endif - if ( hvm_guest(v) ) - { - return v->arch.shadow.mode->x86_emulate_write(v, addr, &val, bytes, ctxt); - } - else - { - SHADOW_PRINTK("this operation is not emulated yet\n"); - return X86EMUL_UNHANDLEABLE; - } + return v->arch.shadow.mode->x86_emulate_write(v, addr, &val, bytes, ctxt); } static int @@ -175,16 +152,8 @@ sh_x86_emulate_cmpxchg_emulated(unsigned SHADOW_PRINTK("d=%u v=%u a=%#lx o?=%#lx n:=%#lx bytes=%u\n", v->domain->domain_id, v->vcpu_id, addr, old, new, bytes); #endif - if ( hvm_guest(v) ) - { - return v->arch.shadow.mode->x86_emulate_cmpxchg(v, addr, old, new, - bytes, ctxt); - } - else - { - SHADOW_PRINTK("this operation is not emulated yet\n"); - return X86EMUL_UNHANDLEABLE; - } + return v->arch.shadow.mode->x86_emulate_cmpxchg(v, addr, old, new, + bytes, ctxt); } static int @@ -201,16 +170,8 @@ sh_x86_emulate_cmpxchg8b_emulated(unsign v->domain->domain_id, v->vcpu_id, addr, old_hi, old_lo, new_hi, new_lo, ctxt); #endif - if ( hvm_guest(v) ) - { - return v->arch.shadow.mode->x86_emulate_cmpxchg8b(v, addr, old_lo, old_hi, - new_lo, new_hi, ctxt); - } - else - { - SHADOW_PRINTK("this operation is not emulated yet\n"); - return X86EMUL_UNHANDLEABLE; - } + return v->arch.shadow.mode->x86_emulate_cmpxchg8b(v, addr, old_lo, old_hi, + new_lo, new_hi, ctxt); } @@ -256,14 +217,18 @@ void shadow_demote(struct vcpu *v, mfn_t clear_bit(type >> PGC_SH_type_shift, &page->shadow_flags); if ( (page->shadow_flags & SHF_page_type_mask) == 0 ) + { + /* tlbflush timestamp field is valid again */ + page->tlbflush_timestamp = tlbflush_current_time(); clear_bit(_PGC_page_table, &page->count_info); + } } /**************************************************************************/ /* Validate a pagetable change from the guest and update the shadows. * Returns a bitmask of SHADOW_SET_* flags. */ -static int +int __shadow_validate_guest_entry(struct vcpu *v, mfn_t gmfn, void *entry, u32 size) { @@ -363,7 +328,9 @@ void void shadow_validate_guest_pt_write(struct vcpu *v, mfn_t gmfn, void *entry, u32 size) -/* This is the entry point for emulated writes to pagetables in HVM guests */ +/* This is the entry point for emulated writes to pagetables in HVM guests and + * PV translated guests. + */ { struct domain *d = v->domain; int rc; @@ -802,7 +769,7 @@ void shadow_free(struct domain *d, mfn_t /* Divert some memory from the pool to be used by the p2m mapping. * This action is irreversible: the p2m mapping only ever grows. - * That's OK because the p2m table only exists for external domains, + * That's OK because the p2m table only exists for translated domains, * and those domains can't ever turn off shadow mode. * Also, we only ever allocate a max-order chunk, so as to preserve * the invariant that shadow_prealloc() always works. @@ -826,7 +793,12 @@ shadow_alloc_p2m_pages(struct domain *d) d->arch.shadow.total_pages -= (1<<SHADOW_MAX_ORDER); for (i = 0; i < (1<<SHADOW_MAX_ORDER); i++) { - /* Unlike shadow pages, mark p2m pages as owned by the domain */ + /* Unlike shadow pages, mark p2m pages as owned by the domain. + * Marking the domain as the owner would normally allow the guest to + * create mappings of these pages, but these p2m pages will never be + * in the domain's guest-physical address space, and so that is not + * believed to be a concern. + */ page_set_owner(&pg[i], d); list_add_tail(&pg[i].list, &d->arch.shadow.p2m_freelist); } @@ -2265,7 +2237,7 @@ void sh_update_paging_modes(struct vcpu // if ( !test_bit(_VCPUF_initialised, &v->vcpu_flags) ) { - printk("%s: postponing determination of shadow mode\n", __func__); + SHADOW_PRINTK("%s: postponing determination of shadow mode\n", __func__); return; } @@ -2290,6 +2262,7 @@ void sh_update_paging_modes(struct vcpu #else #error unexpected paging mode #endif + v->arch.shadow.translate_enabled = !!shadow_mode_translate(d); } else { @@ -2299,8 +2272,8 @@ void sh_update_paging_modes(struct vcpu ASSERT(shadow_mode_translate(d)); ASSERT(shadow_mode_external(d)); - v->arch.shadow.hvm_paging_enabled = !!hvm_paging_enabled(v); - if ( !v->arch.shadow.hvm_paging_enabled ) + v->arch.shadow.translate_enabled = !!hvm_paging_enabled(v); + if ( !v->arch.shadow.translate_enabled ) { /* Set v->arch.guest_table to use the p2m map, and choose @@ -2377,13 +2350,14 @@ void sh_update_paging_modes(struct vcpu if ( v->arch.shadow.mode != old_mode ) { - SHADOW_PRINTK("new paging mode: d=%u v=%u g=%u s=%u " - "(was g=%u s=%u)\n", - d->domain_id, v->vcpu_id, - v->arch.shadow.mode->guest_levels, - v->arch.shadow.mode->shadow_levels, - old_mode ? old_mode->guest_levels : 0, - old_mode ? old_mode->shadow_levels : 0); + SHADOW_PRINTK("new paging mode: d=%u v=%u pe=%d g=%u s=%u " + "(was g=%u s=%u)\n", + d->domain_id, v->vcpu_id, + hvm_guest(v) ? !!hvm_paging_enabled(v) : 1, + v->arch.shadow.mode->guest_levels, + v->arch.shadow.mode->shadow_levels, + old_mode ? old_mode->guest_levels : 0, + old_mode ? old_mode->shadow_levels : 0); if ( old_mode && (v->arch.shadow.mode->shadow_levels != old_mode->shadow_levels) ) @@ -2463,6 +2437,7 @@ static int shadow_enable(struct domain * /* Sanity check the arguments */ if ( (d == current->domain) || shadow_mode_enabled(d) || + ((mode & SHM2_translate) && !(mode & SHM2_refcounts)) || ((mode & SHM2_external) && !(mode & SHM2_translate)) ) { rv = -EINVAL; @@ -2518,7 +2493,7 @@ static int shadow_enable(struct domain * out: shadow_unlock(d); domain_unpause(d); - return 0; + return rv; } void shadow_teardown(struct domain *d) diff -r 914c44d10c8d -r 2bfd19fc1b79 xen/arch/x86/mm/shadow/multi.c --- a/xen/arch/x86/mm/shadow/multi.c Sun Oct 01 11:39:41 2006 -0600 +++ b/xen/arch/x86/mm/shadow/multi.c Sun Oct 01 19:10:18 2006 -0600 @@ -483,8 +483,7 @@ static u32 guest_set_ad_bits(struct vcpu unsigned int level, fetch_type_t ft) { - u32 flags, shflags, bit; - struct page_info *pg; + u32 flags; int res = 0; ASSERT(valid_mfn(gmfn) @@ -502,11 +501,10 @@ static u32 guest_set_ad_bits(struct vcpu if ( unlikely(GUEST_PAGING_LEVELS == 3 && level == 3) ) return flags; - /* Need the D bit as well for writes, in l1es and 32bit/PAE PSE l2es. */ + /* Need the D bit as well for writes, in L1es and PSE L2es. */ if ( ft == ft_demand_write - && (level == 1 || - (level == 2 && GUEST_PAGING_LEVELS < 4 - && (flags & _PAGE_PSE) && guest_supports_superpages(v))) ) + && (level == 1 || + (level == 2 && (flags & _PAGE_PSE) && guest_supports_superpages(v))) ) { if ( (flags & (_PAGE_DIRTY | _PAGE_ACCESSED)) == (_PAGE_DIRTY | _PAGE_ACCESSED) ) @@ -524,76 +522,69 @@ static u32 guest_set_ad_bits(struct vcpu /* Set the bit(s) */ sh_mark_dirty(v->domain, gmfn); - SHADOW_DEBUG(A_AND_D, "gfn = %"SH_PRI_gfn", " + SHADOW_DEBUG(A_AND_D, "gfn = %" SH_PRI_gfn ", " "old flags = %#x, new flags = %#x\n", - guest_l1e_get_gfn(*ep), guest_l1e_get_flags(*ep), flags); + gfn_x(guest_l1e_get_gfn(*ep)), guest_l1e_get_flags(*ep), flags); *ep = guest_l1e_from_gfn(guest_l1e_get_gfn(*ep), flags); - /* May need to propagate this change forward to other kinds of shadow */ - pg = mfn_to_page(gmfn); - if ( !sh_mfn_is_a_page_table(gmfn) ) - { - /* This guest pagetable is not yet shadowed at all. */ - // MAF: I think this assert is busted... If this gmfn has not yet - // been promoted, then it seems perfectly reasonable for there to be - // outstanding type refs to it... - /* TJD: No. If the gmfn has not been promoted, we must at least - * have recognised that it is a pagetable, and pulled write access. - * The type count should only be non-zero if it is actually a page - * table. The test above was incorrect, though, so I've fixed it. */ - ASSERT((pg->u.inuse.type_info & PGT_count_mask) == 0); - return flags; - } - - shflags = pg->shadow_flags & SHF_page_type_mask; - while ( shflags ) - { - bit = find_first_set_bit(shflags); - ASSERT(shflags & (1u << bit)); - shflags &= ~(1u << bit); - if ( !(pg->shadow_flags & (1u << bit)) ) - continue; - switch ( bit ) - { - case PGC_SH_type_to_index(PGC_SH_l1_shadow): - if (level != 1) - res |= sh_map_and_validate_gl1e(v, gmfn, ep, sizeof (*ep)); - break; - case PGC_SH_type_to_index(PGC_SH_l2_shadow): - if (level != 2) - res |= sh_map_and_validate_gl2e(v, gmfn, ep, sizeof (*ep)); - break; -#if GUEST_PAGING_LEVELS == 3 /* PAE only */ - case PGC_SH_type_to_index(PGC_SH_l2h_shadow): - if (level != 2) - res |= sh_map_and_validate_gl2he(v, gmfn, ep, sizeof (*ep)); - break; -#endif -#if GUEST_PAGING_LEVELS >= 3 /* PAE or 64... */ - case PGC_SH_type_to_index(PGC_SH_l3_shadow): - if (level != 3) - res |= sh_map_and_validate_gl3e(v, gmfn, ep, sizeof (*ep)); - break; -#if GUEST_PAGING_LEVELS >= 4 /* 64-bit only... */ - case PGC_SH_type_to_index(PGC_SH_l4_shadow): - if (level != 4) - res |= sh_map_and_validate_gl4e(v, gmfn, ep, sizeof (*ep)); - break; -#endif -#endif - default: - SHADOW_ERROR("mfn %"SH_PRI_mfn" is shadowed in multiple " - "modes: A&D bits may be out of sync (flags=%#x).\n", - mfn_x(gmfn), pg->shadow_flags); - /* XXX Shadows in other modes will not be updated, so will - * have their A and D bits out of sync. */ - } - } - + /* Propagate this change to any existing shadows */ + res = __shadow_validate_guest_entry(v, gmfn, ep, sizeof(*ep)); + /* We should never need to flush the TLB or recopy PAE entries */ - ASSERT( res == 0 || res == SHADOW_SET_CHANGED ); + ASSERT((res == 0) || (res == SHADOW_SET_CHANGED)); + return flags; } + +#if (CONFIG_PAGING_LEVELS == GUEST_PAGING_LEVELS) && (CONFIG_PAGING_LEVELS == SHADOW_PAGING_LEVELS) +void * +sh_guest_map_l1e(struct vcpu *v, unsigned long addr, + unsigned long *gl1mfn) +{ + void *pl1e = NULL; + walk_t gw; + + ASSERT(shadow_mode_translate(v->domain)); + + // XXX -- this is expensive, but it's easy to cobble together... + // FIXME! + + shadow_lock(v->domain); + guest_walk_tables(v, addr, &gw, 1); + + if ( gw.l2e && + (guest_l2e_get_flags(*gw.l2e) & _PAGE_PRESENT) && + !(guest_supports_superpages(v) && (guest_l2e_get_flags(*gw.l2e) & _PAGE_PSE)) ) + { + if ( gl1mfn ) + *gl1mfn = mfn_x(gw.l1mfn); + pl1e = map_domain_page(mfn_x(gw.l1mfn)) + + (guest_l1_table_offset(addr) * sizeof(guest_l1e_t)); + } + + unmap_walk(v, &gw); + shadow_unlock(v->domain); + + return pl1e; +} + +void +sh_guest_get_eff_l1e(struct vcpu *v, unsigned long addr, void *eff_l1e) +{ + walk_t gw; + + ASSERT(shadow_mode_translate(v->domain)); + + // XXX -- this is expensive, but it's easy to cobble together... + // FIXME! + + shadow_lock(v->domain); + guest_walk_tables(v, addr, &gw, 1); + *(guest_l1e_t *)eff_l1e = gw.eff_l1e; + unmap_walk(v, &gw); + shadow_unlock(v->domain); +} +#endif /* CONFIG==SHADOW==GUEST */ /**************************************************************************/ /* Functions to compute the correct index into a shadow page, given an @@ -709,17 +700,6 @@ shadow_l4_index(mfn_t *smfn, u32 guest_i * to the _PAGE_DIRTY bit handling), but for L[234], they are grouped together * into the respective demand_fault functions. */ - -#define CHECK(_cond) \ -do { \ - if (unlikely(!(_cond))) \ - { \ - printk("%s %s %d ASSERTION (%s) FAILED\n", \ - __func__, __FILE__, __LINE__, #_cond); \ - return -1; \ - } \ -} while (0); - // The function below tries to capture all of the flag manipulation for the // demand and propagate functions into one place. // @@ -728,6 +708,16 @@ sh_propagate_flags(struct vcpu *v, mfn_t u32 gflags, guest_l1e_t *guest_entry_ptr, mfn_t gmfn, int mmio, int level, fetch_type_t ft) { +#define CHECK(_cond) \ +do { \ + if (unlikely(!(_cond))) \ + { \ + printk("%s %s %d ASSERTION (%s) FAILED\n", \ + __func__, __FILE__, __LINE__, #_cond); \ + domain_crash(d); \ + } \ +} while (0); + struct domain *d = v->domain; u32 pass_thru_flags; u32 sflags; @@ -763,6 +753,10 @@ sh_propagate_flags(struct vcpu *v, mfn_t return 0; } + // Set the A and D bits in the guest entry, if we need to. + if ( guest_entry_ptr && (ft & FETCH_TYPE_DEMAND) ) + gflags = guest_set_ad_bits(v, gmfn, guest_entry_ptr, level, ft); + // PAE does not allow NX, RW, USER, ACCESSED, or DIRTY bits in its L3e's... // if ( (SHADOW_PAGING_LEVELS == 3) && (level == 3) ) @@ -797,17 +791,12 @@ sh_propagate_flags(struct vcpu *v, mfn_t // Higher level entries do not, strictly speaking, have dirty bits, but // since we use shadow linear tables, each of these entries may, at some // point in time, also serve as a shadow L1 entry. - // By setting both the A&D bits in each of these, we eliminate the burden + // By setting both the A&D bits in each of these, we eliminate the burden // on the hardware to update these bits on initial accesses. // if ( (level > 1) && !((SHADOW_PAGING_LEVELS == 3) && (level == 3)) ) sflags |= _PAGE_ACCESSED | _PAGE_DIRTY; - - // Set the A and D bits in the guest entry, if we need to. - if ( guest_entry_ptr && (ft & FETCH_TYPE_DEMAND) ) - gflags = guest_set_ad_bits(v, gmfn, guest_entry_ptr, level, ft); - // If the A or D bit has not yet been set in the guest, then we must // prevent the corresponding kind of access. // @@ -815,12 +804,12 @@ sh_propagate_flags(struct vcpu *v, mfn_t !(gflags & _PAGE_ACCESSED)) ) sflags &= ~_PAGE_PRESENT; - /* D bits exist in l1es, and 32bit/PAE PSE l2es, but not 64bit PSE l2es */ - if ( unlikely( ((level == 1) - || ((level == 2) && (GUEST_PAGING_LEVELS < 4) - && guest_supports_superpages(v) && - (gflags & _PAGE_PSE))) - && !(gflags & _PAGE_DIRTY)) ) + /* D bits exist in L1es and PSE L2es */ + if ( unlikely(((level == 1) || + ((level == 2) && + (gflags & _PAGE_PSE) && + guest_supports_superpages(v))) + && !(gflags & _PAGE_DIRTY)) ) sflags &= ~_PAGE_RW; // MMIO caching @@ -869,10 +858,17 @@ sh_propagate_flags(struct vcpu *v, mfn_t } } + // PV guests in 64-bit mode use two different page tables for user vs + // supervisor permissions, making the guest's _PAGE_USER bit irrelevant. + // It is always shadowed as present... + if ( (GUEST_PAGING_LEVELS == 4) && !hvm_guest(v) ) + { + sflags |= _PAGE_USER; + } + return sflags; -} - #undef CHECK +} #if GUEST_PAGING_LEVELS >= 4 static void @@ -1732,10 +1728,20 @@ void sh_install_xen_entries_in_l4(struct __PAGE_HYPERVISOR); /* Linear mapping */ - sl4e[shadow_l4_table_offset(LINEAR_PT_VIRT_START)] = - shadow_l4e_from_mfn(gl4mfn, __PAGE_HYPERVISOR); sl4e[shadow_l4_table_offset(SH_LINEAR_PT_VIRT_START)] = shadow_l4e_from_mfn(sl4mfn, __PAGE_HYPERVISOR); + + if ( shadow_mode_translate(v->domain) && !shadow_mode_external(v->domain) ) + { + // linear tables may not be used with translated PV guests + sl4e[shadow_l4_table_offset(LINEAR_PT_VIRT_START)] = + shadow_l4e_empty(); + } + else + { + sl4e[shadow_l4_table_offset(LINEAR_PT_VIRT_START)] = + shadow_l4e_from_mfn(gl4mfn, __PAGE_HYPERVISOR); + } if ( shadow_mode_translate(v->domain) ) { @@ -1779,7 +1785,15 @@ void sh_install_xen_entries_in_l2h(struc /* We don't set up a linear mapping here because we can't until this * l2h is installed in an l3e. sh_update_linear_entries() handles - * the linear mappings when the l3 is loaded. */ + * the linear mappings when the l3 is loaded. We zero them here, just as + * a safety measure. + */ + for ( i = 0; i < SHADOW_L3_PAGETABLE_ENTRIES; i++ ) + sl2e[shadow_l2_table_offset(LINEAR_PT_VIRT_START) + i] = + shadow_l2e_empty(); + for ( i = 0; i < SHADOW_L3_PAGETABLE_ENTRIES; i++ ) + sl2e[shadow_l2_table_offset(SH_LINEAR_PT_VIRT_START) + i] = + shadow_l2e_empty(); if ( shadow_mode_translate(d) ) { @@ -1817,6 +1831,12 @@ void sh_install_xen_entries_in_l3(struct l2smfn = get_shadow_status(v, l2gmfn, PGC_SH_l2h_shadow); if ( !valid_mfn(l2smfn) ) { + /* must remove write access to this page before shadowing it */ + // XXX -- should check to see whether this is better with level==0 or + // level==2... + if ( shadow_remove_write_access(v, l2gmfn, 2, 0xc0000000ul) != 0 ) + flush_tlb_mask(v->domain->domain_dirty_cpumask); + l2smfn = sh_make_shadow(v, l2gmfn, PGC_SH_l2h_shadow); } l3e_propagate_from_guest(v, &gl3e[3], gl3mfn, l2smfn, &new_sl3e, @@ -1852,10 +1872,20 @@ void sh_install_xen_entries_in_l2(struct __PAGE_HYPERVISOR); /* Linear mapping */ - sl2e[shadow_l2_table_offset(LINEAR_PT_VIRT_START)] = - shadow_l2e_from_mfn(gl2mfn, __PAGE_HYPERVISOR); sl2e[shadow_l2_table_offset(SH_LINEAR_PT_VIRT_START)] = shadow_l2e_from_mfn(sl2mfn, __PAGE_HYPERVISOR); + + if ( shadow_mode_translate(v->domain) && !shadow_mode_external(v->domain) ) + { + // linear tables may not be used with translated PV guests + sl2e[shadow_l2_table_offset(LINEAR_PT_VIRT_START)] = + shadow_l2e_empty(); + } + else + { + sl2e[shadow_l2_table_offset(LINEAR_PT_VIRT_START)] = + shadow_l2e_from_mfn(gl2mfn, __PAGE_HYPERVISOR); + } if ( shadow_mode_translate(d) ) { @@ -2150,7 +2180,12 @@ static shadow_l1e_t * shadow_get_and_cre /* Get the l2e */ sl2e = shadow_get_and_create_l2e(v, gw, &sl2mfn, ft); if ( sl2e == NULL ) return NULL; - if ( shadow_l2e_get_flags(*sl2e) & _PAGE_PRESENT ) + /* Install the sl1 in the l2e if it wasn't there or if we need to + * re-do it to fix a PSE dirty bit. */ + if ( shadow_l2e_get_flags(*sl2e) & _PAGE_PRESENT + && likely(ft != ft_demand_write + || (guest_l2e_get_flags(*gw->l2e) & _PAGE_DIRTY) + || !(guest_l2e_get_flags(*gw->l2e) & _PAGE_PSE)) ) { *sl1mfn = shadow_l2e_get_mfn(*sl2e); ASSERT(valid_mfn(*sl1mfn)); @@ -2527,6 +2562,32 @@ static int validate_gl4e(struct vcpu *v, } l4e_propagate_from_guest(v, new_gl4e, _mfn(INVALID_MFN), sl3mfn, &new_sl4e, ft_prefetch); + + // check for updates to xen reserved slots + if ( !shadow_mode_external(v->domain) ) + { + int shadow_index = (((unsigned long)sl4p & ~PAGE_MASK) / + sizeof(shadow_l4e_t)); + int reserved_xen_slot = !is_guest_l4_slot(shadow_index); + + if ( unlikely(reserved_xen_slot) ) + { + // attempt by the guest to write to a xen reserved slot + // + SHADOW_PRINTK("%s out-of-range update " + "sl4mfn=%05lx index=0x%x val=%" SH_PRI_pte "\n", + __func__, mfn_x(sl4mfn), shadow_index, new_sl4e.l4); + if ( shadow_l4e_get_flags(new_sl4e) & _PAGE_PRESENT ) + { + SHADOW_ERROR("out-of-range l4e update\n"); + result |= SHADOW_SET_ERROR; + } + + // do not call shadow_set_l4e... + return result; + } + } + result |= shadow_set_l4e(v, sl4p, new_sl4e, sl4mfn); return result; } @@ -2616,6 +2677,48 @@ static int validate_gl2e(struct vcpu *v, } l2e_propagate_from_guest(v, new_gl2e, _mfn(INVALID_MFN), sl1mfn, &new_sl2e, ft_prefetch); + + // check for updates to xen reserved slots in PV guests... + // XXX -- need to revisit this for PV 3-on-4 guests. + // +#if SHADOW_PAGING_LEVELS < 4 +#if CONFIG_PAGING_LEVELS == SHADOW_PAGING_LEVELS + if ( !shadow_mode_external(v->domain) ) + { + int shadow_index = (((unsigned long)sl2p & ~PAGE_MASK) / + sizeof(shadow_l2e_t)); + int reserved_xen_slot; + +#if SHADOW_PAGING_LEVELS == 3 + reserved_xen_slot = + (((mfn_to_page(sl2mfn)->count_info & PGC_SH_type_mask) + == PGC_SH_l2h_pae_shadow) && + (shadow_index + >= (L2_PAGETABLE_FIRST_XEN_SLOT & (L2_PAGETABLE_ENTRIES-1)))); +#else /* SHADOW_PAGING_LEVELS == 2 */ + reserved_xen_slot = (shadow_index >= L2_PAGETABLE_FIRST_XEN_SLOT); +#endif + + if ( unlikely(reserved_xen_slot) ) + { + // attempt by the guest to write to a xen reserved slot + // + SHADOW_PRINTK("%s out-of-range update " + "sl2mfn=%05lx index=0x%x val=%" SH_PRI_pte "\n", + __func__, mfn_x(sl2mfn), shadow_index, new_sl2e.l2); + if ( shadow_l2e_get_flags(new_sl2e) & _PAGE_PRESENT ) + { + SHADOW_ERROR("out-of-range l2e update\n"); + result |= SHADOW_SET_ERROR; + } + + // do not call shadow_set_l2e... + return result; + } + } +#endif /* CONFIG_PAGING_LEVELS == SHADOW_PAGING_LEVELS */ +#endif /* SHADOW_PAGING_LEVELS < 4 */ + result |= shadow_set_l2e(v, sl2p, new_sl2e, sl2mfn); return result; @@ -2897,7 +3000,7 @@ static int sh_page_fault(struct vcpu *v, } // All levels of the guest page table are now known to be present. - accumulated_gflags = accumulate_guest_flags(&gw); + accumulated_gflags = accumulate_guest_flags(v, &gw); // Check for attempts to access supervisor-only pages from user mode, // i.e. ring 3. Such errors are not caused or dealt with by the shadow @@ -3348,6 +3451,7 @@ sh_update_linear_entries(struct vcpu *v) l2_pgentry_t *l2e, new_l2e; shadow_l3e_t *guest_l3e = NULL, *shadow_l3e; int i; + int unmap_l2e = 0; #if GUEST_PAGING_LEVELS == 2 /* Shadow l3 tables were built by update_cr3 */ @@ -3365,39 +3469,45 @@ sh_update_linear_entries(struct vcpu *v) #endif /* GUEST_PAGING_LEVELS */ /* Choose where to write the entries, using linear maps if possible */ - if ( v == current && shadow_mode_external(d) ) - { - /* From the monitor tables, it's safe to use linear maps to update - * monitor l2s */ - l2e = __linear_l2_table + (3 * L2_PAGETABLE_ENTRIES); - } - else if ( shadow_mode_external(d) ) - { - /* Map the monitor table's high l2 */ - l3_pgentry_t *l3e; - l3e = sh_map_domain_page( - pagetable_get_mfn(v->arch.monitor_table)); - ASSERT(l3e_get_flags(l3e[3]) & _PAGE_PRESENT); - l2e = sh_map_domain_page(_mfn(l3e_get_pfn(l3e[3]))); - sh_unmap_domain_page(l3e); - } + if ( shadow_mode_external(d) ) + { + if ( v == current ) + { + /* From the monitor tables, it's safe to use linear maps + * to update monitor l2s */ + l2e = __linear_l2_table + (3 * L2_PAGETABLE_ENTRIES); + } + else + { + /* Map the monitor table's high l2 */ + l3_pgentry_t *l3e; + l3e = sh_map_domain_page( + pagetable_get_mfn(v->arch.monitor_table)); + ASSERT(l3e_get_flags(l3e[3]) & _PAGE_PRESENT); + l2e = sh_map_domain_page(_mfn(l3e_get_pfn(l3e[3]))); + unmap_l2e = 1; + sh_unmap_domain_page(l3e); + } + } else { /* Map the shadow table's high l2 */ ASSERT(shadow_l3e_get_flags(shadow_l3e[3]) & _PAGE_PRESENT); l2e = sh_map_domain_page(shadow_l3e_get_mfn(shadow_l3e[3])); + unmap_l2e = 1; } - - if ( !shadow_mode_external(d) ) - { - /* Write linear mapping of guest. */ + /* Write linear mapping of guest (only in PV, and only when + * not translated). */ + if ( !shadow_mode_translate(d) ) + { for ( i = 0; i < SHADOW_L3_PAGETABLE_ENTRIES; i++ ) - { - new_l2e = (shadow_l3e_get_flags(guest_l3e[i]) & _PAGE_PRESENT) - ? l2e_from_pfn(mfn_x(shadow_l3e_get_mfn(guest_l3e[i])), - __PAGE_HYPERVISOR) - : l2e_empty(); + { + new_l2e = + ((shadow_l3e_get_flags(guest_l3e[i]) & _PAGE_PRESENT) + ? l2e_from_pfn(mfn_x(shadow_l3e_get_mfn(guest_l3e[i])), + __PAGE_HYPERVISOR) + : l2e_empty()); safe_write_entry( &l2e[l2_table_offset(LINEAR_PT_VIRT_START) + i], &new_l2e); @@ -3416,9 +3526,8 @@ sh_update_linear_entries(struct vcpu *v) &new_l2e); } - if ( v != current || !shadow_mode_external(d) ) + if ( unmap_l2e ) sh_unmap_domain_page(l2e); - } #elif CONFIG_PAGING_LEVELS == 2 @@ -3521,16 +3630,24 @@ static void static void sh_detach_old_tables(struct vcpu *v) { + struct domain *d = v->domain; mfn_t smfn; //// //// vcpu->arch.guest_vtable //// - if ( (shadow_mode_external(v->domain) || (GUEST_PAGING_LEVELS == 3)) && - v->arch.guest_vtable ) - { - // Q: why does this need to use (un)map_domain_page_*global* ? - sh_unmap_domain_page_global(v->arch.guest_vtable); + if ( v->arch.guest_vtable ) + { +#if GUEST_PAGING_LEVELS == 4 + if ( shadow_mode_external(d) || shadow_mode_translate(d) ) + sh_unmap_domain_page_global(v->arch.guest_vtable); +#elif GUEST_PAGING_LEVELS == 3 + if ( 1 || shadow_mode_external(d) || shadow_mode_translate(d) ) + sh_unmap_domain_page_global(v->arch.guest_vtable); +#elif GUEST_PAGING_LEVELS == 2 + if ( shadow_mode_external(d) || shadow_mode_translate(d) ) + sh_unmap_domain_page_global(v->arch.guest_vtable); +#endif v->arch.guest_vtable = NULL; } @@ -3645,9 +3762,14 @@ sh_update_cr3(struct vcpu *v) //// //// vcpu->arch.guest_vtable //// +#if GUEST_PAGING_LEVELS == 4 + if ( shadow_mode_external(d) || shadow_mode_translate(d) ) + v->arch.guest_vtable = sh_map_domain_page_global(gmfn); + else + v->arch.guest_vtable = __linear_l4_table; +#elif GUEST_PAGING_LEVELS == 3 if ( shadow_mode_external(d) ) { -#if GUEST_PAGING_LEVELS == 3 if ( shadow_vcpu_mode_translate(v) ) /* Paging enabled: find where in the page the l3 table is */ guest_idx = guest_index((void *)hvm_get_guest_ctrl_reg(v, 3)); @@ -3658,25 +3780,21 @@ sh_update_cr3(struct vcpu *v) // Ignore the low 2 bits of guest_idx -- they are really just // cache control. guest_idx &= ~3; + // XXX - why does this need a global map? v->arch.guest_vtable = (guest_l3e_t *)sh_map_domain_page_global(gmfn) + guest_idx; + } + else + v->arch.guest_vtable = sh_map_domain_page_global(gmfn); +#elif GUEST_PAGING_LEVELS == 2 + if ( shadow_mode_external(d) || shadow_mode_translate(d) ) + v->arch.guest_vtable = sh_map_domain_page_global(gmfn); + else + v->arch.guest_vtable = __linear_l2_table; #else - // XXX - why does this need a global map? - v->arch.guest_vtable = sh_map_domain_page_global(gmfn); -#endif - } - else - { -#ifdef __x86_64__ - v->arch.guest_vtable = __linear_l4_table; -#elif GUEST_PAGING_LEVELS == 3 - // XXX - why does this need a global map? - v->arch.guest_vtable = sh_map_domain_page_global(gmfn); -#else - v->arch.guest_vtable = __linear_l2_table; -#endif - } +#error this should never happen +#endif #if 0 printk("%s %s %d gmfn=%05lx guest_vtable=%p\n", @@ -3743,6 +3861,17 @@ sh_update_cr3(struct vcpu *v) v->arch.shadow_vtable = __sh_linear_l2_table; #endif } + +#if (CONFIG_PAGING_LEVELS == 3) && (GUEST_PAGING_LEVELS == 3) + // Now that shadow_vtable is in place, check that the sl3e[3] is properly + // shadowed and installed in PAE PV guests... + if ( !shadow_mode_external(d) && + !(shadow_l3e_get_flags(((shadow_l3e_t *)v->arch.shadow_vtable)[3]) & + _PAGE_PRESENT) ) + { + sh_install_xen_entries_in_l3(v, gmfn, smfn); + } +#endif //// //// Take a ref to the new shadow table, and pin it. @@ -4049,7 +4178,7 @@ static inline void * emulate_map_dest(st mfn_t mfn; guest_walk_tables(v, vaddr, &gw, 1); - flags = accumulate_guest_flags(&gw); + flags = accumulate_guest_flags(v, &gw); gfn = guest_l1e_get_gfn(gw.eff_l1e); mfn = vcpu_gfn_to_mfn(v, gfn); sh_audit_gw(v, &gw); @@ -4453,6 +4582,8 @@ struct shadow_paging_mode sh_paging_mode .x86_emulate_cmpxchg8b = sh_x86_emulate_cmpxchg8b, .make_monitor_table = sh_make_monitor_table, .destroy_monitor_table = sh_destroy_monitor_table, + .guest_map_l1e = sh_guest_map_l1e, + .guest_get_eff_l1e = sh_guest_get_eff_l1e, #if SHADOW_OPTIMIZATIONS & SHOPT_WRITABLE_HEURISTIC .guess_wrmap = sh_guess_wrmap, #endif diff -r 914c44d10c8d -r 2bfd19fc1b79 xen/arch/x86/mm/shadow/multi.h --- a/xen/arch/x86/mm/shadow/multi.h Sun Oct 01 11:39:41 2006 -0600 +++ b/xen/arch/x86/mm/shadow/multi.h Sun Oct 01 19:10:18 2006 -0600 @@ -103,6 +103,13 @@ SHADOW_INTERNAL_NAME(sh_audit_l4_table, (struct vcpu *v, mfn_t sl4mfn, mfn_t x); #endif +extern void * +SHADOW_INTERNAL_NAME(sh_guest_map_l1e, CONFIG_PAGING_LEVELS, CONFIG_PAGING_LEVELS) + (struct vcpu *v, unsigned long va, unsigned long *gl1mfn); +extern void +SHADOW_INTERNAL_NAME(sh_guest_get_eff_l1e, CONFIG_PAGING_LEVELS, CONFIG_PAGING_LEVELS) + (struct vcpu *v, unsigned long va, void *eff_l1e); + #if SHADOW_LEVELS == GUEST_LEVELS extern mfn_t SHADOW_INTERNAL_NAME(sh_make_monitor_table, SHADOW_LEVELS, GUEST_LEVELS) diff -r 914c44d10c8d -r 2bfd19fc1b79 xen/arch/x86/mm/shadow/private.h --- a/xen/arch/x86/mm/shadow/private.h Sun Oct 01 11:39:41 2006 -0600 +++ b/xen/arch/x86/mm/shadow/private.h Sun Oct 01 19:10:18 2006 -0600 @@ -532,55 +532,6 @@ static inline void sh_unpin(struct vcpu } } -/**************************************************************************/ -/* Guest physmap (p2m) support */ - -/* Read our own P2M table, checking in the linear pagetables first to be - * sure that we will succeed. Call this function if you expect it to - * fail often, as it avoids page faults. If you expect to succeed, use - * vcpu_gfn_to_mfn, which copy_from_user()s the entry */ -static inline mfn_t -vcpu_gfn_to_mfn_nofault(struct vcpu *v, unsigned long gfn) -{ - unsigned long entry_addr = (unsigned long) &phys_to_machine_mapping[gfn]; -#if CONFIG_PAGING_LEVELS >= 4 - l4_pgentry_t *l4e; - l3_pgentry_t *l3e; -#endif - l2_pgentry_t *l2e; - l1_pgentry_t *l1e; - - ASSERT(current == v); - if ( !shadow_vcpu_mode_translate(v) ) - return _mfn(gfn); - -#if CONFIG_PAGING_LEVELS > 2 - if ( gfn >= (RO_MPT_VIRT_END - RO_MPT_VIRT_START) / sizeof(l1_pgentry_t) ) - /* This pfn is higher than the p2m map can hold */ - return _mfn(INVALID_MFN); -#endif - - /* Walk the linear pagetables. Note that this is *not* the same as - * the walk in sh_gfn_to_mfn_foreign, which is walking the p2m map */ -#if CONFIG_PAGING_LEVELS >= 4 - l4e = __linear_l4_table + l4_linear_offset(entry_addr); - if ( !(l4e_get_flags(*l4e) & _PAGE_PRESENT) ) return _mfn(INVALID_MFN); - l3e = __linear_l3_table + l3_linear_offset(entry_addr); - if ( !(l3e_get_flags(*l3e) & _PAGE_PRESENT) ) return _mfn(INVALID_MFN); -#endif - l2e = __linear_l2_table + l2_linear_offset(entry_addr); - if ( !(l2e_get_flags(*l2e) & _PAGE_PRESENT) ) return _mfn(INVALID_MFN); - l1e = __linear_l1_table + l1_linear_offset(entry_addr); - if ( !(l1e_get_flags(*l1e) & _PAGE_PRESENT) ) return _mfn(INVALID_MFN); - - /* Safe to look at this part of the table */ - if ( l1e_get_flags(phys_to_machine_mapping[gfn]) & _PAGE_PRESENT ) - return _mfn(l1e_get_pfn(phys_to_machine_mapping[gfn])); - - return _mfn(INVALID_MFN); -} - - #endif /* _XEN_SHADOW_PRIVATE_H */ /* diff -r 914c44d10c8d -r 2bfd19fc1b79 xen/arch/x86/mm/shadow/types.h --- a/xen/arch/x86/mm/shadow/types.h Sun Oct 01 11:39:41 2006 -0600 +++ b/xen/arch/x86/mm/shadow/types.h Sun Oct 01 19:10:18 2006 -0600 @@ -205,6 +205,9 @@ static inline shadow_l4e_t shadow_l4e_fr __sh_linear_l1_table; \ }) +// XXX -- these should not be conditional on hvm_guest(v), but rather on +// shadow_mode_external(d)... +// #define sh_linear_l2_table(v) ({ \ ASSERT(current == (v)); \ ((shadow_l2e_t *) \ @@ -507,10 +510,22 @@ struct shadow_walk_t #define sh_guess_wrmap INTERNAL_NAME(sh_guess_wrmap) #define sh_clear_shadow_entry INTERNAL_NAME(sh_clear_shadow_entry) +/* The sh_guest_(map|get)_* functions only depends on the number of config + * levels + */ +#define sh_guest_map_l1e \ + SHADOW_INTERNAL_NAME(sh_guest_map_l1e, \ + CONFIG_PAGING_LEVELS, \ + CONFIG_PAGING_LEVELS) +#define sh_guest_get_eff_l1e \ + SHADOW_INTERNAL_NAME(sh_guest_get_eff_l1e, \ + CONFIG_PAGING_LEVELS, \ + CONFIG_PAGING_LEVELS) + /* sh_make_monitor_table only depends on the number of shadow levels */ -#define sh_make_monitor_table \ - SHADOW_INTERNAL_NAME(sh_make_monitor_table, \ - SHADOW_PAGING_LEVELS, \ +#define sh_make_monitor_table \ + SHADOW_INTERNAL_NAME(sh_make_monitor_table, \ + SHADOW_PAGING_LEVELS, \ SHADOW_PAGING_LEVELS) #define sh_destroy_monitor_table \ SHADOW_INTERNAL_NAME(sh_destroy_monitor_table, \ @@ -652,7 +667,7 @@ static inline void sh_unpin_l3_subshadow #endif /* GUEST_PAGING_LEVELS >= 3 */ static inline u32 -accumulate_guest_flags(walk_t *gw) +accumulate_guest_flags(struct vcpu *v, walk_t *gw) { u32 accumulated_flags; @@ -674,8 +689,14 @@ accumulate_guest_flags(walk_t *gw) accumulated_flags &= guest_l4e_get_flags(*gw->l4e) ^ _PAGE_NX_BIT; #endif - // Finally, revert the NX bit back to its original polarity + // Revert the NX bit back to its original polarity accumulated_flags ^= _PAGE_NX_BIT; + + // In 64-bit PV guests, the _PAGE_USER bit is implied in all guest + // entries (since even the guest kernel runs in ring 3). + // + if ( (GUEST_PAGING_LEVELS == 4) && !hvm_guest(v) ) + accumulated_flags |= _PAGE_USER; return accumulated_flags; } diff -r 914c44d10c8d -r 2bfd19fc1b79 xen/arch/x86/smp.c --- a/xen/arch/x86/smp.c Sun Oct 01 11:39:41 2006 -0600 +++ b/xen/arch/x86/smp.c Sun Oct 01 19:10:18 2006 -0600 @@ -21,6 +21,7 @@ #include <asm/smpboot.h> #include <asm/hardirq.h> #include <asm/ipi.h> +#include <asm/hvm/hvm.h> #include <mach_apic.h> /* @@ -306,6 +307,7 @@ static void stop_this_cpu (void *dummy) local_irq_disable(); disable_local_APIC(); + hvm_disable(); for ( ; ; ) __asm__ __volatile__ ( "hlt" ); diff -r 914c44d10c8d -r 2bfd19fc1b79 xen/arch/x86/traps.c --- a/xen/arch/x86/traps.c Sun Oct 01 11:39:41 2006 -0600 +++ b/xen/arch/x86/traps.c Sun Oct 01 19:10:18 2006 -0600 @@ -886,7 +886,7 @@ static int fixup_page_fault(unsigned lon /* Do not check if access-protection fault since the page may legitimately be not present in shadow page tables */ ((regs->error_code & PFEC_write_access) == PFEC_write_access) && - ptwr_do_page_fault(d, addr, regs) ) + ptwr_do_page_fault(v, addr, regs) ) return EXCRET_fault_fixed; if ( shadow_mode_enabled(d) ) diff -r 914c44d10c8d -r 2bfd19fc1b79 xen/arch/x86/x86_32/entry.S --- a/xen/arch/x86/x86_32/entry.S Sun Oct 01 11:39:41 2006 -0600 +++ b/xen/arch/x86/x86_32/entry.S Sun Oct 01 19:10:18 2006 -0600 @@ -175,7 +175,7 @@ ENTRY(hypercall) jae bad_hypercall PERFC_INCR(PERFC_hypercalls, %eax) #ifndef NDEBUG - /* Deliberately corrupt parameter regs not used by this hypercall. */ + /* Create shadow parameters and corrupt those not used by this call. */ pushl %eax pushl UREGS_eip+4(%esp) pushl 28(%esp) # EBP @@ -192,11 +192,23 @@ ENTRY(hypercall) movl $0xDEADBEEF,%eax rep stosl movl %esi,%eax +#else + /* + * We need shadow parameters even on non-debug builds. We depend on the + * original versions not being clobbered (needed to create a hypercall + * continuation). But that isn't guaranteed by the function-call ABI. + */ + pushl 20(%esp) # EBP + pushl 20(%esp) # EDI + pushl 20(%esp) # ESI + pushl 20(%esp) # EDX + pushl 20(%esp) # ECX + pushl 20(%esp) # EBX #endif call *hypercall_table(,%eax,4) + addl $24,%esp # Discard the shadow parameters #ifndef NDEBUG - /* Deliberately corrupt parameter regs used by this hypercall. */ - addl $24,%esp # Shadow parameters + /* Deliberately corrupt real parameter regs used by this hypercall. */ popl %ecx # Shadow EIP cmpl %ecx,UREGS_eip+4(%esp) popl %ecx # Shadow hypercall index diff -r 914c44d10c8d -r 2bfd19fc1b79 xen/arch/x86/x86_emulate.c --- a/xen/arch/x86/x86_emulate.c Sun Oct 01 11:39:41 2006 -0600 +++ b/xen/arch/x86/x86_emulate.c Sun Oct 01 19:10:18 2006 -0600 @@ -368,12 +368,13 @@ do{ __asm__ __volatile__ ( #endif /* __i386__ */ /* Fetch next part of the instruction being emulated. */ -#define insn_fetch(_type, _size, _eip) \ -({ unsigned long _x; \ - rc = ops->read_std((unsigned long)(_eip), &_x, (_size), ctxt); \ +#define insn_fetch(_type, _size) \ +({ unsigned long _x, _ptr = _regs.eip; \ + if ( mode == X86EMUL_MODE_REAL ) _ptr += _regs.cs << 4; \ + rc = ops->read_std(_ptr, &_x, (_size), ctxt); \ if ( rc != 0 ) \ goto done; \ - (_eip) += (_size); \ + _regs.eip += (_size); \ (_type)_x; \ }) @@ -478,7 +479,7 @@ x86_emulate_memop( /* Legacy prefixes. */ for ( i = 0; i < 8; i++ ) { - switch ( b = insn_fetch(uint8_t, 1, _regs.eip) ) + switch ( b = insn_fetch(uint8_t, 1) ) { case 0x66: /* operand-size override */ op_bytes ^= 6; /* switch between 2/4 bytes */ @@ -529,7 +530,7 @@ x86_emulate_memop( op_bytes = 8; /* REX.W */ modrm_reg = (b & 4) << 1; /* REX.R */ /* REX.B and REX.X do not need to be decoded. */ - b = insn_fetch(uint8_t, 1, _regs.eip); + b = insn_fetch(uint8_t, 1); } /* Opcode byte(s). */ @@ -540,7 +541,7 @@ x86_emulate_memop( if ( b == 0x0f ) { twobyte = 1; - b = insn_fetch(uint8_t, 1, _regs.eip); + b = insn_fetch(uint8_t, 1); d = twobyte_table[b]; } @@ -552,7 +553,7 @@ x86_emulate_memop( /* ModRM and SIB bytes. */ if ( d & ModRM ) { - modrm = insn_fetch(uint8_t, 1, _regs.eip); + modrm = insn_fetch(uint8_t, 1); modrm_mod |= (modrm & 0xc0) >> 6; modrm_reg |= (modrm & 0x38) >> 3; modrm_rm |= (modrm & 0x07); @@ -587,19 +588,19 @@ x86_emulate_memop( { case 0: if ( (modrm_rm == 4) && - (((sib = insn_fetch(uint8_t, 1, _regs.eip)) & 7) == 5) ) + (((sib = insn_fetch(uint8_t, 1)) & 7) == 5) ) _regs.eip += 4; /* skip disp32 specified by SIB.base */ else if ( modrm_rm == 5 ) _regs.eip += 4; /* skip disp32 */ break; case 1: if ( modrm_rm == 4 ) - sib = insn_fetch(uint8_t, 1, _regs.eip); + sib = insn_fetch(uint8_t, 1); _regs.eip += 1; /* skip disp8 */ break; case 2: if ( modrm_rm == 4 ) - sib = insn_fetch(uint8_t, 1, _regs.eip); + sib = insn_fetch(uint8_t, 1); _regs.eip += 4; /* skip disp32 */ break; } @@ -691,16 +692,16 @@ x86_emulate_memop( /* NB. Immediates are sign-extended as necessary. */ switch ( src.bytes ) { - case 1: src.val = insn_fetch(int8_t, 1, _regs.eip); break; - case 2: src.val = insn_fetch(int16_t, 2, _regs.eip); break; - case 4: src.val = insn_fetch(int32_t, 4, _regs.eip); break; + case 1: src.val = insn_fetch(int8_t, 1); break; + case 2: src.val = insn_fetch(int16_t, 2); break; + case 4: src.val = insn_fetch(int32_t, 4); break; } break; case SrcImmByte: src.type = OP_IMM; src.ptr = (unsigned long *)_regs.eip; src.bytes = 1; - src.val = insn_fetch(int8_t, 1, _regs.eip); + src.val = insn_fetch(int8_t, 1); break; } @@ -840,9 +841,9 @@ x86_emulate_memop( if ( src.bytes == 8 ) src.bytes = 4; switch ( src.bytes ) { - case 1: src.val = insn_fetch(int8_t, 1, _regs.eip); break; - case 2: src.val = insn_fetch(int16_t, 2, _regs.eip); break; - case 4: src.val = insn_fetch(int32_t, 4, _regs.eip); break; + case 1: src.val = insn_fetch(int8_t, 1); break; + case 2: src.val = insn_fetch(int16_t, 2); break; + case 4: src.val = insn_fetch(int32_t, 4); break; } goto test; case 2: /* not */ diff -r 914c44d10c8d -r 2bfd19fc1b79 xen/common/gdbstub.c --- a/xen/common/gdbstub.c Sun Oct 01 11:39:41 2006 -0600 +++ b/xen/common/gdbstub.c Sun Oct 01 19:10:18 2006 -0600 @@ -506,14 +506,13 @@ int int __trap_to_gdb(struct cpu_user_regs *regs, unsigned long cookie) { - int resume = 0; - int r; + int rc = 0; unsigned long flags; if ( gdb_ctx->serhnd < 0 ) { dbg_printk("Debugger not ready yet.\n"); - return 0; + return -EBUSY; } /* We rely on our caller to ensure we're only on one processor @@ -532,7 +531,7 @@ __trap_to_gdb(struct cpu_user_regs *regs { printk("WARNING WARNING WARNING: Avoiding recursive gdb.\n"); atomic_inc(&gdb_ctx->running); - return 0; + return -EBUSY; } if ( !gdb_ctx->connected ) @@ -565,19 +564,14 @@ __trap_to_gdb(struct cpu_user_regs *regs gdb_cmd_signum(gdb_ctx); } - while ( resume == 0 ) - { - r = receive_command(gdb_ctx); - if ( r < 0 ) - { - dbg_printk("GDB disappeared, trying to resume Xen...\n"); - resume = 1; - } - else - { - resume = process_command(regs, gdb_ctx); - } - } + do { + if ( receive_command(gdb_ctx) < 0 ) + { + dbg_printk("Error in GDB session...\n"); + rc = -EIO; + break; + } + } while ( process_command(regs, gdb_ctx) == 0 ); gdb_arch_exit(regs); console_end_sync(); @@ -586,7 +580,7 @@ __trap_to_gdb(struct cpu_user_regs *regs local_irq_restore(flags); - return 0; + return rc; } void diff -r 914c44d10c8d -r 2bfd19fc1b79 xen/common/symbols.c --- a/xen/common/symbols.c Sun Oct 01 11:39:41 2006 -0600 +++ b/xen/common/symbols.c Sun Oct 01 19:10:18 2006 -0600 @@ -16,15 +16,14 @@ #include <xen/lib.h> #include <xen/string.h> -/* These will be re-linked against their real values during the second link stage */ -extern unsigned long symbols_addresses[] __attribute__((weak)); -extern unsigned long symbols_num_syms __attribute__((weak,section("data"))); -extern u8 symbols_names[] __attribute__((weak)); +extern unsigned long symbols_addresses[]; +extern unsigned long symbols_num_syms; +extern u8 symbols_names[]; -extern u8 symbols_token_table[] __attribute__((weak)); -extern u16 symbols_token_index[] __attribute__((weak)); +extern u8 symbols_token_table[]; +extern u16 symbols_token_index[]; -extern unsigned long symbols_markers[] __attribute__((weak)); +extern unsigned long symbols_markers[]; /* expand a compressed symbol data into the resulting uncompressed string, given the offset to where the symbol is in the compressed stream */ diff -r 914c44d10c8d -r 2bfd19fc1b79 xen/include/asm-x86/debugger.h --- a/xen/include/asm-x86/debugger.h Sun Oct 01 11:39:41 2006 -0600 +++ b/xen/include/asm-x86/debugger.h Sun Oct 01 19:10:18 2006 -0600 @@ -15,14 +15,13 @@ * 2. debugger_trap_fatal(): * Called when Xen is about to give up and crash. Typically you will use this * hook to drop into a debug session. It can also be used to hook off - * deliberately caused traps (which you then handle and return non-zero) - * but really these should be hooked off 'debugger_trap_entry'. + * deliberately caused traps (which you then handle and return non-zero). * * 3. debugger_trap_immediate(): * Called if we want to drop into a debugger now. This is essentially the * same as debugger_trap_fatal, except that we use the current register state * rather than the state which was in effect when we took the trap. - * Essentially, if we're dying because of an unhandled exception, we call + * For example: if we're dying because of an unhandled exception, we call * debugger_trap_fatal; if we're dying because of a panic() we call * debugger_trap_immediate(). */ @@ -44,42 +43,19 @@ #include <xen/gdbstub.h> -#define __debugger_trap_entry(_v, _r) (0) - -static inline int __debugger_trap_fatal( +static inline int debugger_trap_fatal( unsigned int vector, struct cpu_user_regs *regs) { - (void)__trap_to_gdb(regs, vector); - return (vector == TRAP_int3); /* int3 is harmless */ + return (__trap_to_gdb(regs, vector) == 0); } /* Int3 is a trivial way to gather cpu_user_regs context. */ #define debugger_trap_immediate() __asm__ __volatile__ ( "int3" ); -#elif 0 - -extern int kdb_trap(int, int, struct cpu_user_regs *); - -static inline int __debugger_trap_entry( - unsigned int vector, struct cpu_user_regs *regs) -{ - return 0; -} - -static inline int __debugger_trap_fatal( - unsigned int vector, struct cpu_user_regs *regs) -{ - return kdb_trap(vector, 0, regs); -} - -/* Int3 is a trivial way to gather cpu_user_regs context. */ -#define debugger_trap_immediate() __asm__ __volatile__ ( "int3" ) - #else -#define __debugger_trap_entry(_v, _r) (0) -#define __debugger_trap_fatal(_v, _r) (0) -#define __debugger_trap_immediate() ((void)0) +#define debugger_trap_fatal(v, r) (0) +#define debugger_trap_immediate() ((void)0) #endif @@ -96,12 +72,7 @@ static inline int debugger_trap_entry( return 1; } - return __debugger_trap_entry(vector, regs); + return 0; } -#define debugger_trap_fatal(v, r) (__debugger_trap_fatal(v, r)) -#ifndef debugger_trap_immediate -#define debugger_trap_immediate() (__debugger_trap_immediate()) -#endif - #endif /* __X86_DEBUGGER_H__ */ diff -r 914c44d10c8d -r 2bfd19fc1b79 xen/include/asm-x86/domain.h --- a/xen/include/asm-x86/domain.h Sun Oct 01 11:39:41 2006 -0600 +++ b/xen/include/asm-x86/domain.h Sun Oct 01 19:10:18 2006 -0600 @@ -139,7 +139,7 @@ struct shadow_vcpu { /* Last MFN that we emulated a write to. */ unsigned long last_emulated_mfn; /* HVM guest: paging enabled (CR0.PG)? */ - unsigned int hvm_paging_enabled:1; + unsigned int translate_enabled:1; /* Emulated fault needs to be propagated to guest? */ unsigned int propagate_fault:1; #if CONFIG_PAGING_LEVELS >= 3 diff -r 914c44d10c8d -r 2bfd19fc1b79 xen/include/asm-x86/guest_access.h --- a/xen/include/asm-x86/guest_access.h Sun Oct 01 11:39:41 2006 -0600 +++ b/xen/include/asm-x86/guest_access.h Sun Oct 01 19:10:18 2006 -0600 @@ -8,6 +8,7 @@ #define __ASM_X86_GUEST_ACCESS_H__ #include <asm/uaccess.h> +#include <asm/shadow.h> #include <asm/hvm/support.h> #include <asm/hvm/guest_access.h> @@ -33,7 +34,7 @@ #define copy_to_guest_offset(hnd, off, ptr, nr) ({ \ const typeof(ptr) _x = (hnd).p; \ const typeof(ptr) _y = (ptr); \ - hvm_guest(current) ? \ + shadow_mode_translate(current->domain) ? \ copy_to_user_hvm(_x+(off), _y, sizeof(*_x)*(nr)) : \ copy_to_user(_x+(off), _y, sizeof(*_x)*(nr)); \ }) @@ -45,7 +46,7 @@ #define copy_from_guest_offset(ptr, hnd, off, nr) ({ \ const typeof(ptr) _x = (hnd).p; \ const typeof(ptr) _y = (ptr); \ - hvm_guest(current) ? \ + shadow_mode_translate(current->domain) ? \ copy_from_user_hvm(_y, _x+(off), sizeof(*_x)*(nr)) :\ copy_from_user(_y, _x+(off), sizeof(*_x)*(nr)); \ }) @@ -54,7 +55,7 @@ #define copy_field_to_guest(hnd, ptr, field) ({ \ const typeof(&(ptr)->field) _x = &(hnd).p->field; \ const typeof(&(ptr)->field) _y = &(ptr)->field; \ - hvm_guest(current) ? \ + shadow_mode_translate(current->domain) ? \ copy_to_user_hvm(_x, _y, sizeof(*_x)) : \ copy_to_user(_x, _y, sizeof(*_x)); \ }) @@ -63,7 +64,7 @@ #define copy_field_from_guest(ptr, hnd, field) ({ \ const typeof(&(ptr)->field) _x = &(hnd).p->field; \ const typeof(&(ptr)->field) _y = &(ptr)->field; \ - hvm_guest(current) ? \ + shadow_mode_translate(current->domain) ? \ copy_from_user_hvm(_y, _x, sizeof(*_x)) : \ copy_from_user(_y, _x, sizeof(*_x)); \ }) @@ -73,12 +74,13 @@ * Allows use of faster __copy_* functions. */ #define guest_handle_okay(hnd, nr) \ - (hvm_guest(current) || array_access_ok((hnd).p, (nr), sizeof(*(hnd).p))) + (shadow_mode_external(current->domain) || \ + array_access_ok((hnd).p, (nr), sizeof(*(hnd).p))) #define __copy_to_guest_offset(hnd, off, ptr, nr) ({ \ const typeof(ptr) _x = (hnd).p; \ const typeof(ptr) _y = (ptr); \ - hvm_guest(current) ? \ + shadow_mode_translate(current->domain) ? \ copy_to_user_hvm(_x+(off), _y, sizeof(*_x)*(nr)) : \ __copy_to_user(_x+(off), _y, sizeof(*_x)*(nr)); \ }) @@ -86,7 +88,7 @@ #define __copy_from_guest_offset(ptr, hnd, off, nr) ({ \ const typeof(ptr) _x = (hnd).p; \ const typeof(ptr) _y = (ptr); \ - hvm_guest(current) ? \ + shadow_mode_translate(current->domain) ? \ copy_from_user_hvm(_y, _x+(off),sizeof(*_x)*(nr)) : \ __copy_from_user(_y, _x+(off), sizeof(*_x)*(nr)); \ }) @@ -94,7 +96,7 @@ #define __copy_field_to_guest(hnd, ptr, field) ({ \ const typeof(&(ptr)->field) _x = &(hnd).p->field; \ const typeof(&(ptr)->field) _y = &(ptr)->field; \ - hvm_guest(current) ? \ + shadow_mode_translate(current->domain) ? \ copy_to_user_hvm(_x, _y, sizeof(*_x)) : \ __copy_to_user(_x, _y, sizeof(*_x)); \ }) @@ -102,7 +104,7 @@ #define __copy_field_from_guest(ptr, hnd, field) ({ \ const typeof(&(ptr)->field) _x = &(hnd).p->field; \ const typeof(&(ptr)->field) _y = &(ptr)->field; \ - hvm_guest(current) ? \ + shadow_mode_translate(current->domain) ? \ copy_from_user_hvm(_x, _y, sizeof(*_x)) : \ __copy_from_user(_y, _x, sizeof(*_x)); \ }) diff -r 914c44d10c8d -r 2bfd19fc1b79 xen/include/asm-x86/hvm/io.h --- a/xen/include/asm-x86/hvm/io.h Sun Oct 01 11:39:41 2006 -0600 +++ b/xen/include/asm-x86/hvm/io.h Sun Oct 01 19:10:18 2006 -0600 @@ -68,6 +68,7 @@ #define INSTR_TEST 12 #define INSTR_BT 13 #define INSTR_XCHG 14 +#define INSTR_SUB 15 struct instruction { __s8 instr; /* instruction type */ diff -r 914c44d10c8d -r 2bfd19fc1b79 xen/include/asm-x86/hvm/support.h --- a/xen/include/asm-x86/hvm/support.h Sun Oct 01 11:39:41 2006 -0600 +++ b/xen/include/asm-x86/hvm/support.h Sun Oct 01 19:10:18 2006 -0600 @@ -118,7 +118,7 @@ extern unsigned int opt_hvm_debug_level; extern unsigned int opt_hvm_debug_level; #define HVM_DBG_LOG(level, _f, _a...) \ do { \ - if ( (level) & opt_hvm_debug_level ) \ + if ( unlikely((level) & opt_hvm_debug_level) ) \ printk("[HVM:%d.%d] <%s> " _f "\n", \ current->domain->domain_id, current->vcpu_id, __func__, \ ## _a); \ @@ -136,16 +136,18 @@ extern unsigned int opt_hvm_debug_level; extern int hvm_enabled; -enum { HVM_COPY_IN = 0, HVM_COPY_OUT }; -extern int hvm_copy(void *buf, unsigned long vaddr, int size, int dir); +int hvm_copy_to_guest_phys(unsigned long paddr, void *buf, int size); +int hvm_copy_from_guest_phys(void *buf, unsigned long paddr, int size); +int hvm_copy_to_guest_virt(unsigned long vaddr, void *buf, int size); +int hvm_copy_from_guest_virt(void *buf, unsigned long vaddr, int size); -extern void hvm_setup_platform(struct domain* d); -extern int hvm_mmio_intercept(ioreq_t *p); -extern int hvm_io_intercept(ioreq_t *p, int type); -extern int hvm_buffered_io_intercept(ioreq_t *p); -extern void hvm_hooks_assist(struct vcpu *v); -extern void hvm_print_line(struct vcpu *v, const char c); -extern void hlt_timer_fn(void *data); +void hvm_setup_platform(struct domain* d); +int hvm_mmio_intercept(ioreq_t *p); +int hvm_io_intercept(ioreq_t *p, int type); +int hvm_buffered_io_intercept(ioreq_t *p); +void hvm_hooks_assist(struct vcpu *v); +void hvm_print_line(struct vcpu *v, const char c); +void hlt_timer_fn(void *data); void hvm_do_hypercall(struct cpu_user_regs *pregs); diff -r 914c44d10c8d -r 2bfd19fc1b79 xen/include/asm-x86/hvm/vioapic.h --- a/xen/include/asm-x86/hvm/vioapic.h Sun Oct 01 11:39:41 2006 -0600 +++ b/xen/include/asm-x86/hvm/vioapic.h Sun Oct 01 19:10:18 2006 -0600 @@ -88,6 +88,7 @@ typedef union RedirStatus typedef struct hvm_vioapic { uint32_t irr; + uint32_t irr_xen; /* interrupts forced on by the hypervisor. */ uint32_t isr; /* This is used for level trigger */ uint32_t imr; uint32_t ioregsel; @@ -105,6 +106,7 @@ hvm_vioapic_t *hvm_vioapic_init(struct d void hvm_vioapic_do_irqs_clear(struct domain *d, uint16_t irqs); void hvm_vioapic_do_irqs(struct domain *d, uint16_t irqs); +void hvm_vioapic_set_xen_irq(struct domain *d, int irq, int level); void hvm_vioapic_set_irq(struct domain *d, int irq, int level); int hvm_vioapic_add_lapic(struct vlapic *vlapic, struct vcpu *v); diff -r 914c44d10c8d -r 2bfd19fc1b79 xen/include/asm-x86/hvm/vpic.h --- a/xen/include/asm-x86/hvm/vpic.h Sun Oct 01 11:39:41 2006 -0600 +++ b/xen/include/asm-x86/hvm/vpic.h Sun Oct 01 19:10:18 2006 -0600 @@ -34,6 +34,8 @@ typedef struct PicState { typedef struct PicState { uint8_t last_irr; /* edge detection */ uint8_t irr; /* interrupt request register */ + uint8_t irr_xen; /* interrupts forced on by the hypervisor e.g. + the callback irq. */ uint8_t imr; /* interrupt mask register */ uint8_t isr; /* interrupt service register */ uint8_t priority_add; /* highest irq priority */ @@ -58,20 +60,16 @@ struct hvm_virpic { void (*irq_request)(void *opaque, int level); void *irq_request_opaque; /* IOAPIC callback support */ - void (*alt_irq_func)(void *opaque, int irq_num, int level); - void *alt_irq_opaque; spinlock_t lock; }; +void pic_set_xen_irq(void *opaque, int irq, int level); void pic_set_irq(struct hvm_virpic *s, int irq, int level); void pic_set_irq_new(void *opaque, int irq, int level); void pic_init(struct hvm_virpic *s, void (*irq_request)(void *, int), void *irq_request_opaque); -void pic_set_alt_irq_func(struct hvm_virpic *s, - void (*alt_irq_func)(void *, int, int), - void *alt_irq_opaque); int pic_read_irq(struct hvm_virpic *s); void pic_update_irq(struct hvm_virpic *s); /* Caller must hold s->lock */ uint32_t pic_intack_read(struct hvm_virpic *s); diff -r 914c44d10c8d -r 2bfd19fc1b79 xen/include/asm-x86/mm.h --- a/xen/include/asm-x86/mm.h Sun Oct 01 11:39:41 2006 -0600 +++ b/xen/include/asm-x86/mm.h Sun Oct 01 19:10:18 2006 -0600 @@ -348,7 +348,7 @@ void memguard_unguard_range(void *p, uns void memguard_guard_stack(void *p); -int ptwr_do_page_fault(struct domain *, unsigned long, +int ptwr_do_page_fault(struct vcpu *, unsigned long, struct cpu_user_regs *); int audit_adjust_pgtables(struct domain *d, int dir, int noisy); diff -r 914c44d10c8d -r 2bfd19fc1b79 xen/include/asm-x86/shadow.h --- a/xen/include/asm-x86/shadow.h Sun Oct 01 11:39:41 2006 -0600 +++ b/xen/include/asm-x86/shadow.h Sun Oct 01 19:10:18 2006 -0600 @@ -26,6 +26,7 @@ #include <public/domctl.h> #include <xen/sched.h> #include <xen/perfc.h> +#include <xen/domain_page.h> #include <asm/flushtlb.h> /* How to make sure a page is not referred to in a shadow PT */ @@ -245,7 +246,9 @@ shadow_vcpu_mode_translate(struct vcpu * // enabled. (HVM vcpu's with paging disabled are using the p2m table as // its paging table, so no translation occurs in this case.) // - return v->arch.shadow.hvm_paging_enabled; + // It is also true for translated PV domains. + // + return v->arch.shadow.translate_enabled; } @@ -287,6 +290,10 @@ struct shadow_paging_mode { struct x86_emulate_ctxt *ctxt); mfn_t (*make_monitor_table )(struct vcpu *v); void (*destroy_monitor_table )(struct vcpu *v, mfn_t mmfn); + void * (*guest_map_l1e )(struct vcpu *v, unsigned long va, + unsigned long *gl1mfn); + void (*guest_get_eff_l1e )(struct vcpu *v, unsigned long va, + void *eff_l1e); #if SHADOW_OPTIMIZATIONS & SHOPT_WRITABLE_HEURISTIC int (*guess_wrmap )(struct vcpu *v, unsigned long vaddr, mfn_t gmfn); @@ -452,9 +459,73 @@ shadow_destroy_monitor_table(struct vcpu v->arch.shadow.mode->destroy_monitor_table(v, mmfn); } +static inline void * +guest_map_l1e(struct vcpu *v, unsigned long addr, unsigned long *gl1mfn) +{ + if ( likely(!shadow_mode_translate(v->domain)) ) + { + l2_pgentry_t l2e; + ASSERT(!shadow_mode_external(v->domain)); + /* Find this l1e and its enclosing l1mfn in the linear map */ + if ( __copy_from_user(&l2e, + &__linear_l2_table[l2_linear_offset(addr)], + sizeof(l2_pgentry_t)) != 0 ) + return NULL; + /* Check flags that it will be safe to read the l1e */ + if ( (l2e_get_flags(l2e) & (_PAGE_PRESENT | _PAGE_PSE)) + != _PAGE_PRESENT ) + return NULL; + *gl1mfn = l2e_get_pfn(l2e); + return &__linear_l1_table[l1_linear_offset(addr)]; + } + + return v->arch.shadow.mode->guest_map_l1e(v, addr, gl1mfn); +} + +static inline void +guest_unmap_l1e(struct vcpu *v, void *p) +{ + if ( unlikely(shadow_mode_translate(v->domain)) ) + unmap_domain_page(p); +} + +static inline void +guest_get_eff_l1e(struct vcpu *v, unsigned long addr, void *eff_l1e) +{ + if ( likely(!shadow_mode_translate(v->domain)) ) + { + ASSERT(!shadow_mode_external(v->domain)); + if ( __copy_from_user(eff_l1e, + &__linear_l1_table[l1_linear_offset(addr)], + sizeof(l1_pgentry_t)) != 0 ) + *(l1_pgentry_t *)eff_l1e = l1e_empty(); + return; + } + + v->arch.shadow.mode->guest_get_eff_l1e(v, addr, eff_l1e); +} + +static inline void +guest_get_eff_kern_l1e(struct vcpu *v, unsigned long addr, void *eff_l1e) +{ +#if defined(__x86_64__) + int user_mode = !(v->arch.flags & TF_kernel_mode); +#define TOGGLE_MODE() if ( user_mode ) toggle_guest_mode(v) +#else +#define TOGGLE_MODE() ((void)0) +#endif + + TOGGLE_MODE(); + guest_get_eff_l1e(v, addr, eff_l1e); + TOGGLE_MODE(); +} + + /* Validate a pagetable change from the guest and update the shadows. */ extern int shadow_validate_guest_entry(struct vcpu *v, mfn_t gmfn, void *new_guest_entry); +extern int __shadow_validate_guest_entry(struct vcpu *v, mfn_t gmfn, + void *entry, u32 size); /* Update the shadows in response to a pagetable write from a HVM guest */ extern void shadow_validate_guest_pt_write(struct vcpu *v, mfn_t gmfn, @@ -481,7 +552,12 @@ extern void sh_remove_shadows(struct vcp extern void sh_remove_shadows(struct vcpu *v, mfn_t gmfn, int all); static inline void shadow_remove_all_shadows(struct vcpu *v, mfn_t gmfn) { + int was_locked = shadow_lock_is_acquired(v->domain); + if ( !was_locked ) + shadow_lock(v->domain); sh_remove_shadows(v, gmfn, 1); + if ( !was_locked ) + shadow_unlock(v->domain); } /* Add a page to a domain */ @@ -624,7 +700,14 @@ sh_mfn_to_gfn(struct domain *d, mfn_t mf return mfn_x(mfn); } - +static inline l1_pgentry_t +gl1e_to_ml1e(struct domain *d, l1_pgentry_t l1e) +{ + if ( unlikely(shadow_mode_translate(d)) ) + l1e = l1e_from_pfn(gmfn_to_mfn(d, l1e_get_pfn(l1e)), + l1e_get_flags(l1e)); + return l1e; +} #endif /* _XEN_SHADOW_H */ diff -r 914c44d10c8d -r 2bfd19fc1b79 xen/common/symbols-dummy.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/common/symbols-dummy.c Sun Oct 01 19:10:18 2006 -0600 @@ -0,0 +1,16 @@ +/* + * symbols-dummy.c: dummy symbol-table definitions for the inital partial + * link of the hypervisor image. + */ + +#include <xen/config.h> +#include <xen/types.h> + +unsigned long symbols_addresses[1]; +unsigned long symbols_num_syms; +u8 symbols_names[1]; + +u8 symbols_token_table[1]; +u16 symbols_token_index[1]; + +unsigned long symbols_markers[1]; diff -r 914c44d10c8d -r 2bfd19fc1b79 tools/debugger/pdb/Domain.ml --- a/tools/debugger/pdb/Domain.ml Sun Oct 01 11:39:41 2006 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +0,0 @@ -(** Domain.ml - * - * domain context implementation - * - * @author copyright (c) 2005 alex ho - * @see <www.cl.cam.ac.uk/netos/pdb> pervasive debugger - * @version 1 - *) - -open Int32 -open Intel - -type context_t = -{ - mutable domain : int; - mutable vcpu : int -} - -let default_context = { domain = 0; vcpu = 0 } - -let new_context new_dom new_vcpu = {domain = new_dom; vcpu = new_vcpu} - -let set_domain ctx value = - ctx.domain <- value - -let set_vcpu ctx value = - ctx.vcpu <- value - -let get_domain ctx = - ctx.domain - -let get_vcpu ctx = - ctx.vcpu - -let string_of_context ctx = - Printf.sprintf "{domain} domain: %d, vcpu: %d" - ctx.domain ctx.vcpu - -external read_register : context_t -> int -> int32 = "dom_read_register" -external read_registers : context_t -> registers = "dom_read_registers" -external write_register : context_t -> register -> int32 -> unit = - "dom_write_register" -external read_memory : context_t -> int32 -> int -> int list = - "dom_read_memory" -external write_memory : context_t -> int32 -> int list -> unit = - "dom_write_memory" - -external continue : context_t -> unit = "dom_continue_target" -external step : context_t -> unit = "dom_step_target" - -external insert_memory_breakpoint : context_t -> int32 -> int -> unit = - "dom_insert_memory_breakpoint" -external remove_memory_breakpoint : context_t -> int32 -> int -> unit = - "dom_remove_memory_breakpoint" - -external attach_debugger : int -> int -> unit = "dom_attach_debugger" -external detach_debugger : int -> int -> unit = "dom_detach_debugger" -external pause_target : int -> unit = "dom_pause_target" - -let pause ctx = - pause_target ctx.domain diff -r 914c44d10c8d -r 2bfd19fc1b79 tools/debugger/pdb/Domain.mli --- a/tools/debugger/pdb/Domain.mli Sun Oct 01 11:39:41 2006 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ -(** Domain.mli - * - * domain context interface - * - * @author copyright (c) 2005 alex ho - * @see <www.cl.cam.ac.uk/netos/pdb> pervasive debugger - * @version 1 - *) - -open Int32 -open Intel - -type context_t - -val default_context : context_t -val new_context : int -> int -> context_t - -val set_domain : context_t -> int -> unit -val get_domain : context_t -> int -val set_vcpu : context_t -> int -> unit -val get_vcpu : context_t -> int - -val string_of_context : context_t -> string - -val read_register : context_t -> int -> int32 -val read_registers : context_t -> registers -val write_register : context_t -> register -> int32 -> unit -val read_memory : context_t -> int32 -> int -> int list -val write_memory : context_t -> int32 -> int list -> unit - -val continue : context_t -> unit -val step : context_t -> unit - -val insert_memory_breakpoint : context_t -> int32 -> int -> unit -val remove_memory_breakpoint : context_t -> int32 -> int -> unit - -val attach_debugger : int -> int -> unit -val detach_debugger : int -> int -> unit -val pause : context_t -> unit diff -r 914c44d10c8d -r 2bfd19fc1b79 tools/debugger/pdb/Intel.ml --- a/tools/debugger/pdb/Intel.ml Sun Oct 01 11:39:41 2006 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,66 +0,0 @@ -(** Intel.ml - * - * various sundry Intel x86 definitions - * - * @author copyright (c) 2005 alex ho - * @see <www.cl.cam.ac.uk/netos/pdb> pervasive debugger - * @version 1 - *) - - -type register = - | EAX - | ECX - | EDX - | EBX - | ESP - | EBP - | ESI - | EDI - | EIP - | EFL - | CS - | SS - | DS - | ES - | FS - | GS - -type registers = - { eax : int32; - ecx : int32; - edx : int32; - ebx : int32; - esp : int32; - ebp : int32; - esi : int32; - edi : int32; - eip : int32; - efl : int32; - cs : int32; - ss : int32; - ds : int32; - es : int32; - fs : int32; - gs : int32 - } - -let null_registers = - { eax = 0l; - ecx = 0l; - edx = 0l; - ebx = 0l; - esp = 0l; - ebp = 0l; - esi = 0l; - edi = 0l; - eip = 0l; - efl = 0l; - cs = 0l; - ss = 0l; - ds = 0l; - es = 0l; - fs = 0l; - gs = 0l - } - diff -r 914c44d10c8d -r 2bfd19fc1b79 tools/debugger/pdb/Makefile --- a/tools/debugger/pdb/Makefile Sun Oct 01 11:39:41 2006 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +0,0 @@ -OCAMLMAKEFILE = OCamlMakefile - -XEN_ROOT = ../../.. -include $(XEN_ROOT)/tools/Rules.mk - -# overwrite LDFLAGS from xen/tool/Rules.mk -# otherwise, ocamlmktop gets confused. -LDFLAGS = - -# force ocaml 3.08 -OCAML_ROOT = /usr/local -OCAMLC = $(OCAML_ROOT)/bin/ocamlc -OCAMLMKTOP = $(OCAML_ROOT)/bin/ocamlmktop -OCAMLLIBPATH= $(OCAML_ROOT)/lib/ocaml - -INCLUDES += -I $(XEN_XC) -INCLUDES += -I $(XEN_LIBXC) -INCLUDES += -I ../libxendebug -INCLUDES += -I ./linux-2.6-module -INCLUDES += -I $(OCAML_ROOT)/lib/ocaml - -CFLAGS += $(INCLUDES) -CFLAGS += -Werror -CFLAGS += -g - -CLIBS += xc -CLIBS += xendebug - -LIBDIRS += $(XEN_LIBXC) -LIBDIRS += ../libxendebug - -LIBS += unix str - -# bc = byte-code, dc = debug byte-code -# patches = patch linux domU source code -.PHONY: all -all : dc - -SOURCES += pdb_caml_xc.c -SOURCES += pdb_caml_domain.c pdb_caml_process.c -SOURCES += pdb_caml_evtchn.c pdb_caml_xcs.c pdb_xen.c -SOURCES += Util.ml Intel.ml -SOURCES += evtchn.ml evtchn.mli -SOURCES += xcs.ml xcs.mli -SOURCES += Xen_domain.ml Xen_domain.mli -SOURCES += Domain.ml Process.ml -SOURCES += Domain.mli Process.mli -SOURCES += PDB.ml debugger.ml server.ml - -RESULT = pdb - -include $(OCAMLMAKEFILE) - -PATCHDIR = ./linux-2.6-patches -.PHONY: patches -patches : - make -C $(PATCHDIR) patches diff -r 914c44d10c8d -r 2bfd19fc1b79 tools/debugger/pdb/OCamlMakefile --- a/tools/debugger/pdb/OCamlMakefile Sun Oct 01 11:39:41 2006 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1149 +0,0 @@ -########################################################################### -# OCamlMakefile -# Copyright (C) 1999-2004 Markus Mottl -# -# For updates see: -# http://www.oefai.at/~markus/ocaml_sources -# -# $Id: OCamlMakefile,v 1.1 2005/05/19 09:30:48 root Exp $ -# -########################################################################### - -# Modified by damien for .glade.ml compilation - -# Set these variables to the names of the sources to be processed and -# the result variable. Order matters during linkage! - -ifndef SOURCES - SOURCES := foo.ml -endif -export SOURCES - -ifndef RES_CLIB_SUF - RES_CLIB_SUF := _stubs -endif -export RES_CLIB_SUF - -ifndef RESULT - RESULT := foo -endif -export RESULT - -export LIB_PACK_NAME - -ifndef DOC_FILES - DOC_FILES := $(filter %.mli, $(SOURCES)) -endif -export DOC_FILES - -export BCSUFFIX -export NCSUFFIX - -ifndef TOPSUFFIX - TOPSUFFIX := .top -endif -export TOPSUFFIX - -# Eventually set include- and library-paths, libraries to link, -# additional compilation-, link- and ocamlyacc-flags -# Path- and library information needs not be written with "-I" and such... -# Define THREADS if you need it, otherwise leave it unset (same for -# USE_CAMLP4)! - -export THREADS -export VMTHREADS -export ANNOTATE -export USE_CAMLP4 - -export INCDIRS -export LIBDIRS -export EXTLIBDIRS -export RESULTDEPS -export OCAML_DEFAULT_DIRS - -export LIBS -export CLIBS - -export OCAMLFLAGS -export OCAMLNCFLAGS -export OCAMLBCFLAGS - -export OCAMLLDFLAGS -export OCAMLNLDFLAGS -export OCAMLBLDFLAGS - -ifndef OCAMLCPFLAGS - OCAMLCPFLAGS := a -endif - -export OCAMLCPFLAGS - -export PPFLAGS - -export YFLAGS -export IDLFLAGS - -export OCAMLDOCFLAGS - -export OCAMLFIND_INSTFLAGS - -export DVIPSFLAGS - -export STATIC - -# Add a list of optional trash files that should be deleted by "make clean" -export TRASH - -#################### variables depending on your OCaml-installation - -ifdef MINGW - export MINGW - WIN32 := 1 - CFLAGS_WIN32 := -mno-cygwin -endif -ifdef MSVC - export MSVC - WIN32 := 1 - ifndef STATIC - CPPFLAGS_WIN32 := -DCAML_DLL - endif - CFLAGS_WIN32 += -nologo - EXT_OBJ := obj - EXT_LIB := lib - ifeq ($(CC),gcc) - # work around GNU Make default value - ifdef THREADS - CC := cl -MT - else - CC := cl - endif - endif - ifeq ($(CXX),g++) - # work around GNU Make default value - CXX := $(CC) - endif - CFLAG_O := -Fo -endif -ifdef WIN32 - EXT_CXX := cpp - EXE := .exe -endif - -ifndef EXT_OBJ - EXT_OBJ := o -endif -ifndef EXT_LIB - EXT_LIB := a -endif -ifndef EXT_CXX - EXT_CXX := cc -endif -ifndef EXE - EXE := # empty -endif -ifndef CFLAG_O - CFLAG_O := -o # do not delete this comment (preserves trailing whitespace)! -endif - -export CC -export CXX -export CFLAGS -export CXXFLAGS -export LDFLAGS -export CPPFLAGS - -ifndef RPATH_FLAG - RPATH_FLAG := -R -endif -export RPATH_FLAG - -ifndef MSVC -ifndef PIC_CFLAGS - PIC_CFLAGS := -fPIC -endif -ifndef PIC_CPPFLAGS - PIC_CPPFLAGS := -DPIC -endif -endif - -export PIC_CFLAGS -export PIC_CPPFLAGS - -BCRESULT := $(addsuffix $(BCSUFFIX), $(RESULT)) -NCRESULT := $(addsuffix $(NCSUFFIX), $(RESULT)) -TOPRESULT := $(addsuffix $(TOPSUFFIX), $(RESULT)) - -ifndef OCAMLFIND - OCAMLFIND := ocamlfind -endif -export OCAMLFIND - -ifndef OCAMLC - OCAMLC := ocamlc -endif -export OCAMLC - -ifndef OCAMLOPT - OCAMLOPT := ocamlopt -endif -export OCAMLOPT - -ifndef OCAMLMKTOP - OCAMLMKTOP := ocamlmktop -endif -export OCAMLMKTOP - -ifndef OCAMLCP - OCAMLCP := ocamlcp -endif -export OCAMLCP - -ifndef OCAMLDEP - OCAMLDEP := ocamldep -endif -export OCAMLDEP - -ifndef OCAMLLEX - OCAMLLEX := ocamllex -endif -export OCAMLLEX - -ifndef OCAMLYACC - OCAMLYACC := ocamlyacc -endif -export OCAMLYACC - -ifndef OCAMLMKLIB - OCAMLMKLIB := ocamlmklib -endif -export OCAMLMKLIB - -ifndef OCAML_GLADECC - OCAML_GLADECC := lablgladecc2 -endif -export OCAML_GLADECC - -ifndef OCAML_GLADECC_FLAGS - OCAML_GLADECC_FLAGS := -endif -export OCAML_GLADECC_FLAGS - -ifndef CAMELEON_REPORT - CAMELEON_REPORT := report -endif -export CAMELEON_REPORT - -ifndef CAMELEON_REPORT_FLAGS - CAMELEON_REPORT_FLAGS := -endif -export CAMELEON_REPORT_FLAGS - -ifndef CAMELEON_ZOGGY - CAMELEON_ZOGGY := camlp4o pa_zog.cma pr_o.cmo -endif -export CAMELEON_ZOGGY - -ifndef CAMELEON_ZOGGY_FLAGS - CAMELEON_ZOGGY_FLAGS := -endif -export CAMELEON_ZOGGY_FLAGS - -ifndef OXRIDL - OXRIDL := oxridl -endif -export OXRIDL - -ifndef CAMLIDL - CAMLIDL := camlidl -endif -export CAMLIDL - -ifndef CAMLIDLDLL - CAMLIDLDLL := camlidldll -endif -export CAMLIDLDLL - -ifndef NOIDLHEADER - MAYBE_IDL_HEADER := -header -endif -export NOIDLHEADER - -export NO_CUSTOM - -ifndef CAMLP4 - CAMLP4 := camlp4 -endif -export CAMLP4 - -ifndef REAL_OCAMLFIND - ifdef PACKS - ifndef CREATE_LIB - ifdef THREADS - PACKS += threads - endif - endif - empty := - space := $(empty) $(empty) - comma := , - ifdef PREDS - PRE_OCAML_FIND_PREDICATES := $(subst $(space),$(comma),$(PREDS)) - PRE_OCAML_FIND_PACKAGES := $(subst $(space),$(comma),$(PACKS)) - OCAML_FIND_PREDICATES := -predicates $(PRE_OCAML_FIND_PREDICATES) - # OCAML_DEP_PREDICATES := -syntax $(PRE_OCAML_FIND_PREDICATES) - OCAML_FIND_PACKAGES := $(OCAML_FIND_PREDICATES) -package $(PRE_OCAML_FIND_PACKAGES) - OCAML_DEP_PACKAGES := $(OCAML_DEP_PREDICATES) -package $(PRE_OCAML_FIND_PACKAGES) - else - OCAML_FIND_PACKAGES := -package $(subst $(space),$(comma),$(PACKS)) - OCAML_DEP_PACKAGES := - endif - OCAML_FIND_LINKPKG := -linkpkg - REAL_OCAMLFIND := $(OCAMLFIND) - endif -endif - -export OCAML_FIND_PACKAGES -export OCAML_DEP_PACKAGES -export OCAML_FIND_LINKPKG -export REAL_OCAMLFIND - -ifndef OCAMLDOC - OCAMLDOC := ocamldoc -endif -export OCAMLDOC - -ifndef LATEX - LATEX := latex -endif -export LATEX - -ifndef DVIPS - DVIPS := dvips -endif -export DVIPS - -ifndef PS2PDF - PS2PDF := ps2pdf -endif -export PS2PDF - -ifndef OCAMLMAKEFILE - OCAMLMAKEFILE := OCamlMakefile -endif -export OCAMLMAKEFILE - -ifndef OCAMLLIBPATH - OCAMLLIBPATH := \ - $(shell $(OCAMLC) 2>/dev/null -where || echo /usr/local/lib/ocaml) -endif -export OCAMLLIBPATH - -ifndef OCAML_LIB_INSTALL - OCAML_LIB_INSTALL := $(OCAMLLIBPATH)/contrib -endif -export OCAML_LIB_INSTALL - -########################################################################### - -#################### change following sections only if -#################### you know what you are doing! - -# delete target files when a build command fails -.PHONY: .DELETE_ON_ERROR -.DELETE_ON_ERROR: - -# for pedants using "--warn-undefined-variables" -export MAYBE_IDL -export REAL_RESULT -export CAMLIDLFLAGS -export THREAD_FLAG -export RES_CLIB -export MAKEDLL -export ANNOT_FLAG -export C_OXRIDL -export SUBPROJS -export CFLAGS_WIN32 -export CPPFLAGS_WIN32 - -INCFLAGS := - -SHELL := /bin/sh - -MLDEPDIR := ._d -BCDIDIR := ._bcdi -NCDIDIR := ._ncdi - -FILTER_EXTNS := %.mli %.ml %.mll %.mly %.idl %.oxridl %.c %.$(EXT_CXX) %.rep %.zog %.glade - -FILTERED := $(filter $(FILTER_EXTNS), $(SOURCES)) -SOURCE_DIRS := $(filter-out ./, $(sort $(dir $(FILTERED)))) - -FILTERED_REP := $(filter %.rep, $(FILTERED)) -DEP_REP := $(FILTERED_REP:%.rep=$(MLDEPDIR)/%.d) -AUTO_REP := $(FILTERED_REP:.rep=.ml) - -FILTERED_ZOG := $(filter %.zog, $(FILTERED)) -DEP_ZOG := $(FILTERED_ZOG:%.zog=$(MLDEPDIR)/%.d) -AUTO_ZOG := $(FILTERED_ZOG:.zog=.ml) - -FILTERED_GLADE := $(filter %.glade, $(FILTERED)) -DEP_GLADE := $(FILTERED_GLADE:%.glade=$(MLDEPDIR)/%.d) -AUTO_GLADE := $(FILTERED_GLADE:.glade=.ml) - -FILTERED_ML := $(filter %.ml, $(FILTERED)) -DEP_ML := $(FILTERED_ML:%.ml=$(MLDEPDIR)/%.d) - -FILTERED_MLI := $(filter %.mli, $(FILTERED)) -DEP_MLI := $(FILTERED_MLI:.mli=.di) - -FILTERED_MLL := $(filter %.mll, $(FILTERED)) -DEP_MLL := $(FILTERED_MLL:%.mll=$(MLDEPDIR)/%.d) -AUTO_MLL := $(FILTERED_MLL:.mll=.ml) - -FILTERED_MLY := $(filter %.mly, $(FILTERED)) -DEP_MLY := $(FILTERED_MLY:%.mly=$(MLDEPDIR)/%.d) $(FILTERED_MLY:.mly=.di) -AUTO_MLY := $(FILTERED_MLY:.mly=.mli) $(FILTERED_MLY:.mly=.ml) - -FILTERED_IDL := $(filter %.idl, $(FILTERED)) -DEP_IDL := $(FILTERED_IDL:%.idl=$(MLDEPDIR)/%.d) $(FILTERED_IDL:.idl=.di) -C_IDL := $(FILTERED_IDL:%.idl=%_stubs.c) -ifndef NOIDLHEADER - C_IDL += $(FILTERED_IDL:.idl=.h) -endif -OBJ_C_IDL := $(FILTERED_IDL:%.idl=%_stubs.$(EXT_OBJ)) -AUTO_IDL := $(FILTERED_IDL:.idl=.mli) $(FILTERED_IDL:.idl=.ml) $(C_IDL) - -FILTERED_OXRIDL := $(filter %.oxridl, $(FILTERED)) -DEP_OXRIDL := $(FILTERED_OXRIDL:%.oxridl=$(MLDEPDIR)/%.d) $(FILTERED_OXRIDL:.oxridl=.di) -AUTO_OXRIDL := $(FILTERED_OXRIDL:.oxridl=.mli) $(FILTERED_OXRIDL:.oxridl=.ml) $(C_OXRIDL) - -FILTERED_C_CXX := $(filter %.c %.$(EXT_CXX), $(FILTERED)) -OBJ_C_CXX := $(FILTERED_C_CXX:.c=.$(EXT_OBJ)) -OBJ_C_CXX := $(OBJ_C_CXX:.$(EXT_CXX)=.$(EXT_OBJ)) - -PRE_TARGETS += $(AUTO_MLL) $(AUTO_MLY) $(AUTO_IDL) $(AUTO_OXRIDL) $(AUTO_ZOG) $(AUTO_REP) $(AUTO_GLADE) - -ALL_DEPS := $(DEP_ML) $(DEP_MLI) $(DEP_MLL) $(DEP_MLY) $(DEP_IDL) $(DEP_OXRIDL) $(DEP_ZOG) $(DEP_REP) $(DEP_GLADE) - -MLDEPS := $(filter %.d, $(ALL_DEPS)) -MLIDEPS := $(filter %.di, $(ALL_DEPS)) -BCDEPIS := $(MLIDEPS:%.di=$(BCDIDIR)/%.di) -NCDEPIS := $(MLIDEPS:%.di=$(NCDIDIR)/%.di) - -ALLML := $(filter %.mli %.ml %.mll %.mly %.idl %.oxridl %.rep %.zog %.glade, $(FILTERED)) - -IMPLO_INTF := $(ALLML:%.mli=%.mli.__) -IMPLO_INTF := $(foreach file, $(IMPLO_INTF), \ - $(basename $(file)).cmi $(basename $(file)).cmo) -IMPLO_INTF := $(filter-out %.mli.cmo, $(IMPLO_INTF)) -IMPLO_INTF := $(IMPLO_INTF:%.mli.cmi=%.cmi) - -IMPLX_INTF := $(IMPLO_INTF:.cmo=.cmx) - -INTF := $(filter %.cmi, $(IMPLO_INTF)) -IMPL_CMO := $(filter %.cmo, $(IMPLO_INTF)) -IMPL_CMX := $(IMPL_CMO:.cmo=.cmx) -IMPL_ASM := $(IMPL_CMO:.cmo=.asm) -IMPL_S := $(IMPL_CMO:.cmo=.s) - -OBJ_LINK := $(OBJ_C_IDL) $(OBJ_C_CXX) -OBJ_FILES := $(IMPL_CMO:.cmo=.$(EXT_OBJ)) $(OBJ_LINK) - -EXECS := $(addsuffix $(EXE), \ - $(sort $(TOPRESULT) $(BCRESULT) $(NCRESULT))) -ifdef WIN32 - EXECS += $(BCRESULT).dll $(NCRESULT).dll -endif - -CLIB_BASE := $(RESULT)$(RES_CLIB_SUF) -ifneq ($(strip $(OBJ_LINK)),) - RES_CLIB := lib$(CLIB_BASE).$(EXT_LIB) -endif - -ifdef WIN32 -DLLSONAME := $(CLIB_BASE).dll -else -DLLSONAME := dll$(CLIB_BASE).so -endif - -NONEXECS := $(INTF) $(IMPL_CMO) $(IMPL_CMX) $(IMPL_ASM) $(IMPL_S) \ - $(OBJ_FILES) $(PRE_TARGETS) $(BCRESULT).cma $(NCRESULT).cmxa \ - $(NCRESULT).$(EXT_LIB) $(BCRESULT).cmi $(BCRESULT).cmo \ - $(NCRESULT).cmi $(NCRESULT).cmx $(NCRESULT).o \ - $(RES_CLIB) $(IMPL_CMO:.cmo=.annot) \ - $(LIB_PACK_NAME).cmi $(LIB_PACK_NAME).cmo $(LIB_PACK_NAME).cmx $(LIB_PACK_NAME).o - -ifndef STATIC - NONEXECS += $(DLLSONAME) -endif - -ifndef LIBINSTALL_FILES - LIBINSTALL_FILES := $(RESULT).mli $(RESULT).cmi $(RESULT).cma \ - $(RESULT).cmxa $(RESULT).$(EXT_LIB) $(RES_CLIB) - ifndef STATIC - ifneq ($(strip $(OBJ_LINK)),) - LIBINSTALL_FILES += $(DLLSONAME) - endif - endif -endif - -export LIBINSTALL_FILES - -ifdef WIN32 - # some extra stuff is created while linking DLLs - NONEXECS += $(BCRESULT).$(EXT_LIB) $(BCRESULT).exp $(NCRESULT).exp $(CLIB_BASE).exp $(CLIB_BASE).lib -endif - -TARGETS := $(EXECS) $(NONEXECS) - -# If there are IDL-files -ifneq ($(strip $(FILTERED_IDL)),) - MAYBE_IDL := -cclib -lcamlidl -endif - -ifdef USE_CAMLP4 - CAMLP4PATH := \ - $(shell $(CAMLP4) -where 2>/dev/null || echo /usr/local/lib/camlp4) - INCFLAGS := -I $(CAMLP4PATH) - CINCFLAGS := -I$(CAMLP4PATH) -endif - -DINCFLAGS := $(INCFLAGS) $(SOURCE_DIRS:%=-I %) $(OCAML_DEFAULT_DIRS:%=-I %) -INCFLAGS := $(DINCFLAGS) $(INCDIRS:%=-I %) -CINCFLAGS += $(SOURCE_DIRS:%=-I%) $(INCDIRS:%=-I%) $(OCAML_DEFAULT_DIRS:%=-I%) - -ifndef MSVC -CLIBFLAGS += $(SOURCE_DIRS:%=-L%) $(LIBDIRS:%=-L%) \ - $(EXTLIBDIRS:%=-L%) $(EXTLIBDIRS:%=-Wl,$(RPATH_FLAG)%) \ - $(OCAML_DEFAULT_DIRS:%=-L%) -endif - -ifndef PROFILING - INTF_OCAMLC := $(OCAMLC) -else - ifndef THREADS - INTF_OCAMLC := $(OCAMLCP) -p $(OCAMLCPFLAGS) - else - # OCaml does not support profiling byte code - # with threads (yet), therefore we force an error. - ifndef REAL_OCAMLC - $(error Profiling of multithreaded byte code not yet supported by OCaml) - endif - INTF_OCAMLC := $(OCAMLC) - endif -endif - -ifndef MSVC -COMMON_LDFLAGS := $(LDFLAGS:%=-ccopt %) $(SOURCE_DIRS:%=-ccopt -L%) \ - $(LIBDIRS:%=-ccopt -L%) $(EXTLIBDIRS:%=-ccopt -L%) \ - $(EXTLIBDIRS:%=-ccopt -Wl,$(RPATH_FLAG)%) \ - $(OCAML_DEFAULT_DIRS:%=-ccopt -L%) -else -COMMON_LDFLAGS := -ccopt "/link -NODEFAULTLIB:LIBC $(LDFLAGS:%=%) $(SOURCE_DIRS:%=-LIBPATH:%) \ - $(LIBDIRS:%=-LIBPATH:%) $(EXTLIBDIRS:%=-LIBPATH:%) \ - $(OCAML_DEFAULT_DIRS:%=-LIBPATH:%) " -endif - -CLIBS_OPTS := $(CLIBS:%=-cclib -l%) -ifdef MSVC - ifndef STATIC - # MSVC libraries do not have 'lib' prefix - CLIBS_OPTS := $(CLIBS:%=-cclib %.lib) - endif -endif - -ifneq ($(strip $(OBJ_LINK)),) - ifdef CREATE_LIB - OBJS_LIBS := -cclib -l$(CLIB_BASE) $(CLIBS_OPTS) $(MAYBE_IDL) - else - OBJS_LIBS := $(OBJ_LINK) $(CLIBS_OPTS) $(MAYBE_IDL) - endif -else - OBJS_LIBS := $(CLIBS_OPTS) $(MAYBE_IDL) -endif - -# If we have to make byte-code -ifndef REAL_OCAMLC - BYTE_OCAML := y - - # EXTRADEPS is added dependencies we have to insert for all - # executable files we generate. Ideally it should be all of the - # libraries we use, but it's hard to find the ones that get searched on - # the path since I don't know the paths built into the compiler, so - # just include the ones with slashes in their names. - EXTRADEPS := $(addsuffix .cma,$(foreach i,$(LIBS),$(if $(findstring /,$(i)),$(i)))) - SPECIAL_OCAMLFLAGS := $(OCAMLBCFLAGS) - - REAL_OCAMLC := $(INTF_OCAMLC) - - REAL_IMPL := $(IMPL_CMO) - REAL_IMPL_INTF := $(IMPLO_INTF) - IMPL_SUF := .cmo - - DEPFLAGS := - MAKE_DEPS := $(MLDEPS) $(BCDEPIS) - - ifdef CREATE_LIB - CFLAGS := $(PIC_CFLAGS) $(CFLAGS) - CPPFLAGS := $(PIC_CPPFLAGS) $(CPPFLAGS) - ifndef STATIC - ifneq ($(strip $(OBJ_LINK)),) - MAKEDLL := $(DLLSONAME) - ALL_LDFLAGS := -dllib $(DLLSONAME) - endif - endif - endif - - ifndef NO_CUSTOM - ifneq "$(strip $(OBJ_LINK) $(THREADS) $(MAYBE_IDL) $(CLIBS))" "" - ALL_LDFLAGS += -custom - endif - endif - - ALL_LDFLAGS += $(INCFLAGS) $(OCAMLLDFLAGS) $(OCAMLBLDFLAGS) \ - $(COMMON_LDFLAGS) $(LIBS:%=%.cma) - CAMLIDLDLLFLAGS := - - ifdef THREADS - ifdef VMTHREADS - THREAD_FLAG := -vmthread - else - THREAD_FLAG := -thread - endif - ALL_LDFLAGS := $(THREAD_FLAG) $(ALL_LDFLAGS) - ifndef CREATE_LIB - ifndef REAL_OCAMLFIND - ALL_LDFLAGS := unix.cma threads.cma $(ALL_LDFLAGS) - endif - endif - endif - -# we have to make native-code -else - EXTRADEPS := $(addsuffix .cmxa,$(foreach i,$(LIBS),$(if $(findstring /,$(i)),$(i)))) - ifndef PROFILING - SPECIAL_OCAMLFLAGS := $(OCAMLNCFLAGS) - PLDFLAGS := - else - SPECIAL_OCAMLFLAGS := -p $(OCAMLNCFLAGS) - PLDFLAGS := -p - endif - - REAL_IMPL := $(IMPL_CMX) - REAL_IMPL_INTF := $(IMPLX_INTF) - IMPL_SUF := .cmx - - CPPFLAGS := -DNATIVE_CODE $(CPPFLAGS) - - DEPFLAGS := -native - MAKE_DEPS := $(MLDEPS) $(NCDEPIS) - - ALL_LDFLAGS := $(PLDFLAGS) $(INCFLAGS) $(OCAMLLDFLAGS) \ - $(OCAMLNLDFLAGS) $(COMMON_LDFLAGS) - CAMLIDLDLLFLAGS := -opt - - ifndef CREATE_LIB - ALL_LDFLAGS += $(LIBS:%=%.cmxa) - else - CFLAGS := $(PIC_CFLAGS) $(CFLAGS) - CPPFLAGS := $(PIC_CPPFLAGS) $(CPPFLAGS) - endif - - ifdef THREADS - THREAD_FLAG := -thread - ALL_LDFLAGS := $(THREAD_FLAG) $(ALL_LDFLAGS) - ifndef CREATE_LIB - ifndef REAL_OCAMLFIND - ALL_LDFLAGS := unix.cmxa threads.cmxa $(ALL_LDFLAGS) - endif - endif - endif -endif - -export MAKE_DEPS - -ifdef ANNOTATE - ANNOT_FLAG := -dtypes -else -endif - -ALL_OCAMLCFLAGS := $(THREAD_FLAG) $(ANNOT_FLAG) $(OCAMLFLAGS) \ - $(INCFLAGS) $(SPECIAL_OCAMLFLAGS) - -ifdef make_deps - -include $(MAKE_DEPS) - PRE_TARGETS := -endif - -########################################################################### -# USER RULES - -# Call "OCamlMakefile QUIET=" to get rid of all of the @'s. -QUIET=@ - -# generates byte-code (default) -byte-code: $(PRE_TARGETS) - $(QUIET)$(MAKE) -r -f $(OCAMLMAKEFILE) $(BCRESULT) \ - REAL_RESULT="$(BCRESULT)" make_deps=yes -bc: byte-code - -byte-code-nolink: $(PRE_TARGETS) - $(QUIET)$(MAKE) -r -f $(OCAMLMAKEFILE) nolink \ - REAL_RESULT="$(BCRESULT)" make_deps=yes -bcnl: byte-code-nolink - -top: $(PRE_TARGETS) - $(QUIET)$(MAKE) -r -f $(OCAMLMAKEFILE) $(TOPRESULT) \ - REAL_RESULT="$(BCRESULT)" make_deps=yes - -# generates native-code - -native-code: $(PRE_TARGETS) - $(QUIET)$(MAKE) -r -f $(OCAMLMAKEFILE) $(NCRESULT) \ - REAL_RESULT="$(NCRESULT)" \ - REAL_OCAMLC="$(OCAMLOPT)" \ - make_deps=yes -nc: native-code - -native-code-nolink: $(PRE_TARGETS) - $(QUIET)$(MAKE) -r -f $(OCAMLMAKEFILE) nolink \ - REAL_RESULT="$(NCRESULT)" \ - REAL_OCAMLC="$(OCAMLOPT)" \ - make_deps=yes -ncnl: native-code-nolink - -# generates byte-code libraries -byte-code-library: $(PRE_TARGETS) - $(QUIET)$(MAKE) -r -f $(OCAMLMAKEFILE) \ - $(RES_CLIB) $(BCRESULT).cma \ - REAL_RESULT="$(BCRESULT)" \ - CREATE_LIB=yes \ - make_deps=yes -bcl: byte-code-library - -# generates native-code libraries -native-code-library: $(PRE_TARGETS) - $(QUIET)$(MAKE) -r -f $(OCAMLMAKEFILE) \ - $(RES_CLIB) $(NCRESULT).cmxa \ - REAL_RESULT="$(NCRESULT)" \ - REAL_OCAMLC="$(OCAMLOPT)" \ - CREATE_LIB=yes \ - make_deps=yes -ncl: native-code-library - -ifdef WIN32 -# generates byte-code dll -byte-code-dll: $(PRE_TARGETS) - $(QUIET)$(MAKE) -r -f $(OCAMLMAKEFILE) \ - $(RES_CLIB) $(BCRESULT).dll \ - REAL_RESULT="$(BCRESULT)" \ - make_deps=yes -bcd: byte-code-dll - -# generates native-code dll -native-code-dll: $(PRE_TARGETS) - $(QUIET)$(MAKE) -r -f $(OCAMLMAKEFILE) \ - $(RES_CLIB) $(NCRESULT).dll \ - REAL_RESULT="$(NCRESULT)" \ - REAL_OCAMLC="$(OCAMLOPT)" \ - make_deps=yes -ncd: native-code-dll -endif - -# generates byte-code with debugging information -debug-code: $(PRE_TARGETS) - $(QUIET)$(MAKE) -r -f $(OCAMLMAKEFILE) $(BCRESULT) \ - REAL_RESULT="$(BCRESULT)" make_deps=yes \ - OCAMLFLAGS="-g $(OCAMLFLAGS)" \ - OCAMLLDFLAGS="-g $(OCAMLLDFLAGS)" -dc: debug-code - -debug-code-nolink: $(PRE_TARGETS) - $(QUIET)$(MAKE) -r -f $(OCAMLMAKEFILE) nolink \ - REAL_RESULT="$(BCRESULT)" make_deps=yes \ - OCAMLFLAGS="-g $(OCAMLFLAGS)" \ - OCAMLLDFLAGS="-g $(OCAMLLDFLAGS)" -dcnl: debug-code-nolink - -# generates byte-code libraries with debugging information -debug-code-library: $(PRE_TARGETS) - $(QUIET)$(MAKE) -r -f $(OCAMLMAKEFILE) \ - $(RES_CLIB) $(BCRESULT).cma \ - REAL_RESULT="$(BCRESULT)" make_deps=yes \ - CREATE_LIB=yes \ - OCAMLFLAGS="-g $(OCAMLFLAGS)" \ - OCAMLLDFLAGS="-g $(OCAMLLDFLAGS)" -dcl: debug-code-library - -# generates byte-code for profiling -profiling-byte-code: $(PRE_TARGETS) - $(QUIET)$(MAKE) -r -f $(OCAMLMAKEFILE) $(BCRESULT) \ - REAL_RESULT="$(BCRESULT)" PROFILING="y" \ - make_deps=yes -pbc: profiling-byte-code - -# generates native-code - -profiling-native-code: $(PRE_TARGETS) - $(QUIET)$(MAKE) -r -f $(OCAMLMAKEFILE) $(NCRESULT) \ - REAL_RESULT="$(NCRESULT)" \ - REAL_OCAMLC="$(OCAMLOPT)" \ - PROFILING="y" \ - make_deps=yes -pnc: profiling-native-code - -# generates byte-code libraries -profiling-byte-code-library: $(PRE_TARGETS) - $(QUIET)$(MAKE) -r -f $(OCAMLMAKEFILE) \ - $(RES_CLIB) $(BCRESULT).cma \ - REAL_RESULT="$(BCRESULT)" PROFILING="y" \ - CREATE_LIB=yes \ - make_deps=yes -pbcl: profiling-byte-code-library - -# generates native-code libraries -profiling-native-code-library: $(PRE_TARGETS) - $(QUIET)$(MAKE) -r -f $(OCAMLMAKEFILE) \ - $(RES_CLIB) $(NCRESULT).cmxa \ - REAL_RESULT="$(NCRESULT)" PROFILING="y" \ - REAL_OCAMLC="$(OCAMLOPT)" \ - CREATE_LIB=yes \ - make_deps=yes -pncl: profiling-native-code-library - -# packs byte-code objects -pack-byte-code: $(PRE_TARGETS) - $(QUIET)$(MAKE) -r -f $(OCAMLMAKEFILE) $(BCRESULT).cmo \ - REAL_RESULT="$(BCRESULT)" \ - PACK_LIB=yes make_deps=yes -pabc: pack-byte-code - -# packs native-code objects -pack-native-code: $(PRE_TARGETS) - $(QUIET)$(MAKE) -r -f $(OCAMLMAKEFILE) \ - $(NCRESULT).cmx $(NCRESULT).o \ - REAL_RESULT="$(NCRESULT)" \ - REAL_OCAMLC="$(OCAMLOPT)" \ - PACK_LIB=yes make_deps=yes -panc: pack-native-code - -# generates HTML-documentation -htdoc: doc/$(RESULT)/html - -# generates Latex-documentation -ladoc: doc/$(RESULT)/latex - -# generates PostScript-documentation -psdoc: doc/$(RESULT)/latex/doc.ps - -# generates PDF-documentation -pdfdoc: doc/$(RESULT)/latex/doc.pdf - -# generates all supported forms of documentation -doc: htdoc ladoc psdoc pdfdoc - -########################################################################### -# LOW LEVEL RULES - -$(REAL_RESULT): $(REAL_IMPL_INTF) $(OBJ_LINK) $(EXTRADEPS) $(RESULTDEPS) - $(REAL_OCAMLFIND) $(REAL_OCAMLC) \ - $(OCAML_FIND_PACKAGES) $(OCAML_FIND_LINKPKG) \ - $(ALL_LDFLAGS) $(OBJS_LIBS) -o $@$(EXE) \ - $(REAL_IMPL) - -nolink: $(REAL_IMPL_INTF) $(OBJ_LINK) - -ifdef WIN32 -$(REAL_RESULT).dll: $(REAL_IMPL_INTF) $(OBJ_LINK) - $(CAMLIDLDLL) $(CAMLIDLDLLFLAGS) $(OBJ_LINK) $(CLIBS) \ - -o $@ $(REAL_IMPL) -endif - -%$(TOPSUFFIX): $(REAL_IMPL_INTF) $(OBJ_LINK) $(EXTRADEPS) - $(REAL_OCAMLFIND) $(OCAMLMKTOP) \ - $(OCAML_FIND_PACKAGES) $(OCAML_FIND_LINKPKG) \ - $(ALL_LDFLAGS) $(OBJS_LIBS) -o $@$(EXE) \ - $(REAL_IMPL) - -.SUFFIXES: .mli .ml .cmi .cmo .cmx .cma .cmxa .$(EXT_OBJ) \ - .mly .di .d .$(EXT_LIB) .idl %.oxridl .c .$(EXT_CXX) .h .so \ - .rep .zog .glade - -ifndef STATIC -ifdef MINGW -$(DLLSONAME): $(OBJ_LINK) - $(CC) $(CFLAGS) $(CFLAGS_WIN32) $(OBJ_LINK) -shared -o $@ \ - -Wl,--whole-archive $(wildcard $(foreach dir,$(LIBDIRS),$(CLIBS:%=$(dir)/lib%.a))) \ - $(OCAMLLIBPATH)/ocamlrun.a \ - -Wl,--export-all-symbols \ - -Wl,--no-whole-archive -else -ifdef MSVC -$(DLLSONAME): $(OBJ_LINK) - link /NOLOGO /DLL /OUT:$@ $(OBJ_LINK) \ - $(wildcard $(foreach dir,$(LIBDIRS),$(CLIBS:%=$(dir)/%.lib))) \ - $(OCAMLLIBPATH)/ocamlrun.lib - -else -$(DLLSONAME): $(OBJ_LINK) - $(OCAMLMKLIB) $(INCFLAGS) $(CLIBFLAGS) \ - -o $(CLIB_BASE) $(OBJ_LINK) $(CLIBS:%=-l%) \ - $(OCAMLMKLIB_FLAGS) -endif -endif -endif - -ifndef LIB_PACK_NAME -$(RESULT).cma: $(REAL_IMPL_INTF) $(MAKEDLL) $(EXTRADEPS) $(RESULTDEPS) - $(REAL_OCAMLFIND) $(REAL_OCAMLC) -a $(ALL_LDFLAGS) \ - $(OBJS_LIBS) -o $@ $(OCAMLBLDFLAGS) $(REAL_IMPL) - -$(RESULT).cmxa $(RESULT).$(EXT_LIB): $(REAL_IMPL_INTF) $(EXTRADEPS) $(RESULTDEPS) - $(REAL_OCAMLFIND) $(OCAMLOPT) -a $(ALL_LDFLAGS) $(OBJS_LIBS) \ - $(OCAMLNLDFLAGS) -o $@ $(REAL_IMPL) -else -ifdef BYTE_OCAML -$(LIB_PACK_NAME).cmi $(LIB_PACK_NAME).cmo: $(REAL_IMPL_INTF) - $(REAL_OCAMLFIND) $(REAL_OCAMLC) -pack -o $(LIB_PACK_NAME).cmo $(REAL_IMPL) -else -$(LIB_PACK_NAME).cmi $(LIB_PACK_NAME).cmx: $(REAL_IMPL_INTF) - $(REAL_OCAMLFIND) $(REAL_OCAMLC) -pack -o $(LIB_PACK_NAME).cmx $(REAL_IMPL) -endif - -$(RESULT).cma: $(LIB_PACK_NAME).cmi $(LIB_PACK_NAME).cmo $(MAKEDLL) $(EXTRADEPS) $(RESULTDEPS) - $(REAL_OCAMLFIND) $(REAL_OCAMLC) -a $(ALL_LDFLAGS) \ - $(OBJS_LIBS) -o $@ $(OCAMLBLDFLAGS) $(LIB_PACK_NAME).cmo - -$(RESULT).cmxa $(RESULT).$(EXT_LIB): $(LIB_PACK_NAME).cmi $(LIB_PACK_NAME).cmx $(EXTRADEPS) $(RESULTDEPS) - $(REAL_OCAMLFIND) $(OCAMLOPT) -a $(ALL_LDFLAGS) $(OBJS_LIBS) \ - $(OCAMLNLDFLAGS) -o $@ $(LIB_PACK_NAME).cmx -endif - -$(RES_CLIB): $(OBJ_LINK) -ifndef MSVC - ifneq ($(strip $(OBJ_LINK)),) - $(AR) rcs $@ $(OBJ_LINK) - endif -else - ifneq ($(strip $(OBJ_LINK)),) - lib -nologo -debugtype:cv -out:$(RES_CLIB) $(OBJ_LINK) - endif -endif - -.mli.cmi: $(EXTRADEPS) - $(QUIET)pp=`sed -n -e '/^#/d' -e 's/(\*pp \([^*]*\) \*)/\1/p;q' $<`; \ - if [ -z "$$pp" ]; then \ - echo $(REAL_OCAMLFIND) $(INTF_OCAMLC) $(OCAML_FIND_PACKAGES) \ - -c $(THREAD_FLAG) $(ANNOT_FLAG) \ - $(OCAMLFLAGS) $(INCFLAGS) $<; \ - $(REAL_OCAMLFIND) $(INTF_OCAMLC) $(OCAML_FIND_PACKAGES) \ - -c $(THREAD_FLAG) $(ANNOT_FLAG) \ - $(OCAMLFLAGS) $(INCFLAGS) $<; \ - else \ - echo $(REAL_OCAMLFIND) $(INTF_OCAMLC) $(OCAML_FIND_PACKAGES) \ - -c -pp \"$$pp $(PPFLAGS)\" $(THREAD_FLAG) $(ANNOT_FLAG) \ - $(OCAMLFLAGS) $(INCFLAGS) $<; \ - $(REAL_OCAMLFIND) $(INTF_OCAMLC) $(OCAML_FIND_PACKAGES) \ - -c -pp "$$pp $(PPFLAGS)" $(THREAD_FLAG) $(ANNOT_FLAG) \ - $(OCAMLFLAGS) $(INCFLAGS) $<; \ - fi - -.ml.cmi .ml.$(EXT_OBJ) .ml.cmx .ml.cmo: $(EXTRADEPS) - $(QUIET)pp=`sed -n -e '/^#/d' -e 's/(\*pp \([^*]*\) \*)/\1/p;q' $<`; \ - if [ -z "$$pp" ]; then \ - echo $(REAL_OCAMLFIND) $(REAL_OCAMLC) $(OCAML_FIND_PACKAGES) \ - -c $(ALL_OCAMLCFLAGS) $<; \ - $(REAL_OCAMLFIND) $(REAL_OCAMLC) $(OCAML_FIND_PACKAGES) \ - -c $(ALL_OCAMLCFLAGS) $<; \ - else \ - echo $(REAL_OCAMLFIND) $(REAL_OCAMLC) $(OCAML_FIND_PACKAGES) \ - -c -pp \"$$pp $(PPFLAGS)\" $(ALL_OCAMLCFLAGS) $<; \ - $(REAL_OCAMLFIND) $(REAL_OCAMLC) $(OCAML_FIND_PACKAGES) \ - -c -pp "$$pp $(PPFLAGS)" $(ALL_OCAMLCFLAGS) $<; \ - fi - -ifdef PACK_LIB -$(REAL_RESULT).cmo $(REAL_RESULT).cmx $(REAL_RESULT).o: $(REAL_IMPL_INTF) $(OBJ_LINK) $(EXTRADEPS) - $(REAL_OCAMLFIND) $(REAL_OCAMLC) -pack $(ALL_LDFLAGS) \ - $(OBJS_LIBS) -o $@ $(REAL_IMPL) -endif - -.PRECIOUS: %.ml -%.ml: %.mll - $(OCAMLLEX) $< - -.PRECIOUS: %.ml %.mli -%.ml %.mli: %.mly - $(OCAMLYACC) $(YFLAGS) $< - $(QUIET)pp=`sed -n -e 's/.*(\*pp \([^*]*\) \*).*/\1/p;q' $<`; \ - if [ ! -z "$$pp" ]; then \ - mv $*.ml $*.ml.temporary; \ - echo "(*pp $$pp $(PPFLAGS)*)" > $*.ml; \ - cat $*.ml.temporary >> $*.ml; \ - rm $*.ml.temporary; \ - mv $*.mli $*.mli.temporary; \ - echo "(*pp $$pp $(PPFLAGS)*)" > $*.mli; \ - cat $*.mli.temporary >> $*.mli; \ - rm $*.mli.temporary; \ - fi - - -.PRECIOUS: %.ml -%.ml: %.rep - $(CAMELEON_REPORT) $(CAMELEON_REPORT_FLAGS) -gen $< - -.PRECIOUS: %.ml -%.ml: %.zog - $(CAMELEON_ZOGGY) $(CAMELEON_ZOGGY_FLAGS) -impl $< > $@ - -.PRECIOUS: %.ml -%.ml: %.glade - $(OCAML_GLADECC) $(OCAML_GLADECC_FLAGS) $< > $@ - -.PRECIOUS: %.ml %.mli -%.ml %.mli: %.oxridl - $(OXRIDL) $< - -.PRECIOUS: %.ml %.mli %_stubs.c %.h -%.ml %.mli %_stubs.c %.h: %.idl - $(CAMLIDL) $(MAYBE_IDL_HEADER) $(IDLFLAGS) \ - $(CAMLIDLFLAGS) $< - $(QUIET)if [ $(NOIDLHEADER) ]; then touch $*.h; fi - -.c.$(EXT_OBJ): - $(OCAMLC) -c -cc "$(CC)" -ccopt "$(CFLAGS) \ - $(CPPFLAGS) $(CPPFLAGS_WIN32) \ - $(CFLAGS_WIN32) $(CINCFLAGS) $(CFLAG_O)$@ " $< - -.$(EXT_CXX).$(EXT_OBJ): - $(CXX) -c $(CXXFLAGS) $(CINCFLAGS) $(CPPFLAGS) \ - -I'$(OCAMLLIBPATH)' \ - $< $(CFLAG_O)$@ - -$(MLDEPDIR)/%.d: %.ml - $(QUIET)echo making $@ from $< - $(QUIET)if [ ! -d $(@D) ]; then mkdir -p $(@D); fi - $(QUIET)pp=`sed -n -e '/^#/d' -e 's/(\*pp \([^*]*\) \*)/\1/p;q' $<`; \ - if [ -z "$$pp" ]; then \ - $(REAL_OCAMLFIND) $(OCAMLDEP) $(OCAML_DEP_PACKAGES) \ - $(DINCFLAGS) $< > $@; \ - else \ - $(REAL_OCAMLFIND) $(OCAMLDEP) $(OCAML_DEP_PACKAGES) \ - -pp "$$pp $(PPFLAGS)" $(DINCFLAGS) $< > $@; \ - fi - -$(BCDIDIR)/%.di $(NCDIDIR)/%.di: %.mli - $(QUIET)echo making $@ from $< - $(QUIET)if [ ! -d $(@D) ]; then mkdir -p $(@D); fi - $(QUIET)pp=`sed -n -e '/^#/d' -e 's/(\*pp \([^*]*\) \*)/\1/p;q' $<`; \ - if [ -z "$$pp" ]; then \ - $(REAL_OCAMLFIND) $(OCAMLDEP) $(DEPFLAGS) $(DINCFLAGS) $< > $@; \ - else \ - $(REAL_OCAMLFIND) $(OCAMLDEP) $(DEPFLAGS) \ - -pp "$$pp $(PPFLAGS)" $(DINCFLAGS) $< > $@; \ - fi - -doc/$(RESULT)/html: $(DOC_FILES) - rm -rf $@ - mkdir -p $@ - $(QUIET)pp=`sed -n -e '/^#/d' -e 's/(\*pp \([^*]*\) \*)/\1/p;q' $<`; \ - if [ -z "$$pp" ]; then \ - echo $(OCAMLDOC) -html -d $@ $(OCAMLDOCFLAGS) $(INCFLAGS) $(DOC_FILES); \ - $(OCAMLDOC) -html -d $@ $(OCAMLDOCFLAGS) $(INCFLAGS) $(DOC_FILES); \ - else \ - echo $(OCAMLDOC) -pp \"$$pp $(PPFLAGS)\" -html -d $@ $(OCAMLDOCFLAGS) \ - $(INCFLAGS) $(DOC_FILES); \ - $(OCAMLDOC) -pp "$$pp $(PPFLAGS)" -html -d $@ $(OCAMLDOCFLAGS) \ - $(INCFLAGS) $(DOC_FILES); \ - fi - -doc/$(RESULT)/latex: $(DOC_FILES) - rm -rf $@ - mkdir -p $@ - $(QUIET)pp=`sed -n -e '/^#/d' -e 's/(\*pp \([^*]*\) \*)/\1/p;q' $<`; \ - if [ -z "$$pp" ]; then \ - echo $(OCAMLDOC) -latex $(OCAMLDOCFLAGS) $(INCFLAGS) \ - $(DOC_FILES) -o $@/doc.tex; \ - $(OCAMLDOC) -latex $(OCAMLDOCFLAGS) $(INCFLAGS) $(DOC_FILES) \ - -o $@/doc.tex; \ - else \ - echo $(OCAMLDOC) -pp \"$$pp $(PPFLAGS)\" -latex $(OCAMLDOCFLAGS) \ - $(INCFLAGS) $(DOC_FILES) -o $@/doc.tex; \ - $(OCAMLDOC) -pp "$$pp $(PPFLAGS)" -latex $(OCAMLDOCFLAGS) \ - $(INCFLAGS) $(DOC_FILES) -o $@/doc.tex; \ - fi - -doc/$(RESULT)/latex/doc.ps: doc/$(RESULT)/latex - cd doc/$(RESULT)/latex && \ - $(LATEX) doc.tex && \ - $(LATEX) doc.tex && \ - $(DVIPS) $(DVIPSFLAGS) doc.dvi -o $(@F) - -doc/$(RESULT)/latex/doc.pdf: doc/$(RESULT)/latex/doc.ps - cd doc/$(RESULT)/latex && $(PS2PDF) $(<F) - -define make_subproj -.PHONY: -subproj_$(1): - $$(eval $$(call PROJ_$(1))) - $(QUIET)if [ "$(SUBTARGET)" != "all" ]; then \ - $(MAKE) -f $(OCAMLMAKEFILE) $(SUBTARGET); \ - fi -endef - -$(foreach subproj,$(SUBPROJS),$(eval $(call make_subproj,$(subproj)))) - -.PHONY: -subprojs: $(SUBPROJS:%=subproj_%) - -########################################################################### -# (UN)INSTALL RULES FOR LIBRARIES - -.PHONY: libinstall -libinstall: all - $(QUIET)printf "\nInstalling library with ocamlfind\n" - $(OCAMLFIND) install $(OCAMLFIND_INSTFLAGS) $(RESULT) META $(LIBINSTALL_FILES) - $(QUIET)printf "\nInstallation successful.\n" - -.PHONY: libuninstall -libuninstall: - $(QUIET)printf "\nUninstalling library with ocamlfind\n" - $(OCAMLFIND) remove $(OCAMLFIND_INSTFLAGS) $(RESULT) - $(QUIET)printf "\nUninstallation successful.\n" - -.PHONY: rawinstall -rawinstall: all - $(QUIET)printf "\nInstalling library to: $(OCAML_LIB_INSTALL)\n" - -install -d $(OCAML_LIB_INSTALL) - for i in $(LIBINSTALL_FILES); do \ - if [ -f $$i ]; then \ - install -c -m 0644 $$i $(OCAML_LIB_INSTALL); \ - fi; \ - done - $(QUIET)printf "\nInstallation successful.\n" - -.PHONY: rawuninstall -rawuninstall: - $(QUIET)printf "\nUninstalling library from: $(OCAML_LIB_INSTALL)\n" - cd $(OCAML_LIB_INSTALL) && rm $(notdir $(LIBINSTALL_FILES)) - $(QUIET)printf "\nUninstallation successful.\n" - -########################################################################### -# MAINTAINANCE RULES - -.PHONY: clean -clean:: - rm -f $(TARGETS) $(TRASH) - rm -rf $(BCDIDIR) $(NCDIDIR) $(MLDEPDIR) - -.PHONY: cleanup -cleanup:: - rm -f $(NONEXECS) $(TRASH) - rm -rf $(BCDIDIR) $(NCDIDIR) $(MLDEPDIR) - -.PHONY: clean-doc -clean-doc:: - rm -rf doc - -.PHONY: nobackup -nobackup: - rm -f *.bak *~ *.dup diff -r 914c44d10c8d -r 2bfd19fc1b79 tools/debugger/pdb/PDB.ml --- a/tools/debugger/pdb/PDB.ml Sun Oct 01 11:39:41 2006 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,342 +0,0 @@ -(** PDB.ml - * - * Dispatch debugger commands to the appropriate context - * - * @author copyright (c) 2005 alex ho - * @see <www.cl.cam.ac.uk/netos/pdb> pervasive debugger - * @version 1 - *) - -open Util - -exception Unimplemented of string -exception Unknown_context of string -exception Unknown_domain -exception Unknown_process - -type context_t = - | Void - | Xen_virq - | Xen_xcs - | Xen_domain of Xen_domain.context_t - | Domain of Domain.context_t - | Process of Process.context_t - -let string_of_context ctx = - match ctx with - | Void -> "{void}" - | Xen_virq -> "{Xen virq evtchn}" - | Xen_xcs -> "{Xen xcs socket}" - | Xen_domain d -> Xen_domain.string_of_context d - | Domain d -> Domain.string_of_context d - | Process p -> Process.string_of_context p - - -let hash = Hashtbl.create 10 - - -(***************************************************************************) - -let find_context key = - try - Hashtbl.find hash key - with - Not_found -> - print_endline "error: (find_context) PDB context not found"; - raise Not_found - -let delete_context key = - Hashtbl.remove hash key - - -(** - find_process : Locate the socket associated with the context(s) - matching a particular (domain, process id) pair. if there are multiple - contexts (there shouldn't be), then return the first one. - *) - -let find_process dom pid = - let find key ctx list = - match ctx with - | Process p -> - if (((Process.get_domain p) = dom) && - ((Process.get_process p) = pid)) - then - key :: list - else - list - | _ -> list - in - let sock_list = Hashtbl.fold find hash [] in - match sock_list with - | hd::tl -> hd - | [] -> raise Unknown_process - - -(** - find_domain : Locate the socket associated with the context(s) - matching a particular (domain, vcpu) pair. if there are multiple - contexts (there shouldn't be), then return the first one. - *) - -let find_domain dom vcpu = - let find key ctx list = - match ctx with - | Domain d -> - if (((Domain.get_domain d) = dom) && - ((Domain.get_vcpu d) = vcpu)) - then - key :: list - else - list - | _ -> list - in - let sock_list = Hashtbl.fold find hash [] in - match sock_list with - | hd::tl -> hd - | [] -> raise Unknown_domain - -(** - find_xen_domain_context : fetch the socket associated with the - xen_domain context for a domain. if there are multiple contexts - (there shouldn't be), then return the first one. - *) - -let find_xen_domain_context domain = - let find key ctx list = - match ctx with - | Xen_domain d -> - if ((Xen_domain.get_domain d) = domain) - then - key :: list - else - list - | _ -> list - in - let sock_list = Hashtbl.fold find hash [] in - match sock_list with - | hd::tl -> hd - | [] -> raise Unknown_domain - -let attach_debugger ctx = - match ctx with - | Domain d -> Domain.attach_debugger (Domain.get_domain d) - (Domain.get_vcpu d) - | Process p -> - begin - let xdom_sock = find_xen_domain_context (Process.get_domain p) in - let xdom_ctx = find_context xdom_sock in - begin - match xdom_ctx with - | Xen_domain d -> - Process.attach_debugger p d - | _ -> failwith ("context has wrong xen domain type") - end; - raise No_reply - end - | _ -> raise (Unimplemented "attach debugger") - -let detach_debugger ctx = - match ctx with - | Domain d -> - Domain.detach_debugger (Domain.get_domain d) - (Domain.get_vcpu d); - "OK" - | Process p -> - Process.detach_debugger p; - raise No_reply - | _ -> raise (Unimplemented "detach debugger") - - -let debug_contexts () = - print_endline "context list:"; - let print_context key ctx = - match ctx with - | Void -> print_endline (Printf.sprintf " [%s] {void}" - (Util.get_connection_info key)) - | Xen_virq -> print_endline (Printf.sprintf " [%s] {xen virq evtchn}" - (Util.get_connection_info key)) - | Xen_xcs -> print_endline (Printf.sprintf " [%s] {xen xcs socket}" - (Util.get_connection_info key)) - | Xen_domain d -> print_endline (Printf.sprintf " [%s] %s" - (Util.get_connection_info key) - (Xen_domain.string_of_context d)) - | Domain d -> print_endline (Printf.sprintf " [%s] %s" - (Util.get_connection_info key) - (Domain.string_of_context d)) - | Process p -> print_endline (Printf.sprintf " [%s] %s" - (Util.get_connection_info key) - (Process.string_of_context p)) - in - Hashtbl.iter print_context hash - -(** add_context : add a new context to the hash table. - * if there is an existing context for the same key then it - * is first removed implictly by the hash table replace function. - *) -let add_context (key:Unix.file_descr) context params = - match context with - | "void" -> Hashtbl.replace hash key Void - | "xen virq" -> Hashtbl.replace hash key Xen_virq - | "xen xcs" -> Hashtbl.replace hash key Xen_xcs - | "domain" -> - begin - match params with - | dom::vcpu::_ -> - let d = Domain(Domain.new_context dom vcpu) in - attach_debugger d; - Hashtbl.replace hash key d - | _ -> failwith "bogus parameters to domain context" - end - | "process" -> - begin - match params with - | dom::pid::_ -> - let p = Process(Process.new_context dom pid) in - Hashtbl.replace hash key p; - attach_debugger p - | _ -> failwith "bogus parameters to process context" - end - | "xen domain" - | _ -> raise (Unknown_context context) - -(* - * this is really bogus. add_xen_domain_context should really - * be a case within add_context. however, we need to pass in - * a pointer that can only be represented as an int32. - * this would require a different type for params... :( - * 31 bit integers suck. - *) -let add_xen_domain_context (key:Unix.file_descr) dom evtchn sring = - let d = Xen_domain.new_context dom evtchn sring in - Hashtbl.replace hash key (Xen_domain(d)) - - -let add_default_context sock = - add_context sock "void" [] - -(***************************************************************************) - -(***************************************************************************) - -let read_register ctx register = (* register is int32 because of sscanf *) - match ctx with - | Void -> 0l (* default for startup *) - | Domain d -> Domain.read_register d register - | Process p -> - begin - Process.read_register p register; - raise No_reply - end - | _ -> raise (Unimplemented "read registers") - -let read_registers ctx = - match ctx with - | Void -> Intel.null_registers (* default for startup *) - | Domain d -> Domain.read_registers d - | Process p -> - begin - Process.read_registers p; - raise No_reply - end - | _ -> raise (Unimplemented "read registers") - -let write_register ctx register value = - match ctx with - | Domain d -> Domain.write_register d register value - | Process p -> - begin - Process.write_register p register value; - raise No_reply - end - | _ -> raise (Unimplemented "write register") - - -let read_memory ctx addr len = - match ctx with - | Domain d -> Domain.read_memory d addr len - | Process p -> - begin - Process.read_memory p addr len; - raise No_reply - end - | _ -> raise (Unimplemented "read memory") - -let write_memory ctx addr values = - match ctx with - | Domain d -> Domain.write_memory d addr values - | Process p -> - begin - Process.write_memory p addr values; - raise No_reply - end - | _ -> raise (Unimplemented "write memory") - - -let continue ctx = - match ctx with - | Domain d -> Domain.continue d - | Process p -> Process.continue p - | _ -> raise (Unimplemented "continue") - -let step ctx = - match ctx with - | Domain d -> Domain.step d - | Process p -> Process.step p - | _ -> raise (Unimplemented "step") - - -let insert_memory_breakpoint ctx addr len = - match ctx with - | Domain d -> Domain.insert_memory_breakpoint d addr len - | Process p -> - begin - Process.insert_memory_breakpoint p addr len; - raise No_reply - end - | _ -> raise (Unimplemented "insert memory breakpoint") - -let remove_memory_breakpoint ctx addr len = - match ctx with - | Domain d -> Domain.remove_memory_breakpoint d addr len - | Process p -> - begin - Process.remove_memory_breakpoint p addr len; - raise No_reply - end - | _ -> raise (Unimplemented "remove memory breakpoint") - -let insert_watchpoint ctx kind addr len = - match ctx with -(* | Domain d -> Domain.insert_watchpoint d kind addr len TODO *) - | Process p -> - begin - Process.insert_watchpoint p kind addr len; - raise No_reply - end - | _ -> raise (Unimplemented "insert watchpoint") - -let remove_watchpoint ctx kind addr len = - match ctx with -(* | Domain d -> Domain.remove_watchpoint d kind addr len TODO *) - | Process p -> - begin - Process.remove_watchpoint p kind addr len; - raise No_reply - end - | _ -> raise (Unimplemented "remove watchpoint") - - -let pause ctx = - match ctx with - | Domain d -> Domain.pause d - | Process p -> Process.pause p - | _ -> raise (Unimplemented "pause target") - - -external open_debugger : unit -> unit = "open_context" -external close_debugger : unit -> unit = "close_context" - -(* this is just the domains right now... expand to other contexts later *) -external debugger_status : unit -> unit = "debugger_status" - diff -r 914c44d10c8d -r 2bfd19fc1b79 tools/debugger/pdb/Process.ml --- a/tools/debugger/pdb/Process.ml Sun Oct 01 11:39:41 2006 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,79 +0,0 @@ -(** Process.ml - * - * process context implementation - * - * @author copyright (c) 2005 alex ho - * @see <www.cl.cam.ac.uk/netos/pdb> pervasive debugger - * @version 1 - *) - -open Int32 -open Intel - -type context_t = -{ - mutable domain : int; - mutable process : int; - mutable evtchn : int; - mutable ring : int32; -} - -let default_context = { domain = 0; process = 0; evtchn = 0; ring = 0l } - -let new_context dom proc = { domain = dom; process = proc; - evtchn = 0; ring = 0l } - -let string_of_context ctx = - Printf.sprintf "{process} domain: %d, process: %d" - ctx.domain ctx.process - -let set_domain ctx value = - ctx.domain <- value; - print_endline (Printf.sprintf "ctx.domain <- %d" ctx.domain) - -let set_process ctx value = - ctx.process <- value; - print_endline (Printf.sprintf "ctx.process <- %d" ctx.process) - -let get_domain ctx = - ctx.domain - -let get_process ctx = - ctx.process - -external _attach_debugger : context_t -> unit = "proc_attach_debugger" -external detach_debugger : context_t -> unit = "proc_detach_debugger" -external pause_target : context_t -> unit = "proc_pause_target" - -(* save the event channel and ring for the domain for future use *) -let attach_debugger proc_ctx dom_ctx = - print_endline (Printf.sprintf "%d %lx" - (Xen_domain.get_evtchn dom_ctx) - (Xen_domain.get_ring dom_ctx)); - proc_ctx.evtchn <- Xen_domain.get_evtchn dom_ctx; - proc_ctx.ring <- Xen_domain.get_ring dom_ctx; - _attach_debugger proc_ctx - -external read_register : context_t -> int -> unit = "proc_read_register" -external read_registers : context_t -> unit = "proc_read_registers" -external write_register : context_t -> register -> int32 -> unit = - "proc_write_register" -external read_memory : context_t -> int32 -> int -> unit = - "proc_read_memory" -external write_memory : context_t -> int32 -> int list -> unit = - "proc_write_memory" - -external continue : context_t -> unit = "proc_continue_target" -external step : context_t -> unit = "proc_step_target" - -external insert_memory_breakpoint : context_t -> int32 -> int -> unit = - "proc_insert_memory_breakpoint" -external remove_memory_breakpoint : context_t -> int32 -> int -> unit = - "proc_remove_memory_breakpoint" -external insert_watchpoint : context_t -> int -> int32 -> int -> unit = - "proc_insert_watchpoint" -external remove_watchpoint : context_t -> int -> int32 -> int -> unit = - "proc_remove_watchpoint" - -let pause ctx = - pause_target ctx diff -r 914c44d10c8d -r 2bfd19fc1b79 tools/debugger/pdb/Process.mli --- a/tools/debugger/pdb/Process.mli Sun Oct 01 11:39:41 2006 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,41 +0,0 @@ -(** Process.mli - * - * process context interface - * - * @author copyright (c) 2005 alex ho - * @see <www.cl.cam.ac.uk/netos/pdb> pervasive debugger - * @version 1 - *) - -open Int32 -open Intel - -type context_t - -val default_context : context_t -val new_context : int -> int -> context_t - -val set_domain : context_t -> int -> unit -val get_domain : context_t -> int -val set_process : context_t -> int -> unit -val get_process : context_t -> int - -val string_of_context : context_t -> string - -val attach_debugger : context_t -> Xen_domain.context_t -> unit -val detach_debugger : context_t -> unit -val pause : context_t -> unit - -val read_register : context_t -> int -> unit -val read_registers : context_t -> unit -val write_register : context_t -> register -> int32 -> unit -val read_memory : context_t -> int32 -> int -> unit -val write_memory : context_t -> int32 -> int list -> unit - -val continue : context_t -> unit -val step : context_t -> unit - -val insert_memory_breakpoint : context_t -> int32 -> int -> unit -val remove_memory_breakpoint : context_t -> int32 -> int -> unit -val insert_watchpoint : context_t -> int -> int32 -> int -> unit -val remove_watchpoint : context_t -> int -> int32 -> int -> unit diff -r 914c44d10c8d -r 2bfd19fc1b79 tools/debugger/pdb/Util.ml --- a/tools/debugger/pdb/Util.ml Sun Oct 01 11:39:41 2006 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,165 +0,0 @@ -(** Util.ml - * - * various utility functions - * - * @author copyright (c) 2005 alex ho - * @see <www.cl.cam.ac.uk/netos/pdb> pervasive debugger - * @version 1 - *) - -let int_of_hexchar h = - let i = int_of_char h in - match h with - | '0' .. '9' -> i - (int_of_char '0') - | 'a' .. 'f' -> i - (int_of_char 'a') + 10 - | 'A' .. 'F' -> i - (int_of_char 'A') + 10 - | _ -> raise (Invalid_argument "unknown hex character") - -let hexchar_of_int i = - let hexchars = [| '0'; '1'; '2'; '3'; '4'; '5'; '6'; '7'; - '8'; '9'; 'a'; 'b'; 'c'; 'd'; 'e'; 'f' |] - in - hexchars.(i) - - -(** flip the bytes of a four byte int - *) - -let flip_int num = - let a = num mod 256 - and b = (num / 256) mod 256 - and c = (num / (256 * 256)) mod 256 - and d = (num / (256 * 256 * 256)) in - (a * 256 * 256 * 256) + (b * 256 * 256) + (c * 256) + d - - -let flip_int32 num = - let a = Int32.logand num 0xffl - and b = Int32.logand (Int32.shift_right_logical num 8) 0xffl - and c = Int32.logand (Int32.shift_right_logical num 16) 0xffl - and d = (Int32.shift_right_logical num 24) in - (Int32.logor - (Int32.logor (Int32.shift_left a 24) (Int32.shift_left b 16)) - (Int32.logor (Int32.shift_left c 8) d)) - - -let int_list_of_string_list list = - List.map (fun x -> int_of_string x) list - -let int_list_of_string str len = - let array_of_string s = - let int_array = Array.make len 0 in - for loop = 0 to len - 1 do - int_array.(loop) <- (Char.code s.[loop]); - done; - int_array - in - Array.to_list (array_of_string str) - - -(* remove leading and trailing whitespace from a string *) - -let chomp str = - let head = Str.regexp "^[ \t\r\n]+" in - let tail = Str.regexp "[ \t\r\n]+$" in - let str = Str.global_replace head "" str in - Str.global_replace tail "" str - -(* Stupid little parser for "<key>=<value>[,<key>=<value>]*" - It first chops the entire command at each ',', so no ',' in key or value! - Mucked to return a list of words for "value" - *) - -let list_of_string str = - let delim c = Str.regexp ("[ \t]*" ^ c ^ "[ \t]*") in - let str_list = Str.split (delim " ") str in - List.map (fun x -> chomp(x)) str_list - -let little_parser fn str = - let delim c = Str.regexp ("[ \t]*" ^ c ^ "[ \t]*") in - let str_list = Str.split (delim ",") str in - let pair s = - match Str.split (delim "=") s with - | [key;value] -> fn (chomp key) (list_of_string value) - | [key] -> fn (chomp key) [] - | _ -> failwith (Printf.sprintf "error: (little_parser) parse error [%s]" str) - in - List.iter pair str_list - -(* boolean list membership test *) -let not_list_member the_list element = - try - List.find (fun x -> x = element) the_list; - false - with - Not_found -> true - -(* a very inefficient way to remove the elements of one list from another *) -let list_remove the_list remove_list = - List.filter (not_list_member remove_list) the_list - -(* get a description of a file descriptor *) -let get_connection_info fd = - let get_local_info fd = - let sockname = Unix.getsockname fd in - match sockname with - | Unix.ADDR_UNIX(s) -> "unix" - | Unix.ADDR_INET(a,p) -> ((Unix.string_of_inet_addr a) ^ ":" ^ - (string_of_int p)) - and get_remote_info fd = - let sockname = Unix.getpeername fd in - match sockname with - | Unix.ADDR_UNIX(s) -> s - | Unix.ADDR_INET(a,p) -> ((Unix.string_of_inet_addr a) ^ ":" ^ - (string_of_int p)) - in - try - get_remote_info fd - with - | Unix.Unix_error (Unix.ENOTSOCK, s1, s2) -> - let s = Unix.fstat fd in - Printf.sprintf "dev: %d, inode: %d" s.Unix.st_dev s.Unix.st_ino - | Unix.Unix_error (Unix.EBADF, s1, s2) -> - let s = Unix.fstat fd in - Printf.sprintf "dev: %d, inode: %d" s.Unix.st_dev s.Unix.st_ino - | _ -> get_local_info fd - - -(* really write a string *) -let really_write fd str = - let strlen = String.length str in - let sent = ref 0 in - while (!sent < strlen) do - sent := !sent + (Unix.write fd str !sent (strlen - !sent)) - done - -let write_character fd ch = - let str = String.create 1 in - str.[0] <- ch; - really_write fd str - - - -let send_reply fd reply = - let checksum = ref 0 in - write_character fd '$'; - for loop = 0 to (String.length reply) - 1 do - write_character fd reply.[loop]; - checksum := !checksum + int_of_char reply.[loop] - done; - write_character fd '#'; - write_character fd (hexchar_of_int ((!checksum mod 256) / 16)); - write_character fd (hexchar_of_int ((!checksum mod 256) mod 16)) - (* - * BUG NEED TO LISTEN FOR REPLY +/- AND POSSIBLY RE-TRANSMIT - *) - - -(** A few debugger commands such as step 's' and continue 'c' do - * not immediately return a response to the debugger. In these - * cases we raise No_reply instead. - * This is also used by some contexts (such as Linux processes) - * which utilize an asynchronous request / response protocol when - * communicating with their respective backends. - *) -exception No_reply diff -r 914c44d10c8d -r 2bfd19fc1b79 tools/debugger/pdb/Xen_domain.ml --- a/tools/debugger/pdb/Xen_domain.ml Sun Oct 01 11:39:41 2006 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -(** Xen_domain.ml - * - * domain assist for debugging processes - * - * @author copyright (c) 2005 alex ho - * @see <www.cl.cam.ac.uk/netos/pdb> pervasive debugger - * @version 1 - *) - -type context_t = -{ - mutable domain : int; - mutable evtchn : int; - mutable pdb_front_ring : int32 -} - -let default_context = { domain = 0; evtchn = 0; pdb_front_ring = 0l } - -let new_context dom evtchn ring = - {domain = dom; evtchn = evtchn; pdb_front_ring = ring} - -let set_domain ctx value = - ctx.domain <- value - -let set_evtchn ctx value = - ctx.evtchn <- value - -let set_ring ctx value = - ctx.pdb_front_ring <- value - -let get_domain ctx = - ctx.domain - -let get_evtchn ctx = - ctx.evtchn - -let get_ring ctx = - ctx.pdb_front_ring - -let string_of_context ctx = - Printf.sprintf "{xen domain assist} domain: %d" ctx.domain - -external process_response : int32 -> int * int * string = "process_handle_response" diff -r 914c44d10c8d -r 2bfd19fc1b79 tools/debugger/pdb/Xen_domain.mli --- a/tools/debugger/pdb/Xen_domain.mli Sun Oct 01 11:39:41 2006 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ -(** Xen_domain.ml - * - * domain assist for debugging processes - * - * @author copyright (c) 2005 alex ho - * @see <www.cl.cam.ac.uk/netos/pdb> pervasive debugger - * @version 1 - *) - -type context_t - -val default_context : context_t -val new_context : int -> int -> int32 -> context_t - -val set_domain : context_t -> int -> unit -val get_domain : context_t -> int -val set_evtchn : context_t -> int -> unit -val get_evtchn : context_t -> int -val set_ring : context_t -> int32 -> unit -val get_ring : context_t -> int32 - -val string_of_context : context_t -> string - -val process_response : int32 -> int * int * string - diff -r 914c44d10c8d -r 2bfd19fc1b79 tools/debugger/pdb/debugger.ml --- a/tools/debugger/pdb/debugger.ml Sun Oct 01 11:39:41 2006 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,372 +0,0 @@ -(** debugger.ml - * - * main debug functionality - * - * @author copyright (c) 2005 alex ho - * @see <www.cl.cam.ac.uk/netos/pdb> pervasive debugger - * @version 1 - *) - -open Intel -open PDB -open Util -open Str - -let initialize_debugger () = - () - -let exit_debugger () = - () - - -(** - Detach Command - Note: response is ignored by gdb. We leave the context in the - hash. It will be cleaned up with the socket is closed. - *) -let gdb_detach ctx = - PDB.detach_debugger ctx - -(** - Kill Command - Note: response is ignored by gdb. We leave the context in the - hash. It will be cleaned up with the socket is closed. - *) -let gdb_kill () = - "" - - - -(** - Continue Command. - resume the target - *) -let gdb_continue ctx = - PDB.continue ctx; - raise No_reply - -(** - Step Command. - single step the target - *) -let gdb_step ctx = - PDB.step ctx; - raise No_reply - -(** - Read Register Command. - return register as a 4-byte value. - *) -let gdb_read_register ctx command = - let read_reg register = - (Printf.sprintf "%08lx" (Util.flip_int32 (PDB.read_register ctx register))) - in - Scanf.sscanf command "p%x" read_reg - - -(** - Read Registers Command. - returns 16 4-byte registers in a particular format defined by gdb. - *) -let gdb_read_registers ctx = - let regs = PDB.read_registers ctx in - let str = - (Printf.sprintf "%08lx" (Util.flip_int32 regs.eax)) ^ - (Printf.sprintf "%08lx" (Util.flip_int32 regs.ecx)) ^ - (Printf.sprintf "%08lx" (Util.flip_int32 regs.edx)) ^ - (Printf.sprintf "%08lx" (Util.flip_int32 regs.ebx)) ^ - (Printf.sprintf "%08lx" (Util.flip_int32 regs.esp)) ^ - (Printf.sprintf "%08lx" (Util.flip_int32 regs.ebp)) ^ - (Printf.sprintf "%08lx" (Util.flip_int32 regs.esi)) ^ - (Printf.sprintf "%08lx" (Util.flip_int32 regs.edi)) ^ - (Printf.sprintf "%08lx" (Util.flip_int32 regs.eip)) ^ - (Printf.sprintf "%08lx" (Util.flip_int32 regs.efl)) ^ - (Printf.sprintf "%08lx" (Util.flip_int32 regs.cs)) ^ - (Printf.sprintf "%08lx" (Util.flip_int32 regs.ss)) ^ - (Printf.sprintf "%08lx" (Util.flip_int32 regs.ds)) ^ - (Printf.sprintf "%08lx" (Util.flip_int32 regs.es)) ^ - (Printf.sprintf "%08lx" (Util.flip_int32 regs.fs)) ^ - (Printf.sprintf "%08lx" (Util.flip_int32 regs.gs)) in - str - -(** - Set Thread Command - *) -let gdb_set_thread command = - "OK" - - -(** - Read Memory Packets - *) -let gdb_read_memory ctx command = - let int_list_to_string i str = - (Printf.sprintf "%02x" i) ^ str - in - let read_mem addr len = - try - let mem = PDB.read_memory ctx addr len in - List.fold_right int_list_to_string mem "" - with - Failure s -> "E02" - in - Scanf.sscanf command "m%lx,%x" read_mem - - - -(** - Write Memory Packets - *) -let gdb_write_memory ctx command = - let write_mem addr len = - print_endline (Printf.sprintf " gdb_write_memory %lx %x\n" addr len); - print_endline (Printf.sprintf " [[ unimplemented ]]\n") - in - Scanf.sscanf command "M%lx,%d" write_mem; - "OK" - - - -(** - Write Register Packets - *) -let gdb_write_register ctx command = - let write_reg reg goofy_val = - let new_val = Util.flip_int32 goofy_val in - match reg with - | 0 -> PDB.write_register ctx EAX new_val - | 1 -> PDB.write_register ctx ECX new_val - | 2 -> PDB.write_register ctx EDX new_val - | 3 -> PDB.write_register ctx EBX new_val - | 4 -> PDB.write_register ctx ESP new_val - | 5 -> PDB.write_register ctx EBP new_val - | 6 -> PDB.write_register ctx ESI new_val - | 7 -> PDB.write_register ctx EDI new_val - | 8 -> PDB.write_register ctx EIP new_val - | 9 -> PDB.write_register ctx EFL new_val - | 10 -> PDB.write_register ctx CS new_val - | 11 -> PDB.write_register ctx SS new_val - | 12 -> PDB.write_register ctx DS new_val - | 13 -> PDB.write_register ctx ES new_val - | 14 -> PDB.write_register ctx FS new_val - | 15 -> PDB.write_register ctx GS new_val - | _ -> print_endline (Printf.sprintf "write unknown register [%d]" reg) - in - Scanf.sscanf command "P%x=%lx" write_reg; - "OK" - - -(** - General Query Packets - *) -let gdb_query command = - match command with - | "qC" -> "" - | "qOffsets" -> "" - | "qSymbol::" -> "" - | _ -> - print_endline (Printf.sprintf "unknown gdb query packet [%s]" command); - "E01" - - -(** - Write Memory Binary Packets - *) -let gdb_write_memory_binary ctx command = - let write_mem addr len = - let pos = Str.search_forward (Str.regexp ":") command 0 in - let txt = Str.string_after command (pos + 1) in - PDB.write_memory ctx addr (int_list_of_string txt len) - in - Scanf.sscanf command "X%lx,%d" write_mem; - "OK" - - - -(** - Last Signal Command - *) -let gdb_last_signal = - "S00" - - - - -(** - Process PDB extensions to the GDB serial protocol. - Changes the mutable context state. - *) -let pdb_extensions command sock = - let process_extension key value = - (* since this command can change the context, - we need to grab it again each time *) - let ctx = PDB.find_context sock in - match key with - | "status" -> - PDB.debug_contexts (); - (* print_endline ("debugger status"); - debugger_status () - *) - | "context" -> - PDB.add_context sock (List.hd value) - (int_list_of_string_list (List.tl value)) - | _ -> failwith (Printf.sprintf "unknown pdb extension command [%s:%s]" - key (List.hd value)) - in - try - Util.little_parser process_extension - (String.sub command 1 ((String.length command) - 1)); - "OK" - with - | Unknown_context s -> - print_endline (Printf.sprintf "unknown context [%s]" s); - "E01" - | Unknown_domain -> "E01" - | Failure s -> "E01" - - -(** - Insert Breakpoint or Watchpoint Packet - *) - -let bwc_watch_write = 102 (* from pdb_module.h *) -let bwc_watch_read = 103 -let bwc_watch_access = 104 - -let gdb_insert_bwcpoint ctx command = - let insert cmd addr length = - try - match cmd with - | 0 -> PDB.insert_memory_breakpoint ctx addr length; "OK" - | 2 -> PDB.insert_watchpoint ctx bwc_watch_write addr length; "OK" - | 3 -> PDB.insert_watchpoint ctx bwc_watch_read addr length; "OK" - | 4 -> PDB.insert_watchpoint ctx bwc_watch_access addr length; "OK" - | _ -> "" - with - Failure s -> "E03" - in - Scanf.sscanf command "Z%d,%lx,%x" insert - -(** - Remove Breakpoint or Watchpoint Packet - *) -let gdb_remove_bwcpoint ctx command = - let insert cmd addr length = - try - match cmd with - | 0 -> PDB.remove_memory_breakpoint ctx addr length; "OK" - | 2 -> PDB.remove_watchpoint ctx bwc_watch_write addr length; "OK" - | 3 -> PDB.remove_watchpoint ctx bwc_watch_read addr length; "OK" - | 4 -> PDB.remove_watchpoint ctx bwc_watch_access addr length; "OK" - | _ -> "" - with - Failure s -> "E04" - in - Scanf.sscanf command "z%d,%lx,%d" insert - -(** - Do Work! - - @param command char list - *) - -let process_command command sock = - let ctx = PDB.find_context sock in - try - match command.[0] with - | 'c' -> gdb_continue ctx - | 'D' -> gdb_detach ctx - | 'g' -> gdb_read_registers ctx - | 'H' -> gdb_set_thread command - | 'k' -> gdb_kill () - | 'm' -> gdb_read_memory ctx command - | 'M' -> gdb_write_memory ctx command - | 'p' -> gdb_read_register ctx command - | 'P' -> gdb_write_register ctx command - | 'q' -> gdb_query command - | 's' -> gdb_step ctx - | 'x' -> pdb_extensions command sock - | 'X' -> gdb_write_memory_binary ctx command - | '?' -> gdb_last_signal - | 'z' -> gdb_remove_bwcpoint ctx command - | 'Z' -> gdb_insert_bwcpoint ctx command - | _ -> - print_endline (Printf.sprintf "unknown gdb command [%s]" command); - "" - with - Unimplemented s -> - print_endline (Printf.sprintf "loser. unimplemented command [%s][%s]" - command s); - "E03" - -(** - process_xen_domain - - This is called whenever a domain debug assist responds to a - pdb packet. -*) - -let process_xen_domain fd = - let channel = Evtchn.read fd in - let ctx = find_context fd in - - let (dom, pid, str) = - begin - match ctx with - | Xen_domain d -> Xen_domain.process_response (Xen_domain.get_ring d) - | _ -> failwith ("process_xen_domain called without Xen_domain context") - end - in - let sock = PDB.find_process dom pid in - print_endline (Printf.sprintf "(linux) dom:%d pid:%d %s %s" - dom pid str (Util.get_connection_info sock)); - Util.send_reply sock str; - Evtchn.unmask fd channel (* allow next virq *) - - -(** - process_xen_virq - - This is called each time a virq_pdb is sent from xen to dom 0. - It is sent by Xen when a domain hits a breakpoint. - - Think of this as the continuation function for a "c" or "s" command - issued to a domain. -*) - -external query_domain_stop : unit -> (int * int) list = "query_domain_stop" -(* returns a list of paused domains : () -> (domain, vcpu) list *) - -let process_xen_virq fd = - let channel = Evtchn.read fd in - let find_pair (dom, vcpu) = - print_endline (Printf.sprintf "checking %d.%d" dom vcpu); - try - let sock = PDB.find_domain dom vcpu in - true - with - Unknown_domain -> false - in - let dom_list = query_domain_stop () in - let (dom, vcpu) = List.find find_pair dom_list in - let vec = 3 in - let sock = PDB.find_domain dom vcpu in - print_endline (Printf.sprintf "handle bkpt dom:%d vcpu:%d vec:%d %s" - dom vcpu vec (Util.get_connection_info sock)); - Util.send_reply sock "S05"; - Evtchn.unmask fd channel (* allow next virq *) - - -(** - process_xen_xcs - - This is called each time the software assist residing in a backend - domain starts up. The control message includes the address of a - shared ring page and our end of an event channel (which indicates - when data is available on the ring). -*) - -let process_xen_xcs xcs_fd = - let (local_evtchn_fd, evtchn, dom, ring) = Xcs.read xcs_fd in - add_xen_domain_context local_evtchn_fd dom evtchn ring; - local_evtchn_fd diff -r 914c44d10c8d -r 2bfd19fc1b79 tools/debugger/pdb/evtchn.ml --- a/tools/debugger/pdb/evtchn.ml Sun Oct 01 11:39:41 2006 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,40 +0,0 @@ -(** evtchn.ml - * - * event channel interface - * - * @author copyright (c) 2005 alex ho - * @see <www.cl.cam.ac.uk/netos/pdb> pervasive debugger - * @version 1 - *) - -let dev_name = "/dev/xen/evtchn" (* EVTCHN_DEV_NAME *) -let dev_major = 10 (* EVTCHN_DEV_MAJOR *) -let dev_minor = 201 (* EVTCHN_DEV_MINOR *) - -let virq_pdb = 6 (* as defined VIRQ_PDB *) - -external bind_virq : int -> int = "evtchn_bind_virq" -external bind_interdomain : int -> int * int = "evtchn_bind_interdomain" -external bind : Unix.file_descr -> int -> unit = "evtchn_bind" -external unbind : Unix.file_descr -> int -> unit = "evtchn_unbind" -external ec_open : string -> int -> int -> Unix.file_descr = "evtchn_open" -external read : Unix.file_descr -> int = "evtchn_read" -external ec_close : Unix.file_descr -> unit = "evtchn_close" -external unmask : Unix.file_descr -> int -> unit = "evtchn_unmask" - -let _setup () = - let fd = ec_open dev_name dev_major dev_minor in - fd - -let _bind fd port = - bind fd port - -let setup () = - let port = bind_virq virq_pdb in - let fd = _setup() in - _bind fd port; - fd - -let teardown fd = - unbind fd virq_pdb; - ec_close fd diff -r 914c44d10c8d -r 2bfd19fc1b79 tools/debugger/pdb/evtchn.mli --- a/tools/debugger/pdb/evtchn.mli Sun Oct 01 11:39:41 2006 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,19 +0,0 @@ -(** evtchn.mli - * - * event channel interface - * - * @author copyright (c) 2005 alex ho - * @see <www.cl.cam.ac.uk/netos/pdb> pervasive debugger - * @version 1 - *) - -val _setup : unit -> Unix.file_descr -val _bind : Unix.file_descr -> int -> unit - -val bind_interdomain : int -> int * int - - -val setup : unit -> Unix.file_descr -val read : Unix.file_descr -> int -val teardown : Unix.file_descr -> unit -val unmask : Unix.file_descr -> int -> unit diff -r 914c44d10c8d -r 2bfd19fc1b79 tools/debugger/pdb/linux-2.6-module/Makefile --- a/tools/debugger/pdb/linux-2.6-module/Makefile Sun Oct 01 11:39:41 2006 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,21 +0,0 @@ -XEN_ROOT = ../../../.. -LINUX_DIR = linux-2.6.12-xenU -KDIR = $(XEN_ROOT)/$(LINUX_DIR) - -obj-m += pdb.o -pdb-objs += module.o -pdb-objs += debug.o - -CFLAGS += -g -CFLAGS += -Wall -CFLAGS += -Werror - -.PHONY: module -module : -# make KBUILD_VERBOSE=1 ARCH=xen -C $(KDIR) M=$(PWD) modules - make ARCH=xen -C $(KDIR) M=$(PWD) modules - -.PHONY: clean -clean : - make -C $(KDIR) M=$(PWD) clean - diff -r 914c44d10c8d -r 2bfd19fc1b79 tools/debugger/pdb/linux-2.6-module/debug.c --- a/tools/debugger/pdb/linux-2.6-module/debug.c Sun Oct 01 11:39:41 2006 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,851 +0,0 @@ -/* - * debug.c - * pdb debug functionality for processes. - */ - -#include <linux/module.h> -#include <linux/mm.h> -#include <linux/sched.h> -#include <asm-i386/kdebug.h> -#include <asm-i386/mach-xen/asm/processor.h> -#include <asm-i386/mach-xen/asm/ptrace.h> -#include <asm-i386/mach-xen/asm/tlbflush.h> -#include <xen/interface/xen.h> -#include "pdb_module.h" -#include "pdb_debug.h" - - -static int pdb_debug_fn (struct pt_regs *regs, long error_code, - unsigned int condition); -static int pdb_int3_fn (struct pt_regs *regs, long error_code); -static int pdb_page_fault_fn (struct pt_regs *regs, long error_code, - unsigned int condition); - -/***********************************************************************/ - -typedef struct bwcpoint /* break/watch/catch point */ -{ - struct list_head list; - unsigned long address; - int length; - - uint8_t type; /* BWC_??? */ - uint8_t mode; /* for BWC_PAGE, the current protection mode */ - uint32_t process; - uint8_t error; /* error occured when enabling: don't disable. */ - - /* original values */ - uint8_t orig_bkpt; /* single byte breakpoint */ - pte_t orig_pte; - - struct list_head watchpt_read_list; /* read watchpoints on this page */ - struct list_head watchpt_write_list; /* write */ - struct list_head watchpt_access_list; /* access */ - struct list_head watchpt_disabled_list; /* disabled */ - - struct bwcpoint *parent; /* watchpoint: bwc_watch (the page) */ - struct bwcpoint *watchpoint; /* bwc_watch_step: original watchpoint */ -} bwcpoint_t, *bwcpoint_p; - -static struct list_head bwcpoint_list = LIST_HEAD_INIT(bwcpoint_list); - -#define _pdb_bwcpoint_alloc(_var) \ -{ \ - if ( (_var = kmalloc(sizeof(bwcpoint_t), GFP_KERNEL)) == NULL ) \ - printk("error: unable to allocate memory %d\n", __LINE__); \ - else { \ - memset(_var, 0, sizeof(bwcpoint_t)); \ - INIT_LIST_HEAD(&_var->watchpt_read_list); \ - INIT_LIST_HEAD(&_var->watchpt_write_list); \ - INIT_LIST_HEAD(&_var->watchpt_access_list); \ - INIT_LIST_HEAD(&_var->watchpt_disabled_list); \ - } \ -} - -/***********************************************************************/ - -static void _pdb_bwc_print_list (struct list_head *, char *, int); - -static void -_pdb_bwc_print (bwcpoint_p bwc, char *label, int level) -{ - printk("%s%03d 0x%08lx:0x%02x %c\n", label, bwc->type, - bwc->address, bwc->length, bwc->error ? 'e' : '-'); - - if ( !list_empty(&bwc->watchpt_read_list) ) - _pdb_bwc_print_list(&bwc->watchpt_read_list, "r", level); - if ( !list_empty(&bwc->watchpt_write_list) ) - _pdb_bwc_print_list(&bwc->watchpt_write_list, "w", level); - if ( !list_empty(&bwc->watchpt_access_list) ) - _pdb_bwc_print_list(&bwc->watchpt_access_list, "a", level); - if ( !list_empty(&bwc->watchpt_disabled_list) ) - _pdb_bwc_print_list(&bwc->watchpt_disabled_list, "d", level); -} - -static void -_pdb_bwc_print_list (struct list_head *bwc_list, char *label, int level) -{ - struct list_head *ptr; - int counter = 0; - - list_for_each(ptr, bwc_list) - { - bwcpoint_p bwc = list_entry(ptr, bwcpoint_t, list); - printk(" %s[%02d]%s ", level > 0 ? " " : "", counter++, - level > 0 ? "" : " "); - _pdb_bwc_print(bwc, label, level+1); - } - - if (counter == 0) - { - printk(" empty list\n"); - } -} - -void -pdb_bwc_print_list (void) -{ - _pdb_bwc_print_list(&bwcpoint_list, " ", 0); -} - -bwcpoint_p -pdb_search_watchpoint (uint32_t process, unsigned long address) -{ - bwcpoint_p bwc_watch = (bwcpoint_p) 0; - bwcpoint_p bwc_entry = (bwcpoint_p) 0; - struct list_head *ptr; - - list_for_each(ptr, &bwcpoint_list) /* find bwc page entry */ - { - bwc_watch = list_entry(ptr, bwcpoint_t, list); - if (bwc_watch->address == (address & PAGE_MASK)) break; - } - - if ( !bwc_watch ) - { - return (bwcpoint_p) 0; - } - -#define __pdb_search_watchpoint_list(__list) \ - list_for_each(ptr, (__list)) \ - { \ - bwc_entry = list_entry(ptr, bwcpoint_t, list); \ - if ( bwc_entry->process == process && \ - bwc_entry->address <= address && \ - bwc_entry->address + bwc_entry->length > address ) \ - return bwc_entry; \ - } - - __pdb_search_watchpoint_list(&bwc_watch->watchpt_read_list); - __pdb_search_watchpoint_list(&bwc_watch->watchpt_write_list); - __pdb_search_watchpoint_list(&bwc_watch->watchpt_access_list); - -#undef __pdb_search_watchpoint_list - - return (bwcpoint_p) 0; -} - -/*************************************************************/ - -int -pdb_suspend (struct task_struct *target) -{ - uint32_t rc = 0; - - force_sig(SIGSTOP, target); /* force_sig_specific ??? */ - - return rc; -} - -int -pdb_resume (struct task_struct *target) -{ - int rc = 0; - - wake_up_process(target); - - return rc; -} - -/* - * from linux-2.6.11/arch/i386/kernel/ptrace.c::getreg() - */ -static unsigned long -_pdb_get_register (struct task_struct *target, int reg) -{ - unsigned long result = ~0UL; - unsigned long offset; - unsigned char *stack = 0L; - - switch (reg) - { - case LINUX_FS: - result = target->thread.fs; - break; - case LINUX_GS: - result = target->thread.gs; - break; - case LINUX_DS: - case LINUX_ES: - case LINUX_SS: - case LINUX_CS: - result = 0xffff; - /* fall through */ - default: - if (reg > LINUX_GS) - reg -= 2; - - offset = reg * sizeof(long); - offset -= sizeof(struct pt_regs); - stack = (unsigned char *)target->thread.esp0; - stack += offset; - result &= *((int *)stack); - } - - return result; -} - -/* - * from linux-2.6.11/arch/i386/kernel/ptrace.c::putreg() - */ -static void -_pdb_set_register (struct task_struct *target, int reg, unsigned long val) -{ - unsigned long offset; - unsigned char *stack; - unsigned long value = val; - - switch (reg) - { - case LINUX_FS: - target->thread.fs = value; - return; - case LINUX_GS: - target->thread.gs = value; - return; - case LINUX_DS: - case LINUX_ES: - value &= 0xffff; - break; - case LINUX_SS: - case LINUX_CS: - value &= 0xffff; - break; - case LINUX_EFL: - break; - } - - if (reg > LINUX_GS) - reg -= 2; - offset = reg * sizeof(long); - offset -= sizeof(struct pt_regs); - stack = (unsigned char *)target->thread.esp0; - stack += offset; - *(unsigned long *) stack = value; - - return; -} - -int -pdb_read_register (struct task_struct *target, pdb_op_rd_reg_p op) -{ - int rc = 0; - - switch (op->reg) - { - case 0: op->value = _pdb_get_register(target, LINUX_EAX); break; - case 1: op->value = _pdb_get_register(target, LINUX_ECX); break; - case 2: op->value = _pdb_get_register(target, LINUX_EDX); break; - case 3: op->value = _pdb_get_register(target, LINUX_EBX); break; - case 4: op->value = _pdb_get_register(target, LINUX_ESP); break; - case 5: op->value = _pdb_get_register(target, LINUX_EBP); break; - case 6: op->value = _pdb_get_register(target, LINUX_ESI); break; - case 7: op->value = _pdb_get_register(target, LINUX_EDI); break; - case 8: op->value = _pdb_get_register(target, LINUX_EIP); break; - case 9: op->value = _pdb_get_register(target, LINUX_EFL); break; - - case 10: op->value = _pdb_get_register(target, LINUX_CS); break; - case 11: op->value = _pdb_get_register(target, LINUX_SS); break; - case 12: op->value = _pdb_get_register(target, LINUX_DS); break; - case 13: op->value = _pdb_get_register(target, LINUX_ES); break; - case 14: op->value = _pdb_get_register(target, LINUX_FS); break; - case 15: op->value = _pdb_get_register(target, LINUX_GS); break; - } - - return rc; -} - -int -pdb_read_registers (struct task_struct *target, pdb_op_rd_regs_p op) -{ - int rc = 0; - - op->reg[ 0] = _pdb_get_register(target, LINUX_EAX); - op->reg[ 1] = _pdb_get_register(target, LINUX_ECX); - op->reg[ 2] = _pdb_get_register(target, LINUX_EDX); - op->reg[ 3] = _pdb_get_register(target, LINUX_EBX); - op->reg[ 4] = _pdb_get_register(target, LINUX_ESP); - op->reg[ 5] = _pdb_get_register(target, LINUX_EBP); - op->reg[ 6] = _pdb_get_register(target, LINUX_ESI); - op->reg[ 7] = _pdb_get_register(target, LINUX_EDI); - op->reg[ 8] = _pdb_get_register(target, LINUX_EIP); - op->reg[ 9] = _pdb_get_register(target, LINUX_EFL); - - op->reg[10] = _pdb_get_register(target, LINUX_CS); - op->reg[11] = _pdb_get_register(target, LINUX_SS); - op->reg[12] = _pdb_get_register(target, LINUX_DS); - op->reg[13] = _pdb_get_register(target, LINUX_ES); - op->reg[14] = _pdb_get_register(target, LINUX_FS); - op->reg[15] = _pdb_get_register(target, LINUX_GS); - - return rc; -} - -int -pdb_write_register (struct task_struct *target, pdb_op_wr_reg_p op) -{ - int rc = 0; - - _pdb_set_register(target, op->reg, op->value); - - return rc; -} - -int -pdb_access_memory (struct task_struct *target, unsigned long address, - void *buffer, int length, int write) -{ - int rc = 0; - - access_process_vm(target, address, buffer, length, write); - - return rc; -} - -int -pdb_continue (struct task_struct *target) -{ - int rc = 0; - unsigned long eflags; - - eflags = _pdb_get_register(target, LINUX_EFL); - eflags &= ~X86_EFLAGS_TF; - _pdb_set_register(target, LINUX_EFL, eflags); - - wake_up_process(target); - - return rc; -} - -int -pdb_step (struct task_struct *target) -{ - int rc = 0; - unsigned long eflags; - bwcpoint_p bkpt; - - eflags = _pdb_get_register(target, LINUX_EFL); - eflags |= X86_EFLAGS_TF; - _pdb_set_register(target, LINUX_EFL, eflags); - - _pdb_bwcpoint_alloc(bkpt); - if ( bkpt == NULL ) return -1; - - bkpt->process = target->pid; - bkpt->address = 0; - bkpt->type = BWC_DEBUG; - - list_add_tail(&bkpt->list, &bwcpoint_list); - - wake_up_process(target); - - return rc; -} - -int -pdb_insert_memory_breakpoint (struct task_struct *target, - unsigned long address, uint32_t length) -{ - int rc = 0; - bwcpoint_p bkpt; - uint8_t breakpoint_opcode = 0xcc; - - printk("insert breakpoint %d:%lx len: %d\n", target->pid, address, length); - - if ( length != 1 ) - { - printk("error: breakpoint length should be 1\n"); - return -1; - } - - _pdb_bwcpoint_alloc(bkpt); - if ( bkpt == NULL ) return -1; - - bkpt->process = target->pid; - bkpt->address = address; - bkpt->type = BWC_INT3; - - pdb_access_memory(target, address, &bkpt->orig_bkpt, 1, PDB_MEM_READ); - pdb_access_memory(target, address, &breakpoint_opcode, 1, PDB_MEM_WRITE); - - list_add_tail(&bkpt->list, &bwcpoint_list); - - printk("breakpoint_set %d:%lx OLD: 0x%x\n", - target->pid, address, bkpt->orig_bkpt); - pdb_bwc_print_list(); - - return rc; -} - -int -pdb_remove_memory_breakpoint (struct task_struct *target, - unsigned long address, uint32_t length) -{ - int rc = 0; - bwcpoint_p bkpt = NULL; - - printk ("remove breakpoint %d:%lx\n", target->pid, address); - - struct list_head *entry; - list_for_each(entry, &bwcpoint_list) - { - bkpt = list_entry(entry, bwcpoint_t, list); - if ( target->pid == bkpt->process && - address == bkpt->address && - bkpt->type == BWC_INT3 ) - break; - } - - if (entry == &bwcpoint_list) - { - printk ("error: no breakpoint found\n"); - return -1; - } - - pdb_access_memory(target, address, &bkpt->orig_bkpt, 1, PDB_MEM_WRITE); - - list_del(&bkpt->list); - kfree(bkpt); - - pdb_bwc_print_list(); - - return rc; -} - -#define PDB_PTE_UPDATE 1 -#define PDB_PTE_RESTORE 2 - -int -pdb_change_pte (struct task_struct *target, bwcpoint_p bwc, int mode) -{ - int rc = 0; - pgd_t *pgd; - pud_t *pud; - pmd_t *pmd; - pte_t *ptep; - - pgd = pgd_offset(target->mm, bwc->address); - if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd))) return -1; - - pud = pud_offset(pgd, bwc->address); - if (pud_none(*pud) || unlikely(pud_bad(*pud))) return -2; - - pmd = pmd_offset(pud, bwc->address); - if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd))) return -3; - - ptep = pte_offset_map(pmd, bwc->address); - if (!ptep) return -4; - - switch ( mode ) - { - case PDB_PTE_UPDATE: /* added or removed a watchpoint. update pte. */ - { - pte_t new_pte; - - if ( pte_val(bwc->parent->orig_pte) == 0 ) /* new watchpoint page */ - { - bwc->parent->orig_pte = *ptep; - } - - new_pte = bwc->parent->orig_pte; - - if ( !list_empty(&bwc->parent->watchpt_read_list) || - !list_empty(&bwc->parent->watchpt_access_list) ) - { - new_pte = pte_rdprotect(new_pte); - } - - if ( !list_empty(&bwc->parent->watchpt_write_list) || - !list_empty(&bwc->parent->watchpt_access_list) ) - { - new_pte = pte_wrprotect(new_pte); - } - - if ( pte_val(new_pte) != pte_val(*ptep) ) - { - *ptep = new_pte; - flush_tlb_mm(target->mm); - } - break; - } - case PDB_PTE_RESTORE : /* suspend watchpoint by restoring original pte */ - { - *ptep = bwc->parent->orig_pte; - flush_tlb_mm(target->mm); - break; - } - default : - { - printk("(linux) unknown mode %d %d\n", mode, __LINE__); - break; - } - } - - pte_unmap(ptep); /* can i flush the tlb before pte_unmap? */ - - return rc; -} - -int -pdb_insert_watchpoint (struct task_struct *target, pdb_op_watchpt_p watchpt) -{ - int rc = 0; - - bwcpoint_p bwc_watch; - bwcpoint_p bwc_entry; - struct list_head *ptr; - unsigned long page = watchpt->address & PAGE_MASK; - struct list_head *watchpoint_list; - - printk("insert watchpoint: %d %x %x\n", - watchpt->type, watchpt->address, watchpt->length); - - list_for_each(ptr, &bwcpoint_list) /* find existing bwc page entry */ - { - bwc_watch = list_entry(ptr, bwcpoint_t, list); - - if (bwc_watch->address == page) goto got_bwc_watch; - } - - _pdb_bwcpoint_alloc(bwc_watch); /* create new bwc:watch */ - if ( bwc_watch == NULL ) return -1; - - bwc_watch->type = BWC_WATCH; - bwc_watch->process = target->pid; - bwc_watch->address = page; - - list_add_tail(&bwc_watch->list, &bwcpoint_list); - - got_bwc_watch: - - switch (watchpt->type) - { - case BWC_WATCH_READ: - watchpoint_list = &bwc_watch->watchpt_read_list; break; - case BWC_WATCH_WRITE: - watchpoint_list = &bwc_watch->watchpt_write_list; break; - case BWC_WATCH_ACCESS: - watchpoint_list = &bwc_watch->watchpt_access_list; break; - default: - printk("unknown type %d\n", watchpt->type); return -2; - } - - _pdb_bwcpoint_alloc(bwc_entry); /* create new bwc:entry */ - if ( bwc_entry == NULL ) return -1; - - bwc_entry->process = target->pid; - bwc_entry->address = watchpt->address; - bwc_entry->length = watchpt->length; - bwc_entry->type = watchpt->type; - bwc_entry->parent = bwc_watch; - - list_add_tail(&bwc_entry->list, watchpoint_list); - pdb_change_pte(target, bwc_entry, PDB_PTE_UPDATE); - - pdb_bwc_print_list(); - - return rc; -} - -int -pdb_remove_watchpoint (struct task_struct *target, pdb_op_watchpt_p watchpt) -{ - int rc = 0; - bwcpoint_p bwc_watch = (bwcpoint_p) NULL; - bwcpoint_p bwc_entry = (bwcpoint_p) NULL; - unsigned long page = watchpt->address & PAGE_MASK; - struct list_head *ptr; - struct list_head *watchpoint_list; - - printk("remove watchpoint: %d %x %x\n", - watchpt->type, watchpt->address, watchpt->length); - - list_for_each(ptr, &bwcpoint_list) /* find bwc page entry */ - { - bwc_watch = list_entry(ptr, bwcpoint_t, list); - if (bwc_watch->address == page) break; - } - - if ( !bwc_watch ) - { - printk("(linux) delete watchpoint: can't find bwc page 0x%08x\n", - watchpt->address); - return -1; - } - - switch (watchpt->type) - { - case BWC_WATCH_READ: - watchpoint_list = &bwc_watch->watchpt_read_list; break; - case BWC_WATCH_WRITE: - watchpoint_list = &bwc_watch->watchpt_write_list; break; - case BWC_WATCH_ACCESS: - watchpoint_list = &bwc_watch->watchpt_access_list; break; - default: - printk("unknown type %d\n", watchpt->type); return -2; - } - - list_for_each(ptr, watchpoint_list) /* find watchpoint */ - { - bwc_entry = list_entry(ptr, bwcpoint_t, list); - if ( bwc_entry->address == watchpt->address && - bwc_entry->length == watchpt->length ) break; - } - - if ( !bwc_entry ) /* or ptr == watchpoint_list */ - { - printk("(linux) delete watchpoint: can't find watchpoint 0x%08x\n", - watchpt->address); - return -1; - } - - list_del(&bwc_entry->list); - pdb_change_pte(target, bwc_entry, PDB_PTE_UPDATE); - kfree(bwc_entry); - - - if ( list_empty(&bwc_watch->watchpt_read_list) && - list_empty(&bwc_watch->watchpt_write_list) && - list_empty(&bwc_watch->watchpt_access_list) ) - { - list_del(&bwc_watch->list); - kfree(bwc_watch); - } - - pdb_bwc_print_list(); - - return rc; -} - - -/***************************************************************/ - -int -pdb_exceptions_notify (struct notifier_block *self, unsigned long val, - void *data) -{ - struct die_args *args = (struct die_args *)data; - - switch (val) - { - case DIE_DEBUG: - if ( pdb_debug_fn(args->regs, args->trapnr, args->err) ) - return NOTIFY_STOP; - break; - case DIE_TRAP: - if ( args->trapnr == 3 && pdb_int3_fn(args->regs, args->err) ) - return NOTIFY_STOP; - break; - case DIE_INT3: /* without kprobes, we should never see DIE_INT3 */ - if ( pdb_int3_fn(args->regs, args->err) ) - return NOTIFY_STOP; - break; - case DIE_PAGE_FAULT: - if ( pdb_page_fault_fn(args->regs, args->trapnr, args->err) ) - return NOTIFY_STOP; - break; - case DIE_GPF: - printk("---------------GPF\n"); - break; - default: - break; - } - - return NOTIFY_DONE; -} - - -static int -pdb_debug_fn (struct pt_regs *regs, long error_code, - unsigned int condition) -{ - pdb_response_t resp; - bwcpoint_p bkpt = NULL; - struct list_head *entry; - - printk("pdb_debug_fn\n"); - - list_for_each(entry, &bwcpoint_list) - { - bkpt = list_entry(entry, bwcpoint_t, list); - if ( current->pid == bkpt->process && - (bkpt->type == BWC_DEBUG || /* single step */ - bkpt->type == BWC_WATCH_STEP)) /* single step over watchpoint */ - break; - } - - if (entry == &bwcpoint_list) - { - printk("not my debug 0x%x 0x%lx\n", current->pid, regs->eip); - return 0; - } - - pdb_suspend(current); - - printk("(pdb) %s pid: %d, eip: 0x%08lx\n", - bkpt->type == BWC_DEBUG ? "debug" : "watch-step", - current->pid, regs->eip); - - regs->eflags &= ~X86_EFLAGS_TF; - set_tsk_thread_flag(current, TIF_SINGLESTEP); - - switch (bkpt->type) - { - case BWC_DEBUG: - resp.operation = PDB_OPCODE_STEP; - break; - case BWC_WATCH_STEP: - { - struct list_head *watchpoint_list; - bwcpoint_p watch_page = bkpt->watchpoint->parent; - - switch (bkpt->watchpoint->type) - { - case BWC_WATCH_READ: - watchpoint_list = &watch_page->watchpt_read_list; break; - case BWC_WATCH_WRITE: - watchpoint_list = &watch_page->watchpt_write_list; break; - case BWC_WATCH_ACCESS: - watchpoint_list = &watch_page->watchpt_access_list; break; - default: - printk("unknown type %d\n", bkpt->watchpoint->type); return 0; - } - - resp.operation = PDB_OPCODE_WATCHPOINT; - list_del_init(&bkpt->watchpoint->list); - list_add_tail(&bkpt->watchpoint->list, watchpoint_list); - pdb_change_pte(current, bkpt->watchpoint, PDB_PTE_UPDATE); - pdb_bwc_print_list(); - break; - } - default: - printk("unknown breakpoint type %d %d\n", __LINE__, bkpt->type); - return 0; - } - - resp.process = current->pid; - resp.status = PDB_RESPONSE_OKAY; - - pdb_send_response(&resp); - - list_del(&bkpt->list); - kfree(bkpt); - - return 1; -} - - -static int -pdb_int3_fn (struct pt_regs *regs, long error_code) -{ - pdb_response_t resp; - bwcpoint_p bkpt = NULL; - unsigned long address = regs->eip - 1; - - struct list_head *entry; - list_for_each(entry, &bwcpoint_list) - { - bkpt = list_entry(entry, bwcpoint_t, list); - if ( current->pid == bkpt->process && - address == bkpt->address && - bkpt->type == BWC_INT3 ) - break; - } - - if (entry == &bwcpoint_list) - { - printk("not my int3 bkpt 0x%x 0x%lx\n", current->pid, address); - return 0; - } - - printk("(pdb) int3 pid: %d, eip: 0x%08lx\n", current->pid, address); - - pdb_suspend(current); - - resp.operation = PDB_OPCODE_CONTINUE; - resp.process = current->pid; - resp.status = PDB_RESPONSE_OKAY; - - pdb_send_response(&resp); - - return 1; -} - -static int -pdb_page_fault_fn (struct pt_regs *regs, long error_code, - unsigned int condition) -{ - unsigned long cr2; - unsigned long cr3; - bwcpoint_p bwc; - bwcpoint_p watchpt; - bwcpoint_p bkpt; - - __asm__ __volatile__ ("movl %%cr3,%0" : "=r" (cr3) : ); - __asm__ __volatile__ ("movl %%cr2,%0" : "=r" (cr2) : ); - - bwc = pdb_search_watchpoint(current->pid, cr2); - if ( !bwc ) - { - return 0; /* not mine */ - } - - printk("page_fault cr2:%08lx err:%lx eip:%08lx\n", - cr2, error_code, regs->eip); - - /* disable the watchpoint */ - watchpt = bwc->watchpoint; - list_del_init(&bwc->list); - list_add_tail(&bwc->list, &bwc->parent->watchpt_disabled_list); - pdb_change_pte(current, bwc, PDB_PTE_RESTORE); - - /* single step the faulting instruction */ - regs->eflags |= X86_EFLAGS_TF; - - /* create a bwcpoint entry so we know what to do once we regain control */ - _pdb_bwcpoint_alloc(bkpt); - if ( bkpt == NULL ) return -1; - - bkpt->process = current->pid; - bkpt->address = 0; - bkpt->type = BWC_WATCH_STEP; - bkpt->watchpoint = bwc; - - /* add to head so we see it first the next time we break */ - list_add(&bkpt->list, &bwcpoint_list); - - pdb_bwc_print_list(); - return 1; -} - - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ - diff -r 914c44d10c8d -r 2bfd19fc1b79 tools/debugger/pdb/linux-2.6-module/module.c --- a/tools/debugger/pdb/linux-2.6-module/module.c Sun Oct 01 11:39:41 2006 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,337 +0,0 @@ - -/* - * module.c - * - * Handles initial registration with pdb when the pdb module starts up - * and cleanup when the module goes away (sortof :) - * Also receives each request from pdb in domain 0 and dispatches to the - * appropriate debugger function. - */ - -#include <linux/module.h> -#include <linux/interrupt.h> - -#include <asm-i386/kdebug.h> - -#include <xen/evtchn.h> -#include <xen/ctrl_if.h> -#include <xen/hypervisor.h> -#include <xen/interface/io/domain_controller.h> -#include <xen/interface/xen.h> - -#include <xen/interface/io/ring.h> - -#include "pdb_module.h" -#include "pdb_debug.h" - -#define PDB_RING_SIZE __RING_SIZE((pdb_sring_t *)0, PAGE_SIZE) - -static pdb_back_ring_t pdb_ring; -static unsigned int pdb_evtchn; -static unsigned int pdb_irq; -static unsigned int pdb_domain; - -/* work queue */ -static void pdb_work_handler(void *unused); -static DECLARE_WORK(pdb_deferred_work, pdb_work_handler, NULL); - -/* - * send response to a pdb request - */ -void -pdb_send_response (pdb_response_t *response) -{ - pdb_response_t *resp; - - resp = RING_GET_RESPONSE(&pdb_ring, pdb_ring.rsp_prod_pvt); - - memcpy(resp, response, sizeof(pdb_response_t)); - resp->domain = pdb_domain; - - wmb(); /* Ensure other side can see the response fields. */ - pdb_ring.rsp_prod_pvt++; - RING_PUSH_RESPONSES(&pdb_ring); - notify_via_evtchn(pdb_evtchn); - return; -} - -/* - * handle a debug command from the front end - */ -static void -pdb_process_request (pdb_request_t *request) -{ - pdb_response_t resp; - struct task_struct *target; - - read_lock(&tasklist_lock); - target = find_task_by_pid(request->process); - if (target) - get_task_struct(target); - read_unlock(&tasklist_lock); - - resp.operation = request->operation; - resp.process = request->process; - - if (!target) - { - printk ("(linux) target not found 0x%x\n", request->process); - resp.status = PDB_RESPONSE_ERROR; - goto response; - } - - switch (request->operation) - { - case PDB_OPCODE_PAUSE : - pdb_suspend(target); - resp.status = PDB_RESPONSE_OKAY; - break; - case PDB_OPCODE_ATTACH : - pdb_suspend(target); - pdb_domain = request->u.attach.domain; - printk("(linux) attach dom:0x%x pid:0x%x\n", - pdb_domain, request->process); - resp.status = PDB_RESPONSE_OKAY; - break; - case PDB_OPCODE_DETACH : - pdb_resume(target); - printk("(linux) detach 0x%x\n", request->process); - resp.status = PDB_RESPONSE_OKAY; - break; - case PDB_OPCODE_RD_REG : - resp.u.rd_reg.reg = request->u.rd_reg.reg; - pdb_read_register(target, &resp.u.rd_reg); - resp.status = PDB_RESPONSE_OKAY; - break; - case PDB_OPCODE_RD_REGS : - pdb_read_registers(target, &resp.u.rd_regs); - resp.status = PDB_RESPONSE_OKAY; - break; - case PDB_OPCODE_WR_REG : - pdb_write_register(target, &request->u.wr_reg); - resp.status = PDB_RESPONSE_OKAY; - break; - case PDB_OPCODE_RD_MEM : - pdb_access_memory(target, request->u.rd_mem.address, - &resp.u.rd_mem.data, request->u.rd_mem.length, - PDB_MEM_READ); - resp.u.rd_mem.address = request->u.rd_mem.address; - resp.u.rd_mem.length = request->u.rd_mem.length; - resp.status = PDB_RESPONSE_OKAY; - break; - case PDB_OPCODE_WR_MEM : - pdb_access_memory(target, request->u.wr_mem.address, - &request->u.wr_mem.data, request->u.wr_mem.length, - PDB_MEM_WRITE); - resp.status = PDB_RESPONSE_OKAY; - break; - case PDB_OPCODE_CONTINUE : - pdb_continue(target); - goto no_response; - break; - case PDB_OPCODE_STEP : - pdb_step(target); - resp.status = PDB_RESPONSE_OKAY; - goto no_response; - break; - case PDB_OPCODE_SET_BKPT : - pdb_insert_memory_breakpoint(target, request->u.bkpt.address, - request->u.bkpt.length); - resp.status = PDB_RESPONSE_OKAY; - break; - case PDB_OPCODE_CLR_BKPT : - pdb_remove_memory_breakpoint(target, request->u.bkpt.address, - request->u.bkpt.length); - resp.status = PDB_RESPONSE_OKAY; - break; - case PDB_OPCODE_SET_WATCHPT : - pdb_insert_watchpoint(target, &request->u.watchpt); - resp.status = PDB_RESPONSE_OKAY; - break; - case PDB_OPCODE_CLR_WATCHPT : - pdb_remove_watchpoint(target, &request->u.watchpt); - resp.status = PDB_RESPONSE_OKAY; - break; - default: - printk("(pdb) unknown request operation %d\n", request->operation); - resp.status = PDB_RESPONSE_ERROR; - } - - response: - pdb_send_response (&resp); - - no_response: - return; -} - -/* - * work queue - */ -static void -pdb_work_handler (void *unused) -{ - pdb_request_t *req; - RING_IDX i, rp; - - rp = pdb_ring.sring->req_prod; - rmb(); - - for ( i = pdb_ring.req_cons; - (i != rp) && !RING_REQUEST_CONS_OVERFLOW(&pdb_ring, i); - i++ ) - { - req = RING_GET_REQUEST(&pdb_ring, i); - pdb_process_request(req); - - } - pdb_ring.req_cons = i; -} - -/* - * receive a pdb request - */ -static irqreturn_t -pdb_interrupt (int irq, void *dev_id, struct pt_regs *ptregs) -{ - schedule_work(&pdb_deferred_work); - - return IRQ_HANDLED; -} - -static void -pdb_send_connection_status(int status, unsigned long ring) -{ - ctrl_msg_t cmsg = - { - .type = CMSG_DEBUG, - .subtype = CMSG_DEBUG_CONNECTION_STATUS, - .length = sizeof(pdb_connection_t), - }; - pdb_connection_t *conn = (pdb_connection_t *)cmsg.msg; - - conn->status = status; - conn->ring = ring; - conn->evtchn = 0; - - ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE); -} - - -/* - * this is called each time a message is received on the control channel - */ -static void -pdb_ctrlif_rx(ctrl_msg_t *msg, unsigned long id) -{ - switch (msg->subtype) - { - case CMSG_DEBUG_CONNECTION_STATUS: - /* initialize event channel created by the pdb server */ - - pdb_evtchn = ((pdb_connection_p) msg->msg)->evtchn; - pdb_irq = bind_evtchn_to_irq(pdb_evtchn); - - if ( request_irq(pdb_irq, pdb_interrupt, - SA_SAMPLE_RANDOM, "pdb", NULL) ) - { - printk("(pdb) request irq failed: %d %d\n", pdb_evtchn, pdb_irq); - } - break; - - default: - printk ("(pdb) unknown xcs control message: %d\n", msg->subtype); - break; - } - - return; -} - - -/********************************************************************/ - -static struct notifier_block pdb_exceptions_nb = -{ - .notifier_call = pdb_exceptions_notify, - .priority = 0x1 /* low priority */ -}; - - -static int __init -pdb_initialize (void) -{ - int err; - pdb_sring_t *sring; - - printk("----\npdb initialize %s %s\n", __DATE__, __TIME__); - - /* - if ( xen_start_info.flags & SIF_INITDOMAIN ) - return 1; - */ - - pdb_evtchn = 0; - pdb_irq = 0; - pdb_domain = 0; - - (void)ctrl_if_register_receiver(CMSG_DEBUG, pdb_ctrlif_rx, - CALLBACK_IN_BLOCKING_CONTEXT); - - /* rings */ - sring = (pdb_sring_t *)__get_free_page(GFP_KERNEL); - SHARED_RING_INIT(sring); - BACK_RING_INIT(&pdb_ring, sring, PAGE_SIZE); - - /* notify pdb in dom 0 */ - pdb_send_connection_status(PDB_CONNECTION_STATUS_UP, - virt_to_machine(pdb_ring.sring) >> PAGE_SHIFT); - - /* handler for int1 & int3 */ - err = register_die_notifier(&pdb_exceptions_nb); - - return err; -} - -static void __exit -pdb_terminate(void) -{ - int err = 0; - - printk("pdb cleanup\n"); - - (void)ctrl_if_unregister_receiver(CMSG_DEBUG, pdb_ctrlif_rx); - - if (pdb_irq) - { - free_irq(pdb_irq, NULL); - pdb_irq = 0; - } - - if (pdb_evtchn) - { - unbind_evtchn_from_irq(pdb_evtchn); - pdb_evtchn = 0; - } - - pdb_send_connection_status(PDB_CONNECTION_STATUS_DOWN, 0); - - /* handler for int1 & int3 */ - err = unregister_die_notifier(&pdb_exceptions_nb); - - return; -} - - -module_init(pdb_initialize); -module_exit(pdb_terminate); - - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ - diff -r 914c44d10c8d -r 2bfd19fc1b79 tools/debugger/pdb/linux-2.6-module/pdb_debug.h --- a/tools/debugger/pdb/linux-2.6-module/pdb_debug.h Sun Oct 01 11:39:41 2006 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,47 +0,0 @@ - -#ifndef __PDB_DEBUG_H_ -#define __PDB_DEBUG_H_ - -/* debugger.c */ -void pdb_initialize_bwcpoint (void); -int pdb_suspend (struct task_struct *target); -int pdb_resume (struct task_struct *target); -int pdb_read_register (struct task_struct *target, pdb_op_rd_reg_p op); -int pdb_read_registers (struct task_struct *target, pdb_op_rd_regs_p op); -int pdb_write_register (struct task_struct *target, pdb_op_wr_reg_p op); -int pdb_read_memory (struct task_struct *target, pdb_op_rd_mem_req_p req, - pdb_op_rd_mem_resp_p resp); -int pdb_write_memory (struct task_struct *target, pdb_op_wr_mem_p op); -int pdb_access_memory (struct task_struct *target, unsigned long address, - void *buffer, int length, int write); -int pdb_continue (struct task_struct *target); -int pdb_step (struct task_struct *target); - -int pdb_insert_memory_breakpoint (struct task_struct *target, - unsigned long address, uint32_t length); -int pdb_remove_memory_breakpoint (struct task_struct *target, - unsigned long address, uint32_t length); -int pdb_insert_watchpoint (struct task_struct *target, - pdb_op_watchpt_p watchpt); -int pdb_remove_watchpoint (struct task_struct *target, - pdb_op_watchpt_p watchpt); - -int pdb_exceptions_notify (struct notifier_block *self, unsigned long val, - void *data); - -/* module.c */ -void pdb_send_response (pdb_response_t *response); - -#endif - - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ - diff -r 914c44d10c8d -r 2bfd19fc1b79 tools/debugger/pdb/linux-2.6-module/pdb_module.h --- a/tools/debugger/pdb/linux-2.6-module/pdb_module.h Sun Oct 01 11:39:41 2006 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,142 +0,0 @@ - -#ifndef __PDB_MODULE_H_ -#define __PDB_MODULE_H_ - -#include "../pdb_caml_xen.h" - -#define PDB_OPCODE_PAUSE 1 - -#define PDB_OPCODE_ATTACH 2 -typedef struct pdb_op_attach -{ - uint32_t domain; -} pdb_op_attach_t, *pdb_op_attach_p; - -#define PDB_OPCODE_DETACH 3 - -#define PDB_OPCODE_RD_REG 4 -typedef struct pdb_op_rd_reg -{ - uint32_t reg; - uint32_t value; -} pdb_op_rd_reg_t, *pdb_op_rd_reg_p; - -#define PDB_OPCODE_RD_REGS 5 -typedef struct pdb_op_rd_regs -{ - uint32_t reg[GDB_REGISTER_FRAME_SIZE]; -} pdb_op_rd_regs_t, *pdb_op_rd_regs_p; - -#define PDB_OPCODE_WR_REG 6 -typedef struct pdb_op_wr_reg -{ - uint32_t reg; - uint32_t value; -} pdb_op_wr_reg_t, *pdb_op_wr_reg_p; - -#define PDB_OPCODE_RD_MEM 7 -typedef struct pdb_op_rd_mem_req -{ - uint32_t address; - uint32_t length; -} pdb_op_rd_mem_req_t, *pdb_op_rd_mem_req_p; - -typedef struct pdb_op_rd_mem_resp -{ - uint32_t address; - uint32_t length; - uint8_t data[1024]; -} pdb_op_rd_mem_resp_t, *pdb_op_rd_mem_resp_p; - -#define PDB_OPCODE_WR_MEM 8 -typedef struct pdb_op_wr_mem -{ - uint32_t address; - uint32_t length; - uint8_t data[1024]; /* arbitrary */ -} pdb_op_wr_mem_t, *pdb_op_wr_mem_p; - -#define PDB_OPCODE_CONTINUE 9 -#define PDB_OPCODE_STEP 10 - -#define PDB_OPCODE_SET_BKPT 11 -#define PDB_OPCODE_CLR_BKPT 12 -typedef struct pdb_op_bkpt -{ - uint32_t address; - uint32_t length; -} pdb_op_bkpt_t, *pdb_op_bkpt_p; - -#define PDB_OPCODE_SET_WATCHPT 13 -#define PDB_OPCODE_CLR_WATCHPT 14 -#define PDB_OPCODE_WATCHPOINT 15 -typedef struct pdb_op_watchpt -{ -#define BWC_DEBUG 1 -#define BWC_INT3 3 -#define BWC_WATCH 100 /* pdb: watchpoint page */ -#define BWC_WATCH_STEP 101 /* pdb: watchpoint single step */ -#define BWC_WATCH_WRITE 102 -#define BWC_WATCH_READ 103 -#define BWC_WATCH_ACCESS 104 - uint32_t type; - uint32_t address; - uint32_t length; -} pdb_op_watchpt_t, *pdb_op_watchpt_p; - - -typedef struct -{ - uint8_t operation; /* PDB_OPCODE_??? */ - uint32_t process; - union - { - pdb_op_attach_t attach; - pdb_op_rd_reg_t rd_reg; - pdb_op_wr_reg_t wr_reg; - pdb_op_rd_mem_req_t rd_mem; - pdb_op_wr_mem_t wr_mem; - pdb_op_bkpt_t bkpt; - pdb_op_watchpt_t watchpt; - } u; -} pdb_request_t, *pdb_request_p; - - - -#define PDB_RESPONSE_OKAY 0 -#define PDB_RESPONSE_ERROR -1 - -typedef struct { - uint8_t operation; /* copied from request */ - uint32_t domain; - uint32_t process; - int16_t status; /* PDB_RESPONSE_??? */ - union - { - pdb_op_rd_reg_t rd_reg; - pdb_op_rd_regs_t rd_regs; - pdb_op_rd_mem_resp_t rd_mem; - } u; -} pdb_response_t, *pdb_response_p; - - -DEFINE_RING_TYPES(pdb, pdb_request_t, pdb_response_t); - - -/* from access_process_vm */ -#define PDB_MEM_READ 0 -#define PDB_MEM_WRITE 1 - -#endif - - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ - diff -r 914c44d10c8d -r 2bfd19fc1b79 tools/debugger/pdb/linux-2.6-patches/Makefile --- a/tools/debugger/pdb/linux-2.6-patches/Makefile Sun Oct 01 11:39:41 2006 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -XEN_ROOT = ../../../.. -LINUX_DIR = linux-2.6.12-xenU -KDIR = $(XEN_ROOT)/$(LINUX_DIR) -PATCH_DIR = $(CURDIR) - -.PHONY: patches -patches : patches-done - -patches-done : - ( for i in *.patch ; do ( cd $(KDIR) ; patch -p1 < $(PATCH_DIR)/$$i || exit 1 ) ; done ) - touch $@ diff -r 914c44d10c8d -r 2bfd19fc1b79 tools/debugger/pdb/linux-2.6-patches/i386_ksyms.patch --- a/tools/debugger/pdb/linux-2.6-patches/i386_ksyms.patch Sun Oct 01 11:39:41 2006 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,19 +0,0 @@ -diff -u linux-2.6.12/arch/xen/i386/kernel/i386_ksyms.c linux-2.6.12-pdb/arch/xen/i386/kernel/i386_ksyms.c ---- linux-2.6.12/arch/xen/i386/kernel/i386_ksyms.c 2005-07-31 22:36:50.000000000 +0100 -+++ linux-2.6.12-pdb/arch/xen/i386/kernel/i386_ksyms.c 2005-08-01 10:57:31.000000000 +0100 -@@ -151,6 +151,7 @@ - /* TLB flushing */ - EXPORT_SYMBOL(flush_tlb_page); - #endif -+EXPORT_SYMBOL(flush_tlb_mm); - - #ifdef CONFIG_X86_IO_APIC - EXPORT_SYMBOL(IO_APIC_get_PCI_irq_vector); -@@ -172,6 +173,7 @@ - EXPORT_SYMBOL_GPL(unset_nmi_callback); - - EXPORT_SYMBOL(register_die_notifier); -+EXPORT_SYMBOL(unregister_die_notifier); - #ifdef CONFIG_HAVE_DEC_LOCK - EXPORT_SYMBOL(_atomic_dec_and_lock); - #endif diff -r 914c44d10c8d -r 2bfd19fc1b79 tools/debugger/pdb/linux-2.6-patches/kdebug.patch --- a/tools/debugger/pdb/linux-2.6-patches/kdebug.patch Sun Oct 01 11:39:41 2006 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -diff -u linux-2.6.12/include/asm-i386/kdebug.h linux-2.6.12-pdb/include/asm-i386/kdebug.h ---- linux-2.6.12/include/asm-i386/kdebug.h 2005-06-17 20:48:29.000000000 +0100 -+++ linux-2.6.12-pdb/include/asm-i386/kdebug.h 2005-08-01 11:11:53.000000000 +0100 -@@ -21,6 +21,7 @@ - If you really want to do it first unregister - then synchronize_kernel - then free. - */ - int register_die_notifier(struct notifier_block *nb); -+int unregister_die_notifier(struct notifier_block *nb); - extern struct notifier_block *i386die_chain; - - diff -r 914c44d10c8d -r 2bfd19fc1b79 tools/debugger/pdb/linux-2.6-patches/makefile.patch --- a/tools/debugger/pdb/linux-2.6-patches/makefile.patch Sun Oct 01 11:39:41 2006 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -diff -Naur linux-2.6.12/Makefile linux-2.6.12-pdb/Makefile ---- linux-2.6.12/Makefile 2005-08-01 01:21:21.000000000 +0100 -+++ linux-2.6.12-pdb/Makefile 2005-08-01 10:28:10.000000000 +0100 -@@ -508,7 +508,7 @@ - ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE - CFLAGS += -Os - else --CFLAGS += -O2 -+CFLAGS += -O - endif - - #Add align options if CONFIG_CC_* is not equal to 0 diff -r 914c44d10c8d -r 2bfd19fc1b79 tools/debugger/pdb/linux-2.6-patches/ptrace.patch --- a/tools/debugger/pdb/linux-2.6-patches/ptrace.patch Sun Oct 01 11:39:41 2006 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -diff -u linux-2.6.12/kernel/ptrace.c linux-2.6.12-pdb/kernel/ptrace.c ---- linux-2.6.12/kernel/ptrace.c 2005-06-17 20:48:29.000000000 +0100 -+++ linux-2.6.12-pdb/kernel/ptrace.c 2005-07-22 13:23:16.000000000 +0100 -@@ -239,6 +239,7 @@ - - return buf - old_buf; - } -+EXPORT_SYMBOL(access_process_vm); - - int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len) - { diff -r 914c44d10c8d -r 2bfd19fc1b79 tools/debugger/pdb/linux-2.6-patches/traps.patch --- a/tools/debugger/pdb/linux-2.6-patches/traps.patch Sun Oct 01 11:39:41 2006 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,20 +0,0 @@ -diff -u linux-2.6.12/arch/xen/i386/kernel/traps.c linux-2.6.12-pdb/arch/xen/i386/kernel/traps.c ---- linux-2.6.12/arch/xen/i386/kernel/traps.c 2005-07-31 22:47:00.000000000 +0100 -+++ linux-2.6.12-pdb/arch/xen/i386/kernel/traps.c 2005-07-31 22:47:32.000000000 +0100 -@@ -102,6 +102,16 @@ - return err; - } - -+int unregister_die_notifier(struct notifier_block *nb) -+{ -+ int err = 0; -+ unsigned long flags; -+ spin_lock_irqsave(&die_notifier_lock, flags); -+ err = notifier_chain_unregister(&i386die_chain, nb); -+ spin_unlock_irqrestore(&die_notifier_lock, flags); -+ return err; -+} -+ - static inline int valid_stack_ptr(struct thread_info *tinfo, void *p) - { - return p > (void *)tinfo && diff -r 914c44d10c8d -r 2bfd19fc1b79 tools/debugger/pdb/pdb_caml_domain.c --- a/tools/debugger/pdb/pdb_caml_domain.c Sun Oct 01 11:39:41 2006 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,527 +0,0 @@ -/* - * pdb_caml_xc.c - * - * http://www.cl.cam.ac.uk/netos/pdb - * - * PDB's OCaml interface library for debugging domains - */ - -#include <xenctrl.h> -#include <xendebug.h> -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/mman.h> -#include <caml/alloc.h> -#include <caml/fail.h> -#include <caml/memory.h> -#include <caml/mlvalues.h> - -#include "pdb_caml_xen.h" - -typedef struct -{ - int domain; - int vcpu; -} context_t; - -#define decode_context(_ctx, _ocaml) \ -{ \ - (_ctx)->domain = Int_val(Field((_ocaml),0)); \ - (_ctx)->vcpu = Int_val(Field((_ocaml),1)); \ -} - -#define encode_context(_ctx, _ocaml) \ -{ \ - (_ocaml) = caml_alloc_tuple(2); \ - Store_field((_ocaml), 0, Val_int((_ctx)->domain)); \ - Store_field((_ocaml), 1, Val_int((_ctx)->vcpu)); \ -} - - -/****************************************************************************/ - -/* - * dom_read_register : context_t -> int -> int32 - */ -value -dom_read_register (value context, value reg) -{ - CAMLparam2(context, reg); - CAMLlocal1(result); - - int my_reg = Int_val(reg); - cpu_user_regs_t *regs; - context_t ctx; - - decode_context(&ctx, context); - - if ( xendebug_read_registers(xc_handle, ctx.domain, ctx.vcpu, ®s) ) - { - printf("(pdb) read registers error!\n"); fflush(stdout); - failwith("read registers error"); - } - - dump_regs(regs); - - result = caml_alloc_tuple(16); - - switch (my_reg) - { - case GDB_EAX: result = caml_copy_int32(regs->eax); break; - case GDB_ECX: result = caml_copy_int32(regs->ecx); break; - case GDB_EDX: result = caml_copy_int32(regs->edx); break; - case GDB_EBX: result = caml_copy_int32(regs->ebx); break; - case GDB_ESP: result = caml_copy_int32(regs->esp); break; - case GDB_EBP: result = caml_copy_int32(regs->ebp); break; - case GDB_ESI: result = caml_copy_int32(regs->esi); break; - case GDB_EDI: result = caml_copy_int32(regs->edi); break; - case GDB_EIP: result = caml_copy_int32(regs->eip); break; - case GDB_EFL: result = caml_copy_int32(regs->eflags); break; - case GDB_CS: result = caml_copy_int32(regs->cs); break; - case GDB_SS: result = caml_copy_int32(regs->ss); break; - case GDB_DS: result = caml_copy_int32(regs->ds); break; - case GDB_ES: result = caml_copy_int32(regs->es); break; - case GDB_FS: result = caml_copy_int32(regs->fs); break; - case GDB_GS: result = caml_copy_int32(regs->gs); break; - } - - CAMLreturn(result); -} - -/* - * dom_read_registers : context_t -> int32 - */ -value -dom_read_registers (value context) -{ - CAMLparam1(context); - CAMLlocal1(result); - - cpu_user_regs_t *regs; - context_t ctx; - - decode_context(&ctx, context); - - if ( xendebug_read_registers(xc_handle, ctx.domain, ctx.vcpu, ®s) ) - { - printf("(pdb) read registers error!\n"); fflush(stdout); - failwith("read registers error"); - } - _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |