[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] merge with xen-unstable.hg
# HG changeset patch # User awilliam@xxxxxxxxxxx # Node ID d75a6cc5e68abe8541c326afa2a614bf1973c609 # Parent 7e3cbc40967620fb6b89eff6d931269d21416546 # Parent 4109c4e7804abeabe3b222673f2ba4dd1375be53 merge with xen-unstable.hg diff -r 7e3cbc409676 -r d75a6cc5e68a .hgtags --- a/.hgtags Mon Mar 27 15:36:47 2006 -0700 +++ b/.hgtags Tue Mar 28 08:54:58 2006 -0700 @@ -13,3 +13,4 @@ 30c521db4c71960b0cf1d9c9e1b658e77b535a3e 30c521db4c71960b0cf1d9c9e1b658e77b535a3e split-1.0 3d330e41f41ce1bc118c02346e18949ad5d67f6b split-1.1 c8fdb0caa77b429cf47f9707926e83947778cb48 RELEASE-3.0.0 +af0573e9e5258db0a9d28aa954dd302ddd2c2d23 3.0.2-rc diff -r 7e3cbc409676 -r d75a6cc5e68a Makefile --- a/Makefile Mon Mar 27 15:36:47 2006 -0700 +++ b/Makefile Tue Mar 28 08:54:58 2006 -0700 @@ -2,7 +2,7 @@ # Grand Unified Makefile for Xen. # -KERNELS ?= linux-2.6-xen0 linux-2.6-xenU +KERNELS ?= linux-2.6-xen # You may use wildcards in the above e.g. KERNELS=*2.6* XKERNELS := $(foreach kernel, $(KERNELS), $(patsubst buildconfigs/mk.%,%,$(wildcard buildconfigs/mk.$(kernel))) ) diff -r 7e3cbc409676 -r d75a6cc5e68a buildconfigs/linux-defconfig_xen0_ia64 --- a/buildconfigs/linux-defconfig_xen0_ia64 Mon Mar 27 15:36:47 2006 -0700 +++ b/buildconfigs/linux-defconfig_xen0_ia64 Tue Mar 28 08:54:58 2006 -0700 @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.16-rc3-xen0 -# Thu Feb 16 13:20:46 2006 +# Linux kernel version: 2.6.16-xen0 +# Mon Mar 27 14:46:03 2006 # # @@ -95,8 +95,7 @@ CONFIG_XEN_PRIVILEGED_GUEST=y CONFIG_XEN_PRIVILEGED_GUEST=y CONFIG_XEN_BLKDEV_GRANT=y CONFIG_XEN_BLKDEV_FRONTEND=y -CONFIG_XEN_VT=y -CONFIG_VT=y +CONFIG_XEN_BLKDEV_BACKEND=y CONFIG_XEN_SYSFS=y CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y CONFIG_DMA_IS_DMA32=y @@ -378,7 +377,7 @@ CONFIG_BLK_DEV_IDESCSI=y # # IDE chipset support/bugfixes # -CONFIG_IDE_GENERIC=y +# CONFIG_IDE_GENERIC is not set CONFIG_BLK_DEV_IDEPCI=y # CONFIG_IDEPCI_SHARE_IRQ is not set # CONFIG_BLK_DEV_OFFBOARD is not set @@ -706,6 +705,7 @@ CONFIG_GAMEPORT=y # # Character devices # +CONFIG_VT=y CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y CONFIG_SERIAL_NONSTANDARD=y @@ -1252,11 +1252,7 @@ CONFIG_USB_MON=y # CONFIG_INFINIBAND is not set # -# SN Devices -# - -# -# EDAC - error detection and reporting (RAS) +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) # # diff -r 7e3cbc409676 -r d75a6cc5e68a buildconfigs/linux-defconfig_xenU_ia64 --- a/buildconfigs/linux-defconfig_xenU_ia64 Mon Mar 27 15:36:47 2006 -0700 +++ b/buildconfigs/linux-defconfig_xenU_ia64 Tue Mar 28 08:54:58 2006 -0700 @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.16-rc3-xenU -# Thu Feb 16 13:47:59 2006 +# Linux kernel version: 2.6.16-xenU +# Mon Mar 27 14:01:13 2006 # # @@ -92,8 +92,7 @@ CONFIG_XEN_PRIVILEGED_GUEST=y CONFIG_XEN_PRIVILEGED_GUEST=y CONFIG_XEN_BLKDEV_GRANT=y CONFIG_XEN_BLKDEV_FRONTEND=y -# CONFIG_XEN_VT is not set -# CONFIG_VT is not set +CONFIG_XEN_BLKDEV_BACKEND=y CONFIG_XEN_SYSFS=y CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y CONFIG_DMA_IS_DMA32=y @@ -607,6 +606,9 @@ CONFIG_SERIO=y # # Character devices # +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y # CONFIG_SERIAL_NONSTANDARD is not set # @@ -863,6 +865,13 @@ CONFIG_FB_RADEON_DEBUG=y # CONFIG_FB_VOODOO1 is not set # CONFIG_FB_TRIDENT is not set # CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +CONFIG_VGA_CONSOLE=y +CONFIG_DUMMY_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE is not set # # Logo configuration @@ -1122,11 +1131,7 @@ CONFIG_USB_MON=y # CONFIG_INFINIBAND is not set # -# SN Devices -# - -# -# EDAC - error detection and reporting (RAS) +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) # # diff -r 7e3cbc409676 -r d75a6cc5e68a buildconfigs/linux-defconfig_xen_x86_64 --- a/buildconfigs/linux-defconfig_xen_x86_64 Mon Mar 27 15:36:47 2006 -0700 +++ b/buildconfigs/linux-defconfig_xen_x86_64 Tue Mar 28 08:54:58 2006 -0700 @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.16-rc3-xen -# Mon Feb 20 11:37:11 2006 +# Linux kernel version: 2.6.16-xen +# Mon Mar 27 09:43:44 2006 # CONFIG_X86_64=y CONFIG_64BIT=y @@ -102,6 +102,8 @@ CONFIG_X86_PC=y # CONFIG_MPSC is not set CONFIG_GENERIC_CPU=y CONFIG_X86_64_XEN=y +CONFIG_X86_NO_TSS=y +CONFIG_X86_NO_IDT=y CONFIG_X86_L1_CACHE_BYTES=128 CONFIG_X86_L1_CACHE_SHIFT=7 CONFIG_X86_GOOD_APIC=y @@ -1138,7 +1140,7 @@ CONFIG_AMD8111E_NAPI=y CONFIG_AMD8111E_NAPI=y CONFIG_ADAPTEC_STARFIRE=m CONFIG_ADAPTEC_STARFIRE_NAPI=y -CONFIG_B44=m +# CONFIG_B44 is not set CONFIG_FORCEDETH=m CONFIG_DGRS=m CONFIG_EEPRO100=m @@ -1782,8 +1784,8 @@ CONFIG_VIDEO_HEXIUM_ORION=m CONFIG_VIDEO_HEXIUM_ORION=m CONFIG_VIDEO_HEXIUM_GEMINI=m CONFIG_VIDEO_CX88=m +CONFIG_VIDEO_CX88_ALSA=m CONFIG_VIDEO_CX88_DVB=m -CONFIG_VIDEO_CX88_ALSA=m CONFIG_VIDEO_CX88_DVB_ALL_FRONTENDS=y CONFIG_VIDEO_CX88_VP3054=m CONFIG_VIDEO_EM28XX=m @@ -2331,11 +2333,7 @@ CONFIG_INFINIBAND_SRP=m CONFIG_INFINIBAND_SRP=m # -# SN Devices -# - -# -# EDAC - error detection and reporting (RAS) +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) # CONFIG_EDAC=m diff -r 7e3cbc409676 -r d75a6cc5e68a docs/src/user.tex --- a/docs/src/user.tex Mon Mar 27 15:36:47 2006 -0700 +++ b/docs/src/user.tex Tue Mar 28 08:54:58 2006 -0700 @@ -51,6 +51,40 @@ are licensed under the terms of the GNU are licensed under the terms of the GNU Lesser General Public License, the Zope Public License 2.0, or under ``BSD-style'' licenses. Please refer to the COPYING file for details. + +Xen includes software by Christopher Clark. This software is covered by the +following licence: + +\begin{quote} +Copyright (c) 2002, Christopher Clark. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +\begin{itemize} +\item Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +\item Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +\item Neither the name of the original author; nor the names of any +contributors may be used to endorse or promote products derived from this +software without specific prior written permission. +\end{itemize} + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +\end{quote} \cleardoublepage diff -r 7e3cbc409676 -r d75a6cc5e68a extras/mini-os/Makefile --- a/extras/mini-os/Makefile Mon Mar 27 15:36:47 2006 -0700 +++ b/extras/mini-os/Makefile Tue Mar 28 08:54:58 2006 -0700 @@ -41,8 +41,7 @@ default: $(TARGET) links: [ -e include/xen ] || ln -sf ../../../xen/include/public include/xen - [ -e xenbus/xenstored.h ] || ln -sf ../../../tools/xenstore/xenstored.h xenbus/xenstored.h - + $(TARGET): links $(OBJS) $(LD) -N -T minios-$(TARGET_ARCH).lds $(OBJS) -o $@.elf gzip -f -9 -c $@.elf >$@.gz diff -r 7e3cbc409676 -r d75a6cc5e68a extras/mini-os/console/console.c --- a/extras/mini-os/console/console.c Mon Mar 27 15:36:47 2006 -0700 +++ b/extras/mini-os/console/console.c Tue Mar 28 08:54:58 2006 -0700 @@ -116,12 +116,12 @@ void print(int direct, const char *fmt, { (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(buf), buf); return; + } else { + if(!console_initialised) + (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(buf), buf); + + console_print(buf, strlen(buf)); } - - if(!console_initialised) - (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(buf), buf); - - console_print(buf, strlen(buf)); } void printk(const char *fmt, ...) diff -r 7e3cbc409676 -r d75a6cc5e68a extras/mini-os/console/xencons_ring.c --- a/extras/mini-os/console/xencons_ring.c Mon Mar 27 15:36:47 2006 -0700 +++ b/extras/mini-os/console/xencons_ring.c Tue Mar 28 08:54:58 2006 -0700 @@ -10,7 +10,6 @@ /* TODO - need to define BUG_ON for whole mini-os, need crash-dump as well */ -extern void do_exit(void); #define BUG_ON(_cond) do{if(_cond) do_exit();} while(0); static inline struct xencons_interface *xencons_interface(void) @@ -29,7 +28,6 @@ int xencons_ring_send_no_notify(const ch int sent = 0; struct xencons_interface *intf = xencons_interface(); XENCONS_RING_IDX cons, prod; - cons = intf->out_cons; prod = intf->out_prod; mb(); diff -r 7e3cbc409676 -r d75a6cc5e68a extras/mini-os/events.c --- a/extras/mini-os/events.c Mon Mar 27 15:36:47 2006 -0700 +++ b/extras/mini-os/events.c Tue Mar 28 08:54:58 2006 -0700 @@ -74,9 +74,9 @@ int bind_evtchn( u32 port, void (*handle void unbind_evtchn( u32 port ) { - if (ev_actions[port].handler) + if (ev_actions[port].handler == default_handler) printk("WARN: No handler for port %d when unbinding\n", port); - ev_actions[port].handler = NULL; + ev_actions[port].handler = default_handler; ev_actions[port].status |= EVS_DISABLED; } diff -r 7e3cbc409676 -r d75a6cc5e68a extras/mini-os/include/os.h --- a/extras/mini-os/include/os.h Mon Mar 27 15:36:47 2006 -0700 +++ b/extras/mini-os/include/os.h Tue Mar 28 08:54:58 2006 -0700 @@ -9,6 +9,7 @@ #define NULL 0 + #if __GNUC__ == 2 && __GNUC_MINOR__ < 96 #define __builtin_expect(x, expected_value) (x) #endif @@ -20,6 +21,10 @@ #ifndef __ASSEMBLY__ #include <types.h> #include <hypervisor.h> + +extern void do_exit(void); +#define BUG do_exit + #endif #include <xen/xen.h> diff -r 7e3cbc409676 -r d75a6cc5e68a extras/mini-os/include/wait.h --- a/extras/mini-os/include/wait.h Mon Mar 27 15:36:47 2006 -0700 +++ b/extras/mini-os/include/wait.h Tue Mar 28 08:54:58 2006 -0700 @@ -66,6 +66,14 @@ static inline void wake_up(struct wait_q } } +#define add_waiter(w, wq) do { \ + unsigned long flags; \ + local_irq_save(flags); \ + add_wait_queue(&wq, &w); \ + block(current); \ + local_irq_restore(flags); \ +} while (0) + #define wait_event(wq, condition) do{ \ unsigned long flags; \ if(condition) \ diff -r 7e3cbc409676 -r d75a6cc5e68a extras/mini-os/include/xenbus.h --- a/extras/mini-os/include/xenbus.h Mon Mar 27 15:36:47 2006 -0700 +++ b/extras/mini-os/include/xenbus.h Tue Mar 28 08:54:58 2006 -0700 @@ -1,224 +1,6 @@ -/****************************************************************************** - * xenbus.h - * - * Talks to Xen Store to figure out what devices we have. - * - * Copyright (C) 2005 Rusty Russell, IBM Corporation - * Copyright (C) 2005 XenSource Ltd. - * - * This file may be distributed separately from the Linux kernel, or - * incorporated into other software packages, subject to the following license: - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this source file (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, modify, - * merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ +#ifndef XENBUS_H__ +#define XENBUS_H__ -#ifndef _ASM_XEN_XENBUS_H -#define _ASM_XEN_XENBUS_H +void init_xenbus(void); -#include <errno.h> -#include <xen/io/xenbus.h> -#include <xen/io/xs_wire.h> - -/* Register callback to watch this node. */ -struct xenbus_watch -{ - struct list_head list; - - /* Path being watched. */ - const char *node; - - /* Callback (executed in a process context with no locks held). */ - void (*callback)(struct xenbus_watch *, - const char **vec, unsigned int len); -}; - - -/* A xenbus device. */ -struct xenbus_device { - const char *devicetype; - const char *nodename; - const char *otherend; - int otherend_id; - struct xenbus_watch otherend_watch; - int has_error; - void *data; -}; - -struct xenbus_device_id -{ - /* .../device/<device_type>/<identifier> */ - char devicetype[32]; /* General class of device. */ -}; - -/* A xenbus driver. */ -struct xenbus_driver { - char *name; - struct module *owner; - const struct xenbus_device_id *ids; - int (*probe)(struct xenbus_device *dev, - const struct xenbus_device_id *id); - void (*otherend_changed)(struct xenbus_device *dev, - XenbusState backend_state); - int (*remove)(struct xenbus_device *dev); - int (*suspend)(struct xenbus_device *dev); - int (*resume)(struct xenbus_device *dev); - int (*hotplug)(struct xenbus_device *, char **, int, char *, int); - int (*read_otherend_details)(struct xenbus_device *dev); -}; - -int xenbus_register_frontend(struct xenbus_driver *drv); -int xenbus_register_backend(struct xenbus_driver *drv); -void xenbus_unregister_driver(struct xenbus_driver *drv); - -struct xenbus_transaction; - -char **xenbus_directory(struct xenbus_transaction *t, - const char *dir, const char *node, unsigned int *num); -void *xenbus_read(struct xenbus_transaction *t, - const char *dir, const char *node, unsigned int *len); -int xenbus_write(struct xenbus_transaction *t, - const char *dir, const char *node, const char *string); -int xenbus_mkdir(struct xenbus_transaction *t, - const char *dir, const char *node); -int xenbus_exists(struct xenbus_transaction *t, - const char *dir, const char *node); -int xenbus_rm(struct xenbus_transaction *t, const char *dir, const char *node); -struct xenbus_transaction *xenbus_transaction_start(void); -int xenbus_transaction_end(struct xenbus_transaction *t, int abort); - -/* Single read and scanf: returns -errno or num scanned if > 0. */ -int xenbus_scanf(struct xenbus_transaction *t, - const char *dir, const char *node, const char *fmt, ...) - __attribute__((format(scanf, 4, 5))); - -/* Single printf and write: returns -errno or 0. */ -int xenbus_printf(struct xenbus_transaction *t, - const char *dir, const char *node, const char *fmt, ...) - __attribute__((format(printf, 4, 5))); - -/* Generic read function: NULL-terminated triples of name, - * sprintf-style type string, and pointer. Returns 0 or errno.*/ -int xenbus_gather(struct xenbus_transaction *t, const char *dir, ...); - -int register_xenbus_watch(struct xenbus_watch *watch); -void unregister_xenbus_watch(struct xenbus_watch *watch); -void xs_suspend(void); -void xs_resume(void); - -/* Used by xenbus_dev to borrow kernel's store connection. */ -void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg); - -/* Called from xen core code. */ -void xenbus_suspend(void); -void xenbus_resume(void); - -#define XENBUS_IS_ERR_READ(str) ({ \ - if (!IS_ERR(str) && strlen(str) == 0) { \ - kfree(str); \ - str = ERR_PTR(-ERANGE); \ - } \ - IS_ERR(str); \ -}) - -#define XENBUS_EXIST_ERR(err) ((err) == -ENOENT || (err) == -ERANGE) - - -/** - * Register a watch on the given path, using the given xenbus_watch structure - * for storage, and the given callback function as the callback. Return 0 on - * success, or -errno on error. On success, the given path will be saved as - * watch->node, and remains the caller's to free. On error, watch->node will - * be NULL, the device will switch to XenbusStateClosing, and the error will - * be saved in the store. - */ -int xenbus_watch_path(struct xenbus_device *dev, const char *path, - struct xenbus_watch *watch, - void (*callback)(struct xenbus_watch *, - const char **, unsigned int)); - - -/** - * Register a watch on the given path/path2, using the given xenbus_watch - * structure for storage, and the given callback function as the callback. - * Return 0 on success, or -errno on error. On success, the watched path - * (path/path2) will be saved as watch->node, and becomes the caller's to - * kfree(). On error, watch->node will be NULL, so the caller has nothing to - * free, the device will switch to XenbusStateClosing, and the error will be - * saved in the store. - */ -int xenbus_watch_path2(struct xenbus_device *dev, const char *path, - const char *path2, struct xenbus_watch *watch, - void (*callback)(struct xenbus_watch *, - const char **, unsigned int)); - - -/** - * Advertise in the store a change of the given driver to the given new_state. - * Perform the change inside the given transaction xbt. xbt may be NULL, in - * which case this is performed inside its own transaction. Return 0 on - * success, or -errno on error. On error, the device will switch to - * XenbusStateClosing, and the error will be saved in the store. - */ -int xenbus_switch_state(struct xenbus_device *dev, - struct xenbus_transaction *xbt, - XenbusState new_state); - - -/** - * Grant access to the given ring_mfn to the peer of the given device. Return - * 0 on success, or -errno on error. On error, the device will switch to - * XenbusStateClosing, and the error will be saved in the store. - */ -int xenbus_grant_ring(struct xenbus_device *dev, unsigned long ring_mfn); - - -/** - * Allocate an event channel for the given xenbus_device, assigning the newly - * created local port to *port. Return 0 on success, or -errno on error. On - * error, the device will switch to XenbusStateClosing, and the error will be - * saved in the store. - */ -int xenbus_alloc_evtchn(struct xenbus_device *dev, int *port); - - -/** - * Return the state of the driver rooted at the given store path, or - * XenbusStateClosed if no state can be read. - */ -XenbusState xenbus_read_driver_state(const char *path); - - -/*** - * Report the given negative errno into the store, along with the given - * formatted message. - */ -void xenbus_dev_error(struct xenbus_device *dev, int err, const char *fmt, - ...); - - -/*** - * Equivalent to xenbus_dev_error(dev, err, fmt, args), followed by - * xenbus_switch_state(dev, NULL, XenbusStateClosing) to schedule an orderly - * closedown of this driver and its peer. - */ -void xenbus_dev_fatal(struct xenbus_device *dev, int err, const char *fmt, - ...); - - -#endif /* _ASM_XEN_XENBUS_H */ +#endif /* XENBUS_H__ */ diff -r 7e3cbc409676 -r d75a6cc5e68a extras/mini-os/kernel.c --- a/extras/mini-os/kernel.c Mon Mar 27 15:36:47 2006 -0700 +++ b/extras/mini-os/kernel.c Tue Mar 28 08:54:58 2006 -0700 @@ -35,7 +35,6 @@ #include <lib.h> #include <sched.h> #include <xenbus.h> -#include "xenbus/xenbus_comms.h" /* * Shared page for communicating with the hypervisor. @@ -76,7 +75,15 @@ static shared_info_t *map_shared_info(un } -extern void init_console(void); +void test_xenbus(void); + +/* Do initialisation from a thread once the scheduler's available */ +static void init_xs(void *ign) +{ + init_xenbus(); + + test_xenbus(); +} /* * INITIAL C ENTRY POINT. @@ -84,11 +91,13 @@ void start_kernel(start_info_t *si) void start_kernel(start_info_t *si) { static char hello[] = "Bootstrapping...\n"; + (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(hello), hello); /* Copy the start_info struct to a globally-accessible area. */ + /* WARN: don't do printk before here, it uses information from + shared_info. Use xprintk instead. */ memcpy(&start_info, si, sizeof(*si)); - /* Grab the shared_info pointer and put it in a safe place. */ HYPERVISOR_shared_info = map_shared_info(start_info.shared_info); @@ -120,28 +129,24 @@ void start_kernel(start_info_t *si) si->cmd_line ? (const char *)si->cmd_line : "NULL"); - /* - * If used for porting another OS, start here to figure out your - * guest os entry point. Otherwise continue below... - */ - /* init memory management */ + /* Init memory management. */ init_mm(); - /* set up events */ + /* Set up events. */ init_events(); - /* init time and timers */ + /* Init time and timers. */ init_time(); - /* init the console driver */ + /* Init the console driver. */ init_console(); - - /* init scheduler */ + + /* Init scheduler. */ init_sched(); - - /* init xenbus */ - xs_init(); - + + /* Init XenBus from a separate thread */ + create_thread("init_xs", init_xs, NULL); + /* Everything initialised, start idle thread */ run_idle_thread(); } @@ -156,6 +161,6 @@ void start_kernel(start_info_t *si) void do_exit(void) { - printk("do_exit called!\n"); + printk("Do_exit called!\n"); for ( ;; ) HYPERVISOR_sched_op(SCHEDOP_shutdown, SHUTDOWN_crash); } diff -r 7e3cbc409676 -r d75a6cc5e68a extras/mini-os/minios-x86_32.lds --- a/extras/mini-os/minios-x86_32.lds Mon Mar 27 15:36:47 2006 -0700 +++ b/extras/mini-os/minios-x86_32.lds Tue Mar 28 08:54:58 2006 -0700 @@ -21,15 +21,6 @@ SECTIONS _edata = .; /* End of data section */ - . = ALIGN(8192); /* init_task */ - .data.init_task : { *(.data.init_task) } - - . = ALIGN(4096); - .data.page_aligned : { *(.data.idt) } - - . = ALIGN(32); - .data.cacheline_aligned : { *(.data.cacheline_aligned) } - __bss_start = .; /* BSS */ .bss : { *(.bss) diff -r 7e3cbc409676 -r d75a6cc5e68a extras/mini-os/mm.c --- a/extras/mini-os/mm.c Mon Mar 27 15:36:47 2006 -0700 +++ b/extras/mini-os/mm.c Tue Mar 28 08:54:58 2006 -0700 @@ -51,7 +51,6 @@ unsigned long *phys_to_machine_mapping; unsigned long *phys_to_machine_mapping; extern char *stack; extern char _text, _etext, _edata, _end; -extern void do_exit(void); extern void page_walk(unsigned long virt_addr); /********************* @@ -373,7 +372,7 @@ void new_pt_frame(unsigned long *pt_pfn, unsigned long *tab = (unsigned long *)start_info.pt_base; unsigned long pt_page = (unsigned long)pfn_to_virt(*pt_pfn); unsigned long prot_e, prot_t, pincmd; - mmu_update_t mmu_updates[0]; + mmu_update_t mmu_updates[1]; struct mmuext_op pin_request; DEBUG("Allocating new L%d pt frame for pt_pfn=%lx, " diff -r 7e3cbc409676 -r d75a6cc5e68a extras/mini-os/sched.c --- a/extras/mini-os/sched.c Mon Mar 27 15:36:47 2006 -0700 +++ b/extras/mini-os/sched.c Tue Mar 28 08:54:58 2006 -0700 @@ -64,6 +64,8 @@ struct thread *idle_thread = NULL; LIST_HEAD(exited_threads); + +void idle_thread_fn(void *unused); void dump_stack(struct thread *thread) { @@ -132,7 +134,7 @@ void schedule(void) xfree(thread); } } - next = idle_thread; + next = idle_thread; /* Thread list needs to be protected */ list_for_each(iterator, &idle_thread->thread_list) { @@ -203,8 +205,13 @@ struct thread* create_thread(char *name, set_runnable(thread); local_irq_save(flags); - if(idle_thread != NULL) + if(idle_thread != NULL) { list_add_tail(&thread->thread_list, &idle_thread->thread_list); + } else if(function != idle_thread_fn) + { + printk("BUG: Not allowed to create thread before initialising scheduler.\n"); + BUG(); + } local_irq_restore(flags); return thread; @@ -282,19 +289,9 @@ void th_f2(void *data) void init_sched(void) { - printk("Initialising scheduler\n"); - + printk("Initialising scheduler, idle_thread %p\n", idle_thread); + idle_thread = create_thread("Idle", idle_thread_fn, NULL); INIT_LIST_HEAD(&idle_thread->thread_list); - - -/* create_thread("1", th_f1, (void *)0x1234); - create_thread("2", th_f1, (void *)0x1234); - create_thread("3", th_f1, (void *)0x1234); - create_thread("4", th_f1, (void *)0x1234); - create_thread("5", th_f1, (void *)0x1234); - create_thread("6", th_f1, (void *)0x1234); - create_thread("second", th_f2, NULL); -*/ -} - +} + diff -r 7e3cbc409676 -r d75a6cc5e68a extras/mini-os/traps.c --- a/extras/mini-os/traps.c Mon Mar 27 15:36:47 2006 -0700 +++ b/extras/mini-os/traps.c Tue Mar 28 08:54:58 2006 -0700 @@ -29,11 +29,18 @@ void machine_check(void); void machine_check(void); -extern void do_exit(void); - void dump_regs(struct pt_regs *regs) { - printk("FIXME: proper register dump (with the stack dump)\n"); + printk("EIP: %x, EFLAGS %x.\n", regs->eip, regs->eflags); + printk("EBX: %08x ECX: %08x EDX: %08x\n", + regs->ebx, regs->ecx, regs->edx); + printk("ESI: %08x EDI: %08x EBP: %08x EAX: %08x\n", + regs->esi, regs->edi, regs->ebp, regs->eax); + printk("DS: %04x ES: %04x orig_eax: %08x, eip: %08x\n", + regs->xds, regs->xes, regs->orig_eax, regs->eip); + printk("CS: %04x EFLAGS: %08x esp: %08x ss: %04x\n", + regs->xcs, regs->eflags, regs->esp, regs->xss); + } @@ -94,10 +101,14 @@ void page_walk(unsigned long virt_addres } -void do_page_fault(struct pt_regs *regs, unsigned long error_code, - unsigned long addr) -{ - printk("Page fault at linear address %p\n", addr); +#define read_cr2() \ + (HYPERVISOR_shared_info->vcpu_info[smp_processor_id()].arch.cr2) + +void do_page_fault(struct pt_regs *regs, unsigned long error_code) +{ + unsigned long addr = read_cr2(); + printk("Page fault at linear address %p, regs %p, code %lx\n", addr, regs, + error_code); dump_regs(regs); #ifdef __x86_64__ /* FIXME: _PAGE_PSE */ diff -r 7e3cbc409676 -r d75a6cc5e68a extras/mini-os/x86_32.S --- a/extras/mini-os/x86_32.S Mon Mar 27 15:36:47 2006 -0700 +++ b/extras/mini-os/x86_32.S Tue Mar 28 08:54:58 2006 -0700 @@ -30,10 +30,10 @@ hypercall_page: hypercall_page: .org 0x3000 -ES = 0x20 -ORIG_EAX = 0x24 -EIP = 0x28 -CS = 0x2C +ES = 0x1c +ORIG_EAX = 0x20 +EIP = 0x24 +CS = 0x28 #define ENTRY(X) .globl X ; X : @@ -94,32 +94,6 @@ do_exception: call *%edi addl $8,%esp -/* pushl %ds - pushl %eax - xorl %eax,%eax - pushl %ebp - pushl %edi - pushl %esi - pushl %edx - decl %eax # eax = -1 - pushl %ecx - pushl %ebx - cld - movl %es,%ecx - movl ORIG_EAX(%esp), %esi # get the error code - movl ES(%esp), %edi # get the function address - movl %eax, ORIG_EAX(%esp) - movl %ecx, ES(%esp) - movl %esp,%edx - pushl %esi # push the error code - pushl %edx # push the pt_regs pointer - movl $(__KERNEL_DS),%edx - movl %edx,%ds - movl %edx,%es - call *%edi - addl $8,%esp */ - - ret_from_exception: movb CS(%esp),%cl test $2,%cl # slow return to ring 2 or 3 @@ -290,15 +264,16 @@ ENTRY(page_fault) pushl %ecx pushl %ebx cld - movl %es,%edi - movl ES(%esp), %ecx /* get the faulting address */ - movl ORIG_EAX(%esp), %edx /* get the error code */ + movl ORIG_EAX(%esp), %edi movl %eax, ORIG_EAX(%esp) - movl %edi, ES(%esp) + movl %es, %ecx + movl %ecx, ES(%esp) movl $(__KERNEL_DS),%eax movl %eax, %ds movl %eax, %es - movl %esp,%eax /* pt_regs pointer */ + pushl %edi + movl %esp, %eax + pushl %eax call do_page_fault jmp ret_from_exception diff -r 7e3cbc409676 -r d75a6cc5e68a linux-2.6-xen-sparse/arch/i386/kernel/cpu/common-xen.c --- a/linux-2.6-xen-sparse/arch/i386/kernel/cpu/common-xen.c Mon Mar 27 15:36:47 2006 -0700 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/cpu/common-xen.c Tue Mar 28 08:54:58 2006 -0700 @@ -33,8 +33,6 @@ static int disable_x86_serial_nr __devin static int disable_x86_serial_nr __devinitdata = 1; struct cpu_dev * cpu_devs[X86_VENDOR_NUM] = {}; - -extern void machine_specific_modify_cpu_capabilities(struct cpuinfo_x86 *c); extern int disable_pse; @@ -425,8 +423,6 @@ void __devinit identify_cpu(struct cpuin c->x86_vendor, c->x86_model); } - machine_specific_modify_cpu_capabilities(c); - /* Now the feature flags better reflect actual CPU features! */ printk(KERN_DEBUG "CPU: After all inits, caps:"); diff -r 7e3cbc409676 -r d75a6cc5e68a linux-2.6-xen-sparse/arch/i386/kernel/entry-xen.S --- a/linux-2.6-xen-sparse/arch/i386/kernel/entry-xen.S Mon Mar 27 15:36:47 2006 -0700 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/entry-xen.S Tue Mar 28 08:54:58 2006 -0700 @@ -462,7 +462,7 @@ ENTRY(irq_entries_start) ENTRY(irq_entries_start) .rept NR_IRQS ALIGN -1: pushl $vector-256 +1: pushl 0x80000000+$vector jmp common_interrupt .data .long 1b @@ -479,7 +479,7 @@ common_interrupt: #define BUILD_INTERRUPT(name, nr) \ ENTRY(name) \ - pushl $nr-256; \ + pushl 0x80000000+$nr; \ SAVE_ALL \ movl %esp,%eax; \ call smp_/**/name; \ diff -r 7e3cbc409676 -r d75a6cc5e68a linux-2.6-xen-sparse/arch/i386/kernel/head-xen.S --- a/linux-2.6-xen-sparse/arch/i386/kernel/head-xen.S Mon Mar 27 15:36:47 2006 -0700 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/head-xen.S Tue Mar 28 08:54:58 2006 -0700 @@ -32,14 +32,14 @@ ENTRY(startup_32) /* get vendor info */ xorl %eax,%eax # call CPUID with 0 -> return vendor ID - cpuid + XEN_CPUID movl %eax,X86_CPUID # save CPUID level movl %ebx,X86_VENDOR_ID # lo 4 chars movl %edx,X86_VENDOR_ID+4 # next 4 chars movl %ecx,X86_VENDOR_ID+8 # last 4 chars movl $1,%eax # Use the CPUID instruction to get CPU type - cpuid + XEN_CPUID movb %al,%cl # save reg for future use andb $0x0f,%ah # mask processor family movb %ah,X86 diff -r 7e3cbc409676 -r d75a6cc5e68a linux-2.6-xen-sparse/arch/i386/kernel/irq-xen.c --- a/linux-2.6-xen-sparse/arch/i386/kernel/irq-xen.c Mon Mar 27 15:36:47 2006 -0700 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/irq-xen.c Tue Mar 28 08:54:58 2006 -0700 @@ -53,8 +53,8 @@ static union irq_ctx *softirq_ctx[NR_CPU */ fastcall unsigned int do_IRQ(struct pt_regs *regs) { - /* high bits used in ret_from_ code */ - int irq = regs->orig_eax & __IRQ_MASK(HARDIRQ_BITS); + /* high bit used in ret_from_ code */ + int irq = regs->orig_eax & __IRQ_MASK(BITS_PER_LONG - 1); #ifdef CONFIG_4KSTACKS union irq_ctx *curctx, *irqctx; u32 *isp; diff -r 7e3cbc409676 -r d75a6cc5e68a linux-2.6-xen-sparse/arch/i386/mm/ioremap-xen.c --- a/linux-2.6-xen-sparse/arch/i386/mm/ioremap-xen.c Mon Mar 27 15:36:47 2006 -0700 +++ b/linux-2.6-xen-sparse/arch/i386/mm/ioremap-xen.c Tue Mar 28 08:54:58 2006 -0700 @@ -32,13 +32,13 @@ #endif static int direct_remap_area_pte_fn(pte_t *pte, - struct page *pte_page, + struct page *pmd_page, unsigned long address, void *data) { mmu_update_t **v = (mmu_update_t **)data; - (*v)->ptr = ((u64)pfn_to_mfn(page_to_pfn(pte_page)) << + (*v)->ptr = ((u64)pfn_to_mfn(page_to_pfn(pmd_page)) << PAGE_SHIFT) | ((unsigned long)pte & ~PAGE_MASK); (*v)++; @@ -67,9 +67,9 @@ static int __direct_remap_pfn_range(stru for (i = 0; i < size; i += PAGE_SIZE) { if ((v - u) == (PAGE_SIZE / sizeof(mmu_update_t))) { /* Fill in the PTE pointers. */ - rc = generic_page_range(mm, start_address, - address - start_address, - direct_remap_area_pte_fn, &w); + rc = apply_to_page_range(mm, start_address, + address - start_address, + direct_remap_area_pte_fn, &w); if (rc) goto out; w = u; @@ -93,8 +93,9 @@ static int __direct_remap_pfn_range(stru if (v != u) { /* get the ptep's filled in */ - rc = generic_page_range(mm, start_address, address - start_address, - direct_remap_area_pte_fn, &w); + rc = apply_to_page_range(mm, start_address, + address - start_address, + direct_remap_area_pte_fn, &w); if (rc) goto out; rc = -EFAULT; @@ -142,11 +143,11 @@ EXPORT_SYMBOL(direct_kernel_remap_pfn_ra EXPORT_SYMBOL(direct_kernel_remap_pfn_range); static int lookup_pte_fn( - pte_t *pte, struct page *pte_page, unsigned long addr, void *data) + pte_t *pte, struct page *pmd_page, unsigned long addr, void *data) { uint64_t *ptep = (uint64_t *)data; if (ptep) - *ptep = ((uint64_t)pfn_to_mfn(page_to_pfn(pte_page)) << + *ptep = ((uint64_t)pfn_to_mfn(page_to_pfn(pmd_page)) << PAGE_SHIFT) | ((unsigned long)pte & ~PAGE_MASK); return 0; } @@ -155,13 +156,14 @@ int create_lookup_pte_addr(struct mm_str unsigned long address, uint64_t *ptep) { - return generic_page_range(mm, address, PAGE_SIZE, lookup_pte_fn, ptep); + return apply_to_page_range(mm, address, PAGE_SIZE, + lookup_pte_fn, ptep); } EXPORT_SYMBOL(create_lookup_pte_addr); static int noop_fn( - pte_t *pte, struct page *pte_page, unsigned long addr, void *data) + pte_t *pte, struct page *pmd_page, unsigned long addr, void *data) { return 0; } @@ -170,7 +172,7 @@ int touch_pte_range(struct mm_struct *mm unsigned long address, unsigned long size) { - return generic_page_range(mm, address, size, noop_fn, NULL); + return apply_to_page_range(mm, address, size, noop_fn, NULL); } EXPORT_SYMBOL(touch_pte_range); diff -r 7e3cbc409676 -r d75a6cc5e68a linux-2.6-xen-sparse/arch/ia64/Kconfig --- a/linux-2.6-xen-sparse/arch/ia64/Kconfig Mon Mar 27 15:36:47 2006 -0700 +++ b/linux-2.6-xen-sparse/arch/ia64/Kconfig Tue Mar 28 08:54:58 2006 -0700 @@ -83,19 +83,6 @@ config XEN_BLKDEV_BACKEND depends on XEN bool default y - -config XEN_VT - bool "Override for turning on CONFIG_VT for domU" - default y - help - Hack to turn off CONFIG_VT for domU - -config VT - bool - default y if XEN && XEN_VT - default n if XEN && !XEN_VT - help - Hack to turn off CONFIG_VT for domU config XEN_SYSFS bool "Export Xen attributes in sysfs" diff -r 7e3cbc409676 -r d75a6cc5e68a linux-2.6-xen-sparse/arch/ia64/kernel/setup.c --- a/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c Mon Mar 27 15:36:47 2006 -0700 +++ b/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c Tue Mar 28 08:54:58 2006 -0700 @@ -506,6 +506,22 @@ setup_arch (char **cmdline_p) conswitchp = &vga_con; # endif } +#ifdef CONFIG_XEN + if (running_on_xen) { + extern shared_info_t *HYPERVISOR_shared_info; + + /* xen_start_info isn't setup yet, get the flags manually */ + if (HYPERVISOR_shared_info->arch.flags & SIF_INITDOMAIN) { + if (!(HYPERVISOR_shared_info->arch.flags & SIF_PRIVILEGED)) + panic("Xen granted us console access " + "but not privileged status"); + } else { + extern int console_use_vt; + conswitchp = NULL; + console_use_vt = 0; + } + } +#endif #endif /* enable IA-64 Machine Check Abort Handling unless disabled */ diff -r 7e3cbc409676 -r d75a6cc5e68a linux-2.6-xen-sparse/arch/x86_64/kernel/apic-xen.c --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/apic-xen.c Mon Mar 27 15:36:47 2006 -0700 +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/apic-xen.c Tue Mar 28 08:54:58 2006 -0700 @@ -113,8 +113,6 @@ void smp_apic_timer_interrupt(struct pt_ smp_local_timer_interrupt(regs); irq_exit(); } - -int __initdata unsync_tsc_on_multicluster; /* * This interrupt should _never_ happen with our APIC/SMP architecture diff -r 7e3cbc409676 -r d75a6cc5e68a linux-2.6-xen-sparse/arch/x86_64/kernel/entry-xen.S --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/entry-xen.S Mon Mar 27 15:36:47 2006 -0700 +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/entry-xen.S Tue Mar 28 08:54:58 2006 -0700 @@ -584,7 +584,7 @@ retint_kernel: */ .macro apicinterrupt num,func INTR_FRAME - pushq $\num-256 + pushq 0x8000000000000000+$\num CFI_ADJUST_CFA_OFFSET 8 interrupt \func jmp error_entry @@ -855,32 +855,12 @@ ecrit: /**** END OF CRITICAL REGION *** # i.e. it just resumes from the next instruction interrupted with the same context. # Hypervisor uses this for application faults while it executes. +# Unlike i386 there is no need to reload the saved segment selectors: +# Xen already reloaded all valid ones and zeroed the others. ENTRY(failsafe_callback) - addq $0x10,%rsp /* skip rcx and r11 */ -1: mov (%rsp),%ds -2: mov 8(%rsp),%es -3: mov 16(%rsp),%fs -4: mov 24(%rsp),%gs - addq $0x20,%rsp /* skip the above selectors */ + addq $0x30,%rsp /* skip %rcx,%r11,%ds,%es,%fs,%gs */ SAVE_ALL jmp error_exit -.section .fixup,"ax"; \ -6: movq $0,(%rsp); \ - jmp 1b; \ -7: movq $0,8(%rsp); \ - jmp 2b; \ -8: movq $0,16(%rsp); \ - jmp 3b; \ -9: movq $0,24(%rsp); \ - jmp 4b; \ -.previous; \ -.section __ex_table,"a";\ - .align 16; \ - .quad 1b,6b; \ - .quad 2b,7b; \ - .quad 3b,8b; \ - .quad 4b,9b; \ -.previous #if 0 .section __ex_table,"a" diff -r 7e3cbc409676 -r d75a6cc5e68a linux-2.6-xen-sparse/arch/x86_64/kernel/irq-xen.c --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/irq-xen.c Mon Mar 27 15:36:47 2006 -0700 +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/irq-xen.c Tue Mar 28 08:54:58 2006 -0700 @@ -96,8 +96,8 @@ skip: */ asmlinkage unsigned int do_IRQ(struct pt_regs *regs) { - /* high bits used in ret_from_ code */ - int irq = regs->orig_rax & __IRQ_MASK(HARDIRQ_BITS); + /* high bit used in ret_from_ code */ + int irq = regs->orig_rax & __IRQ_MASK(BITS_PER_LONG - 1); exit_idle(); irq_enter(); diff -r 7e3cbc409676 -r d75a6cc5e68a linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c Mon Mar 27 15:36:47 2006 -0700 +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c Tue Mar 28 08:54:58 2006 -0700 @@ -82,8 +82,6 @@ extern unsigned long start_pfn; extern unsigned long start_pfn; extern struct edid_info edid_info; -extern void machine_specific_modify_cpu_capabilities(struct cpuinfo_x86 *c); - shared_info_t *HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page; EXPORT_SYMBOL(HYPERVISOR_shared_info); @@ -1433,8 +1431,6 @@ void __cpuinit identify_cpu(struct cpuin select_idle_routine(c); detect_ht(c); - machine_specific_modify_cpu_capabilities(c); - /* * On SMP, boot_cpu_data holds the common feature set between * all CPUs; so make sure that we indicate which features are diff -r 7e3cbc409676 -r d75a6cc5e68a linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c --- a/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c Mon Mar 27 15:36:47 2006 -0700 +++ b/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c Tue Mar 28 08:54:58 2006 -0700 @@ -517,7 +517,7 @@ void balloon_update_driver_allowance(lon } static int dealloc_pte_fn( - pte_t *pte, struct page *pte_page, unsigned long addr, void *data) + pte_t *pte, struct page *pmd_page, unsigned long addr, void *data) { unsigned long mfn = pte_mfn(*pte); int ret; @@ -547,8 +547,8 @@ struct page *balloon_alloc_empty_page_ra scrub_pages(vstart, 1 << order); balloon_lock(flags); - ret = generic_page_range( - &init_mm, vstart, PAGE_SIZE << order, dealloc_pte_fn, NULL); + ret = apply_to_page_range(&init_mm, vstart, + PAGE_SIZE << order, dealloc_pte_fn, NULL); BUG_ON(ret); current_pages -= 1UL << order; totalram_pages = current_pages; diff -r 7e3cbc409676 -r d75a6cc5e68a linux-2.6-xen-sparse/drivers/xen/core/evtchn.c --- a/linux-2.6-xen-sparse/drivers/xen/core/evtchn.c Mon Mar 27 15:36:47 2006 -0700 +++ b/linux-2.6-xen-sparse/drivers/xen/core/evtchn.c Tue Mar 28 08:54:58 2006 -0700 @@ -58,17 +58,37 @@ static int evtchn_to_irq[NR_EVENT_CHANNE /* Packed IRQ information: binding type, sub-type index, and event channel. */ static u32 irq_info[NR_IRQS]; + /* Binding types. */ enum { IRQT_UNBOUND, IRQT_PIRQ, IRQT_VIRQ, IRQT_IPI, IRQT_EVTCHN }; + /* Constructor for packed IRQ information. */ -#define mk_irq_info(type, index, evtchn) \ - (((u32)(type) << 24) | ((u32)(index) << 16) | (u32)(evtchn)) +static inline u32 mk_irq_info(u32 type, u32 index, u32 evtchn) +{ + return ((type << 24) | (index << 16) | evtchn); +} + /* Convenient shorthand for packed representation of an unbound IRQ. */ #define IRQ_UNBOUND mk_irq_info(IRQT_UNBOUND, 0, 0) -/* Accessor macros for packed IRQ information. */ -#define evtchn_from_irq(irq) ((u16)(irq_info[irq])) -#define index_from_irq(irq) ((u8)(irq_info[irq] >> 16)) -#define type_from_irq(irq) ((u8)(irq_info[irq] >> 24)) + +/* + * Accessors for packed IRQ information. + */ + +static inline unsigned int evtchn_from_irq(int irq) +{ + return (u16)(irq_info[irq]); +} + +static inline unsigned int index_from_irq(int irq) +{ + return (u8)(irq_info[irq] >> 16); +} + +static inline unsigned int type_from_irq(int irq) +{ + return (u8)(irq_info[irq] >> 24); +} /* IRQ <-> VIRQ mapping. */ DEFINE_PER_CPU(int, virq_to_irq[NR_VIRQS]); @@ -90,10 +110,13 @@ static u8 cpu_evtchn[NR_EVENT_CHANNELS]; static u8 cpu_evtchn[NR_EVENT_CHANNELS]; static unsigned long cpu_evtchn_mask[NR_CPUS][NR_EVENT_CHANNELS/BITS_PER_LONG]; -#define active_evtchns(cpu,sh,idx) \ - ((sh)->evtchn_pending[idx] & \ - cpu_evtchn_mask[cpu][idx] & \ - ~(sh)->evtchn_mask[idx]) +static inline unsigned long active_evtchns(unsigned int cpu, shared_info_t *sh, + unsigned int idx) +{ + return (sh->evtchn_pending[idx] & + cpu_evtchn_mask[cpu][idx] & + ~sh->evtchn_mask[idx]); +} static void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu) { @@ -109,16 +132,31 @@ static void init_evtchn_cpu_bindings(voi memset(cpu_evtchn_mask[0], ~0, sizeof(cpu_evtchn_mask[0])); } -#define cpu_from_evtchn(evtchn) (cpu_evtchn[evtchn]) +static inline unsigned int cpu_from_evtchn(unsigned int evtchn) +{ + return cpu_evtchn[evtchn]; +} #else -#define active_evtchns(cpu,sh,idx) \ - ((sh)->evtchn_pending[idx] & \ - ~(sh)->evtchn_mask[idx]) -#define bind_evtchn_to_cpu(chn,cpu) ((void)0) -#define init_evtchn_cpu_bindings() ((void)0) -#define cpu_from_evtchn(evtchn) (0) +static inline unsigned long active_evtchns(unsigned int cpu, shared_info_t *sh, + unsigned int idx) +{ + return (sh->evtchn_pending[idx] & ~sh->evtchn_mask[idx]); +} + +static void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu) +{ +} + +static void init_evtchn_cpu_bindings(void) +{ +} + +static inline unsigned int cpu_from_evtchn(unsigned int evtchn) +{ + return 0; +} #endif @@ -132,9 +170,9 @@ static inline void exit_idle(void) {} #include <asm/idle.h> #define IRQ_REG orig_rax #endif -#define do_IRQ(irq, regs) do { \ - (regs)->IRQ_REG = (irq); \ - do_IRQ((regs)); \ +#define do_IRQ(irq, regs) do { \ + (regs)->IRQ_REG = (irq) | (1UL << (BITS_PER_LONG - 1)); \ + do_IRQ((regs)); \ } while (0) #endif diff -r 7e3cbc409676 -r d75a6cc5e68a linux-2.6-xen-sparse/drivers/xen/core/gnttab.c --- a/linux-2.6-xen-sparse/drivers/xen/core/gnttab.c Mon Mar 27 15:36:47 2006 -0700 +++ b/linux-2.6-xen-sparse/drivers/xen/core/gnttab.c Tue Mar 28 08:54:58 2006 -0700 @@ -360,7 +360,7 @@ gnttab_request_free_callback(struct gntt } #ifndef __ia64__ -static int map_pte_fn(pte_t *pte, struct page *pte_page, +static int map_pte_fn(pte_t *pte, struct page *pmd_page, unsigned long addr, void *data) { unsigned long **frames = (unsigned long **)data; @@ -370,7 +370,7 @@ static int map_pte_fn(pte_t *pte, struct return 0; } -static int unmap_pte_fn(pte_t *pte, struct page *pte_page, +static int unmap_pte_fn(pte_t *pte, struct page *pmd_page, unsigned long addr, void *data) { @@ -384,6 +384,7 @@ gnttab_resume(void) { gnttab_setup_table_t setup; unsigned long frames[NR_GRANT_FRAMES]; + int rc; #ifndef __ia64__ void *pframes = frames; struct vm_struct *area; @@ -393,8 +394,8 @@ gnttab_resume(void) setup.nr_frames = NR_GRANT_FRAMES; setup.frame_list = frames; - BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1)); - BUG_ON(setup.status != 0); + rc = HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1); + BUG_ON(rc || setup.status); #ifndef __ia64__ if (shared == NULL) { @@ -402,9 +403,10 @@ gnttab_resume(void) BUG_ON(area == NULL); shared = area->addr; } - BUG_ON(generic_page_range(&init_mm, (unsigned long)shared, - PAGE_SIZE * NR_GRANT_FRAMES, - map_pte_fn, &pframes)); + rc = apply_to_page_range(&init_mm, (unsigned long)shared, + PAGE_SIZE * NR_GRANT_FRAMES, + map_pte_fn, &pframes); + BUG_ON(rc); #else shared = __va(frames[0] << PAGE_SHIFT); printk("grant table at %p\n", shared); @@ -418,9 +420,9 @@ gnttab_suspend(void) { #ifndef __ia64__ - generic_page_range(&init_mm, (unsigned long)shared, - PAGE_SIZE * NR_GRANT_FRAMES, - unmap_pte_fn, NULL); + apply_to_page_range(&init_mm, (unsigned long)shared, + PAGE_SIZE * NR_GRANT_FRAMES, + unmap_pte_fn, NULL); #endif return 0; diff -r 7e3cbc409676 -r d75a6cc5e68a linux-2.6-xen-sparse/drivers/xen/core/reboot.c --- a/linux-2.6-xen-sparse/drivers/xen/core/reboot.c Mon Mar 27 15:36:47 2006 -0700 +++ b/linux-2.6-xen-sparse/drivers/xen/core/reboot.c Tue Mar 28 08:54:58 2006 -0700 @@ -25,9 +25,10 @@ EXPORT_SYMBOL(pm_power_off); EXPORT_SYMBOL(pm_power_off); #endif +extern void ctrl_alt_del(void); + #define SHUTDOWN_INVALID -1 #define SHUTDOWN_POWEROFF 0 -#define SHUTDOWN_REBOOT 1 #define SHUTDOWN_SUSPEND 2 /* Code 3 is SHUTDOWN_CRASH, which we don't use because the domain can only * report a crash, not be instructed to crash! @@ -234,33 +235,19 @@ static int shutdown_process(void *__unus { static char *envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL }; - static char *restart_argv[] = { "/sbin/reboot", NULL }; static char *poweroff_argv[] = { "/sbin/poweroff", NULL }; extern asmlinkage long sys_reboot(int magic1, int magic2, unsigned int cmd, void *arg); - daemonize("shutdown"); - - switch (shutting_down) { - case SHUTDOWN_POWEROFF: - case SHUTDOWN_HALT: + if ((shutting_down == SHUTDOWN_POWEROFF) || + (shutting_down == SHUTDOWN_HALT)) { if (execve("/sbin/poweroff", poweroff_argv, envp) < 0) { sys_reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_POWER_OFF, NULL); } - break; - - case SHUTDOWN_REBOOT: - if (execve("/sbin/reboot", restart_argv, envp) < 0) { - sys_reboot(LINUX_REBOOT_MAGIC1, - LINUX_REBOOT_MAGIC2, - LINUX_REBOOT_CMD_RESTART, - NULL); - } - break; } shutting_down = SHUTDOWN_INVALID; /* could try again */ @@ -331,7 +318,7 @@ static void shutdown_handler(struct xenb if (strcmp(str, "poweroff") == 0) shutting_down = SHUTDOWN_POWEROFF; else if (strcmp(str, "reboot") == 0) - shutting_down = SHUTDOWN_REBOOT; + ctrl_alt_del(); else if (strcmp(str, "suspend") == 0) shutting_down = SHUTDOWN_SUSPEND; else if (strcmp(str, "halt") == 0) @@ -391,8 +378,6 @@ static struct xenbus_watch sysrq_watch = }; #endif -static struct notifier_block xenstore_notifier; - static int setup_shutdown_watcher(struct notifier_block *notifier, unsigned long event, void *data) @@ -420,11 +405,10 @@ static int setup_shutdown_watcher(struct static int __init setup_shutdown_event(void) { - - xenstore_notifier.notifier_call = setup_shutdown_watcher; - + static struct notifier_block xenstore_notifier = { + .notifier_call = setup_shutdown_watcher + }; register_xenstore_notifier(&xenstore_notifier); - return 0; } diff -r 7e3cbc409676 -r d75a6cc5e68a linux-2.6-xen-sparse/drivers/xen/netback/netback.c --- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Mon Mar 27 15:36:47 2006 -0700 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Tue Mar 28 08:54:58 2006 -0700 @@ -331,7 +331,7 @@ static void net_rx_action(unsigned long if (make_rx_response(netif, id, status, (unsigned long)skb->data & ~PAGE_MASK, size, skb->proto_csum_valid ? - NETRXF_csum_valid : 0) && + NETRXF_data_validated : 0) && (rx_notify[irq] == 0)) { rx_notify[irq] = 1; notify_list[notify_nr++] = irq; diff -r 7e3cbc409676 -r d75a6cc5e68a linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Mon Mar 27 15:36:47 2006 -0700 +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Tue Mar 28 08:54:58 2006 -0700 @@ -68,18 +68,12 @@ #define NET_TX_RING_SIZE __RING_SIZE((netif_tx_sring_t *)0, PAGE_SIZE) #define NET_RX_RING_SIZE __RING_SIZE((netif_rx_sring_t *)0, PAGE_SIZE) -#define alloc_xen_skb(_l) __dev_alloc_skb((_l), GFP_ATOMIC|__GFP_NOWARN) - -#define init_skb_shinfo(_skb) \ - do { \ - atomic_set(&(skb_shinfo(_skb)->dataref), 1); \ - skb_shinfo(_skb)->nr_frags = 0; \ - skb_shinfo(_skb)->frag_list = NULL; \ - } while (0) - -static unsigned long rx_pfn_array[NET_RX_RING_SIZE]; -static multicall_entry_t rx_mcl[NET_RX_RING_SIZE+1]; -static mmu_update_t rx_mmu[NET_RX_RING_SIZE]; +static inline void init_skb_shinfo(struct sk_buff *skb) +{ + atomic_set(&(skb_shinfo(skb)->dataref), 1); + skb_shinfo(skb)->nr_frags = 0; + skb_shinfo(skb)->frag_list = NULL; +} struct netfront_info { @@ -134,16 +128,28 @@ struct netfront_info int tx_ring_ref; int rx_ring_ref; u8 mac[ETH_ALEN]; + + unsigned long rx_pfn_array[NET_RX_RING_SIZE]; + multicall_entry_t rx_mcl[NET_RX_RING_SIZE+1]; + mmu_update_t rx_mmu[NET_RX_RING_SIZE]; }; -/* Access macros for acquiring freeing slots in {tx,rx}_skbs[]. */ -#define ADD_ID_TO_FREELIST(_list, _id) \ - (_list)[(_id)] = (_list)[0]; \ - (_list)[0] = (void *)(unsigned long)(_id); -#define GET_ID_FROM_FREELIST(_list) \ - ({ unsigned long _id = (unsigned long)(_list)[0]; \ - (_list)[0] = (_list)[_id]; \ - (unsigned short)_id; }) +/* + * Access macros for acquiring freeing slots in {tx,rx}_skbs[]. + */ + +static inline void add_id_to_freelist(struct sk_buff **list, unsigned short id) +{ + list[id] = list[0]; + list[0] = (void *)(unsigned long)id; +} + +static inline unsigned short get_id_from_freelist(struct sk_buff **list) +{ + unsigned int id = (unsigned int)(unsigned long)list[0]; + list[0] = list[id]; + return id; +} #ifdef DEBUG static char *be_state_name[] = { @@ -484,7 +490,7 @@ static void network_tx_buf_gc(struct net gnttab_release_grant_reference( &np->gref_tx_head, np->grant_tx_ref[id]); np->grant_tx_ref[id] = GRANT_INVALID_REF; - ADD_ID_TO_FREELIST(np->tx_skbs, id); + add_id_to_freelist(np->tx_skbs, id); dev_kfree_skb_irq(skb); } @@ -545,9 +551,10 @@ static void network_alloc_rx_buffers(str * Subtract dev_alloc_skb headroom (16 bytes) and shared info * tailroom then round down to SKB_DATA_ALIGN boundary. */ - skb = alloc_xen_skb( + skb = __dev_alloc_skb( ((PAGE_SIZE - sizeof(struct skb_shared_info)) & - (-SKB_DATA_ALIGN(1))) - 16); + (-SKB_DATA_ALIGN(1))) - 16, + GFP_ATOMIC|__GFP_NOWARN); if (skb == NULL) { /* Any skbuffs queued for refill? Force them out. */ if (i != 0) @@ -576,7 +583,7 @@ static void network_alloc_rx_buffers(str skb->dev = dev; - id = GET_ID_FROM_FREELIST(np->rx_skbs); + id = get_id_from_freelist(np->rx_skbs); np->rx_skbs[id] = skb; @@ -588,13 +595,13 @@ static void network_alloc_rx_buffers(str np->xbdev->otherend_id, __pa(skb->head) >> PAGE_SHIFT); RING_GET_REQUEST(&np->rx, req_prod + i)->gref = ref; - rx_pfn_array[i] = virt_to_mfn(skb->head); + np->rx_pfn_array[i] = virt_to_mfn(skb->head); if (!xen_feature(XENFEAT_auto_translated_physmap)) { /* Remove this page before passing back to Xen. */ set_phys_to_machine(__pa(skb->head) >> PAGE_SHIFT, INVALID_P2M_ENTRY); - MULTI_update_va_mapping(rx_mcl+i, + MULTI_update_va_mapping(np->rx_mcl+i, (unsigned long)skb->head, __pte(0), 0); } @@ -603,7 +610,7 @@ static void network_alloc_rx_buffers(str /* Tell the ballon driver what is going on. */ balloon_update_driver_allowance(i); - reservation.extent_start = rx_pfn_array; + reservation.extent_start = np->rx_pfn_array; reservation.nr_extents = i; reservation.extent_order = 0; reservation.address_bits = 0; @@ -611,19 +618,19 @@ static void network_alloc_rx_buffers(str if (!xen_feature(XENFEAT_auto_translated_physmap)) { /* After all PTEs have been zapped, flush the TLB. */ - rx_mcl[i-1].args[MULTI_UVMFLAGS_INDEX] = + np->rx_mcl[i-1].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_ALL; /* Give away a batch of pages. */ - rx_mcl[i].op = __HYPERVISOR_memory_op; - rx_mcl[i].args[0] = XENMEM_decrease_reservation; - rx_mcl[i].args[1] = (unsigned long)&reservation; + np->rx_mcl[i].op = __HYPERVISOR_memory_op; + np->rx_mcl[i].args[0] = XENMEM_decrease_reservation; + np->rx_mcl[i].args[1] = (unsigned long)&reservation; /* Zap PTEs and give away pages in one big multicall. */ - (void)HYPERVISOR_multicall(rx_mcl, i+1); + (void)HYPERVISOR_multicall(np->rx_mcl, i+1); /* Check return status of HYPERVISOR_memory_op(). */ - if (unlikely(rx_mcl[i].result != i)) + if (unlikely(np->rx_mcl[i].result != i)) panic("Unable to reduce memory reservation\n"); } else if (HYPERVISOR_memory_op(XENMEM_decrease_reservation, @@ -656,7 +663,8 @@ static int network_start_xmit(struct sk_ if (unlikely((((unsigned long)skb->data & ~PAGE_MASK) + skb->len) >= PAGE_SIZE)) { struct sk_buff *nskb; - if (unlikely((nskb = alloc_xen_skb(skb->len)) == NULL)) + nskb = __dev_alloc_skb(skb->len, GFP_ATOMIC|__GFP_NOWARN); + if (unlikely(nskb == NULL)) goto drop; skb_put(nskb, skb->len); memcpy(nskb->data, skb->data, skb->len); @@ -674,7 +682,7 @@ static int network_start_xmit(struct sk_ i = np->tx.req_prod_pvt; - id = GET_ID_FROM_FREELIST(np->tx_skbs); + id = get_id_from_freelist(np->tx_skbs); np->tx_skbs[id] = skb; tx = RING_GET_REQUEST(&np->tx, i); @@ -739,8 +747,8 @@ static int netif_poll(struct net_device struct sk_buff *skb, *nskb; netif_rx_response_t *rx; RING_IDX i, rp; - mmu_update_t *mmu = rx_mmu; - multicall_entry_t *mcl = rx_mcl; + mmu_update_t *mmu = np->rx_mmu; + multicall_entry_t *mcl = np->rx_mcl; int work_done, budget, more_to_do = 1; struct sk_buff_head rxq; unsigned long flags; @@ -796,14 +804,14 @@ static int netif_poll(struct net_device np->grant_rx_ref[rx->id] = GRANT_INVALID_REF; skb = np->rx_skbs[rx->id]; - ADD_ID_TO_FREELIST(np->rx_skbs, rx->id); + add_id_to_freelist(np->rx_skbs, rx->id); /* NB. We handle skb overflow later. */ skb->data = skb->head + rx->offset; skb->len = rx->status; skb->tail = skb->data + skb->len; - if (rx->flags & NETRXF_csum_valid) + if (rx->flags & NETRXF_data_validated) skb->ip_summed = CHECKSUM_UNNECESSARY; np->stats.rx_packets++; @@ -831,14 +839,14 @@ static int netif_poll(struct net_device balloon_update_driver_allowance(-work_done); /* Do all the remapping work, and M2P updates, in one big hypercall. */ - if (likely((mcl - rx_mcl) != 0)) { + if (likely((mcl - np->rx_mcl) != 0)) { mcl->op = __HYPERVISOR_mmu_update; - mcl->args[0] = (unsigned long)rx_mmu; - mcl->args[1] = mmu - rx_mmu; + mcl->args[0] = (unsigned long)np->rx_mmu; + mcl->args[1] = mmu - np->rx_mmu; mcl->args[2] = 0; mcl->args[3] = DOMID_SELF; mcl++; - (void)HYPERVISOR_multicall(rx_mcl, mcl - rx_mcl); + (void)HYPERVISOR_multicall(np->rx_mcl, mcl - np->rx_mcl); } while ((skb = __skb_dequeue(&rxq)) != NULL) { @@ -871,7 +879,8 @@ static int netif_poll(struct net_device 16 - (skb->data - skb->head)); } - nskb = alloc_xen_skb(skb->len + 2); + nskb = __dev_alloc_skb(skb->len + 2, + GFP_ATOMIC|__GFP_NOWARN); if (nskb != NULL) { skb_reserve(nskb, 2); skb_put(nskb, skb->len); diff -r 7e3cbc409676 -r d75a6cc5e68a linux-2.6-xen-sparse/drivers/xen/pciback/passthrough.c --- a/linux-2.6-xen-sparse/drivers/xen/pciback/passthrough.c Mon Mar 27 15:36:47 2006 -0700 +++ b/linux-2.6-xen-sparse/drivers/xen/pciback/passthrough.c Tue Mar 28 08:54:58 2006 -0700 @@ -7,10 +7,13 @@ #include <linux/list.h> #include <linux/pci.h> +#include <linux/spinlock.h> #include "pciback.h" struct passthrough_dev_data { + /* Access to dev_list must be protected by lock */ struct list_head dev_list; + spinlock_t lock; }; struct pci_dev *pciback_get_pci_dev(struct pciback_device *pdev, @@ -19,31 +22,64 @@ struct pci_dev *pciback_get_pci_dev(stru { struct passthrough_dev_data *dev_data = pdev->pci_dev_data; struct pci_dev_entry *dev_entry; + struct pci_dev *dev = NULL; + unsigned long flags; + + spin_lock_irqsave(&dev_data->lock, flags); list_for_each_entry(dev_entry, &dev_data->dev_list, list) { if (domain == (unsigned int)pci_domain_nr(dev_entry->dev->bus) && bus == (unsigned int)dev_entry->dev->bus->number - && devfn == dev_entry->dev->devfn) - return dev_entry->dev; + && devfn == dev_entry->dev->devfn) { + dev = dev_entry->dev; + break; + } } - return NULL; + spin_unlock_irqrestore(&dev_data->lock, flags); + + return dev; } -/* Must hold pciback_device->dev_lock when calling this */ int pciback_add_pci_dev(struct pciback_device *pdev, struct pci_dev *dev) { struct passthrough_dev_data *dev_data = pdev->pci_dev_data; struct pci_dev_entry *dev_entry; + unsigned long flags; dev_entry = kmalloc(sizeof(*dev_entry), GFP_KERNEL); if (!dev_entry) return -ENOMEM; dev_entry->dev = dev; + spin_lock_irqsave(&dev_data->lock, flags); list_add_tail(&dev_entry->list, &dev_data->dev_list); + spin_unlock_irqrestore(&dev_data->lock, flags); return 0; +} + +void pciback_release_pci_dev(struct pciback_device *pdev, struct pci_dev *dev) +{ + struct passthrough_dev_data *dev_data = pdev->pci_dev_data; + struct pci_dev_entry *dev_entry, *t; + struct pci_dev *found_dev = NULL; + unsigned long flags; + + spin_lock_irqsave(&dev_data->lock, flags); + + list_for_each_entry_safe(dev_entry, t, &dev_data->dev_list, list) { + if (dev_entry->dev == dev) { + list_del(&dev_entry->list); + found_dev = dev_entry->dev; + kfree(dev_entry); + } + } + + spin_unlock_irqrestore(&dev_data->lock, flags); + + if (found_dev) + pcistub_put_pci_dev(found_dev); } int pciback_init_devices(struct pciback_device *pdev) @@ -53,6 +89,8 @@ int pciback_init_devices(struct pciback_ dev_data = kmalloc(sizeof(*dev_data), GFP_KERNEL); if (!dev_data) return -ENOMEM; + + spin_lock_init(&dev_data->lock); INIT_LIST_HEAD(&dev_data->dev_list); @@ -70,6 +108,8 @@ int pciback_publish_pci_roots(struct pci struct pci_dev *dev; int found; unsigned int domain, bus; + + spin_lock(&dev_data->lock); list_for_each_entry(dev_entry, &dev_data->dev_list, list) { /* Only publish this device as a root if none of its @@ -96,10 +136,11 @@ int pciback_publish_pci_roots(struct pci } } + spin_unlock(&dev_data->lock); + return err; } -/* Must hold pciback_device->dev_lock when calling this */ void pciback_release_devices(struct pciback_device *pdev) { struct passthrough_dev_data *dev_data = pdev->pci_dev_data; diff -r 7e3cbc409676 -r d75a6cc5e68a linux-2.6-xen-sparse/drivers/xen/pciback/pci_stub.c --- a/linux-2.6-xen-sparse/drivers/xen/pciback/pci_stub.c Mon Mar 27 15:36:47 2006 -0700 +++ b/linux-2.6-xen-sparse/drivers/xen/pciback/pci_stub.c Tue Mar 28 08:54:58 2006 -0700 @@ -7,110 +7,190 @@ #include <linux/init.h> #include <linux/list.h> #include <linux/spinlock.h> +#include <linux/kref.h> #include <asm/atomic.h> #include "pciback.h" static char *pci_devs_to_hide = NULL; module_param_named(hide, pci_devs_to_hide, charp, 0444); -struct pci_stub_device_id { +struct pcistub_device_id { struct list_head slot_list; int domain; unsigned char bus; unsigned int devfn; }; -LIST_HEAD(pci_stub_device_ids); - -struct pci_stub_device { +static LIST_HEAD(pcistub_device_ids); +static DEFINE_SPINLOCK(device_ids_lock); + +struct pcistub_device { + struct kref kref; struct list_head dev_list; + spinlock_t lock; + struct pci_dev *dev; - atomic_t in_use; + struct pciback_device *pdev; /* non-NULL if struct pci_dev is in use */ }; -/* Access to pci_stub_devices & seized_devices lists and the initialize_devices - * flag must be locked with pci_stub_devices_lock +/* Access to pcistub_devices & seized_devices lists and the initialize_devices + * flag must be locked with pcistub_devices_lock */ -DEFINE_SPINLOCK(pci_stub_devices_lock); -LIST_HEAD(pci_stub_devices); +static DEFINE_SPINLOCK(pcistub_devices_lock); +static LIST_HEAD(pcistub_devices); /* wait for device_initcall before initializing our devices * (see pcistub_init_devices_late) */ static int initialize_devices = 0; -LIST_HEAD(seized_devices); - -static inline struct pci_dev *get_pci_dev(struct pci_stub_device *psdev) -{ - if (atomic_dec_and_test(&psdev->in_use)) - return psdev->dev; - else { - atomic_inc(&psdev->in_use); +static LIST_HEAD(seized_devices); + +static struct pcistub_device *pcistub_device_alloc(struct pci_dev *dev) +{ + struct pcistub_device *psdev; + + dev_dbg(&dev->dev, "pcistub_device_alloc\n"); + + psdev = kzalloc(sizeof(*psdev), GFP_ATOMIC); + if (!psdev) return NULL; - } -} - -struct pci_dev *pcistub_get_pci_dev_by_slot(int domain, int bus, + + psdev->dev = pci_dev_get(dev); + if (!psdev->dev) { + kfree(psdev); + return NULL; + } + + kref_init(&psdev->kref); + spin_lock_init(&psdev->lock); + + return psdev; +} + +/* Don't call this directly as it's called by pcistub_device_put */ +static void pcistub_device_release(struct kref *kref) +{ + struct pcistub_device *psdev; + + psdev = container_of(kref, struct pcistub_device, kref); + + dev_dbg(&psdev->dev->dev, "pcistub_device_release\n"); + + /* Clean-up the device */ + pciback_reset_device(psdev->dev); + pciback_config_free(psdev->dev); + kfree(pci_get_drvdata(psdev->dev)); + pci_set_drvdata(psdev->dev, NULL); + + pci_dev_put(psdev->dev); + + kfree(psdev); +} + +static inline void pcistub_device_get(struct pcistub_device *psdev) +{ + kref_get(&psdev->kref); +} + +static inline void pcistub_device_put(struct pcistub_device *psdev) +{ + kref_put(&psdev->kref, pcistub_device_release); +} + +static struct pci_dev *pcistub_device_get_pci_dev(struct pciback_device *pdev, + struct pcistub_device *psdev) +{ + struct pci_dev *pci_dev = NULL; + unsigned long flags; + + pcistub_device_get(psdev); + + spin_lock_irqsave(&psdev->lock, flags); + if (!psdev->pdev) { + psdev->pdev = pdev; + pci_dev = psdev->dev; + } + spin_unlock_irqrestore(&psdev->lock, flags); + + if (!pci_dev) + pcistub_device_put(psdev); + + return pci_dev; +} + +struct pci_dev *pcistub_get_pci_dev_by_slot(struct pciback_device *pdev, + int domain, int bus, int slot, int func) { - struct pci_stub_device *psdev; + struct pcistub_device *psdev; struct pci_dev *found_dev = NULL; - - spin_lock(&pci_stub_devices_lock); - - list_for_each_entry(psdev, &pci_stub_devices, dev_list) { + unsigned long flags; + + spin_lock_irqsave(&pcistub_devices_lock, flags); + + list_for_each_entry(psdev, &pcistub_devices, dev_list) { if (psdev->dev != NULL && domain == pci_domain_nr(psdev->dev->bus) && bus == psdev->dev->bus->number && PCI_DEVFN(slot, func) == psdev->dev->devfn) { - found_dev = get_pci_dev(psdev); + found_dev = pcistub_device_get_pci_dev(pdev, psdev); break; } } - spin_unlock(&pci_stub_devices_lock); + spin_unlock_irqrestore(&pcistub_devices_lock, flags); return found_dev; } -struct pci_dev *pcistub_get_pci_dev(struct pci_dev *dev) -{ - struct pci_stub_device *psdev; +struct pci_dev *pcistub_get_pci_dev(struct pciback_device *pdev, + struct pci_dev *dev) +{ + struct pcistub_device *psdev; struct pci_dev *found_dev = NULL; - - spin_lock(&pci_stub_devices_lock); - - list_for_each_entry(psdev, &pci_stub_devices, dev_list) { + unsigned long flags; + + spin_lock_irqsave(&pcistub_devices_lock, flags); + + list_for_each_entry(psdev, &pcistub_devices, dev_list) { if (psdev->dev == dev) { - found_dev = get_pci_dev(psdev); + found_dev = pcistub_device_get_pci_dev(pdev, psdev); break; } } - spin_unlock(&pci_stub_devices_lock); + spin_unlock_irqrestore(&pcistub_devices_lock, flags); return found_dev; } void pcistub_put_pci_dev(struct pci_dev *dev) { - struct pci_stub_device *psdev; - - spin_lock(&pci_stub_devices_lock); - - list_for_each_entry(psdev, &pci_stub_devices, dev_list) { + struct pcistub_device *psdev, *found_psdev = NULL; + unsigned long flags; + + spin_lock_irqsave(&pcistub_devices_lock, flags); + + list_for_each_entry(psdev, &pcistub_devices, dev_list) { if (psdev->dev == dev) { - /* Cleanup our device - * (so it's ready for the next domain) - */ - pciback_reset_device(psdev->dev); - - atomic_inc(&psdev->in_use); + found_psdev = psdev; break; } } - spin_unlock(&pci_stub_devices_lock); -} - -static int __devinit pcistub_match(struct pci_dev *dev, - struct pci_stub_device_id *pdev_id) + spin_unlock_irqrestore(&pcistub_devices_lock, flags); + + /* Cleanup our device + * (so it's ready for the next domain) + */ + pciback_reset_device(found_psdev->dev); + pciback_config_reset(found_psdev->dev); + + spin_lock_irqsave(&found_psdev->lock, flags); + found_psdev->pdev = NULL; + spin_unlock_irqrestore(&found_psdev->lock, flags); + + pcistub_device_put(found_psdev); +} + +static int __devinit pcistub_match_one(struct pci_dev *dev, + struct pcistub_device_id *pdev_id) { /* Match the specified device by domain, bus, slot, func and also if * any of the device's parent bridges match. @@ -125,23 +205,44 @@ static int __devinit pcistub_match(struc return 0; } +static int __devinit pcistub_match(struct pci_dev *dev) +{ + struct pcistub_device_id *pdev_id; + unsigned long flags; + int found = 0; + + spin_lock_irqsave(&device_ids_lock, flags); + list_for_each_entry(pdev_id, &pcistub_device_ids, slot_list) { + if (pcistub_match_one(dev, pdev_id)) { + found = 1; + break; + } + } + spin_unlock_irqrestore(&device_ids_lock, flags); + + return found; +} + static int __devinit pcistub_init_device(struct pci_dev *dev) { struct pciback_dev_data *dev_data; int err = 0; + + dev_dbg(&dev->dev, "initializing...\n"); /* The PCI backend is not intended to be a module (or to work with * removable PCI devices (yet). If it were, pciback_config_free() * would need to be called somewhere to free the memory allocated * here and then to call kfree(pci_get_drvdata(psdev->dev)). */ - dev_data = kmalloc(sizeof(*dev_data), GFP_KERNEL); + dev_data = kmalloc(sizeof(*dev_data), GFP_ATOMIC); if (!dev_data) { err = -ENOMEM; goto out; } pci_set_drvdata(dev, dev_data); + dev_dbg(&dev->dev, "initializing config\n"); err = pciback_config_init(dev); if (err) goto out; @@ -153,14 +254,15 @@ static int __devinit pcistub_init_device * This makes the assumption that the device's resources won't * change after this point (otherwise this code may break!) */ + dev_dbg(&dev->dev, "enabling device\n"); err = pci_enable_device(dev); if (err) goto config_release; /* Now disable the device (this also ensures some private device * data is setup before we export) - * This calls pciback_config_reset(dev) - */ + */ + dev_dbg(&dev->dev, "reset device\n"); pciback_reset_device(dev); return 0; @@ -182,60 +284,82 @@ static int __devinit pcistub_init_device */ static int __init pcistub_init_devices_late(void) { - struct pci_stub_device *psdev, *t; + struct pcistub_device *psdev; + unsigned long flags; int err = 0; - spin_lock(&pci_stub_devices_lock); - - list_for_each_entry_safe(psdev, t, &seized_devices, dev_list) { + pr_debug("pciback: pcistub_init_devices_late\n"); + + spin_lock_irqsave(&pcistub_devices_lock, flags); + + while (!list_empty(&seized_devices)) { + psdev = container_of(seized_devices.next, + struct pcistub_device, dev_list); list_del(&psdev->dev_list); + + spin_unlock_irqrestore(&pcistub_devices_lock, flags); + err = pcistub_init_device(psdev->dev); if (err) { - printk(KERN_ERR - "pciback: %s error %d initializing device\n", - pci_name(psdev->dev), err); + dev_err(&psdev->dev->dev, + "error %d initializing device\n", err); kfree(psdev); - continue; - } - - list_add_tail(&psdev->dev_list, &pci_stub_devices); + psdev = NULL; + } + + spin_lock_irqsave(&pcistub_devices_lock, flags); + + if (psdev) + list_add_tail(&psdev->dev_list, &pcistub_devices); } initialize_devices = 1; - spin_unlock(&pci_stub_devices_lock); + spin_unlock_irqrestore(&pcistub_devices_lock, flags); return 0; } static int __devinit pcistub_seize(struct pci_dev *dev) { - struct pci_stub_device *psdev; + struct pcistub_device *psdev; + unsigned long flags; + int initialize_devices_copy; int err = 0; - psdev = kmalloc(sizeof(*psdev), GFP_KERNEL); + psdev = pcistub_device_alloc(dev); if (!psdev) return -ENOMEM; - psdev->dev = dev; - atomic_set(&psdev->in_use, 1); - - spin_lock(&pci_stub_devices_lock); - - if (initialize_devices) { + /* initialize_devices has to be accessed under a spin lock. But since + * it can only change from 0 -> 1, if it's already 1, we don't have to + * worry about it changing. That's why we can take a *copy* of + * initialize_devices and wait till we're outside of the lock to + * check if it's 1 (don't ever check if it's 0 outside of the lock) + */ + spin_lock_irqsave(&pcistub_devices_lock, flags); + + initialize_devices_copy = initialize_devices; + + if (!initialize_devices_copy) { + dev_dbg(&dev->dev, "deferring initialization\n"); + list_add(&psdev->dev_list, &seized_devices); + } + + spin_unlock_irqrestore(&pcistub_devices_lock, flags); + + if (initialize_devices_copy) { + /* don't want irqs disabled when calling pcistub_init_device */ err = pcistub_init_device(psdev->dev); if (err) goto out; - list_add(&psdev->dev_list, &pci_stub_devices); - } else - list_add(&psdev->dev_list, &seized_devices); + list_add(&psdev->dev_list, &pcistub_devices); + } out: - spin_unlock(&pci_stub_devices_lock); - if (err) - kfree(psdev); + pcistub_device_put(psdev); return err; } @@ -243,47 +367,78 @@ static int __devinit pcistub_probe(struc static int __devinit pcistub_probe(struct pci_dev *dev, const struct pci_device_id *id) { - struct pci_stub_device_id *pdev_id; - struct pci_dev *seized_dev; int err = 0; - list_for_each_entry(pdev_id, &pci_stub_device_ids, slot_list) { - - if (!pcistub_match(dev, pdev_id)) - continue; + dev_dbg(&dev->dev, "probing...\n"); + + if (pcistub_match(dev)) { if (dev->hdr_type != PCI_HEADER_TYPE_NORMAL && dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) { - printk(KERN_ERR - "pciback: %s: can't export pci devices that " - "don't have a normal (0) or bridge (1) " - "header type!\n", pci_name(dev)); + dev_err(&dev->dev, "can't export pci devices that " + "don't have a normal (0) or bridge (1) " + "header type!\n"); + err = -ENODEV; + goto out; + } + + dev_info(&dev->dev, "seizing device\n"); + err = pcistub_seize(dev); + } else + /* Didn't find the device */ + err = -ENODEV; + + out: + return err; +} + +static void pcistub_remove(struct pci_dev *dev) +{ + struct pcistub_device *psdev, *found_psdev = NULL; + unsigned long flags; + + dev_dbg(&dev->dev, "removing\n"); + + spin_lock_irqsave(&pcistub_devices_lock, flags); + + list_for_each_entry(psdev, &pcistub_devices, dev_list) { + if (psdev->dev == dev) { + found_psdev = psdev; break; } - - pr_info("pciback: seizing PCI device %s\n", pci_name(dev)); - seized_dev = pci_dev_get(dev); - - if (seized_dev) { - err = pcistub_seize(seized_dev); - if (err) { - pci_dev_put(dev); - goto out; - } - - /* Success! */ - goto out; - } - } - - /* Didn't find the device */ - err = -ENODEV; - - out: - return err; -} - -struct pci_device_id pcistub_ids[] = { + } + + spin_unlock_irqrestore(&pcistub_devices_lock, flags); + + if (found_psdev) { + dev_dbg(&dev->dev, "found device to remove - in use? %p\n", + found_psdev->pdev); + + if (found_psdev->pdev) { + printk(KERN_WARNING "pciback: ****** removing device " + "%s while still in-use! ******\n", + pci_name(found_psdev->dev)); + printk(KERN_WARNING "pciback: ****** driver domain may " + "still access this device's i/o resources!\n"); + printk(KERN_WARNING "pciback: ****** shutdown driver " + "domain before binding device\n"); + printk(KERN_WARNING "pciback: ****** to other drivers " + "or domains\n"); + + pciback_release_pci_dev(found_psdev->pdev, + found_psdev->dev); + } + + spin_lock_irqsave(&pcistub_devices_lock, flags); + list_del(&found_psdev->dev_list); + spin_unlock_irqrestore(&pcistub_devices_lock, flags); + + /* the final put for releasing from the list */ + pcistub_device_put(found_psdev); + } +} + +static struct pci_device_id pcistub_ids[] = { { .vendor = PCI_ANY_ID, .device = PCI_ANY_ID, @@ -298,16 +453,152 @@ struct pci_device_id pcistub_ids[] = { * for a normal device. I don't want it to be loaded automatically. */ -struct pci_driver pciback_pci_driver = { +static struct pci_driver pciback_pci_driver = { .name = "pciback", .id_table = pcistub_ids, .probe = pcistub_probe, + .remove = pcistub_remove, }; +static inline int str_to_slot(const char *buf, int *domain, int *bus, + int *slot, int *func) +{ + int err; + + err = sscanf(buf, " %x:%x:%x.%x", domain, bus, slot, func); + if (err == 4) + return 0; + else if (err < 0) + return -EINVAL; + + /* try again without domain */ + *domain = 0; + err = sscanf(buf, " %x:%x.%x", bus, slot, func); + if (err == 3) + return 0; + + return -EINVAL; +} + +static int pcistub_device_id_add(int domain, int bus, int slot, int func) +{ + struct pcistub_device_id *pci_dev_id; + unsigned long flags; + + pci_dev_id = kmalloc(sizeof(*pci_dev_id), GFP_KERNEL); + if (!pci_dev_id) + return -ENOMEM; + + pci_dev_id->domain = domain; + pci_dev_id->bus = bus; + pci_dev_id->devfn = PCI_DEVFN(slot, func); + + pr_debug("pciback: wants to seize %04x:%02x:%02x.%01x\n", + domain, bus, slot, func); + + spin_lock_irqsave(&device_ids_lock, flags); + list_add_tail(&pci_dev_id->slot_list, &pcistub_device_ids); + spin_unlock_irqrestore(&device_ids_lock, flags); + + return 0; +} + +static int pcistub_device_id_remove(int domain, int bus, int slot, int func) +{ + struct pcistub_device_id *pci_dev_id, *t; + int devfn = PCI_DEVFN(slot, func); + int err = -ENOENT; + unsigned long flags; + + spin_lock_irqsave(&device_ids_lock, flags); + list_for_each_entry_safe(pci_dev_id, t, &pcistub_device_ids, slot_list) { + + if (pci_dev_id->domain == domain + && pci_dev_id->bus == bus && pci_dev_id->devfn == devfn) { + /* Don't break; here because it's possible the same + * slot could be in the list more than once + */ + list_del(&pci_dev_id->slot_list); + kfree(pci_dev_id); + + err = 0; + + pr_debug("pciback: removed %04x:%02x:%02x.%01x from " + "seize list\n", domain, bus, slot, func); + } + } + spin_unlock_irqrestore(&device_ids_lock, flags); + + return err; +} + +static ssize_t pcistub_slot_add(struct device_driver *drv, const char *buf, + size_t count) +{ + int domain, bus, slot, func; + int err; + + err = str_to_slot(buf, &domain, &bus, &slot, &func); + if (err) + goto out; + + err = pcistub_device_id_add(domain, bus, slot, func); + + out: + if (!err) + err = count; + return err; +} + +DRIVER_ATTR(new_slot, S_IWUSR, NULL, pcistub_slot_add); + +static ssize_t pcistub_slot_remove(struct device_driver *drv, const char *buf, + size_t count) +{ + int domain, bus, slot, func; + int err; + + err = str_to_slot(buf, &domain, &bus, &slot, &func); + if (err) + goto out; + + err = pcistub_device_id_remove(domain, bus, slot, func); + + out: + if (!err) + err = count; + return err; +} + +DRIVER_ATTR(remove_slot, S_IWUSR, NULL, pcistub_slot_remove); + +static ssize_t pcistub_slot_show(struct device_driver *drv, char *buf) +{ + struct pcistub_device_id *pci_dev_id; + size_t count = 0; + unsigned long flags; + + spin_lock_irqsave(&device_ids_lock, flags); + list_for_each_entry(pci_dev_id, &pcistub_device_ids, slot_list) { + if (count >= PAGE_SIZE) + break; + + count += scnprintf(buf + count, PAGE_SIZE - count, + "%04x:%02x:%02x.%01x\n", + pci_dev_id->domain, pci_dev_id->bus, + PCI_SLOT(pci_dev_id->devfn), + PCI_FUNC(pci_dev_id->devfn)); + } + spin_unlock_irqrestore(&device_ids_lock, flags); + + return count; +} + +DRIVER_ATTR(slots, S_IRUSR, pcistub_slot_show, NULL); + static int __init pcistub_init(void) { int pos = 0; - struct pci_stub_device_id *pci_dev_id; int err = 0; int domain, bus, slot, func; int parsed; @@ -328,33 +619,27 @@ static int __init pcistub_init(void) goto parse_error; } - pci_dev_id = kmalloc(sizeof(*pci_dev_id), GFP_KERNEL); - if (!pci_dev_id) { - err = -ENOMEM; + err = pcistub_device_id_add(domain, bus, slot, func); + if (err) goto out; - } - - pci_dev_id->domain = domain; - pci_dev_id->bus = bus; - pci_dev_id->devfn = PCI_DEVFN(slot, func); - - pr_debug - ("pciback: wants to seize %04x:%02x:%02x.%01x\n", - domain, bus, slot, func); - - list_add_tail(&pci_dev_id->slot_list, - &pci_stub_device_ids); /* if parsed<=0, we've reached the end of the string */ pos += parsed; } while (parsed > 0 && pci_devs_to_hide[pos]); - - /* If we're the first PCI Device Driver to register, we're the - * first one to get offered PCI devices as they become - * available (and thus we can be the first to grab them) - */ - pci_register_driver(&pciback_pci_driver); - } + } + + /* If we're the first PCI Device Driver to register, we're the + * first one to get offered PCI devices as they become + * available (and thus we can be the first to grab them) + */ + err = pci_register_driver(&pciback_pci_driver); + if (err < 0) + goto out; + + driver_create_file(&pciback_pci_driver.driver, &driver_attr_new_slot); + driver_create_file(&pciback_pci_driver.driver, + &driver_attr_remove_slot); + driver_create_file(&pciback_pci_driver.driver, &driver_attr_slots); out: return err; @@ -386,19 +671,22 @@ static int __init pciback_init(void) return err; #endif - if (list_empty(&pci_stub_device_ids)) - return -ENODEV; pcistub_init_devices_late(); pciback_xenbus_register(); - __unsafe(THIS_MODULE); - return 0; } -static void pciback_cleanup(void) -{ - BUG(); +static void __exit pciback_cleanup(void) +{ + pciback_xenbus_unregister(); + + driver_remove_file(&pciback_pci_driver.driver, &driver_attr_new_slot); + driver_remove_file(&pciback_pci_driver.driver, + &driver_attr_remove_slot); + driver_remove_file(&pciback_pci_driver.driver, &driver_attr_slots); + + pci_unregister_driver(&pciback_pci_driver); } module_init(pciback_init); diff -r 7e3cbc409676 -r d75a6cc5e68a linux-2.6-xen-sparse/drivers/xen/pciback/pciback.h --- a/linux-2.6-xen-sparse/drivers/xen/pciback/pciback.h Mon Mar 27 15:36:47 2006 -0700 +++ b/linux-2.6-xen-sparse/drivers/xen/pciback/pciback.h Tue Mar 28 08:54:58 2006 -0700 @@ -37,9 +37,11 @@ struct pciback_dev_data { }; /* Get/Put PCI Devices that are hidden from the PCI Backend Domain */ -struct pci_dev *pcistub_get_pci_dev_by_slot(int domain, int bus, +struct pci_dev *pcistub_get_pci_dev_by_slot(struct pciback_device *pdev, + int domain, int bus, int slot, int func); -struct pci_dev *pcistub_get_pci_dev(struct pci_dev *dev); +struct pci_dev *pcistub_get_pci_dev(struct pciback_device *pdev, + struct pci_dev *dev); void pcistub_put_pci_dev(struct pci_dev *dev); /* Ensure a device is turned off or reset */ @@ -57,6 +59,7 @@ typedef int (*publish_pci_root_cb) (stru typedef int (*publish_pci_root_cb) (struct pciback_device * pdev, unsigned int domain, unsigned int bus); int pciback_add_pci_dev(struct pciback_device *pdev, struct pci_dev *dev); +void pciback_release_pci_dev(struct pciback_device *pdev, struct pci_dev *dev); struct pci_dev *pciback_get_pci_dev(struct pciback_device *pdev, unsigned int domain, unsigned int bus, unsigned int devfn); @@ -69,6 +72,7 @@ irqreturn_t pciback_handle_event(int irq irqreturn_t pciback_handle_event(int irq, void *dev_id, struct pt_regs *regs); int pciback_xenbus_register(void); +void pciback_xenbus_unregister(void); extern int verbose_request; #endif diff -r 7e3cbc409676 -r d75a6cc5e68a linux-2.6-xen-sparse/drivers/xen/pciback/pciback_ops.c --- a/linux-2.6-xen-sparse/drivers/xen/pciback/pciback_ops.c Mon Mar 27 15:36:47 2006 -0700 +++ b/linux-2.6-xen-sparse/drivers/xen/pciback/pciback_ops.c Tue Mar 28 08:54:58 2006 -0700 @@ -12,9 +12,8 @@ module_param(verbose_request, int, 0644) module_param(verbose_request, int, 0644); /* Ensure a device is "turned off" and ready to be exported. - * This also sets up the device's private data to keep track of what should - * be in the base address registers (BARs) so that we can keep the - * client from manipulating them directly. + * (Also see pciback_config_reset to ensure virtual configuration space is + * ready to be re-exported) */ void pciback_reset_device(struct pci_dev *dev) { diff -r 7e3cbc409676 -r d75a6cc5e68a linux-2.6-xen-sparse/drivers/xen/pciback/vpci.c --- a/linux-2.6-xen-sparse/drivers/xen/pciback/vpci.c Mon Mar 27 15:36:47 2006 -0700 +++ b/linux-2.6-xen-sparse/drivers/xen/pciback/vpci.c Tue Mar 28 08:54:58 2006 -0700 @@ -8,12 +8,15 @@ #include <linux/list.h> #include <linux/slab.h> #include <linux/pci.h> +#include <linux/spinlock.h> #include "pciback.h" #define PCI_SLOT_MAX 32 struct vpci_dev_data { + /* Access to dev_list must be protected by lock */ struct list_head dev_list[PCI_SLOT_MAX]; + spinlock_t lock; }; static inline struct list_head *list_first(struct list_head *head) @@ -25,25 +28,29 @@ struct pci_dev *pciback_get_pci_dev(stru unsigned int domain, unsigned int bus, unsigned int devfn) { - struct pci_dev_entry *dev_entry; - struct vpci_dev_data *vpci_dev = pdev->pci_dev_data; + struct pci_dev_entry *entry; + struct pci_dev *dev = NULL; + struct vpci_dev_data *vpci_dev = pdev->pci_dev_data; + unsigned long flags; if (domain != 0 || bus != 0) return NULL; if (PCI_SLOT(devfn) < PCI_SLOT_MAX) { - /* we don't need to lock the list here because once the backend - * is in operation, it won't have any more devices addeded - * (or removed). - */ - list_for_each_entry(dev_entry, + spin_lock_irqsave(&vpci_dev->lock, flags); + + list_for_each_entry(entry, &vpci_dev->dev_list[PCI_SLOT(devfn)], list) { - if (PCI_FUNC(dev_entry->dev->devfn) == PCI_FUNC(devfn)) - return dev_entry->dev; - } - } - return NULL; + if (PCI_FUNC(entry->dev->devfn) == PCI_FUNC(devfn)) { + dev = entry->dev; + break; + } + } + + spin_unlock_irqrestore(&vpci_dev->lock, flags); + } + return dev; } static inline int match_slot(struct pci_dev *l, struct pci_dev *r) @@ -55,12 +62,12 @@ static inline int match_slot(struct pci_ return 0; } -/* Must hold pciback_device->dev_lock when calling this */ int pciback_add_pci_dev(struct pciback_device *pdev, struct pci_dev *dev) { int err = 0, slot; struct pci_dev_entry *t, *dev_entry; struct vpci_dev_data *vpci_dev = pdev->pci_dev_data; + unsigned long flags; if ((dev->class >> 24) == PCI_BASE_CLASS_BRIDGE) { err = -EFAULT; @@ -78,6 +85,8 @@ int pciback_add_pci_dev(struct pciback_d } dev_entry->dev = dev; + + spin_lock_irqsave(&vpci_dev->lock, flags); /* Keep multi-function devices together on the virtual PCI bus */ for (slot = 0; slot < PCI_SLOT_MAX; slot++) { @@ -92,7 +101,7 @@ int pciback_add_pci_dev(struct pciback_d PCI_FUNC(dev->devfn)); list_add_tail(&dev_entry->list, &vpci_dev->dev_list[slot]); - goto out; + goto unlock; } } } @@ -105,7 +114,7 @@ int pciback_add_pci_dev(struct pciback_d pci_name(dev), slot); list_add_tail(&dev_entry->list, &vpci_dev->dev_list[slot]); - goto out; + goto unlock; } } @@ -113,8 +122,39 @@ int pciback_add_pci_dev(struct pciback_d xenbus_dev_fatal(pdev->xdev, err, "No more space on root virtual PCI bus"); + unlock: + spin_unlock_irqrestore(&vpci_dev->lock, flags); out: return err; +} + +void pciback_release_pci_dev(struct pciback_device *pdev, struct pci_dev *dev) +{ + int slot; + struct vpci_dev_data *vpci_dev = pdev->pci_dev_data; + struct pci_dev *found_dev = NULL; + unsigned long flags; + + spin_lock_irqsave(&vpci_dev->lock, flags); + + for (slot = 0; slot < PCI_SLOT_MAX; slot++) { + struct pci_dev_entry *e, *tmp; + list_for_each_entry_safe(e, tmp, &vpci_dev->dev_list[slot], + list) { + if (e->dev == dev) { + list_del(&e->list); + found_dev = e->dev; + kfree(e); + goto out; + } + } + } + + out: + spin_unlock_irqrestore(&vpci_dev->lock, flags); + + if (found_dev) + pcistub_put_pci_dev(found_dev); } int pciback_init_devices(struct pciback_device *pdev) @@ -126,6 +166,8 @@ int pciback_init_devices(struct pciback_ if (!vpci_dev) return -ENOMEM; + spin_lock_init(&vpci_dev->lock); + for (slot = 0; slot < PCI_SLOT_MAX; slot++) { INIT_LIST_HEAD(&vpci_dev->dev_list[slot]); } @@ -142,7 +184,6 @@ int pciback_publish_pci_roots(struct pci return publish_cb(pdev, 0, 0); } -/* Must hold pciback_device->dev_lock when calling this */ void pciback_release_devices(struct pciback_device *pdev) { int slot; diff -r 7e3cbc409676 -r d75a6cc5e68a linux-2.6-xen-sparse/drivers/xen/pciback/xenbus.c --- a/linux-2.6-xen-sparse/drivers/xen/pciback/xenbus.c Mon Mar 27 15:36:47 2006 -0700 +++ b/linux-2.6-xen-sparse/drivers/xen/pciback/xenbus.c Tue Mar 28 08:54:58 2006 -0700 @@ -12,7 +12,7 @@ #define INVALID_EVTCHN_IRQ (-1) -struct pciback_device *alloc_pdev(struct xenbus_device *xdev) +static struct pciback_device *alloc_pdev(struct xenbus_device *xdev) { struct pciback_device *pdev; @@ -38,7 +38,7 @@ struct pciback_device *alloc_pdev(struct return pdev; } -void free_pdev(struct pciback_device *pdev) +static void free_pdev(struct pciback_device *pdev) { if (pdev->be_watching) unregister_xenbus_watch(&pdev->be_watch); @@ -247,7 +247,7 @@ static int pciback_export_device(struct dev_dbg(&pdev->xdev->dev, "exporting dom %x bus %x slot %x func %x\n", domain, bus, slot, func); - dev = pcistub_get_pci_dev_by_slot(domain, bus, slot, func); + dev = pcistub_get_pci_dev_by_slot(pdev, domain, bus, slot, func); if (!dev) { err = -EINVAL; xenbus_dev_fatal(pdev->xdev, err, @@ -434,3 +434,8 @@ int __init pciback_xenbus_register(void) { return xenbus_register_backend(&xenbus_pciback_driver); } + +void __exit pciback_xenbus_unregister(void) +{ + xenbus_unregister_driver(&xenbus_pciback_driver); +} diff -r 7e3cbc409676 -r d75a6cc5e68a linux-2.6-xen-sparse/drivers/xen/pcifront/pci_op.c --- a/linux-2.6-xen-sparse/drivers/xen/pcifront/pci_op.c Mon Mar 27 15:36:47 2006 -0700 +++ b/linux-2.6-xen-sparse/drivers/xen/pcifront/pci_op.c Tue Mar 28 08:54:58 2006 -0700 @@ -56,19 +56,19 @@ static int do_pci_op(struct pcifront_dev notify_remote_via_evtchn(port); /* - * We set a poll timeout of 5 seconds but give up on return after - * 4 seconds. It is better to time out too late rather than too early + * We set a poll timeout of 3 seconds but give up on return after + * 2 seconds. It is better to time out too late rather than too early * (in the latter case we end up continually re-executing poll() with a * timeout in the past). 1s difference gives plenty of slack for error. */ do_gettimeofday(&tv); - ns_timeout = timeval_to_ns(&tv) + 4 * (nsec_t)NSEC_PER_SEC; + ns_timeout = timeval_to_ns(&tv) + 2 * (nsec_t)NSEC_PER_SEC; clear_evtchn(port); while (test_bit(_XEN_PCIF_active, (unsigned long *)&pdev->sh_info->flags)) { - if (HYPERVISOR_poll(&port, 1, jiffies + 5*HZ)) + if (HYPERVISOR_poll(&port, 1, jiffies + 3*HZ)) BUG(); clear_evtchn(port); do_gettimeofday(&tv); @@ -173,7 +173,7 @@ static void pcifront_claim_resource(stru if (!r->parent && r->start && r->flags) { dev_dbg(&pdev->xdev->dev, "claiming resource %s/%d\n", - pci_name(dev), i); + pci_name(dev), i); pci_claim_resource(dev, i); } } @@ -234,25 +234,38 @@ int pcifront_scan_root(struct pcifront_d return err; } +static void free_root_bus_devs(struct pci_bus *bus) +{ + struct pci_dev *dev; + + spin_lock(&pci_bus_lock); + while (!list_empty(&bus->devices)) { + dev = container_of(bus->devices.next, struct pci_dev, bus_list); + spin_unlock(&pci_bus_lock); + + dev_dbg(&dev->dev, "removing device\n"); + pci_remove_bus_device(dev); + + spin_lock(&pci_bus_lock); + } + spin_unlock(&pci_bus_lock); +} + void pcifront_free_roots(struct pcifront_device *pdev) { struct pci_bus_entry *bus_entry, *t; + dev_dbg(&pdev->xdev->dev, "cleaning up root buses\n"); + list_for_each_entry_safe(bus_entry, t, &pdev->root_buses, list) { - /* TODO: Removing a PCI Bus is untested (as it normally - * just goes away on domain shutdown) - */ list_del(&bus_entry->list); - spin_lock(&pci_bus_lock); - list_del(&bus_entry->bus->node); - spin_unlock(&pci_bus_lock); + free_root_bus_devs(bus_entry->bus); kfree(bus_entry->bus->sysdata); device_unregister(bus_entry->bus->bridge); - - /* Do we need to free() the bus itself? */ + pci_remove_bus(bus_entry->bus); kfree(bus_entry); } diff -r 7e3cbc409676 -r d75a6cc5e68a linux-2.6-xen-sparse/drivers/xen/pcifront/xenbus.c --- a/linux-2.6-xen-sparse/drivers/xen/pcifront/xenbus.c Mon Mar 27 15:36:47 2006 -0700 +++ b/linux-2.6-xen-sparse/drivers/xen/pcifront/xenbus.c Tue Mar 28 08:54:58 2006 -0700 @@ -50,6 +50,8 @@ static void free_pdev(struct pcifront_de { dev_dbg(&pdev->xdev->dev, "freeing pdev @ 0x%p\n", pdev); + pcifront_free_roots(pdev); + if (pdev->evtchn != INVALID_EVTCHN) xenbus_free_evtchn(pdev->xdev, pdev->evtchn); diff -r 7e3cbc409676 -r d75a6cc5e68a linux-2.6-xen-sparse/drivers/xen/util.c --- a/linux-2.6-xen-sparse/drivers/xen/util.c Mon Mar 27 15:36:47 2006 -0700 +++ b/linux-2.6-xen-sparse/drivers/xen/util.c Tue Mar 28 08:54:58 2006 -0700 @@ -6,9 +6,9 @@ #include <asm/uaccess.h> #include <xen/driver_util.h> -static int f(pte_t *pte, struct page *pte_page, unsigned long addr, void *data) +static int f(pte_t *pte, struct page *pmd_page, unsigned long addr, void *data) { - /* generic_page_range() does all the hard work. */ + /* apply_to_page_range() does all the hard work. */ return 0; } @@ -24,8 +24,8 @@ struct vm_struct *alloc_vm_area(unsigned * This ensures that page tables are constructed for this region * of kernel virtual address space and mapped into init_mm. */ - if (generic_page_range(&init_mm, (unsigned long)area->addr, - area->size, f, NULL)) { + if (apply_to_page_range(&init_mm, (unsigned long)area->addr, + area->size, f, NULL)) { free_vm_area(area); return NULL; } diff -r 7e3cbc409676 -r d75a6cc5e68a linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Mon Mar 27 15:36:47 2006 -0700 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Tue Mar 28 08:54:58 2006 -0700 @@ -1039,8 +1039,7 @@ static int __init xenbus_probe_init(void xsd_port_intf = create_xen_proc_entry("xsd_port", 0400); if (xsd_port_intf) xsd_port_intf->read_proc = xsd_port_read; - } - else + } else xenstored_ready = 1; /* Initialize the interface to xenstore. */ diff -r 7e3cbc409676 -r d75a6cc5e68a linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/processor.h --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/processor.h Mon Mar 27 15:36:47 2006 -0700 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/processor.h Tue Mar 28 08:54:58 2006 -0700 @@ -146,7 +146,7 @@ static inline void detect_ht(struct cpui */ static inline void cpuid(unsigned int op, unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx) { - __asm__("cpuid" + __asm__(XEN_CPUID : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), @@ -158,7 +158,7 @@ static inline void cpuid_count(int op, i static inline void cpuid_count(int op, int count, int *eax, int *ebx, int *ecx, int *edx) { - __asm__("cpuid" + __asm__(XEN_CPUID : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), @@ -173,7 +173,7 @@ static inline unsigned int cpuid_eax(uns { unsigned int eax; - __asm__("cpuid" + __asm__(XEN_CPUID : "=a" (eax) : "0" (op) : "bx", "cx", "dx"); @@ -183,7 +183,7 @@ static inline unsigned int cpuid_ebx(uns { unsigned int eax, ebx; - __asm__("cpuid" + __asm__(XEN_CPUID : "=a" (eax), "=b" (ebx) : "0" (op) : "cx", "dx" ); @@ -193,7 +193,7 @@ static inline unsigned int cpuid_ecx(uns { unsigned int eax, ecx; - __asm__("cpuid" + __asm__(XEN_CPUID : "=a" (eax), "=c" (ecx) : "0" (op) : "bx", "dx" ); @@ -203,7 +203,7 @@ static inline unsigned int cpuid_edx(uns { unsigned int eax, edx; - __asm__("cpuid" + __asm__(XEN_CPUID : "=a" (eax), "=d" (edx) : "0" (op) : "bx", "cx"); @@ -237,20 +237,11 @@ extern unsigned long mmu_cr4_features; static inline void set_in_cr4 (unsigned long mask) { + unsigned cr4; mmu_cr4_features |= mask; - switch (mask) { - case X86_CR4_OSFXSR: - case X86_CR4_OSXMMEXCPT: - break; - default: - do { - const char *msg = "Xen unsupported cr4 update\n"; - (void)HYPERVISOR_console_io( - CONSOLEIO_write, __builtin_strlen(msg), - (char *)msg); - BUG(); - } while (0); - } + cr4 = read_cr4(); + cr4 |= mask; + write_cr4(cr4); } static inline void clear_in_cr4 (unsigned long mask) diff -r 7e3cbc409676 -r d75a6cc5e68a linux-2.6-xen-sparse/include/asm-i386/mach-xen/setup_arch_post.h --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/setup_arch_post.h Mon Mar 27 15:36:47 2006 -0700 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/setup_arch_post.h Tue Mar 28 08:54:58 2006 -0700 @@ -14,18 +14,6 @@ static char * __init machine_specific_me add_memory_region(0, PFN_PHYS(max_pfn), E820_RAM); return "Xen"; -} - -void __devinit machine_specific_modify_cpu_capabilities(struct cpuinfo_x86 *c) -{ - clear_bit(X86_FEATURE_VME, c->x86_capability); - clear_bit(X86_FEATURE_DE, c->x86_capability); - clear_bit(X86_FEATURE_PSE, c->x86_capability); - clear_bit(X86_FEATURE_PGE, c->x86_capability); - clear_bit(X86_FEATURE_SEP, c->x86_capability); - if (!(xen_start_info->flags & SIF_PRIVILEGED)) - clear_bit(X86_FEATURE_MTRR, c->x86_capability); - c->hlt_works_ok = 0; } extern void hypervisor_callback(void); @@ -51,8 +39,6 @@ static void __init machine_specific_arch cb.handler_address = (unsigned long)&nmi; HYPERVISOR_nmi_op(XENNMI_register_callback, &cb); - machine_specific_modify_cpu_capabilities(&boot_cpu_data); - if (HYPERVISOR_xen_version(XENVER_platform_parameters, &pp) == 0) set_fixaddr_top(pp.virt_start - PAGE_SIZE); diff -r 7e3cbc409676 -r d75a6cc5e68a linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/processor.h --- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/processor.h Mon Mar 27 15:36:47 2006 -0700 +++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/processor.h Tue Mar 28 08:54:58 2006 -0700 @@ -141,31 +141,21 @@ static inline void set_in_cr4 (unsigned static inline void set_in_cr4 (unsigned long mask) { mmu_cr4_features |= mask; - switch (mask) { - case X86_CR4_OSFXSR: - case X86_CR4_OSXMMEXCPT: - break; - default: - do { - const char *msg = "Xen unsupported cr4 update\n"; - (void)HYPERVISOR_console_io( - CONSOLEIO_write, __builtin_strlen(msg), - (char *)msg); - BUG(); - } while (0); - } + __asm__("movq %%cr4,%%rax\n\t" + "orq %0,%%rax\n\t" + "movq %%rax,%%cr4\n" + : : "irg" (mask) + :"ax"); } static inline void clear_in_cr4 (unsigned long mask) { -#ifndef CONFIG_XEN mmu_cr4_features &= ~mask; __asm__("movq %%cr4,%%rax\n\t" "andq %0,%%rax\n\t" "movq %%rax,%%cr4\n" : : "irg" (~mask) :"ax"); -#endif } diff -r 7e3cbc409676 -r d75a6cc5e68a linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/setup_arch_post.h --- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/setup_arch_post.h Mon Mar 27 15:36:47 2006 -0700 +++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/setup_arch_post.h Tue Mar 28 08:54:58 2006 -0700 @@ -5,17 +5,6 @@ * This is included late in kernel/setup.c so that it can make * use of all of the static functions. **/ - -void __cpuinit machine_specific_modify_cpu_capabilities(struct cpuinfo_x86 *c) -{ - clear_bit(X86_FEATURE_VME, c->x86_capability); - clear_bit(X86_FEATURE_DE, c->x86_capability); - clear_bit(X86_FEATURE_PSE, c->x86_capability); - clear_bit(X86_FEATURE_PGE, c->x86_capability); - clear_bit(X86_FEATURE_SEP, c->x86_capability); - if (!(xen_start_info->flags & SIF_PRIVILEGED)) - clear_bit(X86_FEATURE_MTRR, c->x86_capability); -} extern void hypervisor_callback(void); extern void failsafe_callback(void); @@ -36,6 +25,4 @@ static void __init machine_specific_arch cb.handler_address = (unsigned long)&nmi; HYPERVISOR_nmi_op(XENNMI_register_callback, &cb); #endif - - machine_specific_modify_cpu_capabilities(&boot_cpu_data); } diff -r 7e3cbc409676 -r d75a6cc5e68a linux-2.6-xen-sparse/include/linux/mm.h --- a/linux-2.6-xen-sparse/include/linux/mm.h Mon Mar 27 15:36:47 2006 -0700 +++ b/linux-2.6-xen-sparse/include/linux/mm.h Tue Mar 28 08:54:58 2006 -0700 @@ -1020,10 +1020,10 @@ struct page *follow_page(struct vm_area_ #define FOLL_ANON 0x08 /* give ZERO_PAGE if no pgtable */ #ifdef CONFIG_XEN -typedef int (*pte_fn_t)(pte_t *pte, struct page *pte_page, unsigned long addr, - void *data); -extern int generic_page_range(struct mm_struct *mm, unsigned long address, - unsigned long size, pte_fn_t fn, void *data); +typedef int (*pte_fn_t)(pte_t *pte, struct page *pmd_page, unsigned long addr, + void *data); +extern int apply_to_page_range(struct mm_struct *mm, unsigned long address, + unsigned long size, pte_fn_t fn, void *data); #endif #ifdef CONFIG_PROC_FS diff -r 7e3cbc409676 -r d75a6cc5e68a linux-2.6-xen-sparse/mm/memory.c --- a/linux-2.6-xen-sparse/mm/memory.c Mon Mar 27 15:36:47 2006 -0700 +++ b/linux-2.6-xen-sparse/mm/memory.c Tue Mar 28 08:54:58 2006 -0700 @@ -1378,36 +1378,39 @@ EXPORT_SYMBOL(remap_pfn_range); EXPORT_SYMBOL(remap_pfn_range); #ifdef CONFIG_XEN -static inline int generic_pte_range(struct mm_struct *mm, pmd_t *pmd, - unsigned long addr, unsigned long end, - pte_fn_t fn, void *data) +static inline int apply_to_pte_range(struct mm_struct *mm, pmd_t *pmd, + unsigned long addr, unsigned long end, + pte_fn_t fn, void *data) { pte_t *pte; int err; - struct page *pte_page; + struct page *pmd_page; + spinlock_t *ptl; pte = (mm == &init_mm) ? pte_alloc_kernel(pmd, addr) : - pte_alloc_map(mm, pmd, addr); + pte_alloc_map_lock(mm, pmd, addr, &ptl); if (!pte) return -ENOMEM; - pte_page = pmd_page(*pmd); + BUG_ON(pmd_huge(*pmd)); + + pmd_page = pmd_page(*pmd); do { - err = fn(pte, pte_page, addr, data); + err = fn(pte, pmd_page, addr, data); if (err) break; } while (pte++, addr += PAGE_SIZE, addr != end); if (mm != &init_mm) - pte_unmap(pte-1); + pte_unmap_unlock(pte-1, ptl); return err; } -static inline int generic_pmd_range(struct mm_struct *mm, pud_t *pud, - unsigned long addr, unsigned long end, - pte_fn_t fn, void *data) +static inline int apply_to_pmd_range(struct mm_struct *mm, pud_t *pud, + unsigned long addr, unsigned long end, + pte_fn_t fn, void *data) { pmd_t *pmd; unsigned long next; @@ -1418,16 +1421,16 @@ static inline int generic_pmd_range(stru return -ENOMEM; do { next = pmd_addr_end(addr, end); - err = generic_pte_range(mm, pmd, addr, next, fn, data); + err = apply_to_pte_range(mm, pmd, addr, next, fn, data); if (err) break; } while (pmd++, addr = next, addr != end); return err; } -static inline int generic_pud_range(struct mm_struct *mm, pgd_t *pgd, - unsigned long addr, unsigned long end, - pte_fn_t fn, void *data) +static inline int apply_to_pud_range(struct mm_struct *mm, pgd_t *pgd, + unsigned long addr, unsigned long end, + pte_fn_t fn, void *data) { pud_t *pud; unsigned long next; @@ -1438,7 +1441,7 @@ static inline int generic_pud_range(stru return -ENOMEM; do { next = pud_addr_end(addr, end); - err = generic_pmd_range(mm, pud, addr, next, fn, data); + err = apply_to_pmd_range(mm, pud, addr, next, fn, data); if (err) break; } while (pud++, addr = next, addr != end); @@ -1449,8 +1452,8 @@ static inline int generic_pud_range(stru * Scan a region of virtual memory, filling in page tables as necessary * and calling a provided function on each leaf page table. */ -int generic_page_range(struct mm_struct *mm, unsigned long addr, - unsigned long size, pte_fn_t fn, void *data) +int apply_to_page_range(struct mm_struct *mm, unsigned long addr, + unsigned long size, pte_fn_t fn, void *data) { pgd_t *pgd; unsigned long next; @@ -1461,12 +1464,13 @@ int generic_page_range(struct mm_struct pgd = pgd_offset(mm, addr); do { next = pgd_addr_end(addr, end); - err = generic_pud_range(mm, pgd, addr, next, fn, data); + err = apply_to_pud_range(mm, pgd, addr, next, fn, data); if (err) break; } while (pgd++, addr = next, addr != end); return err; } +EXPORT_SYMBOL_GPL(apply_to_page_range); #endif /* diff -r 7e3cbc409676 -r d75a6cc5e68a tools/Makefile --- a/tools/Makefile Mon Mar 27 15:36:47 2006 -0700 +++ b/tools/Makefile Tue Mar 28 08:54:58 2006 -0700 @@ -37,6 +37,7 @@ install: check $(MAKE) -C $$subdir $@; \ done $(MAKE) ioemuinstall + $(INSTALL_DIR) -p $(DESTDIR)/var/xen/dump clean: check_clean @set -e; for subdir in $(SUBDIRS); do \ diff -r 7e3cbc409676 -r d75a6cc5e68a tools/debugger/gdb/README --- a/tools/debugger/gdb/README Mon Mar 27 15:36:47 2006 -0700 +++ b/tools/debugger/gdb/README Tue Mar 28 08:54:58 2006 -0700 @@ -11,8 +11,8 @@ To build the GDB server: to your test machine. To build a debuggable guest kernel image: - 1. cd linux-2.6.12-xenU - 2. ARCH=xen make menuconfig + 1. cd linux-2.6.xx-xenU + 2. make menuconfig 3. From within the configurator, enable the following options: # Kernel hacking -> Compile the kernel with debug info [*] -> Compile the kernel with frame pointers diff -r 7e3cbc409676 -r d75a6cc5e68a tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/configure.srv --- a/tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/configure.srv Mon Mar 27 15:36:47 2006 -0700 +++ b/tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/configure.srv Tue Mar 28 08:54:58 2006 -0700 @@ -61,7 +61,7 @@ case "${target}" in srv_linux_thread_db=yes ;; x86_64-*-linux*) srv_regobj=reg-x86-64.o - srv_tgtobj="linux-low.o linux-x86-64-low.o i387-fp.o" + srv_tgtobj="linux-xen-low.o linux-x86-64-low.o i387-fp.o" srv_linux_regsets=yes ;; xscale*-*-linux*) srv_regobj=reg-arm.o diff -r 7e3cbc409676 -r d75a6cc5e68a tools/examples/xen-backend.agent --- a/tools/examples/xen-backend.agent Mon Mar 27 15:36:47 2006 -0700 +++ b/tools/examples/xen-backend.agent Tue Mar 28 08:54:58 2006 -0700 @@ -1,6 +1,10 @@ #! /bin/sh PATH=/etc/xen/scripts:$PATH + +. /etc/xen/scripts/locking.sh + +claim_lock xenbus_hotplug_global case "$XENBUS_TYPE" in vbd) @@ -25,3 +29,5 @@ case "$ACTION" in offline) ;; esac + +release_lock xenbus_hotplug_global diff -r 7e3cbc409676 -r d75a6cc5e68a tools/examples/xend-config.sxp --- a/tools/examples/xend-config.sxp Mon Mar 27 15:36:47 2006 -0700 +++ b/tools/examples/xend-config.sxp Tue Mar 28 08:54:58 2006 -0700 @@ -15,7 +15,9 @@ #(loglevel DEBUG) #(xend-http-server no) -#(xend-unix-server yes) +#(xend-unix-server no) +#(xend-tcp-xmlrpc-server no) +#(xend-unix-xmlrpc-server yes) #(xend-relocation-server no) (xend-relocation-server yes) diff -r 7e3cbc409676 -r d75a6cc5e68a tools/ioemu/hw/pcnet.c --- a/tools/ioemu/hw/pcnet.c Mon Mar 27 15:36:47 2006 -0700 +++ b/tools/ioemu/hw/pcnet.c Tue Mar 28 08:54:58 2006 -0700 @@ -45,21 +45,6 @@ #define PCNET_PNPMMIO_SIZE 0x20 -typedef struct PCNetState_st PCNetState; - -struct PCNetState_st { - PCIDevice dev; - NetDriverState *nd; - int mmio_io_addr, rap, isr, lnkst; - target_phys_addr_t rdra, tdra; - uint8_t prom[16]; - uint16_t csr[128]; - uint16_t bcr[32]; - uint64_t timer; - int xmit_pos, recv_pos; - uint8_t buffer[4096]; -}; - #include "pcnet.h" static void pcnet_poll(PCNetState *s); @@ -217,6 +202,11 @@ static void pcnet_init(PCNetState *s) CSR_RCVRC(s) = CSR_RCVRL(s); CSR_XMTRC(s) = CSR_XMTRL(s); + /* flush any cached receive descriptors */ + s->crmd.rmd1.own = 0; + s->nrmd.rmd1.own = 0; + s->nnrmd.rmd1.own = 0; + #ifdef PCNET_DEBUG printf("pcnet ss32=%d rdra=0x%08x[%d] tdra=0x%08x[%d]\n", BCR_SSIZE32(s), @@ -239,6 +229,11 @@ static void pcnet_start(PCNetState *s) if (!CSR_DRX(s)) s->csr[0] |= 0x0020; /* set RXON */ + /* flush any cached receive descriptors */ + s->crmd.rmd1.own = 0; + s->nrmd.rmd1.own = 0; + s->nnrmd.rmd1.own = 0; + s->csr[0] &= ~0x0004; /* clear STOP bit */ s->csr[0] |= 0x0002; } @@ -260,29 +255,21 @@ static void pcnet_rdte_poll(PCNetState * s->csr[28] = s->csr[29] = 0; if (s->rdra) { int bad = 0; -#if 1 target_phys_addr_t crda = pcnet_rdra_addr(s, CSR_RCVRC(s)); target_phys_addr_t nrda = pcnet_rdra_addr(s, -1 + CSR_RCVRC(s)); target_phys_addr_t nnrd = pcnet_rdra_addr(s, -2 + CSR_RCVRC(s)); -#else - target_phys_addr_t crda = s->rdra + - (CSR_RCVRL(s) - CSR_RCVRC(s)) * - (BCR_SWSTYLE(s) ? 16 : 8 ); - int nrdc = CSR_RCVRC(s)<=1 ? CSR_RCVRL(s) : CSR_RCVRC(s)-1; - target_phys_addr_t nrda = s->rdra + - (CSR_RCVRL(s) - nrdc) * - (BCR_SWSTYLE(s) ? 16 : 8 ); - int nnrc = nrdc<=1 ? CSR_RCVRL(s) : nrdc-1; - target_phys_addr_t nnrd = s->rdra + - (CSR_RCVRL(s) - nnrc) * - (BCR_SWSTYLE(s) ? 16 : 8 ); -#endif - - CHECK_RMD(PHYSADDR(s,crda), bad); + + if (!s->crmd.rmd1.own) { + CHECK_RMD(&(s->crmd),PHYSADDR(s,crda), bad); + } if (!bad) { - CHECK_RMD(PHYSADDR(s,nrda), bad); + if (s->crmd.rmd1.own && !s->nrmd.rmd1.own) { + CHECK_RMD(&(s->nrmd),PHYSADDR(s,nrda), bad); + } if (bad || (nrda == crda)) nrda = 0; - CHECK_RMD(PHYSADDR(s,nnrd), bad); + if (s->crmd.rmd1.own && s->nrmd.rmd1.own && !s->nnrmd.rmd1.own) { + CHECK_RMD(&(s->nnrmd),PHYSADDR(s,nnrd), bad); + } if (bad || (nnrd == crda)) nnrd = 0; s->csr[28] = crda & 0xffff; @@ -303,14 +290,12 @@ static void pcnet_rdte_poll(PCNetState * } if (CSR_CRDA(s)) { - struct pcnet_RMD rmd; - RMDLOAD(&rmd, PHYSADDR(s,CSR_CRDA(s))); - CSR_CRBC(s) = rmd.rmd1.bcnt; - CSR_CRST(s) = ((uint32_t *)&rmd)[1] >> 16; + CSR_CRBC(s) = s->crmd.rmd1.bcnt; + CSR_CRST(s) = ((uint32_t *)&(s->crmd))[1] >> 16; #ifdef PCNET_DEBUG_RMD_X printf("CRDA=0x%08x CRST=0x%04x RCVRC=%d RMD1=0x%08x RMD2=0x%08x\n", PHYSADDR(s,CSR_CRDA(s)), CSR_CRST(s), CSR_RCVRC(s), - ((uint32_t *)&rmd)[1], ((uint32_t *)&rmd)[2]); + ((uint32_t *)&(s->crmd))[1], ((uint32_t *)&(s->crmd))[2]); PRINT_RMD(&rmd); #endif } else { @@ -318,10 +303,8 @@ static void pcnet_rdte_poll(PCNetState * } if (CSR_NRDA(s)) { - struct pcnet_RMD rmd; - RMDLOAD(&rmd, PHYSADDR(s,CSR_NRDA(s))); - CSR_NRBC(s) = rmd.rmd1.bcnt; - CSR_NRST(s) = ((uint32_t *)&rmd)[1] >> 16; + CSR_NRBC(s) = s->nrmd.rmd1.bcnt; + CSR_NRST(s) = ((uint32_t *)&(s->nrmd))[1] >> 16; } else { CSR_NRBC(s) = CSR_NRST(s) = 0; } @@ -336,6 +319,7 @@ static int pcnet_tdte_poll(PCNetState *s (CSR_XMTRL(s) - CSR_XMTRC(s)) * (BCR_SWSTYLE(s) ? 16 : 8 ); int bad = 0; + s->csr[0] &= ~0x0008; /* clear TDMD */ CHECK_TMD(PHYSADDR(s, cxda),bad); if (!bad) { if (CSR_CXDA(s) != cxda) { @@ -354,12 +338,8 @@ static int pcnet_tdte_poll(PCNetState *s } if (CSR_CXDA(s)) { - struct pcnet_TMD tmd; - - TMDLOAD(&tmd, PHYSADDR(s,CSR_CXDA(s))); - - CSR_CXBC(s) = tmd.tmd1.bcnt; - CSR_CXST(s) = ((uint32_t *)&tmd)[1] >> 16; + CSR_CXBC(s) = s->tmd.tmd1.bcnt; + CSR_CXST(s) = ((uint32_t *)&(s->tmd))[1] >> 16; } else { CSR_CXBC(s) = CSR_CXST(s) = 0; } @@ -373,14 +353,11 @@ static int pcnet_can_receive(void *opaqu if (CSR_STOP(s) || CSR_SPND(s)) return 0; - if (s->recv_pos > 0) - return 0; - pcnet_rdte_poll(s); if (!(CSR_CRST(s) & 0x8000)) { return 0; } - return sizeof(s->buffer)-16; + return sizeof(s->rx_buffer)-16; } #define MIN_BUF_SIZE 60 @@ -389,7 +366,7 @@ static void pcnet_receive(void *opaque, { PCNetState *s = opaque; int is_padr = 0, is_bcast = 0, is_ladr = 0; - uint8_t buf1[60]; + int pad; if (CSR_DRX(s) || CSR_STOP(s) || CSR_SPND(s) || !size) return; @@ -399,12 +376,10 @@ static void pcnet_receive(void *opaque, #endif /* if too small buffer, then expand it */ - if (size < MIN_BUF_SIZE) { - memcpy(buf1, buf, size); - memset(buf1 + size, 0, MIN_BUF_SIZE - size); - buf = buf1; - size = MIN_BUF_SIZE; - } + if (size < MIN_BUF_SIZE) + pad = MIN_BUF_SIZE - size + 4; + else + pad = 4; if (CSR_PROM(s) || (is_padr=padr_match(s, buf, size)) @@ -413,124 +388,74 @@ static void pcnet_receive(void *opaque, pcnet_rdte_poll(s); - if (!(CSR_CRST(s) & 0x8000) && s->rdra) { - struct pcnet_RMD rmd; - int rcvrc = CSR_RCVRC(s)-1,i; - target_phys_addr_t nrda; - for (i = CSR_RCVRL(s)-1; i > 0; i--, rcvrc--) { - if (rcvrc <= 1) - rcvrc = CSR_RCVRL(s); - nrda = s->rdra + - (CSR_RCVRL(s) - rcvrc) * - (BCR_SWSTYLE(s) ? 16 : 8 ); - RMDLOAD(&rmd, PHYSADDR(s,nrda)); - if (rmd.rmd1.own) { + if (size > 2000) { #ifdef PCNET_DEBUG_RMD - printf("pcnet - scan buffer: RCVRC=%d PREV_RCVRC=%d\n", - rcvrc, CSR_RCVRC(s)); -#endif - CSR_RCVRC(s) = rcvrc; - pcnet_rdte_poll(s); - break; - } - } - } - - if (!(CSR_CRST(s) & 0x8000)) { + printf("pcnet - oversize packet discarded.\n"); +#endif + } else if (!(CSR_CRST(s) & 0x8000)) { #ifdef PCNET_DEBUG_RMD printf("pcnet - no buffer: RCVRC=%d\n", CSR_RCVRC(s)); #endif s->csr[0] |= 0x1000; /* Set MISS flag */ CSR_MISSC(s)++; } else { - uint8_t *src = &s->buffer[8]; + uint8_t *src = &s->rx_buffer[8]; target_phys_addr_t crda = CSR_CRDA(s); - struct pcnet_RMD rmd; + target_phys_addr_t nrda = CSR_NRDA(s); + target_phys_addr_t nnrda = CSR_NNRD(s); int pktcount = 0; + int packet_size = size + pad; memcpy(src, buf, size); - - if (!CSR_ASTRP_RCV(s)) { - uint32_t fcs = ~0; -#if 0 - uint8_t *p = s->buffer; - - ((uint32_t *)p)[0] = ((uint32_t *)p)[1] = 0xaaaaaaaa; - p[7] = 0xab; -#else - uint8_t *p = src; -#endif - - while (size < 46) { - src[size++] = 0; - } - - while (p != &src[size]) { - CRC(fcs, *p++); - } - ((uint32_t *)&src[size])[0] = htonl(fcs); - size += 4; /* FCS at end of packet */ - } else size += 4; + memset(src + size, 0, pad); + size += pad; #ifdef PCNET_DEBUG_MATCH PRINT_PKTHDR(buf); #endif - RMDLOAD(&rmd, PHYSADDR(s,crda)); - /*if (!CSR_LAPPEN(s))*/ - rmd.rmd1.stp = 1; - -#define PCNET_RECV_STORE() do { \ - int count = MIN(4096 - rmd.rmd1.bcnt,size); \ - target_phys_addr_t rbadr = PHYSADDR(s, rmd.rmd0.rbadr); \ - cpu_physical_memory_write(rbadr, src, count); \ - cpu_physical_memory_set_dirty(rbadr); \ - cpu_physical_memory_set_dirty(rbadr+count); \ - src += count; size -= count; \ - rmd.rmd2.mcnt = count; rmd.rmd1.own = 0; \ - RMDSTORE(&rmd, PHYSADDR(s,crda)); \ - pktcount++; \ -} while (0) - - PCNET_RECV_STORE(); - if ((size > 0) && CSR_NRDA(s)) { - target_phys_addr_t nrda = CSR_NRDA(s); - RMDLOAD(&rmd, PHYSADDR(s,nrda)); - if (rmd.rmd1.own) { - crda = nrda; - PCNET_RECV_STORE(); - if ((size > 0) && (nrda=CSR_NNRD(s))) { - RMDLOAD(&rmd, PHYSADDR(s,nrda)); - if (rmd.rmd1.own) { - crda = nrda; - PCNET_RECV_STORE(); - } - } - } + s->crmd.rmd1.stp = 1; + do { + int count = MIN(4096 - s->crmd.rmd1.bcnt,size); + target_phys_addr_t rbadr = PHYSADDR(s, s->crmd.rmd0.rbadr); + cpu_physical_memory_write(rbadr, src, count); + cpu_physical_memory_set_dirty(rbadr); + cpu_physical_memory_set_dirty(rbadr+count); + src += count; size -= count; + if (size > 0 && s->nrmd.rmd1.own) { + RMDSTORE(&(s->crmd), PHYSADDR(s,crda)); + crda = nrda; + nrda = nnrda; + s->crmd = s->nrmd; + s->nrmd = s->nnrmd; + s->nnrmd.rmd1.own = 0; + } + pktcount++; + } while (size > 0 && s->crmd.rmd1.own); + + if (size == 0) { + s->crmd.rmd1.enp = 1; + s->crmd.rmd2.mcnt = packet_size; + s->crmd.rmd1.pam = !CSR_PROM(s) && is_padr; + s->crmd.rmd1.lafm = !CSR_PROM(s) && is_ladr; + s->crmd.rmd1.bam = !CSR_PROM(s) && is_bcast; + } else { + s->crmd.rmd1.oflo = 1; + s->crmd.rmd1.buff = 1; + s->crmd.rmd1.err = 1; } - -#undef PCNET_RECV_STORE - - RMDLOAD(&rmd, PHYSADDR(s,crda)); - if (size == 0) { - rmd.rmd1.enp = 1; - rmd.rmd1.pam = !CSR_PROM(s) && is_padr; - rmd.rmd1.lafm = !CSR_PROM(s) && is_ladr; - rmd.rmd1.bam = !CSR_PROM(s) && is_bcast; - } else { - rmd.rmd1.oflo = 1; - rmd.rmd1.buff = 1; - rmd.rmd1.err = 1; - } - RMDSTORE(&rmd, PHYSADDR(s,crda)); + RMDSTORE(&(s->crmd), PHYSADDR(s,crda)); s->csr[0] |= 0x0400; + s->crmd = s->nrmd; + s->nrmd = s->nnrmd; + s->nnrmd.rmd1.own = 0; #ifdef PCNET_DEBUG printf("RCVRC=%d CRDA=0x%08x BLKS=%d\n", CSR_RCVRC(s), PHYSADDR(s,CSR_CRDA(s)), pktcount); #endif #ifdef PCNET_DEBUG_RMD - PRINT_RMD(&rmd); + PRINT_RMD(&s->crmd); #endif while (pktcount--) { @@ -551,80 +476,88 @@ static void pcnet_receive(void *opaque, static void pcnet_transmit(PCNetState *s) { - target_phys_addr_t xmit_cxda = 0; + target_phys_addr_t start_addr = 0; + struct pcnet_TMD start_tmd; int count = CSR_XMTRL(s)-1; - s->xmit_pos = -1; + int xmit_pos = 0; + int len; + if (!CSR_TXON(s)) { s->csr[0] &= ~0x0008; return; } - txagain: - if (pcnet_tdte_poll(s)) { - struct pcnet_TMD tmd; - - TMDLOAD(&tmd, PHYSADDR(s,CSR_CXDA(s))); + while (pcnet_tdte_poll(s)) { #ifdef PCNET_DEBUG_TMD printf(" TMDLOAD 0x%08x\n", PHYSADDR(s,CSR_CXDA(s))); - PRINT_TMD(&tmd); -#endif - if (tmd.tmd1.stp) { - s->xmit_pos = 0; - if (!tmd.tmd1.enp) { - cpu_physical_memory_read(PHYSADDR(s, tmd.tmd0.tbadr), - s->buffer, 4096 - tmd.tmd1.bcnt); - s->xmit_pos += 4096 - tmd.tmd1.bcnt; - } - xmit_cxda = PHYSADDR(s,CSR_CXDA(s)); - } - if (tmd.tmd1.enp && (s->xmit_pos >= 0)) { - cpu_physical_memory_read(PHYSADDR(s, tmd.tmd0.tbadr), - s->buffer + s->xmit_pos, 4096 - tmd.tmd1.bcnt); - s->xmit_pos += 4096 - tmd.tmd1.bcnt; - - tmd.tmd1.own = 0; - TMDSTORE(&tmd, PHYSADDR(s,CSR_CXDA(s))); - -#ifdef PCNET_DEBUG - printf("pcnet_transmit size=%d\n", s->xmit_pos); -#endif - if (CSR_LOOP(s)) - pcnet_receive(s, s->buffer, s->xmit_pos); - else - qemu_send_packet(s->nd, s->buffer, s->xmit_pos); - - s->csr[0] &= ~0x0008; /* clear TDMD */ - s->csr[4] |= 0x0004; /* set TXSTRT */ - s->xmit_pos = -1; - } else { - tmd.tmd1.own = 0; - TMDSTORE(&tmd, PHYSADDR(s,CSR_CXDA(s))); - } - if (!CSR_TOKINTD(s) || (CSR_LTINTEN(s) && tmd.tmd1.ltint)) - s->csr[0] |= 0x0200; /* set TINT */ - - if (CSR_XMTRC(s)<=1) + PRINT_TMD(&(s->tmd)); +#endif + len = 4096 - s->tmd.tmd1.bcnt; + if (CSR_XMTRC(s) <= 1) CSR_XMTRC(s) = CSR_XMTRL(s); else CSR_XMTRC(s)--; - if (count--) - goto txagain; - - } else - if (s->xmit_pos >= 0) { - struct pcnet_TMD tmd; - TMDLOAD(&tmd, PHYSADDR(s,xmit_cxda)); - tmd.tmd2.buff = tmd.tmd2.uflo = tmd.tmd1.err = 1; - tmd.tmd1.own = 0; - TMDSTORE(&tmd, PHYSADDR(s,xmit_cxda)); + + /* handle start followed by start */ + if (s->tmd.tmd1.stp && start_addr) { + TMDSTORE(&start_tmd, start_addr); + start_addr = 0; + xmit_pos = 0; + } + if ((xmit_pos + len) < sizeof(s->tx_buffer)) { + cpu_physical_memory_read(PHYSADDR(s, s->tmd.tmd0.tbadr), + s->tx_buffer + xmit_pos, len); + xmit_pos += len; + } else { + s->tmd.tmd2.buff = s->tmd.tmd2.uflo = s->tmd.tmd1.err = 1; + TMDSTORE(&(s->tmd), PHYSADDR(s,CSR_CXDA(s))); + if (start_addr == PHYSADDR(s,CSR_CXDA(s))) + start_addr = 0; /* don't clear own bit twice */ + continue; + } + if (s->tmd.tmd1.stp) { + if (s->tmd.tmd1.enp) { + if (CSR_LOOP(s)) + pcnet_receive(s, s->tx_buffer, xmit_pos); + else + qemu_send_packet(s->nd, s->tx_buffer, xmit_pos); + + s->csr[4] |= 0x0008; /* set TXSTRT */ + TMDSTORE(&(s->tmd), PHYSADDR(s,CSR_CXDA(s))); + xmit_pos = 0; + count--; + } else { + start_tmd = s->tmd; + start_addr = PHYSADDR(s,CSR_CXDA(s)); + } + } else if (s->tmd.tmd1.enp) { + TMDSTORE(&(s->tmd), PHYSADDR(s,CSR_CXDA(s))); + if (start_addr) { + TMDSTORE(&start_tmd, start_addr); + } + start_addr = 0; + xmit_pos = 0; + count--; + + } else { + TMDSTORE(&(s->tmd), PHYSADDR(s,CSR_CXDA(s))); + } + if (!CSR_TOKINTD(s) || (CSR_LTINTEN(s) && s->tmd.tmd1.ltint)) + s->csr[0] |= 0x0200; /* set TINT */ + + if (count <= 0) + break; + + } + if (start_addr) { + start_tmd.tmd2.buff = start_tmd.tmd2.uflo = start_tmd.tmd1.err = 1; + TMDSTORE(&start_tmd, PHYSADDR(s,start_addr)); s->csr[0] |= 0x0200; /* set TINT */ if (!CSR_DXSUFLO(s)) { s->csr[0] &= ~0x0010; - } else - if (count--) - goto txagain; + } } } diff -r 7e3cbc409676 -r d75a6cc5e68a tools/ioemu/hw/pcnet.h --- a/tools/ioemu/hw/pcnet.h Mon Mar 27 15:36:47 2006 -0700 +++ b/tools/ioemu/hw/pcnet.h Tue Mar 28 08:54:58 2006 -0700 @@ -177,6 +177,26 @@ struct pcnet_RMD { } rmd3; }; +typedef struct PCNetState_st PCNetState; + +struct PCNetState_st { + PCIDevice dev; + NetDriverState *nd; + int mmio_io_addr, rap, isr, lnkst; + target_phys_addr_t rdra, tdra; + uint8_t prom[16]; + uint16_t csr[128]; + uint16_t bcr[32]; + uint64_t timer; + int recv_pos; + uint8_t tx_buffer[2048]; + uint8_t rx_buffer[2048]; + struct pcnet_TMD tmd; + struct pcnet_RMD crmd; + struct pcnet_RMD nrmd; + struct pcnet_RMD nnrmd; +}; + #define PRINT_TMD(T) printf( \ "TMD0 : TBADR=0x%08x\n" \ @@ -230,18 +250,17 @@ static inline void pcnet_tmd_load(PCNetS cpu_physical_memory_read(addr+4, (void *)&tmd->tmd1, 4); cpu_physical_memory_read(addr, (void *)&tmd->tmd0, 4); } else { - uint32_t xda[4]; - cpu_physical_memory_read(addr, - (void *)&xda[0], sizeof(xda)); - ((uint32_t *)tmd)[0] = xda[2]; - ((uint32_t *)tmd)[1] = xda[1]; - ((uint32_t *)tmd)[2] = xda[0]; - ((uint32_t *)tmd)[3] = xda[3]; + uint32_t xda[2]; + cpu_physical_memory_read(addr+4, (void *)&xda[0], sizeof(xda)); + ((uint32_t *)tmd)[0] = xda[1]; + ((uint32_t *)tmd)[1] = xda[0]; + ((uint32_t *)tmd)[2] = 0; } } static inline void pcnet_tmd_store(PCNetState *s, struct pcnet_TMD *tmd, target_phys_addr_t addr) { + tmd->tmd1.own = 0; cpu_physical_memory_set_dirty(addr); if (!BCR_SWSTYLE(s)) { uint16_t xda[4]; @@ -259,13 +278,10 @@ static inline void pcnet_tmd_store(PCNet cpu_physical_memory_write(addr+8, (void *)&tmd->tmd2, 4); cpu_physical_memory_write(addr+4, (void *)&tmd->tmd1, 4); } else { - uint32_t xda[4]; + uint32_t xda[2]; xda[0] = ((uint32_t *)tmd)[2]; xda[1] = ((uint32_t *)tmd)[1]; - xda[2] = ((uint32_t *)tmd)[0]; - xda[3] = ((uint32_t *)tmd)[3]; - cpu_physical_memory_write(addr, - (void *)&xda[0], sizeof(xda)); + cpu_physical_memory_write(addr, (void *)&xda[0], sizeof(xda)); } cpu_physical_memory_set_dirty(addr+15); } @@ -286,22 +302,21 @@ static inline void pcnet_rmd_load(PCNetS } else if (BCR_SWSTYLE(s) != 3) { - rmd->rmd2.zeros = 0; + ((uint32_t *)rmd)[2] = 0; cpu_physical_memory_read(addr+4, (void *)&rmd->rmd1, 4); cpu_physical_memory_read(addr, (void *)&rmd->rmd0, 4); } else { - uint32_t rda[4]; - cpu_physical_memory_read(addr, - (void *)&rda[0], sizeof(rda)); - ((uint32_t *)rmd)[0] = rda[2]; - ((uint32_t *)rmd)[1] = rda[1]; - ((uint32_t *)rmd)[2] = rda[0]; - ((uint32_t *)rmd)[3] = rda[3]; + uint32_t rda[2]; + cpu_physical_memory_read(addr+4, (void *)&rda[0], sizeof(rda)); + ((uint32_t *)rmd)[0] = rda[1]; + ((uint32_t *)rmd)[1] = rda[0]; + ((uint32_t *)rmd)[2] = 0; } } static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd, target_phys_addr_t addr) { + rmd->rmd1.own = 0; cpu_physical_memory_set_dirty(addr); if (!BCR_SWSTYLE(s)) { uint16_t rda[4]; \ @@ -319,13 +334,10 @@ static inline void pcnet_rmd_store(PCNet cpu_physical_memory_write(addr+8, (void *)&rmd->rmd2, 4); cpu_physical_memory_write(addr+4, (void *)&rmd->rmd1, 4); } else { - uint32_t rda[4]; + uint32_t rda[2]; rda[0] = ((uint32_t *)rmd)[2]; rda[1] = ((uint32_t *)rmd)[1]; - rda[2] = ((uint32_t *)rmd)[0]; - rda[3] = ((uint32_t *)rmd)[3]; - cpu_physical_memory_write(addr, - (void *)&rda[0], sizeof(rda)); + cpu_physical_memory_write(addr, (void *)&rda[0], sizeof(rda)); } cpu_physical_memory_set_dirty(addr+15); } @@ -340,79 +352,16 @@ static inline void pcnet_rmd_store(PCNet #define RMDSTORE(RMD,ADDR) pcnet_rmd_store(s,RMD,ADDR) -#if 1 - -#define CHECK_RMD(ADDR,RES) do { \ - struct pcnet_RMD rmd; \ - RMDLOAD(&rmd,(ADDR)); \ - (RES) |= (rmd.rmd1.ones != 15); \ +#define CHECK_RMD(RMD,ADDR,RES) do { \ + RMDLOAD((RMD),(ADDR)); \ + (RES) |= ((RMD)->rmd1.ones != 15); \ } while (0) -#define CHECK_TMD(ADDR,RES) do { \ - struct pcnet_TMD tmd; \ - TMDLOAD(&tmd,(ADDR)); \ - (RES) |= (tmd.tmd1.ones != 15); \ +#define CHECK_TMD(ADDR,RES) do { \ + TMDLOAD(&(s->tmd),(ADDR)); \ + (RES) |= (s->tmd.tmd1.ones != 15); \ } while (0) -#else - -#define CHECK_RMD(ADDR,RES) do { \ - switch (BCR_SWSTYLE(s)) { \ - case 0x00: \ - do { \ - uint16_t rda[4]; \ - cpu_physical_memory_read((ADDR), \ - (void *)&rda[0], sizeof(rda)); \ - (RES) |= (rda[2] & 0xf000)!=0xf000; \ - (RES) |= (rda[3] & 0xf000)!=0x0000; \ - } while (0); \ - break; \ - case 0x01: \ - case 0x02: \ - do { \ - uint32_t rda[4]; \ - cpu_physical_memory_read((ADDR), \ - (void *)&rda[0], sizeof(rda)); \ - (RES) |= (rda[1] & 0x0000f000L)!=0x0000f000L; \ - (RES) |= (rda[2] & 0x0000f000L)!=0x00000000L; \ - } while (0); \ - break; \ - case 0x03: \ - do { \ - uint32_t rda[4]; \ - cpu_physical_memory_read((ADDR), \ - (void *)&rda[0], sizeof(rda)); \ - (RES) |= (rda[0] & 0x0000f000L)!=0x00000000L; \ - (RES) |= (rda[1] & 0x0000f000L)!=0x0000f000L; \ - } while (0); \ - break; \ - } \ -} while (0) - -#define CHECK_TMD(ADDR,RES) do { \ - switch (BCR_SWSTYLE(s)) { \ - case 0x00: \ - do { \ - uint16_t xda[4]; \ - cpu_physical_memory_read((ADDR), \ - (void *)&xda[0], sizeof(xda)); \ - (RES) |= (xda[2] & 0xf000)!=0xf000;\ - } while (0); \ - break; \ - case 0x01: \ - case 0x02: \ - case 0x03: \ - do { \ - uint32_t xda[4]; \ - cpu_physical_memory_read((ADDR), \ - (void *)&xda[0], sizeof(xda)); \ - (RES) |= (xda[1] & 0x0000f000L)!=0x0000f000L; \ - } while (0); \ - break; \ - } \ -} while (0) - -#endif #define PRINT_PKTHDR(BUF) do { \ struct ether_header *hdr = (void *)(BUF); \ diff -r 7e3cbc409676 -r d75a6cc5e68a tools/libxc/Makefile --- a/tools/libxc/Makefile Mon Mar 27 15:36:47 2006 -0700 +++ b/tools/libxc/Makefile Tue Mar 28 08:54:58 2006 -0700 @@ -21,13 +21,9 @@ SRCS += xc_sedf.c SRCS += xc_sedf.c SRCS += xc_tbuf.c -ifeq ($(XEN_TARGET_ARCH),x86_32) +ifeq ($(patsubst x86%,x86,$(XEN_TARGET_ARCH)),x86) SRCS += xc_ptrace.c SRCS += xc_ptrace_core.c -SRCS += xc_pagetab.c -endif - -ifeq ($(XEN_TARGET_ARCH),x86_64) SRCS += xc_pagetab.c endif diff -r 7e3cbc409676 -r d75a6cc5e68a tools/libxc/xc_core.c --- a/tools/libxc/xc_core.c Mon Mar 27 15:36:47 2006 -0700 +++ b/tools/libxc/xc_core.c Tue Mar 28 08:54:58 2006 -0700 @@ -3,7 +3,6 @@ #include "xc_elf.h" #include <stdlib.h> #include <unistd.h> -#include <zlib.h> /* number of pages to write at a time */ #define DUMP_INCREMENT (4 * 1024) diff -r 7e3cbc409676 -r d75a6cc5e68a tools/libxc/xc_private.c --- a/tools/libxc/xc_private.c Mon Mar 27 15:36:47 2006 -0700 +++ b/tools/libxc/xc_private.c Tue Mar 28 08:54:58 2006 -0700 @@ -4,7 +4,6 @@ * Helper functions for the rest of the library. */ -#include <zlib.h> #include "xc_private.h" #include <xen/memory.h> diff -r 7e3cbc409676 -r d75a6cc5e68a tools/libxc/xc_ptrace.c --- a/tools/libxc/xc_ptrace.c Mon Mar 27 15:36:47 2006 -0700 +++ b/tools/libxc/xc_ptrace.c Tue Mar 28 08:54:58 2006 -0700 @@ -38,9 +38,6 @@ static char *ptrace_names[] = { }; #endif -/* XXX application state */ -static long nr_pages = 0; -static unsigned long *page_array = NULL; static int current_domid = -1; static int current_isfile; @@ -196,6 +193,60 @@ map_domain_va_pae( return (void *)((unsigned long)v | (va & (PAGE_SIZE - 1))); } +#ifdef __x86_64__ +static void * +map_domain_va( + int xc_handle, + int cpu, + void *guest_va, + int perm) +{ + unsigned long l3p, l2p, l1p, p, va = (unsigned long)guest_va; + uint64_t *l4, *l3, *l2, *l1; + static void *v; + + if ((ctxt[cpu].ctrlreg[4] & 0x20) == 0 ) /* legacy ia32 mode */ + return map_domain_va_pae(xc_handle, cpu, guest_va, perm); + + if (fetch_regs(xc_handle, cpu, NULL)) + return NULL; + + l4 = xc_map_foreign_range( + xc_handle, current_domid, PAGE_SIZE, PROT_READ, ctxt[cpu].ctrlreg[3] >> PAGE_SHIFT); + if ( l4 == NULL ) + return NULL; + + l3p = l4[l4_table_offset(va)] >> PAGE_SHIFT; + l3 = xc_map_foreign_range(xc_handle, current_domid, PAGE_SIZE, PROT_READ, l3p); + if ( l3 == NULL ) + return NULL; + + l2p = l3[l3_table_offset(va)] >> PAGE_SHIFT; + l2 = xc_map_foreign_range(xc_handle, current_domid, PAGE_SIZE, PROT_READ, l2p); + if ( l2 == NULL ) + return NULL; + + l1p = l2[l2_table_offset(va)] >> PAGE_SHIFT; + l1 = xc_map_foreign_range(xc_handle, current_domid, PAGE_SIZE, perm, l1p); + if ( l1 == NULL ) + return NULL; + + p = l1[l1_table_offset(va)] >> PAGE_SHIFT; + if ( v != NULL ) + munmap(v, PAGE_SIZE); + v = xc_map_foreign_range(xc_handle, current_domid, PAGE_SIZE, perm, p); + if ( v == NULL ) + return NULL; + + return (void *)((unsigned long)v | (va & (PAGE_SIZE - 1))); +} +#endif + +#ifdef __i386__ +/* XXX application state */ +static long nr_pages = 0; +static unsigned long *page_array = NULL; + static void * map_domain_va( int xc_handle, @@ -216,15 +267,18 @@ map_domain_va( static unsigned long page_phys[MAX_VIRT_CPUS]; static unsigned long *page_virt[MAX_VIRT_CPUS]; static int prev_perm[MAX_VIRT_CPUS]; - static enum { MODE_UNKNOWN, MODE_32, MODE_PAE } mode; + static enum { MODE_UNKNOWN, MODE_32, MODE_PAE, MODE_64 } mode; if ( mode == MODE_UNKNOWN ) { xen_capabilities_info_t caps; (void)xc_version(xc_handle, XENVER_capabilities, caps); - mode = MODE_32; - if ( strstr(caps, "_x86_32p") ) + if ( strstr(caps, "-x86_64") ) + mode = MODE_64; + else if ( strstr(caps, "-x86_32p") ) mode = MODE_PAE; + else if ( strstr(caps, "-x86_32") ) + mode = MODE_32; } if ( mode == MODE_PAE ) @@ -303,6 +357,8 @@ map_domain_va( return (void *)(((unsigned long)page_virt[cpu]) | (va & BSD_PAGE_MASK)); } + +#endif static int __xc_waitdomain( diff -r 7e3cbc409676 -r d75a6cc5e68a tools/libxc/xc_ptrace.h --- a/tools/libxc/xc_ptrace.h Mon Mar 27 15:36:47 2006 -0700 +++ b/tools/libxc/xc_ptrace.h Tue Mar 28 08:54:58 2006 -0700 @@ -9,6 +9,96 @@ #define BSD_PAGE_MASK (PAGE_SIZE-1) #define PDRSHIFT 22 #define PSL_T 0x00000100 /* trace enable bit */ + +#ifdef __x86_64__ +struct gdb_regs +{ + unsigned long r15; + unsigned long r14; + unsigned long r13; + unsigned long r12; + unsigned long rbp; + unsigned long rbx; + unsigned long r11; + unsigned long r10; + unsigned long r9; + unsigned long r8; + unsigned long rax; + unsigned long rcx; + unsigned long rdx; + unsigned long rsi; + unsigned long rdi; + unsigned long orig_rax; + unsigned long rip; + unsigned long xcs; + unsigned long eflags; + unsigned long rsp; + unsigned long xss; + unsigned long fs_base; + unsigned long gs_base; + unsigned long xds; + unsigned long xes; + unsigned long xfs; + unsigned long xgs; +}; + +#define SET_PT_REGS(pt, xc) \ +{ \ + pt.r8 = xc.r8; \ + pt.r9 = xc.r9; \ + pt.r10 = xc.r10; \ + pt.r11 = xc.r11; \ + pt.r12 = xc.r12; \ + pt.r13 = xc.r13; \ + pt.r14 = xc.r14; \ + pt.r15 = xc.r15; \ + pt.rbx = xc.rbx; \ + pt.rcx = xc.rcx; \ + pt.rdx = xc.rdx; \ + pt.rsi = xc.rsi; \ + pt.rdi = xc.rdi; \ + pt.rbp = xc.rbp; \ + pt.rax = xc.rax; \ + pt.rip = xc.rip; \ + pt.xcs = xc.cs; \ + pt.eflags = xc.eflags; \ + pt.rsp = xc.rsp; \ + pt.xss = xc.ss; \ + pt.xes = xc.es; \ + pt.xds = xc.ds; \ + pt.xfs = xc.fs; \ + pt.xgs = xc.gs; \ +} + +#define SET_XC_REGS(pt, xc) \ +{ \ + xc.r8 = pt->r8; \ + xc.r9 = pt->r9; \ + xc.r10 = pt->r10; \ + xc.r11 = pt->r11; \ + xc.r12 = pt->r12; \ + xc.r13 = pt->r13; \ + xc.r14 = pt->r14; \ + xc.r15 = pt->r15; \ + xc.rbx = pt->rbx; \ + xc.rcx = pt->rcx; \ + xc.rdx = pt->rdx; \ + xc.rsi = pt->rsi; \ + xc.rdi = pt->rdi; \ + xc.rbp = pt->rbp; \ + xc.rax = pt->rax; \ + xc.rip = pt->rip; \ + xc.cs = pt->xcs; \ + xc.eflags = pt->eflags; \ + xc.rsp = pt->rsp; \ + xc.ss = pt->xss; \ + xc.es = pt->xes; \ + xc.ds = pt->xds; \ + xc.fs = pt->xfs; \ + xc.gs = pt->xgs; \ +} + +#elif __i386__ struct gdb_regs { long ebx; /* 0 */ @@ -30,8 +120,6 @@ struct gdb_regs { int xss; /* 64 */ }; - -#define printval(x) printf("%s = %lx\n", #x, (long)x); #define SET_PT_REGS(pt, xc) \ { \ pt.ebx = xc.ebx; \ @@ -71,7 +159,9 @@ struct gdb_regs { xc.fs = pt->xfs; \ xc.gs = pt->xgs; \ } +#endif +#define printval(x) printf("%s = %lx\n", #x, (long)x); #define vtopdi(va) ((va) >> PDRSHIFT) #define vtopti(va) (((va) >> PAGE_SHIFT) & 0x3ff) #endif diff -r 7e3cbc409676 -r d75a6cc5e68a tools/python/xen/xend/XendClient.py --- a/tools/python/xen/xend/XendClient.py Mon Mar 27 15:36:47 2006 -0700 +++ b/tools/python/xen/xend/XendClient.py Tue Mar 28 08:54:58 2006 -0700 @@ -14,403 +14,15 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #============================================================================ # Copyright (C) 2004, 2005 Mike Wray <mike.wray@xxxxxx> +# Copyright (C) 2006 Anthony Liguori <aliguori@xxxxxxxxxx> #============================================================================ -"""Client API for the HTTP interface on xend. -Callable as a script - see main(). -Supports inet or unix connection to xend. +from xen.util.xmlrpclib2 import ServerProxy -This API is the 'control-plane' for xend. -The 'data-plane' is done separately. -""" -import os -import sys -import types +XML_RPC_SOCKET = "/var/run/xend-xmlrpc.sock" -import sxp -import PrettyPrint -from XendProtocol import HttpXendClientProtocol, \ - UnixXendClientProtocol, \ - XendError +ERROR_INTERNAL = 1 +ERROR_GENERIC = 2 +ERROR_INVALID_DOMAIN = 3 -def fileof(val): - """Converter for passing configs or other 'large' data. - Handles lists, files directly. - Assumes a string is a file name and passes its contents. - """ - if isinstance(val, types.ListType): - return sxp.to_string(val) - if isinstance(val, types.StringType): - return file(val) - if hasattr(val, 'readlines'): - return val - raise XendError('cannot convert value') - -class URL: - """A URL. - """ - - def __init__(self, proto='http', host='localhost', port=None, path='', query=None, frag=None): - self.proto = proto - self.host = host - if port: port = int(port) - self.port = port - self.path = path - self.query = query - self.frag = frag - - def url(self): - """Get the full URL string including protocol, location and the full path. - """ - return self.proto + '://' + self.location() + self.fullpath() - - def location(self): - """Get the location part of the URL, including host and port, if present. - """ - if self.port: - return self.host + ':' + str(self.port) - else: - return self.host - - def fullpath(self): - """Get the full path part of the URL, including query and fragment if present. - """ - u = [ self.path ] - if self.query: - u.append('?') - u.append(self.query) - if self.frag: - u.append('#') - u.append(self.frag) - return ''.join(u) - - def relative(self, path='', query=None, frag=None): - """Create a URL relative to this one. - """ - return URL(proto=self.proto, - host=self.host, - port=self.port, - path=self.path + path, - query=query, - frag=frag) - -class Xend: - """Client interface to Xend. - """ - - """Default location of the xend server.""" - SRV_DEFAULT = "localhost:8000" - - """Environment variable to set the location of xend.""" - SRV_VAR = "XEND" - - """Default path to the xend root on the server.""" - ROOT_DEFAULT = "/xend/" - - """Environment variable to set the xend root path.""" - ROOT_VAR = "XEND_ROOT" - - def __init__(self, client=None, srv=None, root=None): - """Create a xend client interface. - If the client protocol is not specified, the default - is to use a synchronous protocol. - - @param client: client protocol to use - @param srv: server host, and optional port (format host:port) - @param root: xend root path on the server - """ - if client is None: - client = HttpXendClientProtocol() - self.client = client - self.bind(srv, root) - - def default_server(self): - """Get the default location of the xend server. - """ - return os.getenv(self.SRV_VAR, self.SRV_DEFAULT) - - def default_root(self): - """Get the default root path on the xend server. - """ - return os.getenv(self.ROOT_VAR, self.ROOT_DEFAULT) - - def bind(self, srv=None, root=None): - """Bind to a given server. - - @param srv: server location (host:port) - @param root: xend root path on the server - """ - if srv is None: srv = self.default_server() - if root is None: root = self.default_root() - if not root.endswith('/'): root += '/' - (host, port) = srv.split(':', 1) - self.url = URL(host=host, port=port, path=root) - - def xendGet(self, url, args=None): - return self.client.xendGet(url, args) - - def xendPost(self, url, data): - return self.client.xendPost(url, data) - - def nodeurl(self, id=''): - return self.url.relative('node/' + str(id)) - - def domainurl(self, id=''): - return self.url.relative('domain/' + str(id)) - - def deviceurl(self, id=''): - return self.url.relative('device/' + str(id)) - - def vneturl(self, id=''): - return self.url.relative('vnet/' + str(id)) - - def xend(self): - return self.xendGet(self.url) - - def xend_node(self): - return self.xendGet(self.nodeurl()) - - def xend_node_shutdown(self): - return self.xendPost(self.nodeurl(), - {'op' : 'shutdown'}) - - def xend_node_restart(self): - return self.xendPost(self.nodeurl(), - {'op' : 'reboot'}) - - def xend_node_get_dmesg(self): - return self.xendGet(self.nodeurl('dmesg')) - - def xend_node_clear_dmesg(self): - return self.xendPost(self.nodeurl('dmesg'), - {'op' : 'clear' } ) - - def xend_node_log(self): - return self.xendGet(self.nodeurl('log')) - - def xend_node_cpu_bvt_slice_set(self, ctx_allow): - return self.xendPost(self.nodeurl(), - {'op' : 'cpu_bvt_slice_set', - 'ctx_allow' : ctx_allow }) - - def xend_domains(self): - return self.xendGet(self.domainurl()) - - def xend_list_domains(self, detail = True): - return self.xendGet(self.domainurl(), - {'detail': detail and '1' or '0'}) - - def xend_domain_vcpuinfo(self, dom): - return self.xendGet(self.domainurl(dom), {'op': 'vcpuinfo'}) - - def xend_domain_create(self, conf): - return self.xendPost(self.domainurl(), - {'op' : 'create', - 'config' : fileof(conf) }) - - def xend_domain_restore(self, filename): - return self.xendPost(self.domainurl(), - {'op' : 'restore', - 'file' : filename }) - - def xend_domain_configure(self, id, conf): - return self.xendPost(self.domainurl(id), - {'op' : 'configure', - 'config' : fileof(conf) }) - - def xend_domain(self, id): - return self.xendGet(self.domainurl(id)) - - def xend_domain_wait_for_devices(self, id): - return self.xendPost(self.domainurl(id), - {'op' : 'wait_for_devices' }) - - def xend_domain_unpause(self, id): - return self.xendPost(self.domainurl(id), - {'op' : 'unpause' }) - - def xend_domain_pause(self, id): - return self.xendPost(self.domainurl(id), - {'op' : 'pause' }) - - def xend_domain_rename(self, id, name): - return self.xendPost(self.domainurl(id), - {'op' : 'rename', - 'name' : name}) - - def xend_domain_shutdown(self, id, reason): - return self.xendPost(self.domainurl(id), - {'op' : 'shutdown', - 'reason' : reason}) - - def xend_domain_sysrq(self, id, key): - return self.xendPost(self.domainurl(id), - {'op' : 'sysrq', - 'key' : key}) - - def xend_domain_destroy(self, id): - return self.xendPost(self.domainurl(id), - {'op' : 'destroy' }) - - def xend_domain_save(self, id, filename): - return self.xendPost(self.domainurl(id), - {'op' : 'save', - 'file' : filename }) - - def xend_domain_migrate(self, id, dst, live=0, resource=0, port=0): - return self.xendPost(self.domainurl(id), - {'op' : 'migrate', - 'destination': dst, - 'live' : live, - 'resource' : resource, - 'port' : port }) - - def xend_domain_pincpu(self, id, vcpu, cpumap): - return self.xendPost(self.domainurl(id), - {'op' : 'pincpu', - 'vcpu' : vcpu, - 'cpumap' : str(cpumap) }) - - def xend_domain_cpu_bvt_set(self, id, mcuadv, warpback, warpvalue, warpl, warpu): - return self.xendPost(self.domainurl(id), - {'op' : 'cpu_bvt_set', - 'mcuadv' : mcuadv, - 'warpback' : warpback, - 'warpvalue': warpvalue, - 'warpl' : warpl, - 'warpu' : warpu }) - - def xend_domain_cpu_sedf_get(self, id): - return self.xendPost(self.domainurl(id), - {'op' : 'cpu_sedf_get'}) - - def xend_domain_cpu_sedf_set(self, id, period, slice, latency, extratime, weight): - return self.xendPost(self.domainurl(id), - {'op' : 'cpu_sedf_set', - 'period' : period, - 'slice' : slice, - 'latency' : latency, - 'extratime' : extratime, - 'weight' : weight }) - - def xend_domain_maxmem_set(self, id, memory): - return self.xendPost(self.domainurl(id), - { 'op' : 'maxmem_set', - 'memory' : memory }) - - def xend_domain_mem_target_set(self, id, mem_target): - val = self.xendPost(self.domainurl(id), - {'op' : 'mem_target_set', - 'target' : mem_target }) - return val - - def xend_domain_set_vcpus(self, dom, vcpus): - return self.xendPost(self.domainurl(dom), - {'op' : 'set_vcpus', - 'vcpus' : vcpus }) - - def xend_domain_devices(self, id, type): - return self.xendPost(self.domainurl(id), - {'op' : 'devices', - 'type' : type }) - - def xend_domain_device_create(self, id, config): - return self.xendPost(self.domainurl(id), - {'op' : 'device_create', - 'config' : fileof(config) }) - - def xend_domain_device_refresh(self, id, type, dev): - return self.xendPost(self.domainurl(id), - {'op' : 'device_refresh', - 'type' : type, - 'dev' : dev }) - - def xend_domain_device_destroy(self, id, type, dev): - return self.xendPost(self.domainurl(id), - {'op' : 'device_destroy', - 'type' : type, - 'dev' : dev }) - - def xend_domain_device_configure(self, id, config, dev): - return self.xendPost(self.domainurl(id), - {'op' : 'device_configure', - 'dev' : dev, - 'config' : fileof(config) }) - - def xend_vnets(self): - return self.xendGet(self.vneturl()) - - def xend_vnet_create(self, conf): - return self.xendPost(self.vneturl(), - {'op' : 'create', - 'config' : fileof(conf) }) - - def xend_vnet(self, id): - return self.xendGet(self.vneturl(id)) - - def xend_vnet_delete(self, id): - return self.xendPost(self.vneturl(id), - {'op' : 'delete' }) - -def getHttpServer(srv=None): - """Create and return a xend client. - """ - return Xend(srv=srv, client=HttpXendClientProtocol()) - -def getUnixServer(srv=None): - """Create and return a unix-domain xend client. - """ - return Xend(client=UnixXendClientProtocol(srv)) - -def xendmain(srv, fn, args, unix=False): - if unix: - xend = getUnixServer(srv) - else: - xend = getHttpServer(srv) - xend.rc = 0 - try: - v = getattr(xend, fn)(*args) - PrettyPrint.prettyprint(v) - return 0 - except XendError, err: - print 'ERROR:', err - return 1 - -def main(argv): - """Call an API function: - - python XendClient.py fn args... - - The leading 'xend_' on the function can be omitted. - Example: - -python XendClient.py domains - (0 8) -python XendClient.py domain 0 - (domain (id 0) (name Domain-0) (memory 128)) - """ - from getopt import getopt - short_options = 'x:au:d' - long_options = ['xend=', 'unix=', 'debug'] - (options, args) = getopt(argv[1:], short_options, long_options) - srv = None - unix = 1 - for k, v in options: - if k in ['-x', '--xend']: - srv = v - elif k in ['-u', '--unix']: - unix = int(v) - if len(args): - fn = args[0] - args = args[1:] - else: - fn = 'xend' - args = [] - if not fn.startswith('xend'): - fn = 'xend_' + fn - sys.exit(xendmain(srv, fn, args, unix=unix)) - -if __name__ == "__main__": - main(sys.argv) -else: - server = getUnixServer() +server = ServerProxy('httpu:///var/run/xend-xmlrpc.sock') diff -r 7e3cbc409676 -r d75a6cc5e68a tools/python/xen/xend/XendDomain.py --- a/tools/python/xen/xend/XendDomain.py Mon Mar 27 15:36:47 2006 -0700 +++ b/tools/python/xen/xend/XendDomain.py Tue Mar 28 08:54:58 2006 -0700 @@ -81,7 +81,8 @@ class XendDomain: # that we're sure that we haven't missed any releases, but inside # the domains_lock, as we don't want the watch to fire until after # the refresh call has completed. - xswatch("@releaseDomain", self.onReleaseDomain) + xswatch("@introduceDomain", self.onChangeDomain) + xswatch("@releaseDomain", self.onChangeDomain) self.refresh(True) finally: @@ -121,7 +122,7 @@ class XendDomain: ## private: - def onReleaseDomain(self, _): + def onChangeDomain(self, _): self.domains_lock.acquire() try: self.refresh() @@ -355,7 +356,7 @@ class XendDomain: def domain_unpause(self, domid): """Unpause domain execution.""" try: - dominfo = self.domain_lookup(domid) + dominfo = self.domain_lookup_by_name_or_id_nr(domid) log.info("Domain %s (%d) unpaused.", dominfo.getName(), dominfo.getDomid()) return dominfo.unpause() @@ -366,7 +367,7 @@ class XendDomain: def domain_pause(self, domid): """Pause domain execution.""" try: - dominfo = self.domain_lookup(domid) + dominfo = self.domain_lookup_by_name_or_id_nr(domid) log.info("Domain %s (%d) paused.", dominfo.getName(), dominfo.getDomid()) return dominfo.pause() @@ -377,10 +378,10 @@ class XendDomain: def domain_destroy(self, domid): """Terminate domain immediately.""" - if domid == PRIV_DOMAIN: - raise XendError("Cannot destroy privileged domain %i" % domid) - - dominfo = self.domain_lookup(domid) + dominfo = self.domain_lookup_by_name_or_id_nr(domid) + if dominfo and dominfo.getDomid() == PRIV_DOMAIN: + raise XendError("Cannot destroy privileged domain %s" % domid) + if dominfo: val = dominfo.destroy() else: @@ -393,7 +394,7 @@ class XendDomain: def domain_migrate(self, domid, dst, live=False, resource=0, port=0): """Start domain migration.""" - dominfo = self.domain_lookup(domid) + dominfo = self.domain_lookup_by_name_or_id_nr(domid) if dominfo.getDomid() == PRIV_DOMAIN: raise XendError("Cannot migrate privileged domain %i" % domid) @@ -418,7 +419,7 @@ class XendDomain: """ try: - dominfo = self.domain_lookup(domid) + dominfo = self.domain_lookup_by_name_or_id_nr(domid) if dominfo.getDomid() == PRIV_DOMAIN: raise XendError("Cannot save privileged domain %i" % domid) @@ -438,7 +439,7 @@ class XendDomain: @param cpumap: string repr of list of usable cpus """ - dominfo = self.domain_lookup(domid) + dominfo = self.domain_lookup_by_name_or_id_nr(domid) # convert cpumap string into a list of ints cpumap = map(lambda x: int(x), cpumap.replace("[", "").replace("]", "").split(",")) @@ -451,7 +452,7 @@ class XendDomain: warpu): """Set BVT (Borrowed Virtual Time) scheduler parameters for a domain. """ - dominfo = self.domain_lookup(domid) + dominfo = self.domain_lookup_by_name_or_id_nr(domid) try: return xc.bvtsched_domain_set(dom=dominfo.getDomid(), mcuadv=mcuadv, @@ -464,7 +465,7 @@ class XendDomain: def domain_cpu_bvt_get(self, domid): """Get BVT (Borrowed Virtual Time) scheduler parameters for a domain. """ - dominfo = self.domain_lookup(domid) + dominfo = self.domain_lookup_by_name_or_id_nr(domid) try: return xc.bvtsched_domain_get(dominfo.getDomid()) except Exception, ex: @@ -475,7 +476,7 @@ class XendDomain: weight): """Set Simple EDF scheduler parameters for a domain. """ - dominfo = self.domain_lookup(domid) + dominfo = self.domain_lookup_by_name_or_id_nr(domid) try: return xc.sedf_domain_set(dominfo.getDomid(), period, slice_, latency, extratime, weight) @@ -485,7 +486,7 @@ class XendDomain: def domain_cpu_sedf_get(self, domid): """Get Simple EDF scheduler parameters for a domain. """ - dominfo = self.domain_lookup(domid) + dominfo = self.domain_lookup_by_name_or_id_nr(domid) try: sedf_info = xc.sedf_domain_get(dominfo.getDomid()) @@ -507,7 +508,7 @@ class XendDomain: @param mem: memory limit (in MiB) @return: 0 on success, -1 on error """ - dominfo = self.domain_lookup(domid) + dominfo = self.domain_lookup_by_name_or_id_nr(domid) maxmem = int(mem) * 1024 try: return xc.domain_setmaxmem(dominfo.getDomid(), maxmem) @@ -521,7 +522,7 @@ class XendDomain: @param last: last IO port @return: 0 on success, -1 on error """ - dominfo = self.domain_lookup(domid) + dominfo = self.domain_lookup_by_name_or_id_nr(domid) nr_ports = last - first + 1 try: return xc.domain_ioport_permission(dominfo.getDomid(), @@ -538,7 +539,7 @@ class XendDomain: @param last: last IO port @return: 0 on success, -1 on error """ - dominfo = self.domain_lookup(domid) + dominfo = self.domain_lookup_by_name_or_id_nr(domid) nr_ports = last - first + 1 try: return xc.domain_ioport_permission(dominfo.getDomid(), diff -r 7e3cbc409676 -r d75a6cc5e68a tools/python/xen/xend/XendError.py --- a/tools/python/xen/xend/XendError.py Mon Mar 27 15:36:47 2006 -0700 +++ b/tools/python/xen/xend/XendError.py Tue Mar 28 08:54:58 2006 -0700 @@ -15,9 +15,18 @@ # Copyright (C) 2004, 2005 Mike Wray <mike.wray@xxxxxx> #============================================================================ -class XendError(ValueError): +from xmlrpclib import Fault + +import XendClient + +class XendInvalidDomain(Fault): + def __init__(self, value): + Fault.__init__(self, XendClient.ERROR_INVALID_DOMAIN, value) + +class XendError(Fault): def __init__(self, value): + Fault.__init__(self, XendClient.ERROR_GENERIC, value) self.value = value def __str__(self): diff -r 7e3cbc409676 -r d75a6cc5e68a tools/python/xen/xend/XendRoot.py --- a/tools/python/xen/xend/XendRoot.py Mon Mar 27 15:36:47 2006 -0700 +++ b/tools/python/xen/xend/XendRoot.py Tue Mar 28 08:54:58 2006 -0700 @@ -57,8 +57,13 @@ class XendRoot: """Default level of information to be logged.""" loglevel_default = 'DEBUG' - """Default for the flag indicating whether xend should run an http server.""" + """Default for the flag indicating whether xend should run an http server + (deprecated).""" xend_http_server_default = 'no' + + xend_tcp_xmlrpc_server_default = 'no' + + xend_unix_xmlrpc_server_default = 'yes' """Default interface address xend listens at. """ xend_address_default = '' @@ -77,8 +82,9 @@ class XendRoot: xend_relocation_hosts_allow_default = '' - """Default for the flag indicating whether xend should run a unix-domain server.""" - xend_unix_server_default = 'yes' + """Default for the flag indicating whether xend should run a unix-domain + server (deprecated).""" + xend_unix_server_default = 'no' """Default path the unix-domain server listens at.""" xend_unix_path_default = '/var/lib/xend/xend-socket' @@ -180,6 +186,12 @@ class XendRoot: """ return self.get_config_bool("xend-http-server", self.xend_http_server_default) + def get_xend_tcp_xmlrpc_server(self): + return self.get_config_bool("xend-tcp-xmlrpc-server", self.xend_tcp_xmlrpc_server_default) + + def get_xend_unix_xmlrpc_server(self): + return self.get_config_bool("xend-unix-xmlrpc-server", self.xend_unix_xmlrpc_server_default) + def get_xend_relocation_server(self): """Get the flag indicating whether xend should run a relocation server. """ diff -r 7e3cbc409676 -r d75a6cc5e68a tools/python/xen/xend/server/SrvServer.py --- a/tools/python/xen/xend/server/SrvServer.py Mon Mar 27 15:36:47 2006 -0700 +++ b/tools/python/xen/xend/server/SrvServer.py Tue Mar 28 08:54:58 2006 -0700 @@ -52,6 +52,7 @@ from xen.web.SrvDir import SrvDir from xen.web.SrvDir import SrvDir from SrvRoot import SrvRoot +from XMLRPCServer import XMLRPCServer xroot = XendRoot.instance() @@ -114,4 +115,10 @@ def create(): path = xroot.get_xend_unix_path() log.info('unix path=' + path) servers.add(UnixHttpServer(root, path)) + + if xroot.get_xend_tcp_xmlrpc_server(): + servers.add(XMLRPCServer(True)) + + if xroot.get_xend_unix_xmlrpc_server(): + servers.add(XMLRPCServer()) return servers diff -r 7e3cbc409676 -r d75a6cc5e68a tools/python/xen/xend/server/pciif.py --- a/tools/python/xen/xend/server/pciif.py Mon Mar 27 15:36:47 2006 -0700 +++ b/tools/python/xen/xend/server/pciif.py Tue Mar 28 08:54:58 2006 -0700 @@ -118,10 +118,12 @@ class PciController(DevController): "parse it's resources - %s"+str(e)) if dev.driver!='pciback': - raise VmError(("pci: PCI Backend does not own device "+ - "%s\n"+ - "See the pciback.hide kernel "+ - "command-line parameter")%(dev.name)) + raise VmError(("pci: PCI Backend does not own device "+ \ + "%s\n"+ \ + "See the pciback.hide kernel "+ \ + "command-line parameter or\n"+ \ + "bind your slot/device to the PCI backend using sysfs" \ + )%(dev.name)) for (start, size) in dev.ioports: log.debug('pci: enabling ioport 0x%x/0x%x'%(start,size)) diff -r 7e3cbc409676 -r d75a6cc5e68a tools/python/xen/xm/create.py --- a/tools/python/xen/xm/create.py Mon Mar 27 15:36:47 2006 -0700 +++ b/tools/python/xen/xm/create.py Tue Mar 28 08:54:58 2006 -0700 @@ -30,7 +30,7 @@ import re from xen.xend import sxp from xen.xend import PrettyPrint -from xen.xend.XendClient import server, XendError +from xen.xend.XendClient import server from xen.xend.XendBootloader import bootloader from xen.util import blkif @@ -813,8 +813,8 @@ def make_domain(opts, config): """ try: - dominfo = server.xend_domain_create(config) - except XendError, ex: + dominfo = server.xend.domain.create(config) + except Exception, ex: import signal if vncpid: os.kill(vncpid, signal.SIGKILL) @@ -822,13 +822,17 @@ def make_domain(opts, config): dom = sxp.child_value(dominfo, 'name') - if server.xend_domain_wait_for_devices(dom) < 0: - server.xend_domain_destroy(dom) + try: + server.xend.domain.waitForDevices(dom) + except: + server.xend.domain.destroy(dom) err("Device creation failed for domain %s" % dom) if not opts.vals.paused: - if server.xend_domain_unpause(dom) < 0: - server.xend_domain_destroy(dom) + try: + server.xend.domain.unpause(dom) + except: + server.xend.domain.destroy(dom) err("Failed to unpause domain %s" % dom) opts.info("Started domain %s" % (dom)) return int(sxp.child_value(dominfo, 'domid')) diff -r 7e3cbc409676 -r d75a6cc5e68a tools/python/xen/xm/main.py --- a/tools/python/xen/xm/main.py Mon Mar 27 15:36:47 2006 -0700 +++ b/tools/python/xen/xm/main.py Tue Mar 28 08:54:58 2006 -0700 @@ -1,6 +1,6 @@ # (C) Copyright IBM Corp. 2005 # Copyright (C) 2004 Mike Wray -# Copyright (c) 2005 XenSource Ltd +# Copyright (c) 2005-2006 XenSource Ltd. # # Authors: # Sean Dague <sean at dague dot net> @@ -29,8 +29,8 @@ import socket import socket import warnings warnings.filterwarnings('ignore', category=FutureWarning) - -import xen.xend.XendError +import xmlrpclib + import xen.xend.XendProtocol from xen.xend import PrettyPrint @@ -38,7 +38,8 @@ from xen.xm.opts import * from xen.xm.opts import * import console - +import xen.xend.XendClient +from xen.xend.XendClient import server # getopt.gnu_getopt is better, but only exists in Python 2.3+. Use # getopt.getopt if gnu_getopt is not available. This will mean that options @@ -319,8 +320,7 @@ def xm_save(args): err("xm save: Unable to create file %s" % savefile) sys.exit(1) - from xen.xend.XendClient import server - server.xend_domain_save(dom, savefile) + server.xend.domain.save(dom, savefile) def xm_restore(args): arg_check(args, "restore", 1) @@ -331,16 +331,14 @@ def xm_restore(args): err("xm restore: Unable to read file %s" % savefile) sys.exit(1) - from xen.xend.XendClient import server - server.xend_domain_restore(savefile) + server.xend.domain.restore(savefile) def getDomains(domain_names): - from xen.xend.XendClient import server if domain_names: - return map(server.xend_domain, domain_names) - else: - return server.xend_list_domains() + return map(server.xend.domain, domain_names) + else: + return server.xend.domains(1) def xm_list(args): @@ -416,12 +414,11 @@ def xm_brief_list(doms): def xm_vcpu_list(args): - from xen.xend.XendClient import server if args: - dominfo = map(server.xend_domain_vcpuinfo, args) - else: - doms = server.xend_list_domains(False) - dominfo = map(server.xend_domain_vcpuinfo, doms) + dominfo = map(server.xend.domain.getVCPUInfo, args) + else: + doms = server.xend.domains(False) + dominfo = map(server.xend.domain.getVCPUInfo, doms) print 'Name ID VCPU CPU State Time(s) CPU Affinity' @@ -475,8 +472,7 @@ def xm_vcpu_list(args): cpumap = map(lambda x: int(x), cpumap) cpumap.sort() - from xen.xend.XendClient import server - for x in server.xend_node()[1:]: + for x in server.xend.node.info()[1:]: if len(x) > 1 and x[0] == 'nr_cpus': nr_cpus = int(x[1]) # normalize cpumap by modulus nr_cpus, and drop duplicates @@ -532,21 +528,18 @@ def xm_pause(args): arg_check(args, "pause", 1) dom = args[0] - from xen.xend.XendClient import server - server.xend_domain_pause(dom) + server.xend.domain.pause(dom) def xm_unpause(args): arg_check(args, "unpause", 1) dom = args[0] - from xen.xend.XendClient import server - server.xend_domain_unpause(dom) + server.xend.domain.unpause(dom) def xm_rename(args): arg_check(args, "rename", 2) - from xen.xend.XendClient import server - server.xend_domain_rename(args[0], args[1]) + server.xend.domain.setName(args[0], args[1]) def xm_subcommand(command, args): cmd = __import__(command, globals(), locals(), 'xen.xm') @@ -574,8 +567,7 @@ def xm_vcpu_pin(args): vcpu = int(args[1]) cpumap = cpu_make_map(args[2]) - from xen.xend.XendClient import server - server.xend_domain_pincpu(dom, vcpu, cpumap) + server.xend.domain.pincpu(dom, vcpu, cpumap) def xm_mem_max(args): arg_check(args, "mem-max", 2) @@ -583,8 +575,7 @@ def xm_mem_max(args): dom = args[0] mem = int_unit(args[1], 'm') - from xen.xend.XendClient import server - server.xend_domain_maxmem_set(dom, mem) + server.xend.domain.maxmem_set(dom, mem) def xm_mem_set(args): arg_check(args, "mem-set", 2) @@ -592,20 +583,17 @@ def xm_mem_set(args): dom = args[0] mem_target = int_unit(args[1], 'm') - from xen.xend.XendClient import server - server.xend_domain_mem_target_set(dom, mem_target) + server.xend.domain.setMemoryTarget(dom, mem_target) def xm_vcpu_set(args): arg_check(args, "vcpu-set", 2) - from xen.xend.XendClient import server - server.xend_domain_set_vcpus(args[0], int(args[1])) + server.xend.domain.setVCpuCount(args[0], int(args[1])) def xm_destroy(args): arg_check(args, "destroy", 1) - from xen.xend.XendClient import server - server.xend_domain_destroy(args[0]) + server.xend.domain.destroy(args[0]) def xm_domid(args): @@ -613,8 +601,7 @@ def xm_domid(args): name = args[0] - from xen.xend.XendClient import server - dom = server.xend_domain(name) + dom = server.xend.domain(name) print sxp.child_value(dom, 'domid') def xm_domname(args): @@ -622,23 +609,20 @@ def xm_domname(args): name = args[0] - from xen.xend.XendClient import server - dom = server.xend_domain(name) + dom = server.xend.domain(name) print sxp.child_value(dom, 'name') def xm_sched_bvt(args): arg_check(args, "sched-bvt", 6) dom = args[0] v = map(long, args[1:6]) - from xen.xend.XendClient import server - server.xend_domain_cpu_bvt_set(dom, *v) + server.xend.domain.cpu_bvt_set(dom, *v) def xm_sched_bvt_ctxallow(args): arg_check(args, "sched-bvt-ctxallow", 1) slice = int(args[0]) - from xen.xend.XendClient import server - server.xend_node_cpu_bvt_slice_set(slice) + server.xend.node.cpu_bvt_slice_set(slice) def xm_sched_sedf(args): def ns_to_ms(val): @@ -695,13 +679,12 @@ def xm_sched_sedf(args): 'Slice(ms)', 'Lat(ms)', 'Extra','Weight') - from xen.xend.XendClient import server doms = filter(lambda x : domid_match(domid, x), [parse_doms_info(dom) for dom in getDomains("")]) for d in doms: # fetch current values so as not to clobber them sedf_info = \ - parse_sedf_info(server.xend_domain_cpu_sedf_get(d['dom'])) + parse_sedf_info(server.xend.domain.cpu_sedf_get(d['dom'])) sedf_info['name'] = d['name'] # update values in case of call to set @@ -713,7 +696,7 @@ def xm_sched_sedf(args): v = map(int, [sedf_info['period'], sedf_info['slice'], sedf_info['latency'],sedf_info['extratime'], sedf_info['weight']]) - rv = server.xend_domain_cpu_sedf_set(d['dom'], *v) + rv = server.xend.domain.cpu_sedf_set(d['dom'], *v) if int(rv) != 0: err("Failed to set sedf parameters (rv=%d)."%(rv)) @@ -725,8 +708,7 @@ def xm_info(args): def xm_info(args): arg_check(args, "info", 0) - from xen.xend.XendClient import server - info = server.xend_node() + info = server.xend.node.info() for x in info[1:]: if len(x) < 2: @@ -738,8 +720,7 @@ def xm_console(args): arg_check(args, "console", 1) dom = args[0] - from xen.xend.XendClient import server - info = server.xend_domain(dom) + info = server.xend.domain(dom) domid = int(sxp.child_value(info, 'domid', '-1')) console.execConsole(domid) @@ -768,17 +749,15 @@ its contents if the [-c|--clear] flag is if not (1 <= len(myargs) <= 2): err('Invalid arguments: ' + str(myargs)) - from xen.xend.XendClient import server if not gopts.vals.clear: - print server.xend_node_get_dmesg() - else: - server.xend_node_clear_dmesg() + print server.xend.node.dmesg.info() + else: + server.xend.node.dmesg.clear() def xm_log(args): arg_check(args, "log", 0) - from xen.xend.XendClient import server - print server.xend_node_log() + print server.xend.node.log() def parse_dev_info(info): def get_info(n, t, d): @@ -826,13 +805,12 @@ def xm_network_list(args): print 'No domain parameter given' sys.exit(1) dom = params[0] - from xen.xend.XendClient import server if use_long: - devs = server.xend_domain_devices(dom, 'vif') + devs = server.xend.domain.getDeviceSxprs(dom, 'vif') map(PrettyPrint.prettyprint, devs) else: hdr = 0 - for x in server.xend_domain_devices(dom, 'vif'): + for x in server.xend.domain.getDeviceSxprs(dom, 'vif'): if hdr == 0: print 'Idx BE MAC Addr. handle state evt-ch tx-/rx-ring-ref BE-path' hdr = 1 @@ -857,13 +835,12 @@ def xm_block_list(args): print 'No domain parameter given' sys.exit(1) dom = params[0] - from xen.xend.XendClient import server if use_long: - devs = server.xend_domain_devices(dom, 'vbd') + devs = server.xend.domain.getDeviceSxprs(dom, 'vbd') map(PrettyPrint.prettyprint, devs) else: hdr = 0 - for x in server.xend_domain_devices(dom, 'vbd'): + for x in server.xend.domain.getDeviceSxprs(dom, 'vbd'): if hdr == 0: print 'Vdev BE handle state evt-ch ring-ref BE-path' hdr = 1 @@ -887,13 +864,12 @@ def xm_vtpm_list(args): print 'No domain parameter given' sys.exit(1) dom = params[0] - from xen.xend.XendClient import server if use_long: - devs = server.xend_domain_devices(dom, 'vtpm') + devs = server.xend.domain.getDeviceSxprs(dom, 'vtpm') map(PrettyPrint.prettyprint, devs) else: hdr = 0 - for x in server.xend_domain_devices(dom, 'vtpm'): + for x in server.xend.domain.getDeviceSxprs(dom, 'vtpm'): if hdr == 0: print 'Idx BE handle state evt-ch ring-ref BE-path' hdr = 1 @@ -919,8 +895,7 @@ def xm_block_attach(args): if len(args) == 5: vbd.append(['backend', args[4]]) - from xen.xend.XendClient import server - server.xend_domain_device_create(dom, vbd) + server.xend.domain.device_create(dom, vbd) def xm_network_attach(args): @@ -932,8 +907,7 @@ def xm_network_attach(args): for a in args[1:]: vif.append(a.split("=")) - from xen.xend.XendClient import server - server.xend_domain_device_create(dom, vif) + server.xend.domain.device_create(dom, vif) def detach(args, command, deviceClass): @@ -942,8 +916,7 @@ def detach(args, command, deviceClass): dom = args[0] dev = args[1] - from xen.xend.XendClient import server - server.xend_domain_device_destroy(dom, deviceClass, dev) + server.xend.domain.destroyDevice(dom, deviceClass, dev) def xm_block_detach(args): @@ -955,7 +928,6 @@ def xm_network_detach(args): def xm_vnet_list(args): - from xen.xend.XendClient import server try: (options, params) = getopt.gnu_getopt(args, 'l', ['long']) except getopt.GetoptError, opterr: @@ -990,13 +962,11 @@ def xm_vnet_create(args): print "File not found: %s" % conf sys.exit(1) - from xen.xend.XendClient import server server.xend_vnet_create(conf) def xm_vnet_delete(args): arg_check(args, "vnet-delete", 1) vnet = args[0] - from xen.xend.XendClient import server server.xend_vnet_delete(vnet) commands = { @@ -1132,23 +1102,13 @@ def main(argv=sys.argv): else: err("Error connecting to xend: %s." % ex[1]) sys.exit(1) - except xen.xend.XendError.XendError, ex: - if len(args) > 0: - handle_xend_error(argv[1], args, ex) + except SystemExit: + sys.exit(1) + except xmlrpclib.Fault, ex: + if ex.faultCode == xen.xend.XendClient.ERROR_INVALID_DOMAIN: + print "Error: the domain '%s' does not exist." % ex.faultString else: - print "Unexpected error:", sys.exc_info()[0] - print - print "Please report to xen-devel@xxxxxxxxxxxxxxxxxxx" - raise - except xen.xend.XendProtocol.XendError, ex: - if len(args) > 0: - handle_xend_error(argv[1], args, ex) - else: - print "Unexpected error:", sys.exc_info()[0] - print - print "Please report to xen-devel@xxxxxxxxxxxxxxxxxxx" - raise - except SystemExit: + print "Error: %s" % ex.faultString sys.exit(1) except: print "Unexpected error:", sys.exc_info()[0] diff -r 7e3cbc409676 -r d75a6cc5e68a tools/python/xen/xm/migrate.py --- a/tools/python/xen/xm/migrate.py Mon Mar 27 15:36:47 2006 -0700 +++ b/tools/python/xen/xm/migrate.py Tue Mar 28 08:54:58 2006 -0700 @@ -60,4 +60,4 @@ def main(argv): opts.err('Invalid arguments: ' + str(args)) dom = args[0] dst = args[1] - server.xend_domain_migrate(dom, dst, opts.vals.live, opts.vals.resource, opts.vals.port) + server.xend.domain.migrate(dom, dst, opts.vals.live, opts.vals.resource, opts.vals.port) diff -r 7e3cbc409676 -r d75a6cc5e68a tools/python/xen/xm/shutdown.py --- a/tools/python/xen/xm/shutdown.py Mon Mar 27 15:36:47 2006 -0700 +++ b/tools/python/xen/xm/shutdown.py Tue Mar 28 08:54:58 2006 -0700 @@ -53,8 +53,8 @@ gopts.opt('reboot', short='R', use='Shutdown and reboot.') def shutdown(opts, doms, mode, wait): - if doms == None: doms = server.xend_domains() - dom0_name = sxp.child_value(server.xend_domain(0), 'name') + if doms == None: doms = server.xend.domains(0) + dom0_name = sxp.child_value(server.xend.domain(0), 'name') for x in [dom0_name, DOM0_ID]: if x in doms: if opts.vals.all: @@ -62,10 +62,10 @@ def shutdown(opts, doms, mode, wait): else: opts.err("Can't specify Domain-0") for d in doms: - server.xend_domain_shutdown(d, mode) + server.xend.domain.shutdown(d, mode) if wait: while doms: - alive = server.xend_domains() + alive = server.xend.domains(0) dead = [] for d in doms: if d in alive: continue diff -r 7e3cbc409676 -r d75a6cc5e68a tools/python/xen/xm/sysrq.py --- a/tools/python/xen/xm/sysrq.py Mon Mar 27 15:36:47 2006 -0700 +++ b/tools/python/xen/xm/sysrq.py Tue Mar 28 08:54:58 2006 -0700 @@ -28,4 +28,4 @@ def main(argv): if len(args) < 2: opts.err('Missing sysrq character') dom = args[0] req = ord(args[1][0]) - server.xend_domain_sysrq(dom, req) + server.xend.domain.send_sysrq(dom, req) diff -r 7e3cbc409676 -r d75a6cc5e68a tools/xenstore/talloc.c --- a/tools/xenstore/talloc.c Mon Mar 27 15:36:47 2006 -0700 +++ b/tools/xenstore/talloc.c Tue Mar 28 08:54:58 2006 -0700 @@ -1,4 +1,4 @@ -/* +/* Samba Unix SMB/CIFS implementation. Samba trivial allocation library - new interface @@ -6,26 +6,29 @@ NOTE: Please read talloc_guide.txt for full documentation Copyright (C) Andrew Tridgell 2004 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, + + ** NOTE! The following LGPL license applies to the talloc + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* inspired by http://swapped.cc/halloc/ */ - #ifdef _SAMBA_BUILD_ #include "includes.h" @@ -52,15 +55,13 @@ /* use this to force every realloc to change the pointer, to stress test code that might not cope */ -#ifdef TESTING -#define ALWAYS_REALLOC 1 -void *test_malloc(size_t size); -#define malloc test_malloc -#endif +#define ALWAYS_REALLOC 0 + #define MAX_TALLOC_SIZE 0x10000000 -#define TALLOC_MAGIC 0xe814ec4f -#define TALLOC_MAGIC_FREE 0x7faebef3 +#define TALLOC_MAGIC 0xe814ec70 +#define TALLOC_FLAG_FREE 0x01 +#define TALLOC_FLAG_LOOP 0x02 #define TALLOC_MAGIC_REFERENCE ((const char *)1) /* by default we abort when given a bad pointer (such as when talloc_free() is called @@ -83,8 +84,7 @@ void *test_malloc(size_t size); */ static const void *null_context; static void *cleanup_context; -static int (*malloc_fail_handler)(void *); -static void *malloc_fail_data; + struct talloc_reference_handle { struct talloc_reference_handle *next, *prev; @@ -97,24 +97,27 @@ struct talloc_chunk { struct talloc_chunk *next, *prev; struct talloc_chunk *parent, *child; struct talloc_reference_handle *refs; - size_t size; - unsigned magic; talloc_destructor_t destructor; const char *name; + size_t size; + unsigned flags; }; + +/* 16 byte alignment seems to keep everyone happy */ +#define TC_HDR_SIZE ((sizeof(struct talloc_chunk)+15)&~15) +#define TC_PTR_FROM_CHUNK(tc) ((void *)(TC_HDR_SIZE + (char*)tc)) /* panic if we get a bad magic value */ static struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr) { - struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, ptr)-1; - if (tc->magic != TALLOC_MAGIC) { - if (tc->magic == TALLOC_MAGIC_FREE) { - TALLOC_ABORT("Bad talloc magic value - double free"); - } else { - TALLOC_ABORT("Bad talloc magic value - unknown value"); - } - } - + const char *pp = ptr; + struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, pp - TC_HDR_SIZE); + if ((tc->flags & ~0xF) != TALLOC_MAGIC) { + TALLOC_ABORT("Bad talloc magic value - unknown value"); + } + if (tc->flags & TALLOC_FLAG_FREE) { + TALLOC_ABORT("Bad talloc magic value - double free"); + } return tc; } @@ -159,7 +162,7 @@ void *talloc_parent(const void *ptr) void *talloc_parent(const void *ptr) { struct talloc_chunk *tc = talloc_parent_chunk(ptr); - return (void *)(tc+1); + return tc? TC_PTR_FROM_CHUNK(tc) : NULL; } /* @@ -177,17 +180,11 @@ void *_talloc(const void *context, size_ return NULL; } - tc = malloc(sizeof(*tc)+size); - if (tc == NULL) { - if (malloc_fail_handler) - if (malloc_fail_handler(malloc_fail_data)) - tc = malloc(sizeof(*tc)+size); - if (!tc) - return NULL; - } + tc = malloc(TC_HDR_SIZE+size); + if (tc == NULL) return NULL; tc->size = size; - tc->magic = TALLOC_MAGIC; + tc->flags = TALLOC_MAGIC; tc->destructor = NULL; tc->child = NULL; tc->name = NULL; @@ -207,7 +204,7 @@ void *_talloc(const void *context, size_ tc->next = tc->prev = tc->parent = NULL; } - return (void *)(tc+1); + return TC_PTR_FROM_CHUNK(tc); } @@ -292,7 +289,11 @@ static int talloc_unreference(const void for (h=tc->refs;h;h=h->next) { struct talloc_chunk *p = talloc_parent_chunk(h); - if ((p==NULL && context==NULL) || p+1 == context) break; + if (p == NULL) { + if (context == NULL) break; + } else if (TC_PTR_FROM_CHUNK(p) == context) { + break; + } } if (h == NULL) { return -1; @@ -343,7 +344,7 @@ int talloc_unlink(const void *context, v new_p = talloc_parent_chunk(tc_p->refs); if (new_p) { - new_parent = new_p+1; + new_parent = TC_PTR_FROM_CHUNK(new_p); } else { new_parent = NULL; } @@ -470,6 +471,8 @@ void *talloc_init(const char *fmt, ...) { va_list ap; void *ptr; + + talloc_enable_null_tracking(); ptr = _talloc(NULL, 0); if (ptr == NULL) return NULL; @@ -502,16 +505,16 @@ void talloc_free_children(void *ptr) choice is owner of any remaining reference to this pointer, the second choice is our parent, and the final choice is the null context. */ - void *child = tc->child+1; + void *child = TC_PTR_FROM_CHUNK(tc->child); const void *new_parent = null_context; if (tc->child->refs) { struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs); - if (p) new_parent = p+1; + if (p) new_parent = TC_PTR_FROM_CHUNK(p); } if (talloc_free(child) == -1) { if (new_parent == null_context) { struct talloc_chunk *p = talloc_parent_chunk(ptr); - if (p) new_parent = p+1; + if (p) new_parent = TC_PTR_FROM_CHUNK(p); } talloc_steal(new_parent, child); } @@ -539,6 +542,11 @@ int talloc_free(void *ptr) if (tc->refs) { talloc_reference_destructor(tc->refs); return -1; + } + + if (tc->flags & TALLOC_FLAG_LOOP) { + /* we have a free loop - stop looping */ + return 0; } if (tc->destructor) { @@ -554,6 +562,8 @@ int talloc_free(void *ptr) tc->destructor = NULL; } + tc->flags |= TALLOC_FLAG_LOOP; + talloc_free_children(ptr); if (tc->parent) { @@ -566,7 +576,7 @@ int talloc_free(void *ptr) if (tc->next) tc->next->prev = tc->prev; } - tc->magic = TALLOC_MAGIC_FREE; + tc->flags |= TALLOC_FLAG_FREE; free(tc); return 0; @@ -606,36 +616,24 @@ void *_talloc_realloc(const void *contex } /* by resetting magic we catch users of the old memory */ - tc->magic = TALLOC_MAGIC_FREE; + tc->flags |= TALLOC_FLAG_FREE; #if ALWAYS_REALLOC - new_ptr = malloc(size + sizeof(*tc)); - if (!new_ptr) { - tc->magic = TALLOC_MAGIC; - if (malloc_fail_handler) - if (malloc_fail_handler(malloc_fail_data)) - new_ptr = malloc(size + sizeof(*tc)); - } + new_ptr = malloc(size + TC_HDR_SIZE); if (new_ptr) { - memcpy(new_ptr, tc, tc->size + sizeof(*tc)); + memcpy(new_ptr, tc, tc->size + TC_HDR_SIZE); free(tc); } #else - new_ptr = realloc(tc, size + sizeof(*tc)); - if (!new_ptr) { - tc->magic = TALLOC_MAGIC; - if (malloc_fail_handler) - if (malloc_fail_handler(malloc_fail_data)) - new_ptr = realloc(tc, size + sizeof(*tc)); - } + new_ptr = realloc(tc, size + TC_HDR_SIZE); #endif if (!new_ptr) { - tc->magic = TALLOC_MAGIC; + tc->flags &= ~TALLOC_FLAG_FREE; return NULL; } tc = new_ptr; - tc->magic = TALLOC_MAGIC; + tc->flags &= ~TALLOC_FLAG_FREE; if (tc->parent) { tc->parent->child = new_ptr; } @@ -651,9 +649,9 @@ void *_talloc_realloc(const void *contex } tc->size = size; - talloc_set_name_const(tc+1, name); - - return (void *)(tc+1); + talloc_set_name_const(TC_PTR_FROM_CHUNK(tc), name); + + return TC_PTR_FROM_CHUNK(tc); } /* @@ -730,10 +728,19 @@ off_t talloc_total_size(const void *ptr) tc = talloc_chunk_from_ptr(ptr); + if (tc->flags & TALLOC_FLAG_LOOP) { + return 0; + } + + tc->flags |= TALLOC_FLAG_LOOP; + total = tc->size; for (c=tc->child;c;c=c->next) { - total += talloc_total_size(c+1); - } + total += talloc_total_size(TC_PTR_FROM_CHUNK(c)); + } + + tc->flags &= ~TALLOC_FLAG_LOOP; + return total; } @@ -743,20 +750,21 @@ off_t talloc_total_blocks(const void *pt off_t talloc_total_blocks(const void *ptr) { off_t total = 0; - struct talloc_chunk *c, *tc; - - if (ptr == NULL) { - ptr = null_context; - } - if (ptr == NULL) { + struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr); + + if (tc->flags & TALLOC_FLAG_LOOP) { return 0; } - tc = talloc_chunk_from_ptr(ptr); + + tc->flags |= TALLOC_FLAG_LOOP; total++; for (c=tc->child;c;c=c->next) { - total += talloc_total_blocks(c+1); - } + total += talloc_total_blocks(TC_PTR_FROM_CHUNK(c)); + } + + tc->flags &= ~TALLOC_FLAG_LOOP; + return total; } @@ -782,23 +790,29 @@ void talloc_report_depth(const void *ptr { struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr); + if (tc->flags & TALLOC_FLAG_LOOP) { + return; + } + + tc->flags |= TALLOC_FLAG_LOOP; + for (c=tc->child;c;c=c->next) { if (c->name == TALLOC_MAGIC_REFERENCE) { - struct talloc_reference_handle *handle = (void *)(c+1); + struct talloc_reference_handle *handle = TC_PTR_FROM_CHUNK(c); const char *name2 = talloc_get_name(handle->ptr); fprintf(f, "%*sreference to: %s\n", depth*4, "", name2); } else { - const char *name = talloc_get_name(c+1); + const char *name = talloc_get_name(TC_PTR_FROM_CHUNK(c)); fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d)\n", depth*4, "", name, - (unsigned long)talloc_total_size(c+1), - (unsigned long)talloc_total_blocks(c+1), - talloc_reference_count(c+1)); - talloc_report_depth(c+1, f, depth+1); - } - } - + (unsigned long)talloc_total_size(TC_PTR_FROM_CHUNK(c)), + (unsigned long)talloc_total_blocks(TC_PTR_FROM_CHUNK(c)), + talloc_reference_count(TC_PTR_FROM_CHUNK(c))); + talloc_report_depth(TC_PTR_FROM_CHUNK(c), f, depth+1); + } + } + tc->flags &= ~TALLOC_FLAG_LOOP; } /* @@ -841,9 +855,9 @@ void talloc_report(const void *ptr, FILE for (c=tc->child;c;c=c->next) { fprintf(f, "\t%-30s contains %6lu bytes in %3lu blocks\n", - talloc_get_name(c+1), - (unsigned long)talloc_total_size(c+1), - (unsigned long)talloc_total_blocks(c+1)); + talloc_get_name(TC_PTR_FROM_CHUNK(c)), + (unsigned long)talloc_total_size(TC_PTR_FROM_CHUNK(c)), + (unsigned long)talloc_total_blocks(TC_PTR_FROM_CHUNK(c))); } fflush(f); } @@ -877,6 +891,74 @@ void talloc_enable_null_tracking(void) null_context = talloc_named_const(NULL, 0, "null_context"); } } + +#ifdef _SAMBA_BUILD_ +/* Ugly calls to Samba-specific sprintf_append... JRA. */ + +/* + report on memory usage by all children of a pointer, giving a full tree view +*/ +static void talloc_report_depth_str(const void *ptr, char **pps, ssize_t *plen, size_t *pbuflen, int depth) +{ + struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr); + + if (tc->flags & TALLOC_FLAG_LOOP) { + return; + } + + tc->flags |= TALLOC_FLAG_LOOP; + + for (c=tc->child;c;c=c->next) { + if (c->name == TALLOC_MAGIC_REFERENCE) { + struct talloc_reference_handle *handle = TC_PTR_FROM_CHUNK(c); + const char *name2 = talloc_get_name(handle->ptr); + + sprintf_append(NULL, pps, plen, pbuflen, + "%*sreference to: %s\n", depth*4, "", name2); + + } else { + const char *name = talloc_get_name(TC_PTR_FROM_CHUNK(c)); + + sprintf_append(NULL, pps, plen, pbuflen, + "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d)\n", + depth*4, "", + name, + (unsigned long)talloc_total_size(TC_PTR_FROM_CHUNK(c)), + (unsigned long)talloc_total_blocks(TC_PTR_FROM_CHUNK(c)), + talloc_reference_count(TC_PTR_FROM_CHUNK(c))); + + talloc_report_depth_str(TC_PTR_FROM_CHUNK(c), pps, plen, pbuflen, depth+1); + } + } + tc->flags &= ~TALLOC_FLAG_LOOP; +} + +/* + report on memory usage by all children of a pointer +*/ +char *talloc_describe_all(void) +{ + ssize_t len = 0; + size_t buflen = 512; + char *s = NULL; + + if (null_context == NULL) { + return NULL; + } + + sprintf_append(NULL, &s, &len, &buflen, + "full talloc report on '%s' (total %lu bytes in %lu blocks)\n", + talloc_get_name(null_context), + (unsigned long)talloc_total_size(null_context), + (unsigned long)talloc_total_blocks(null_context)); + + if (!s) { + return NULL; + } + talloc_report_depth_str(null_context, &s, &len, &buflen, 1); + return s; +} +#endif /* enable leak reporting on exit @@ -942,6 +1024,30 @@ char *talloc_strdup(const void *t, const } /* + append to a talloced string +*/ +char *talloc_append_string(const void *t, char *orig, const char *append) +{ + char *ret; + size_t olen = strlen(orig); + size_t alenz; + + if (!append) + return orig; + + alenz = strlen(append) + 1; + + ret = talloc_realloc(t, orig, char, olen + alenz); + if (!ret) + return NULL; + + /* append the string with the trailing \0 */ + memcpy(&ret[olen], append, alenz); + + return ret; +} + +/* strndup with a talloc */ char *talloc_strndup(const void *t, const char *p, size_t n) @@ -949,7 +1055,7 @@ char *talloc_strndup(const void *t, cons size_t len; char *ret; - for (len=0; p[len] && len<n; len++) ; + for (len=0; len<n && p[len]; len++) ; ret = _talloc(t, len + 1); if (!ret) { return NULL; } @@ -974,10 +1080,14 @@ char *talloc_vasprintf(const void *t, co int len; char *ret; va_list ap2; + char c; VA_COPY(ap2, ap); - len = vsnprintf(NULL, 0, fmt, ap2); + /* this call looks strange, but it makes it work on older solaris boxes */ + if ((len = vsnprintf(&c, 1, fmt, ap2)) < 0) { + return NULL; + } ret = _talloc(t, len+1); if (ret) { @@ -1029,7 +1139,15 @@ static char *talloc_vasprintf_append(cha VA_COPY(ap2, ap); s_len = tc->size - 1; - len = vsnprintf(NULL, 0, fmt, ap2); + if ((len = vsnprintf(NULL, 0, fmt, ap2)) <= 0) { + /* Either the vsnprintf failed or the format resulted in + * no characters being formatted. In the former case, we + * ought to return NULL, in the latter we ought to return + * the original string. Most current callers of this + * function expect it to never return NULL. + */ + return s; + } s = talloc_realloc(NULL, s, char, s_len + len+1); if (!s) return NULL; @@ -1133,11 +1251,45 @@ size_t talloc_get_size(const void *conte return tc->size; } -talloc_fail_handler *talloc_set_fail_handler(talloc_fail_handler *handler, - void *data) -{ - talloc_fail_handler *old = malloc_fail_handler; - malloc_fail_handler = handler; - malloc_fail_data = data; - return old; -} +/* + find a parent of this context that has the given name, if any +*/ +void *talloc_find_parent_byname(const void *context, const char *name) +{ + struct talloc_chunk *tc; + + if (context == NULL) { + return NULL; + } + + tc = talloc_chunk_from_ptr(context); + while (tc) { + if (tc->name && strcmp(tc->name, name) == 0) { + return TC_PTR_FROM_CHUNK(tc); + } + while (tc && tc->prev) tc = tc->prev; + tc = tc->parent; + } + return NULL; +} + +/* + show the parentage of a context +*/ +void talloc_show_parents(const void *context, FILE *file) +{ + struct talloc_chunk *tc; + + if (context == NULL) { + fprintf(file, "talloc no parents for NULL\n"); + return; + } + + tc = talloc_chunk_from_ptr(context); + fprintf(file, "talloc parents of '%s'\n", talloc_get_name(context)); + while (tc) { + fprintf(file, "\t'%s'\n", talloc_get_name(TC_PTR_FROM_CHUNK(tc))); + while (tc && tc->prev) tc = tc->prev; + tc = tc->parent; + } +} diff -r 7e3cbc409676 -r d75a6cc5e68a tools/xenstore/talloc.h --- a/tools/xenstore/talloc.h Mon Mar 27 15:36:47 2006 -0700 +++ b/tools/xenstore/talloc.h Tue Mar 28 08:54:58 2006 -0700 @@ -6,19 +6,23 @@ Copyright (C) Andrew Tridgell 2004-2005 - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. + ** NOTE! The following LGPL license applies to the talloc + ** library. This does NOT imply that all of Samba is released + ** under the LGPL - This program is distributed in the hope that it will be useful, + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* this is only needed for compatibility with the old talloc */ @@ -58,12 +62,17 @@ typedef void TALLOC_CTX; #define malloc_array_p(type, count) (type *)realloc_array(NULL, sizeof(type), count) #define realloc_p(p, type, count) (type *)realloc_array(p, sizeof(type), count) +#if 0 +/* Not correct for Samba3. */ #define data_blob(ptr, size) data_blob_named(ptr, size, "DATA_BLOB: "__location__) #define data_blob_talloc(ctx, ptr, size) data_blob_talloc_named(ctx, ptr, size, "DATA_BLOB: "__location__) #define data_blob_dup_talloc(ctx, blob) data_blob_talloc_named(ctx, (blob)->data, (blob)->length, "DATA_BLOB: "__location__) +#endif #define talloc_set_type(ptr, type) talloc_set_name_const(ptr, #type) #define talloc_get_type(ptr, type) (type *)talloc_check_name(ptr, #type) + +#define talloc_find_parent_bytype(ptr, type) (type *)talloc_find_parent_byname(ptr, #type) #if TALLOC_DEPRECATED @@ -117,6 +126,7 @@ void *_talloc_memdup(const void *t, cons void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name); char *talloc_strdup(const void *t, const char *p); char *talloc_strndup(const void *t, const char *p, size_t n); +char *talloc_append_string(const void *t, char *orig, const char *append); char *talloc_vasprintf(const void *t, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); char *talloc_asprintf(const void *t, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); char *talloc_asprintf_append(char *s, @@ -127,8 +137,8 @@ void *talloc_realloc_fn(const void *cont void *talloc_realloc_fn(const void *context, void *ptr, size_t size); void *talloc_autofree_context(void); size_t talloc_get_size(const void *ctx); +void *talloc_find_parent_byname(const void *ctx, const char *name); +void talloc_show_parents(const void *context, FILE *file); -typedef int talloc_fail_handler(void *); -talloc_fail_handler *talloc_set_fail_handler(talloc_fail_handler *, void *); #endif diff -r 7e3cbc409676 -r d75a6cc5e68a tools/xenstore/xenstored_core.c --- a/tools/xenstore/xenstored_core.c Mon Mar 27 15:36:47 2006 -0700 +++ b/tools/xenstore/xenstored_core.c Tue Mar 28 08:54:58 2006 -0700 @@ -1231,39 +1231,17 @@ static void process_message(struct conne conn->transaction = NULL; } -static int out_of_mem(void *data) -{ - longjmp(*(jmp_buf *)data, 1); -} - static void consider_message(struct connection *conn) { - jmp_buf talloc_fail; - if (verbose) xprintf("Got message %s len %i from %p\n", sockmsg_string(conn->in->hdr.msg.type), conn->in->hdr.msg.len, conn); - /* For simplicity, we kill the connection on OOM. */ - talloc_set_fail_handler(out_of_mem, &talloc_fail); - if (setjmp(talloc_fail)) { - talloc_free(conn); - goto end; - } - process_message(conn, conn->in); talloc_free(conn->in); conn->in = new_buffer(conn); - -end: - talloc_set_fail_handler(NULL, NULL); - if (talloc_total_blocks(NULL) - != talloc_total_blocks(talloc_autofree_context()) + 1) { - talloc_report_full(NULL, stderr); - abort(); - } } /* Errors in reading or allocating here mean we get out of sync, so we diff -r 7e3cbc409676 -r d75a6cc5e68a tools/xentrace/Makefile --- a/tools/xentrace/Makefile Mon Mar 27 15:36:47 2006 -0700 +++ b/tools/xentrace/Makefile Tue Mar 28 08:54:58 2006 -0700 @@ -6,7 +6,7 @@ XEN_ROOT=../.. XEN_ROOT=../.. include $(XEN_ROOT)/tools/Rules.mk -CFLAGS += -Werror +CFLAGS += -Werror -D_LARGEFILE64_SOURCE CFLAGS += -I $(XEN_XC) CFLAGS += -I $(XEN_LIBXC) diff -r 7e3cbc409676 -r d75a6cc5e68a tools/xentrace/formats --- a/tools/xentrace/formats Mon Mar 27 15:36:47 2006 -0700 +++ b/tools/xentrace/formats Tue Mar 28 08:54:58 2006 -0700 @@ -16,6 +16,6 @@ 0x00080002 CPU%(cpu)d %(tsc)d VMX_ 0x00080002 CPU%(cpu)d %(tsc)d VMX_VECTOR [ domid = 0x%(1)08x, eip = 0x%(2)08x, vector = 0x%(3)08x ] 0x00080003 CPU%(cpu)d %(tsc)d VMX_INT [ domid = 0x%(1)08x, trap = 0x%(2)08x, va = 0x%(3)08x ] -0x00090001 CPU%(cpu)d %(tsc)d VMENTRY 0x%(1)08x 0x%(2)08x 0x%(3)08x 0x%(4)08x 0x%(5)08x -0x00090002 CPU%(cpu)d %(tsc)d VMEXIT 0x%(1)08x 0x%(2)08x 0x%(3)08x +0x00081001 CPU%(cpu)d %(tsc)d VMEXIT 0x%(1)08x 0x%(2)08x 0x%(3)08x +0x00081002 CPU%(cpu)d %(tsc)d VMENTRY 0x%(1)08x 0x%(2)08x 0x%(3)08x 0x%(4)08x 0x%(5)08x diff -r 7e3cbc409676 -r d75a6cc5e68a tools/xentrace/xentrace.c --- a/tools/xentrace/xentrace.c Mon Mar 27 15:36:47 2006 -0700 +++ b/tools/xentrace/xentrace.c Tue Mar 28 08:54:58 2006 -0700 @@ -498,7 +498,7 @@ int main(int argc, char **argv) } if ( opts.outfile ) - outfd = open(opts.outfile, O_WRONLY | O_CREAT); + outfd = open(opts.outfile, O_WRONLY | O_CREAT | O_LARGEFILE, 0644); if(outfd < 0) { diff -r 7e3cbc409676 -r d75a6cc5e68a tools/xm-test/lib/XmTestLib/Test.py --- a/tools/xm-test/lib/XmTestLib/Test.py Mon Mar 27 15:36:47 2006 -0700 +++ b/tools/xm-test/lib/XmTestLib/Test.py Tue Mar 28 08:54:58 2006 -0700 @@ -131,12 +131,12 @@ def becomeNonRoot(): if os.geteuid() == 0: FAIL("Could not become a non-root user") -def FAIL(reason): - print "\nREASON: %s" % reason +def FAIL(format, *args): + print "\nREASON:", (format % args) sys.exit(TEST_FAIL) -def SKIP(reason): - print "\nREASON: %s" % reason +def SKIP(format, *args): + print "\nREASON:", (format % args) sys.exit(TEST_SKIP) def saveLog(logText, filename=None): diff -r 7e3cbc409676 -r d75a6cc5e68a tools/xm-test/ramdisk/Makefile.am --- a/tools/xm-test/ramdisk/Makefile.am Mon Mar 27 15:36:47 2006 -0700 +++ b/tools/xm-test/ramdisk/Makefile.am Tue Mar 28 08:54:58 2006 -0700 @@ -1,3 +1,4 @@ +INITRD ?= http://xm-test.xensource.com/ramdisks EXTRA_DIST = skel configs patches @@ -60,7 +61,7 @@ disk.img: existing fi existing: - @if test -n "$(INITRD)"; then \ + @if [ -n "$(INITRD)" ] && [ ! -f $(XMTEST_VER_IMG) ] ; then \ wget $(INITRD)/$(XMTEST_VER_IMG); \ fi @if [ -f $(XMTEST_VER_IMG) ] ; then \ diff -r 7e3cbc409676 -r d75a6cc5e68a tools/xm-test/tests/block-create/Makefile.am --- a/tools/xm-test/tests/block-create/Makefile.am Mon Mar 27 15:36:47 2006 -0700 +++ b/tools/xm-test/tests/block-create/Makefile.am Tue Mar 28 08:54:58 2006 -0700 @@ -12,7 +12,7 @@ TESTS = 01_block_attach_device_pos.test 11_block_attach_shared_dom0.test \ 12_block_attach_shared_domU.test -EXTRA_DIST = $(TESTS) $(XFAIL_TESTS) +EXTRA_DIST = $(TESTS) TESTS_ENVIRONMENT=@TENV@ diff -r 7e3cbc409676 -r d75a6cc5e68a tools/xm-test/tests/create/Makefile.am --- a/tools/xm-test/tests/create/Makefile.am Mon Mar 27 15:36:47 2006 -0700 +++ b/tools/xm-test/tests/create/Makefile.am Tue Mar 28 08:54:58 2006 -0700 @@ -15,7 +15,7 @@ TESTS = 01_create_basic_pos.test \ 14_create_blockroot_pos.test \ 15_create_smallmem_pos.test -EXTRA_DIST = $(TESTS) $(XFAIL_TESTS) +EXTRA_DIST = $(TESTS) TESTS_ENVIRONMENT=@TENV@ diff -r 7e3cbc409676 -r d75a6cc5e68a xen/arch/x86/dom0_ops.c --- a/xen/arch/x86/dom0_ops.c Mon Mar 27 15:36:47 2006 -0700 +++ b/xen/arch/x86/dom0_ops.c Tue Mar 28 08:54:58 2006 -0700 @@ -460,8 +460,7 @@ void arch_getdomaininfo_ctxt( if ( hvm_guest(v) ) { - hvm_store_cpu_guest_regs(v, &c->user_regs); - hvm_store_cpu_guest_ctrl_regs(v, c->ctrlreg); + hvm_store_cpu_guest_regs(v, &c->user_regs, c->ctrlreg); } else { diff -r 7e3cbc409676 -r d75a6cc5e68a xen/arch/x86/hvm/platform.c --- a/xen/arch/x86/hvm/platform.c Mon Mar 27 15:36:47 2006 -0700 +++ b/xen/arch/x86/hvm/platform.c Tue Mar 28 08:54:58 2006 -0700 @@ -773,7 +773,7 @@ void handle_mmio(unsigned long va, unsig mmio_opp = &v->arch.hvm_vcpu.mmio_op; regs = mmio_opp->inst_decoder_regs; - hvm_store_cpu_guest_regs(v, regs); + hvm_store_cpu_guest_regs(v, regs, NULL); if ((inst_len = hvm_instruction_length(v)) <= 0) { printf("handle_mmio: failed to get instruction length\n"); diff -r 7e3cbc409676 -r d75a6cc5e68a xen/arch/x86/hvm/svm/intr.c --- a/xen/arch/x86/hvm/svm/intr.c Mon Mar 27 15:36:47 2006 -0700 +++ b/xen/arch/x86/hvm/svm/intr.c Tue Mar 28 08:54:58 2006 -0700 @@ -44,6 +44,58 @@ */ #define BSP_CPU(v) (!(v->vcpu_id)) +u64 svm_get_guest_time(struct vcpu *v) +{ + struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit); + u64 host_tsc; + + rdtscll(host_tsc); + return host_tsc + vpit->cache_tsc_offset; +} + +void svm_set_guest_time(struct vcpu *v, u64 gtime) +{ + struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit); + u64 host_tsc; + + rdtscll(host_tsc); + + vpit->cache_tsc_offset = gtime - host_tsc; + v->arch.hvm_svm.vmcb->tsc_offset = vpit->cache_tsc_offset; +} + +static inline void +interrupt_post_injection(struct vcpu * v, int vector, int type) +{ + struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit); + + if ( is_pit_irq(v, vector, type) ) { + if ( !vpit->first_injected ) { + vpit->pending_intr_nr = 0; + vpit->last_pit_gtime = svm_get_guest_time(v); + vpit->scheduled = NOW() + vpit->period; + set_timer(&vpit->pit_timer, vpit->scheduled); + vpit->first_injected = 1; + } else { + vpit->pending_intr_nr--; + } + vpit->inject_point = NOW(); + + vpit->last_pit_gtime += vpit->period; + svm_set_guest_time(v, vpit->last_pit_gtime); + } + + switch(type) + { + case VLAPIC_DELIV_MODE_EXT: + break; + + default: + vlapic_post_injection(v, vector, type); + break; + } +} + static inline int svm_inject_extint(struct vcpu *v, int trap, int error_code) { struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; @@ -62,45 +114,6 @@ static inline int svm_inject_extint(stru vmcb->vintr = intr; // printf( "IRQ = %d\n", trap ); return 0; -} - -void svm_set_tsc_shift(struct vcpu *v, struct hvm_virpit *vpit) -{ - struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; - u64 drift; - - if ( vpit->first_injected ) - drift = vpit->period_cycles * vpit->pending_intr_nr; - else - drift = 0; - vmcb->tsc_offset = ( 0 - drift ); -} - -static inline void -interrupt_post_injection(struct vcpu * v, int vector, int type) -{ - struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit); - - if ( is_pit_irq(v, vector, type) ) { - if ( !vpit->first_injected ) { - vpit->first_injected = 1; - vpit->pending_intr_nr = 0; - } - else if (vpit->pending_intr_nr) { - --vpit->pending_intr_nr; - } - vpit->inject_point = NOW(); - svm_set_tsc_shift (v, vpit); - } - - switch(type) - { - case VLAPIC_DELIV_MODE_EXT: - break; - - default: - vlapic_post_injection(v, vector, type); - } } asmlinkage void svm_intr_assist(void) diff -r 7e3cbc409676 -r d75a6cc5e68a xen/arch/x86/hvm/svm/svm.c --- a/xen/arch/x86/hvm/svm/svm.c Mon Mar 27 15:36:47 2006 -0700 +++ b/xen/arch/x86/hvm/svm/svm.c Tue Mar 28 08:54:58 2006 -0700 @@ -201,31 +201,41 @@ int svm_initialize_guest_resources(struc } static void svm_store_cpu_guest_regs( - struct vcpu *v, struct cpu_user_regs *regs) + struct vcpu *v, struct cpu_user_regs *regs, unsigned long *crs) { struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; + if ( regs != NULL ) + { #if defined (__x86_64__) - regs->rip = vmcb->rip; - regs->rsp = vmcb->rsp; - regs->rflags = vmcb->rflags; - regs->cs = vmcb->cs.sel; - regs->ds = vmcb->ds.sel; - regs->es = vmcb->es.sel; - regs->ss = vmcb->ss.sel; - regs->gs = vmcb->gs.sel; - regs->fs = vmcb->fs.sel; + regs->rip = vmcb->rip; + regs->rsp = vmcb->rsp; + regs->rflags = vmcb->rflags; + regs->cs = vmcb->cs.sel; + regs->ds = vmcb->ds.sel; + regs->es = vmcb->es.sel; + regs->ss = vmcb->ss.sel; + regs->gs = vmcb->gs.sel; + regs->fs = vmcb->fs.sel; #elif defined (__i386__) - regs->eip = vmcb->rip; - regs->esp = vmcb->rsp; - regs->eflags = vmcb->rflags; - regs->cs = vmcb->cs.sel; - regs->ds = vmcb->ds.sel; - regs->es = vmcb->es.sel; - regs->ss = vmcb->ss.sel; - regs->gs = vmcb->gs.sel; - regs->fs = vmcb->fs.sel; + regs->eip = vmcb->rip; + regs->esp = vmcb->rsp; + regs->eflags = vmcb->rflags; + regs->cs = vmcb->cs.sel; + regs->ds = vmcb->ds.sel; + regs->es = vmcb->es.sel; + regs->ss = vmcb->ss.sel; + regs->gs = vmcb->gs.sel; + regs->fs = vmcb->fs.sel; #endif + } + + if ( crs != NULL ) + { + crs[0] = vmcb->cr0; + crs[3] = vmcb->cr3; + crs[4] = vmcb->cr4; + } } static void svm_load_cpu_guest_regs( @@ -372,15 +382,6 @@ static inline int long_mode_do_msr_write return 1; } -void svm_store_cpu_guest_ctrl_regs(struct vcpu *v, unsigned long crs[8]) -{ - struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; - - crs[0] = vmcb->cr0; - crs[3] = vmcb->cr3; - crs[4] = vmcb->cr4; -} - void svm_modify_guest_state(struct vcpu *v) { svm_modify_vmcb(v, &v->arch.guest_context.user_regs); @@ -448,7 +449,6 @@ int start_svm(void) hvm_funcs.store_cpu_guest_regs = svm_store_cpu_guest_regs; hvm_funcs.load_cpu_guest_regs = svm_load_cpu_guest_regs; - hvm_funcs.store_cpu_guest_ctrl_regs = svm_store_cpu_guest_ctrl_regs; hvm_funcs.modify_guest_state = svm_modify_guest_state; hvm_funcs.realmode = svm_realmode; @@ -670,8 +670,18 @@ static void arch_svm_do_launch(struct vc reset_stack_and_jump(svm_asm_do_launch); } +static void svm_freeze_time(struct vcpu *v) +{ + struct hvm_virpit *vpit = &v->domain->arch.hvm_domain.vpit; + + v->domain->arch.hvm_domain.guest_time = svm_get_guest_time(v); + if ( vpit->first_injected ) + stop_timer(&(vpit->pit_timer)); +} + static void svm_ctxt_switch_from(struct vcpu *v) { + svm_freeze_time(v); } static void svm_ctxt_switch_to(struct vcpu *v) @@ -718,6 +728,8 @@ static void svm_relinquish_guest_resourc for_each_vcpu ( d, v ) { + if ( !test_bit(_VCPUF_initialised, &v->vcpu_flags) ) + continue; #if 0 /* Memory leak by not freeing this. XXXKAF: *Why* is not per core?? */ free_host_save_area(v->arch.hvm_svm.host_save_area); @@ -911,7 +923,7 @@ static void svm_vmexit_do_cpuid(struct v if (input == 1) { - if ( hvm_apic_support(v->domain) && + if ( !hvm_apic_support(v->domain) || !vlapic_global_enabled((VLAPIC(v))) ) clear_bit(X86_FEATURE_APIC, &edx); @@ -1251,11 +1263,6 @@ static void svm_io_instruction(struct vc /* Need the original rip, here. */ addr = svm_get_io_address(vmcb, regs, dir, real); - /* - * On SVM, the RIP of the intruction following the IN/OUT is saved in - * ExitInfo2 - */ - vmcb->rip = vmcb->exitinfo2; /* "rep" prefix */ if (info.fields.rep) @@ -1288,6 +1295,8 @@ static void svm_io_instruction(struct vc else count = (addr & ~PAGE_MASK) / size; } + else + vmcb->rip = vmcb->exitinfo2; send_pio_req(regs, port, count, size, addr, dir, 1); } @@ -1693,7 +1702,7 @@ static inline void svm_do_msr_access(str { struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; int inst_len; - int64_t tsc_sum; + u64 msr_content=0; ASSERT(vmcb); @@ -1708,24 +1717,27 @@ static inline void svm_do_msr_access(str inst_len = __get_instruction_length(vmcb, INSTR_RDMSR, NULL); regs->edx = 0; - switch (regs->ecx) + switch (regs->ecx) { + case MSR_IA32_TIME_STAMP_COUNTER: { + struct hvm_virpit *vpit; + + rdtscll(msr_content); + vpit = &(v->domain->arch.hvm_domain.vpit); + msr_content += vpit->cache_tsc_offset; + break; + } case MSR_IA32_SYSENTER_CS: - regs->eax = vmcb->sysenter_cs; + msr_content = vmcb->sysenter_cs; break; case MSR_IA32_SYSENTER_ESP: - regs->eax = vmcb->sysenter_esp; + msr_content = vmcb->sysenter_esp; break; case MSR_IA32_SYSENTER_EIP: - regs->eax = vmcb->sysenter_eip; + msr_content = vmcb->sysenter_eip; break; - case MSR_IA32_TIME_STAMP_COUNTER: - __asm__ __volatile__("rdtsc" : "=a" (regs->eax), "=d" (regs->edx)); - tsc_sum = regs->edx; - tsc_sum = (tsc_sum << 32) + regs->eax; - tsc_sum += (int64_t) vmcb->tsc_offset; - regs->eax = tsc_sum & 0xFFFFFFFF; - regs->edx = (tsc_sum >> 32) & 0xFFFFFFFF; + case MSR_IA32_APICBASE: + msr_content = VLAPIC(v) ? VLAPIC(v)->apic_base_msr : 0; break; default: if (long_mode_do_msr_read(regs)) @@ -1733,21 +1745,30 @@ static inline void svm_do_msr_access(str rdmsr_safe(regs->ecx, regs->eax, regs->edx); break; } + regs->eax = msr_content & 0xFFFFFFFF; + regs->edx = msr_content >> 32; } else { inst_len = __get_instruction_length(vmcb, INSTR_WRMSR, NULL); + msr_content = (regs->eax & 0xFFFFFFFF) | ((u64)regs->edx << 32); switch (regs->ecx) { + case MSR_IA32_TIME_STAMP_COUNTER: + svm_set_guest_time(v, msr_content); + break; case MSR_IA32_SYSENTER_CS: - vmcb->sysenter_cs = regs->eax; + vmcb->sysenter_cs = msr_content; break; case MSR_IA32_SYSENTER_ESP: - vmcb->sysenter_esp = regs->eax; + vmcb->sysenter_esp = msr_content; break; case MSR_IA32_SYSENTER_EIP: - vmcb->sysenter_eip = regs->eax; + vmcb->sysenter_eip = msr_content; + break; + case MSR_IA32_APICBASE: + vlapic_msr_set(VLAPIC(v), msr_content); break; default: long_mode_do_msr_write(regs); diff -r 7e3cbc409676 -r d75a6cc5e68a xen/arch/x86/hvm/svm/vmcb.c --- a/xen/arch/x86/hvm/svm/vmcb.c Mon Mar 27 15:36:47 2006 -0700 +++ b/xen/arch/x86/hvm/svm/vmcb.c Tue Mar 28 08:54:58 2006 -0700 @@ -123,7 +123,7 @@ static int construct_vmcb_controls(struc GENERAL1_INTERCEPT_RDTSC | GENERAL1_INTERCEPT_PUSHF | GENERAL1_INTERCEPT_SWINT | GENERAL1_INTERCEPT_POPF | GENERAL1_INTERCEPT_IRET | GENERAL1_INTERCEPT_PAUSE | - GENERAL1_INTERCEPT_TASK_SWITCH | GENERAL1_INTERCEPT_SMI + GENERAL1_INTERCEPT_TASK_SWITCH ); /* turn on the general 2 intercepts */ @@ -467,6 +467,8 @@ void svm_do_launch(struct vcpu *v) v->arch.hvm_svm.injecting_event = 0; v->arch.hvm_svm.saved_irq_vector = -1; + svm_set_guest_time(v, 0); + if (svm_dbg_on) svm_dump_vmcb(__func__, vmcb); } @@ -494,15 +496,16 @@ void svm_do_resume(struct vcpu *v) struct hvm_virpit *vpit = &d->arch.hvm_domain.vpit; svm_stts(v); + + /* pick up the elapsed PIT ticks and re-enable pit_timer */ + if ( vpit->first_injected) { + svm_set_guest_time(v, v->domain->arch.hvm_domain.guest_time); + pickup_deactive_ticks(vpit); + } if ( test_bit(iopacket_port(v), &d->shared_info->evtchn_pending[0]) || test_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags) ) hvm_wait_io(); - - /* pick up the elapsed PIT ticks and re-enable pit_timer */ - if ( vpit->first_injected ) - pickup_deactive_ticks(vpit); - svm_set_tsc_shift(v, vpit); /* We can't resume the guest if we're waiting on I/O */ ASSERT(!test_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags)); diff -r 7e3cbc409676 -r d75a6cc5e68a xen/arch/x86/hvm/vmx/io.c --- a/xen/arch/x86/hvm/vmx/io.c Mon Mar 27 15:36:47 2006 -0700 +++ b/xen/arch/x86/hvm/vmx/io.c Tue Mar 28 08:54:58 2006 -0700 @@ -86,7 +86,7 @@ interrupt_post_injection(struct vcpu * v } vpit->inject_point = NOW(); - vpit->last_pit_gtime += vpit->period; + vpit->last_pit_gtime += vpit->period_cycles; set_guest_time(v, vpit->last_pit_gtime); } @@ -206,8 +206,11 @@ void vmx_do_resume(struct vcpu *v) vmx_stts(); /* pick up the elapsed PIT ticks and re-enable pit_timer */ - if ( vpit->first_injected) { - set_guest_time(v, v->domain->arch.hvm_domain.guest_time); + if ( vpit->first_injected ) { + if ( v->domain->arch.hvm_domain.guest_time ) { + set_guest_time(v, v->domain->arch.hvm_domain.guest_time); + v->domain->arch.hvm_domain.guest_time = 0; + } pickup_deactive_ticks(vpit); } diff -r 7e3cbc409676 -r d75a6cc5e68a xen/arch/x86/hvm/vmx/vmx.c --- a/xen/arch/x86/hvm/vmx/vmx.c Mon Mar 27 15:36:47 2006 -0700 +++ b/xen/arch/x86/hvm/vmx/vmx.c Tue Mar 28 08:54:58 2006 -0700 @@ -89,6 +89,8 @@ static void vmx_relinquish_guest_resourc for_each_vcpu ( d, v ) { + if ( !test_bit(_VCPUF_initialised, &v->vcpu_flags) ) + continue; vmx_request_clear_vmcs(v); destroy_vmcs(&v->arch.hvm_vmx); free_monitor_pagetable(v); @@ -358,9 +360,10 @@ static void vmx_freeze_time(struct vcpu { struct hvm_virpit *vpit = &v->domain->arch.hvm_domain.vpit; - v->domain->arch.hvm_domain.guest_time = get_guest_time(v); - if ( vpit->first_injected ) + if ( vpit->first_injected && !v->domain->arch.hvm_domain.guest_time ) { + v->domain->arch.hvm_domain.guest_time = get_guest_time(v); stop_timer(&(vpit->pit_timer)); + } } static void vmx_ctxt_switch_from(struct vcpu *v) @@ -397,31 +400,81 @@ void vmx_migrate_timers(struct vcpu *v) migrate_timer(&(VLAPIC(v)->vlapic_timer), v->processor); } -void vmx_store_cpu_guest_regs(struct vcpu *v, struct cpu_user_regs *regs) -{ +struct vmx_store_cpu_guest_regs_callback_info { + struct vcpu *v; + struct cpu_user_regs *regs; + unsigned long *crs; +}; + +static void vmx_store_cpu_guest_regs( + struct vcpu *v, struct cpu_user_regs *regs, unsigned long *crs); + +static void vmx_store_cpu_guest_regs_callback(void *data) +{ + struct vmx_store_cpu_guest_regs_callback_info *info = data; + vmx_store_cpu_guest_regs(info->v, info->regs, info->crs); +} + +static void vmx_store_cpu_guest_regs( + struct vcpu *v, struct cpu_user_regs *regs, unsigned long *crs) +{ + if ( v != current ) + { + /* Non-current VCPUs must be paused to get a register snapshot. */ + ASSERT(atomic_read(&v->pausecnt) != 0); + + if ( v->arch.hvm_vmx.launch_cpu != smp_processor_id() ) + { + /* Get register details from remote CPU. */ + struct vmx_store_cpu_guest_regs_callback_info info = { + .v = v, .regs = regs, .crs = crs }; + cpumask_t cpumask = cpumask_of_cpu(v->arch.hvm_vmx.launch_cpu); + on_selected_cpus(cpumask, vmx_store_cpu_guest_regs_callback, + &info, 1, 1); + return; + } + + /* Register details are on this CPU. Load the correct VMCS. */ + __vmptrld(virt_to_maddr(v->arch.hvm_vmx.vmcs)); + } + + ASSERT(v->arch.hvm_vmx.launch_cpu == smp_processor_id()); + + if ( regs != NULL ) + { #if defined (__x86_64__) - __vmread(GUEST_RFLAGS, ®s->rflags); - __vmread(GUEST_SS_SELECTOR, ®s->ss); - __vmread(GUEST_CS_SELECTOR, ®s->cs); - __vmread(GUEST_DS_SELECTOR, ®s->ds); - __vmread(GUEST_ES_SELECTOR, ®s->es); - __vmread(GUEST_GS_SELECTOR, ®s->gs); - __vmread(GUEST_FS_SELECTOR, ®s->fs); - __vmread(GUEST_RIP, ®s->rip); - __vmread(GUEST_RSP, ®s->rsp); + __vmread(GUEST_RFLAGS, ®s->rflags); + __vmread(GUEST_SS_SELECTOR, ®s->ss); + __vmread(GUEST_CS_SELECTOR, ®s->cs); + __vmread(GUEST_DS_SELECTOR, ®s->ds); + __vmread(GUEST_ES_SELECTOR, ®s->es); + __vmread(GUEST_GS_SELECTOR, ®s->gs); + __vmread(GUEST_FS_SELECTOR, ®s->fs); + __vmread(GUEST_RIP, ®s->rip); + __vmread(GUEST_RSP, ®s->rsp); #elif defined (__i386__) - __vmread(GUEST_RFLAGS, ®s->eflags); - __vmread(GUEST_SS_SELECTOR, ®s->ss); - __vmread(GUEST_CS_SELECTOR, ®s->cs); - __vmread(GUEST_DS_SELECTOR, ®s->ds); - __vmread(GUEST_ES_SELECTOR, ®s->es); - __vmread(GUEST_GS_SELECTOR, ®s->gs); - __vmread(GUEST_FS_SELECTOR, ®s->fs); - __vmread(GUEST_RIP, ®s->eip); - __vmread(GUEST_RSP, ®s->esp); -#else -#error Unsupported architecture + __vmread(GUEST_RFLAGS, ®s->eflags); + __vmread(GUEST_SS_SELECTOR, ®s->ss); + __vmread(GUEST_CS_SELECTOR, ®s->cs); + __vmread(GUEST_DS_SELECTOR, ®s->ds); + __vmread(GUEST_ES_SELECTOR, ®s->es); + __vmread(GUEST_GS_SELECTOR, ®s->gs); + __vmread(GUEST_FS_SELECTOR, ®s->fs); + __vmread(GUEST_RIP, ®s->eip); + __vmread(GUEST_RSP, ®s->esp); #endif + } + + if ( crs != NULL ) + { + __vmread(CR0_READ_SHADOW, &crs[0]); + __vmread(GUEST_CR3, &crs[3]); + __vmread(CR4_READ_SHADOW, &crs[4]); + } + + /* Reload current VCPU's VMCS if it was temporarily unloaded. */ + if ( (v != current) && hvm_guest(current) ) + __vmptrld(virt_to_maddr(current->arch.hvm_vmx.vmcs)); } void vmx_load_cpu_guest_regs(struct vcpu *v, struct cpu_user_regs *regs) @@ -453,13 +506,6 @@ void vmx_load_cpu_guest_regs(struct vcpu #else #error Unsupported architecture #endif -} - -void vmx_store_cpu_guest_ctrl_regs(struct vcpu *v, unsigned long crs[8]) -{ - __vmread(CR0_READ_SHADOW, &crs[0]); - __vmread(GUEST_CR3, &crs[3]); - __vmread(CR4_READ_SHADOW, &crs[4]); } void vmx_modify_guest_state(struct vcpu *v) @@ -615,7 +661,6 @@ int start_vmx(void) hvm_funcs.store_cpu_guest_regs = vmx_store_cpu_guest_regs; hvm_funcs.load_cpu_guest_regs = vmx_load_cpu_guest_regs; - hvm_funcs.store_cpu_guest_ctrl_regs = vmx_store_cpu_guest_ctrl_regs; hvm_funcs.modify_guest_state = vmx_modify_guest_state; hvm_funcs.realmode = vmx_realmode; @@ -945,7 +990,7 @@ static void vmx_io_instruction(struct cp port = (exit_qualification >> 16) & 0xFFFF; else port = regs->edx & 0xffff; - TRACE_VMEXIT(2, port); + TRACE_VMEXIT(1, port); size = (exit_qualification & 7) + 1; dir = test_bit(3, &exit_qualification); /* direction */ @@ -1308,7 +1353,8 @@ static int vmx_set_cr0(unsigned long val vm_entry_value |= VM_ENTRY_CONTROLS_IA32E_MODE; __vmwrite(VM_ENTRY_CONTROLS, vm_entry_value); - if ( !shadow_set_guest_paging_levels(v->domain, 4) ) { + if ( !shadow_set_guest_paging_levels(v->domain, PAGING_L4) ) + { printk("Unsupported guest paging levels\n"); domain_crash_synchronous(); /* need to take a clean path */ } @@ -1317,9 +1363,26 @@ static int vmx_set_cr0(unsigned long val #endif /* __x86_64__ */ { #if CONFIG_PAGING_LEVELS >= 3 - if ( !shadow_set_guest_paging_levels(v->domain, 2) ) { - printk("Unsupported guest paging levels\n"); - domain_crash_synchronous(); /* need to take a clean path */ + /* seems it's a 32-bit or 32-bit PAE guest */ + + if ( test_bit(VMX_CPU_STATE_PAE_ENABLED, + &v->arch.hvm_vmx.cpu_state) ) + { + /* The guest enables PAE first and then it enables PG, it is + * really a PAE guest */ + if ( !shadow_set_guest_paging_levels(v->domain, PAGING_L3) ) + { + printk("Unsupported guest paging levels\n"); + domain_crash_synchronous(); + } + } + else + { + if ( !shadow_set_guest_paging_levels(v->domain, PAGING_L2) ) + { + printk("Unsupported guest paging levels\n"); + domain_crash_synchronous(); /* need to take a clean path */ + } } #endif } @@ -1398,6 +1461,12 @@ static int vmx_set_cr0(unsigned long val "Restoring to %%eip 0x%lx\n", eip); return 0; /* do not update eip! */ } + } + else if ( (value & (X86_CR0_PE | X86_CR0_PG)) == X86_CR0_PE ) + { + /* we should take care of this kind of situation */ + clear_all_shadow_status(v->domain); + __vmwrite(GUEST_CR3, pagetable_get_paddr(v->domain->arch.phys_table)); } return 1; @@ -1528,11 +1597,11 @@ static int mov_to_cr(int gp, int cr, str if ( vmx_pgbit_test(v) ) { - /* The guest is 32 bit. */ + /* The guest is a 32-bit PAE guest. */ #if CONFIG_PAGING_LEVELS >= 4 unsigned long mfn, old_base_mfn; - if( !shadow_set_guest_paging_levels(v->domain, 3) ) + if( !shadow_set_guest_paging_levels(v->domain, PAGING_L3) ) { printk("Unsupported guest paging levels\n"); domain_crash_synchronous(); /* need to take a clean path */ @@ -1572,12 +1641,31 @@ static int mov_to_cr(int gp, int cr, str } else { - /* The guest is 64 bit. */ + /* The guest is a 64 bit or 32-bit PAE guest. */ #if CONFIG_PAGING_LEVELS >= 4 - if ( !shadow_set_guest_paging_levels(v->domain, 4) ) + if ( (v->domain->arch.ops != NULL) && + v->domain->arch.ops->guest_paging_levels == PAGING_L2) { - printk("Unsupported guest paging levels\n"); - domain_crash_synchronous(); /* need to take a clean path */ + /* Seems the guest first enables PAE without enabling PG, + * it must enable PG after that, and it is a 32-bit PAE + * guest */ + + if ( !shadow_set_guest_paging_levels(v->domain, + PAGING_L3) ) + { + printk("Unsupported guest paging levels\n"); + /* need to take a clean path */ + domain_crash_synchronous(); + } + } + else + { + if ( !shadow_set_guest_paging_levels(v->domain, + PAGING_L4) ) + { + printk("Unsupported guest paging levels\n"); + domain_crash_synchronous(); + } } #endif } @@ -1827,6 +1915,7 @@ static inline void vmx_vmexit_do_extint( vector &= 0xff; local_irq_disable(); + TRACE_VMEXIT(1,vector); switch(vector) { case LOCAL_TIMER_VECTOR: @@ -1956,7 +2045,6 @@ asmlinkage void vmx_vmexit_handler(struc { __vmread(GUEST_RIP, &eip); - TRACE_3D(TRC_VMX_VMEXIT, v->domain->domain_id, eip, exit_reason); TRACE_VMEXIT(0,exit_reason); } @@ -1980,7 +2068,6 @@ asmlinkage void vmx_vmexit_handler(struc TRACE_VMEXIT(1,vector); perfc_incra(cause_vector, vector); - TRACE_3D(TRC_VMX_VECTOR, v->domain->domain_id, eip, vector); switch (vector) { #ifdef XEN_DEBUGGER case TRAP_debug: @@ -2164,7 +2251,7 @@ asmlinkage void vmx_load_cr2(void) asmlinkage void vmx_trace_vmentry (void) { - TRACE_5D(TRC_VMENTRY, + TRACE_5D(TRC_VMX_VMENTRY, trace_values[smp_processor_id()][0], trace_values[smp_processor_id()][1], trace_values[smp_processor_id()][2], @@ -2180,7 +2267,7 @@ asmlinkage void vmx_trace_vmentry (void) asmlinkage void vmx_trace_vmexit (void) { - TRACE_3D(TRC_VMEXIT,0,0,0); + TRACE_3D(TRC_VMX_VMEXIT,0,0,0); return; } diff -r 7e3cbc409676 -r d75a6cc5e68a xen/arch/x86/mm.c --- a/xen/arch/x86/mm.c Mon Mar 27 15:36:47 2006 -0700 +++ b/xen/arch/x86/mm.c Tue Mar 28 08:54:58 2006 -0700 @@ -3351,8 +3351,9 @@ int ptwr_do_page_fault(struct domain *d, * permissions in page directories by writing back to the linear mapping. */ if ( (flags = l1e_get_flags(pte) & WRPT_PTE_FLAGS) == WRPT_PTE_FLAGS ) - return !__put_user( - pte.l1, &linear_pg_table[l1_linear_offset(addr)].l1); + return __put_user( + pte.l1, &linear_pg_table[l1_linear_offset(addr)].l1) ? + 0 : EXCRET_not_a_fault; /* We are looking only for read-only mappings of p.t. pages. */ if ( ((flags | _PAGE_RW) != WRPT_PTE_FLAGS) || diff -r 7e3cbc409676 -r d75a6cc5e68a xen/arch/x86/shadow.c --- a/xen/arch/x86/shadow.c Mon Mar 27 15:36:47 2006 -0700 +++ b/xen/arch/x86/shadow.c Tue Mar 28 08:54:58 2006 -0700 @@ -1807,6 +1807,16 @@ static int resync_all(struct domain *d, entry_has_changed( guest_pt[i], snapshot_pt[i], PAGE_FLAG_MASK) ) { + + unsigned long gpfn; + + gpfn = entry_get_pfn(guest_pt[i]); + /* + * Looks like it's longer a page table. + */ + if ( unlikely(gpfn != (gpfn & PGT_mfn_mask)) ) + continue; + need_flush |= validate_entry_change( d, &guest_pt[i], &shadow_pt[i], shadow_type_to_level(stype)); @@ -1851,6 +1861,14 @@ static int resync_all(struct domain *d, { #ifndef GUEST_PGENTRY_32 l4_pgentry_t *shadow4 = shadow; + unsigned long gpfn; + + gpfn = l4e_get_pfn(new_root_e); + /* + * Looks like it's longer a page table. + */ + if ( unlikely(gpfn != (gpfn & PGT_mfn_mask)) ) + continue; if ( d->arch.ops->guest_paging_levels == PAGING_L4 ) { @@ -1894,7 +1912,7 @@ static int resync_all(struct domain *d, unmap_domain_page(snapshot); unmap_domain_page(guest); - if ( unlikely(unshadow) ) + if ( unlikely(unshadow && stype == PGT_root_page_table) ) { for_each_vcpu(d, v) if(smfn == pagetable_get_pfn(v->arch.shadow_table)) diff -r 7e3cbc409676 -r d75a6cc5e68a xen/arch/x86/smp.c --- a/xen/arch/x86/smp.c Mon Mar 27 15:36:47 2006 -0700 +++ b/xen/arch/x86/smp.c Tue Mar 28 08:54:58 2006 -0700 @@ -106,6 +106,16 @@ void send_IPI_self(int vector) __send_IPI_shortcut(APIC_DEST_SELF, vector); } +static inline void check_IPI_mask(cpumask_t cpumask) +{ + /* + * Sanity, and necessary. An IPI with no target generates a send accept + * error with Pentium and P6 APICs. + */ + ASSERT(cpus_subset(cpumask, cpu_online_map)); + ASSERT(!cpus_empty(cpumask)); +} + /* * This is only used on smaller machines. */ @@ -115,6 +125,8 @@ void send_IPI_mask_bitmask(cpumask_t cpu unsigned long cfg; unsigned long flags; + check_IPI_mask(cpumask); + local_irq_save(flags); /* @@ -145,6 +157,8 @@ inline void send_IPI_mask_sequence(cpuma { unsigned long cfg, flags; unsigned int query_cpu; + + check_IPI_mask(mask); /* * Hack. The clustered APIC addressing mode doesn't allow us to send @@ -304,6 +318,9 @@ extern int on_selected_cpus( ASSERT(local_irq_is_enabled()); + if ( nr_cpus == 0 ) + return 0; + data.func = func; data.info = info; data.wait = wait; diff -r 7e3cbc409676 -r d75a6cc5e68a xen/arch/x86/traps.c --- a/xen/arch/x86/traps.c Mon Mar 27 15:36:47 2006 -0700 +++ b/xen/arch/x86/traps.c Tue Mar 28 08:54:58 2006 -0700 @@ -286,7 +286,7 @@ asmlinkage void fatal_trap(int trapnr, s unsigned long cr2; static char *trapstr[] = { "divide error", "debug", "nmi", "bkpt", "overflow", "bounds", - "invalid operation", "device not available", "double fault", + "invalid opcode", "device not available", "double fault", "coprocessor segment", "invalid tss", "segment not found", "stack error", "general protection fault", "page fault", "spurious interrupt", "coprocessor error", "alignment check", @@ -382,7 +382,6 @@ DO_ERROR_NOCODE( 0, "divide error", divi DO_ERROR_NOCODE( 0, "divide error", divide_error) DO_ERROR_NOCODE( 4, "overflow", overflow) DO_ERROR_NOCODE( 5, "bounds", bounds) -DO_ERROR_NOCODE( 6, "invalid operand", invalid_op) DO_ERROR_NOCODE( 9, "coprocessor segment overrun", coprocessor_segment_overrun) DO_ERROR(10, "invalid TSS", invalid_TSS) DO_ERROR(11, "segment not present", segment_not_present) @@ -391,6 +390,85 @@ DO_ERROR(17, "alignment check", alignmen DO_ERROR(17, "alignment check", alignment_check) DO_ERROR_NOCODE(19, "simd error", simd_coprocessor_error) +static int emulate_forced_invalid_op(struct cpu_user_regs *regs) +{ + char signature[5], instr[2]; + unsigned long a, b, c, d, eip; + + a = regs->eax; + b = regs->ebx; + c = regs->ecx; + d = regs->edx; + eip = regs->eip; + + /* Check for forced emulation signature: ud2 ; .ascii "xen". */ + if ( copy_from_user(signature, (char *)eip, sizeof(signature)) || + memcmp(signature, "\xf\xbxen", sizeof(signature)) ) + return 0; + eip += sizeof(signature); + + /* We only emulate CPUID. */ + if ( copy_from_user(instr, (char *)eip, sizeof(instr)) || + memcmp(instr, "\xf\xa2", sizeof(instr)) ) + return 0; + eip += sizeof(instr); + + __asm__ ( + "cpuid" + : "=a" (a), "=b" (b), "=c" (c), "=d" (d) + : "0" (a), "1" (b), "2" (c), "3" (d) ); + + if ( regs->eax == 1 ) + { + /* Modify Feature Information. */ + clear_bit(X86_FEATURE_VME, &d); + clear_bit(X86_FEATURE_DE, &d); + clear_bit(X86_FEATURE_PSE, &d); + clear_bit(X86_FEATURE_PGE, &d); + clear_bit(X86_FEATURE_SEP, &d); + if ( !IS_PRIV(current->domain) ) + clear_bit(X86_FEATURE_MTRR, &d); + } + + regs->eax = a; + regs->ebx = b; + regs->ecx = c; + regs->edx = d; + regs->eip = eip; + + return EXCRET_fault_fixed; +} + +asmlinkage int do_invalid_op(struct cpu_user_regs *regs) +{ + struct vcpu *v = current; + struct trap_bounce *tb = &v->arch.trap_bounce; + struct trap_info *ti; + int rc; + + DEBUGGER_trap_entry(TRAP_invalid_op, regs); + + if ( unlikely(!guest_mode(regs)) ) + { + DEBUGGER_trap_fatal(TRAP_invalid_op, regs); + show_registers(regs); + panic("CPU%d FATAL TRAP: vector = %d (invalid opcode)\n", + smp_processor_id(), TRAP_invalid_op); + } + + if ( (rc = emulate_forced_invalid_op(regs)) != 0 ) + return rc; + + ti = ¤t->arch.guest_context.trap_ctxt[TRAP_invalid_op]; + tb->flags = TBF_EXCEPTION; + tb->cs = ti->cs; + tb->eip = ti->address; + if ( TI_GET_IF(ti) ) + tb->flags |= TBF_INTERRUPT; + + return 0; +} + asmlinkage int do_int3(struct cpu_user_regs *regs) { struct vcpu *v = current; @@ -540,6 +618,46 @@ static int fixup_page_fault(unsigned lon } return 0; +} + +static int spurious_page_fault(unsigned long addr, struct cpu_user_regs *regs) +{ + struct vcpu *v = current; + struct domain *d = v->domain; + int rc; + + /* + * The only possible reason for a spurious page fault not to be picked + * up already is that a page directory was unhooked by writable page table + * logic and then reattached before the faulting VCPU could detect it. + */ + if ( is_idle_domain(d) || /* no ptwr in idle domain */ + IN_HYPERVISOR_RANGE(addr) || /* no ptwr on hypervisor addrs */ + shadow_mode_enabled(d) || /* no ptwr logic in shadow mode */ + ((regs->error_code & 0x1d) != 0) ) /* simple not-present fault? */ + return 0; + + LOCK_BIGLOCK(d); + + /* + * The page directory could have been detached again while we weren't + * holding the per-domain lock. Detect that and fix up if it's the case. + */ + if ( unlikely(d->arch.ptwr[PTWR_PT_ACTIVE].l1va) && + unlikely(l2_linear_offset(addr) == + d->arch.ptwr[PTWR_PT_ACTIVE].l2_idx) ) + { + ptwr_flush(d, PTWR_PT_ACTIVE); + rc = 1; + } + else + { + /* Okay, walk the page tables. Only check for not-present faults.*/ + rc = __spurious_page_fault(addr); + } + + UNLOCK_BIGLOCK(d); + return rc; } /* @@ -566,6 +684,13 @@ asmlinkage int do_page_fault(struct cpu_ if ( unlikely(!guest_mode(regs)) ) { + if ( spurious_page_fault(addr, regs) ) + { + DPRINTK("Spurious fault in domain %u:%u at addr %lx\n", + current->domain->domain_id, current->vcpu_id, addr); + return EXCRET_not_a_fault; + } + if ( likely((fixup = search_exception_table(regs->eip)) != 0) ) { perfc_incrc(copy_user_faults); @@ -580,7 +705,7 @@ asmlinkage int do_page_fault(struct cpu_ panic("CPU%d FATAL PAGE FAULT\n" "[error_code=%04x]\n" "Faulting linear address: %p\n", - smp_processor_id(), regs->error_code, addr); + smp_processor_id(), regs->error_code, _p(addr)); } propagate_page_fault(addr, regs->error_code); diff -r 7e3cbc409676 -r d75a6cc5e68a xen/arch/x86/x86_32/traps.c --- a/xen/arch/x86/x86_32/traps.c Mon Mar 27 15:36:47 2006 -0700 +++ b/xen/arch/x86/x86_32/traps.c Tue Mar 28 08:54:58 2006 -0700 @@ -27,8 +27,7 @@ void show_registers(struct cpu_user_regs if ( hvm_guest(current) && guest_mode(regs) ) { context = "hvm"; - hvm_store_cpu_guest_regs(current, &fault_regs); - hvm_store_cpu_guest_ctrl_regs(current, fault_crs); + hvm_store_cpu_guest_regs(current, &fault_regs, fault_crs); } else { @@ -71,38 +70,77 @@ void show_registers(struct cpu_user_regs void show_page_walk(unsigned long addr) { + unsigned long pfn, mfn = read_cr3() >> PAGE_SHIFT; +#ifdef CONFIG_X86_PAE + l3_pgentry_t l3e, *l3t; +#endif + l2_pgentry_t l2e, *l2t; + l1_pgentry_t l1e, *l1t; + + printk("Pagetable walk from %08lx:\n", addr); + +#ifdef CONFIG_X86_PAE + l3t = map_domain_page(mfn); + l3e = l3t[l3_table_offset(addr)]; + mfn = l3e_get_pfn(l3e); + pfn = get_gpfn_from_mfn(mfn); + printk(" L3 = %"PRIpte" %08lx\n", l3e_get_intpte(l3e), pfn); + unmap_domain_page(l3t); + if ( !(l3e_get_flags(l3e) & _PAGE_PRESENT) ) + return; +#endif + + l2t = map_domain_page(mfn); + l2e = l2t[l2_table_offset(addr)]; + mfn = l2e_get_pfn(l2e); + pfn = get_gpfn_from_mfn(mfn); + printk(" L2 = %"PRIpte" %08lx %s\n", l2e_get_intpte(l2e), pfn, + (l2e_get_flags(l2e) & _PAGE_PSE) ? "(PSE)" : ""); + unmap_domain_page(l2t); + if ( !(l2e_get_flags(l2e) & _PAGE_PRESENT) || + (l2e_get_flags(l2e) & _PAGE_PSE) ) + return; + + l1t = map_domain_page(mfn); + l1e = l1t[l1_table_offset(addr)]; + mfn = l1e_get_pfn(l1e); + pfn = get_gpfn_from_mfn(mfn); + printk(" L1 = %"PRIpte" %08lx\n", l1e_get_intpte(l1e), pfn); + unmap_domain_page(l1t); +} + +int __spurious_page_fault(unsigned long addr) +{ unsigned long mfn = read_cr3() >> PAGE_SHIFT; - intpte_t *ptab, ent; - unsigned long pfn; - - printk("Pagetable walk from %08lx:\n", addr); - #ifdef CONFIG_X86_PAE - ptab = map_domain_page(mfn); - ent = ptab[l3_table_offset(addr)]; - pfn = get_gpfn_from_mfn((u32)(ent >> PAGE_SHIFT)); - printk(" L3 = %"PRIpte" %08lx\n", ent, pfn); - unmap_domain_page(ptab); - if ( !(ent & _PAGE_PRESENT) ) - return; - mfn = ent >> PAGE_SHIFT; + l3_pgentry_t l3e, *l3t; #endif - - ptab = map_domain_page(mfn); - ent = ptab[l2_table_offset(addr)]; - pfn = get_gpfn_from_mfn((u32)(ent >> PAGE_SHIFT)); - printk(" L2 = %"PRIpte" %08lx %s\n", ent, pfn, - (ent & _PAGE_PSE) ? "(PSE)" : ""); - unmap_domain_page(ptab); - if ( !(ent & _PAGE_PRESENT) || (ent & _PAGE_PSE) ) - return; - mfn = ent >> PAGE_SHIFT; - - ptab = map_domain_page(ent >> PAGE_SHIFT); - ent = ptab[l1_table_offset(addr)]; - pfn = get_gpfn_from_mfn((u32)(ent >> PAGE_SHIFT)); - printk(" L1 = %"PRIpte" %08lx\n", ent, pfn); - unmap_domain_page(ptab); + l2_pgentry_t l2e, *l2t; + l1_pgentry_t l1e, *l1t; + +#ifdef CONFIG_X86_PAE + l3t = map_domain_page(mfn); + l3e = l3t[l3_table_offset(addr)]; + mfn = l3e_get_pfn(l3e); + unmap_domain_page(l3t); + if ( !(l3e_get_flags(l3e) & _PAGE_PRESENT) ) + return 0; +#endif + + l2t = map_domain_page(mfn); + l2e = l2t[l2_table_offset(addr)]; + mfn = l2e_get_pfn(l2e); + unmap_domain_page(l2t); + if ( !(l2e_get_flags(l2e) & _PAGE_PRESENT) ) + return 0; + if ( l2e_get_flags(l2e) & _PAGE_PSE ) + return 1; + + l1t = map_domain_page(mfn); + l1e = l1t[l1_table_offset(addr)]; + mfn = l1e_get_pfn(l1e); + unmap_domain_page(l1t); + return !!(l1e_get_flags(l1e) & _PAGE_PRESENT); } #define DOUBLEFAULT_STACK_SIZE 1024 diff -r 7e3cbc409676 -r d75a6cc5e68a xen/arch/x86/x86_64/traps.c --- a/xen/arch/x86/x86_64/traps.c Mon Mar 27 15:36:47 2006 -0700 +++ b/xen/arch/x86/x86_64/traps.c Tue Mar 28 08:54:58 2006 -0700 @@ -27,8 +27,7 @@ void show_registers(struct cpu_user_regs if ( hvm_guest(current) && guest_mode(regs) ) { context = "hvm"; - hvm_store_cpu_guest_regs(current, &fault_regs); - hvm_store_cpu_guest_ctrl_regs(current, fault_crs); + hvm_store_cpu_guest_regs(current, &fault_regs, fault_crs); } else { @@ -71,31 +70,79 @@ void show_registers(struct cpu_user_regs void show_page_walk(unsigned long addr) { - unsigned long page = read_cr3(); - + unsigned long pfn, mfn = read_cr3() >> PAGE_SHIFT; + l4_pgentry_t l4e, *l4t; + l3_pgentry_t l3e, *l3t; + l2_pgentry_t l2e, *l2t; + l1_pgentry_t l1e, *l1t; + printk("Pagetable walk from %016lx:\n", addr); - page &= PAGE_MASK; - page = ((unsigned long *) __va(page))[l4_table_offset(addr)]; - printk(" L4 = %016lx\n", page); - if ( !(page & _PAGE_PRESENT) ) + l4t = mfn_to_virt(mfn); + l4e = l4t[l4_table_offset(addr)]; + mfn = l4e_get_pfn(l4e); + pfn = get_gpfn_from_mfn(mfn); + printk(" L4 = %"PRIpte" %016lx\n", l4e_get_intpte(l4e), pfn); + if ( !(l4e_get_flags(l4e) & _PAGE_PRESENT) ) return; - page &= PAGE_MASK; - page = ((unsigned long *) __va(page))[l3_table_offset(addr)]; - printk(" L3 = %016lx\n", page); - if ( !(page & _PAGE_PRESENT) ) + l3t = mfn_to_virt(mfn); + l3e = l3t[l3_table_offset(addr)]; + mfn = l3e_get_pfn(l3e); + pfn = get_gpfn_from_mfn(mfn); + printk(" L3 = %"PRIpte" %016lx\n", l3e_get_intpte(l3e), pfn); + if ( !(l3e_get_flags(l3e) & _PAGE_PRESENT) ) return; - page &= PAGE_MASK; - page = ((unsigned long *) __va(page))[l2_table_offset(addr)]; - printk(" L2 = %016lx %s\n", page, (page & _PAGE_PSE) ? "(2MB)" : ""); - if ( !(page & _PAGE_PRESENT) || (page & _PAGE_PSE) ) + l2t = mfn_to_virt(mfn); + l2e = l2t[l2_table_offset(addr)]; + mfn = l2e_get_pfn(l2e); + pfn = get_gpfn_from_mfn(mfn); + printk(" L2 = %"PRIpte" %016lx %s\n", l2e_get_intpte(l2e), pfn, + (l2e_get_flags(l2e) & _PAGE_PSE) ? "(PSE)" : ""); + if ( !(l2e_get_flags(l2e) & _PAGE_PRESENT) || + (l2e_get_flags(l2e) & _PAGE_PSE) ) return; - page &= PAGE_MASK; - page = ((unsigned long *) __va(page))[l1_table_offset(addr)]; - printk(" L1 = %016lx\n", page); + l1t = mfn_to_virt(mfn); + l1e = l1t[l1_table_offset(addr)]; + mfn = l1e_get_pfn(l1e); + pfn = get_gpfn_from_mfn(mfn); + printk(" L1 = %"PRIpte" %016lx\n", l1e_get_intpte(l1e), pfn); +} + +int __spurious_page_fault(unsigned long addr) +{ + unsigned long mfn = read_cr3() >> PAGE_SHIFT; + l4_pgentry_t l4e, *l4t; + l3_pgentry_t l3e, *l3t; + l2_pgentry_t l2e, *l2t; + l1_pgentry_t l1e, *l1t; + + l4t = mfn_to_virt(mfn); + l4e = l4t[l4_table_offset(addr)]; + mfn = l4e_get_pfn(l4e); + if ( !(l4e_get_flags(l4e) & _PAGE_PRESENT) ) + return 0; + + l3t = mfn_to_virt(mfn); + l3e = l3t[l3_table_offset(addr)]; + mfn = l3e_get_pfn(l3e); + if ( !(l3e_get_flags(l3e) & _PAGE_PRESENT) ) + return 0; + + l2t = mfn_to_virt(mfn); + l2e = l2t[l2_table_offset(addr)]; + mfn = l2e_get_pfn(l2e); + if ( !(l2e_get_flags(l2e) & _PAGE_PRESENT) ) + return 0; + if ( l2e_get_flags(l2e) & _PAGE_PSE ) + return 1; + + l1t = mfn_to_virt(mfn); + l1e = l1t[l1_table_offset(addr)]; + mfn = l1e_get_pfn(l1e); + return !!(l1e_get_flags(l1e) & _PAGE_PRESENT); } asmlinkage void double_fault(void); diff -r 7e3cbc409676 -r d75a6cc5e68a xen/common/gdbstub.c --- a/xen/common/gdbstub.c Mon Mar 27 15:36:47 2006 -0700 +++ b/xen/common/gdbstub.c Tue Mar 28 08:54:58 2006 -0700 @@ -562,6 +562,7 @@ initialise_gdb(void) gdb_ctx->serhnd = serial_parse_handle(opt_gdb); if ( gdb_ctx->serhnd != -1 ) printk("GDB stub initialised.\n"); + serial_start_sync(gdb_ctx->serhnd); } /* diff -r 7e3cbc409676 -r d75a6cc5e68a xen/common/page_alloc.c --- a/xen/common/page_alloc.c Mon Mar 27 15:36:47 2006 -0700 +++ b/xen/common/page_alloc.c Tue Mar 28 08:54:58 2006 -0700 @@ -219,8 +219,6 @@ unsigned long alloc_boot_pages(unsigned #define pfn_dom_zone_type(_pfn) \ (((_pfn) <= MAX_DMADOM_PFN) ? MEMZONE_DMADOM : MEMZONE_DOM) -/* Up to 2^20 pages can be allocated at once. */ -#define MAX_ORDER 20 static struct list_head heap[NR_ZONES][MAX_ORDER+1]; static unsigned long avail[NR_ZONES]; diff -r 7e3cbc409676 -r d75a6cc5e68a xen/drivers/char/ns16550.c --- a/xen/drivers/char/ns16550.c Mon Mar 27 15:36:47 2006 -0700 +++ b/xen/drivers/char/ns16550.c Tue Mar 28 08:54:58 2006 -0700 @@ -121,8 +121,11 @@ static void ns16550_interrupt( while ( !(ns_read_reg(uart, IIR) & IIR_NOINT) ) { - serial_tx_interrupt(port, regs); - serial_rx_interrupt(port, regs); + char lsr = ns_read_reg(uart, LSR); + if ( lsr & LSR_THRE ) + serial_tx_interrupt(port, regs); + if ( lsr & LSR_DR ) + serial_rx_interrupt(port, regs); } } diff -r 7e3cbc409676 -r d75a6cc5e68a xen/drivers/char/serial.c --- a/xen/drivers/char/serial.c Mon Mar 27 15:36:47 2006 -0700 +++ b/xen/drivers/char/serial.c Tue Mar 28 08:54:58 2006 -0700 @@ -7,6 +7,7 @@ */ #include <xen/config.h> +#include <xen/delay.h> #include <xen/init.h> #include <xen/irq.h> #include <xen/keyhandler.h> @@ -15,8 +16,8 @@ #include <xen/serial.h> static struct serial_port com[2] = { - { .lock = SPIN_LOCK_UNLOCKED }, - { .lock = SPIN_LOCK_UNLOCKED } + { .rx_lock = SPIN_LOCK_UNLOCKED, .tx_lock = SPIN_LOCK_UNLOCKED }, + { .rx_lock = SPIN_LOCK_UNLOCKED, .tx_lock = SPIN_LOCK_UNLOCKED } }; void serial_rx_interrupt(struct serial_port *port, struct cpu_user_regs *regs) @@ -25,7 +26,7 @@ void serial_rx_interrupt(struct serial_p serial_rx_fn fn = NULL; unsigned long flags; - spin_lock_irqsave(&port->lock, flags); + spin_lock_irqsave(&port->rx_lock, flags); if ( port->driver->getc(port, &c) ) { @@ -39,7 +40,7 @@ void serial_rx_interrupt(struct serial_p port->rxbuf[MASK_SERIAL_RXBUF_IDX(port->rxbufp++)] = c; } - spin_unlock_irqrestore(&port->lock, flags); + spin_unlock_irqrestore(&port->rx_lock, flags); if ( fn != NULL ) (*fn)(c & 0x7f, regs); @@ -50,7 +51,19 @@ void serial_tx_interrupt(struct serial_p int i; unsigned long flags; - spin_lock_irqsave(&port->lock, flags); + local_irq_save(flags); + + /* + * Avoid spinning for a long time: if there is a long-term lock holder + * then we know that they'll be stuffing bytes into the transmitter which + * will therefore not be empty for long. + */ + while ( !spin_trylock(&port->tx_lock) ) + { + if ( !port->driver->tx_empty(port) ) + return; + cpu_relax(); + } if ( port->driver->tx_empty(port) ) { @@ -63,7 +76,7 @@ void serial_tx_interrupt(struct serial_p } } - spin_unlock_irqrestore(&port->lock, flags); + spin_unlock_irqrestore(&port->tx_lock, flags); } static void __serial_putc(struct serial_port *port, char c) @@ -117,7 +130,7 @@ void serial_putc(int handle, char c) if ( (handle == -1) || !port->driver || !port->driver->putc ) return; - spin_lock_irqsave(&port->lock, flags); + spin_lock_irqsave(&port->tx_lock, flags); if ( (c == '\n') && (handle & SERHND_COOKED) ) __serial_putc(port, '\r'); @@ -129,7 +142,7 @@ void serial_putc(int handle, char c) __serial_putc(port, c); - spin_unlock_irqrestore(&port->lock, flags); + spin_unlock_irqrestore(&port->tx_lock, flags); } void serial_puts(int handle, const char *s) @@ -141,7 +154,7 @@ void serial_puts(int handle, const char if ( (handle == -1) || !port->driver || !port->driver->putc ) return; - spin_lock_irqsave(&port->lock, flags); + spin_lock_irqsave(&port->tx_lock, flags); while ( (c = *s++) != '\0' ) { @@ -156,7 +169,7 @@ void serial_puts(int handle, const char __serial_putc(port, c); } - spin_unlock_irqrestore(&port->lock, flags); + spin_unlock_irqrestore(&port->tx_lock, flags); } char serial_getc(int handle) @@ -168,27 +181,28 @@ char serial_getc(int handle) if ( (handle == -1) || !port->driver || !port->driver->getc ) return '\0'; - do { + do { for ( ; ; ) { - spin_lock_irqsave(&port->lock, flags); + spin_lock_irqsave(&port->rx_lock, flags); if ( port->rxbufp != port->rxbufc ) { c = port->rxbuf[MASK_SERIAL_RXBUF_IDX(port->rxbufc++)]; - spin_unlock_irqrestore(&port->lock, flags); + spin_unlock_irqrestore(&port->rx_lock, flags); break; } if ( port->driver->getc(port, &c) ) { - spin_unlock_irqrestore(&port->lock, flags); + spin_unlock_irqrestore(&port->rx_lock, flags); break; } - spin_unlock_irqrestore(&port->lock, flags); + spin_unlock_irqrestore(&port->rx_lock, flags); cpu_relax(); + udelay(100); } } while ( ((handle & SERHND_LO) && (c & 0x80)) || ((handle & SERHND_HI) && !(c & 0x80)) ); @@ -241,7 +255,7 @@ void serial_set_rx_handler(int handle, s if ( handle == -1 ) return; - spin_lock_irqsave(&port->lock, flags); + spin_lock_irqsave(&port->rx_lock, flags); if ( port->rx != NULL ) goto fail; @@ -265,11 +279,11 @@ void serial_set_rx_handler(int handle, s port->rx = fn; } - spin_unlock_irqrestore(&port->lock, flags); + spin_unlock_irqrestore(&port->rx_lock, flags); return; fail: - spin_unlock_irqrestore(&port->lock, flags); + spin_unlock_irqrestore(&port->rx_lock, flags); printk("ERROR: Conflicting receive handlers for COM%d\n", handle & SERHND_IDX); } @@ -277,8 +291,13 @@ void serial_force_unlock(int handle) void serial_force_unlock(int handle) { struct serial_port *port = &com[handle & SERHND_IDX]; - if ( handle != -1 ) - port->lock = SPIN_LOCK_UNLOCKED; + + if ( handle == -1 ) + return; + + port->rx_lock = SPIN_LOCK_UNLOCKED; + port->tx_lock = SPIN_LOCK_UNLOCKED; + serial_start_sync(handle); } @@ -290,7 +309,7 @@ void serial_start_sync(int handle) if ( handle == -1 ) return; - spin_lock_irqsave(&port->lock, flags); + spin_lock_irqsave(&port->tx_lock, flags); if ( port->sync++ == 0 ) { @@ -303,7 +322,7 @@ void serial_start_sync(int handle) } } - spin_unlock_irqrestore(&port->lock, flags); + spin_unlock_irqrestore(&port->tx_lock, flags); } void serial_end_sync(int handle) @@ -314,11 +333,11 @@ void serial_end_sync(int handle) if ( handle == -1 ) return; - spin_lock_irqsave(&port->lock, flags); + spin_lock_irqsave(&port->tx_lock, flags); port->sync--; - spin_unlock_irqrestore(&port->lock, flags); + spin_unlock_irqrestore(&port->tx_lock, flags); } int serial_tx_space(int handle) diff -r 7e3cbc409676 -r d75a6cc5e68a xen/include/asm-x86/hvm/hvm.h --- a/xen/include/asm-x86/hvm/hvm.h Mon Mar 27 15:36:47 2006 -0700 +++ b/xen/include/asm-x86/hvm/hvm.h Tue Mar 28 08:54:58 2006 -0700 @@ -41,12 +41,12 @@ struct hvm_function_table { /* * Store and load guest state: * 1) load/store guest register state, - * 2) store guest control register state (used for panic dumps), - * 3) modify guest state (e.g., set debug flags). + * 2) modify guest state (e.g., set debug flags). */ - void (*store_cpu_guest_regs)(struct vcpu *v, struct cpu_user_regs *r); - void (*load_cpu_guest_regs)(struct vcpu *v, struct cpu_user_regs *r); - void (*store_cpu_guest_ctrl_regs)(struct vcpu *v, unsigned long crs[8]); + void (*store_cpu_guest_regs)( + struct vcpu *v, struct cpu_user_regs *r, unsigned long *crs); + void (*load_cpu_guest_regs)( + struct vcpu *v, struct cpu_user_regs *r); void (*modify_guest_state)(struct vcpu *v); /* @@ -93,21 +93,16 @@ hvm_relinquish_guest_resources(struct do } static inline void -hvm_store_cpu_guest_regs(struct vcpu *v, struct cpu_user_regs *r) +hvm_store_cpu_guest_regs( + struct vcpu *v, struct cpu_user_regs *r, unsigned long *crs) { - hvm_funcs.store_cpu_guest_regs(v, r); + hvm_funcs.store_cpu_guest_regs(v, r, crs); } static inline void hvm_load_cpu_guest_regs(struct vcpu *v, struct cpu_user_regs *r) { hvm_funcs.load_cpu_guest_regs(v, r); -} - -static inline void -hvm_store_cpu_guest_ctrl_regs(struct vcpu *v, unsigned long crs[8]) -{ - hvm_funcs.store_cpu_guest_ctrl_regs(v, crs); } static inline void diff -r 7e3cbc409676 -r d75a6cc5e68a xen/include/asm-x86/hvm/svm/svm.h --- a/xen/include/asm-x86/hvm/svm/svm.h Mon Mar 27 15:36:47 2006 -0700 +++ b/xen/include/asm-x86/hvm/svm/svm.h Tue Mar 28 08:54:58 2006 -0700 @@ -48,6 +48,8 @@ extern void svm_stts(struct vcpu *v); extern void svm_stts(struct vcpu *v); extern void svm_do_launch(struct vcpu *v); extern void svm_do_resume(struct vcpu *v); +extern void svm_set_guest_time(struct vcpu *v, u64 gtime); +extern u64 svm_get_guest_time(struct vcpu *v); extern void arch_svm_do_resume(struct vcpu *v); extern int load_vmcb(struct arch_svm_struct *arch_svm, u64 phys_hsa); /* For debugging. Remove when no longer needed. */ diff -r 7e3cbc409676 -r d75a6cc5e68a xen/include/asm-x86/processor.h --- a/xen/include/asm-x86/processor.h Mon Mar 27 15:36:47 2006 -0700 +++ b/xen/include/asm-x86/processor.h Tue Mar 28 08:54:58 2006 -0700 @@ -524,6 +524,7 @@ void show_stack(struct cpu_user_regs *re void show_stack(struct cpu_user_regs *regs); void show_registers(struct cpu_user_regs *regs); void show_page_walk(unsigned long addr); +int __spurious_page_fault(unsigned long addr); asmlinkage void fatal_trap(int trapnr, struct cpu_user_regs *regs); extern void mtrr_ap_init(void); diff -r 7e3cbc409676 -r d75a6cc5e68a xen/include/public/arch-x86_32.h --- a/xen/include/public/arch-x86_32.h Mon Mar 27 15:36:47 2006 -0700 +++ b/xen/include/public/arch-x86_32.h Tue Mar 28 08:54:58 2006 -0700 @@ -170,6 +170,18 @@ typedef struct { #endif /* !__ASSEMBLY__ */ +/* + * Prefix forces emulation of some non-trapping instructions. + * Currently only CPUID. + */ +#ifdef __ASSEMBLY__ +#define XEN_EMULATE_PREFIX .byte 0x0f,0x0b,0x78,0x65,0x6e ; +#define XEN_CPUID XEN_EMULATE_PREFIX cpuid +#else +#define XEN_EMULATE_PREFIX ".byte 0x0f,0x0b,0x78,0x65,0x6e ; " +#define XEN_CPUID XEN_EMULATE_PREFIX "cpuid" +#endif + #endif /* diff -r 7e3cbc409676 -r d75a6cc5e68a xen/include/public/arch-x86_64.h --- a/xen/include/public/arch-x86_64.h Mon Mar 27 15:36:47 2006 -0700 +++ b/xen/include/public/arch-x86_64.h Tue Mar 28 08:54:58 2006 -0700 @@ -246,6 +246,18 @@ typedef struct { #endif /* !__ASSEMBLY__ */ +/* + * Prefix forces emulation of some non-trapping instructions. + * Currently only CPUID. + */ +#ifdef __ASSEMBLY__ +#define XEN_EMULATE_PREFIX .byte 0x0f,0x0b,0x78,0x65,0x6e ; +#define XEN_CPUID XEN_EMULATE_PREFIX cpuid +#else +#define XEN_EMULATE_PREFIX ".byte 0x0f,0x0b,0x78,0x65,0x6e ; " +#define XEN_CPUID XEN_EMULATE_PREFIX "cpuid" +#endif + #endif /* diff -r 7e3cbc409676 -r d75a6cc5e68a xen/include/public/io/netif.h --- a/xen/include/public/io/netif.h Mon Mar 27 15:36:47 2006 -0700 +++ b/xen/include/public/io/netif.h Tue Mar 28 08:54:58 2006 -0700 @@ -20,8 +20,12 @@ */ /* Protocol checksum field is blank in the packet (hardware offload)? */ -#define _NETTXF_csum_blank (0) -#define NETTXF_csum_blank (1U<<_NETTXF_csum_blank) +#define _NETTXF_csum_blank (0) +#define NETTXF_csum_blank (1U<<_NETTXF_csum_blank) + +/* Packet data has been validated against protocol checksum. */ +#define _NETTXF_data_validated (1) +#define NETTXF_data_validated (1U<<_NETTXF_data_validated) typedef struct netif_tx_request { grant_ref_t gref; /* Reference to buffer page */ @@ -41,9 +45,13 @@ typedef struct { grant_ref_t gref; /* Reference to incoming granted frame */ } netif_rx_request_t; -/* Protocol checksum already validated (e.g., performed by hardware)? */ -#define _NETRXF_csum_valid (0) -#define NETRXF_csum_valid (1U<<_NETRXF_csum_valid) +/* Packet data has been validated against protocol checksum. */ +#define _NETRXF_data_validated (0) +#define NETRXF_data_validated (1U<<_NETRXF_data_validated) + +/* Protocol checksum field is blank in the packet (hardware offload)? */ +#define _NETRXF_csum_blank (1) +#define NETRXF_csum_blank (1U<<_NETRXF_csum_blank) typedef struct { uint16_t id; diff -r 7e3cbc409676 -r d75a6cc5e68a xen/include/public/trace.h --- a/xen/include/public/trace.h Mon Mar 27 15:36:47 2006 -0700 +++ b/xen/include/public/trace.h Tue Mar 28 08:54:58 2006 -0700 @@ -24,7 +24,6 @@ #define TRC_VMXTIMER 0x00082000 /* VMX timer trace */ #define TRC_VMXINT 0x00084000 /* VMX interrupt trace */ #define TRC_VMXIO 0x00088000 /* VMX io emulation trace */ -#define TRC_VMEXIT_HANDLER 0x00090000 /* VMX handler trace */ /* Trace events per class */ @@ -50,14 +49,11 @@ /* trace events per subclass */ #define TRC_VMX_VMEXIT (TRC_VMXEXIT + 1) -#define TRC_VMX_VECTOR (TRC_VMXEXIT + 2) +#define TRC_VMX_VMENTRY (TRC_VMXEXIT + 2) #define TRC_VMX_TIMER_INTR (TRC_VMXTIMER + 1) #define TRC_VMX_INT (TRC_VMXINT + 1) - -#define TRC_VMEXIT (TRC_VMEXIT_HANDLER + 1) -#define TRC_VMENTRY (TRC_VMEXIT_HANDLER + 2) /* This structure represents a single trace buffer record. */ diff -r 7e3cbc409676 -r d75a6cc5e68a xen/include/xen/lib.h --- a/xen/include/xen/lib.h Mon Mar 27 15:36:47 2006 -0700 +++ b/xen/include/xen/lib.h Tue Mar 28 08:54:58 2006 -0700 @@ -47,7 +47,8 @@ extern void debugtrace_printk(const char #define printk(_f , _a...) printf( _f , ## _a ) extern void printf(const char *format, ...) __attribute__ ((format (printf, 1, 2))); -extern void panic(const char *format, ...); +extern void panic(const char *format, ...) + __attribute__ ((format (printf, 1, 2))); extern long vm_assist(struct domain *, unsigned int, unsigned int); /* vsprintf.c */ diff -r 7e3cbc409676 -r d75a6cc5e68a xen/include/xen/mm.h --- a/xen/include/xen/mm.h Mon Mar 27 15:36:47 2006 -0700 +++ b/xen/include/xen/mm.h Tue Mar 28 08:54:58 2006 -0700 @@ -68,6 +68,9 @@ unsigned long avail_domheap_pages(void); #define ALLOC_DOM_DMA 1 +/* Up to 2^20 pages can be allocated at once. */ +#define MAX_ORDER 20 + /* Automatic page scrubbing for dead domains. */ extern struct list_head page_scrub_list; #define page_scrub_schedule_work() \ diff -r 7e3cbc409676 -r d75a6cc5e68a xen/include/xen/serial.h --- a/xen/include/xen/serial.h Mon Mar 27 15:36:47 2006 -0700 +++ b/xen/include/xen/serial.h Tue Mar 28 08:54:58 2006 -0700 @@ -42,7 +42,7 @@ struct serial_port { char rxbuf[SERIAL_RXBUFSZ]; unsigned int rxbufp, rxbufc; /* Serial I/O is concurrency-safe. */ - spinlock_t lock; + spinlock_t rx_lock, tx_lock; }; struct uart_driver { diff -r 7e3cbc409676 -r d75a6cc5e68a buildconfigs/linux-defconfig_xen_ia64 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/buildconfigs/linux-defconfig_xen_ia64 Tue Mar 28 08:54:58 2006 -0700 @@ -0,0 +1,1523 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.16-xen +# Mon Mar 27 14:36:21 2006 +# + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +# CONFIG_CPUSETS is not set +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +# CONFIG_EMBEDDED is not set +CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_ALL=y +CONFIG_KALLSYMS_EXTRA_PASS=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +CONFIG_SLAB=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_KMOD=y +CONFIG_STOP_MACHINE=y + +# +# Block layer +# + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" + +# +# Processor type and features +# +CONFIG_IA64=y +CONFIG_64BIT=y +CONFIG_MMU=y +CONFIG_SWIOTLB=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_TIME_INTERPOLATION=y +CONFIG_EFI=y +CONFIG_GENERIC_IOMAP=y +CONFIG_XEN=y +CONFIG_ARCH_XEN=y +CONFIG_XEN_PRIVILEGED_GUEST=y +CONFIG_XEN_BLKDEV_GRANT=y +CONFIG_XEN_BLKDEV_FRONTEND=y +CONFIG_XEN_BLKDEV_BACKEND=y +CONFIG_XEN_SYSFS=y +CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_DMA_IS_DMA32=y +# CONFIG_IA64_GENERIC is not set +CONFIG_IA64_DIG=y +# CONFIG_IA64_HP_ZX1 is not set +# CONFIG_IA64_HP_ZX1_SWIOTLB is not set +# CONFIG_IA64_SGI_SN2 is not set +# CONFIG_IA64_HP_SIM is not set +# CONFIG_ITANIUM is not set +CONFIG_MCKINLEY=y +# CONFIG_IA64_PAGE_SIZE_4KB is not set +# CONFIG_IA64_PAGE_SIZE_8KB is not set +CONFIG_IA64_PAGE_SIZE_16KB=y +# CONFIG_IA64_PAGE_SIZE_64KB is not set +CONFIG_PGTABLE_3=y +# CONFIG_PGTABLE_4 is not set +CONFIG_HZ_100=y +# CONFIG_HZ_250 is not set +# CONFIG_HZ_1000 is not set +CONFIG_HZ=100 +CONFIG_IA64_L1_CACHE_SHIFT=7 +CONFIG_IA64_CYCLONE=y +CONFIG_IOSAPIC=y +CONFIG_FORCE_MAX_ZONEORDER=11 +CONFIG_SMP=y +CONFIG_NR_CPUS=4 +CONFIG_HOTPLUG_CPU=y +# CONFIG_SCHED_SMT is not set +# CONFIG_PREEMPT is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_ARCH_DISCONTIGMEM_ENABLE=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +# CONFIG_VIRTUAL_MEM_MAP is not set +# CONFIG_IA32_SUPPORT is not set +CONFIG_IA64_MCA_RECOVERY=y +CONFIG_PERFMON=y +CONFIG_IA64_PALINFO=y + +# +# Firmware Drivers +# +CONFIG_EFI_VARS=y +CONFIG_EFI_PCDP=y +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=y + +# +# Power management and ACPI +# +CONFIG_PM=y +CONFIG_PM_LEGACY=y +# CONFIG_PM_DEBUG is not set + +# +# ACPI (Advanced Configuration and Power Interface) Support +# +CONFIG_ACPI=y +CONFIG_ACPI_BUTTON=y +CONFIG_ACPI_FAN=y +CONFIG_ACPI_PROCESSOR=y +CONFIG_ACPI_HOTPLUG_CPU=y +CONFIG_ACPI_THERMAL=y +CONFIG_ACPI_BLACKLIST_YEAR=0 +# CONFIG_ACPI_DEBUG is not set +CONFIG_ACPI_EC=y +CONFIG_ACPI_POWER=y +CONFIG_ACPI_SYSTEM=y +CONFIG_ACPI_CONTAINER=y + +# +# CPU Frequency scaling +# +# CONFIG_CPU_FREQ is not set + +# +# Bus options (PCI, PCMCIA) +# +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_LEGACY_PROC=y +# CONFIG_PCI_DEBUG is not set + +# +# PCI Hotplug Support +# +CONFIG_HOTPLUG_PCI=y +# CONFIG_HOTPLUG_PCI_FAKE is not set +CONFIG_HOTPLUG_PCI_ACPI=y +# CONFIG_HOTPLUG_PCI_ACPI_IBM is not set +# CONFIG_HOTPLUG_PCI_CPCI is not set +# CONFIG_HOTPLUG_PCI_SHPC is not set + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +CONFIG_ARPD=y +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y + +# +# IP: Virtual Server Configuration +# +# CONFIG_IP_VS is not set +# CONFIG_IPV6 is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_BRIDGE_NETFILTER=y + +# +# Core Netfilter Configuration +# +# CONFIG_NETFILTER_NETLINK is not set +# CONFIG_NF_CONNTRACK is not set +# CONFIG_NETFILTER_XTABLES is not set + +# +# IP: Netfilter Configuration +# +# CONFIG_IP_NF_CONNTRACK is not set +# CONFIG_IP_NF_QUEUE is not set + +# +# Bridge: Netfilter Configuration +# +# CONFIG_BRIDGE_NF_EBTABLES is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +CONFIG_BRIDGE=y +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +# CONFIG_DEBUG_DRIVER is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# +# CONFIG_PNP is not set + +# +# Block devices +# +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_CRYPTOLOOP=y +CONFIG_BLK_DEV_NBD=y +# CONFIG_BLK_DEV_SX8 is not set +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_INITRD=y +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_IDE_MAX_HWIFS=4 +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_IDE_SATA is not set +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_IDEDISK_MULTI_MODE is not set +CONFIG_BLK_DEV_IDECD=y +# CONFIG_BLK_DEV_IDETAPE is not set +CONFIG_BLK_DEV_IDEFLOPPY=y +CONFIG_BLK_DEV_IDESCSI=y +# CONFIG_IDE_TASK_IOCTL is not set + +# +# IDE chipset support/bugfixes +# +# CONFIG_IDE_GENERIC is not set +CONFIG_BLK_DEV_IDEPCI=y +# CONFIG_IDEPCI_SHARE_IRQ is not set +# CONFIG_BLK_DEV_OFFBOARD is not set +CONFIG_BLK_DEV_GENERIC=y +# CONFIG_BLK_DEV_OPTI621 is not set +CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set +CONFIG_IDEDMA_PCI_AUTO=y +# CONFIG_IDEDMA_ONLYDISK is not set +# CONFIG_BLK_DEV_AEC62XX is not set +# CONFIG_BLK_DEV_ALI15X3 is not set +# CONFIG_BLK_DEV_AMD74XX is not set +CONFIG_BLK_DEV_CMD64X=y +# CONFIG_BLK_DEV_TRIFLEX is not set +# CONFIG_BLK_DEV_CY82C693 is not set +# CONFIG_BLK_DEV_CS5520 is not set +# CONFIG_BLK_DEV_CS5530 is not set +# CONFIG_BLK_DEV_HPT34X is not set +# CONFIG_BLK_DEV_HPT366 is not set +# CONFIG_BLK_DEV_SC1200 is not set +CONFIG_BLK_DEV_PIIX=y +# CONFIG_BLK_DEV_IT821X is not set +# CONFIG_BLK_DEV_NS87415 is not set +# CONFIG_BLK_DEV_PDC202XX_OLD is not set +# CONFIG_BLK_DEV_PDC202XX_NEW is not set +# CONFIG_BLK_DEV_SVWKS is not set +# CONFIG_BLK_DEV_SIIMAGE is not set +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +# CONFIG_BLK_DEV_VIA82CXXX is not set +# CONFIG_IDE_ARM is not set +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_IVB is not set +CONFIG_IDEDMA_AUTO=y +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_ST=y +CONFIG_CHR_DEV_OSST=y +CONFIG_BLK_DEV_SR=y +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_CHR_DEV_SG=y +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y + +# +# SCSI Transport Attributes +# +CONFIG_SCSI_SPI_ATTRS=y +CONFIG_SCSI_FC_ATTRS=y +# CONFIG_SCSI_ISCSI_ATTRS is not set +CONFIG_SCSI_SAS_ATTRS=y + +# +# SCSI low-level drivers +# +# CONFIG_ISCSI_TCP is not set +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_3W_9XXX is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set +# CONFIG_MEGARAID_SAS is not set +# CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set +CONFIG_SCSI_SYM53C8XX_2=y +CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 +CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 +CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 +# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set +# CONFIG_SCSI_IPR is not set +CONFIG_SCSI_QLOGIC_FC=y +# CONFIG_SCSI_QLOGIC_FC_FIRMWARE is not set +CONFIG_SCSI_QLOGIC_1280=y +# CONFIG_SCSI_QLA_FC is not set +# CONFIG_SCSI_LPFC is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_DEBUG is not set + +# +# Multi-device support (RAID and LVM) +# +CONFIG_MD=y +# CONFIG_BLK_DEV_MD is not set +# CONFIG_BLK_DEV_DM is not set + +# +# Fusion MPT device support +# +CONFIG_FUSION=y +CONFIG_FUSION_SPI=y +# CONFIG_FUSION_FC is not set +CONFIG_FUSION_SAS=y +CONFIG_FUSION_MAX_SGE=128 +# CONFIG_FUSION_CTL is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y +CONFIG_DUMMY=y +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +CONFIG_TUN=y + +# +# ARCnet devices +# +CONFIG_ARCNET=y +# CONFIG_ARCNET_1201 is not set +# CONFIG_ARCNET_1051 is not set +# CONFIG_ARCNET_RAW is not set +# CONFIG_ARCNET_CAP is not set +# CONFIG_ARCNET_COM90xx is not set +# CONFIG_ARCNET_COM90xxIO is not set +# CONFIG_ARCNET_RIM_I is not set +# CONFIG_ARCNET_COM20020 is not set + +# +# PHY device support +# +# CONFIG_PHYLIB is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +CONFIG_NET_TULIP=y +# CONFIG_DE2104X is not set +CONFIG_TULIP=y +CONFIG_TULIP_MWI=y +CONFIG_TULIP_MMIO=y +CONFIG_TULIP_NAPI=y +CONFIG_TULIP_NAPI_HW_MITIGATION=y +# CONFIG_DE4X5 is not set +# CONFIG_WINBOND_840 is not set +# CONFIG_DM9102 is not set +# CONFIG_ULI526X is not set +# CONFIG_HP100 is not set +CONFIG_NET_PCI=y +# CONFIG_PCNET32 is not set +# CONFIG_AMD8111_ETH is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_B44 is not set +# CONFIG_FORCEDETH is not set +# CONFIG_DGRS is not set +CONFIG_EEPRO100=y +CONFIG_E100=y +# CONFIG_FEALNX is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_VIA_RHINE is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +CONFIG_E1000=y +# CONFIG_E1000_NAPI is not set +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SKGE is not set +# CONFIG_SKY2 is not set +# CONFIG_SK98LIN is not set +# CONFIG_VIA_VELOCITY is not set +CONFIG_TIGON3=y +# CONFIG_BNX2 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_CHELSIO_T1 is not set +# CONFIG_IXGB is not set +# CONFIG_S2IO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NET_FC is not set +# CONFIG_SHAPER is not set +CONFIG_NETCONSOLE=y +CONFIG_NETPOLL=y +# CONFIG_NETPOLL_RX is not set +# CONFIG_NETPOLL_TRAP is not set +CONFIG_NET_POLL_CONTROLLER=y + +# +# ISDN subsystem +# +CONFIG_ISDN=m + +# +# Old ISDN4Linux +# +# CONFIG_ISDN_I4L is not set + +# +# CAPI subsystem +# +# CONFIG_ISDN_CAPI is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +CONFIG_INPUT_JOYDEV=y +# CONFIG_INPUT_TSDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +# CONFIG_SERIO_SERPORT is not set +# CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +CONFIG_GAMEPORT=y +# CONFIG_GAMEPORT_NS558 is not set +# CONFIG_GAMEPORT_L4 is not set +# CONFIG_GAMEPORT_EMU10K1 is not set +# CONFIG_GAMEPORT_FM801 is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +CONFIG_SERIAL_NONSTANDARD=y +# CONFIG_COMPUTONE is not set +# CONFIG_ROCKETPORT is not set +# CONFIG_CYCLADES is not set +# CONFIG_DIGIEPCA is not set +# CONFIG_MOXA_INTELLIO is not set +# CONFIG_MOXA_SMARTIO is not set +# CONFIG_ISI is not set +# CONFIG_SYNCLINKMP is not set +# CONFIG_SYNCLINK_GT is not set +# CONFIG_N_HDLC is not set +# CONFIG_SPECIALIX is not set +# CONFIG_SX is not set +# CONFIG_STALDRV is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_ACPI=y +CONFIG_SERIAL_8250_NR_UARTS=6 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +# CONFIG_SERIAL_8250_DETECT_IRQ is not set +# CONFIG_SERIAL_8250_RSA is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_HW_RANDOM is not set +CONFIG_EFI_RTC=y +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +CONFIG_AGP=y +CONFIG_AGP_I460=y +CONFIG_DRM=y +# CONFIG_DRM_TDFX is not set +# CONFIG_DRM_R128 is not set +# CONFIG_DRM_RADEON is not set +# CONFIG_DRM_MGA is not set +# CONFIG_DRM_SIS is not set +# CONFIG_DRM_VIA is not set +# CONFIG_DRM_SAVAGE is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_HPET is not set +# CONFIG_HANGCHECK_TIMER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=y + +# +# I2C Algorithms +# +CONFIG_I2C_ALGOBIT=y +CONFIG_I2C_ALGOPCF=y +# CONFIG_I2C_ALGOPCA is not set + +# +# I2C Hardware Bus support +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_I810 is not set +# CONFIG_I2C_PIIX4 is not set +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_PROSAVAGE is not set +# CONFIG_I2C_SAVAGE4 is not set +# CONFIG_SCx200_ACB is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set +# CONFIG_I2C_VOODOO3 is not set +# CONFIG_I2C_PCA_ISA is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_RTC8564 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_RTC_X1205_I2C is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support +# +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ASB100 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_FSCHER is not set +# CONFIG_SENSORS_FSCPOS is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_SIS5595 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_VIA686A is not set +# CONFIG_SENSORS_VT8231 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Misc devices +# + +# +# Multimedia Capabilities Port drivers +# + +# +# Multimedia devices +# +CONFIG_VIDEO_DEV=y + +# +# Video For Linux +# + +# +# Video Adapters +# +# CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_BT848 is not set +# CONFIG_VIDEO_CPIA is not set +# CONFIG_VIDEO_SAA5246A is not set +# CONFIG_VIDEO_SAA5249 is not set +# CONFIG_TUNER_3036 is not set +# CONFIG_VIDEO_STRADIS is not set +# CONFIG_VIDEO_ZORAN is not set +# CONFIG_VIDEO_SAA7134 is not set +# CONFIG_VIDEO_MXB is not set +# CONFIG_VIDEO_DPC is not set +# CONFIG_VIDEO_HEXIUM_ORION is not set +# CONFIG_VIDEO_HEXIUM_GEMINI is not set +# CONFIG_VIDEO_CX88 is not set +# CONFIG_VIDEO_EM28XX is not set +# CONFIG_VIDEO_OVCAMCHIP is not set +# CONFIG_VIDEO_AUDIO_DECODER is not set +# CONFIG_VIDEO_DECODER is not set + +# +# Radio Adapters +# +# CONFIG_RADIO_GEMTEK_PCI is not set +# CONFIG_RADIO_MAXIRADIO is not set +# CONFIG_RADIO_MAESTRO is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +CONFIG_FB=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_MACMODES is not set +CONFIG_FB_MODE_HELPERS=y +# CONFIG_FB_TILEBLITTING is not set +# CONFIG_FB_CIRRUS is not set +# CONFIG_FB_PM2 is not set +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_ASILIANT is not set +# CONFIG_FB_IMSTT is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_NVIDIA is not set +# CONFIG_FB_RIVA is not set +# CONFIG_FB_MATROX is not set +# CONFIG_FB_RADEON_OLD is not set +CONFIG_FB_RADEON=y +CONFIG_FB_RADEON_I2C=y +CONFIG_FB_RADEON_DEBUG=y +# CONFIG_FB_ATY128 is not set +# CONFIG_FB_ATY is not set +# CONFIG_FB_SAVAGE is not set +# CONFIG_FB_SIS is not set +# CONFIG_FB_NEOMAGIC is not set +# CONFIG_FB_KYRO is not set +# CONFIG_FB_3DFX is not set +# CONFIG_FB_VOODOO1 is not set +# CONFIG_FB_TRIDENT is not set +# CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +CONFIG_VGA_CONSOLE=y +CONFIG_DUMMY_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE is not set + +# +# Logo configuration +# +CONFIG_LOGO=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +CONFIG_LOGO_LINUX_CLUT224=y +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Sound +# +CONFIG_SOUND=y + +# +# Advanced Linux Sound Architecture +# +CONFIG_SND=y +CONFIG_SND_TIMER=y +CONFIG_SND_PCM=y +CONFIG_SND_HWDEP=y +CONFIG_SND_RAWMIDI=y +CONFIG_SND_SEQUENCER=y +CONFIG_SND_SEQ_DUMMY=y +CONFIG_SND_OSSEMUL=y +CONFIG_SND_MIXER_OSS=y +CONFIG_SND_PCM_OSS=y +CONFIG_SND_SEQUENCER_OSS=y +# CONFIG_SND_DYNAMIC_MINORS is not set +CONFIG_SND_SUPPORT_OLD_API=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set + +# +# Generic devices +# +CONFIG_SND_MPU401_UART=y +CONFIG_SND_OPL3_LIB=y +CONFIG_SND_AC97_CODEC=y +CONFIG_SND_AC97_BUS=y +CONFIG_SND_DUMMY=y +CONFIG_SND_VIRMIDI=y +CONFIG_SND_MTPAV=y +CONFIG_SND_SERIAL_U16550=y +CONFIG_SND_MPU401=y + +# +# PCI devices +# +# CONFIG_SND_AD1889 is not set +# CONFIG_SND_ALI5451 is not set +CONFIG_SND_ATIIXP=y +# CONFIG_SND_ATIIXP_MODEM is not set +# CONFIG_SND_AU8810 is not set +# CONFIG_SND_AU8820 is not set +# CONFIG_SND_AU8830 is not set +# CONFIG_SND_AZT3328 is not set +# CONFIG_SND_BT87X is not set +# CONFIG_SND_CA0106 is not set +# CONFIG_SND_CMIPCI is not set +# CONFIG_SND_CS4281 is not set +# CONFIG_SND_CS46XX is not set +# CONFIG_SND_EMU10K1 is not set +# CONFIG_SND_EMU10K1X is not set +# CONFIG_SND_ENS1370 is not set +# CONFIG_SND_ENS1371 is not set +# CONFIG_SND_ES1938 is not set +# CONFIG_SND_ES1968 is not set +CONFIG_SND_FM801=y +CONFIG_SND_FM801_TEA575X=y +# CONFIG_SND_HDA_INTEL is not set +# CONFIG_SND_HDSP is not set +# CONFIG_SND_HDSPM is not set +# CONFIG_SND_ICE1712 is not set +# CONFIG_SND_ICE1724 is not set +# CONFIG_SND_INTEL8X0 is not set +# CONFIG_SND_INTEL8X0M is not set +# CONFIG_SND_KORG1212 is not set +# CONFIG_SND_MAESTRO3 is not set +# CONFIG_SND_MIXART is not set +# CONFIG_SND_NM256 is not set +# CONFIG_SND_PCXHR is not set +# CONFIG_SND_RME32 is not set +# CONFIG_SND_RME96 is not set +# CONFIG_SND_RME9652 is not set +# CONFIG_SND_SONICVIBES is not set +# CONFIG_SND_TRIDENT is not set +# CONFIG_SND_VIA82XX is not set +# CONFIG_SND_VIA82XX_MODEM is not set +# CONFIG_SND_VX222 is not set +# CONFIG_SND_YMFPCI is not set + +# +# USB devices +# +# CONFIG_SND_USB_AUDIO is not set + +# +# Open Sound System +# +CONFIG_SOUND_PRIME=y +# CONFIG_OBSOLETE_OSS_DRIVER is not set +# CONFIG_SOUND_FUSION is not set +# CONFIG_SOUND_ICH is not set +# CONFIG_SOUND_TRIDENT is not set +# CONFIG_SOUND_MSNDCLAS is not set +# CONFIG_SOUND_MSNDPIN is not set +# CONFIG_SOUND_TVMIXER is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +CONFIG_USB_BANDWIDTH=y +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_SUSPEND is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +CONFIG_USB_EHCI_HCD=y +# CONFIG_USB_EHCI_SPLIT_ISO is not set +# CONFIG_USB_EHCI_ROOT_HUB_TT is not set +# CONFIG_USB_ISP116X_HCD is not set +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_OHCI_BIG_ENDIAN is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +CONFIG_USB_UHCI_HCD=y +# CONFIG_USB_SL811_HCD is not set + +# +# USB Device Class drivers +# +# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# may also be needed; see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Input Devices +# +CONFIG_USB_HID=y +CONFIG_USB_HIDINPUT=y +# CONFIG_USB_HIDINPUT_POWERBOOK is not set +# CONFIG_HID_FF is not set +CONFIG_USB_HIDDEV=y +# CONFIG_USB_AIPTEK is not set +# CONFIG_USB_WACOM is not set +# CONFIG_USB_ACECAD is not set +# CONFIG_USB_KBTAB is not set +# CONFIG_USB_POWERMATE is not set +# CONFIG_USB_MTOUCH is not set +# CONFIG_USB_ITMTOUCH is not set +# CONFIG_USB_EGALAX is not set +# CONFIG_USB_YEALINK is not set +# CONFIG_USB_XPAD is not set +# CONFIG_USB_ATI_REMOTE is not set +# CONFIG_USB_ATI_REMOTE2 is not set +# CONFIG_USB_KEYSPAN_REMOTE is not set +# CONFIG_USB_APPLETOUCH is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB Multimedia devices +# +# CONFIG_USB_DABUSB is not set +# CONFIG_USB_VICAM is not set +# CONFIG_USB_DSBR is not set +# CONFIG_USB_ET61X251 is not set +# CONFIG_USB_IBMCAM is not set +# CONFIG_USB_KONICAWC is not set +# CONFIG_USB_OV511 is not set +# CONFIG_USB_SE401 is not set +# CONFIG_USB_SN9C102 is not set +# CONFIG_USB_STV680 is not set +# CONFIG_USB_PWC is not set + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set +CONFIG_USB_MON=y + +# +# USB port drivers +# + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGETKIT is not set +# CONFIG_USB_PHIDGETSERVO is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TEST is not set + +# +# USB DSL modem support +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# InfiniBand support +# +# CONFIG_INFINIBAND is not set + +# +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +CONFIG_REISERFS_FS=y +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +CONFIG_REISERFS_FS_XATTR=y +CONFIG_REISERFS_FS_POSIX_ACL=y +CONFIG_REISERFS_FS_SECURITY=y +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_XFS_FS=y +CONFIG_XFS_EXPORT=y +# CONFIG_XFS_QUOTA is not set +# CONFIG_XFS_SECURITY is not set +# CONFIG_XFS_POSIX_ACL is not set +# CONFIG_XFS_RT is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +CONFIG_AUTOFS_FS=y +CONFIG_AUTOFS4_FS=y +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +# CONFIG_ZISOFS is not set +CONFIG_UDF_FS=y +CONFIG_UDF_NLS=y + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_RELAYFS_FS is not set +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +CONFIG_NFS_V4=y +CONFIG_NFS_DIRECTIO=y +CONFIG_NFSD=y +CONFIG_NFSD_V3=y +# CONFIG_NFSD_V3_ACL is not set +CONFIG_NFSD_V4=y +CONFIG_NFSD_TCP=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +CONFIG_RPCSEC_GSS_KRB5=y +# CONFIG_RPCSEC_GSS_SPKM3 is not set +CONFIG_SMB_FS=y +CONFIG_SMB_NLS_DEFAULT=y +CONFIG_SMB_NLS_REMOTE="cp437" +CONFIG_CIFS=y +# CONFIG_CIFS_STATS is not set +# CONFIG_CIFS_XATTR is not set +# CONFIG_CIFS_EXPERIMENTAL is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +CONFIG_SGI_PARTITION=y +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +CONFIG_EFI_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_737=y +CONFIG_NLS_CODEPAGE_775=y +CONFIG_NLS_CODEPAGE_850=y +CONFIG_NLS_CODEPAGE_852=y +CONFIG_NLS_CODEPAGE_855=y +CONFIG_NLS_CODEPAGE_857=y +CONFIG_NLS_CODEPAGE_860=y +CONFIG_NLS_CODEPAGE_861=y +CONFIG_NLS_CODEPAGE_862=y +CONFIG_NLS_CODEPAGE_863=y +CONFIG_NLS_CODEPAGE_864=y +CONFIG_NLS_CODEPAGE_865=y +CONFIG_NLS_CODEPAGE_866=y +CONFIG_NLS_CODEPAGE_869=y +CONFIG_NLS_CODEPAGE_936=y +CONFIG_NLS_CODEPAGE_950=y +CONFIG_NLS_CODEPAGE_932=y +CONFIG_NLS_CODEPAGE_949=y +CONFIG_NLS_CODEPAGE_874=y +CONFIG_NLS_ISO8859_8=y +# CONFIG_NLS_CODEPAGE_1250 is not set +CONFIG_NLS_CODEPAGE_1251=y +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_ISO8859_2=y +CONFIG_NLS_ISO8859_3=y +CONFIG_NLS_ISO8859_4=y +CONFIG_NLS_ISO8859_5=y +CONFIG_NLS_ISO8859_6=y +CONFIG_NLS_ISO8859_7=y +CONFIG_NLS_ISO8859_9=y +CONFIG_NLS_ISO8859_13=y +CONFIG_NLS_ISO8859_14=y +CONFIG_NLS_ISO8859_15=y +CONFIG_NLS_KOI8_R=y +CONFIG_NLS_KOI8_U=y +CONFIG_NLS_UTF8=y + +# +# Library routines +# +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_PENDING_IRQ=y + +# +# Instrumentation Support +# +# CONFIG_PROFILING is not set +# CONFIG_KPROBES is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=20 +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_SLAB is not set +CONFIG_DEBUG_MUTEXES=y +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_DEBUG_VM is not set +CONFIG_FORCED_INLINING=y +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_IA64_GRANULE_16MB=y +# CONFIG_IA64_GRANULE_64MB is not set +CONFIG_IA64_PRINT_HAZARDS=y +# CONFIG_DISABLE_VHPT is not set +# CONFIG_IA64_DEBUG_CMPXCHG is not set +# CONFIG_IA64_DEBUG_IRQ is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD5=y +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_TGR192 is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Hardware crypto devices +# diff -r 7e3cbc409676 -r d75a6cc5e68a extras/mini-os/include/console.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extras/mini-os/include/console.h Tue Mar 28 08:54:58 2006 -0700 @@ -0,0 +1,49 @@ +/* + **************************************************************************** + * (C) 2006 - Grzegorz Milos - Cambridge University + **************************************************************************** + * + * File: console.h + * Author: Grzegorz Milos + * Changes: + * + * Date: Mar 2006 + * + * Environment: Xen Minimal OS + * Description: Console interface. + * + * Handles console I/O. Defines printk. + * + **************************************************************************** + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ +#ifndef _LIB_CONSOLE_H_ +#define _LIB_CONSOLE_H_ + +#include<traps.h> + +void printk(const char *fmt, ...); +void xprintk(const char *fmt, ...); + +void xencons_rx(char *buf, unsigned len, struct pt_regs *regs); +void xencons_tx(void); + +void init_console(void); + +#endif /* _LIB_CONSOLE_H_ */ diff -r 7e3cbc409676 -r d75a6cc5e68a extras/mini-os/xenbus/xenbus.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extras/mini-os/xenbus/xenbus.c Tue Mar 28 08:54:58 2006 -0700 @@ -0,0 +1,387 @@ +/* + **************************************************************************** + * (C) 2006 - Cambridge University + **************************************************************************** + * + * File: mm.c + * Author: Steven Smith (sos22@xxxxxxxxx) + * Changes: Grzegorz Milos (gm281@xxxxxxxxx) + * + * Date: Mar 2006, chages Aug 2005 + * + * Environment: Xen Minimal OS + * Description: Minimal implementation of xenbus + * + **************************************************************************** + **/ +#include <os.h> +#include <mm.h> +#include <traps.h> +#include <lib.h> +#include <xenbus.h> +#include <events.h> +#include <errno.h> +#include <sched.h> +#include <wait.h> +#include <xen/io/xs_wire.h> +#include <spinlock.h> +#include <xmalloc.h> + +#define BUG_ON(x) do { \ + if (x) {printk("BUG at %s:%d\n", __FILE__, __LINE__); BUG(); } \ +} while (0) + +#define min(x,y) ({ \ + typeof(x) tmpx = (x); \ + typeof(y) tmpy = (y); \ + tmpx < tmpy ? tmpx : tmpy; \ + }) + +#ifdef XENBUS_DEBUG +#define DEBUG(_f, _a...) \ + printk("MINI_OS(file=xenbus.c, line=%d) " _f , __LINE__, ## _a) +#else +#define DEBUG(_f, _a...) ((void)0) +#endif + + +static struct xenstore_domain_interface *xenstore_buf; +static DECLARE_WAIT_QUEUE_HEAD(xb_waitq); +struct xenbus_req_info +{ + int in_use:1; + struct wait_queue_head waitq; + void *reply; +}; + +#define NR_REQS 32 +static struct xenbus_req_info req_info[NR_REQS]; + +static void memcpy_from_ring(const void *Ring, + void *Dest, + int off, + int len) +{ + int c1, c2; + const char *ring = Ring; + char *dest = Dest; + c1 = min(len, XENSTORE_RING_SIZE - off); + c2 = len - c1; + memcpy(dest, ring + off, c1); + memcpy(dest + c1, ring, c2); +} + +static void xenbus_thread_func(void *ign) +{ + struct xsd_sockmsg msg; + unsigned prod; + + for (;;) + { + wait_event(xb_waitq, prod != xenstore_buf->rsp_prod); + while (1) + { + prod = xenstore_buf->rsp_prod; + DEBUG("Rsp_cons %d, rsp_prod %d.\n", xenstore_buf->rsp_cons, + xenstore_buf->rsp_prod); + if (xenstore_buf->rsp_prod - xenstore_buf->rsp_cons < sizeof(msg)) + break; + rmb(); + memcpy_from_ring(xenstore_buf->rsp, + &msg, + MASK_XENSTORE_IDX(xenstore_buf->rsp_cons), + sizeof(msg)); + DEBUG("Msg len %d, %d avail, id %d.\n", + msg.len + sizeof(msg), + xenstore_buf->rsp_prod - xenstore_buf->rsp_cons, + msg.req_id); + if (xenstore_buf->rsp_prod - xenstore_buf->rsp_cons < + sizeof(msg) + msg.len) + break; + + DEBUG("Message is good.\n"); + req_info[msg.req_id].reply = malloc(sizeof(msg) + msg.len); + memcpy_from_ring(xenstore_buf->rsp, + req_info[msg.req_id].reply, + MASK_XENSTORE_IDX(xenstore_buf->rsp_cons), + msg.len + sizeof(msg)); + wake_up(&req_info[msg.req_id].waitq); + xenstore_buf->rsp_cons += msg.len + sizeof(msg); + } + } +} + +static void xenbus_evtchn_handler(int port, struct pt_regs *regs) +{ + wake_up(&xb_waitq); +} + +static int nr_live_reqs; +static spinlock_t req_lock = SPIN_LOCK_UNLOCKED; +static DECLARE_WAIT_QUEUE_HEAD(req_wq); + +/* Release a xenbus identifier */ +static void release_xenbus_id(int id) +{ + BUG_ON(!req_info[id].in_use); + spin_lock(&req_lock); + nr_live_reqs--; + if (nr_live_reqs == NR_REQS - 1) + wake_up(&req_wq); + spin_unlock(&req_lock); +} + +/* Allocate an identifier for a xenbus request. Blocks if none are + available. */ +static int allocate_xenbus_id(void) +{ + static int probe; + int o_probe; + + while (1) + { + spin_lock(&req_lock); + if (nr_live_reqs < NR_REQS) + break; + spin_unlock(&req_lock); + wait_event(req_wq, (nr_live_reqs < NR_REQS)); + } + + o_probe = probe; + for (;;) + { + if (!req_info[o_probe].in_use) + break; + o_probe = (o_probe + 1) % NR_REQS; + BUG_ON(o_probe == probe); + } + nr_live_reqs++; + req_info[o_probe].in_use = 1; + probe = o_probe + 1; + spin_unlock(&req_lock); + init_waitqueue_head(&req_info[o_probe].waitq); + return o_probe; +} + +/* Initialise xenbus. */ +void init_xenbus(void) +{ + int err; + DEBUG("init_xenbus called.\n"); + xenstore_buf = mfn_to_virt(start_info.store_mfn); + create_thread("xenstore", xenbus_thread_func, NULL); + DEBUG("buf at %p.\n", xenstore_buf); + err = bind_evtchn(start_info.store_evtchn, + xenbus_evtchn_handler); + DEBUG("xenbus on irq %d\n", err); +} + +struct write_req { + const void *data; + unsigned len; +}; + +/* Send data to xenbus. This can block. All of the requests are seen + by xenbus as if sent atomically. The header is added + automatically, using type %type, req_id %req_id, and trans_id + %trans_id. */ +static void xb_write(int type, int req_id, int trans_id, + const struct write_req *req, int nr_reqs) +{ + XENSTORE_RING_IDX prod; + int r; + int len = 0; + const struct write_req *cur_req; + int req_off; + int total_off; + int this_chunk; + struct xsd_sockmsg m = {.type = type, .req_id = req_id, + .tx_id = trans_id }; + struct write_req header_req = { &m, sizeof(m) }; + + for (r = 0; r < nr_reqs; r++) + len += req[r].len; + m.len = len; + len += sizeof(m); + + cur_req = &header_req; + + BUG_ON(len > XENSTORE_RING_SIZE); + /* Wait for the ring to drain to the point where we can send the + message. */ + prod = xenstore_buf->req_prod; + if (prod + len - xenstore_buf->req_cons > XENSTORE_RING_SIZE) + { + /* Wait for there to be space on the ring */ + DEBUG("prod %d, len %d, cons %d, size %d; waiting.\n", + prod, len, xenstore_buf->req_cons, XENSTORE_RING_SIZE); + wait_event(xb_waitq, + xenstore_buf->req_prod + len - xenstore_buf->req_cons <= + XENSTORE_RING_SIZE); + DEBUG("Back from wait.\n"); + prod = xenstore_buf->req_prod; + } + + /* We're now guaranteed to be able to send the message without + overflowing the ring. Do so. */ + total_off = 0; + req_off = 0; + while (total_off < len) + { + this_chunk = min(cur_req->len - req_off, + XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod)); + memcpy((char *)xenstore_buf->req + MASK_XENSTORE_IDX(prod), + (char *)cur_req->data + req_off, this_chunk); + prod += this_chunk; + req_off += this_chunk; + total_off += this_chunk; + if (req_off == cur_req->len) + { + req_off = 0; + if (cur_req == &header_req) + cur_req = req; + else + cur_req++; + } + } + + DEBUG("Complete main loop of xb_write.\n"); + BUG_ON(req_off != 0); + BUG_ON(total_off != len); + BUG_ON(prod > xenstore_buf->req_cons + XENSTORE_RING_SIZE); + + /* Remote must see entire message before updating indexes */ + wmb(); + + xenstore_buf->req_prod += len; + + /* Send evtchn to notify remote */ + notify_remote_via_evtchn(start_info.store_evtchn); +} + +/* Send a mesasge to xenbus, in the same fashion as xb_write, and + block waiting for a reply. The reply is malloced and should be + freed by the caller. */ +static void *xenbus_msg_reply(int type, + int trans, + struct write_req *io, + int nr_reqs) +{ + int id; + DEFINE_WAIT(w); + void *rep; + struct xsd_sockmsg *repmsg; + + id = allocate_xenbus_id(); + add_waiter(w, req_info[id].waitq); + + xb_write(type, id, trans, io, nr_reqs); + + schedule(); + wake(current); + + rep = req_info[id].reply; + repmsg = rep; + BUG_ON(repmsg->req_id != id); + release_xenbus_id(id); + + return rep; +} + +/* Send a debug message to xenbus. Can block. */ +static void xenbus_debug_msg(const char *msg) +{ + int len = strlen(msg); + struct write_req req[] = { + { "print", sizeof("print") }, + { msg, len }, + { "", 1 }}; + void *reply; + struct xsd_sockmsg *repmsg; + + reply = xenbus_msg_reply(XS_DEBUG, 0, req, 3); + repmsg = reply; + DEBUG("Got a reply, type %d, id %d, len %d.\n", + repmsg->type, repmsg->req_id, repmsg->len); +} + +/* List the contents of a directory. Returns a malloc()ed array of + pointers to malloc()ed strings. The array is NULL terminated. May + block. */ +static char **xenbus_ls(const char *pre) +{ + void *reply; + struct xsd_sockmsg *repmsg; + struct write_req req[] = { { pre, strlen(pre)+1 } }; + int nr_elems, x, i; + char **res; + + repmsg = xenbus_msg_reply(XS_DIRECTORY, 0, req, 1); + reply = repmsg + 1; + for (x = nr_elems = 0; x < repmsg->len; x++) + nr_elems += (((char *)reply)[x] == 0); + res = malloc(sizeof(res[0]) * (nr_elems + 1)); + for (x = i = 0; i < nr_elems; i++) { + int l = strlen((char *)reply + x); + res[i] = malloc(l + 1); + memcpy(res[i], (char *)reply + x, l + 1); + x += l + 1; + } + res[i] = NULL; + free(repmsg); + return res; +} + +static char *xenbus_read(const char *path) +{ + struct write_req req[] = { {path, strlen(path) + 1}}; + struct xsd_sockmsg *rep; + char *res; + rep = xenbus_msg_reply(XS_READ, 0, req, 1); + res = malloc(rep->len + 1); + memcpy(res, rep + 1, rep->len); + res[rep->len] = 0; + free(rep); + return res; +} + +static void do_ls_test(const char *pre) +{ + char **dirs; + int x; + + DEBUG("ls %s...\n", pre); + dirs = xenbus_ls(pre); + for (x = 0; dirs[x]; x++) + { + DEBUG("ls %s[%d] -> %s\n", pre, x, dirs[x]); + free(dirs[x]); + } + free(dirs); +} + +static void do_read_test(const char *path) +{ + char *res; + DEBUG("Read %s...\n", path); + res = xenbus_read(path); + DEBUG("Read %s -> %s.\n", path, res); + free(res); +} + +/* Simple testing thing */ +void test_xenbus(void) +{ + DEBUG("Doing xenbus test.\n"); + xenbus_debug_msg("Testing xenbus...\n"); + + DEBUG("Doing ls test.\n"); + do_ls_test("device"); + do_ls_test("device/vif"); + do_ls_test("device/vif/0"); + + DEBUG("Doing read test.\n"); + do_read_test("device/vif/0/mac"); + do_read_test("device/vif/0/backend"); + printk("Xenbus initialised.\n"); +} diff -r 7e3cbc409676 -r d75a6cc5e68a linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/msr.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/msr.h Tue Mar 28 08:54:58 2006 -0700 @@ -0,0 +1,399 @@ +#ifndef X86_64_MSR_H +#define X86_64_MSR_H 1 + +#ifndef __ASSEMBLY__ +/* + * Access to machine-specific registers (available on 586 and better only) + * Note: the rd* operations modify the parameters directly (without using + * pointer indirection), this allows gcc to optimize better + */ + +#define rdmsr(msr,val1,val2) \ + __asm__ __volatile__("rdmsr" \ + : "=a" (val1), "=d" (val2) \ + : "c" (msr)) + + +#define rdmsrl(msr,val) do { unsigned long a__,b__; \ + __asm__ __volatile__("rdmsr" \ + : "=a" (a__), "=d" (b__) \ + : "c" (msr)); \ + val = a__ | (b__<<32); \ +} while(0) + +#define wrmsr(msr,val1,val2) \ + __asm__ __volatile__("wrmsr" \ + : /* no outputs */ \ + : "c" (msr), "a" (val1), "d" (val2)) + +#define wrmsrl(msr,val) wrmsr(msr,(__u32)((__u64)(val)),((__u64)(val))>>32) + +/* wrmsr with exception handling */ +#define wrmsr_safe(msr,a,b) ({ int ret__; \ + asm volatile("2: wrmsr ; xorl %0,%0\n" \ + "1:\n\t" \ + ".section .fixup,\"ax\"\n\t" \ + "3: movl %4,%0 ; jmp 1b\n\t" \ + ".previous\n\t" \ + ".section __ex_table,\"a\"\n" \ + " .align 8\n\t" \ + " .quad 2b,3b\n\t" \ + ".previous" \ + : "=a" (ret__) \ + : "c" (msr), "0" (a), "d" (b), "i" (-EFAULT)); \ + ret__; }) + +#define checking_wrmsrl(msr,val) wrmsr_safe(msr,(u32)(val),(u32)((val)>>32)) + +#define rdmsr_safe(msr,a,b) \ + ({ int ret__; \ + asm volatile ("1: rdmsr\n" \ + "2:\n" \ + ".section .fixup,\"ax\"\n" \ + "3: movl %4,%0\n" \ + " jmp 2b\n" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n" \ + " .align 8\n" \ + " .quad 1b,3b\n" \ + ".previous":"=&bDS" (ret__), "=a"(*(a)), "=d"(*(b))\ + :"c"(msr), "i"(-EIO), "0"(0)); \ + ret__; }) + +#define rdtsc(low,high) \ + __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high)) + +#define rdtscl(low) \ + __asm__ __volatile__ ("rdtsc" : "=a" (low) : : "edx") + +#define rdtscll(val) do { \ + unsigned int __a,__d; \ + asm volatile("rdtsc" : "=a" (__a), "=d" (__d)); \ + (val) = ((unsigned long)__a) | (((unsigned long)__d)<<32); \ +} while(0) + +#define write_tsc(val1,val2) wrmsr(0x10, val1, val2) + +#define rdpmc(counter,low,high) \ + __asm__ __volatile__("rdpmc" \ + : "=a" (low), "=d" (high) \ + : "c" (counter)) + +static inline void cpuid(int op, unsigned int *eax, unsigned int *ebx, + unsigned int *ecx, unsigned int *edx) +{ + __asm__(XEN_CPUID + : "=a" (*eax), + "=b" (*ebx), + "=c" (*ecx), + "=d" (*edx) + : "0" (op)); +} + +/* Some CPUID calls want 'count' to be placed in ecx */ +static inline void cpuid_count(int op, int count, int *eax, int *ebx, int *ecx, + int *edx) +{ + __asm__(XEN_CPUID + : "=a" (*eax), + "=b" (*ebx), + "=c" (*ecx), + "=d" (*edx) + : "0" (op), "c" (count)); +} + +/* + * CPUID functions returning a single datum + */ +static inline unsigned int cpuid_eax(unsigned int op) +{ + unsigned int eax; + + __asm__(XEN_CPUID + : "=a" (eax) + : "0" (op) + : "bx", "cx", "dx"); + return eax; +} +static inline unsigned int cpuid_ebx(unsigned int op) +{ + unsigned int eax, ebx; + + __asm__(XEN_CPUID + : "=a" (eax), "=b" (ebx) + : "0" (op) + : "cx", "dx" ); + return ebx; +} +static inline unsigned int cpuid_ecx(unsigned int op) +{ + unsigned int eax, ecx; + + __asm__(XEN_CPUID + : "=a" (eax), "=c" (ecx) + : "0" (op) + : "bx", "dx" ); + return ecx; +} +static inline unsigned int cpuid_edx(unsigned int op) +{ + unsigned int eax, edx; + + __asm__(XEN_CPUID + : "=a" (eax), "=d" (edx) + : "0" (op) + : "bx", "cx"); + return edx; +} + +#define MSR_IA32_UCODE_WRITE 0x79 +#define MSR_IA32_UCODE_REV 0x8b + + +#endif + +/* AMD/K8 specific MSRs */ +#define MSR_EFER 0xc0000080 /* extended feature register */ +#define MSR_STAR 0xc0000081 /* legacy mode SYSCALL target */ +#define MSR_LSTAR 0xc0000082 /* long mode SYSCALL target */ +#define MSR_CSTAR 0xc0000083 /* compatibility mode SYSCALL target */ +#define MSR_SYSCALL_MASK 0xc0000084 /* EFLAGS mask for syscall */ +#define MSR_FS_BASE 0xc0000100 /* 64bit GS base */ +#define MSR_GS_BASE 0xc0000101 /* 64bit FS base */ +#define MSR_KERNEL_GS_BASE 0xc0000102 /* SwapGS GS shadow (or USER_GS from kernel) */ +/* EFER bits: */ +#define _EFER_SCE 0 /* SYSCALL/SYSRET */ +#define _EFER_LME 8 /* Long mode enable */ +#define _EFER_LMA 10 /* Long mode active (read-only) */ +#define _EFER_NX 11 /* No execute enable */ + +#define EFER_SCE (1<<_EFER_SCE) +#define EFER_LME (1<<_EFER_LME) +#define EFER_LMA (1<<_EFER_LMA) +#define EFER_NX (1<<_EFER_NX) + +/* Intel MSRs. Some also available on other CPUs */ +#define MSR_IA32_TSC 0x10 +#define MSR_IA32_PLATFORM_ID 0x17 + +#define MSR_IA32_PERFCTR0 0xc1 +#define MSR_IA32_PERFCTR1 0xc2 + +#define MSR_MTRRcap 0x0fe +#define MSR_IA32_BBL_CR_CTL 0x119 + +#define MSR_IA32_SYSENTER_CS 0x174 +#define MSR_IA32_SYSENTER_ESP 0x175 +#define MSR_IA32_SYSENTER_EIP 0x176 + +#define MSR_IA32_MCG_CAP 0x179 +#define MSR_IA32_MCG_STATUS 0x17a +#define MSR_IA32_MCG_CTL 0x17b + +#define MSR_IA32_EVNTSEL0 0x186 +#define MSR_IA32_EVNTSEL1 0x187 + +#define MSR_IA32_DEBUGCTLMSR 0x1d9 +#define MSR_IA32_LASTBRANCHFROMIP 0x1db +#define MSR_IA32_LASTBRANCHTOIP 0x1dc +#define MSR_IA32_LASTINTFROMIP 0x1dd +#define MSR_IA32_LASTINTTOIP 0x1de + +#define MSR_MTRRfix64K_00000 0x250 +#define MSR_MTRRfix16K_80000 0x258 +#define MSR_MTRRfix16K_A0000 0x259 +#define MSR_MTRRfix4K_C0000 0x268 +#define MSR_MTRRfix4K_C8000 0x269 +#define MSR_MTRRfix4K_D0000 0x26a +#define MSR_MTRRfix4K_D8000 0x26b +#define MSR_MTRRfix4K_E0000 0x26c +#define MSR_MTRRfix4K_E8000 0x26d +#define MSR_MTRRfix4K_F0000 0x26e +#define MSR_MTRRfix4K_F8000 0x26f +#define MSR_MTRRdefType 0x2ff + +#define MSR_IA32_MC0_CTL 0x400 +#define MSR_IA32_MC0_STATUS 0x401 +#define MSR_IA32_MC0_ADDR 0x402 +#define MSR_IA32_MC0_MISC 0x403 + +#define MSR_P6_PERFCTR0 0xc1 +#define MSR_P6_PERFCTR1 0xc2 +#define MSR_P6_EVNTSEL0 0x186 +#define MSR_P6_EVNTSEL1 0x187 + +/* K7/K8 MSRs. Not complete. See the architecture manual for a more complete list. */ +#define MSR_K7_EVNTSEL0 0xC0010000 +#define MSR_K7_PERFCTR0 0xC0010004 +#define MSR_K7_EVNTSEL1 0xC0010001 +#define MSR_K7_PERFCTR1 0xC0010005 +#define MSR_K7_EVNTSEL2 0xC0010002 +#define MSR_K7_PERFCTR2 0xC0010006 +#define MSR_K7_EVNTSEL3 0xC0010003 +#define MSR_K7_PERFCTR3 0xC0010007 +#define MSR_K8_TOP_MEM1 0xC001001A +#define MSR_K8_TOP_MEM2 0xC001001D +#define MSR_K8_SYSCFG 0xC0010010 +#define MSR_K8_HWCR 0xC0010015 + +/* K6 MSRs */ +#define MSR_K6_EFER 0xC0000080 +#define MSR_K6_STAR 0xC0000081 +#define MSR_K6_WHCR 0xC0000082 +#define MSR_K6_UWCCR 0xC0000085 +#define MSR_K6_PSOR 0xC0000087 +#define MSR_K6_PFIR 0xC0000088 + +/* Centaur-Hauls/IDT defined MSRs. */ +#define MSR_IDT_FCR1 0x107 +#define MSR_IDT_FCR2 0x108 +#define MSR_IDT_FCR3 0x109 +#define MSR_IDT_FCR4 0x10a + +#define MSR_IDT_MCR0 0x110 +#define MSR_IDT_MCR1 0x111 +#define MSR_IDT_MCR2 0x112 +#define MSR_IDT_MCR3 0x113 +#define MSR_IDT_MCR4 0x114 +#define MSR_IDT_MCR5 0x115 +#define MSR_IDT_MCR6 0x116 +#define MSR_IDT_MCR7 0x117 +#define MSR_IDT_MCR_CTRL 0x120 + +/* VIA Cyrix defined MSRs*/ +#define MSR_VIA_FCR 0x1107 +#define MSR_VIA_LONGHAUL 0x110a +#define MSR_VIA_RNG 0x110b +#define MSR_VIA_BCR2 0x1147 + +/* Intel defined MSRs. */ +#define MSR_IA32_P5_MC_ADDR 0 +#define MSR_IA32_P5_MC_TYPE 1 +#define MSR_IA32_PLATFORM_ID 0x17 +#define MSR_IA32_EBL_CR_POWERON 0x2a + +#define MSR_IA32_APICBASE 0x1b +#define MSR_IA32_APICBASE_BSP (1<<8) +#define MSR_IA32_APICBASE_ENABLE (1<<11) +#define MSR_IA32_APICBASE_BASE (0xfffff<<12) + +/* P4/Xeon+ specific */ +#define MSR_IA32_MCG_EAX 0x180 +#define MSR_IA32_MCG_EBX 0x181 +#define MSR_IA32_MCG_ECX 0x182 +#define MSR_IA32_MCG_EDX 0x183 +#define MSR_IA32_MCG_ESI 0x184 +#define MSR_IA32_MCG_EDI 0x185 +#define MSR_IA32_MCG_EBP 0x186 +#define MSR_IA32_MCG_ESP 0x187 +#define MSR_IA32_MCG_EFLAGS 0x188 +#define MSR_IA32_MCG_EIP 0x189 +#define MSR_IA32_MCG_RESERVED 0x18A + +#define MSR_P6_EVNTSEL0 0x186 +#define MSR_P6_EVNTSEL1 0x187 + +#define MSR_IA32_PERF_STATUS 0x198 +#define MSR_IA32_PERF_CTL 0x199 + +#define MSR_IA32_THERM_CONTROL 0x19a +#define MSR_IA32_THERM_INTERRUPT 0x19b +#define MSR_IA32_THERM_STATUS 0x19c +#define MSR_IA32_MISC_ENABLE 0x1a0 + +#define MSR_IA32_DEBUGCTLMSR 0x1d9 +#define MSR_IA32_LASTBRANCHFROMIP 0x1db +#define MSR_IA32_LASTBRANCHTOIP 0x1dc +#define MSR_IA32_LASTINTFROMIP 0x1dd +#define MSR_IA32_LASTINTTOIP 0x1de + +#define MSR_IA32_MC0_CTL 0x400 +#define MSR_IA32_MC0_STATUS 0x401 +#define MSR_IA32_MC0_ADDR 0x402 +#define MSR_IA32_MC0_MISC 0x403 + +/* Pentium IV performance counter MSRs */ +#define MSR_P4_BPU_PERFCTR0 0x300 +#define MSR_P4_BPU_PERFCTR1 0x301 +#define MSR_P4_BPU_PERFCTR2 0x302 +#define MSR_P4_BPU_PERFCTR3 0x303 +#define MSR_P4_MS_PERFCTR0 0x304 +#define MSR_P4_MS_PERFCTR1 0x305 +#define MSR_P4_MS_PERFCTR2 0x306 +#define MSR_P4_MS_PERFCTR3 0x307 +#define MSR_P4_FLAME_PERFCTR0 0x308 +#define MSR_P4_FLAME_PERFCTR1 0x309 +#define MSR_P4_FLAME_PERFCTR2 0x30a +#define MSR_P4_FLAME_PERFCTR3 0x30b +#define MSR_P4_IQ_PERFCTR0 0x30c +#define MSR_P4_IQ_PERFCTR1 0x30d +#define MSR_P4_IQ_PERFCTR2 0x30e +#define MSR_P4_IQ_PERFCTR3 0x30f +#define MSR_P4_IQ_PERFCTR4 0x310 +#define MSR_P4_IQ_PERFCTR5 0x311 +#define MSR_P4_BPU_CCCR0 0x360 +#define MSR_P4_BPU_CCCR1 0x361 +#define MSR_P4_BPU_CCCR2 0x362 +#define MSR_P4_BPU_CCCR3 0x363 +#define MSR_P4_MS_CCCR0 0x364 +#define MSR_P4_MS_CCCR1 0x365 +#define MSR_P4_MS_CCCR2 0x366 +#define MSR_P4_MS_CCCR3 0x367 +#define MSR_P4_FLAME_CCCR0 0x368 +#define MSR_P4_FLAME_CCCR1 0x369 +#define MSR_P4_FLAME_CCCR2 0x36a +#define MSR_P4_FLAME_CCCR3 0x36b +#define MSR_P4_IQ_CCCR0 0x36c +#define MSR_P4_IQ_CCCR1 0x36d +#define MSR_P4_IQ_CCCR2 0x36e +#define MSR_P4_IQ_CCCR3 0x36f +#define MSR_P4_IQ_CCCR4 0x370 +#define MSR_P4_IQ_CCCR5 0x371 +#define MSR_P4_ALF_ESCR0 0x3ca +#define MSR_P4_ALF_ESCR1 0x3cb +#define MSR_P4_BPU_ESCR0 0x3b2 +#define MSR_P4_BPU_ESCR1 0x3b3 +#define MSR_P4_BSU_ESCR0 0x3a0 +#define MSR_P4_BSU_ESCR1 0x3a1 +#define MSR_P4_CRU_ESCR0 0x3b8 +#define MSR_P4_CRU_ESCR1 0x3b9 +#define MSR_P4_CRU_ESCR2 0x3cc +#define MSR_P4_CRU_ESCR3 0x3cd +#define MSR_P4_CRU_ESCR4 0x3e0 +#define MSR_P4_CRU_ESCR5 0x3e1 +#define MSR_P4_DAC_ESCR0 0x3a8 +#define MSR_P4_DAC_ESCR1 0x3a9 +#define MSR_P4_FIRM_ESCR0 0x3a4 +#define MSR_P4_FIRM_ESCR1 0x3a5 +#define MSR_P4_FLAME_ESCR0 0x3a6 +#define MSR_P4_FLAME_ESCR1 0x3a7 +#define MSR_P4_FSB_ESCR0 0x3a2 +#define MSR_P4_FSB_ESCR1 0x3a3 +#define MSR_P4_IQ_ESCR0 0x3ba +#define MSR_P4_IQ_ESCR1 0x3bb +#define MSR_P4_IS_ESCR0 0x3b4 +#define MSR_P4_IS_ESCR1 0x3b5 +#define MSR_P4_ITLB_ESCR0 0x3b6 +#define MSR_P4_ITLB_ESCR1 0x3b7 +#define MSR_P4_IX_ESCR0 0x3c8 +#define MSR_P4_IX_ESCR1 0x3c9 +#define MSR_P4_MOB_ESCR0 0x3aa +#define MSR_P4_MOB_ESCR1 0x3ab +#define MSR_P4_MS_ESCR0 0x3c0 +#define MSR_P4_MS_ESCR1 0x3c1 +#define MSR_P4_PMH_ESCR0 0x3ac +#define MSR_P4_PMH_ESCR1 0x3ad +#define MSR_P4_RAT_ESCR0 0x3bc +#define MSR_P4_RAT_ESCR1 0x3bd +#define MSR_P4_SAAT_ESCR0 0x3ae +#define MSR_P4_SAAT_ESCR1 0x3af +#define MSR_P4_SSU_ESCR0 0x3be +#define MSR_P4_SSU_ESCR1 0x3bf /* guess: not defined in manual */ +#define MSR_P4_TBPU_ESCR0 0x3c2 +#define MSR_P4_TBPU_ESCR1 0x3c3 +#define MSR_P4_TC_ESCR0 0x3c4 +#define MSR_P4_TC_ESCR1 0x3c5 +#define MSR_P4_U2L_ESCR0 0x3b0 +#define MSR_P4_U2L_ESCR1 0x3b1 + +#endif diff -r 7e3cbc409676 -r d75a6cc5e68a patches/linux-2.6.16/device_bind.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/patches/linux-2.6.16/device_bind.patch Tue Mar 28 08:54:58 2006 -0700 @@ -0,0 +1,14 @@ +--- linux-2.6.16/drivers/base/bus.c 2006-03-16 10:50:20.000000000 -0500 ++++ linux-2.6.16/drivers/base/bus.c 2006-03-16 11:02:08.000000000 -0500 +@@ -188,6 +188,11 @@ static ssize_t driver_bind(struct device + up(&dev->sem); + if (dev->parent) + up(&dev->parent->sem); ++ ++ if (err > 0) /* success */ ++ err = count; ++ else if (err == 0) /* driver didn't accept device */ ++ err = -ENODEV; + } + put_device(dev); + put_bus(bus); diff -r 7e3cbc409676 -r d75a6cc5e68a tools/python/xen/util/xmlrpclib2.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/python/xen/util/xmlrpclib2.py Tue Mar 28 08:54:58 2006 -0700 @@ -0,0 +1,111 @@ +#============================================================================ +# This library is free software; you can redistribute it and/or +# modify it under the terms of version 2.1 of the GNU Lesser General Public +# License as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#============================================================================ +# Copyright (C) 2006 Anthony Liguori <aliguori@xxxxxxxxxx> +# Copyright (C) 2006 XenSource Ltd. +#============================================================================ + +""" +An enhanced XML-RPC client/server interface for Python. +""" + +from httplib import HTTPConnection, HTTP +from xmlrpclib import Transport +from SimpleXMLRPCServer import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler +import xmlrpclib, socket, os, traceback +import SocketServer + +# A new ServerProxy that also supports httpu urls. An http URL comes in the +# form: +# +# httpu:///absolute/path/to/socket.sock +# +# It assumes that the RPC handler is /RPC2. This probably needs to be improved + +class HTTPUnixConnection(HTTPConnection): + def connect(self): + self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + self.sock.connect(self.host) + +class HTTPUnix(HTTP): + _connection_class = HTTPUnixConnection + +class UnixTransport(Transport): + def request(self, host, handler, request_body, verbose=0): + self.__handler = handler + return Transport.request(self, host, '/RPC2', request_body, verbose) + def make_connection(self, host): + return HTTPUnix(self.__handler) + +class ServerProxy(xmlrpclib.ServerProxy): + def __init__(self, uri, transport=None, encoding=None, verbose=0, + allow_none=1): + if transport == None: + (protocol, rest) = uri.split(':', 1) + if protocol == 'httpu': + uri = 'http:' + rest + transport = UnixTransport() + xmlrpclib.ServerProxy.__init__(self, uri, transport, encoding, + verbose, allow_none) + +# This is a base XML-RPC server for TCP. It sets allow_reuse_address to +# true, and has an improved marshaller that serializes unknown exceptions +# with full traceback information. + +class TCPXMLRPCServer(SocketServer.ThreadingMixIn, SimpleXMLRPCServer): + allow_reuse_address = True + + def _marshaled_dispatch(self, data, dispatch_method = None): + params, method = xmlrpclib.loads(data) + try: + if dispatch_method is not None: + response = dispatch_method(method, params) + else: + response = self._dispatch(method, params) + + response = (response,) + response = xmlrpclib.dumps(response, + methodresponse=1, + allow_none=1) + except xmlrpclib.Fault, fault: + response = xmlrpclib.dumps(fault) + except: + response = xmlrpclib.dumps( + xmlrpclib.Fault(1, traceback.format_exc()) + ) + + return response + +# This is a XML-RPC server that sits on a Unix domain socket. +# It implements proper support for allow_reuse_address by +# unlink()'ing an existing socket. + +class UnixXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): + def address_string(self): + try: + return SimpleXMLRPCRequestHandler.address_string(self) + except ValueError, e: + return self.client_address[:2] + +class UnixXMLRPCServer(TCPXMLRPCServer): + address_family = socket.AF_UNIX + + def __init__(self, addr, logRequests): + if self.allow_reuse_address: + try: + os.unlink(addr) + except OSError, exc: + pass + TCPXMLRPCServer.__init__(self, addr, UnixXMLRPCRequestHandler, + logRequests) diff -r 7e3cbc409676 -r d75a6cc5e68a tools/python/xen/xend/server/XMLRPCServer.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/python/xen/xend/server/XMLRPCServer.py Tue Mar 28 08:54:58 2006 -0700 @@ -0,0 +1,113 @@ +#============================================================================ +# This library is free software; you can redistribute it and/or +# modify it under the terms of version 2.1 of the GNU Lesser General Public +# License as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#============================================================================ +# Copyright (C) 2006 Anthony Liguori <aliguori@xxxxxxxxxx> +# Copyright (C) 2006 XenSource Ltd. +#============================================================================ + +import xmlrpclib + +from xen.xend import XendDomain, XendDomainInfo, XendNode, \ + XendLogging, XendDmesg +from xen.util.xmlrpclib2 import UnixXMLRPCServer, TCPXMLRPCServer + +from xen.xend.XendClient import XML_RPC_SOCKET, ERROR_INVALID_DOMAIN +from xen.xend.XendError import * + +def lookup(domid): + info = XendDomain.instance().domain_lookup_by_name_or_id(domid) + if not info: + raise XendInvalidDomain(str(domid)) + return info + +def dispatch(domid, fn, args): + info = lookup(domid) + return getattr(info, fn)(*args) + +def domain(domid): + info = lookup(domid) + return info.sxpr() + +def domains(detail=1): + if detail < 1: + return XendDomain.instance().list_names() + else: + domains = XendDomain.instance().list_sorted() + return map(lambda dom: dom.sxpr(), domains) + +def domain_create(config): + info = XendDomain.instance().domain_create(config) + return info.sxpr() + +def domain_restore(src): + info = XendDomain.instance().domain_restore(src) + return info.sxpr() + +def get_log(): + f = open(XendLogging.getLogFilename(), 'r') + try: + return f.read() + finally: + f.close() + +methods = ['device_create', 'destroyDevice', 'getDeviceSxprs', + 'setMemoryTarget', 'setName', 'setVCpuCount', 'shutdown', + 'send_sysrq', 'getVCPUInfo', 'waitForDevices'] + +exclude = ['domain_create', 'domain_restore'] + +class XMLRPCServer: + def __init__(self, use_tcp=False): + self.ready = False + self.use_tcp = use_tcp + + def run(self): + if self.use_tcp: + # bind to something fixed for now as we may eliminate + # tcp support completely. + self.server = TCPXMLRPCServer(("localhost", 8005), logRequests=False) + else: + self.server = UnixXMLRPCServer(XML_RPC_SOCKET, False) + + # Functions in XendDomainInfo + for name in methods: + fn = eval("lambda domid, *args: dispatch(domid, '%s', args)"%name) + self.server.register_function(fn, "xend.domain.%s" % name) + + # Functions in XendDomain + inst = XendDomain.instance() + for name in dir(inst): + fn = getattr(inst, name) + if name.startswith("domain_") and callable(fn): + if name not in exclude: + self.server.register_function(fn, "xend.domain.%s" % name[7:]) + + # Functions in XendNode and XendDmesg + for type, lst, n in [(XendNode, ['info', 'cpu_bvt_slice_set'], 'node'), + (XendDmesg, ['info', 'clear'], 'node.dmesg')]: + inst = type.instance() + for name in lst: + self.server.register_function(getattr(inst, name), + "xend.%s.%s" % (n, name)) + + # A few special cases + self.server.register_function(domain, 'xend.domain') + self.server.register_function(domains, 'xend.domains') + self.server.register_function(get_log, 'xend.node.log') + self.server.register_function(domain_create, 'xend.domain.create') + self.server.register_function(domain_restore, 'xend.domain.restore') + + self.server.register_introspection_functions() + self.ready = True + self.server.serve_forever() diff -r 7e3cbc409676 -r d75a6cc5e68a tools/xenstore/README --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/xenstore/README Tue Mar 28 08:54:58 2006 -0700 @@ -0,0 +1,5 @@ +The following files are imported from the Samba project. We use the versions +from Samba 3, the current stable branch. + +talloc.c: samba-trunk/source/lib/talloc.c r14291 2006-03-13 04:27:47 +0000 +talloc.h: samba-trunk/source/include/talloc.h r11986 2005-12-01 00:43:36 +0000 diff -r 7e3cbc409676 -r d75a6cc5e68a tools/xm-test/ramdisk/README-XenSource-initrd-0.7-img --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/xm-test/ramdisk/README-XenSource-initrd-0.7-img Tue Mar 28 08:54:58 2006 -0700 @@ -0,0 +1,42 @@ +XenSource xm-test 0.7 initrd.img +================================ + +http://xm-test.xensource.com/ramdisks/initrd-0.7.img is an initrd suitable for +use with Xen's xm-test regression testing suite. It has been built and +provided by XenSource, for the convenience of Xen users. xm-test initrds may +be mixed across minor xm-test versions, but not across major versions; this +initrd is suitable for all 0.7.x versions of xm-test (as shipped with Xen +3.0.x). + +In order to use this initrd, run "./autogen; ./configure; make existing" +inside the xm-test directory, and the initrd will be downloaded automatically. +Alternatively, if you have already downloaded this file, place it into the +xm-test/ramdisk directory and run the same command. In either case, +runtest.sh can then be used as normal. See xm-test/README for more details. + +This initrd was built using the infrastructure provided by xm-test. It is a +full guest operating system and filesystem, and as such includes a large +number of pieces of software. The source code for the majority of these are +included in full inside the file +http://xm-test.xensource.com/ramdisks/initrd.0.7.img-buildroot.tar.bz2, or +alongside this file. Copyright statements and licences are contained therein. +The remaining source code is included in the Xen distribution, at +http://www.xensource.com/xen/downloads/archives.html. The configurations used +for BusyBox, uClibc, and Buildroot are available as +http://xm-test.xensource.com/ramdisks/initrd-0.7-busybox-config, +http://xm-test.xensource.com/ramdisks/initrd-0.7-uClibc-config, and +http://xm-test.xensource.com/ramdisks/initrd-0.7-buildroot-config +respectively, or alongside this file. + +XenSource and the Xen contributors are grateful to the authors of these +software packages for their contributions to free and open-source software. + + +Buildroot and BusyBox are Copyright (c) Erik Andersen <andersen@xxxxxxxxxxxx>. +BusyBox is licensed under the GNU General Public License (GPL). A copy of +this license is available in the file GPL-2, +http://xm-test.xensource.com/ramdisks/GPL-2, or alongside this file. + +uClibc is licensed under the GNU Lesser General Public License (LGPL). A copy +of this license is available in the file +http://xm-test.xensource.com/ramdisks/LGPL-2, or alongside this file. diff -r 7e3cbc409676 -r d75a6cc5e68a extras/mini-os/xenbus/Makefile --- a/extras/mini-os/xenbus/Makefile Mon Mar 27 15:36:47 2006 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -all: xenstore.h xenbus_comms.o xenbus_xs.o xenbus_probe.o - -xenstore.h: - [ -e xenstored.h ] || ln -sf ../../../tools/xenstore/xenstored.h xenstored.h - -clean: - #Taken care of by main Makefile - #rm xenstored.h - #rm *.o diff -r 7e3cbc409676 -r d75a6cc5e68a extras/mini-os/xenbus/xenbus_comms.c --- a/extras/mini-os/xenbus/xenbus_comms.c Mon Mar 27 15:36:47 2006 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,184 +0,0 @@ -/****************************************************************************** - * xenbus_comms.c - * - * Low level code to talks to Xen Store: ringbuffer and event channel. - * - * Copyright (C) 2005 Rusty Russell, IBM Corporation - * - * This file may be distributed separately from the Linux kernel, or - * incorporated into other software packages, subject to the following license: - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this source file (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, modify, - * merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ -#include <types.h> -#include <wait.h> -#include <mm.h> -#include <hypervisor.h> -#include <events.h> -#include <os.h> -#include <lib.h> -#include <xenbus.h> -#include "xenbus_comms.h" - -static int xenbus_irq; - -extern void xenbus_probe(void *); -extern int xenstored_ready; - -DECLARE_WAIT_QUEUE_HEAD(xb_waitq); - -static inline struct xenstore_domain_interface *xenstore_domain_interface(void) -{ - return mfn_to_virt(start_info.store_mfn); -} - -static void wake_waiting(int port, struct pt_regs *regs) -{ - wake_up(&xb_waitq); -} - -static int check_indexes(XENSTORE_RING_IDX cons, XENSTORE_RING_IDX prod) -{ - return ((prod - cons) <= XENSTORE_RING_SIZE); -} - -static void *get_output_chunk(XENSTORE_RING_IDX cons, - XENSTORE_RING_IDX prod, - char *buf, uint32_t *len) -{ - *len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod); - if ((XENSTORE_RING_SIZE - (prod - cons)) < *len) - *len = XENSTORE_RING_SIZE - (prod - cons); - return buf + MASK_XENSTORE_IDX(prod); -} - -static const void *get_input_chunk(XENSTORE_RING_IDX cons, - XENSTORE_RING_IDX prod, - const char *buf, uint32_t *len) -{ - *len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(cons); - if ((prod - cons) < *len) - *len = prod - cons; - return buf + MASK_XENSTORE_IDX(cons); -} - -int xb_write(const void *data, unsigned len) -{ - struct xenstore_domain_interface *intf = xenstore_domain_interface(); - XENSTORE_RING_IDX cons, prod; - - while (len != 0) { - void *dst; - unsigned int avail; - - wait_event(xb_waitq, (intf->req_prod - intf->req_cons) != - XENSTORE_RING_SIZE); - - /* Read indexes, then verify. */ - cons = intf->req_cons; - prod = intf->req_prod; - mb(); - if (!check_indexes(cons, prod)) - return -EIO; - - dst = get_output_chunk(cons, prod, intf->req, &avail); - if (avail == 0) - continue; - if (avail > len) - avail = len; - - memcpy(dst, data, avail); - data = (void*) ( (unsigned long)data + avail ); - len -= avail; - - /* Other side must not see new header until data is there. */ - wmb(); - intf->req_prod += avail; - - /* This implies mb() before other side sees interrupt. */ - notify_remote_via_evtchn(start_info.store_evtchn); - } - - return 0; -} - -int xb_read(void *data, unsigned len) -{ - struct xenstore_domain_interface *intf = xenstore_domain_interface(); - XENSTORE_RING_IDX cons, prod; - - while (len != 0) { - unsigned int avail; - const char *src; - - wait_event(xb_waitq, - intf->rsp_cons != intf->rsp_prod); - - /* Read indexes, then verify. */ - cons = intf->rsp_cons; - prod = intf->rsp_prod; - mb(); - if (!check_indexes(cons, prod)) - return -EIO; - - src = get_input_chunk(cons, prod, intf->rsp, &avail); - if (avail == 0) - continue; - if (avail > len) - avail = len; - - /* We must read header before we read data. */ - rmb(); - - memcpy(data, src, avail); - data = (void*) ( (unsigned long)data + avail ); - len -= avail; - - /* Other side must not see free space until we've copied out */ - mb(); - intf->rsp_cons += avail; - - printk("Finished read of %i bytes (%i to go)\n", avail, len); - - /* Implies mb(): they will see new header. */ - notify_remote_via_evtchn(start_info.store_evtchn); - } - - return 0; -} - -/* Set up interrupt handler off store event channel. */ -int xb_init_comms(void) -{ - int err; - - if (xenbus_irq) - unbind_evtchn(xenbus_irq); - - err = bind_evtchn( - start_info.store_evtchn, wake_waiting); - if (err <= 0) { - printk("XENBUS request irq failed %i\n", err); - return err; - } - - xenbus_irq = err; - - return 0; -} diff -r 7e3cbc409676 -r d75a6cc5e68a extras/mini-os/xenbus/xenbus_comms.h --- a/extras/mini-os/xenbus/xenbus_comms.h Mon Mar 27 15:36:47 2006 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,40 +0,0 @@ -/* - * Private include for xenbus communications. - * - * Copyright (C) 2005 Rusty Russell, IBM Corporation - * - * This file may be distributed separately from the Linux kernel, or - * incorporated into other software packages, subject to the following license: - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this source file (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, modify, - * merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef _XENBUS_COMMS_H -#define _XENBUS_COMMS_H - -int xs_init(void); -int xb_init_comms(void); - -/* Low level routines. */ -int xb_write(const void *data, unsigned len); -int xb_read(void *data, unsigned len); -int xs_input_avail(void); -extern struct wait_queue_head xb_waitq; - -#endif /* _XENBUS_COMMS_H */ diff -r 7e3cbc409676 -r d75a6cc5e68a extras/mini-os/xenbus/xenbus_xs.c --- a/extras/mini-os/xenbus/xenbus_xs.c Mon Mar 27 15:36:47 2006 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,796 +0,0 @@ -/****************************************************************************** - * xenbus_xs.c - * - * This is the kernel equivalent of the "xs" library. We don't need everything - * and we use xenbus_comms for communication. - * - * Copyright (C) 2005 Rusty Russell, IBM Corporation - * - * This file may be distributed separately from the Linux kernel, or - * incorporated into other software packages, subject to the following license: - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this source file (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, modify, - * merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ -#include <errno.h> -#include <types.h> -#include <list.h> -#include <lib.h> -#include <err.h> -#include <os.h> -#include <xmalloc.h> -#include <fcntl.h> -#include <xenbus.h> -#include <wait.h> -#include <sched.h> -#include <semaphore.h> -#include <spinlock.h> -#include <xen/io/xs_wire.h> -#include "xenbus_comms.h" - -#define streq(a, b) (strcmp((a), (b)) == 0) - -struct xs_stored_msg { - struct list_head list; - - struct xsd_sockmsg hdr; - - union { - /* Queued replies. */ - struct { - char *body; - } reply; - - /* Queued watch events. */ - struct { - struct xenbus_watch *handle; - char **vec; - unsigned int vec_size; - } watch; - } u; -}; - -struct xs_handle { - /* A list of replies. Currently only one will ever be outstanding. */ - struct list_head reply_list; - spinlock_t reply_lock; - struct wait_queue_head reply_waitq; - - /* One request at a time. */ - struct semaphore request_mutex; - - /* Protect transactions against save/restore. */ - struct rw_semaphore suspend_mutex; -}; - -static struct xs_handle xs_state; - -/* List of registered watches, and a lock to protect it. */ -static LIST_HEAD(watches); -static DEFINE_SPINLOCK(watches_lock); - -/* List of pending watch callback events, and a lock to protect it. */ -static LIST_HEAD(watch_events); -static DEFINE_SPINLOCK(watch_events_lock); - -/* - * Details of the xenwatch callback kernel thread. The thread waits on the - * watch_events_waitq for work to do (queued on watch_events list). When it - * wakes up it acquires the xenwatch_mutex before reading the list and - * carrying out work. - */ -/* static */ DECLARE_MUTEX(xenwatch_mutex); -static DECLARE_WAIT_QUEUE_HEAD(watch_events_waitq); - -static int get_error(const char *errorstring) -{ - unsigned int i; - - for (i = 0; !streq(errorstring, xsd_errors[i].errstring); i++) { - if (i == ARRAY_SIZE(xsd_errors) - 1) { - printk("XENBUS xen store gave: unknown error %s", - errorstring); - return EINVAL; - } - } - return xsd_errors[i].errnum; -} - -static void *read_reply(enum xsd_sockmsg_type *type, unsigned int *len) -{ - struct xs_stored_msg *msg; - char *body; - - spin_lock(&xs_state.reply_lock); - - while (list_empty(&xs_state.reply_list)) { - spin_unlock(&xs_state.reply_lock); - wait_event(xs_state.reply_waitq, - !list_empty(&xs_state.reply_list)); - spin_lock(&xs_state.reply_lock); - } - - msg = list_entry(xs_state.reply_list.next, - struct xs_stored_msg, list); - list_del(&msg->list); - - spin_unlock(&xs_state.reply_lock); - - *type = msg->hdr.type; - if (len) - *len = msg->hdr.len; - body = msg->u.reply.body; - - free(msg); - - return body; -} - -/* Emergency write. */ -void xenbus_debug_write(const char *str, unsigned int count) -{ - struct xsd_sockmsg msg = { 0 }; - - msg.type = XS_DEBUG; - msg.len = sizeof("print") + count + 1; - - down(&xs_state.request_mutex); - xb_write(&msg, sizeof(msg)); - xb_write("print", sizeof("print")); - xb_write(str, count); - xb_write("", 1); - up(&xs_state.request_mutex); -} - -void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg) -{ - void *ret; - struct xsd_sockmsg req_msg = *msg; - int err; - - if (req_msg.type == XS_TRANSACTION_START) - down_read(&xs_state.suspend_mutex); - - down(&xs_state.request_mutex); - - err = xb_write(msg, sizeof(*msg) + msg->len); - if (err) { - msg->type = XS_ERROR; - ret = ERR_PTR(err); - } else { - ret = read_reply(&msg->type, &msg->len); - } - - up(&xs_state.request_mutex); - - if ((msg->type == XS_TRANSACTION_END) || - ((req_msg.type == XS_TRANSACTION_START) && - (msg->type == XS_ERROR))) - up_read(&xs_state.suspend_mutex); - - return ret; -} - -/* Send message to xs, get kmalloc'ed reply. ERR_PTR() on error. */ -static void *xs_talkv(struct xenbus_transaction *t, - enum xsd_sockmsg_type type, - const struct kvec *iovec, - unsigned int num_vecs, - unsigned int *len) -{ - struct xsd_sockmsg msg; - void *ret = NULL; - unsigned int i; - int err; - - msg.tx_id = (u32)(unsigned long)t; - msg.req_id = 0; - msg.type = type; - msg.len = 0; - for (i = 0; i < num_vecs; i++) - msg.len += iovec[i].iov_len; - - down(&xs_state.request_mutex); - - err = xb_write(&msg, sizeof(msg)); - if (err) { - up(&xs_state.request_mutex); - return ERR_PTR(err); - } - - for (i = 0; i < num_vecs; i++) { - err = xb_write(iovec[i].iov_base, iovec[i].iov_len);; - if (err) { - up(&xs_state.request_mutex); - return ERR_PTR(err); - } - } - - ret = read_reply(&msg.type, len); - - up(&xs_state.request_mutex); - - if (IS_ERR(ret)) - return ret; - - if (msg.type == XS_ERROR) { - err = get_error(ret); - free(ret); - return ERR_PTR(-err); - } - - // BUG_ON(msg.type != type); - return ret; -} - -/* Simplified version of xs_talkv: single message. */ -static void *xs_single(struct xenbus_transaction *t, - enum xsd_sockmsg_type type, - const char *string, - unsigned int *len) -{ - struct kvec iovec; - - iovec.iov_base = (void *)string; - iovec.iov_len = strlen(string) + 1; - return xs_talkv(t, type, &iovec, 1, len); -} - -/* Many commands only need an ack, don't care what it says. */ -static int xs_error(char *reply) -{ - if (IS_ERR(reply)) - return PTR_ERR(reply); - free(reply); - return 0; -} - -static unsigned int count_strings(const char *strings, unsigned int len) -{ - unsigned int num; - const char *p; - - for (p = strings, num = 0; p < strings + len; p += strlen(p) + 1) - num++; - - return num; -} - -/* Return the path to dir with /name appended. Buffer must be kfree()'ed. */ -static char *join(const char *dir, const char *name) -{ - char *buffer; - - buffer = malloc(strlen(dir) + strlen("/") + strlen(name) + 1); - if (buffer == NULL) - return ERR_PTR(-ENOMEM); - - strcpy(buffer, dir); - if (!streq(name, "")) { - strcat(buffer, "/"); - strcat(buffer, name); - } - - return buffer; -} - -static char **split(char *strings, unsigned int len, unsigned int *num) -{ - char *p, **ret; - - /* Count the strings. */ - *num = count_strings(strings, len); - - /* Transfer to one big alloc for easy freeing. */ - ret = malloc(*num * sizeof(char *) + len); - if (!ret) { - free(strings); - return ERR_PTR(-ENOMEM); - } - memcpy(&ret[*num], strings, len); - free(strings); - - strings = (char *)&ret[*num]; - for (p = strings, *num = 0; p < strings + len; p += strlen(p) + 1) - ret[(*num)++] = p; - - return ret; -} - -char **xenbus_directory(struct xenbus_transaction *t, - const char *dir, const char *node, unsigned int *num) -{ - char *strings, *path; - unsigned int len; - - path = join(dir, node); - if (IS_ERR(path)) - return (char **)path; - - strings = xs_single(t, XS_DIRECTORY, path, &len); - free(path); - if (IS_ERR(strings)) - return (char **)strings; - - return split(strings, len, num); -} - -/* Check if a path exists. Return 1 if it does. */ -int xenbus_exists(struct xenbus_transaction *t, - const char *dir, const char *node) -{ - char **d; - int dir_n; - - d = xenbus_directory(t, dir, node, &dir_n); - if (IS_ERR(d)) - return 0; - free(d); - return 1; -} - -/* Get the value of a single file. - * Returns a kmalloced value: call free() on it after use. - * len indicates length in bytes. - */ -void *xenbus_read(struct xenbus_transaction *t, - const char *dir, const char *node, unsigned int *len) -{ - char *path; - void *ret; - - path = join(dir, node); - if (IS_ERR(path)) - return (void *)path; - - ret = xs_single(t, XS_READ, path, len); - free(path); - return ret; -} - -/* Write the value of a single file. - * Returns -err on failure. - */ -int xenbus_write(struct xenbus_transaction *t, - const char *dir, const char *node, const char *string) -{ - const char *path; - struct kvec iovec[2]; - int ret; - - path = join(dir, node); - if (IS_ERR(path)) - return PTR_ERR(path); - - iovec[0].iov_base = (void *)path; - iovec[0].iov_len = strlen(path) + 1; - iovec[1].iov_base = (void *)string; - iovec[1].iov_len = strlen(string); - - ret = xs_error(xs_talkv(t, XS_WRITE, iovec, ARRAY_SIZE(iovec), NULL)); - free(path); - return ret; -} - -/* Create a new directory. */ -int xenbus_mkdir(struct xenbus_transaction *t, - const char *dir, const char *node) -{ - char *path; - int ret; - - path = join(dir, node); - if (IS_ERR(path)) - return PTR_ERR(path); - - ret = xs_error(xs_single(t, XS_MKDIR, path, NULL)); - free(path); - return ret; -} - -/* Destroy a file or directory (directories must be empty). */ -int xenbus_rm(struct xenbus_transaction *t, const char *dir, const char *node) -{ - char *path; - int ret; - - path = join(dir, node); - if (IS_ERR(path)) - return PTR_ERR(path); - - ret = xs_error(xs_single(t, XS_RM, path, NULL)); - free(path); - return ret; -} - -/* Start a transaction: changes by others will not be seen during this - * transaction, and changes will not be visible to others until end. - */ -struct xenbus_transaction *xenbus_transaction_start(void) -{ - char *id_str; - unsigned long id; - - down_read(&xs_state.suspend_mutex); - - id_str = xs_single(NULL, XS_TRANSACTION_START, "", NULL); - if (IS_ERR(id_str)) { - up_read(&xs_state.suspend_mutex); - return (struct xenbus_transaction *)id_str; - } - - id = simple_strtoul(id_str, NULL, 0); - free(id_str); - - return (struct xenbus_transaction *)id; -} - -/* End a transaction. - * If abandon is true, transaction is discarded instead of committed. - */ -int xenbus_transaction_end(struct xenbus_transaction *t, int abort) -{ - char abortstr[2]; - int err; - - if (abort) - strcpy(abortstr, "F"); - else - strcpy(abortstr, "T"); - - err = xs_error(xs_single(t, XS_TRANSACTION_END, abortstr, NULL)); - - up_read(&xs_state.suspend_mutex); - - return err; -} - -/* Single read and scanf: returns -errno or num scanned. */ -int xenbus_scanf(struct xenbus_transaction *t, - const char *dir, const char *node, const char *fmt, ...) -{ - va_list ap; - int ret; - char *val; - - val = xenbus_read(t, dir, node, NULL); - if (IS_ERR(val)) - return PTR_ERR(val); - - va_start(ap, fmt); - ret = vsscanf(val, fmt, ap); - va_end(ap); - free(val); - /* Distinctive errno. */ - if (ret == 0) - return -ERANGE; - return ret; -} - -/* Single printf and write: returns -errno or 0. */ -int xenbus_printf(struct xenbus_transaction *t, - const char *dir, const char *node, const char *fmt, ...) -{ - va_list ap; - int ret; -#define PRINTF_BUFFER_SIZE 4096 - char *printf_buffer; - - printf_buffer = malloc(PRINTF_BUFFER_SIZE); - if (printf_buffer == NULL) - return -ENOMEM; - - va_start(ap, fmt); - ret = vsnprintf(printf_buffer, PRINTF_BUFFER_SIZE, fmt, ap); - va_end(ap); - - // BUG_ON(ret > PRINTF_BUFFER_SIZE-1); - ret = xenbus_write(t, dir, node, printf_buffer); - - free(printf_buffer); - - return ret; -} - -/* Takes tuples of names, scanf-style args, and void **, NULL terminated. */ -int xenbus_gather(struct xenbus_transaction *t, const char *dir, ...) -{ - va_list ap; - const char *name; - int ret = 0; - - va_start(ap, dir); - while (ret == 0 && (name = va_arg(ap, char *)) != NULL) { - const char *fmt = va_arg(ap, char *); - void *result = va_arg(ap, void *); - char *p; - - p = xenbus_read(t, dir, name, NULL); - if (IS_ERR(p)) { - ret = PTR_ERR(p); - break; - } - if (fmt) { - if (sscanf(p, fmt, result) == 0) - ret = -EINVAL; - free(p); - } else - *(char **)result = p; - } - va_end(ap); - return ret; -} - -static int xs_watch(const char *path, const char *token) -{ - struct kvec iov[2]; - - iov[0].iov_base = (void *)path; - iov[0].iov_len = strlen(path) + 1; - iov[1].iov_base = (void *)token; - iov[1].iov_len = strlen(token) + 1; - - return xs_error(xs_talkv(NULL, XS_WATCH, iov, - ARRAY_SIZE(iov), NULL)); -} - -static int xs_unwatch(const char *path, const char *token) -{ - struct kvec iov[2]; - - iov[0].iov_base = (char *)path; - iov[0].iov_len = strlen(path) + 1; - iov[1].iov_base = (char *)token; - iov[1].iov_len = strlen(token) + 1; - - return xs_error(xs_talkv(NULL, XS_UNWATCH, iov, - ARRAY_SIZE(iov), NULL)); -} - -static struct xenbus_watch *find_watch(const char *token) -{ - struct xenbus_watch *i, *cmp; - - cmp = (void *)simple_strtoul(token, NULL, 16); - - list_for_each_entry(i, &watches, list) - if (i == cmp) - return i; - - return NULL; -} - -/* Register callback to watch this node. */ -int register_xenbus_watch(struct xenbus_watch *watch) -{ - /* Pointer in ascii is the token. */ - char token[sizeof(watch) * 2 + 1]; - int err; - - sprintf(token, "%lX", (long)watch); - - down_read(&xs_state.suspend_mutex); - - spin_lock(&watches_lock); - // BUG_ON(find_watch(token)); - list_add(&watch->list, &watches); - spin_unlock(&watches_lock); - - err = xs_watch(watch->node, token); - - /* Ignore errors due to multiple registration. */ - if ((err != 0) && (err != -EEXIST)) { - spin_lock(&watches_lock); - list_del(&watch->list); - spin_unlock(&watches_lock); - } - - up_read(&xs_state.suspend_mutex); - - return err; -} - -void unregister_xenbus_watch(struct xenbus_watch *watch) -{ - struct xs_stored_msg *msg, *tmp; - char token[sizeof(watch) * 2 + 1]; - int err; - - sprintf(token, "%lX", (long)watch); - - down_read(&xs_state.suspend_mutex); - - spin_lock(&watches_lock); - // BUG_ON(!find_watch(token)); - list_del(&watch->list); - spin_unlock(&watches_lock); - - err = xs_unwatch(watch->node, token); - if (err) - printk("XENBUS Failed to release watch %s: %i\n", - watch->node, err); - - up_read(&xs_state.suspend_mutex); - - /* Cancel pending watch events. */ - spin_lock(&watch_events_lock); - list_for_each_entry_safe(msg, tmp, &watch_events, list) { - if (msg->u.watch.handle != watch) - continue; - list_del(&msg->list); - free(msg->u.watch.vec); - free(msg); - } - spin_unlock(&watch_events_lock); -} - -void xs_suspend(void) -{ - down_write(&xs_state.suspend_mutex); - down(&xs_state.request_mutex); -} - -void xs_resume(void) -{ - struct xenbus_watch *watch; - char token[sizeof(watch) * 2 + 1]; - - up(&xs_state.request_mutex); - - /* No need for watches_lock: the suspend_mutex is sufficient. */ - list_for_each_entry(watch, &watches, list) { - sprintf(token, "%lX", (long)watch); - xs_watch(watch->node, token); - } - - up_write(&xs_state.suspend_mutex); -} - -static void xenwatch_thread(void *unused) -{ - struct list_head *ent; - struct xs_stored_msg *msg; - - for (;;) { - wait_event(watch_events_waitq, - !list_empty(&watch_events)); - - down(&xenwatch_mutex); - - spin_lock(&watch_events_lock); - ent = watch_events.next; - if (ent != &watch_events) - list_del(ent); - spin_unlock(&watch_events_lock); - - if (ent != &watch_events) { - msg = list_entry(ent, struct xs_stored_msg, list); - msg->u.watch.handle->callback( - msg->u.watch.handle, - (const char **)msg->u.watch.vec, - msg->u.watch.vec_size); - free(msg->u.watch.vec); - free(msg); - } - - up(&xenwatch_mutex); - } -} - -static int process_msg(void) -{ - struct xs_stored_msg *msg; - char *body; - int err; - - msg = malloc(sizeof(*msg)); - if (msg == NULL) - return -ENOMEM; - - err = xb_read(&msg->hdr, sizeof(msg->hdr)); - if (err) { - free(msg); - return err; - } - - body = malloc(msg->hdr.len + 1); - if (body == NULL) { - free(msg); - return -ENOMEM; - } - - err = xb_read(body, msg->hdr.len); - if (err) { - free(body); - free(msg); - return err; - } - body[msg->hdr.len] = '\0'; - - if (msg->hdr.type == XS_WATCH_EVENT) { - msg->u.watch.vec = split(body, msg->hdr.len, - &msg->u.watch.vec_size); - if (IS_ERR(msg->u.watch.vec)) { - free(msg); - return PTR_ERR(msg->u.watch.vec); - } - - spin_lock(&watches_lock); - msg->u.watch.handle = find_watch( - msg->u.watch.vec[XS_WATCH_TOKEN]); - if (msg->u.watch.handle != NULL) { - spin_lock(&watch_events_lock); - list_add_tail(&msg->list, &watch_events); - wake_up(&watch_events_waitq); - spin_unlock(&watch_events_lock); - } else { - free(msg->u.watch.vec); - free(msg); - } - spin_unlock(&watches_lock); - } else { - msg->u.reply.body = body; - spin_lock(&xs_state.reply_lock); - list_add_tail(&msg->list, &xs_state.reply_list); - spin_unlock(&xs_state.reply_lock); - wake_up(&xs_state.reply_waitq); - } - - return 0; -} - -static void xenbus_thread(void *unused) -{ - int err; - - for (;;) { - err = process_msg(); - if (err) - printk("XENBUS error %d while reading " - "message\n", err); - } -} - -int xs_init(void) -{ - int err; - struct thread *kxwatcher_thread; - struct thread *kxenbus_thread; - - INIT_LIST_HEAD(&xs_state.reply_list); - spin_lock_init(&xs_state.reply_lock); - init_waitqueue_head(&xs_state.reply_waitq); - - init_MUTEX(&xs_state.request_mutex); - init_rwsem(&xs_state.suspend_mutex); - - /* Initialize the shared memory rings to talk to xenstored */ - err = xb_init_comms(); - if (err) - return err; - - kxwatcher_thread = create_thread("kxwatch", xenwatch_thread, NULL); - if (IS_ERR(kxwatcher_thread)) - return PTR_ERR(kxwatcher_thread); - - kxenbus_thread = create_thread("kxenbus", xenbus_thread, NULL); - if (IS_ERR(kxenbus_thread)) - return PTR_ERR(kxenbus_thread); - - return 0; -} _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |