[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] merge with xen-unstable.hg
# HG changeset patch # User awilliam@xxxxxxxxxxx # Node ID 3e26719ab827f249e8fefa310db1c1a45af2f1e0 # Parent d246b79986d12e99db87339ba57bdac067950ec5 # Parent abee5c6b930daae7b97ca2837591b737e939ddf4 merge with xen-unstable.hg --- xen/include/asm-x86/hvm/vpit.h | 139 ---- linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c | 10 linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c | 25 linux-2.6-xen-sparse/drivers/xen/blkfront/vbd.c | 10 linux-2.6-xen-sparse/drivers/xen/core/features.c | 4 linux-2.6-xen-sparse/drivers/xen/core/gnttab.c | 4 linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c | 4 linux-2.6-xen-sparse/drivers/xen/xenbus/Makefile | 1 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_client.c | 4 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c | 4 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c | 5 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c | 260 +------ linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.h | 77 ++ linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe_backend.c | 271 ++++++++ linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c | 6 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/synch_bitops.h | 4 linux-2.6-xen-sparse/include/xen/xenbus.h | 1 tools/blktap/drivers/blktapctrl.c | 104 +-- tools/blktap/drivers/tapdisk.c | 58 - tools/blktap/drivers/tapdisk.h | 8 tools/firmware/acpi/acpi_fadt.h | 9 tools/ioemu/vl.c | 10 tools/ioemu/vnc.c | 2 tools/libxc/Makefile | 2 tools/libxc/ia64/xc_ia64_hvm_build.c | 10 tools/libxc/xc_linux_build.c | 2 tools/libxc/xc_linux_restore.c | 2 tools/libxc/xc_linux_save.c | 2 tools/libxc/xc_private.c | 18 tools/python/xen/xend/image.py | 11 tools/python/xen/xend/server/SrvDaemon.py | 7 tools/xenstat/xentop/xentop.1 | 3 tools/xenstat/xentop/xentop.c | 6 tools/xm-test/lib/XmTestLib/arch.py | 3 unmodified_drivers/linux-2.6/blkfront/Makefile | 3 unmodified_drivers/linux-2.6/compat-include/asm-generic/pgtable-nopmd.h | 14 unmodified_drivers/linux-2.6/compat-include/asm-generic/pgtable-nopud.h | 14 unmodified_drivers/linux-2.6/compat-include/linux/io.h | 10 unmodified_drivers/linux-2.6/compat-include/linux/mutex.h | 31 unmodified_drivers/linux-2.6/compat-include/xen/platform-compat.h | 52 + unmodified_drivers/linux-2.6/netfront/Makefile | 3 unmodified_drivers/linux-2.6/overrides.mk | 2 unmodified_drivers/linux-2.6/platform-pci/Kbuild | 2 unmodified_drivers/linux-2.6/platform-pci/Makefile | 3 unmodified_drivers/linux-2.6/platform-pci/evtchn.c | 4 unmodified_drivers/linux-2.6/platform-pci/platform-compat.c | 116 +++ unmodified_drivers/linux-2.6/platform-pci/platform-pci.c | 5 unmodified_drivers/linux-2.6/platform-pci/xen_support.c | 4 unmodified_drivers/linux-2.6/xenbus/Makefile | 3 xen/arch/ia64/vmx/mmio.c | 70 ++ xen/arch/ia64/vmx/vmx_init.c | 14 xen/arch/x86/Makefile | 2 xen/arch/x86/hvm/Makefile | 1 xen/arch/x86/hvm/hvm.c | 3 xen/arch/x86/hvm/i8254.c | 2 xen/arch/x86/hvm/io.c | 2 xen/arch/x86/hvm/pmtimer.c | 63 + xen/arch/x86/hvm/rtc.c | 2 xen/arch/x86/hvm/svm/svm.c | 3 xen/arch/x86/hvm/vmx/vmx.c | 3 xen/arch/x86/numa.c | 308 +++++++++ xen/arch/x86/setup.c | 30 xen/arch/x86/smpboot.c | 3 xen/arch/x86/srat.c | 315 +++++++++ xen/common/memory.c | 21 xen/common/page_alloc.c | 209 ++++-- xen/drivers/acpi/Makefile | 1 xen/drivers/acpi/numa.c | 216 ++++++ xen/include/asm-ia64/vmx_platform.h | 2 xen/include/asm-x86/acpi.h | 4 xen/include/asm-x86/config.h | 5 xen/include/asm-x86/hvm/domain.h | 2 xen/include/asm-x86/hvm/vpt.h | 151 ++++ xen/include/asm-x86/mach-generic/mach_apic.h | 6 xen/include/asm-x86/numa.h | 78 ++ xen/include/public/arch-ia64.h | 3 xen/include/public/hvm/ioreq.h | 4 xen/include/xen/config.h | 2 xen/include/xen/mm.h | 7 xen/include/xen/nodemask.h | 338 ++++++++++ xen/include/xen/numa.h | 13 81 files changed, 2656 insertions(+), 579 deletions(-) diff -r d246b79986d1 -r 3e26719ab827 linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c --- a/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c Tue Oct 24 11:21:48 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c Wed Oct 25 12:12:01 2006 -0600 @@ -392,16 +392,24 @@ static void dispatch_rw_block_io(blkif_t for (i = 0; i < nseg; i++) { if (unlikely(map[i].status != 0)) { DPRINTK("invalid buffer -- could not remap it\n"); - goto fail_flush; + map[i].handle = BLKBACK_INVALID_HANDLE; + ret |= 1; } pending_handle(pending_req, i) = map[i].handle; + + if (ret) + continue; + set_phys_to_machine(__pa(vaddr( pending_req, i)) >> PAGE_SHIFT, FOREIGN_FRAME(map[i].dev_bus_addr >> PAGE_SHIFT)); seg[i].buf = map[i].dev_bus_addr | (req->seg[i].first_sect << 9); } + + if (ret) + goto fail_flush; if (vbd_translate(&preq, blkif, operation) != 0) { DPRINTK("access denied: %s of [%llu,%llu] on dev=%04x\n", diff -r d246b79986d1 -r 3e26719ab827 linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c Tue Oct 24 11:21:48 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c Wed Oct 25 12:12:01 2006 -0600 @@ -48,6 +48,10 @@ #include <asm/hypervisor.h> #include <asm/maddr.h> +#ifdef HAVE_XEN_PLATFORM_COMPAT_H +#include <xen/platform-compat.h> +#endif + #define BLKIF_STATE_DISCONNECTED 0 #define BLKIF_STATE_CONNECTED 1 #define BLKIF_STATE_SUSPENDED 2 @@ -468,6 +472,27 @@ int blkif_ioctl(struct inode *inode, str command, (long)argument, inode->i_rdev); switch (command) { +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16) + case HDIO_GETGEO: { + struct block_device *bd = inode->i_bdev; + struct hd_geometry geo; + int ret; + + if (!argument) + return -EINVAL; + + geo.start = get_start_sect(bd); + ret = blkif_getgeo(bd, &geo); + if (ret) + return ret; + + if (copy_to_user((struct hd_geometry __user *)argument, &geo, + sizeof(geo))) + return -EFAULT; + + return 0; + } +#endif case CDROMMULTISESSION: DPRINTK("FIXME: support multisession CDs later\n"); for (i = 0; i < sizeof(struct cdrom_multisession); i++) diff -r d246b79986d1 -r 3e26719ab827 linux-2.6-xen-sparse/drivers/xen/blkfront/vbd.c --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/vbd.c Tue Oct 24 11:21:48 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/vbd.c Wed Oct 25 12:12:01 2006 -0600 @@ -36,6 +36,10 @@ #include <linux/blkdev.h> #include <linux/list.h> +#ifdef HAVE_XEN_PLATFORM_COMPAT_H +#include <xen/platform-compat.h> +#endif + #define BLKIF_MAJOR(dev) ((dev)>>8) #define BLKIF_MINOR(dev) ((dev) & 0xff) @@ -91,7 +95,9 @@ static struct block_device_operations xl .open = blkif_open, .release = blkif_release, .ioctl = blkif_ioctl, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) .getgeo = blkif_getgeo +#endif }; DEFINE_SPINLOCK(blkif_io_lock); @@ -186,7 +192,11 @@ xlvbd_init_blk_queue(struct gendisk *gd, if (rq == NULL) return -1; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) elevator_init(rq, "noop"); +#else + elevator_init(rq, &elevator_noop); +#endif /* Hard sector size and max sectors impersonate the equiv. hardware. */ blk_queue_hardsect_size(rq, sector_size); diff -r d246b79986d1 -r 3e26719ab827 linux-2.6-xen-sparse/drivers/xen/core/features.c --- a/linux-2.6-xen-sparse/drivers/xen/core/features.c Tue Oct 24 11:21:48 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/core/features.c Wed Oct 25 12:12:01 2006 -0600 @@ -10,6 +10,10 @@ #include <linux/module.h> #include <asm/hypervisor.h> #include <xen/features.h> + +#ifdef HAVE_XEN_PLATFORM_COMPAT_H +#include <xen/platform-compat.h> +#endif u8 xen_features[XENFEAT_NR_SUBMAPS * 32] __read_mostly; /* Not a GPL symbol: used in ubiquitous macros, so too restrictive. */ diff -r d246b79986d1 -r 3e26719ab827 linux-2.6-xen-sparse/drivers/xen/core/gnttab.c --- a/linux-2.6-xen-sparse/drivers/xen/core/gnttab.c Tue Oct 24 11:21:48 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/core/gnttab.c Wed Oct 25 12:12:01 2006 -0600 @@ -44,6 +44,10 @@ #include <asm/io.h> #include <xen/interface/memory.h> +#ifdef HAVE_XEN_PLATFORM_COMPAT_H +#include <xen/platform-compat.h> +#endif + /* External tools reserve first few grant table entries. */ #define NR_RESERVED_ENTRIES 8 diff -r d246b79986d1 -r 3e26719ab827 linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Tue Oct 24 11:21:48 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Wed Oct 25 12:12:01 2006 -0600 @@ -64,6 +64,10 @@ #include <xen/interface/grant_table.h> #include <xen/gnttab.h> +#ifdef HAVE_XEN_PLATFORM_COMPAT_H +#include <xen/platform-compat.h> +#endif + /* * Mutually-exclusive module options to select receive data path: * rx_copy : Packets are copied by network backend into local memory diff -r d246b79986d1 -r 3e26719ab827 linux-2.6-xen-sparse/drivers/xen/xenbus/Makefile --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/Makefile Tue Oct 24 11:21:48 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/Makefile Wed Oct 25 12:12:01 2006 -0600 @@ -9,4 +9,5 @@ xenbus-objs += xenbus_comms.o xenbus-objs += xenbus_comms.o xenbus-objs += xenbus_xs.o xenbus-objs += xenbus_probe.o +obj-$(CONFIG_XEN_BACKEND) += xenbus_probe_backend.o obj-$(CONFIG_XEN_XENBUS_DEV) += xenbus_dev.o diff -r d246b79986d1 -r 3e26719ab827 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_client.c --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_client.c Tue Oct 24 11:21:48 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_client.c Wed Oct 25 12:12:01 2006 -0600 @@ -34,6 +34,10 @@ #include <xen/gnttab.h> #include <xen/xenbus.h> #include <xen/driver_util.h> + +#ifdef HAVE_XEN_PLATFORM_COMPAT_H +#include <xen/platform-compat.h> +#endif /* xenbus_probe.c */ extern char *kasprintf(const char *fmt, ...); diff -r d246b79986d1 -r 3e26719ab827 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c Tue Oct 24 11:21:48 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c Wed Oct 25 12:12:01 2006 -0600 @@ -39,6 +39,10 @@ #include <xen/xenbus.h> #include "xenbus_comms.h" +#ifdef HAVE_XEN_PLATFORM_COMPAT_H +#include <xen/platform-compat.h> +#endif + static int xenbus_irq; extern void xenbus_probe(void *); diff -r d246b79986d1 -r 3e26719ab827 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c Tue Oct 24 11:21:48 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c Wed Oct 25 12:12:01 2006 -0600 @@ -40,6 +40,7 @@ #include <linux/wait.h> #include <linux/fs.h> #include <linux/poll.h> +#include <linux/mutex.h> #include "xenbus_comms.h" @@ -48,6 +49,10 @@ #include <xen/xenbus.h> #include <xen/xen_proc.h> #include <asm/hypervisor.h> + +#ifdef HAVE_XEN_PLATFORM_COMPAT_H +#include <xen/platform-compat.h> +#endif struct xenbus_dev_transaction { struct list_head list; diff -r d246b79986d1 -r 3e26719ab827 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Tue Oct 24 11:21:48 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Wed Oct 25 12:12:01 2006 -0600 @@ -42,6 +42,7 @@ #include <linux/mm.h> #include <linux/notifier.h> #include <linux/kthread.h> +#include <linux/mutex.h> #include <asm/io.h> #include <asm/page.h> @@ -55,6 +56,11 @@ #include <xen/hvm.h> #include "xenbus_comms.h" +#include "xenbus_probe.h" + +#ifdef HAVE_XEN_PLATFORM_COMPAT_H +#include <xen/platform-compat.h> +#endif int xen_store_evtchn; struct xenstore_domain_interface *xen_store_interface; @@ -67,12 +73,7 @@ static void wait_for_devices(struct xenb static void wait_for_devices(struct xenbus_driver *xendrv); static int xenbus_probe_frontend(const char *type, const char *name); -static int xenbus_uevent_backend(struct device *dev, char **envp, - int num_envp, char *buffer, int buffer_size); -static int xenbus_probe_backend(const char *type, const char *domid); - -static int xenbus_dev_probe(struct device *_dev); -static int xenbus_dev_remove(struct device *_dev); + static void xenbus_dev_shutdown(struct device *_dev); /* If something in array of ids matches this device, return it. */ @@ -86,7 +87,7 @@ match_device(const struct xenbus_device_ return NULL; } -static int xenbus_match(struct device *_dev, struct device_driver *_drv) +int xenbus_match(struct device *_dev, struct device_driver *_drv) { struct xenbus_driver *drv = to_xenbus_driver(_drv); @@ -95,17 +96,6 @@ static int xenbus_match(struct device *_ return match_device(drv->ids, to_xenbus_device(_dev)) != NULL; } - -struct xen_bus_type -{ - char *root; - unsigned int levels; - int (*get_bus_id)(char bus_id[BUS_ID_SIZE], const char *nodename); - int (*probe)(const char *type, const char *dir); - struct bus_type bus; - struct device dev; -}; - /* device/<type>/<id> => <type>-<id> */ static int frontend_bus_id(char bus_id[BUS_ID_SIZE], const char *nodename) @@ -143,7 +133,7 @@ static void free_otherend_watch(struct x } -static int read_otherend_details(struct xenbus_device *xendev, +int read_otherend_details(struct xenbus_device *xendev, char *id_node, char *path_node) { int err = xenbus_gather(XBT_NIL, xendev->nodename, @@ -176,12 +166,6 @@ static int read_backend_details(struct x } -static int read_frontend_details(struct xenbus_device *xendev) -{ - return read_otherend_details(xendev, "frontend-id", "frontend"); -} - - /* Bus type for frontend drivers. */ static struct xen_bus_type xenbus_frontend = { .root = "device", @@ -191,114 +175,16 @@ static struct xen_bus_type xenbus_fronte .bus = { .name = "xen", .match = xenbus_match, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) .probe = xenbus_dev_probe, .remove = xenbus_dev_remove, .shutdown = xenbus_dev_shutdown, +#endif }, .dev = { .bus_id = "xen", }, }; - -/* backend/<type>/<fe-uuid>/<id> => <type>-<fe-domid>-<id> */ -static int backend_bus_id(char bus_id[BUS_ID_SIZE], const char *nodename) -{ - int domid, err; - const char *devid, *type, *frontend; - unsigned int typelen; - - type = strchr(nodename, '/'); - if (!type) - return -EINVAL; - type++; - typelen = strcspn(type, "/"); - if (!typelen || type[typelen] != '/') - return -EINVAL; - - devid = strrchr(nodename, '/') + 1; - - err = xenbus_gather(XBT_NIL, nodename, "frontend-id", "%i", &domid, - "frontend", NULL, &frontend, - NULL); - if (err) - return err; - if (strlen(frontend) == 0) - err = -ERANGE; - if (!err && !xenbus_exists(XBT_NIL, frontend, "")) - err = -ENOENT; - - kfree(frontend); - - if (err) - return err; - - if (snprintf(bus_id, BUS_ID_SIZE, - "%.*s-%i-%s", typelen, type, domid, devid) >= BUS_ID_SIZE) - return -ENOSPC; - return 0; -} - -static struct xen_bus_type xenbus_backend = { - .root = "backend", - .levels = 3, /* backend/type/<frontend>/<id> */ - .get_bus_id = backend_bus_id, - .probe = xenbus_probe_backend, - .bus = { - .name = "xen-backend", - .match = xenbus_match, - .probe = xenbus_dev_probe, - .remove = xenbus_dev_remove, -// .shutdown = xenbus_dev_shutdown, - .uevent = xenbus_uevent_backend, - }, - .dev = { - .bus_id = "xen-backend", - }, -}; - -static int xenbus_uevent_backend(struct device *dev, char **envp, - int num_envp, char *buffer, int buffer_size) -{ - struct xenbus_device *xdev; - struct xenbus_driver *drv; - int i = 0; - int length = 0; - - DPRINTK(""); - - if (dev == NULL) - return -ENODEV; - - xdev = to_xenbus_device(dev); - if (xdev == NULL) - return -ENODEV; - - /* stuff we want to pass to /sbin/hotplug */ - add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, - "XENBUS_TYPE=%s", xdev->devicetype); - - add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, - "XENBUS_PATH=%s", xdev->nodename); - - add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, - "XENBUS_BASE_PATH=%s", xenbus_backend.root); - - /* terminate, set to next free slot, shrink available space */ - envp[i] = NULL; - envp = &envp[i]; - num_envp -= i; - buffer = &buffer[length]; - buffer_size -= length; - - if (dev->driver) { - drv = to_xenbus_driver(dev->driver); - if (drv && drv->uevent) - return drv->uevent(xdev, envp, num_envp, buffer, - buffer_size); - } - - return 0; -} static void otherend_changed(struct xenbus_watch *watch, const char **vec, unsigned int len) @@ -359,7 +245,7 @@ static int watch_otherend(struct xenbus_ } -static int xenbus_dev_probe(struct device *_dev) +int xenbus_dev_probe(struct device *_dev) { struct xenbus_device *dev = to_xenbus_device(_dev); struct xenbus_driver *drv = to_xenbus_driver(_dev->driver); @@ -406,7 +292,7 @@ fail: return -ENODEV; } -static int xenbus_dev_remove(struct device *_dev) +int xenbus_dev_remove(struct device *_dev) { struct xenbus_device *dev = to_xenbus_device(_dev); struct xenbus_driver *drv = to_xenbus_driver(_dev->driver); @@ -444,14 +330,21 @@ static void xenbus_dev_shutdown(struct d put_device(&dev->dev); } -static int xenbus_register_driver_common(struct xenbus_driver *drv, - struct xen_bus_type *bus) +int xenbus_register_driver_common(struct xenbus_driver *drv, + struct xen_bus_type *bus) { int ret; drv->driver.name = drv->name; drv->driver.bus = &bus->bus; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) drv->driver.owner = drv->owner; +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16) + drv->driver.probe = xenbus_dev_probe; + drv->driver.remove = xenbus_dev_remove; + drv->driver.shutdown = xenbus_dev_shutdown; +#endif mutex_lock(&xenwatch_mutex); ret = driver_register(&drv->driver); @@ -475,14 +368,6 @@ int xenbus_register_frontend(struct xenb return 0; } EXPORT_SYMBOL_GPL(xenbus_register_frontend); - -int xenbus_register_backend(struct xenbus_driver *drv) -{ - drv->read_otherend_details = read_frontend_details; - - return xenbus_register_driver_common(drv, &xenbus_backend); -} -EXPORT_SYMBOL_GPL(xenbus_register_backend); void xenbus_unregister_driver(struct xenbus_driver *drv) { @@ -581,23 +466,29 @@ char *kasprintf(const char *fmt, ...) } static ssize_t xendev_show_nodename(struct device *dev, - struct device_attribute *attr, char *buf) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13) + struct device_attribute *attr, +#endif + char *buf) { return sprintf(buf, "%s\n", to_xenbus_device(dev)->nodename); } DEVICE_ATTR(nodename, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_nodename, NULL); static ssize_t xendev_show_devtype(struct device *dev, - struct device_attribute *attr, char *buf) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13) + struct device_attribute *attr, +#endif + char *buf) { return sprintf(buf, "%s\n", to_xenbus_device(dev)->devicetype); } DEVICE_ATTR(devtype, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_devtype, NULL); -static int xenbus_probe_node(struct xen_bus_type *bus, - const char *type, - const char *nodename) +int xenbus_probe_node(struct xen_bus_type *bus, + const char *type, + const char *nodename) { int err; struct xenbus_device *xendev; @@ -667,55 +558,6 @@ static int xenbus_probe_frontend(const c return err; } -/* backend/<typename>/<frontend-uuid>/<name> */ -static int xenbus_probe_backend_unit(const char *dir, - const char *type, - const char *name) -{ - char *nodename; - int err; - - nodename = kasprintf("%s/%s", dir, name); - if (!nodename) - return -ENOMEM; - - DPRINTK("%s\n", nodename); - - err = xenbus_probe_node(&xenbus_backend, type, nodename); - kfree(nodename); - return err; -} - -/* backend/<typename>/<frontend-domid> */ -static int xenbus_probe_backend(const char *type, const char *domid) -{ - char *nodename; - int err = 0; - char **dir; - unsigned int i, dir_n = 0; - - DPRINTK(""); - - nodename = kasprintf("%s/%s/%s", xenbus_backend.root, type, domid); - if (!nodename) - return -ENOMEM; - - dir = xenbus_directory(XBT_NIL, nodename, "", &dir_n); - if (IS_ERR(dir)) { - kfree(nodename); - return PTR_ERR(dir); - } - - for (i = 0; i < dir_n; i++) { - err = xenbus_probe_backend_unit(nodename, type, dir[i]); - if (err) - break; - } - kfree(dir); - kfree(nodename); - return err; -} - static int xenbus_probe_device_type(struct xen_bus_type *bus, const char *type) { int err = 0; @@ -736,7 +578,7 @@ static int xenbus_probe_device_type(stru return err; } -static int xenbus_probe_devices(struct xen_bus_type *bus) +int xenbus_probe_devices(struct xen_bus_type *bus) { int err = 0; char **dir; @@ -778,7 +620,7 @@ static int strsep_len(const char *str, c return (len == 0) ? i : -ERANGE; } -static void dev_changed(const char *node, struct xen_bus_type *bus) +void dev_changed(const char *node, struct xen_bus_type *bus) { int exists, rootlen; struct xenbus_device *dev; @@ -823,23 +665,10 @@ static void frontend_changed(struct xenb dev_changed(vec[XS_WATCH_PATH], &xenbus_frontend); } -static void backend_changed(struct xenbus_watch *watch, - const char **vec, unsigned int len) -{ - DPRINTK(""); - - dev_changed(vec[XS_WATCH_PATH], &xenbus_backend); -} - /* We watch for devices appearing and vanishing. */ static struct xenbus_watch fe_watch = { .node = "device", .callback = frontend_changed, -}; - -static struct xenbus_watch be_watch = { - .node = "backend", - .callback = backend_changed, }; static int suspend_dev(struct device *dev, void *data) @@ -912,7 +741,7 @@ void xenbus_suspend(void) DPRINTK(""); bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, suspend_dev); - bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, suspend_dev); + xenbus_backend_suspend(suspend_dev); xs_suspend(); } EXPORT_SYMBOL_GPL(xenbus_suspend); @@ -922,7 +751,7 @@ void xenbus_resume(void) xb_init_comms(); xs_resume(); bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, resume_dev); - bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, resume_dev); + xenbus_backend_resume(resume_dev); } EXPORT_SYMBOL_GPL(xenbus_resume); @@ -955,20 +784,17 @@ void xenbus_probe(void *unused) { BUG_ON((xenstored_ready <= 0)); - /* Enumerate devices in xenstore. */ + /* Enumerate devices in xenstore and watch for changes. */ xenbus_probe_devices(&xenbus_frontend); - xenbus_probe_devices(&xenbus_backend); - - /* Watch for changes. */ register_xenbus_watch(&fe_watch); - register_xenbus_watch(&be_watch); + xenbus_backend_probe_and_watch(); /* Notify others that xenstore is up */ notifier_call_chain(&xenstore_chain, 0, NULL); } -#ifdef CONFIG_PROC_FS +#if defined(CONFIG_PROC_FS) && defined(CONFIG_XEN_PRIVILEGED_GUEST) static struct file_operations xsd_kva_fops; static struct proc_dir_entry *xsd_kva_intf; static struct proc_dir_entry *xsd_port_intf; @@ -1020,7 +846,7 @@ static int __init xenbus_probe_init(void /* Register ourselves with the kernel bus subsystem */ bus_register(&xenbus_frontend.bus); - bus_register(&xenbus_backend.bus); + xenbus_backend_bus_register(); /* * Domain0 doesn't have a store_evtchn or store_mfn yet. @@ -1049,7 +875,7 @@ static int __init xenbus_probe_init(void xen_store_evtchn = xen_start_info->store_evtchn = alloc_unbound.port; -#ifdef CONFIG_PROC_FS +#if defined(CONFIG_PROC_FS) && defined(CONFIG_XEN_PRIVILEGED_GUEST) /* And finally publish the above info in /proc/xen */ xsd_kva_intf = create_xen_proc_entry("xsd_kva", 0600); if (xsd_kva_intf) { @@ -1091,7 +917,7 @@ static int __init xenbus_probe_init(void /* Register ourselves with the kernel device subsystem */ device_register(&xenbus_frontend.dev); - device_register(&xenbus_backend.dev); + xenbus_backend_device_register(); if (!is_initial_xendomain()) xenbus_probe(NULL); diff -r d246b79986d1 -r 3e26719ab827 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c Tue Oct 24 11:21:48 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c Wed Oct 25 12:12:01 2006 -0600 @@ -42,8 +42,14 @@ #include <linux/fcntl.h> #include <linux/kthread.h> #include <linux/rwsem.h> +#include <linux/module.h> +#include <linux/mutex.h> #include <xen/xenbus.h> #include "xenbus_comms.h" + +#ifdef HAVE_XEN_PLATFORM_COMPAT_H +#include <xen/platform-compat.h> +#endif /* xenbus_probe.c */ extern char *kasprintf(const char *fmt, ...); diff -r d246b79986d1 -r 3e26719ab827 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/synch_bitops.h --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/synch_bitops.h Tue Oct 24 11:21:48 2006 -0600 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/synch_bitops.h Wed Oct 25 12:12:01 2006 -0600 @@ -8,6 +8,10 @@ */ #include <linux/config.h> + +#ifdef HAVE_XEN_PLATFORM_COMPAT_H +#include <xen/platform-compat.h> +#endif #define ADDR (*(volatile long *) addr) diff -r d246b79986d1 -r 3e26719ab827 linux-2.6-xen-sparse/include/xen/xenbus.h --- a/linux-2.6-xen-sparse/include/xen/xenbus.h Tue Oct 24 11:21:48 2006 -0600 +++ b/linux-2.6-xen-sparse/include/xen/xenbus.h Wed Oct 25 12:12:01 2006 -0600 @@ -38,6 +38,7 @@ #include <linux/notifier.h> #include <linux/mutex.h> #include <linux/completion.h> +#include <linux/init.h> #include <xen/interface/xen.h> #include <xen/interface/grant_table.h> #include <xen/interface/io/xenbus.h> diff -r d246b79986d1 -r 3e26719ab827 tools/blktap/drivers/blktapctrl.c --- a/tools/blktap/drivers/blktapctrl.c Tue Oct 24 11:21:48 2006 -0600 +++ b/tools/blktap/drivers/blktapctrl.c Wed Oct 25 12:12:01 2006 -0600 @@ -204,81 +204,49 @@ static blkif_t *test_path(char *path, ch static void add_disktype(blkif_t *blkif, int type) { - driver_list_entry_t *entry, *ptr, *last; - - if (type > MAX_DISK_TYPES) return; + driver_list_entry_t *entry, **pprev; + + if (type > MAX_DISK_TYPES) + return; entry = malloc(sizeof(driver_list_entry_t)); entry->blkif = blkif; - entry->next = NULL; - ptr = active_disks[type]; - - if (ptr == NULL) { - active_disks[type] = entry; - entry->prev = NULL; - return; - } - - while (ptr != NULL) { - last = ptr; - ptr = ptr->next; - } - - /*We've found the end of the list*/ - last->next = entry; - entry->prev = last; - - return; + entry->next = NULL; + + pprev = &active_disks[type]; + while (*pprev != NULL) + pprev = &(*pprev)->next; + + *pprev = entry; + entry->pprev = pprev; } static int del_disktype(blkif_t *blkif) { - driver_list_entry_t *ptr, *cur, *last; + driver_list_entry_t *entry, **pprev; int type = blkif->drivertype, count = 0, close = 0; - if (type > MAX_DISK_TYPES) return 1; - - ptr = active_disks[type]; - last = NULL; - while (ptr != NULL) { - count++; - if (blkif == ptr->blkif) { - cur = ptr; - if (ptr->next != NULL) { - /*There's more later in the chain*/ - if (!last) { - /*We're first in the list*/ - active_disks[type] = ptr->next; - ptr = ptr->next; - ptr->prev = NULL; - } - else { - /*We're sandwiched*/ - last->next = ptr->next; - ptr = ptr->next; - ptr->prev = last; - } - - } else if (last) { - /*There's more earlier in the chain*/ - last->next = NULL; - } else { - /*We're the only entry*/ - active_disks[type] = NULL; - if(dtypes[type]->single_handler == 1) - close = 1; - } - DPRINTF("DEL_DISKTYPE: Freeing entry\n"); - free(cur); - if (dtypes[type]->single_handler == 0) close = 1; - - return close; - } - last = ptr; - ptr = ptr->next; - } - DPRINTF("DEL_DISKTYPE: No match\n"); - return 1; + if (type > MAX_DISK_TYPES) + return 1; + + pprev = &active_disks[type]; + while ((*pprev != NULL) && ((*pprev)->blkif != blkif)) + pprev = &(*pprev)->next; + + if ((entry = *pprev) == NULL) { + DPRINTF("DEL_DISKTYPE: No match\n"); + return 1; + } + + *pprev = entry->next; + if (entry->next) + entry->next->pprev = pprev; + + DPRINTF("DEL_DISKTYPE: Freeing entry\n"); + free(entry); + + /* Caller should close() if no single controller, or list is empty. */ + return (!dtypes[type]->single_handler || (active_disks[type] == NULL)); } static int write_msg(int fd, int msgtype, void *ptr, void *ptr2) @@ -592,8 +560,8 @@ int unmap_blktapctrl(blkif_t *blkif) if (del_disktype(blkif)) { close(blkif->fds[WRITE]); close(blkif->fds[READ]); - - } + } + return 0; } diff -r d246b79986d1 -r 3e26719ab827 tools/blktap/drivers/tapdisk.c --- a/tools/blktap/drivers/tapdisk.c Tue Oct 24 11:21:48 2006 -0600 +++ b/tools/blktap/drivers/tapdisk.c Wed Oct 25 12:12:01 2006 -0600 @@ -79,31 +79,17 @@ static void unmap_disk(struct td_state * { tapdev_info_t *info = s->ring_info; struct tap_disk *drv = s->drv; - fd_list_entry_t *ptr, *prev; + fd_list_entry_t *entry; drv->td_close(s); if (info != NULL && info->mem > 0) munmap(info->mem, getpagesize() * BLKTAP_MMAP_REGION_SIZE); - ptr = s->fd_entry; - prev = ptr->prev; - - if (prev) { - /*There are entries earlier in the list*/ - prev->next = ptr->next; - if (ptr->next) { - ptr = ptr->next; - ptr->prev = prev; - } - } else { - /*We are the first entry in list*/ - if (ptr->next) { - ptr = ptr->next; - fd_start = ptr; - ptr->prev = NULL; - } else fd_start = NULL; - } + entry = s->fd_entry; + *entry->pprev = entry->next; + if (entry->next) + entry->next->pprev = entry->pprev; close(info->fd); @@ -144,35 +130,29 @@ static inline int LOCAL_FD_SET(fd_set *r return 0; } -static inline fd_list_entry_t *add_fd_entry(int tap_fd, int io_fd[MAX_IOFD], struct td_state *s) -{ - fd_list_entry_t *ptr, *last, *entry; +static inline fd_list_entry_t *add_fd_entry( + int tap_fd, int io_fd[MAX_IOFD], struct td_state *s) +{ + fd_list_entry_t **pprev, *entry; int i; + DPRINTF("Adding fd_list_entry\n"); /*Add to linked list*/ s->fd_entry = entry = malloc(sizeof(fd_list_entry_t)); entry->tap_fd = tap_fd; - for (i = 0; i < MAX_IOFD; i++) entry->io_fd[i] = io_fd[i]; + for (i = 0; i < MAX_IOFD; i++) + entry->io_fd[i] = io_fd[i]; entry->s = s; entry->next = NULL; - ptr = fd_start; - if (ptr == NULL) { - /*We are the first entry*/ - fd_start = entry; - entry->prev = NULL; - goto finish; - } - - while (ptr != NULL) { - last = ptr; - ptr = ptr->next; - } - last->next = entry; - entry->prev = last; - - finish: + pprev = &fd_start; + while (*pprev != NULL) + pprev = &(*pprev)->next; + + *pprev = entry; + entry->pprev = pprev; + return entry; } diff -r d246b79986d1 -r 3e26719ab827 tools/blktap/drivers/tapdisk.h --- a/tools/blktap/drivers/tapdisk.h Tue Oct 24 11:21:48 2006 -0600 +++ b/tools/blktap/drivers/tapdisk.h Wed Oct 25 12:12:01 2006 -0600 @@ -191,9 +191,8 @@ static disk_info_t *dtypes[] = { }; typedef struct driver_list_entry { - void *blkif; - void *prev; - void *next; + struct blkif *blkif; + struct driver_list_entry **pprev, *next; } driver_list_entry_t; typedef struct fd_list_entry { @@ -201,8 +200,7 @@ typedef struct fd_list_entry { int tap_fd; int io_fd[MAX_IOFD]; struct td_state *s; - void *prev; - void *next; + struct fd_list_entry **pprev, *next; } fd_list_entry_t; int qcow_create(const char *filename, uint64_t total_size, diff -r d246b79986d1 -r 3e26719ab827 tools/firmware/acpi/acpi_fadt.h --- a/tools/firmware/acpi/acpi_fadt.h Tue Oct 24 11:21:48 2006 -0600 +++ b/tools/firmware/acpi/acpi_fadt.h Wed Oct 25 12:12:01 2006 -0600 @@ -17,6 +17,8 @@ */ #ifndef _FADT_H_ #define _FADT_H_ + +#include <xen/hvm/ioreq.h> // // FADT Definitions, see ACPI 2.0 specification for details. @@ -51,7 +53,9 @@ // // Fixed Feature Flags // -#define ACPI_FIXED_FEATURE_FLAGS (ACPI_PROC_C1|ACPI_SLP_BUTTON|ACPI_WBINVD|ACPI_PWR_BUTTON|ACPI_FIX_RTC) +#define ACPI_FIXED_FEATURE_FLAGS (ACPI_PROC_C1 | ACPI_SLP_BUTTON | \ + ACPI_WBINVD | ACPI_PWR_BUTTON | \ + ACPI_FIX_RTC | ACPI_TMR_VAL_EXT) // // PM1A Event Register Block Generic Address Information @@ -59,7 +63,6 @@ #define ACPI_PM1A_EVT_BLK_ADDRESS_SPACE_ID ACPI_SYSTEM_IO #define ACPI_PM1A_EVT_BLK_BIT_WIDTH 0x20 #define ACPI_PM1A_EVT_BLK_BIT_OFFSET 0x00 -#define ACPI_PM1A_EVT_BLK_ADDRESS 0x000000000000c010 // // PM1B Event Register Block Generic Address Information @@ -75,7 +78,6 @@ #define ACPI_PM1A_CNT_BLK_ADDRESS_SPACE_ID ACPI_SYSTEM_IO #define ACPI_PM1A_CNT_BLK_BIT_WIDTH 0x10 #define ACPI_PM1A_CNT_BLK_BIT_OFFSET 0x00 -#define ACPI_PM1A_CNT_BLK_ADDRESS (ACPI_PM1A_EVT_BLK_ADDRESS + 0x04) // // PM1B Control Register Block Generic Address Information @@ -100,7 +102,6 @@ #define ACPI_PM_TMR_BLK_ADDRESS_SPACE_ID ACPI_SYSTEM_IO #define ACPI_PM_TMR_BLK_BIT_WIDTH 0x20 #define ACPI_PM_TMR_BLK_BIT_OFFSET 0x00 -#define ACPI_PM_TMR_BLK_ADDRESS (ACPI_PM1A_EVT_BLK_ADDRESS + 0x08) // // General Purpose Event 0 Register Block Generic Address diff -r d246b79986d1 -r 3e26719ab827 tools/ioemu/vl.c --- a/tools/ioemu/vl.c Tue Oct 24 11:21:48 2006 -0600 +++ b/tools/ioemu/vl.c Wed Oct 25 12:12:01 2006 -0600 @@ -6448,7 +6448,6 @@ int main(int argc, char **argv) fprintf(logfile, "shared page at pfn:%lx, mfn: %"PRIx64"\n", shared_page_nr, (uint64_t)(page_array[shared_page_nr])); - /* not yet add for IA64 */ buffered_io_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE, PROT_READ|PROT_WRITE, page_array[shared_page_nr - 2]); @@ -6465,7 +6464,7 @@ int main(int argc, char **argv) #elif defined(__ia64__) if (xc_ia64_get_pfn_list(xc_handle, domid, page_array, - IO_PAGE_START >> PAGE_SHIFT, 1) != 1) { + IO_PAGE_START >> PAGE_SHIFT, 3) != 3) { fprintf(logfile, "xc_ia64_get_pfn_list returned error %d\n", errno); exit(-1); } @@ -6476,6 +6475,12 @@ int main(int argc, char **argv) fprintf(logfile, "shared page at pfn:%lx, mfn: %016lx\n", IO_PAGE_START >> PAGE_SHIFT, page_array[0]); + + buffered_io_page =xc_map_foreign_range(xc_handle, domid, PAGE_SIZE, + PROT_READ|PROT_WRITE, + page_array[2]); + fprintf(logfile, "Buffered IO page at pfn:%lx, mfn: %016lx\n", + BUFFER_IO_PAGE_START >> PAGE_SHIFT, page_array[2]); if (xc_ia64_get_pfn_list(xc_handle, domid, page_array, 0, nr_pages) != nr_pages) { @@ -6496,6 +6501,7 @@ int main(int argc, char **argv) fprintf(logfile, "xc_map_foreign_batch returned error %d\n", errno); exit(-1); } + free(page_array); #endif #else /* !CONFIG_DM */ diff -r d246b79986d1 -r 3e26719ab827 tools/ioemu/vnc.c --- a/tools/ioemu/vnc.c Tue Oct 24 11:21:48 2006 -0600 +++ b/tools/ioemu/vnc.c Wed Oct 25 12:12:01 2006 -0600 @@ -203,6 +203,8 @@ static void set_bits_in_row(VncState *vs mask = ~(0ULL); h += y; + if (h > vs->ds->height) + h = vs->ds->height; for (; y < h; y++) row[y] |= mask; } diff -r d246b79986d1 -r 3e26719ab827 tools/libxc/Makefile --- a/tools/libxc/Makefile Tue Oct 24 11:21:48 2006 -0600 +++ b/tools/libxc/Makefile Wed Oct 25 12:12:01 2006 -0600 @@ -31,7 +31,7 @@ GUEST_SRCS-$(CONFIG_HVM) += xc_hvm_build -include $(XEN_TARGET_ARCH)/Makefile -CFLAGS += -Werror +CFLAGS += -Werror -Wmissing-prototypes CFLAGS += -fno-strict-aliasing CFLAGS += $(INCLUDES) -I. diff -r d246b79986d1 -r 3e26719ab827 tools/libxc/ia64/xc_ia64_hvm_build.c --- a/tools/libxc/ia64/xc_ia64_hvm_build.c Tue Oct 24 11:21:48 2006 -0600 +++ b/tools/libxc/ia64/xc_ia64_hvm_build.c Wed Oct 25 12:12:01 2006 -0600 @@ -551,8 +551,9 @@ setup_guest(int xc_handle, uint32_t dom, char *image, unsigned long image_size, uint32_t vcpus, unsigned int store_evtchn, unsigned long *store_mfn) { - unsigned long page_array[2]; + unsigned long page_array[3]; shared_iopage_t *sp; + void *ioreq_buffer_page; unsigned long dom_memsize = (memsize << 20); DECLARE_DOMCTL; @@ -587,7 +588,7 @@ setup_guest(int xc_handle, uint32_t dom, /* Retrieve special pages like io, xenstore, etc. */ if (xc_ia64_get_pfn_list(xc_handle, dom, page_array, - IO_PAGE_START>>PAGE_SHIFT, 2) != 2) { + IO_PAGE_START>>PAGE_SHIFT, 3) != 3) { PERROR("Could not get the page frame list"); goto error_out; } @@ -604,7 +605,10 @@ setup_guest(int xc_handle, uint32_t dom, memset(sp, 0, PAGE_SIZE); munmap(sp, PAGE_SIZE); - + ioreq_buffer_page = xc_map_foreign_range(xc_handle, dom, + PAGE_SIZE, PROT_READ|PROT_WRITE, page_array[2]); + memset(ioreq_buffer_page,0,PAGE_SIZE); + munmap(ioreq_buffer_page, PAGE_SIZE); return 0; error_out: diff -r d246b79986d1 -r 3e26719ab827 tools/libxc/xc_linux_build.c --- a/tools/libxc/xc_linux_build.c Tue Oct 24 11:21:48 2006 -0600 +++ b/tools/libxc/xc_linux_build.c Wed Oct 25 12:12:01 2006 -0600 @@ -128,7 +128,7 @@ static int probeimageformat(const char * return 0; } -int load_initrd(int xc_handle, domid_t dom, +static int load_initrd(int xc_handle, domid_t dom, struct initrd_info *initrd, unsigned long physbase, xen_pfn_t *phys_to_mach) diff -r d246b79986d1 -r 3e26719ab827 tools/libxc/xc_linux_restore.c --- a/tools/libxc/xc_linux_restore.c Tue Oct 24 11:21:48 2006 -0600 +++ b/tools/libxc/xc_linux_restore.c Wed Oct 25 12:12:01 2006 -0600 @@ -57,7 +57,7 @@ read_exact(int fd, void *buf, size_t cou ** This function inverts that operation, replacing the pfn values with ** the (now known) appropriate mfn values. */ -int uncanonicalize_pagetable(unsigned long type, void *page) +static int uncanonicalize_pagetable(unsigned long type, void *page) { int i, pte_last; unsigned long pfn; diff -r d246b79986d1 -r 3e26719ab827 tools/libxc/xc_linux_save.c --- a/tools/libxc/xc_linux_save.c Tue Oct 24 11:21:48 2006 -0600 +++ b/tools/libxc/xc_linux_save.c Wed Oct 25 12:12:01 2006 -0600 @@ -413,7 +413,7 @@ static int suspend_and_state(int (*suspe ** which entries do not require canonicalization (in particular, those ** entries which map the virtual address reserved for the hypervisor). */ -int canonicalize_pagetable(unsigned long type, unsigned long pfn, +static int canonicalize_pagetable(unsigned long type, unsigned long pfn, const void *spage, void *dpage) { diff -r d246b79986d1 -r 3e26719ab827 tools/libxc/xc_private.c --- a/tools/libxc/xc_private.c Tue Oct 24 11:21:48 2006 -0600 +++ b/tools/libxc/xc_private.c Wed Oct 25 12:12:01 2006 -0600 @@ -6,6 +6,7 @@ #include <inttypes.h> #include "xc_private.h" +#include "xg_private.h" int lock_pages(void *addr, size_t len) { @@ -33,23 +34,6 @@ int xc_get_pfn_type_batch(int xc_handle, domctl.u.getpageframeinfo2.num = num; set_xen_guest_handle(domctl.u.getpageframeinfo2.array, arr); return do_domctl(xc_handle, &domctl); -} - -#define GETPFN_ERR (~0U) -unsigned int get_pfn_type(int xc_handle, - unsigned long mfn, - uint32_t dom) -{ - DECLARE_DOMCTL; - domctl.cmd = XEN_DOMCTL_getpageframeinfo; - domctl.u.getpageframeinfo.gmfn = mfn; - domctl.domain = (domid_t)dom; - if ( do_domctl(xc_handle, &domctl) < 0 ) - { - PERROR("Unexpected failure when getting page frame info!"); - return GETPFN_ERR; - } - return domctl.u.getpageframeinfo.type; } int xc_mmuext_op( diff -r d246b79986d1 -r 3e26719ab827 tools/python/xen/xend/image.py --- a/tools/python/xen/xend/image.py Tue Oct 24 11:21:48 2006 -0600 +++ b/tools/python/xen/xend/image.py Wed Oct 25 12:12:01 2006 -0600 @@ -471,7 +471,7 @@ class IA64_HVM_ImageHandler(HVMImageHand def getRequiredAvailableMemory(self, mem_kb): page_kb = 16 # ROM size for guest firmware, ioreq page and xenstore page - extra_pages = 1024 + 2 + extra_pages = 1024 + 3 return mem_kb + extra_pages * page_kb def getRequiredShadowMemory(self, shadow_mem_kb, maxmem_kb): @@ -500,9 +500,12 @@ class X86_HVM_ImageHandler(HVMImageHandl # overhead due to getRequiredInitialReservation. maxmem_kb = self.getRequiredInitialReservation(maxmem_kb) - # 1MB per vcpu plus 4Kib/Mib of RAM. This is higher than - # the minimum that Xen would allocate if no value were given. - return max(1024 * self.vm.getVCpuCount() + maxmem_kb / 256, + # 256 pages (1MB) per vcpu, + # plus 1 page per MiB of RAM for the P2M map, + # plus 1 page per MiB of RAM to shadow the resident processes. + # This is higher than the minimum that Xen would allocate if no value + # were given (but the Xen minimum is for safety, not performance). + return max(4 * (256 * self.vm.getVCpuCount() + 2 * (maxmem_kb / 1024)), shadow_mem_kb) diff -r d246b79986d1 -r 3e26719ab827 tools/python/xen/xend/server/SrvDaemon.py --- a/tools/python/xen/xend/server/SrvDaemon.py Tue Oct 24 11:21:48 2006 -0600 +++ b/tools/python/xen/xend/server/SrvDaemon.py Wed Oct 25 12:12:01 2006 -0600 @@ -9,6 +9,7 @@ import signal import signal import sys import threading +import time import linecache import pwd import re @@ -106,12 +107,14 @@ class Daemon: os.close(2) if XEND_DEBUG: os.open('/dev/null', os.O_RDONLY) - os.open(XEND_DEBUG_LOG, os.O_WRONLY|os.O_CREAT) + os.open(XEND_DEBUG_LOG, os.O_WRONLY|os.O_CREAT|os.O_APPEND) os.dup(1) else: os.open('/dev/null', os.O_RDWR) os.dup(0) - os.open(XEND_DEBUG_LOG, os.O_WRONLY|os.O_CREAT) + os.open(XEND_DEBUG_LOG, os.O_WRONLY|os.O_CREAT|os.O_APPEND) + print >>sys.stderr, ("Xend started at %s." % + time.asctime(time.localtime())) def start(self, trace=0): diff -r d246b79986d1 -r 3e26719ab827 tools/xenstat/xentop/xentop.1 --- a/tools/xenstat/xentop/xentop.1 Tue Oct 24 11:21:48 2006 -0600 +++ b/tools/xenstat/xentop/xentop.1 Wed Oct 25 12:12:01 2006 -0600 @@ -47,6 +47,9 @@ seconds between updates (default 3) \fB\-n\fR, \fB\-\-networks\fR output network information .TP +\fB\-x\fR, \fB\-\-vbds\fR +output vbd block device data +.TP \fB\-r\fR, \fB\-\-repeat\-header\fR repeat table header before each domain .TP diff -r d246b79986d1 -r 3e26719ab827 tools/xenstat/xentop/xentop.c --- a/tools/xenstat/xentop/xentop.c Tue Oct 24 11:21:48 2006 -0600 +++ b/tools/xenstat/xentop/xentop.c Wed Oct 25 12:12:01 2006 -0600 @@ -204,7 +204,7 @@ static void usage(const char *program) "-V, --version output version information and exit\n" "-d, --delay=SECONDS seconds between updates (default 3)\n" "-n, --networks output vif network data\n" - "-b, --vbds output vbd block device data\n" + "-x, --vbds output vbd block device data\n" "-r, --repeat-header repeat table header before each domain\n" "-v, --vcpus output vcpu data\n" "-b, --batch output in batch mode, no user input accepted\n" @@ -976,7 +976,7 @@ int main(int argc, char **argv) { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'V' }, { "networks", no_argument, NULL, 'n' }, - { "vbds", no_argument, NULL, 'x' }, + { "vbds", no_argument, NULL, 'x' }, { "repeat-header", no_argument, NULL, 'r' }, { "vcpus", no_argument, NULL, 'v' }, { "delay", required_argument, NULL, 'd' }, @@ -1065,7 +1065,7 @@ int main(int argc, char **argv) break; } while (1); } - + /* Cleanup occurs in cleanup(), so no work to do here. */ return 0; diff -r d246b79986d1 -r 3e26719ab827 tools/xm-test/lib/XmTestLib/arch.py --- a/tools/xm-test/lib/XmTestLib/arch.py Tue Oct 24 11:21:48 2006 -0600 +++ b/tools/xm-test/lib/XmTestLib/arch.py Wed Oct 25 12:12:01 2006 -0600 @@ -124,6 +124,7 @@ _uname_to_arch_map = { "i486" : "x86", "i586" : "x86", "i686" : "x86", + "x86_64": "x86_64", "ia64" : "ia64", "ppc" : "powerpc", "ppc64" : "powerpc", @@ -131,7 +132,7 @@ _uname_to_arch_map = { # Lookup current platform. _arch = _uname_to_arch_map.get(os.uname()[4], "Unknown") -if _arch == "x86" or _arch == "ia64": +if _arch == "x86" or _arch == "x86_64" or _arch == "ia64": minSafeMem = ia_minSafeMem getDefaultKernel = ia_getDefaultKernel checkBuffer = ia_checkBuffer diff -r d246b79986d1 -r 3e26719ab827 unmodified_drivers/linux-2.6/overrides.mk --- a/unmodified_drivers/linux-2.6/overrides.mk Tue Oct 24 11:21:48 2006 -0600 +++ b/unmodified_drivers/linux-2.6/overrides.mk Wed Oct 25 12:12:01 2006 -0600 @@ -9,4 +9,4 @@ EXTRA_CFLAGS += -DCONFIG_XEN_BLKDEV_GRAN EXTRA_CFLAGS += -DCONFIG_XEN_BLKDEV_GRANT -DXEN_EVTCHN_MASK_OPS EXTRA_CFLAGS += -DCONFIG_XEN_NETDEV_GRANT_RX -DCONFIG_XEN_NETDEV_GRANT_TX EXTRA_CFLAGS += -D__XEN_INTERFACE_VERSION__=0x00030202 -EXTRA_CFLAGS += -I$(M)/include +EXTRA_CFLAGS += -I$(M)/include -I$(M)/compat-include -DHAVE_XEN_PLATFORM_COMPAT_H diff -r d246b79986d1 -r 3e26719ab827 unmodified_drivers/linux-2.6/platform-pci/Kbuild --- a/unmodified_drivers/linux-2.6/platform-pci/Kbuild Tue Oct 24 11:21:48 2006 -0600 +++ b/unmodified_drivers/linux-2.6/platform-pci/Kbuild Wed Oct 25 12:12:01 2006 -0600 @@ -4,7 +4,7 @@ obj-m := xen-platform-pci.o EXTRA_CFLAGS += -I$(M)/platform-pci -xen-platform-pci-objs := evtchn.o platform-pci.o gnttab.o xen_support.o features.o +xen-platform-pci-objs := evtchn.o platform-pci.o gnttab.o xen_support.o features.o platform-compat.o # Can we do better ? ifeq ($(ARCH),ia64) diff -r d246b79986d1 -r 3e26719ab827 unmodified_drivers/linux-2.6/platform-pci/evtchn.c --- a/unmodified_drivers/linux-2.6/platform-pci/evtchn.c Tue Oct 24 11:21:48 2006 -0600 +++ b/unmodified_drivers/linux-2.6/platform-pci/evtchn.c Wed Oct 25 12:12:01 2006 -0600 @@ -35,6 +35,10 @@ #include <xen/interface/hvm/ioreq.h> #include <xen/features.h> #include "platform-pci.h" + +#ifdef HAVE_XEN_PLATFORM_COMPAT_H +#include <xen/platform-compat.h> +#endif void *shared_info_area; diff -r d246b79986d1 -r 3e26719ab827 unmodified_drivers/linux-2.6/platform-pci/platform-pci.c --- a/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c Tue Oct 24 11:21:48 2006 -0600 +++ b/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c Wed Oct 25 12:12:01 2006 -0600 @@ -33,6 +33,7 @@ #include <asm/irq.h> #include <asm/uaccess.h> #include <asm/hypervisor.h> +#include <asm/pgtable.h> #include <xen/interface/memory.h> #include <xen/features.h> #ifdef __ia64__ @@ -40,6 +41,10 @@ #endif #include "platform-pci.h" + +#ifdef HAVE_XEN_PLATFORM_COMPAT_H +#include <xen/platform-compat.h> +#endif #define DRV_NAME "xen-platform-pci" #define DRV_VERSION "0.10" diff -r d246b79986d1 -r 3e26719ab827 unmodified_drivers/linux-2.6/platform-pci/xen_support.c --- a/unmodified_drivers/linux-2.6/platform-pci/xen_support.c Tue Oct 24 11:21:48 2006 -0600 +++ b/unmodified_drivers/linux-2.6/platform-pci/xen_support.c Wed Oct 25 12:12:01 2006 -0600 @@ -26,6 +26,10 @@ #include <asm/hypervisor.h> #include "platform-pci.h" +#ifdef HAVE_XEN_PLATFORM_COMPAT_H +#include <xen/platform-compat.h> +#endif + void xen_machphys_update(unsigned long mfn, unsigned long pfn) { BUG(); diff -r d246b79986d1 -r 3e26719ab827 xen/arch/ia64/vmx/mmio.c --- a/xen/arch/ia64/vmx/mmio.c Tue Oct 24 11:21:48 2006 -0600 +++ b/xen/arch/ia64/vmx/mmio.c Wed Oct 25 12:12:01 2006 -0600 @@ -52,6 +52,70 @@ struct mmio_list *lookup_mmio(u64 gpa, s #define PIB_OFST_INTA 0x1E0000 #define PIB_OFST_XTP 0x1E0008 +#define HVM_BUFFERED_IO_RANGE_NR 1 + +struct hvm_buffered_io_range { + unsigned long start_addr; + unsigned long length; +}; + +static struct hvm_buffered_io_range buffered_stdvga_range = {0xA0000, 0x20000}; +static struct hvm_buffered_io_range +*hvm_buffered_io_ranges[HVM_BUFFERED_IO_RANGE_NR] = +{ + &buffered_stdvga_range +}; + +int hvm_buffered_io_intercept(ioreq_t *p) +{ + struct vcpu *v = current; + spinlock_t *buffered_io_lock; + buffered_iopage_t *buffered_iopage = + (buffered_iopage_t *)(v->domain->arch.hvm_domain.buffered_io_va); + unsigned long tmp_write_pointer = 0; + int i; + + /* ignore READ ioreq_t! */ + if ( p->dir == IOREQ_READ ) + return 0; + + for ( i = 0; i < HVM_BUFFERED_IO_RANGE_NR; i++ ) { + if ( p->addr >= hvm_buffered_io_ranges[i]->start_addr && + p->addr + p->size - 1 < hvm_buffered_io_ranges[i]->start_addr + + hvm_buffered_io_ranges[i]->length ) + break; + } + + if ( i == HVM_BUFFERED_IO_RANGE_NR ) + return 0; + + buffered_io_lock = &v->domain->arch.hvm_domain.buffered_io_lock; + spin_lock(buffered_io_lock); + + if ( buffered_iopage->write_pointer - buffered_iopage->read_pointer == + (unsigned long)IOREQ_BUFFER_SLOT_NUM ) { + /* the queue is full. + * send the iopacket through the normal path. + * NOTE: The arithimetic operation could handle the situation for + * write_pointer overflow. + */ + spin_unlock(buffered_io_lock); + return 0; + } + + tmp_write_pointer = buffered_iopage->write_pointer % IOREQ_BUFFER_SLOT_NUM; + + memcpy(&buffered_iopage->ioreq[tmp_write_pointer], p, sizeof(ioreq_t)); + + /*make the ioreq_t visible before write_pointer*/ + wmb(); + buffered_iopage->write_pointer++; + + spin_unlock(buffered_io_lock); + + return 1; +} + static void write_ipi (VCPU *vcpu, uint64_t addr, uint64_t value); static void pib_write(VCPU *vcpu, void *src, uint64_t pib_off, size_t s, int ma) @@ -156,7 +220,11 @@ static void low_mmio_access(VCPU *vcpu, p->df = 0; p->io_count++; - + if(hvm_buffered_io_intercept(p)){ + p->state = STATE_IORESP_READY; + vmx_io_assist(v); + return ; + }else vmx_send_assist_req(v); if(dir==IOREQ_READ){ //read *val=p->u.data; diff -r d246b79986d1 -r 3e26719ab827 xen/arch/ia64/vmx/vmx_init.c --- a/xen/arch/ia64/vmx/vmx_init.c Tue Oct 24 11:21:48 2006 -0600 +++ b/xen/arch/ia64/vmx/vmx_init.c Wed Oct 25 12:12:01 2006 -0600 @@ -362,8 +362,8 @@ static const io_range_t io_ranges[] = { {PIB_START, PIB_SIZE, GPFN_PIB}, }; -/* Reseve 1 page for shared I/O and 1 page for xenstore. */ -#define VMX_SYS_PAGES (2 + (GFW_SIZE >> PAGE_SHIFT)) +/* Reseve 1 page for shared I/O ,1 page for xenstore and 1 page for buffer I/O. */ +#define VMX_SYS_PAGES (3 + (GFW_SIZE >> PAGE_SHIFT)) #define VMX_CONFIG_PAGES(d) ((d)->max_pages - VMX_SYS_PAGES) static void vmx_build_physmap_table(struct domain *d) @@ -425,8 +425,12 @@ static void vmx_build_physmap_table(stru mfn = page_to_mfn(list_entry(list_ent, struct page_info, list)); assign_domain_page(d, STORE_PAGE_START, mfn << PAGE_SHIFT); list_ent = mfn_to_page(mfn)->list.next; + ASSERT(list_ent != &d->page_list); + + mfn = page_to_mfn(list_entry(list_ent, struct page_info, list)); + assign_domain_page(d, BUFFER_IO_PAGE_START, mfn << PAGE_SHIFT); + list_ent = mfn_to_page(mfn)->list.next; ASSERT(list_ent == &d->page_list); - } void vmx_setup_platform(struct domain *d) @@ -437,6 +441,10 @@ void vmx_setup_platform(struct domain *d d->arch.vmx_platform.shared_page_va = (unsigned long)__va(__gpa_to_mpa(d, IO_PAGE_START)); + //For buffered IO requests. + spin_lock_init(&d->arch.hvm_domain.buffered_io_lock); + d->arch.hvm_domain.buffered_io_va = + (unsigned long)__va(__gpa_to_mpa(d, BUFFER_IO_PAGE_START)); /* TEMP */ d->arch.vmx_platform.pib_base = 0xfee00000UL; diff -r d246b79986d1 -r 3e26719ab827 xen/arch/x86/Makefile --- a/xen/arch/x86/Makefile Tue Oct 24 11:21:48 2006 -0600 +++ b/xen/arch/x86/Makefile Wed Oct 25 12:12:01 2006 -0600 @@ -28,12 +28,14 @@ obj-y += mm.o obj-y += mm.o obj-y += mpparse.o obj-y += nmi.o +obj-y += numa.o obj-y += physdev.o obj-y += rwlock.o obj-y += setup.o obj-y += shutdown.o obj-y += smp.o obj-y += smpboot.o +obj-y += srat.o obj-y += string.o obj-y += sysctl.o obj-y += time.o diff -r d246b79986d1 -r 3e26719ab827 xen/arch/x86/hvm/Makefile --- a/xen/arch/x86/hvm/Makefile Tue Oct 24 11:21:48 2006 -0600 +++ b/xen/arch/x86/hvm/Makefile Wed Oct 25 12:12:01 2006 -0600 @@ -5,6 +5,7 @@ obj-y += i8254.o obj-y += i8254.o obj-y += i8259.o obj-y += rtc.o +obj-y += pmtimer.o obj-y += instrlen.o obj-y += intercept.o obj-y += io.o diff -r d246b79986d1 -r 3e26719ab827 xen/arch/x86/hvm/hvm.c --- a/xen/arch/x86/hvm/hvm.c Tue Oct 24 11:21:48 2006 -0600 +++ b/xen/arch/x86/hvm/hvm.c Wed Oct 25 12:12:01 2006 -0600 @@ -43,7 +43,7 @@ #include <asm/mc146818rtc.h> #include <asm/spinlock.h> #include <asm/hvm/hvm.h> -#include <asm/hvm/vpit.h> +#include <asm/hvm/vpt.h> #include <asm/hvm/support.h> #include <public/sched.h> #include <public/hvm/ioreq.h> @@ -285,6 +285,7 @@ void hvm_setup_platform(struct domain* d pt_timer_fn, v, v->processor); pit_init(v, cpu_khz); rtc_init(v, RTC_PORT(0), RTC_IRQ); + pmtimer_init(v, ACPI_PM_TMR_BLK_ADDRESS); } void pic_irq_request(void *data, int level) diff -r d246b79986d1 -r 3e26719ab827 xen/arch/x86/hvm/i8254.c --- a/xen/arch/x86/hvm/i8254.c Tue Oct 24 11:21:48 2006 -0600 +++ b/xen/arch/x86/hvm/i8254.c Wed Oct 25 12:12:01 2006 -0600 @@ -38,7 +38,7 @@ #include <asm/hvm/hvm.h> #include <asm/hvm/io.h> #include <asm/hvm/support.h> -#include <asm/hvm/vpit.h> +#include <asm/hvm/vpt.h> #include <asm/current.h> /* Enable DEBUG_PIT may cause guest calibration inaccuracy */ diff -r d246b79986d1 -r 3e26719ab827 xen/arch/x86/hvm/io.c --- a/xen/arch/x86/hvm/io.c Tue Oct 24 11:21:48 2006 -0600 +++ b/xen/arch/x86/hvm/io.c Wed Oct 25 12:12:01 2006 -0600 @@ -35,7 +35,7 @@ #include <asm/shadow.h> #include <asm/hvm/hvm.h> #include <asm/hvm/support.h> -#include <asm/hvm/vpit.h> +#include <asm/hvm/vpt.h> #include <asm/hvm/vpic.h> #include <asm/hvm/vlapic.h> diff -r d246b79986d1 -r 3e26719ab827 xen/arch/x86/hvm/rtc.c --- a/xen/arch/x86/hvm/rtc.c Tue Oct 24 11:21:48 2006 -0600 +++ b/xen/arch/x86/hvm/rtc.c Wed Oct 25 12:12:01 2006 -0600 @@ -23,7 +23,7 @@ */ #include <asm/mc146818rtc.h> -#include <asm/hvm/vpit.h> +#include <asm/hvm/vpt.h> #include <asm/hvm/io.h> #include <asm/hvm/support.h> #include <asm/current.h> diff -r d246b79986d1 -r 3e26719ab827 xen/arch/x86/hvm/svm/svm.c --- a/xen/arch/x86/hvm/svm/svm.c Tue Oct 24 11:21:48 2006 -0600 +++ b/xen/arch/x86/hvm/svm/svm.c Wed Oct 25 12:12:01 2006 -0600 @@ -922,6 +922,7 @@ static void svm_relinquish_guest_resourc kill_timer(&d->arch.hvm_domain.pl_time.periodic_tm.timer); rtc_deinit(d); + pmtimer_deinit(d); if ( d->arch.hvm_domain.shared_page_va ) unmap_domain_page_global( @@ -937,6 +938,7 @@ static void svm_migrate_timers(struct vc struct periodic_time *pt = &(v->domain->arch.hvm_domain.pl_time.periodic_tm); struct RTCState *vrtc = &v->domain->arch.hvm_domain.pl_time.vrtc; + struct PMTState *vpmt = &v->domain->arch.hvm_domain.pl_time.vpmt; if ( pt->enabled ) { @@ -947,6 +949,7 @@ static void svm_migrate_timers(struct vc migrate_timer(&VLAPIC(v)->vlapic_timer, v->processor); migrate_timer(&vrtc->second_timer, v->processor); migrate_timer(&vrtc->second_timer2, v->processor); + migrate_timer(&vpmt->timer, v->processor); } diff -r d246b79986d1 -r 3e26719ab827 xen/arch/x86/hvm/vmx/vmx.c --- a/xen/arch/x86/hvm/vmx/vmx.c Tue Oct 24 11:21:48 2006 -0600 +++ b/xen/arch/x86/hvm/vmx/vmx.c Wed Oct 25 12:12:01 2006 -0600 @@ -147,6 +147,7 @@ static void vmx_relinquish_guest_resourc kill_timer(&d->arch.hvm_domain.pl_time.periodic_tm.timer); rtc_deinit(d); + pmtimer_deinit(d); if ( d->arch.hvm_domain.shared_page_va ) unmap_domain_page_global( @@ -489,6 +490,7 @@ void vmx_migrate_timers(struct vcpu *v) { struct periodic_time *pt = &(v->domain->arch.hvm_domain.pl_time.periodic_tm); struct RTCState *vrtc = &v->domain->arch.hvm_domain.pl_time.vrtc; + struct PMTState *vpmt = &v->domain->arch.hvm_domain.pl_time.vpmt; if ( pt->enabled ) { @@ -499,6 +501,7 @@ void vmx_migrate_timers(struct vcpu *v) migrate_timer(&VLAPIC(v)->vlapic_timer, v->processor); migrate_timer(&vrtc->second_timer, v->processor); migrate_timer(&vrtc->second_timer2, v->processor); + migrate_timer(&vpmt->timer, v->processor); } static void vmx_store_cpu_guest_regs( diff -r d246b79986d1 -r 3e26719ab827 xen/arch/x86/setup.c --- a/xen/arch/x86/setup.c Tue Oct 24 11:21:48 2006 -0600 +++ b/xen/arch/x86/setup.c Wed Oct 25 12:12:01 2006 -0600 @@ -16,6 +16,7 @@ #include <xen/percpu.h> #include <xen/hypercall.h> #include <xen/keyhandler.h> +#include <xen/numa.h> #include <public/version.h> #include <asm/bitops.h> #include <asm/smp.h> @@ -29,6 +30,7 @@ extern void dmi_scan_machine(void); extern void generic_apic_probe(void); +extern void numa_initmem_init(unsigned long start_pfn, unsigned long end_pfn); /* * opt_xenheap_megabytes: Size of Xen heap in megabytes, excluding the @@ -255,6 +257,20 @@ static void __init init_idle_domain(void idle_vcpu[0] = this_cpu(curr_vcpu) = current; setup_idle_pagetable(); +} + +static void srat_detect_node(int cpu) +{ + unsigned node; + u8 apicid = x86_cpu_to_apicid[cpu]; + + node = apicid_to_node[apicid]; + if ( node == NUMA_NO_NODE ) + node = 0; + numa_set_node(cpu, node); + + if ( acpi_numa > 0 ) + printk(KERN_INFO "CPU %d APIC %d -> Node %d\n", cpu, apicid, node); } void __init __start_xen(multiboot_info_t *mbi) @@ -485,6 +501,12 @@ void __init __start_xen(multiboot_info_t init_frametable(); + acpi_boot_table_init(); + + acpi_numa_init(); + + numa_initmem_init(0, max_page); + end_boot_allocator(); /* Initialise the Xen heap, skipping RAM holes. */ @@ -536,8 +558,9 @@ void __init __start_xen(multiboot_info_t generic_apic_probe(); - acpi_boot_table_init(); acpi_boot_init(); + + init_cpu_to_node(); if ( smp_found_config ) get_smp_config(); @@ -589,6 +612,11 @@ void __init __start_xen(multiboot_info_t break; if ( !cpu_online(i) ) __cpu_up(i); + + /* Set up cpu_to_node[]. */ + srat_detect_node(i); + /* Set up node_to_cpumask based on cpu_to_node[]. */ + numa_add_cpu(i); } printk("Brought up %ld CPUs\n", (long)num_online_cpus()); diff -r d246b79986d1 -r 3e26719ab827 xen/arch/x86/smpboot.c --- a/xen/arch/x86/smpboot.c Tue Oct 24 11:21:48 2006 -0600 +++ b/xen/arch/x86/smpboot.c Wed Oct 25 12:12:01 2006 -0600 @@ -43,6 +43,7 @@ #include <xen/delay.h> #include <xen/softirq.h> #include <xen/serial.h> +#include <xen/numa.h> #include <asm/current.h> #include <asm/mc146818rtc.h> #include <asm/desc.h> @@ -628,7 +629,7 @@ static void map_cpu_to_logical_apicid(vo static void map_cpu_to_logical_apicid(void) { int cpu = smp_processor_id(); - int apicid = logical_smp_processor_id(); + int apicid = hard_smp_processor_id(); cpu_2_logical_apicid[cpu] = apicid; map_cpu_to_node(cpu, apicid_to_node(apicid)); diff -r d246b79986d1 -r 3e26719ab827 xen/common/memory.c --- a/xen/common/memory.c Tue Oct 24 11:21:48 2006 -0600 +++ b/xen/common/memory.c Wed Oct 25 12:12:01 2006 -0600 @@ -41,6 +41,8 @@ increase_reservation( struct page_info *page; unsigned long i; xen_pfn_t mfn; + /* use domain's first processor for locality parameter */ + unsigned int cpu = d->vcpu[0]->processor; if ( !guest_handle_is_null(extent_list) && !guest_handle_okay(extent_list, nr_extents) ) @@ -58,8 +60,8 @@ increase_reservation( return i; } - if ( unlikely((page = alloc_domheap_pages( - d, extent_order, memflags)) == NULL) ) + if ( unlikely((page = __alloc_domheap_pages( d, cpu, + extent_order, memflags )) == NULL) ) { DPRINTK("Could not allocate order=%d extent: " "id=%d memflags=%x (%ld of %d)\n", @@ -92,6 +94,8 @@ populate_physmap( unsigned long i, j; xen_pfn_t gpfn; xen_pfn_t mfn; + /* use domain's first processor for locality parameter */ + unsigned int cpu = d->vcpu[0]->processor; if ( !guest_handle_okay(extent_list, nr_extents) ) return 0; @@ -111,8 +115,8 @@ populate_physmap( if ( unlikely(__copy_from_guest_offset(&gpfn, extent_list, i, 1)) ) goto out; - if ( unlikely((page = alloc_domheap_pages( - d, extent_order, memflags)) == NULL) ) + if ( unlikely((page = __alloc_domheap_pages( d, cpu, + extent_order, memflags )) == NULL) ) { DPRINTK("Could not allocate order=%d extent: " "id=%d memflags=%x (%ld of %d)\n", @@ -294,7 +298,7 @@ memory_exchange(XEN_GUEST_HANDLE(xen_mem unsigned long in_chunk_order, out_chunk_order; xen_pfn_t gpfn, gmfn, mfn; unsigned long i, j, k; - unsigned int memflags = 0; + unsigned int memflags = 0, cpu; long rc = 0; struct domain *d; struct page_info *page; @@ -368,6 +372,9 @@ memory_exchange(XEN_GUEST_HANDLE(xen_mem } d = current->domain; + /* use domain's first processor for locality parameter */ + cpu = d->vcpu[0]->processor; + for ( i = 0; i < (exch.in.nr_extents >> in_chunk_order); i++ ) { if ( hypercall_preempt_check() ) @@ -413,8 +420,8 @@ memory_exchange(XEN_GUEST_HANDLE(xen_mem /* Allocate a chunk's worth of anonymous output pages. */ for ( j = 0; j < (1UL << out_chunk_order); j++ ) { - page = alloc_domheap_pages( - NULL, exch.out.extent_order, memflags); + page = __alloc_domheap_pages( NULL, cpu, + exch.out.extent_order, memflags); if ( unlikely(page == NULL) ) { rc = -ENOMEM; diff -r d246b79986d1 -r 3e26719ab827 xen/common/page_alloc.c --- a/xen/common/page_alloc.c Tue Oct 24 11:21:48 2006 -0600 +++ b/xen/common/page_alloc.c Wed Oct 25 12:12:01 2006 -0600 @@ -4,6 +4,7 @@ * Simple buddy heap allocator for Xen. * * Copyright (c) 2002-2004 K A Fraser + * Copyright (c) 2006 IBM Ryan Harper <ryanh@xxxxxxxxxx> * * 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 @@ -33,6 +34,8 @@ #include <xen/domain_page.h> #include <xen/keyhandler.h> #include <xen/perfc.h> +#include <xen/numa.h> +#include <xen/nodemask.h> #include <asm/page.h> /* @@ -247,22 +250,23 @@ unsigned long alloc_boot_pages(unsigned #define pfn_dom_zone_type(_pfn) \ (((_pfn) <= MAX_DMADOM_PFN) ? MEMZONE_DMADOM : MEMZONE_DOM) -static struct list_head heap[NR_ZONES][MAX_ORDER+1]; - -static unsigned long avail[NR_ZONES]; +static struct list_head heap[NR_ZONES][MAX_NUMNODES][MAX_ORDER+1]; + +static unsigned long avail[NR_ZONES][MAX_NUMNODES]; static DEFINE_SPINLOCK(heap_lock); void end_boot_allocator(void) { - unsigned long i, j; + unsigned long i, j, k; int curr_free = 0, next_free = 0; memset(avail, 0, sizeof(avail)); for ( i = 0; i < NR_ZONES; i++ ) - for ( j = 0; j <= MAX_ORDER; j++ ) - INIT_LIST_HEAD(&heap[i][j]); + for ( j = 0; j < MAX_NUMNODES; j++ ) + for ( k = 0; k <= MAX_ORDER; k++ ) + INIT_LIST_HEAD(&heap[i][j][k]); /* Pages that are free now go to the domain sub-allocator. */ for ( i = 0; i < max_page; i++ ) @@ -272,29 +276,59 @@ void end_boot_allocator(void) if ( next_free ) map_alloc(i+1, 1); /* prevent merging in free_heap_pages() */ if ( curr_free ) - free_heap_pages(pfn_dom_zone_type(i), mfn_to_page(i), 0); - } -} - -/* Hand the specified arbitrary page range to the specified heap zone. */ + init_heap_pages(pfn_dom_zone_type(i), mfn_to_page(i), 1); + } +} + +/* + * Hand the specified arbitrary page range to the specified heap zone + * checking the node_id of the previous page. If they differ and the + * latter is not on a MAX_ORDER boundary, then we reserve the page by + * not freeing it to the buddy allocator. + */ +#define MAX_ORDER_ALIGNED (1UL << (MAX_ORDER)) void init_heap_pages( unsigned int zone, struct page_info *pg, unsigned long nr_pages) { + unsigned int nid_curr,nid_prev; unsigned long i; ASSERT(zone < NR_ZONES); + if ( likely(page_to_mfn(pg) != 0) ) + nid_prev = phys_to_nid(page_to_maddr(pg-1)); + else + nid_prev = phys_to_nid(page_to_maddr(pg)); + for ( i = 0; i < nr_pages; i++ ) - free_heap_pages(zone, pg+i, 0); -} - + { + nid_curr = phys_to_nid(page_to_maddr(pg+i)); + + /* + * free pages of the same node, or if they differ, but are on a + * MAX_ORDER alignement boundary (which already get reserved) + */ + if ( (nid_curr == nid_prev) || (page_to_maddr(pg+i) & + MAX_ORDER_ALIGNED) ) + free_heap_pages(zone, pg+i, 0); + else + printk("Reserving non-aligned node boundary @ mfn %lu\n", + page_to_mfn(pg+i)); + + nid_prev = nid_curr; + } +} /* Allocate 2^@order contiguous pages. */ -struct page_info *alloc_heap_pages(unsigned int zone, unsigned int order) -{ - int i; +struct page_info *alloc_heap_pages(unsigned int zone, unsigned int cpu, + unsigned int order) +{ + unsigned int i,j, node = cpu_to_node(cpu), num_nodes = num_online_nodes(); + unsigned int request = (1UL << order); struct page_info *pg; + ASSERT(node >= 0); + ASSERT(node < num_nodes); ASSERT(zone < NR_ZONES); if ( unlikely(order > MAX_ORDER) ) @@ -302,29 +336,46 @@ struct page_info *alloc_heap_pages(unsig spin_lock(&heap_lock); - /* Find smallest order which can satisfy the request. */ - for ( i = order; i <= MAX_ORDER; i++ ) - if ( !list_empty(&heap[zone][i]) ) - goto found; + /* start with requested node, but exhaust all node memory + * in requested zone before failing, only calc new node + * value if we fail to find memory in target node, this avoids + * needless computation on fast-path */ + for ( i = 0; i < num_nodes; i++ ) + { + /* check if target node can support the allocation */ + if ( avail[zone][node] >= request ) + { + /* Find smallest order which can satisfy the request. */ + for ( j = order; j <= MAX_ORDER; j++ ) + { + if ( !list_empty(&heap[zone][node][j]) ) + goto found; + } + } + /* pick next node, wrapping around if needed */ + if ( ++node == num_nodes ) + node = 0; + } /* No suitable memory blocks. Fail the request. */ spin_unlock(&heap_lock); return NULL; found: - pg = list_entry(heap[zone][i].next, struct page_info, list); + pg = list_entry(heap[zone][node][j].next, struct page_info, list); list_del(&pg->list); /* We may have to halve the chunk a number of times. */ - while ( i != order ) - { - PFN_ORDER(pg) = --i; - list_add_tail(&pg->list, &heap[zone][i]); - pg += 1 << i; + while ( j != order ) + { + PFN_ORDER(pg) = --j; + list_add_tail(&pg->list, &heap[zone][node][j]); + pg += 1 << j; } - map_alloc(page_to_mfn(pg), 1 << order); - avail[zone] -= 1 << order; + map_alloc(page_to_mfn(pg), request); + ASSERT(avail[zone][node] >= request); + avail[zone][node] -= request; spin_unlock(&heap_lock); @@ -337,14 +388,17 @@ void free_heap_pages( unsigned int zone, struct page_info *pg, unsigned int order) { unsigned long mask; + int node = phys_to_nid(page_to_maddr(pg)); ASSERT(zone < NR_ZONES); ASSERT(order <= MAX_ORDER); + ASSERT(node >= 0); + ASSERT(node < num_online_nodes()); spin_lock(&heap_lock); map_free(page_to_mfn(pg), 1 << order); - avail[zone] += 1 << order; + avail[zone][node] += 1 << order; /* Merge chunks as far as possible. */ while ( order < MAX_ORDER ) @@ -370,10 +424,13 @@ void free_heap_pages( } order++; + + /* after merging, pg should be in the same node */ + ASSERT(phys_to_nid(page_to_maddr(pg)) == node ); } PFN_ORDER(pg) = order; - list_add_tail(&pg->list, &heap[zone][order]); + list_add_tail(&pg->list, &heap[zone][node][order]); spin_unlock(&heap_lock); } @@ -466,7 +523,7 @@ void *alloc_xenheap_pages(unsigned int o int i; local_irq_save(flags); - pg = alloc_heap_pages(MEMZONE_XEN, order); + pg = alloc_heap_pages(MEMZONE_XEN, smp_processor_id(), order); local_irq_restore(flags); if ( unlikely(pg == NULL) ) @@ -580,8 +637,9 @@ int assign_pages( } -struct page_info *alloc_domheap_pages( - struct domain *d, unsigned int order, unsigned int memflags) +struct page_info *__alloc_domheap_pages( + struct domain *d, unsigned int cpu, unsigned int order, + unsigned int memflags) { struct page_info *pg = NULL; cpumask_t mask; @@ -591,17 +649,17 @@ struct page_info *alloc_domheap_pages( if ( !(memflags & MEMF_dma) ) { - pg = alloc_heap_pages(MEMZONE_DOM, order); + pg = alloc_heap_pages(MEMZONE_DOM, cpu, order); /* Failure? Then check if we can fall back to the DMA pool. */ if ( unlikely(pg == NULL) && ((order > MAX_ORDER) || - (avail[MEMZONE_DMADOM] < + (avail_heap_pages(MEMZONE_DMADOM,-1) < (lowmem_emergency_pool_pages + (1UL << order)))) ) return NULL; } if ( pg == NULL ) - if ( (pg = alloc_heap_pages(MEMZONE_DMADOM, order)) == NULL ) + if ( (pg = alloc_heap_pages(MEMZONE_DMADOM, cpu, order)) == NULL ) return NULL; mask = pg->u.free.cpumask; @@ -640,6 +698,11 @@ struct page_info *alloc_domheap_pages( return pg; } +inline struct page_info *alloc_domheap_pages( + struct domain *d, unsigned int order, unsigned int flags) +{ + return __alloc_domheap_pages(d, smp_processor_id(), order, flags); +} void free_domheap_pages(struct page_info *pg, unsigned int order) { @@ -714,13 +777,27 @@ void free_domheap_pages(struct page_info } +unsigned long avail_heap_pages(int zone, int node) +{ + int i,j, num_nodes = num_online_nodes(); + unsigned long free_pages = 0; + + for (i=0; i<NR_ZONES; i++) + if ( (zone == -1) || (zone == i) ) + for (j=0; j < num_nodes; j++) + if ( (node == -1) || (node == j) ) + free_pages += avail[i][j]; + + return free_pages; +} + unsigned long avail_domheap_pages(void) { unsigned long avail_nrm, avail_dma; - - avail_nrm = avail[MEMZONE_DOM]; - - avail_dma = avail[MEMZONE_DMADOM]; + + avail_nrm = avail_heap_pages(MEMZONE_DOM,-1); + + avail_dma = avail_heap_pages(MEMZONE_DMADOM,-1); if ( avail_dma > lowmem_emergency_pool_pages ) avail_dma -= lowmem_emergency_pool_pages; else @@ -729,6 +806,10 @@ unsigned long avail_domheap_pages(void) return avail_nrm + avail_dma; } +unsigned long avail_nodeheap_pages(int node) +{ + return avail_heap_pages(-1, node); +} static void pagealloc_keyhandler(unsigned char key) { @@ -736,9 +817,9 @@ static void pagealloc_keyhandler(unsigne printk(" Xen heap: %lukB free\n" " DMA heap: %lukB free\n" " Dom heap: %lukB free\n", - avail[MEMZONE_XEN]<<(PAGE_SHIFT-10), - avail[MEMZONE_DMADOM]<<(PAGE_SHIFT-10), - avail[MEMZONE_DOM]<<(PAGE_SHIFT-10)); + avail_heap_pages(MEMZONE_XEN, -1) << (PAGE_SHIFT-10), + avail_heap_pages(MEMZONE_DMADOM, -1) <<(PAGE_SHIFT-10), + avail_heap_pages(MEMZONE_DOM, -1) <<(PAGE_SHIFT-10)); } @@ -805,6 +886,46 @@ unsigned long avail_scrub_pages(void) { return scrub_pages; } + +static unsigned long count_bucket(struct list_head* l, int order) +{ + unsigned long total_pages = 0; + int pages = 1 << order; + struct page_info *pg; + + list_for_each_entry(pg, l, list) + total_pages += pages; + + return total_pages; +} + +static void dump_heap(unsigned char key) +{ + s_time_t now = NOW(); + int i,j,k; + unsigned long total; + + printk("'%c' pressed -> dumping heap info (now-0x%X:%08X)\n", key, + (u32)(now>>32), (u32)now); + + for (i=0; i<NR_ZONES; i++ ) + for (j=0;j<MAX_NUMNODES;j++) + for (k=0;k<=MAX_ORDER;k++) + if ( !list_empty(&heap[i][j][k]) ) + { + total = count_bucket(&heap[i][j][k], k); + printk("heap[%d][%d][%d]-> %lu pages\n", + i, j, k, total); + } +} + +static __init int register_heap_trigger(void) +{ + register_keyhandler('H', dump_heap, "dump heap info"); + return 0; +} +__initcall(register_heap_trigger); + static __init int page_scrub_init(void) { diff -r d246b79986d1 -r 3e26719ab827 xen/drivers/acpi/Makefile --- a/xen/drivers/acpi/Makefile Tue Oct 24 11:21:48 2006 -0600 +++ b/xen/drivers/acpi/Makefile Wed Oct 25 12:12:01 2006 -0600 @@ -1,1 +1,2 @@ obj-y += tables.o obj-y += tables.o +obj-y += numa.o diff -r d246b79986d1 -r 3e26719ab827 xen/include/asm-ia64/vmx_platform.h --- a/xen/include/asm-ia64/vmx_platform.h Tue Oct 24 11:21:48 2006 -0600 +++ b/xen/include/asm-ia64/vmx_platform.h Wed Oct 25 12:12:01 2006 -0600 @@ -24,6 +24,8 @@ #include <asm/hvm/vioapic.h> struct mmio_list; typedef struct virtual_platform_def { + unsigned long buffered_io_va; + spinlock_t buffered_io_lock; unsigned long shared_page_va; unsigned long pib_base; unsigned char xtp; diff -r d246b79986d1 -r 3e26719ab827 xen/include/asm-x86/acpi.h --- a/xen/include/asm-x86/acpi.h Tue Oct 24 11:21:48 2006 -0600 +++ b/xen/include/asm-x86/acpi.h Wed Oct 25 12:12:01 2006 -0600 @@ -157,6 +157,9 @@ static inline void check_acpi_pci(void) static inline void acpi_noirq_set(void) { acpi_noirq = 1; } static inline int acpi_irq_balance_set(char *str) { return 0; } +extern int acpi_scan_nodes(u64 start, u64 end); +extern int acpi_numa; +#define NR_NODE_MEMBLKS (MAX_NUMNODES*2) #ifdef CONFIG_ACPI_SLEEP @@ -173,5 +176,6 @@ extern void acpi_reserve_bootmem(void); #endif /*CONFIG_ACPI_SLEEP*/ extern u8 x86_acpiid_to_apicid[]; +#define MAX_LOCAL_APIC 256 #endif /*_ASM_ACPI_H*/ diff -r d246b79986d1 -r 3e26719ab827 xen/include/asm-x86/config.h --- a/xen/include/asm-x86/config.h Tue Oct 24 11:21:48 2006 -0600 +++ b/xen/include/asm-x86/config.h Wed Oct 25 12:12:01 2006 -0600 @@ -24,6 +24,11 @@ #define CONFIG_X86_IO_APIC 1 #define CONFIG_HPET_TIMER 1 #define CONFIG_X86_MCE_P4THERMAL 1 +#define CONFIG_ACPI_NUMA 1 +#define CONFIG_NUMA 1 +#define CONFIG_ACPI_SRAT 1 +#define CONFIG_DISCONTIGMEM 1 +#define CONFIG_NUMA_EMU 1 /* Intel P4 currently has largest cache line (L2 line size is 128 bytes). */ #define CONFIG_X86_L1_CACHE_SHIFT 7 diff -r d246b79986d1 -r 3e26719ab827 xen/include/asm-x86/hvm/domain.h --- a/xen/include/asm-x86/hvm/domain.h Tue Oct 24 11:21:48 2006 -0600 +++ b/xen/include/asm-x86/hvm/domain.h Wed Oct 25 12:12:01 2006 -0600 @@ -23,7 +23,7 @@ #define __ASM_X86_HVM_DOMAIN_H__ #include <asm/hvm/vpic.h> -#include <asm/hvm/vpit.h> +#include <asm/hvm/vpt.h> #include <asm/hvm/vlapic.h> #include <asm/hvm/vioapic.h> #include <public/hvm/params.h> diff -r d246b79986d1 -r 3e26719ab827 xen/include/asm-x86/mach-generic/mach_apic.h --- a/xen/include/asm-x86/mach-generic/mach_apic.h Tue Oct 24 11:21:48 2006 -0600 +++ b/xen/include/asm-x86/mach-generic/mach_apic.h Wed Oct 25 12:12:01 2006 -0600 @@ -22,11 +22,7 @@ static inline void enable_apic_mode(void return; } -/* No sane NUMA support right now. We should parse ACPI SRAT. */ -static inline int apicid_to_node(int logical_apicid) -{ - return 0; -} +#define apicid_to_node(apicid) ((int)apicid_to_node[(u8)apicid]) extern u8 bios_cpu_apicid[]; static inline int cpu_present_to_apicid(int mps_cpu) diff -r d246b79986d1 -r 3e26719ab827 xen/include/public/arch-ia64.h --- a/xen/include/public/arch-ia64.h Tue Oct 24 11:21:48 2006 -0600 +++ b/xen/include/public/arch-ia64.h Wed Oct 25 12:12:01 2006 -0600 @@ -67,6 +67,9 @@ typedef unsigned long xen_ulong_t; #define STORE_PAGE_START (IO_PAGE_START + IO_PAGE_SIZE) #define STORE_PAGE_SIZE PAGE_SIZE + +#define BUFFER_IO_PAGE_START (STORE_PAGE_START+PAGE_SIZE) +#define BUFFER_IO_PAGE_SIZE PAGE_SIZE #define IO_SAPIC_START 0xfec00000UL #define IO_SAPIC_SIZE 0x100000 diff -r d246b79986d1 -r 3e26719ab827 xen/include/public/hvm/ioreq.h --- a/xen/include/public/hvm/ioreq.h Tue Oct 24 11:21:48 2006 -0600 +++ b/xen/include/public/hvm/ioreq.h Wed Oct 25 12:12:01 2006 -0600 @@ -86,6 +86,10 @@ struct buffered_iopage { }; /* sizeof this structure must be in one page */ typedef struct buffered_iopage buffered_iopage_t; +#define ACPI_PM1A_EVT_BLK_ADDRESS 0x000000000000c010 +#define ACPI_PM1A_CNT_BLK_ADDRESS (ACPI_PM1A_EVT_BLK_ADDRESS + 0x04) +#define ACPI_PM_TMR_BLK_ADDRESS (ACPI_PM1A_EVT_BLK_ADDRESS + 0x08) + #endif /* _IOREQ_H_ */ /* diff -r d246b79986d1 -r 3e26719ab827 xen/include/xen/config.h --- a/xen/include/xen/config.h Tue Oct 24 11:21:48 2006 -0600 +++ b/xen/include/xen/config.h Wed Oct 25 12:12:01 2006 -0600 @@ -50,5 +50,7 @@ #endif /* !__ASSEMBLY__ */ #define fastcall +#define __cpuinitdata +#define __cpuinit #endif /* __XEN_CONFIG_H__ */ diff -r d246b79986d1 -r 3e26719ab827 xen/include/xen/mm.h --- a/xen/include/xen/mm.h Tue Oct 24 11:21:48 2006 -0600 +++ b/xen/include/xen/mm.h Wed Oct 25 12:12:01 2006 -0600 @@ -45,7 +45,8 @@ void end_boot_allocator(void); /* Generic allocator. These functions are *not* interrupt-safe. */ void init_heap_pages( unsigned int zone, struct page_info *pg, unsigned long nr_pages); -struct page_info *alloc_heap_pages(unsigned int zone, unsigned int order); +struct page_info *alloc_heap_pages( + unsigned int zone, unsigned int cpu, unsigned int order); void free_heap_pages( unsigned int zone, struct page_info *pg, unsigned int order); void scrub_heap_pages(void); @@ -61,8 +62,12 @@ void init_domheap_pages(paddr_t ps, padd void init_domheap_pages(paddr_t ps, paddr_t pe); struct page_info *alloc_domheap_pages( struct domain *d, unsigned int order, unsigned int memflags); +struct page_info *__alloc_domheap_pages( + struct domain *d, unsigned int cpu, unsigned int order, + unsigned int memflags); void free_domheap_pages(struct page_info *pg, unsigned int order); unsigned long avail_domheap_pages(void); +unsigned long avail_heap_pages(int zone, int node); #define alloc_domheap_page(d) (alloc_domheap_pages(d,0,0)) #define free_domheap_page(p) (free_domheap_pages(p,0)) diff -r d246b79986d1 -r 3e26719ab827 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.h Wed Oct 25 12:12:01 2006 -0600 @@ -0,0 +1,77 @@ +/****************************************************************************** + * xenbus_probe.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 program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation; or, when 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_PROBE_H +#define _XENBUS_PROBE_H + +#ifdef CONFIG_XEN_BACKEND +extern void xenbus_backend_suspend(int (*fn)(struct device *, void *)); +extern void xenbus_backend_resume(int (*fn)(struct device *, void *)); +extern void xenbus_backend_probe_and_watch(void); +extern void xenbus_backend_bus_register(void); +extern void xenbus_backend_device_register(void); +#else +static inline void xenbus_backend_suspend(int (*fn)(struct device *, void *)) {} +static inline void xenbus_backend_resume(int (*fn)(struct device *, void *)) {} +static inline void xenbus_backend_probe_and_watch(void) {} +static inline void xenbus_backend_bus_register(void) {} +static inline void xenbus_backend_device_register(void) {} +#endif + +struct xen_bus_type +{ + char *root; + unsigned int levels; + int (*get_bus_id)(char bus_id[BUS_ID_SIZE], const char *nodename); + int (*probe)(const char *type, const char *dir); + struct bus_type bus; + struct device dev; +}; + +extern int xenbus_match(struct device *_dev, struct device_driver *_drv); +extern int xenbus_dev_probe(struct device *_dev); +extern int xenbus_dev_remove(struct device *_dev); +extern int xenbus_register_driver_common(struct xenbus_driver *drv, + struct xen_bus_type *bus); +extern int xenbus_probe_node(struct xen_bus_type *bus, + const char *type, + const char *nodename); +extern int xenbus_probe_devices(struct xen_bus_type *bus); + +extern void dev_changed(const char *node, struct xen_bus_type *bus); + +/* Simplified asprintf. Probably belongs in lib */ +extern char *kasprintf(const char *fmt, ...); + +#endif + diff -r d246b79986d1 -r 3e26719ab827 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe_backend.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe_backend.c Wed Oct 25 12:12:01 2006 -0600 @@ -0,0 +1,271 @@ +/****************************************************************************** + * Talks to Xen Store to figure out what devices we have (backend half). + * + * Copyright (C) 2005 Rusty Russell, IBM Corporation + * Copyright (C) 2005 Mike Wray, Hewlett-Packard + * Copyright (C) 2005, 2006 XenSource Ltd + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation; or, when 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. + */ + +#define DPRINTK(fmt, args...) \ + pr_debug("xenbus_probe (%s:%d) " fmt ".\n", \ + __FUNCTION__, __LINE__, ##args) + +#include <linux/kernel.h> +#include <linux/err.h> +#include <linux/string.h> +#include <linux/ctype.h> +#include <linux/fcntl.h> +#include <linux/mm.h> +#include <linux/notifier.h> +#include <linux/kthread.h> + +#include <asm/io.h> +#include <asm/page.h> +#include <asm/maddr.h> +#include <asm/pgtable.h> +#include <asm/hypervisor.h> +#include <xen/xenbus.h> +#include <xen/xen_proc.h> +#include <xen/evtchn.h> +#include <xen/features.h> +#include <xen/hvm.h> + +#include "xenbus_comms.h" +#include "xenbus_probe.h" + +#ifdef HAVE_XEN_PLATFORM_COMPAT_H +#include <xen/platform-compat.h> +#endif + +static int xenbus_uevent_backend(struct device *dev, char **envp, + int num_envp, char *buffer, int buffer_size); +static int xenbus_probe_backend(const char *type, const char *domid); + +extern int read_otherend_details(struct xenbus_device *xendev, + char *id_node, char *path_node); + +static int read_frontend_details(struct xenbus_device *xendev) +{ + return read_otherend_details(xendev, "frontend-id", "frontend"); +} + +/* backend/<type>/<fe-uuid>/<id> => <type>-<fe-domid>-<id> */ +static int backend_bus_id(char bus_id[BUS_ID_SIZE], const char *nodename) +{ + int domid, err; + const char *devid, *type, *frontend; + unsigned int typelen; + + type = strchr(nodename, '/'); + if (!type) + return -EINVAL; + type++; + typelen = strcspn(type, "/"); + if (!typelen || type[typelen] != '/') + return -EINVAL; + + devid = strrchr(nodename, '/') + 1; + + err = xenbus_gather(XBT_NIL, nodename, "frontend-id", "%i", &domid, + "frontend", NULL, &frontend, + NULL); + if (err) + return err; + if (strlen(frontend) == 0) + err = -ERANGE; + if (!err && !xenbus_exists(XBT_NIL, frontend, "")) + err = -ENOENT; + kfree(frontend); + + if (err) + return err; + + if (snprintf(bus_id, BUS_ID_SIZE, + "%.*s-%i-%s", typelen, type, domid, devid) >= BUS_ID_SIZE) + return -ENOSPC; + return 0; +} + +static struct xen_bus_type xenbus_backend = { + .root = "backend", + .levels = 3, /* backend/type/<frontend>/<id> */ + .get_bus_id = backend_bus_id, + .probe = xenbus_probe_backend, + .bus = { + .name = "xen-backend", + .match = xenbus_match, + .probe = xenbus_dev_probe, + .remove = xenbus_dev_remove, +// .shutdown = xenbus_dev_shutdown, + .uevent = xenbus_uevent_backend, + }, + .dev = { + .bus_id = "xen-backend", + }, +}; + +static int xenbus_uevent_backend(struct device *dev, char **envp, + int num_envp, char *buffer, int buffer_size) +{ + struct xenbus_device *xdev; + struct xenbus_driver *drv; + int i = 0; + int length = 0; + + DPRINTK(""); + + if (dev == NULL) + return -ENODEV; + + xdev = to_xenbus_device(dev); + if (xdev == NULL) + return -ENODEV; + + /* stuff we want to pass to /sbin/hotplug */ + add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, + "XENBUS_TYPE=%s", xdev->devicetype); + + add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, + "XENBUS_PATH=%s", xdev->nodename); + + add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, + "XENBUS_BASE_PATH=%s", xenbus_backend.root); + + /* terminate, set to next free slot, shrink available space */ + envp[i] = NULL; + envp = &envp[i]; + num_envp -= i; + buffer = &buffer[length]; + buffer_size -= length; + + if (dev->driver) { + drv = to_xenbus_driver(dev->driver); + if (drv && drv->uevent) + return drv->uevent(xdev, envp, num_envp, buffer, + buffer_size); + } + + return 0; +} + +int xenbus_register_backend(struct xenbus_driver *drv) +{ + drv->read_otherend_details = read_frontend_details; + + return xenbus_register_driver_common(drv, &xenbus_backend); +} +EXPORT_SYMBOL_GPL(xenbus_register_backend); + +/* backend/<typename>/<frontend-uuid>/<name> */ +static int xenbus_probe_backend_unit(const char *dir, + const char *type, + const char *name) +{ + char *nodename; + int err; + + nodename = kasprintf("%s/%s", dir, name); + if (!nodename) + return -ENOMEM; + + DPRINTK("%s\n", nodename); + + err = xenbus_probe_node(&xenbus_backend, type, nodename); + kfree(nodename); + return err; +} + +/* backend/<typename>/<frontend-domid> */ +static int xenbus_probe_backend(const char *type, const char *domid) +{ + char *nodename; + int err = 0; + char **dir; + unsigned int i, dir_n = 0; + + DPRINTK(""); + + nodename = kasprintf("%s/%s/%s", xenbus_backend.root, type, domid); + if (!nodename) + return -ENOMEM; + + dir = xenbus_directory(XBT_NIL, nodename, "", &dir_n); + if (IS_ERR(dir)) { + kfree(nodename); + return PTR_ERR(dir); + } + + for (i = 0; i < dir_n; i++) { + err = xenbus_probe_backend_unit(nodename, type, dir[i]); + if (err) + break; + } + kfree(dir); + kfree(nodename); + return err; +} + +static void backend_changed(struct xenbus_watch *watch, + const char **vec, unsigned int len) +{ + DPRINTK(""); + + dev_changed(vec[XS_WATCH_PATH], &xenbus_backend); +} + +static struct xenbus_watch be_watch = { + .node = "backend", + .callback = backend_changed, +}; + +void xenbus_backend_suspend(int (*fn)(struct device *, void *)) +{ + DPRINTK(""); + bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, fn); +} + +void xenbus_backend_resume(int (*fn)(struct device *, void *)) +{ + DPRINTK(""); + bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, fn); +} + +void xenbus_backend_probe_and_watch(void) +{ + xenbus_probe_devices(&xenbus_backend); + register_xenbus_watch(&be_watch); +} + +void xenbus_backend_bus_register(void) +{ + bus_register(&xenbus_backend.bus); +} + +void xenbus_backend_device_register(void) +{ + device_register(&xenbus_backend.dev); +} diff -r d246b79986d1 -r 3e26719ab827 unmodified_drivers/linux-2.6/blkfront/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/unmodified_drivers/linux-2.6/blkfront/Makefile Wed Oct 25 12:12:01 2006 -0600 @@ -0,0 +1,3 @@ +ifneq ($(KERNELRELEASE),) +include $(src)/Kbuild +endif diff -r d246b79986d1 -r 3e26719ab827 unmodified_drivers/linux-2.6/compat-include/asm-generic/pgtable-nopmd.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/unmodified_drivers/linux-2.6/compat-include/asm-generic/pgtable-nopmd.h Wed Oct 25 12:12:01 2006 -0600 @@ -0,0 +1,14 @@ +#ifndef _PGTABLE_NOPMD_H +#define _PGTABLE_NOPMD_H + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11) +#error "This version of Linux should not need compat pgtable-nopmd.h" +#endif + +#define pud_t pgd_t +#define pud_offset(d, va) d +#define pud_none(pud) 0 +#define pud_present(pud) 1 +#define PTRS_PER_PUD 1 + +#endif /* _PGTABLE_NOPMD_H */ diff -r d246b79986d1 -r 3e26719ab827 unmodified_drivers/linux-2.6/compat-include/asm-generic/pgtable-nopud.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/unmodified_drivers/linux-2.6/compat-include/asm-generic/pgtable-nopud.h Wed Oct 25 12:12:01 2006 -0600 @@ -0,0 +1,14 @@ +#ifndef _PGTABLE_NOPUD_H +#define _PGTABLE_NOPUD_H + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11) +#error "This version of Linux should not need compat pgtable-nopud.h" +#endif + +#define pud_t pgd_t +#define pud_offset(d, va) d +#define pud_none(pud) 0 +#define pud_present(pud) 1 +#define PTRS_PER_PUD 1 + +#endif /* _PGTABLE_NOPUD_H */ diff -r d246b79986d1 -r 3e26719ab827 unmodified_drivers/linux-2.6/compat-include/linux/io.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/unmodified_drivers/linux-2.6/compat-include/linux/io.h Wed Oct 25 12:12:01 2006 -0600 @@ -0,0 +1,10 @@ +#ifndef _LINUX_IO_H +#define _LINUX_IO_H + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) +#error "This version of Linux should not need compat linux/io.h" +#endif + +#include <asm/io.h> + +#endif diff -r d246b79986d1 -r 3e26719ab827 unmodified_drivers/linux-2.6/compat-include/linux/mutex.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/unmodified_drivers/linux-2.6/compat-include/linux/mutex.h Wed Oct 25 12:12:01 2006 -0600 @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2006 Cisco Systems. All rights reserved. + * + * This file is released under the GPLv2. + */ + +/* mutex compatibility for pre-2.6.16 kernels */ + +#ifndef __LINUX_MUTEX_H +#define __LINUX_MUTEX_H + +#include <linux/version.h> + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) +#error "This version of Linux should not need compat mutex.h" +#endif + +#include <linux/version.h> +#include <asm/semaphore.h> + +#define mutex semaphore +#define DEFINE_MUTEX(foo) DECLARE_MUTEX(foo) +#define mutex_init(foo) init_MUTEX(foo) +#define mutex_lock(foo) down(foo) +#define mutex_lock_interruptible(foo) down_interruptible(foo) +/* this function follows the spin_trylock() convention, so * + * it is negated to the down_trylock() return values! Be careful */ +#define mutex_trylock(foo) !down_trylock(foo) +#define mutex_unlock(foo) up(foo) + +#endif /* __LINUX_MUTEX_H */ diff -r d246b79986d1 -r 3e26719ab827 unmodified_drivers/linux-2.6/compat-include/xen/platform-compat.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/unmodified_drivers/linux-2.6/compat-include/xen/platform-compat.h Wed Oct 25 12:12:01 2006 -0600 @@ -0,0 +1,52 @@ +#ifndef COMPAT_INCLUDE_XEN_PLATFORM_COMPAT_H +#define COMPAT_INCLUDE_XEN_PLATFORM_COMPAT_H + +#include <linux/version.h> + +#include <linux/spinlock.h> + +#if defined(__LINUX_COMPILER_H) && !defined(__always_inline) +#define __always_inline inline +#endif + +#if defined(__LINUX_SPINLOCK_H) && !defined(DEFINE_SPINLOCK) +#define DEFINE_SPINLOCK(x) spinlock_t x = SPIN_LOCK_UNLOCKED +#endif + +#if defined(_LINUX_INIT_H) && !defined(__init) +#define __init +#endif + +#if defined(__LINUX_CACHE_H) && !defined(__read_mostly) +#define __read_mostly +#endif + +#if defined(_LINUX_SKBUFF_H) && !defined(NET_IP_ALIGN) +#define NET_IP_ALIGN 0 +#endif + +#if defined(_LINUX_FS_H) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9) +#define nonseekable_open(inode, filp) /* Nothing to do */ +#endif + +#if defined(_LINUX_MM_H) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) +unsigned long vmalloc_to_pfn(void *addr); +#endif + +#if defined(__LINUX_COMPLETION_H) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) +unsigned long wait_for_completion_timeout(struct completion *x, unsigned long timeout); +#endif + +#if defined(_LINUX_SCHED_H) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14) +signed long schedule_timeout_interruptible(signed long timeout); +#endif + +#if defined(_LINUX_SLAB_H) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14) +void *kzalloc(size_t size, int flags); +#endif + +#if defined(_LINUX_BLKDEV_H) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16) +#define end_that_request_last(req, uptodate) end_that_request_last(req) +#endif + +#endif diff -r d246b79986d1 -r 3e26719ab827 unmodified_drivers/linux-2.6/netfront/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/unmodified_drivers/linux-2.6/netfront/Makefile Wed Oct 25 12:12:01 2006 -0600 @@ -0,0 +1,3 @@ +ifneq ($(KERNELRELEASE),) +include $(src)/Kbuild +endif diff -r d246b79986d1 -r 3e26719ab827 unmodified_drivers/linux-2.6/platform-pci/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/unmodified_drivers/linux-2.6/platform-pci/Makefile Wed Oct 25 12:12:01 2006 -0600 @@ -0,0 +1,3 @@ +ifneq ($(KERNELRELEASE),) +include $(src)/Kbuild +endif diff -r d246b79986d1 -r 3e26719ab827 unmodified_drivers/linux-2.6/platform-pci/platform-compat.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/unmodified_drivers/linux-2.6/platform-pci/platform-compat.c Wed Oct 25 12:12:01 2006 -0600 @@ -0,0 +1,116 @@ +#include <linux/config.h> +#include <linux/version.h> + +#include <linux/mm.h> +#include <linux/module.h> +#include <linux/sched.h> +#include <linux/slab.h> + +#include <xen/platform-compat.h> + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7) +static int system_state = 1; +EXPORT_SYMBOL(system_state); +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8) +size_t strcspn(const char *s, const char *reject) +{ + const char *p; + const char *r; + size_t count = 0; + + for (p = s; *p != '\0'; ++p) { + for (r = reject; *r != '\0'; ++r) { + if (*p == *r) + return count; + } + ++count; + } + + return count; +} +EXPORT_SYMBOL(strcspn); +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) +/* + * Map a vmalloc()-space virtual address to the physical page frame number. + */ +unsigned long vmalloc_to_pfn(void * vmalloc_addr) +{ + return page_to_pfn(vmalloc_to_page(vmalloc_addr)); +} +EXPORT_SYMBOL(vmalloc_to_pfn); +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) +unsigned long wait_for_completion_timeout(struct completion *x, unsigned long timeout) +{ + might_sleep(); + + spin_lock_irq(&x->wait.lock); + if (!x->done) { + DECLARE_WAITQUEUE(wait, current); + + wait.flags |= WQ_FLAG_EXCLUSIVE; + __add_wait_queue_tail(&x->wait, &wait); + do { + __set_current_state(TASK_UNINTERRUPTIBLE); + spin_unlock_irq(&x->wait.lock); + timeout = schedule_timeout(timeout); + spin_lock_irq(&x->wait.lock); + if (!timeout) { + __remove_wait_queue(&x->wait, &wait); + goto out; + } + } while (!x->done); + __remove_wait_queue(&x->wait, &wait); + } + x->done--; +out: + spin_unlock_irq(&x->wait.lock); + return timeout; +} +EXPORT_SYMBOL(wait_for_completion_timeout); +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12) +/* + fake do_exit using complete_and_exit + */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) +asmlinkage NORET_TYPE void do_exit(long code) +#else +fastcall NORET_TYPE void do_exit(long code) +#endif +{ + complete_and_exit(NULL, code); +} +EXPORT_SYMBOL_GPL(do_exit); +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14) +signed long schedule_timeout_interruptible(signed long timeout) +{ + __set_current_state(TASK_INTERRUPTIBLE); + return schedule_timeout(timeout); +} +EXPORT_SYMBOL(schedule_timeout_interruptible); +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14) +/** + * kzalloc - allocate memory. The memory is set to zero. + * @size: how many bytes of memory are required. + * @flags: the type of memory to allocate. + */ +void *kzalloc(size_t size, int flags) +{ + void *ret = kmalloc(size, flags); + if (ret) + memset(ret, 0, size); + return ret; +} +EXPORT_SYMBOL(kzalloc); +#endif diff -r d246b79986d1 -r 3e26719ab827 unmodified_drivers/linux-2.6/xenbus/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/unmodified_drivers/linux-2.6/xenbus/Makefile Wed Oct 25 12:12:01 2006 -0600 @@ -0,0 +1,3 @@ +ifneq ($(KERNELRELEASE),) +include $(src)/Kbuild +endif diff -r d246b79986d1 -r 3e26719ab827 xen/arch/x86/hvm/pmtimer.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/arch/x86/hvm/pmtimer.c Wed Oct 25 12:12:01 2006 -0600 @@ -0,0 +1,63 @@ +#include <asm/hvm/vpt.h> +#include <asm/hvm/io.h> +#include <asm/hvm/support.h> + +#define TMR_STS (1 << 0) +static void pmt_update_status(void *opaque) +{ + PMTState *s = opaque; + s->pm1_status |= TMR_STS; + + /* TODO: When TMR_EN == 1, generate a SCI event */ + + set_timer(&s->timer, NOW() + (1000000000ULL << 31) / FREQUENCE_PMTIMER); +} + +static int handle_pmt_io(ioreq_t *p) +{ + struct vcpu *v = current; + PMTState *s = &v->domain->arch.hvm_domain.pl_time.vpmt; + uint64_t curr_gtime; + + if (p->size != 4 || + p->pdata_valid || + p->type != IOREQ_TYPE_PIO){ + printk("HVM_PMT: wrong PM timer IO\n"); + return 1; + } + + if (p->dir == 0) { /* write */ + /* PM_TMR_BLK is read-only */ + return 1; + } else if (p->dir == 1) { /* read */ + curr_gtime = hvm_get_guest_time(s->vcpu); + s->pm1_timer += ((curr_gtime - s->last_gtime) * s->scale) >> 32; + p->u.data = s->pm1_timer; + s->last_gtime = curr_gtime; + return 1; + } + return 0; +} + +void pmtimer_init(struct vcpu *v, int base) +{ + PMTState *s = &v->domain->arch.hvm_domain.pl_time.vpmt; + + s->pm1_timer = 0; + s->pm1_status = 0; + s->scale = ((uint64_t)FREQUENCE_PMTIMER << 32) / ticks_per_sec(v); + s->vcpu = v; + + init_timer(&s->timer, pmt_update_status, s, v->processor); + /* ACPI supports a 32-bit power management timer */ + set_timer(&s->timer, NOW() + (1000000000ULL << 31) / FREQUENCE_PMTIMER); + + register_portio_handler(base, 4, handle_pmt_io); +} + +void pmtimer_deinit(struct domain *d) +{ + PMTState *s = &d->arch.hvm_domain.pl_time.vpmt; + + kill_timer(&s->timer); +} diff -r d246b79986d1 -r 3e26719ab827 xen/arch/x86/numa.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/arch/x86/numa.c Wed Oct 25 12:12:01 2006 -0600 @@ -0,0 +1,308 @@ +/* + * Generic VM initialization for x86-64 NUMA setups. + * Copyright 2002,2003 Andi Kleen, SuSE Labs. + * Adapted for Xen: Ryan Harper <ryanh@xxxxxxxxxx> + */ + +#include <xen/mm.h> +#include <xen/string.h> +#include <xen/init.h> +#include <xen/ctype.h> +#include <xen/nodemask.h> +#include <xen/numa.h> +#include <xen/keyhandler.h> +#include <xen/time.h> +#include <xen/smp.h> +#include <asm/acpi.h> + +static int numa_setup(char *s); +custom_param("numa", numa_setup); + +#ifndef Dprintk +#define Dprintk(x...) +#endif + +/* from proto.h */ +#define round_up(x,y) ((((x)+(y))-1) & (~((y)-1))) + +struct node_data node_data[MAX_NUMNODES]; + +int memnode_shift; +u8 memnodemap[NODEMAPSIZE]; + +unsigned char cpu_to_node[NR_CPUS] __read_mostly = { + [0 ... NR_CPUS-1] = NUMA_NO_NODE +}; +unsigned char apicid_to_node[MAX_LOCAL_APIC] __cpuinitdata = { + [0 ... MAX_LOCAL_APIC-1] = NUMA_NO_NODE +}; +cpumask_t node_to_cpumask[MAX_NUMNODES] __read_mostly; + +nodemask_t node_online_map = { { [0] = 1UL } }; + +/* Default NUMA to off for now. acpi=on required to enable it. */ +int numa_off __initdata = 1; + +int acpi_numa __initdata; + +/* + * Given a shift value, try to populate memnodemap[] + * Returns : + * 1 if OK + * 0 if memnodmap[] too small (of shift too small) + * -1 if node overlap or lost ram (shift too big) + */ +static int __init +populate_memnodemap(const struct node *nodes, int numnodes, int shift) +{ + int i; + int res = -1; + unsigned long addr, end; + + if (shift >= 64) + return -1; + memset(memnodemap, 0xff, sizeof(memnodemap)); + for (i = 0; i < numnodes; i++) { + addr = nodes[i].start; + end = nodes[i].end; + if (addr >= end) + continue; + if ((end >> shift) >= NODEMAPSIZE) + return 0; + do { + if (memnodemap[addr >> shift] != 0xff) + return -1; + memnodemap[addr >> shift] = i; + addr += (1UL << shift); + } while (addr < end); + res = 1; + } + return res; +} + +int __init compute_hash_shift(struct node *nodes, int numnodes) +{ + int shift = 20; + + while (populate_memnodemap(nodes, numnodes, shift + 1) >= 0) + shift++; + + printk(KERN_DEBUG "NUMA: Using %d for the hash shift.\n", + shift); + + if (populate_memnodemap(nodes, numnodes, shift) != 1) { + printk(KERN_INFO + "Your memory is not aligned you need to rebuild your kernel " + "with a bigger NODEMAPSIZE shift=%d\n", + shift); + return -1; + } + return shift; +} + +/* initialize NODE_DATA given nodeid and start/end */ +void __init setup_node_bootmem(int nodeid, u64 start, u64 end) +{ + unsigned long start_pfn, end_pfn; + + start_pfn = start >> PAGE_SHIFT; + end_pfn = end >> PAGE_SHIFT; + + NODE_DATA(nodeid)->node_id = nodeid; + NODE_DATA(nodeid)->node_start_pfn = start_pfn; + NODE_DATA(nodeid)->node_spanned_pages = end_pfn - start_pfn; + + node_set_online(nodeid); +} + +void __init numa_init_array(void) +{ + int rr, i; + /* There are unfortunately some poorly designed mainboards around + that only connect memory to a single CPU. This breaks the 1:1 cpu->node + mapping. To avoid this fill in the mapping for all possible + CPUs, as the number of CPUs is not known yet. + We round robin the existing nodes. */ + rr = first_node(node_online_map); + for (i = 0; i < NR_CPUS; i++) { + if (cpu_to_node[i] != NUMA_NO_NODE) + continue; + numa_set_node(i, rr); + rr = next_node(rr, node_online_map); + if (rr == MAX_NUMNODES) + rr = first_node(node_online_map); + } + +} + +#ifdef CONFIG_NUMA_EMU +static int numa_fake __initdata = 0; + +/* Numa emulation */ +static int numa_emulation(unsigned long start_pfn, unsigned long end_pfn) +{ + int i; + struct node nodes[MAX_NUMNODES]; + unsigned long sz = ((end_pfn - start_pfn)<<PAGE_SHIFT) / numa_fake; + + /* Kludge needed for the hash function */ + if (hweight64(sz) > 1) { + unsigned long x = 1; + while ((x << 1) < sz) + x <<= 1; + if (x < sz/2) + printk(KERN_ERR "Numa emulation unbalanced. Complain to maintainer\n"); + sz = x; + } + + memset(&nodes,0,sizeof(nodes)); + for (i = 0; i < numa_fake; i++) { + nodes[i].start = (start_pfn<<PAGE_SHIFT) + i*sz; + if (i == numa_fake-1) + sz = (end_pfn<<PAGE_SHIFT) - nodes[i].start; + nodes[i].end = nodes[i].start + sz; + printk(KERN_INFO "Faking node %d at %"PRIx64"-%"PRIx64" (%"PRIu64"MB)\n", + i, + nodes[i].start, nodes[i].end, + (nodes[i].end - nodes[i].start) >> 20); + node_set_online(i); + } + memnode_shift = compute_hash_shift(nodes, numa_fake); + if (memnode_shift < 0) { + memnode_shift = 0; + printk(KERN_ERR "No NUMA hash function found. Emulation disabled.\n"); + return -1; + } + for_each_online_node(i) + setup_node_bootmem(i, nodes[i].start, nodes[i].end); + numa_init_array(); + return 0; +} +#endif + +void __init numa_initmem_init(unsigned long start_pfn, unsigned long end_pfn) +{ + int i; + +#ifdef CONFIG_NUMA_EMU + if (numa_fake && !numa_emulation(start_pfn, end_pfn)) + return; +#endif + +#ifdef CONFIG_ACPI_NUMA + if (!numa_off && !acpi_scan_nodes(start_pfn << PAGE_SHIFT, + end_pfn << PAGE_SHIFT)) + return; +#endif + + printk(KERN_INFO "%s\n", + numa_off ? "NUMA turned off" : "No NUMA configuration found"); + + printk(KERN_INFO "Faking a node at %016lx-%016lx\n", + start_pfn << PAGE_SHIFT, + end_pfn << PAGE_SHIFT); + /* setup dummy node covering all memory */ + memnode_shift = 63; + memnodemap[0] = 0; + nodes_clear(node_online_map); + node_set_online(0); + for (i = 0; i < NR_CPUS; i++) + numa_set_node(i, 0); + node_to_cpumask[0] = cpumask_of_cpu(0); + setup_node_bootmem(0, start_pfn << PAGE_SHIFT, end_pfn << PAGE_SHIFT); +} + +__cpuinit void numa_add_cpu(int cpu) +{ + set_bit(cpu, &node_to_cpumask[cpu_to_node(cpu)]); +} + +void __cpuinit numa_set_node(int cpu, int node) +{ + cpu_to_node[cpu] = node; +} + +/* [numa=off] */ +static __init int numa_setup(char *opt) +{ + if (!strncmp(opt,"off",3)) + numa_off = 1; + if (!strncmp(opt,"on",2)) + numa_off = 0; +#ifdef CONFIG_NUMA_EMU + if(!strncmp(opt, "fake=", 5)) { + numa_off = 0; + numa_fake = simple_strtoul(opt+5,NULL,0); ; + if (numa_fake >= MAX_NUMNODES) + numa_fake = MAX_NUMNODES; + } +#endif +#ifdef CONFIG_ACPI_NUMA + if (!strncmp(opt,"noacpi",6)) { + numa_off = 0; + acpi_numa = -1; + } +#endif + return 1; +} + +/* + * Setup early cpu_to_node. + * + * Populate cpu_to_node[] only if x86_cpu_to_apicid[], + * and apicid_to_node[] tables have valid entries for a CPU. + * This means we skip cpu_to_node[] initialisation for NUMA + * emulation and faking node case (when running a kernel compiled + * for NUMA on a non NUMA box), which is OK as cpu_to_node[] + * is already initialized in a round robin manner at numa_init_array, + * prior to this call, and this initialization is good enough + * for the fake NUMA cases. + */ +void __init init_cpu_to_node(void) +{ + int i; + for (i = 0; i < NR_CPUS; i++) { + u8 apicid = x86_cpu_to_apicid[i]; + if (apicid == BAD_APICID) + continue; + if (apicid_to_node[apicid] == NUMA_NO_NODE) + continue; + numa_set_node(i,apicid_to_node[apicid]); + } +} + +EXPORT_SYMBOL(cpu_to_node); +EXPORT_SYMBOL(node_to_cpumask); +EXPORT_SYMBOL(memnode_shift); +EXPORT_SYMBOL(memnodemap); +EXPORT_SYMBOL(node_data); + +static void dump_numa(unsigned char key) +{ + s_time_t now = NOW(); + int i; + + printk("'%c' pressed -> dumping numa info (now-0x%X:%08X)\n", key, + (u32)(now>>32), (u32)now); + + for_each_online_node(i) { + unsigned long pa = (NODE_DATA(i)->node_start_pfn + 1)<< PAGE_SHIFT; + printk("idx%d -> NODE%d start->%lu size->%lu\n", + i, NODE_DATA(i)->node_id, + NODE_DATA(i)->node_start_pfn, + NODE_DATA(i)->node_spanned_pages); + /* sanity check phys_to_nid() */ + printk("phys_to_nid(%lx) -> %d should be %d\n", pa, phys_to_nid(pa), + NODE_DATA(i)->node_id); + } + for_each_online_cpu(i) + printk("CPU%d -> NODE%d\n", i, cpu_to_node[i]); +} + +static __init int register_numa_trigger(void) +{ + register_keyhandler('u', dump_numa, "dump numa info"); + return 0; +} +__initcall(register_numa_trigger); + diff -r d246b79986d1 -r 3e26719ab827 xen/arch/x86/srat.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/arch/x86/srat.c Wed Oct 25 12:12:01 2006 -0600 @@ -0,0 +1,315 @@ +/* + * ACPI 3.0 based NUMA setup + * Copyright 2004 Andi Kleen, SuSE Labs. + * + * Reads the ACPI SRAT table to figure out what memory belongs to which CPUs. + * + * Called from acpi_numa_init while reading the SRAT and SLIT tables. + * Assumes all memory regions belonging to a single proximity domain + * are in one chunk. Holes between them will be included in the node. + * + * Adapted for Xen: Ryan Harper <ryanh@xxxxxxxxxx> + */ + +#include <xen/init.h> +#include <xen/mm.h> +#include <xen/inttypes.h> +#include <xen/nodemask.h> +#include <xen/acpi.h> +#include <xen/numa.h> +#include <asm/page.h> + +static struct acpi_table_slit *acpi_slit; + +static nodemask_t nodes_parsed __initdata; +static nodemask_t nodes_found __initdata; +static struct node nodes[MAX_NUMNODES] __initdata; +static u8 pxm2node[256] = { [0 ... 255] = 0xff }; + +/* Too small nodes confuse the VM badly. Usually they result + from BIOS bugs. */ +#define NODE_MIN_SIZE (4*1024*1024) + +static int node_to_pxm(int n); + +int pxm_to_node(int pxm) +{ + if ((unsigned)pxm >= 256) + return -1; + /* Extend 0xff to (int)-1 */ + return (signed char)pxm2node[pxm]; +} + +static __init int setup_node(int pxm) +{ + unsigned node = pxm2node[pxm]; + if (node == 0xff) { + if (nodes_weight(nodes_found) >= MAX_NUMNODES) + return -1; + node = first_unset_node(nodes_found); + node_set(node, nodes_found); + pxm2node[pxm] = node; + } + return pxm2node[pxm]; +} + +static __init int conflicting_nodes(u64 start, u64 end) +{ + int i; + for_each_node_mask(i, nodes_parsed) { + struct node *nd = &nodes[i]; + if (nd->start == nd->end) + continue; + if (nd->end > start && nd->start < end) + return i; + if (nd->end == end && nd->start == start) + return i; + } + return -1; +} + +static __init void cutoff_node(int i, u64 start, u64 end) +{ + struct node *nd = &nodes[i]; + if (nd->start < start) { + nd->start = start; + if (nd->end < nd->start) + nd->start = nd->end; + } + if (nd->end > end) { + nd->end = end; + if (nd->start > nd->end) + nd->start = nd->end; + } +} + +static __init void bad_srat(void) +{ + int i; + printk(KERN_ERR "SRAT: SRAT not used.\n"); + acpi_numa = -1; + for (i = 0; i < MAX_LOCAL_APIC; i++) + apicid_to_node[i] = NUMA_NO_NODE; +} + +static __init inline int srat_disabled(void) +{ + return numa_off || acpi_numa < 0; +} + +/* + * A lot of BIOS fill in 10 (= no distance) everywhere. This messes + * up the NUMA heuristics which wants the local node to have a smaller + * distance than the others. + * Do some quick checks here and only use the SLIT if it passes. + */ +static __init int slit_valid(struct acpi_table_slit *slit) +{ + int i, j; + int d = slit->localities; + for (i = 0; i < d; i++) { + for (j = 0; j < d; j++) { + u8 val = slit->entry[d*i + j]; + if (i == j) { + if (val != 10) + return 0; + } else if (val <= 10) + return 0; + } + } + return 1; +} + +/* Callback for SLIT parsing */ +void __init acpi_numa_slit_init(struct acpi_table_slit *slit) +{ + if (!slit_valid(slit)) { + printk(KERN_INFO "ACPI: SLIT table looks invalid. Not used.\n"); + return; + } + acpi_slit = slit; +} + +/* Callback for Proximity Domain -> LAPIC mapping */ +void __init +acpi_numa_processor_affinity_init(struct acpi_table_processor_affinity *pa) +{ + int pxm, node; + if (srat_disabled()) + return; + if (pa->header.length != sizeof(struct acpi_table_processor_affinity)) { bad_srat(); + return; + } + if (pa->flags.enabled == 0) + return; + pxm = pa->proximity_domain; + node = setup_node(pxm); + if (node < 0) { + printk(KERN_ERR "SRAT: Too many proximity domains %x\n", pxm); + bad_srat(); + return; + } + apicid_to_node[pa->apic_id] = node; + acpi_numa = 1; + printk(KERN_INFO "SRAT: PXM %u -> APIC %u -> Node %u\n", + pxm, pa->apic_id, node); +} + +/* Callback for parsing of the Proximity Domain <-> Memory Area mappings */ +void __init +acpi_numa_memory_affinity_init(struct acpi_table_memory_affinity *ma) +{ + struct node *nd; + u64 start, end; + int node, pxm; + int i; + + if (srat_disabled()) + return; + if (ma->header.length != sizeof(struct acpi_table_memory_affinity)) { + bad_srat(); + return; + } + if (ma->flags.enabled == 0) + return; + start = ma->base_addr_lo | ((u64)ma->base_addr_hi << 32); + end = start + (ma->length_lo | ((u64)ma->length_hi << 32)); + pxm = ma->proximity_domain; + node = setup_node(pxm); + if (node < 0) { + printk(KERN_ERR "SRAT: Too many proximity domains.\n"); + bad_srat(); + return; + } + /* It is fine to add this area to the nodes data it will be used later*/ + if (ma->flags.hot_pluggable == 1) + printk(KERN_INFO "SRAT: hot plug zone found %"PRIx64" - %"PRIx64" \n", + start, end); + i = conflicting_nodes(start, end); + if (i == node) { + printk(KERN_WARNING + "SRAT: Warning: PXM %d (%"PRIx64"-%"PRIx64") overlaps with itself (%" + PRIx64"-%"PRIx64")\n", pxm, start, end, nodes[i].start, nodes[i].end); + } else if (i >= 0) { + printk(KERN_ERR + "SRAT: PXM %d (%"PRIx64"-%"PRIx64") overlaps with PXM %d (%" + PRIx64"-%"PRIx64")\n", pxm, start, end, node_to_pxm(i), + nodes[i].start, nodes[i].end); + bad_srat(); + return; + } + nd = &nodes[node]; + if (!node_test_and_set(node, nodes_parsed)) { + nd->start = start; + nd->end = end; + } else { + if (start < nd->start) + nd->start = start; + if (nd->end < end) + nd->end = end; + } + printk(KERN_INFO "SRAT: Node %u PXM %u %"PRIx64"-%"PRIx64"\n", node, pxm, + nd->start, nd->end); +} + +/* Sanity check to catch more bad SRATs (they are amazingly common). + Make sure the PXMs cover all memory. */ +static int nodes_cover_memory(void) +{ + int i; + u64 pxmram, e820ram; + + pxmram = 0; + for_each_node_mask(i, nodes_parsed) { + u64 s = nodes[i].start >> PAGE_SHIFT; + u64 e = nodes[i].end >> PAGE_SHIFT; + pxmram += e - s; + } + + e820ram = max_page; + /* We seem to lose 3 pages somewhere. Allow a bit of slack. */ + if ((long)(e820ram - pxmram) >= 1*1024*1024) { + printk(KERN_ERR "SRAT: PXMs only cover %"PRIu64"MB of your %" + PRIu64"MB e820 RAM. Not used.\n", + (pxmram << PAGE_SHIFT) >> 20, + (e820ram << PAGE_SHIFT) >> 20); + return 0; + } + return 1; +} + +static void unparse_node(int node) +{ + int i; + node_clear(node, nodes_parsed); + for (i = 0; i < MAX_LOCAL_APIC; i++) { + if (apicid_to_node[i] == node) + apicid_to_node[i] = NUMA_NO_NODE; + } +} + +void __init acpi_numa_arch_fixup(void) {} + +/* Use the information discovered above to actually set up the nodes. */ +int __init acpi_scan_nodes(u64 start, u64 end) +{ + int i; + + /* First clean up the node list */ + for (i = 0; i < MAX_NUMNODES; i++) { + cutoff_node(i, start, end); + if ((nodes[i].end - nodes[i].start) < NODE_MIN_SIZE) + unparse_node(i); + } + + if (acpi_numa <= 0) + return -1; + + if (!nodes_cover_memory()) { + bad_srat(); + return -1; + } + + memnode_shift = compute_hash_shift(nodes, MAX_NUMNODES); + if (memnode_shift < 0) { + printk(KERN_ERR + "SRAT: No NUMA node hash function found. Contact maintainer\n"); + bad_srat(); + return -1; + } + + /* Finally register nodes */ + for_each_node_mask(i, nodes_parsed) + setup_node_bootmem(i, nodes[i].start, nodes[i].end); + for (i = 0; i < NR_CPUS; i++) { + if (cpu_to_node[i] == NUMA_NO_NODE) + continue; + if (!node_isset(cpu_to_node[i], nodes_parsed)) + numa_set_node(i, NUMA_NO_NODE); + } + numa_init_array(); + return 0; +} + +static int node_to_pxm(int n) +{ + int i; + if (pxm2node[n] == n) + return n; + for (i = 0; i < 256; i++) + if (pxm2node[i] == n) + return i; + return 0; +} + +int __node_distance(int a, int b) +{ + int index; + + if (!acpi_slit) + return a == b ? 10 : 20; + index = acpi_slit->localities * node_to_pxm(a); + return acpi_slit->entry[index + node_to_pxm(b)]; +} + +EXPORT_SYMBOL(__node_distance); diff -r d246b79986d1 -r 3e26719ab827 xen/drivers/acpi/numa.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/drivers/acpi/numa.c Wed Oct 25 12:12:01 2006 -0600 @@ -0,0 +1,216 @@ +/* + * acpi_numa.c - ACPI NUMA support + * + * Copyright (C) 2002 Takayoshi Kochi <t-kochi@xxxxxxxxxxxxx> + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + */ +#if 0 +#include <linux/module.h> +#include <linux/kernel.h> +#endif +#include <xen/config.h> +#include <xen/init.h> +#include <xen/types.h> +#include <xen/errno.h> +#include <xen/acpi.h> +#include <xen/numa.h> +#include <acpi/acpi_bus.h> +#include <acpi/acmacros.h> +#include <asm/page.h> /* __va() */ + +#define ACPI_NUMA 0x80000000 +#define _COMPONENT ACPI_NUMA +ACPI_MODULE_NAME("numa") + +extern int __init acpi_table_parse_madt_family(enum acpi_table_id id, + unsigned long madt_size, + int entry_id, + acpi_madt_entry_handler handler, + unsigned int max_entries); + +void __init acpi_table_print_srat_entry(acpi_table_entry_header * header) +{ + + ACPI_FUNCTION_NAME("acpi_table_print_srat_entry"); + + if (!header) + return; + + switch (header->type) { + + case ACPI_SRAT_PROCESSOR_AFFINITY: +#ifdef ACPI_DEBUG_OUTPUT + { + struct acpi_table_processor_affinity *p = + (struct acpi_table_processor_affinity *)header; + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "SRAT Processor (id[0x%02x] eid[0x%02x]) in proximity domain %d %s\n", + p->apic_id, p->lsapic_eid, + p->proximity_domain, + p->flags. + enabled ? "enabled" : "disabled")); + } +#endif /* ACPI_DEBUG_OUTPUT */ + break; + + case ACPI_SRAT_MEMORY_AFFINITY: +#ifdef ACPI_DEBUG_OUTPUT + { + struct acpi_table_memory_affinity *p = + (struct acpi_table_memory_affinity *)header; + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "SRAT Memory (0x%08x%08x length 0x%08x%08x type 0x%x) in proximity domain %d %s%s\n", + p->base_addr_hi, p->base_addr_lo, + p->length_hi, p->length_lo, + p->memory_type, p->proximity_domain, + p->flags. + enabled ? "enabled" : "disabled", + p->flags. + hot_pluggable ? " hot-pluggable" : + "")); + } +#endif /* ACPI_DEBUG_OUTPUT */ + break; + + default: + printk(KERN_WARNING PREFIX + "Found unsupported SRAT entry (type = 0x%x)\n", + header->type); + break; + } +} + +static int __init acpi_parse_slit(unsigned long phys_addr, unsigned long size) +{ + struct acpi_table_slit *slit; + u32 localities; + + if (!phys_addr || !size) + return -EINVAL; + + slit = (struct acpi_table_slit *)__va(phys_addr); + + /* downcast just for %llu vs %lu for i386/ia64 */ + localities = (u32) slit->localities; + + acpi_numa_slit_init(slit); + + return 0; +} + +static int __init +acpi_parse_processor_affinity(acpi_table_entry_header * header, + const unsigned long end) +{ + struct acpi_table_processor_affinity *processor_affinity; + + processor_affinity = (struct acpi_table_processor_affinity *)header; + if (!processor_affinity) + return -EINVAL; + + acpi_table_print_srat_entry(header); + + /* let architecture-dependent part to do it */ + acpi_numa_processor_affinity_init(processor_affinity); + + return 0; +} + +static int __init +acpi_parse_memory_affinity(acpi_table_entry_header * header, + const unsigned long end) +{ + struct acpi_table_memory_affinity *memory_affinity; + + memory_affinity = (struct acpi_table_memory_affinity *)header; + if (!memory_affinity) + return -EINVAL; + + acpi_table_print_srat_entry(header); + + /* let architecture-dependent part to do it */ + acpi_numa_memory_affinity_init(memory_affinity); + + return 0; +} + +static int __init acpi_parse_srat(unsigned long phys_addr, unsigned long size) +{ + struct acpi_table_srat *srat; + + if (!phys_addr || !size) + return -EINVAL; + + srat = (struct acpi_table_srat *)__va(phys_addr); + + return 0; +} + +int __init +acpi_table_parse_srat(enum acpi_srat_entry_id id, + acpi_madt_entry_handler handler, unsigned int max_entries) +{ + return acpi_table_parse_madt_family(ACPI_SRAT, + sizeof(struct acpi_table_srat), id, + handler, max_entries); +} + +int __init acpi_numa_init(void) +{ + int result; + + /* SRAT: Static Resource Affinity Table */ + result = acpi_table_parse(ACPI_SRAT, acpi_parse_srat); + + if (result > 0) { + result = acpi_table_parse_srat(ACPI_SRAT_PROCESSOR_AFFINITY, + acpi_parse_processor_affinity, + NR_CPUS); + result = acpi_table_parse_srat(ACPI_SRAT_MEMORY_AFFINITY, acpi_parse_memory_affinity, NR_NODE_MEMBLKS); // IA64 specific + } + + /* SLIT: System Locality Information Table */ + result = acpi_table_parse(ACPI_SLIT, acpi_parse_slit); + + acpi_numa_arch_fixup(); + return 0; +} + +#if 0 +int acpi_get_pxm(acpi_handle h) +{ + unsigned long pxm; + acpi_status status; + acpi_handle handle; + acpi_handle phandle = h; + + do { + handle = phandle; + status = acpi_evaluate_integer(handle, "_PXM", NULL, &pxm); + if (ACPI_SUCCESS(status)) + return (int)pxm; + status = acpi_get_parent(handle, &phandle); + } while (ACPI_SUCCESS(status)); + return -1; +} + +EXPORT_SYMBOL(acpi_get_pxm); +#endif diff -r d246b79986d1 -r 3e26719ab827 xen/include/asm-x86/hvm/vpt.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/include/asm-x86/hvm/vpt.h Wed Oct 25 12:12:01 2006 -0600 @@ -0,0 +1,151 @@ +/* + * vpt.h: Virtual Platform Timer definitions + * + * Copyright (c) 2004, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef __ASM_X86_HVM_VPT_H__ +#define __ASM_X86_HVM_VPT_H__ + +#include <xen/config.h> +#include <xen/init.h> +#include <xen/lib.h> +#include <xen/time.h> +#include <xen/errno.h> +#include <xen/time.h> +#include <xen/timer.h> +#include <asm/hvm/vpic.h> + +#define PIT_FREQ 1193181 +#define PIT_BASE 0x40 + +typedef struct PITChannelState { + int count; /* can be 65536 */ + u16 latched_count; + u8 count_latched; + u8 status_latched; + u8 status; + u8 read_state; + u8 write_state; + u8 write_latch; + u8 rw_mode; + u8 mode; + u8 bcd; /* not supported */ + u8 gate; /* timer start */ + s64 count_load_time; + /* irq handling */ + struct vcpu *vcpu; + struct periodic_time *pt; +} PITChannelState; + +typedef struct PITState { + PITChannelState channels[3]; + int speaker_data_on; + int dummy_refresh_clock; +} PITState; + +#define RTC_SIZE 14 +typedef struct RTCState { + uint8_t cmos_data[RTC_SIZE]; /* Only handle time/interrupt part in HV */ + uint8_t cmos_index; + struct tm current_tm; + int irq; + /* second update */ + int64_t next_second_time; + struct timer second_timer; + struct timer second_timer2; + struct vcpu *vcpu; + struct periodic_time *pt; +} RTCState; + +#define FREQUENCE_PMTIMER 3579545 +typedef struct PMTState { + uint32_t pm1_timer; + uint32_t pm1_status; + uint64_t last_gtime; + struct timer timer; + uint64_t scale; + struct vcpu *vcpu; +} PMTState; + +/* + * Abstract layer of periodic time, one short time. + */ +typedef void time_cb(struct vcpu *v, void *opaque); + +struct periodic_time { + char enabled; /* enabled */ + char one_shot; /* one shot time */ + char irq; + char first_injected; /* flag to prevent shadow window */ + u32 pending_intr_nr; /* the couner for pending timer interrupts */ + u32 period; /* frequency in ns */ + u64 period_cycles; /* frequency in cpu cycles */ + s_time_t scheduled; /* scheduled timer interrupt */ + u64 last_plt_gtime; /* platform time when last IRQ is injected */ + struct timer timer; /* ac_timer */ + time_cb *cb; + void *priv; /* ponit back to platform time source */ +}; + +struct pl_time { /* platform time */ + struct periodic_time periodic_tm; + struct PITState vpit; + struct RTCState vrtc; + struct PMTState vpmt; +}; + +static __inline__ s_time_t get_scheduled( + struct vcpu *v, int irq, + struct periodic_time *pt) +{ + if ( is_irq_enabled(v, irq) ) { + return pt->scheduled; + } + else + return -1; +} + +extern u64 hvm_get_guest_time(struct vcpu *v); +/* + * get processor time. + * unit: TSC + */ +static __inline__ int64_t hvm_get_clock(struct vcpu *v) +{ + uint64_t gtsc; + + gtsc = hvm_get_guest_time(v); + return gtsc; +} + +#define ticks_per_sec(v) (v->domain->arch.hvm_domain.tsc_frequency) + +/* to hook the ioreq packet to get the PIT initialization info */ +extern void hvm_hooks_assist(struct vcpu *v); +extern void pickup_deactive_ticks(struct periodic_time *vpit); +extern struct periodic_time *create_periodic_time(u32 period, char irq, char one_shot, time_cb *cb, void *data); +extern void destroy_periodic_time(struct periodic_time *pt); +void pit_init(struct vcpu *v, unsigned long cpu_khz); +void rtc_init(struct vcpu *v, int base, int irq); +void rtc_deinit(struct domain *d); +void pmtimer_init(struct vcpu *v, int base); +void pmtimer_deinit(struct domain *d); +int is_rtc_periodic_irq(void *opaque); +void pt_timer_fn(void *data); +void pit_time_fired(struct vcpu *v, void *priv); + +#endif /* __ASM_X86_HVM_VPT_H__ */ diff -r d246b79986d1 -r 3e26719ab827 xen/include/asm-x86/numa.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/include/asm-x86/numa.h Wed Oct 25 12:12:01 2006 -0600 @@ -0,0 +1,78 @@ +#ifndef _ASM_X8664_NUMA_H +#define _ASM_X8664_NUMA_H 1 + +#include <xen/cpumask.h> + +#define NODES_SHIFT 6 + +extern unsigned char cpu_to_node[]; +extern cpumask_t node_to_cpumask[]; + +#define cpu_to_node(cpu) (cpu_to_node[cpu]) +#define parent_node(node) (node) +#define node_to_first_cpu(node) (__ffs(node_to_cpumask[node])) +#define node_to_cpumask(node) (node_to_cpumask[node]) + +struct node { + u64 start,end; +}; + +extern int compute_hash_shift(struct node *nodes, int numnodes); +extern int pxm_to_node(int nid); + +#define ZONE_ALIGN (1UL << (MAX_ORDER+PAGE_SHIFT)) +#define VIRTUAL_BUG_ON(x) +#define NODEMAPSIZE 0xfff + +extern void numa_add_cpu(int cpu); +extern void numa_init_array(void); +extern int numa_off; + +extern void numa_set_node(int cpu, int node); + +extern void setup_node_bootmem(int nodeid, u64 start, u64 end); +extern unsigned char apicid_to_node[256]; +#ifdef CONFIG_NUMA +extern void __init init_cpu_to_node(void); + +static inline void clear_node_cpumask(int cpu) +{ + clear_bit(cpu, &node_to_cpumask[cpu_to_node(cpu)]); +} + +/* Simple perfect hash to map physical addresses to node numbers */ +extern int memnode_shift; +extern u8 memnodemap[NODEMAPSIZE]; + +struct node_data { + unsigned long node_start_pfn; + unsigned long node_spanned_pages; + unsigned int node_id; +}; + +extern struct node_data node_data[]; + +static inline __attribute__((pure)) int phys_to_nid(unsigned long addr) +{ + unsigned nid; + VIRTUAL_BUG_ON((addr >> memnode_shift) >= NODEMAPSIZE); + nid = memnodemap[addr >> memnode_shift]; + VIRTUAL_BUG_ON(nid >= MAX_NUMNODES || !node_data[nid]); + return nid; +} + +#define NODE_DATA(nid) (&(node_data[nid])) + +#define node_start_pfn(nid) (NODE_DATA(nid)->node_start_pfn) +#define node_end_pfn(nid) (NODE_DATA(nid)->node_start_pfn + \ + NODE_DATA(nid)->node_spanned_pages) + + +#else +#define init_cpu_to_node() do {} while (0) +#define clear_node_cpumask(cpu) do {} while (0) +#endif + +#define NUMA_NO_NODE 0xff + +#endif diff -r d246b79986d1 -r 3e26719ab827 xen/include/xen/nodemask.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/include/xen/nodemask.h Wed Oct 25 12:12:01 2006 -0600 @@ -0,0 +1,338 @@ +#ifndef __LINUX_NODEMASK_H +#define __LINUX_NODEMASK_H + +/* + * Nodemasks provide a bitmap suitable for representing the + * set of Node's in a system, one bit position per Node number. + * + * See detailed comments in the file linux/bitmap.h describing the + * data type on which these nodemasks are based. + * + * For details of nodemask_scnprintf() and nodemask_parse(), + * see bitmap_scnprintf() and bitmap_parse() in lib/bitmap.c. + * + * The available nodemask operations are: + * + * void node_set(node, mask) turn on bit 'node' in mask + * void node_clear(node, mask) turn off bit 'node' in mask + * void nodes_setall(mask) set all bits + * void nodes_clear(mask) clear all bits + * int node_isset(node, mask) true iff bit 'node' set in mask + * int node_test_and_set(node, mask) test and set bit 'node' in mask + * + * void nodes_and(dst, src1, src2) dst = src1 & src2 [intersection] + * void nodes_or(dst, src1, src2) dst = src1 | src2 [union] + * void nodes_xor(dst, src1, src2) dst = src1 ^ src2 + * void nodes_andnot(dst, src1, src2) dst = src1 & ~src2 + * void nodes_complement(dst, src) dst = ~src + * + * int nodes_equal(mask1, mask2) Does mask1 == mask2? + * int nodes_intersects(mask1, mask2) Do mask1 and mask2 intersect? + * int nodes_subset(mask1, mask2) Is mask1 a subset of mask2? + * int nodes_empty(mask) Is mask empty (no bits sets)? + * int nodes_full(mask) Is mask full (all bits sets)? + * int nodes_weight(mask) Hamming weight - number of set bits + * + * void nodes_shift_right(dst, src, n) Shift right + * void nodes_shift_left(dst, src, n) Shift left + * + * int first_node(mask) Number lowest set bit, or MAX_NUMNODES + * int next_node(node, mask) Next node past 'node', or MAX_NUMNODES + * int first_unset_node(mask) First node not set in mask, or + * MAX_NUMNODES. + * + * nodemask_t nodemask_of_node(node) Return nodemask with bit 'node' set + * NODE_MASK_ALL Initializer - all bits set + * NODE_MASK_NONE Initializer - no bits set + * unsigned long *nodes_addr(mask) Array of unsigned long's in mask + * + * int nodemask_scnprintf(buf, len, mask) Format nodemask for printing + * int nodemask_parse(ubuf, ulen, mask) Parse ascii string as nodemask + * + * for_each_node_mask(node, mask) for-loop node over mask + * + * int num_online_nodes() Number of online Nodes + * int num_possible_nodes() Number of all possible Nodes + * + * int node_online(node) Is some node online? + * int node_possible(node) Is some node possible? + * + * int any_online_node(mask) First online node in mask + * + * node_set_online(node) set bit 'node' in node_online_map + * node_set_offline(node) clear bit 'node' in node_online_map + * + * for_each_node(node) for-loop node over node_possible_map + * for_each_online_node(node) for-loop node over node_online_map + * + * Subtlety: + * 1) The 'type-checked' form of node_isset() causes gcc (3.3.2, anyway) + * to generate slightly worse code. So use a simple one-line #define + * for node_isset(), instead of wrapping an inline inside a macro, the + * way we do the other calls. + */ + +#include <xen/kernel.h> +#include <xen/bitmap.h> +#include <xen/numa.h> + +typedef struct { DECLARE_BITMAP(bits, MAX_NUMNODES); } nodemask_t; +extern nodemask_t _unused_nodemask_arg_; + +#define node_set(node, dst) __node_set((node), &(dst)) +static inline void __node_set(int node, volatile nodemask_t *dstp) +{ + set_bit(node, dstp->bits); +} + +#define node_clear(node, dst) __node_clear((node), &(dst)) +static inline void __node_clear(int node, volatile nodemask_t *dstp) +{ + clear_bit(node, dstp->bits); +} + +#define nodes_setall(dst) __nodes_setall(&(dst), MAX_NUMNODES) +static inline void __nodes_setall(nodemask_t *dstp, int nbits) +{ + bitmap_fill(dstp->bits, nbits); +} + +#define nodes_clear(dst) __nodes_clear(&(dst), MAX_NUMNODES) +static inline void __nodes_clear(nodemask_t *dstp, int nbits) +{ + bitmap_zero(dstp->bits, nbits); +} + +/* No static inline type checking - see Subtlety (1) above. */ +#define node_isset(node, nodemask) test_bit((node), (nodemask).bits) + +#define node_test_and_set(node, nodemask) \ + __node_test_and_set((node), &(nodemask)) +static inline int __node_test_and_set(int node, nodemask_t *addr) +{ + return test_and_set_bit(node, addr->bits); +} + +#define nodes_and(dst, src1, src2) \ + __nodes_and(&(dst), &(src1), &(src2), MAX_NUMNODES) +static inline void __nodes_and(nodemask_t *dstp, const nodemask_t *src1p, + const nodemask_t *src2p, int nbits) +{ + bitmap_and(dstp->bits, src1p->bits, src2p->bits, nbits); +} + +#define nodes_or(dst, src1, src2) \ + __nodes_or(&(dst), &(src1), &(src2), MAX_NUMNODES) +static inline void __nodes_or(nodemask_t *dstp, const nodemask_t *src1p, + const nodemask_t *src2p, int nbits) +{ + bitmap_or(dstp->bits, src1p->bits, src2p->bits, nbits); +} + +#define nodes_xor(dst, src1, src2) \ + __nodes_xor(&(dst), &(src1), &(src2), MAX_NUMNODES) +static inline void __nodes_xor(nodemask_t *dstp, const nodemask_t *src1p, + const nodemask_t *src2p, int nbits) +{ + bitmap_xor(dstp->bits, src1p->bits, src2p->bits, nbits); +} + +#define nodes_andnot(dst, src1, src2) \ + __nodes_andnot(&(dst), &(src1), &(src2), MAX_NUMNODES) +static inline void __nodes_andnot(nodemask_t *dstp, const nodemask_t *src1p, + const nodemask_t *src2p, int nbits) +{ + bitmap_andnot(dstp->bits, src1p->bits, src2p->bits, nbits); +} + +#define nodes_complement(dst, src) \ + __nodes_complement(&(dst), &(src), MAX_NUMNODES) +static inline void __nodes_complement(nodemask_t *dstp, + const nodemask_t *srcp, int nbits) +{ + bitmap_complement(dstp->bits, srcp->bits, nbits); +} + +#define nodes_equal(src1, src2) \ + __nodes_equal(&(src1), &(src2), MAX_NUMNODES) +static inline int __nodes_equal(const nodemask_t *src1p, + const nodemask_t *src2p, int nbits) +{ + return bitmap_equal(src1p->bits, src2p->bits, nbits); +} + +#define nodes_intersects(src1, src2) \ + __nodes_intersects(&(src1), &(src2), MAX_NUMNODES) +static inline int __nodes_intersects(const nodemask_t *src1p, + const nodemask_t *src2p, int nbits) +{ + return bitmap_intersects(src1p->bits, src2p->bits, nbits); +} + +#define nodes_subset(src1, src2) \ + __nodes_subset(&(src1), &(src2), MAX_NUMNODES) +static inline int __nodes_subset(const nodemask_t *src1p, + const nodemask_t *src2p, int nbits) +{ + return bitmap_subset(src1p->bits, src2p->bits, nbits); +} + +#define nodes_empty(src) __nodes_empty(&(src), MAX_NUMNODES) +static inline int __nodes_empty(const nodemask_t *srcp, int nbits) +{ + return bitmap_empty(srcp->bits, nbits); +} + +#define nodes_full(nodemask) __nodes_full(&(nodemask), MAX_NUMNODES) +static inline int __nodes_full(const nodemask_t *srcp, int nbits) +{ + return bitmap_full(srcp->bits, nbits); +} + +#define nodes_weight(nodemask) __nodes_weight(&(nodemask), MAX_NUMNODES) +static inline int __nodes_weight(const nodemask_t *srcp, int nbits) +{ + return bitmap_weight(srcp->bits, nbits); +} + +#define nodes_shift_right(dst, src, n) \ + __nodes_shift_right(&(dst), &(src), (n), MAX_NUMNODES) +static inline void __nodes_shift_right(nodemask_t *dstp, + const nodemask_t *srcp, int n, int nbits) +{ + bitmap_shift_right(dstp->bits, srcp->bits, n, nbits); +} + +#define nodes_shift_left(dst, src, n) \ + __nodes_shift_left(&(dst), &(src), (n), MAX_NUMNODES) +static inline void __nodes_shift_left(nodemask_t *dstp, + const nodemask_t *srcp, int n, int nbits) +{ + bitmap_shift_left(dstp->bits, srcp->bits, n, nbits); +} + +/* FIXME: better would be to fix all architectures to never return + > MAX_NUMNODES, then the silly min_ts could be dropped. */ + +#define first_node(src) __first_node(&(src)) +static inline int __first_node(const nodemask_t *srcp) +{ + return min_t(int, MAX_NUMNODES, find_first_bit(srcp->bits, MAX_NUMNODES)); +} + +#define next_node(n, src) __next_node((n), &(src)) +static inline int __next_node(int n, const nodemask_t *srcp) +{ + return min_t(int,MAX_NUMNODES,find_next_bit(srcp->bits, MAX_NUMNODES, n+1)); +} + +#define nodemask_of_node(node) \ +({ \ + typeof(_unused_nodemask_arg_) m; \ + if (sizeof(m) == sizeof(unsigned long)) { \ + m.bits[0] = 1UL<<(node); \ + } else { \ + nodes_clear(m); \ + node_set((node), m); \ + } \ + m; \ +}) + +#define first_unset_node(mask) __first_unset_node(&(mask)) +static inline int __first_unset_node(const nodemask_t *maskp) +{ + return min_t(int,MAX_NUMNODES, + find_first_zero_bit(maskp->bits, MAX_NUMNODES)); +} + +#define NODE_MASK_LAST_WORD BITMAP_LAST_WORD_MASK(MAX_NUMNODES) + +#if MAX_NUMNODES <= BITS_PER_LONG + +#define NODE_MASK_ALL \ +((nodemask_t) { { \ + [BITS_TO_LONGS(MAX_NUMNODES)-1] = NODE_MASK_LAST_WORD \ +} }) + +#else + +#define NODE_MASK_ALL \ +((nodemask_t) { { \ + [0 ... BITS_TO_LONGS(MAX_NUMNODES)-2] = ~0UL, \ + [BITS_TO_LONGS(MAX_NUMNODES)-1] = NODE_MASK_LAST_WORD \ +} }) + +#endif + +#define NODE_MASK_NONE \ +((nodemask_t) { { \ + [0 ... BITS_TO_LONGS(MAX_NUMNODES)-1] = 0UL \ +} }) + +#define nodes_addr(src) ((src).bits) + +#if 0 +#define nodemask_scnprintf(buf, len, src) \ + __nodemask_scnprintf((buf), (len), &(src), MAX_NUMNODES) +static inline int __nodemask_scnprintf(char *buf, int len, + const nodemask_t *srcp, int nbits) +{ + return bitmap_scnprintf(buf, len, srcp->bits, nbits); +} + +#define nodemask_parse(ubuf, ulen, dst) \ + __nodemask_parse((ubuf), (ulen), &(dst), MAX_NUMNODES) +static inline int __nodemask_parse(const char __user *buf, int len, + nodemask_t *dstp, int nbits) +{ + return bitmap_parse(buf, len, dstp->bits, nbits); +} +#endif + +#if MAX_NUMNODES > 1 +#define for_each_node_mask(node, mask) \ + for ((node) = first_node(mask); \ + (node) < MAX_NUMNODES; \ + (node) = next_node((node), (mask))) +#else /* MAX_NUMNODES == 1 */ +#define for_each_node_mask(node, mask) \ + if (!nodes_empty(mask)) \ + for ((node) = 0; (node) < 1; (node)++) +#endif /* MAX_NUMNODES */ + +/* + * The following particular system nodemasks and operations + * on them manage all possible and online nodes. + */ + +extern nodemask_t node_online_map; +extern nodemask_t node_possible_map; + +#if MAX_NUMNODES > 1 +#define num_online_nodes() nodes_weight(node_online_map) +#define num_possible_nodes() nodes_weight(node_possible_map) +#define node_online(node) node_isset((node), node_online_map) +#define node_possible(node) node_isset((node), node_possible_map) +#else +#define num_online_nodes() 1 +#define num_possible_nodes() 1 +#define node_online(node) ((node) == 0) +#define node_possible(node) ((node) == 0) +#endif + +#define any_online_node(mask) \ +({ \ + int node; \ + for_each_node_mask(node, (mask)) \ + if (node_online(node)) \ + break; \ + node; \ +}) + +#define node_set_online(node) set_bit((node), node_online_map.bits) +#define node_set_offline(node) clear_bit((node), node_online_map.bits) + +#define for_each_node(node) for_each_node_mask((node), node_possible_map) +#define for_each_online_node(node) for_each_node_mask((node), node_online_map) + +#endif /* __LINUX_NODEMASK_H */ diff -r d246b79986d1 -r 3e26719ab827 xen/include/xen/numa.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/include/xen/numa.h Wed Oct 25 12:12:01 2006 -0600 @@ -0,0 +1,13 @@ +#ifndef _XEN_NUMA_H +#define _XEN_NUMA_H + +#include <xen/config.h> +#include <asm/numa.h> + +#ifndef NODES_SHIFT +#define NODES_SHIFT 0 +#endif + +#define MAX_NUMNODES (1 << NODES_SHIFT) + +#endif /* _XEN_NUMA_H */ diff -r d246b79986d1 -r 3e26719ab827 xen/include/asm-x86/hvm/vpit.h --- a/xen/include/asm-x86/hvm/vpit.h Tue Oct 24 11:21:48 2006 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,139 +0,0 @@ -/* - * vpit.h: Virtual PIT definitions - * - * Copyright (c) 2004, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 Temple - * Place - Suite 330, Boston, MA 02111-1307 USA. - */ - -#ifndef __ASM_X86_HVM_VPIT_H__ -#define __ASM_X86_HVM_VPIT_H__ - -#include <xen/config.h> -#include <xen/init.h> -#include <xen/lib.h> -#include <xen/time.h> -#include <xen/errno.h> -#include <xen/time.h> -#include <xen/timer.h> -#include <asm/hvm/vpic.h> - -#define PIT_FREQ 1193181 -#define PIT_BASE 0x40 - -typedef struct PITChannelState { - int count; /* can be 65536 */ - u16 latched_count; - u8 count_latched; - u8 status_latched; - u8 status; - u8 read_state; - u8 write_state; - u8 write_latch; - u8 rw_mode; - u8 mode; - u8 bcd; /* not supported */ - u8 gate; /* timer start */ - s64 count_load_time; - /* irq handling */ - struct vcpu *vcpu; - struct periodic_time *pt; -} PITChannelState; - -typedef struct PITState { - PITChannelState channels[3]; - int speaker_data_on; - int dummy_refresh_clock; -} PITState; - -#define RTC_SIZE 14 -typedef struct RTCState { - uint8_t cmos_data[RTC_SIZE]; /* Only handle time/interrupt part in HV */ - uint8_t cmos_index; - struct tm current_tm; - int irq; - /* second update */ - int64_t next_second_time; - struct timer second_timer; - struct timer second_timer2; - struct vcpu *vcpu; - struct periodic_time *pt; -} RTCState; - -/* - * Abstract layer of periodic time, one short time. - */ -typedef void time_cb(struct vcpu *v, void *opaque); - -struct periodic_time { - char enabled; /* enabled */ - char one_shot; /* one shot time */ - char irq; - char first_injected; /* flag to prevent shadow window */ - u32 pending_intr_nr; /* the couner for pending timer interrupts */ - u32 period; /* frequency in ns */ - u64 period_cycles; /* frequency in cpu cycles */ - s_time_t scheduled; /* scheduled timer interrupt */ - u64 last_plt_gtime; /* platform time when last IRQ is injected */ - struct timer timer; /* ac_timer */ - time_cb *cb; - void *priv; /* ponit back to platform time source */ -}; - -struct pl_time { /* platform time */ - struct periodic_time periodic_tm; - struct PITState vpit; - struct RTCState vrtc; - /* TODO: ACPI time */ -}; - -static __inline__ s_time_t get_scheduled( - struct vcpu *v, int irq, - struct periodic_time *pt) -{ - if ( is_irq_enabled(v, irq) ) { - return pt->scheduled; - } - else - return -1; -} - -extern u64 hvm_get_guest_time(struct vcpu *v); -/* - * get processor time. - * unit: TSC - */ -static __inline__ int64_t hvm_get_clock(struct vcpu *v) -{ - uint64_t gtsc; - - gtsc = hvm_get_guest_time(v); - return gtsc; -} - -#define ticks_per_sec(v) (v->domain->arch.hvm_domain.tsc_frequency) - -/* to hook the ioreq packet to get the PIT initialization info */ -extern void hvm_hooks_assist(struct vcpu *v); -extern void pickup_deactive_ticks(struct periodic_time *vpit); -extern struct periodic_time *create_periodic_time(u32 period, char irq, char one_shot, time_cb *cb, void *data); -extern void destroy_periodic_time(struct periodic_time *pt); -void pit_init(struct vcpu *v, unsigned long cpu_khz); -void rtc_init(struct vcpu *v, int base, int irq); -void rtc_deinit(struct domain *d); -int is_rtc_periodic_irq(void *opaque); -void pt_timer_fn(void *data); -void pit_time_fired(struct vcpu *v, void *priv); - -#endif /* __ASM_X86_HVM_VPIT_H__ */ _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |