[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [linux-2.6.18-xen] merge with linux-2.6.18-xen.hg



# HG changeset patch
# User Alex Williamson <alex.williamson@xxxxxx>
# Date 1184078403 21600
# Node ID e57b5bec937fe48ba4d2ba9a8976dffd332def05
# Parent  56e84a427523b38a4aec928599ac837202449665
# Parent  e9c0b1c115872a62aedb298da80a48621f6f958b
merge with linux-2.6.18-xen.hg
---
 arch/i386/kernel/pci-dma-xen.c              |    5 
 arch/i386/kernel/swiotlb.c                  |   30 
 arch/i386/kernel/time-xen.c                 |   10 
 arch/ia64/xen/hypervisor.c                  |    5 
 arch/powerpc/Kconfig                        |   13 
 arch/powerpc/Kconfig.debug                  |   14 
 arch/powerpc/Makefile                       |    1 
 arch/powerpc/boot/Makefile                  |    3 
 arch/powerpc/boot/xen_guest.S               |    7 
 arch/powerpc/configs/xen_maple_defconfig    | 1342 ++++++++++++++++++++++++++++
 arch/powerpc/kernel/cpu_setup_power4.S      |    7 
 arch/powerpc/kernel/prom_init.c             |   34 
 arch/powerpc/kernel/setup-common.c          |    6 
 arch/powerpc/kernel/udbg.c                  |    3 
 arch/powerpc/mm/slb_low.S                   |   17 
 arch/powerpc/platforms/Makefile             |    2 
 arch/powerpc/platforms/pseries/iommu.c      |   11 
 arch/powerpc/platforms/xen/Makefile         |   20 
 arch/powerpc/platforms/xen/balloon.c        |   82 +
 arch/powerpc/platforms/xen/gnttab.c         |  468 +++++++++
 arch/powerpc/platforms/xen/hcall.c          |  749 +++++++++++++++
 arch/powerpc/platforms/xen/reboot.c         |   53 +
 arch/powerpc/platforms/xen/setup.c          |  324 ++++++
 arch/powerpc/platforms/xen/setup.h          |   49 +
 arch/powerpc/platforms/xen/smp.c            |  444 +++++++++
 arch/powerpc/platforms/xen/time.c           |  114 ++
 arch/powerpc/platforms/xen/udbg_xen.c       |  164 +++
 arch/powerpc/platforms/xen/util.c           |   70 +
 arch/powerpc/platforms/xen/xen_guest.S      |   27 
 arch/powerpc/platforms/xen/xencomm.c        |   54 +
 arch/powerpc/sysdev/mpic.c                  |    7 
 arch/powerpc/xmon/xmon.c                    |    3 
 drivers/xen/Kconfig                         |   14 
 drivers/xen/Makefile                        |    4 
 drivers/xen/blkback/xenbus.c                |    6 
 drivers/xen/blkfront/blkfront.c             |   10 
 drivers/xen/blkfront/block.h                |    1 
 drivers/xen/blktap/xenbus.c                 |    4 
 drivers/xen/char/Makefile                   |    3 
 drivers/xen/char/mem.c                      |    8 
 drivers/xen/core/Makefile                   |    1 
 drivers/xen/core/evtchn.c                   |    3 
 drivers/xen/core/gnttab.c                   |   31 
 drivers/xen/core/hypervisor_sysfs.c         |    1 
 drivers/xen/core/xencomm.c                  |  192 ++++
 drivers/xen/netback/Makefile                |    2 
 drivers/xen/netback/accel.c                 |  207 ++++
 drivers/xen/netback/common.h                |   44 
 drivers/xen/netback/netback.c               |    2 
 drivers/xen/netback/xenbus.c                |    9 
 drivers/xen/netfront/Makefile               |    2 
 drivers/xen/netfront/accel.c                |  866 ++++++++++++++++++
 drivers/xen/netfront/netfront.c             |  169 ++-
 drivers/xen/netfront/netfront.h             |  297 ++++++
 drivers/xen/privcmd/Makefile                |    3 
 drivers/xen/privcmd/compat_privcmd.c        |   73 +
 drivers/xen/privcmd/privcmd.c               |   15 
 drivers/xen/util.c                          |    9 
 drivers/xen/xenbus/xenbus_probe.c           |   12 
 drivers/xen/xenbus/xenbus_probe_backend.c   |    7 
 fs/compat_ioctl.c                           |   17 
 include/asm-i386/mach-xen/asm/dma-mapping.h |    6 
 include/asm-i386/mach-xen/asm/io.h          |    4 
 include/asm-ia64/uaccess.h                  |    4 
 include/asm-powerpc/io.h                    |    3 
 include/asm-powerpc/mpic.h                  |    2 
 include/asm-powerpc/page.h                  |    9 
 include/asm-powerpc/udbg.h                  |    1 
 include/asm-powerpc/xen/asm/gnttab_dma.h    |   29 
 include/asm-powerpc/xen/asm/hypercall.h     |   90 +
 include/asm-powerpc/xen/asm/hypervisor.h    |  276 +++++
 include/asm-powerpc/xen/asm/maddr.h         |    7 
 include/asm-powerpc/xen/asm/synch_bitops.h  |  100 ++
 include/asm-x86_64/mach-xen/asm/io.h        |    4 
 include/xen/compat_ioctl.h                  |   45 
 include/xen/gnttab.h                        |    2 
 include/xen/interface/sysctl.h              |   42 
 include/xen/xenbus.h                        |    4 
 include/xen/xencomm.h                       |   51 +
 79 files changed, 6696 insertions(+), 133 deletions(-)

diff -r 56e84a427523 -r e57b5bec937f arch/i386/kernel/pci-dma-xen.c
--- a/arch/i386/kernel/pci-dma-xen.c    Mon Jul 09 09:24:03 2007 -0600
+++ b/arch/i386/kernel/pci-dma-xen.c    Tue Jul 10 08:40:03 2007 -0600
@@ -97,6 +97,9 @@ dma_map_sg(struct device *hwdev, struct 
                        BUG_ON(!sg[i].page);
                        IOMMU_BUG_ON(address_needs_mapping(
                                hwdev, sg[i].dma_address));
+                       IOMMU_BUG_ON(range_straddles_page_boundary(
+                               page_to_pseudophys(sg[i].page) + sg[i].offset,
+                               sg[i].length));
                }
                rc = nents;
        }
@@ -338,7 +341,7 @@ dma_map_single(struct device *dev, void 
        } else {
                dma = gnttab_dma_map_page(virt_to_page(ptr)) +
                      offset_in_page(ptr);
-               IOMMU_BUG_ON(range_straddles_page_boundary(ptr, size));
+               IOMMU_BUG_ON(range_straddles_page_boundary(__pa(ptr), size));
                IOMMU_BUG_ON(address_needs_mapping(dev, dma));
        }
 
diff -r 56e84a427523 -r e57b5bec937f arch/i386/kernel/swiotlb.c
--- a/arch/i386/kernel/swiotlb.c        Mon Jul 09 09:24:03 2007 -0600
+++ b/arch/i386/kernel/swiotlb.c        Tue Jul 10 08:40:03 2007 -0600
@@ -304,6 +304,7 @@ map_single(struct device *hwdev, struct 
        unsigned long flags;
        char *dma_addr;
        unsigned int nslots, stride, index, wrap;
+       struct phys_addr slot_buf;
        int i;
 
        /*
@@ -375,11 +376,27 @@ map_single(struct device *hwdev, struct 
         * This is needed when we sync the memory.  Then we sync the buffer if
         * needed.
         */
-       io_tlb_orig_addr[index] = buffer;
+       slot_buf = buffer;
+       for (i = 0; i < nslots; i++) {
+               slot_buf.page += slot_buf.offset >> PAGE_SHIFT;
+               slot_buf.offset &= PAGE_SIZE - 1;
+               io_tlb_orig_addr[index+i] = slot_buf;
+               slot_buf.offset += 1 << IO_TLB_SHIFT;
+       }
        if ((dir == DMA_TO_DEVICE) || (dir == DMA_BIDIRECTIONAL))
                __sync_single(buffer, dma_addr, size, DMA_TO_DEVICE);
 
        return dma_addr;
+}
+
+struct phys_addr dma_addr_to_phys_addr(char *dma_addr)
+{
+       int index = (dma_addr - iotlb_virt_start) >> IO_TLB_SHIFT;
+       struct phys_addr buffer = io_tlb_orig_addr[index];
+       buffer.offset += (long)dma_addr & ((1 << IO_TLB_SHIFT) - 1);
+       buffer.page += buffer.offset >> PAGE_SHIFT;
+       buffer.offset &= PAGE_SIZE - 1;
+       return buffer;
 }
 
 /*
@@ -391,7 +408,7 @@ unmap_single(struct device *hwdev, char 
        unsigned long flags;
        int i, count, nslots = ALIGN(size, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT;
        int index = (dma_addr - iotlb_virt_start) >> IO_TLB_SHIFT;
-       struct phys_addr buffer = io_tlb_orig_addr[index];
+       struct phys_addr buffer = dma_addr_to_phys_addr(dma_addr);
 
        /*
         * First, sync the memory before unmapping the entry
@@ -431,8 +448,7 @@ static void
 static void
 sync_single(struct device *hwdev, char *dma_addr, size_t size, int dir)
 {
-       int index = (dma_addr - iotlb_virt_start) >> IO_TLB_SHIFT;
-       struct phys_addr buffer = io_tlb_orig_addr[index];
+       struct phys_addr buffer = dma_addr_to_phys_addr(dma_addr);
        BUG_ON((dir != DMA_FROM_DEVICE) && (dir != DMA_TO_DEVICE));
        __sync_single(buffer, dma_addr, size, dir);
 }
@@ -480,7 +496,7 @@ swiotlb_map_single(struct device *hwdev,
         * we can safely return the device addr and not worry about bounce
         * buffering it.
         */
-       if (!range_straddles_page_boundary(ptr, size) &&
+       if (!range_straddles_page_boundary(__pa(ptr), size) &&
            !address_needs_mapping(hwdev, dev_addr))
                return dev_addr;
 
@@ -577,7 +593,9 @@ swiotlb_map_sg(struct device *hwdev, str
        for (i = 0; i < nelems; i++, sg++) {
                dev_addr = gnttab_dma_map_page(sg->page) + sg->offset;
 
-               if (address_needs_mapping(hwdev, dev_addr)) {
+               if (range_straddles_page_boundary(page_to_pseudophys(sg->page)
+                                                 + sg->offset, sg->length)
+                   || address_needs_mapping(hwdev, dev_addr)) {
                        gnttab_dma_unmap_page(dev_addr);
                        buffer.page   = sg->page;
                        buffer.offset = sg->offset;
diff -r 56e84a427523 -r e57b5bec937f arch/i386/kernel/time-xen.c
--- a/arch/i386/kernel/time-xen.c       Mon Jul 09 09:24:03 2007 -0600
+++ b/arch/i386/kernel/time-xen.c       Tue Jul 10 08:40:03 2007 -0600
@@ -130,6 +130,12 @@ static DEFINE_PER_CPU(struct vcpu_runsta
 /* Must be signed, as it's compared with s64 quantities which can be -ve. */
 #define NS_PER_TICK (1000000000LL/HZ)
 
+static void __clock_was_set(void *unused)
+{
+       clock_was_set();
+}
+static DECLARE_WORK(clock_was_set_work, __clock_was_set, NULL);
+
 static inline void __normalize_time(time_t *sec, s64 *nsec)
 {
        while (*nsec >= NSEC_PER_SEC) {
@@ -365,7 +371,6 @@ void do_gettimeofday(struct timeval *tv)
 {
        unsigned long seq;
        unsigned long usec, sec;
-       unsigned long max_ntp_tick;
        unsigned long flags;
        s64 nsec;
        unsigned int cpu;
@@ -677,7 +682,8 @@ irqreturn_t timer_interrupt(int irq, voi
 
        if (shadow_tv_version != HYPERVISOR_shared_info->wc_version) {
                update_wallclock();
-               clock_was_set();
+               if (keventd_up())
+                       schedule_work(&clock_was_set_work);
        }
 
        write_sequnlock(&xtime_lock);
diff -r 56e84a427523 -r e57b5bec937f arch/ia64/xen/hypervisor.c
--- a/arch/ia64/xen/hypervisor.c        Mon Jul 09 09:24:03 2007 -0600
+++ b/arch/ia64/xen/hypervisor.c        Tue Jul 10 08:40:03 2007 -0600
@@ -407,6 +407,11 @@ __xen_destroy_contiguous_region(unsigned
 #include <linux/mm.h>
 #include <xen/interface/xen.h>
 #include <xen/gnttab.h>
+
+void *arch_gnttab_alloc_shared(unsigned long *frames)
+{
+       return __va(frames[0] << PAGE_SHIFT);
+}
 
 static void
 gnttab_map_grant_ref_pre(struct gnttab_map_grant_ref *uop)
diff -r 56e84a427523 -r e57b5bec937f arch/powerpc/Kconfig
--- a/arch/powerpc/Kconfig      Mon Jul 09 09:24:03 2007 -0600
+++ b/arch/powerpc/Kconfig      Tue Jul 10 08:40:03 2007 -0600
@@ -438,6 +438,17 @@ config UDBG_RTAS_CONSOLE
 config UDBG_RTAS_CONSOLE
        bool
        default n
+
+config PPC_XEN
+       bool "Enable Xen compatible kernel"
+       depends on PPC_MULTIPLATFORM && PPC64 && PPC_MAPLE && PPC_PSERIES && SMP
+       select XEN
+       select XEN_PRIVILEGED_GUEST
+       select XEN_UNPRIVILEGED_GUEST
+       select XEN_XENCOMM
+       
+       help
+         This option will compile a kernel compatible with Xen hypervisor
 
 config XICS
        depends on PPC_PSERIES
@@ -1071,6 +1082,8 @@ source "arch/powerpc/Kconfig.debug"
 
 source "security/Kconfig"
 
+source "drivers/xen/Kconfig"
+
 config KEYS_COMPAT
        bool
        depends on COMPAT && KEYS
diff -r 56e84a427523 -r e57b5bec937f arch/powerpc/Kconfig.debug
--- a/arch/powerpc/Kconfig.debug        Mon Jul 09 09:24:03 2007 -0600
+++ b/arch/powerpc/Kconfig.debug        Tue Jul 10 08:40:03 2007 -0600
@@ -160,6 +160,20 @@ config PPC_EARLY_DEBUG_ISERIES
          Select this to enable early debugging for legacy iSeries. You need
          to hit "Ctrl-x Ctrl-x" to see the messages on the console.
 
+config PPC_EARLY_DEBUG_XEN_DOM0
+       bool "Xen Dom0 Console"
+       depends on PPC_XEN
+       help
+         Select this to enable early debugging for Xen Dom0. Setting
+         this will result in a kernel that may not work as a DomU.
+
+config PPC_EARLY_DEBUG_XEN_DOMU
+       bool "Xen DomU Console"
+       depends on PPC_XEN && XEN_UNPRIVILEGED_GUEST
+       help
+         Select this to enable early debugging for Xen DomU. Setting
+         this will result in a kernel that may not work as a Dom0.
+
 endchoice
 
 endmenu
diff -r 56e84a427523 -r e57b5bec937f arch/powerpc/Makefile
--- a/arch/powerpc/Makefile     Mon Jul 09 09:24:03 2007 -0600
+++ b/arch/powerpc/Makefile     Tue Jul 10 08:40:03 2007 -0600
@@ -65,6 +65,7 @@ AFLAGS-$(CONFIG_PPC32)        := -Iarch/$(ARCH)
 AFLAGS-$(CONFIG_PPC32) := -Iarch/$(ARCH)
 CFLAGS-$(CONFIG_PPC64) := -mminimal-toc -mtraceback=none  -mcall-aixdesc
 CFLAGS-$(CONFIG_PPC32) := -Iarch/$(ARCH) -ffixed-r2 -mmultiple
+CFLAGS-$(CONFIG_PPC_XEN) += -Iinclude/asm-$(ARCH)/xen
 CPPFLAGS       += $(CPPFLAGS-y)
 AFLAGS         += $(AFLAGS-y)
 CFLAGS         += -msoft-float -pipe $(CFLAGS-y)
diff -r 56e84a427523 -r e57b5bec937f arch/powerpc/boot/Makefile
--- a/arch/powerpc/boot/Makefile        Mon Jul 09 09:24:03 2007 -0600
+++ b/arch/powerpc/boot/Makefile        Tue Jul 10 08:40:03 2007 -0600
@@ -36,8 +36,11 @@ zliblinuxheader := zlib.h zconf.h zutil.
 $(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) 
$(addprefix $(obj)/,$(zlibheader))
 #$(addprefix $(obj)/,main.o): $(addprefix $(obj)/,zlib.h)
 
+xen_guest-y = xen_guest.S
+
 src-boot := crt0.S string.S prom.c stdio.c main.c div64.S
 src-boot += $(zlib)
+src-boot += $(xen_guest-$(CONFIG_XEN))
 src-boot := $(addprefix $(obj)/, $(src-boot))
 obj-boot := $(addsuffix .o, $(basename $(src-boot)))
 
diff -r 56e84a427523 -r e57b5bec937f arch/powerpc/boot/xen_guest.S
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/arch/powerpc/boot/xen_guest.S     Tue Jul 10 08:40:03 2007 -0600
@@ -0,0 +1,7 @@
+       .section __xen_guest
+       .ascii  "GUEST_OS=linux"
+       .ascii  ",GUEST_VER=xen-3.0"
+       .ascii  ",XEN_VER=xen-3.0"
+       .ascii  ",VIRT_BASE=0x0"
+       .ascii  ",LOADER=generic"
+       .byte   0
diff -r 56e84a427523 -r e57b5bec937f arch/powerpc/configs/xen_maple_defconfig
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/arch/powerpc/configs/xen_maple_defconfig  Tue Jul 10 08:40:03 2007 -0600
@@ -0,0 +1,1342 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.17
+# Mon Jan 15 23:48:47 2007
+#
+CONFIG_PPC64=y
+CONFIG_64BIT=y
+CONFIG_PPC_MERGE=y
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_IRQ_PER_CPU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_PPC=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_COMPAT=y
+CONFIG_SYSVIPC_COMPAT=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_OF=y
+CONFIG_PPC_UDBG_16550=y
+CONFIG_GENERIC_TBSYNC=y
+# CONFIG_DEFAULT_UIMAGE is not set
+
+#
+# Processor support
+#
+CONFIG_POWER4_ONLY=y
+CONFIG_POWER4=y
+CONFIG_PPC_FPU=y
+CONFIG_ALTIVEC=y
+CONFIG_PPC_STD_MMU=y
+CONFIG_VIRT_CPU_ACCOUNTING=y
+CONFIG_SMP=y
+CONFIG_NR_CPUS=32
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION="-Xen"
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+# CONFIG_CPUSETS is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_RT_MUTEXES=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+
+#
+# Block layer
+#
+# CONFIG_BLK_DEV_IO_TRACE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+CONFIG_DEFAULT_DEADLINE=y
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="deadline"
+
+#
+# Platform support
+#
+CONFIG_PPC_MULTIPLATFORM=y
+# CONFIG_PPC_ISERIES is not set
+# CONFIG_EMBEDDED6xx is not set
+# CONFIG_APUS is not set
+CONFIG_PPC_PSERIES=y
+# CONFIG_PPC_PMAC is not set
+CONFIG_PPC_MAPLE=y
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PPC_IBM_CELL_BLADE is not set
+# CONFIG_UDBG_RTAS_CONSOLE is not set
+CONFIG_PPC_XEN=y
+CONFIG_XICS=y
+CONFIG_U3_DART=y
+CONFIG_MPIC=y
+CONFIG_PPC_RTAS=y
+CONFIG_RTAS_ERROR_LOGGING=y
+CONFIG_RTAS_PROC=y
+CONFIG_RTAS_FLASH=y
+# CONFIG_MMIO_NVRAM is not set
+CONFIG_MPIC_BROKEN_U3=y
+CONFIG_IBMVIO=y
+# CONFIG_IBMEBUS is not set
+# CONFIG_PPC_MPC106 is not set
+CONFIG_PPC_970_NAP=y
+# CONFIG_CPU_FREQ is not set
+# CONFIG_WANT_EARLY_SERIAL is not set
+
+#
+# Kernel options
+#
+CONFIG_HZ_100=y
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=100
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_PREEMPT_BKL is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_FORCE_MAX_ZONEORDER=13
+CONFIG_IOMMU_VMERGE=y
+# CONFIG_HOTPLUG_CPU is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+CONFIG_IRQ_ALL_CPUS=y
+# CONFIG_PPC_SPLPAR is not set
+CONFIG_EEH=y
+CONFIG_SCANLOG=y
+CONFIG_LPARCFG=y
+CONFIG_NUMA=y
+CONFIG_NODES_SHIFT=4
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_SELECT_MEMORY_MODEL=y
+# CONFIG_FLATMEM_MANUAL is not set
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_SPARSEMEM=y
+CONFIG_NEED_MULTIPLE_NODES=y
+CONFIG_HAVE_MEMORY_PRESENT=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPARSEMEM_EXTREME=y
+CONFIG_MEMORY_HOTPLUG=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MIGRATION=y
+CONFIG_RESOURCES_64BIT=y
+CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y
+CONFIG_ARCH_MEMORY_PROBE=y
+# CONFIG_PPC_64K_PAGES is not set
+# CONFIG_SCHED_SMT is not set
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
+# CONFIG_PM is not set
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_PPC_I8259=y
+# CONFIG_PPC_INDIRECT_PCI is not set
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCIEPORTBUS is not set
+# CONFIG_PCI_DEBUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+CONFIG_KERNEL_START=0xc000000000000000
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_FWMARK=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+# CONFIG_IP_ROUTE_VERBOSE is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_NET_IPIP=y
+# CONFIG_NET_IPGRE is not set
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=y
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+CONFIG_IPV6=y
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_INET6_XFRM_TUNNEL=y
+CONFIG_INET6_TUNNEL=y
+CONFIG_INET6_XFRM_MODE_TRANSPORT=y
+CONFIG_INET6_XFRM_MODE_TUNNEL=y
+CONFIG_IPV6_TUNNEL=y
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=y
+CONFIG_NETFILTER_NETLINK_QUEUE=y
+CONFIG_NETFILTER_NETLINK_LOG=y
+CONFIG_NETFILTER_XTABLES=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=y
+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_DCCP=y
+CONFIG_NETFILTER_XT_MATCH_ESP=y
+CONFIG_NETFILTER_XT_MATCH_HELPER=y
+CONFIG_NETFILTER_XT_MATCH_LENGTH=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+CONFIG_NETFILTER_XT_MATCH_POLICY=y
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_REALM=y
+CONFIG_NETFILTER_XT_MATCH_SCTP=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
+CONFIG_NETFILTER_XT_MATCH_STRING=y
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=y
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=y
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+CONFIG_IP_NF_CONNTRACK_EVENTS=y
+CONFIG_IP_NF_CONNTRACK_NETLINK=y
+CONFIG_IP_NF_CT_PROTO_SCTP=y
+CONFIG_IP_NF_FTP=y
+CONFIG_IP_NF_IRC=y
+# CONFIG_IP_NF_NETBIOS_NS is not set
+CONFIG_IP_NF_TFTP=y
+CONFIG_IP_NF_AMANDA=y
+CONFIG_IP_NF_PPTP=y
+# CONFIG_IP_NF_H323 is not set
+# CONFIG_IP_NF_SIP is not set
+# CONFIG_IP_NF_QUEUE is not set
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_IPRANGE=y
+CONFIG_IP_NF_MATCH_TOS=y
+CONFIG_IP_NF_MATCH_RECENT=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_DSCP=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_MATCH_OWNER=y
+CONFIG_IP_NF_MATCH_ADDRTYPE=y
+CONFIG_IP_NF_MATCH_HASHLIMIT=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_TARGET_LOG=y
+CONFIG_IP_NF_TARGET_ULOG=y
+CONFIG_IP_NF_TARGET_TCPMSS=y
+CONFIG_IP_NF_NAT=y
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_SAME=y
+CONFIG_IP_NF_NAT_SNMP_BASIC=y
+CONFIG_IP_NF_NAT_IRC=y
+CONFIG_IP_NF_NAT_FTP=y
+CONFIG_IP_NF_NAT_TFTP=y
+CONFIG_IP_NF_NAT_AMANDA=y
+CONFIG_IP_NF_NAT_PPTP=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_TARGET_TOS=y
+CONFIG_IP_NF_TARGET_ECN=y
+CONFIG_IP_NF_TARGET_DSCP=y
+CONFIG_IP_NF_TARGET_TTL=y
+CONFIG_IP_NF_TARGET_CLUSTERIP=y
+CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARP_MANGLE=y
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP6_NF_QUEUE is not set
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_MATCH_RT=y
+CONFIG_IP6_NF_MATCH_OPTS=y
+CONFIG_IP6_NF_MATCH_FRAG=y
+CONFIG_IP6_NF_MATCH_HL=y
+CONFIG_IP6_NF_MATCH_OWNER=y
+CONFIG_IP6_NF_MATCH_IPV6HEADER=y
+CONFIG_IP6_NF_MATCH_AH=y
+CONFIG_IP6_NF_MATCH_EUI64=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_TARGET_LOG=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_TARGET_HL=y
+CONFIG_IP6_NF_RAW=y
+
+#
+# Bridge: Netfilter Configuration
+#
+CONFIG_BRIDGE_NF_EBTABLES=y
+CONFIG_BRIDGE_EBT_BROUTE=y
+CONFIG_BRIDGE_EBT_T_FILTER=y
+CONFIG_BRIDGE_EBT_T_NAT=y
+CONFIG_BRIDGE_EBT_802_3=y
+CONFIG_BRIDGE_EBT_AMONG=y
+CONFIG_BRIDGE_EBT_ARP=y
+CONFIG_BRIDGE_EBT_IP=y
+CONFIG_BRIDGE_EBT_LIMIT=y
+CONFIG_BRIDGE_EBT_MARK=y
+CONFIG_BRIDGE_EBT_PKTTYPE=y
+CONFIG_BRIDGE_EBT_STP=y
+CONFIG_BRIDGE_EBT_VLAN=y
+CONFIG_BRIDGE_EBT_ARPREPLY=y
+CONFIG_BRIDGE_EBT_DNAT=y
+CONFIG_BRIDGE_EBT_MARK_T=y
+CONFIG_BRIDGE_EBT_REDIRECT=y
+CONFIG_BRIDGE_EBT_SNAT=y
+CONFIG_BRIDGE_EBT_LOG=y
+CONFIG_BRIDGE_EBT_ULOG=y
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+CONFIG_BRIDGE=y
+CONFIG_VLAN_8021Q=y
+# CONFIG_DECNET is not set
+CONFIG_LLC=y
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+CONFIG_NET_CLS_ROUTE=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=10240
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+CONFIG_IDE_TASK_IOCTL=y
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+# CONFIG_BLK_DEV_SL82C105 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+CONFIG_BLK_DEV_AMD74XX=y
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT821X is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+# CONFIG_SCSI_PROC_FS is not set
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=y
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=y
+CONFIG_SCSI_FC_ATTRS=y
+CONFIG_SCSI_ISCSI_ATTRS=y
+CONFIG_SCSI_SAS_ATTRS=y
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_IBMVSCSI is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+CONFIG_SCSI_IPR=y
+# CONFIG_SCSI_IPR_TRACE is not set
+# CONFIG_SCSI_IPR_DUMP is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+# CONFIG_WINDFARM is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_IBMVETH=y
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+CONFIG_AMD8111_ETH=y
+# CONFIG_AMD8111E_NAPI is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+CONFIG_E1000=y
+# CONFIG_E1000_NAPI is not set
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+CONFIG_SKY2=y
+CONFIG_SK98LIN=y
+# CONFIG_VIA_VELOCITY is not set
+CONFIG_TIGON3=y
+CONFIG_BNX2=y
+# CONFIG_MV643XX_ETH is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1600
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=1200
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_ICOM is not set
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+CONFIG_HVC_DRIVER=y
+CONFIG_HVC_CONSOLE=y
+# CONFIG_HVC_RTAS is not set
+# CONFIG_HVCS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+CONFIG_HW_RANDOM=y
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_HANGCHECK_TIMER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=y
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+CONFIG_I2C_AMD8111=y
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+CONFIG_INFINIBAND=y
+CONFIG_INFINIBAND_USER_MAD=y
+CONFIG_INFINIBAND_USER_ACCESS=y
+CONFIG_INFINIBAND_ADDR_TRANS=y
+CONFIG_INFINIBAND_MTHCA=y
+CONFIG_INFINIBAND_MTHCA_DEBUG=y
+CONFIG_INFINIBAND_IPOIB=y
+CONFIG_INFINIBAND_IPOIB_DEBUG=y
+CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y
+CONFIG_INFINIBAND_SRP=y
+# CONFIG_INFINIBAND_ISER is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT2_FS_XIP=y
+CONFIG_FS_XIP=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_REISERFS_FS=y
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_PROC_INFO=y
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=y
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_CRAMFS=y
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_ACL_SUPPORT=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf-8"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=y
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=y
+CONFIG_TEXTSEARCH_BM=y
+CONFIG_TEXTSEARCH_FSM=y
+CONFIG_PLIST=y
+
+#
+# Instrumentation Support
+#
+# CONFIG_PROFILING is not set
+# CONFIG_KPROBES is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+CONFIG_DEBUG_SLAB=y
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_FS=y
+# CONFIG_DEBUG_VM is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_DEBUG_STACKOVERFLOW=y
+CONFIG_DEBUG_STACK_USAGE=y
+CONFIG_DEBUGGER=y
+CONFIG_XMON=y
+CONFIG_XMON_DEFAULT=y
+# CONFIG_IRQSTACKS is not set
+CONFIG_BOOTX_TEXT=y
+# CONFIG_PPC_EARLY_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+CONFIG_XEN=y
+CONFIG_XEN_INTERFACE_VERSION=0x00030202
+
+#
+# XEN
+#
+CONFIG_XEN_PRIVILEGED_GUEST=y
+CONFIG_XEN_UNPRIVILEGED_GUEST=y
+CONFIG_XEN_PRIVCMD=y
+CONFIG_XEN_BACKEND=y
+# CONFIG_XEN_PCIDEV_BACKEND is not set
+CONFIG_XEN_BLKDEV_BACKEND=y
+CONFIG_XEN_XENBUS_DEV=y
+CONFIG_XEN_NETDEV_BACKEND=y
+# CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set
+CONFIG_XEN_NETDEV_LOOPBACK=y
+# CONFIG_XEN_TPMDEV_BACKEND is not set
+CONFIG_XEN_BLKDEV_FRONTEND=y
+CONFIG_XEN_NETDEV_FRONTEND=y
+CONFIG_XEN_SCRUB_PAGES=y
+CONFIG_XEN_DISABLE_SERIAL=y
+CONFIG_XEN_SYSFS=y
+# CONFIG_XEN_COMPAT_030002_AND_LATER is not set
+CONFIG_XEN_COMPAT_LATEST_ONLY=y
+# CONFIG_XEN_COMPAT_030002 is not set
+CONFIG_HAVE_ARCH_ALLOC_SKB=y
+CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y
+CONFIG_HAVE_IRQ_IGNORE_UNHANDLED=y
+CONFIG_NO_IDLE_HZ=y
+CONFIG_XEN_DEVMEM=y
+CONFIG_XEN_SKBUFF=y
+CONFIG_XEN_REBOOT=y
+CONFIG_XEN_XENCOMM=y
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=y
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
diff -r 56e84a427523 -r e57b5bec937f arch/powerpc/kernel/cpu_setup_power4.S
--- a/arch/powerpc/kernel/cpu_setup_power4.S    Mon Jul 09 09:24:03 2007 -0600
+++ b/arch/powerpc/kernel/cpu_setup_power4.S    Tue Jul 10 08:40:03 2007 -0600
@@ -73,6 +73,13 @@ 1:
        blr
 
 _GLOBAL(__setup_cpu_ppc970)
+       /*
+        * Do nothing if not running in HV mode
+        */
+       mfmsr   r0
+       rldicl. r0,r0,4,63
+       beqlr
+
        mfspr   r0,SPRN_HID0
        li      r11,5                   /* clear DOZE and SLEEP */
        rldimi  r0,r11,52,8             /* set NAP and DPM */
diff -r 56e84a427523 -r e57b5bec937f arch/powerpc/kernel/prom_init.c
--- a/arch/powerpc/kernel/prom_init.c   Mon Jul 09 09:24:03 2007 -0600
+++ b/arch/powerpc/kernel/prom_init.c   Tue Jul 10 08:40:03 2007 -0600
@@ -188,6 +188,7 @@ static unsigned long __initdata prom_tce
 #define PLATFORM_LPAR          0x0001
 #define PLATFORM_POWERMAC      0x0400
 #define PLATFORM_GENERIC       0x0500
+#define PLATFORM_GENERIC_XEN   (PLATFORM_GENERIC | PLATFORM_LPAR)
 
 static int __initdata of_platform;
 
@@ -1529,6 +1530,14 @@ static int __init prom_find_machine_type
        phandle rtas;
        int x;
 #endif
+#ifdef CONFIG_PPC_XEN
+       phandle xen;
+
+       xen = call_prom("finddevice", 1, 1, ADDR("/xen"));
+       if (PHANDLE_VALID(xen)) {
+               return PLATFORM_GENERIC_XEN;
+       }
+#endif
 
        /* Look for a PowerMac */
        len = prom_getprop(_prom->root, "compatible",
@@ -2262,6 +2271,31 @@ unsigned long __init prom_init(unsigned 
        if (RELOC(of_platform) == PLATFORM_PSERIES)
                prom_initialize_tce_table();
 #endif
+#ifdef CONFIG_PPC_XEN
+       if (RELOC(of_platform) & PLATFORM_LPAR) {
+               phandle xen;
+
+               prom_debug("XXX:checking for Xen OF package\n");
+
+               xen = call_prom("finddevice", 1, 1, ADDR("/xen"));
+               if (PHANDLE_VALID(xen)) {
+                       u64 res[2];
+                       int l;
+                       ulong base;
+
+                       l = prom_getprop(xen, "reserved", res, sizeof (res));
+                       if (l != sizeof(res)) {
+                               prom_panic("Xen reserved prop not exist\n");
+                       }
+                       
+                       base = alloc_down(res[1], PAGE_SIZE, 0);
+                       if (base != res[0]) {
+                               prom_panic("XSI != alloc_down()\n");
+                       }
+                       reserve_mem(res[0], res[1]);
+               }
+       }       
+#endif
 
        /*
         * On non-powermacs, try to instantiate RTAS and puts all CPUs
diff -r 56e84a427523 -r e57b5bec937f arch/powerpc/kernel/setup-common.c
--- a/arch/powerpc/kernel/setup-common.c        Mon Jul 09 09:24:03 2007 -0600
+++ b/arch/powerpc/kernel/setup-common.c        Tue Jul 10 08:40:03 2007 -0600
@@ -387,6 +387,12 @@ void __init smp_setup_cpu_maps(void)
                }
        }
 
+       if (machine_is(xen)) {
+               /* something more inteligent perhaps? */
+               for (cpu = 0; cpu < NR_CPUS; cpu++)
+                       cpu_set(cpu, cpu_possible_map);
+       }
+
 #ifdef CONFIG_PPC64
        /*
         * On pSeries LPAR, we need to know how many cpus
diff -r 56e84a427523 -r e57b5bec937f arch/powerpc/kernel/udbg.c
--- a/arch/powerpc/kernel/udbg.c        Mon Jul 09 09:24:03 2007 -0600
+++ b/arch/powerpc/kernel/udbg.c        Tue Jul 10 08:40:03 2007 -0600
@@ -45,6 +45,9 @@ void __init udbg_early_init(void)
 #elif defined(CONFIG_PPC_EARLY_DEBUG_ISERIES)
        /* For iSeries - hit Ctrl-x Ctrl-x to see the output */
        udbg_init_iseries();
+#elif defined(CONFIG_PPC_EARLY_DEBUG_XEN_DOM0) || \
+       defined(CONFIG_PPC_EARLY_DEBUG_XEN_DOMU)
+       udbg_init_xen();
 #endif
 }
 
diff -r 56e84a427523 -r e57b5bec937f arch/powerpc/mm/slb_low.S
--- a/arch/powerpc/mm/slb_low.S Mon Jul 09 09:24:03 2007 -0600
+++ b/arch/powerpc/mm/slb_low.S Tue Jul 10 08:40:03 2007 -0600
@@ -51,6 +51,23 @@ _GLOBAL(slb_allocate_realmode)
        */
        bne     cr7,1f
 
+#ifdef CONFIG_PPC_XEN
+_GLOBAL(slb_miss_kernel_load_xen_nop)
+       b 3f
+       /* Need to check if it is in the part of our XEN Foreign Map */
+       rldicl  r9,r3,30,63             /* get Xen region */
+       cmpldi  cr7,r9,1                /* cmp this bit set to 1 */
+       bne     cr7,3f
+       /* Xen Linear mapping encoding bits, the "li" instruction below
+        * could be patched below (like the other pages of the linear map)
+        * if we ever wish to map anything other that 4K pages in 
+        * this region, right now it is fine as zero.
+        */
+_GLOBAL(slb_miss_kernel_load_xen_linear)
+       li      r11,0
+       b       slb_finish_load
+3:
+#endif
        /* Linear mapping encoding bits, the "li" instruction below will
         * be patched by the kernel at boot
         */
diff -r 56e84a427523 -r e57b5bec937f arch/powerpc/platforms/Makefile
--- a/arch/powerpc/platforms/Makefile   Mon Jul 09 09:24:03 2007 -0600
+++ b/arch/powerpc/platforms/Makefile   Tue Jul 10 08:40:03 2007 -0600
@@ -12,6 +12,8 @@ obj-$(CONFIG_PPC_86xx)                += 86xx/
 obj-$(CONFIG_PPC_86xx)         += 86xx/
 obj-$(CONFIG_PPC_PSERIES)      += pseries/
 obj-$(CONFIG_PPC_ISERIES)      += iseries/
+# must occur before xen hosting platforms
+obj-$(CONFIG_PPC_XEN)          += xen/
 obj-$(CONFIG_PPC_MAPLE)                += maple/
 obj-$(CONFIG_PPC_CELL)         += cell/
 obj-$(CONFIG_EMBEDDED6xx)      += embedded6xx/
diff -r 56e84a427523 -r e57b5bec937f arch/powerpc/platforms/pseries/iommu.c
--- a/arch/powerpc/platforms/pseries/iommu.c    Mon Jul 09 09:24:03 2007 -0600
+++ b/arch/powerpc/platforms/pseries/iommu.c    Tue Jul 10 08:40:03 2007 -0600
@@ -531,6 +531,17 @@ static void iommu_dev_setup_pSeriesLP(st
         * already allocated.
         */
        dn = pci_device_to_OF_node(dev);
+       if (dn == NULL) {
+#ifdef CONFIG_PPC_XEN
+               /* this becomes possible for Xen Dom0 */
+               DBG("%s, dev %p (%s) has no OF devtree entree\n", __func__,
+                   dev, pci_name(dev));
+               return;
+#else
+               panic("%s, dev %p (%s) has no OF devtree entree\n", __func__,
+                     dev, pci_name(dev));
+#endif
+       }
 
        for (pdn = dn; pdn && PCI_DN(pdn) && !PCI_DN(pdn)->iommu_table;
             pdn = pdn->parent) {
diff -r 56e84a427523 -r e57b5bec937f arch/powerpc/platforms/xen/Makefile
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/arch/powerpc/platforms/xen/Makefile       Tue Jul 10 08:40:03 2007 -0600
@@ -0,0 +1,20 @@
+obj-y  += gnttab.o
+obj-y  += hcall.o
+obj-y  += reboot.o
+obj-y  += setup.o
+obj-y  += smp.o
+obj-y  += time.o
+obj-y  += udbg_xen.o
+obj-y  += xen_guest.o
+obj-y  += xencomm.o
+
+# we need the latest __XEN_INTERFACE_VERSION__ (see xen-compat.h)
+CFLAGS_hcall.o += -D__XEN_TOOLS__
+
+ifndef CONFIG_XEN_BALLOON
+obj-y += balloon.o
+endif
+
+ifndef CONFIG_XEN_UTIL
+obj-y  += util.o
+endif
diff -r 56e84a427523 -r e57b5bec937f arch/powerpc/platforms/xen/balloon.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/arch/powerpc/platforms/xen/balloon.c      Tue Jul 10 08:40:03 2007 -0600
@@ -0,0 +1,82 @@
+/*
+ * 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
+ *
+ * Copyright (C) IBM Corp. 2006
+ *
+ * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
+ */
+
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <asm/hypervisor.h>
+#include "setup.h"
+
+/*
+ * FIXME: Port balloon driver, if ever
+ */
+
+struct page **alloc_empty_pages_and_pagevec(int nr_pages)
+{
+       struct page *page, **pagevec;
+       int i;
+
+       pagevec = kmalloc(sizeof(*pagevec) * nr_pages, GFP_KERNEL);
+       if (pagevec == NULL)
+               return  NULL;
+
+       for (i = 0; i < nr_pages; i++) {
+               page = alloc_foreign_page();
+               BUG_ON(page == NULL);
+               pagevec[i] = page;
+               /* There is no real page backing us yet so it cannot
+                * be scrubbed */
+       }
+
+       return pagevec;
+}
+
+void free_empty_pages_and_pagevec(struct page **pagevec, int nr_pages)
+{
+       int i;
+
+       if (pagevec == NULL)
+               return;
+
+       for (i = 0; i < nr_pages; i++) {
+               free_foreign_page(pagevec[i]);
+       }
+       
+       kfree(pagevec);
+}
+
+void balloon_dealloc_empty_page_range(
+       struct page *page, unsigned long nr_pages)
+{
+       __free_pages(page, get_order(nr_pages * PAGE_SIZE));
+}
+
+void balloon_update_driver_allowance(long delta)
+{
+}
+
+void balloon_release_driver_page(struct page *page)
+{
+       BUG();
+}
+
+EXPORT_SYMBOL_GPL(balloon_update_driver_allowance);
+EXPORT_SYMBOL_GPL(alloc_empty_pages_and_pagevec);
+EXPORT_SYMBOL_GPL(free_empty_pages_and_pagevec);
+EXPORT_SYMBOL_GPL(balloon_release_driver_page);
diff -r 56e84a427523 -r e57b5bec937f arch/powerpc/platforms/xen/gnttab.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/arch/powerpc/platforms/xen/gnttab.c       Tue Jul 10 08:40:03 2007 -0600
@@ -0,0 +1,468 @@
+/*
+ * 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
+ *
+ * Copyright (C) IBM Corp. 2006
+ *
+ * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
+ */
+
+#include <linux/config.h>
+#include <linux/vmalloc.h>
+#include <linux/memory_hotplug.h>
+#include <xen/gnttab.h>
+#include <asm/hypervisor.h>
+#include <xen/interface/grant_table.h>
+#include <asm/pgtable.h>
+#include <asm/sections.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/prom.h>
+#include <asm/cacheflush.h>
+#include "setup.h"
+#include "../pseries/plpar_wrappers.h"
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(fmt...) printk(KERN_EMERG fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+#define NR_GRANT_FRAMES 4
+
+struct address_space xen_foreign_dummy_mapping;
+
+static ulong foreign_map_pfn;
+static ulong foreign_map_pgs;
+static unsigned long *foreign_map_bitmap;
+
+
+/* hijack _mapcount */
+static inline int gnt_mapcount(struct page *page)
+{
+       return atomic_read(&(page)->_mapcount) + 1;
+}
+
+static inline int gnt_map(struct page *page)
+{
+       /* return true is transition from -1 to 0 */
+       return atomic_inc_and_test(&page->_mapcount);
+}
+
+static inline int gnt_unmap(struct page *page)
+{
+       int val;
+
+       val = atomic_dec_return(&page->_mapcount);
+       if (val < -1) {
+               atomic_inc(&page->_mapcount);
+               printk(KERN_EMERG "%s: %d\n", __func__, val);
+       }
+
+       return (val == -1);
+}
+
+
+static long map_to_linear(ulong paddr)
+{
+       unsigned long vaddr;
+       int psize;
+       unsigned long mode;
+       int slot;
+       uint shift;
+       unsigned long tmp_mode;
+
+       psize = MMU_PAGE_4K;
+       shift = mmu_psize_defs[psize].shift;
+       mode = _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_COHERENT | PP_RWXX;
+       vaddr = (ulong)__va(paddr);
+
+       {
+               unsigned long vpn, hash, hpteg;
+               unsigned long vsid = get_kernel_vsid(vaddr);
+               unsigned long va = (vsid << 28) | (vaddr & 0x0fffffff);
+
+               vpn = va >> shift;
+               tmp_mode = mode;
+               
+               /* Make non-kernel text non-executable */
+               if (!in_kernel_text(vaddr))
+                       tmp_mode = mode | HPTE_R_N;
+
+               hash = hpt_hash(va, shift);
+               hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP);
+
+               BUG_ON(!ppc_md.hpte_insert);
+               slot = ppc_md.hpte_insert(hpteg, va, paddr,
+                                         tmp_mode, HPTE_V_BOLTED, psize);
+               if (slot < 0)
+                       printk(KERN_EMERG
+                              "%s: no more bolted entries "
+                              "HTAB[0x%lx]: 0x%lx\n",
+                              __func__, hpteg, paddr);
+       }
+       return slot;
+}
+
+static unsigned long get_hpte_vsid(ulong slot)
+{
+       unsigned long dword0;
+       unsigned long lpar_rc;
+       unsigned long dummy_word1;
+       unsigned long flags;
+
+       /* Read 1 pte at a time                        */
+       /* Do not need RPN to logical page translation */
+       /* No cross CEC PFT access                     */
+       flags = 0;
+
+       lpar_rc = plpar_pte_read(flags, slot, &dword0, &dummy_word1);
+
+       BUG_ON(lpar_rc != H_SUCCESS);
+
+       return dword0;
+}
+
+static long find_hpte_slot(unsigned long va, int psize)
+{
+       unsigned long hash;
+       unsigned long i, j;
+       long slot;
+       unsigned long want_v, hpte_v;
+
+       hash = hpt_hash(va, mmu_psize_defs[psize].shift);
+       want_v = hpte_encode_v(va, psize);
+
+       for (j = 0; j < 2; j++) {
+               slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
+               for (i = 0; i < HPTES_PER_GROUP; i++) {
+                       hpte_v = get_hpte_vsid(slot);
+
+                       if (HPTE_V_COMPARE(hpte_v, want_v)
+                           && (hpte_v & HPTE_V_VALID)
+                           && (!!(hpte_v & HPTE_V_SECONDARY) == j)) {
+                               /* HPTE matches */
+                               if (j)
+                                       slot = -slot;
+                               return slot;
+                       }
+                       ++slot;
+               }
+               hash = ~hash;
+       }
+
+       return -1;
+} 
+
+static long find_map_slot(ulong ea)
+{
+       int psize = MMU_PAGE_4K;
+       ulong vsid;
+       ulong va;
+
+       vsid = get_kernel_vsid(ea);
+       va = (vsid << 28) | (ea & 0x0fffffff);
+       
+       return find_hpte_slot(va, psize);
+}
+
+
+static void gnttab_pre_unmap_grant_ref(
+       struct gnttab_unmap_grant_ref *unmap, int count)
+{
+       long slot;
+       int i;
+       ulong ea;
+       unsigned long dummy1, dummy2;
+       ulong flags;
+
+       /* paranoia */
+       local_irq_save(flags);
+
+       for (i = 0 ; i < count; i++) {
+               struct page *page;
+
+               ea = (ulong)__va(unmap[i].host_addr);
+               page = virt_to_page(ea);
+               
+               if (!gnt_unmap(page)) {
+                       DBG("%s[0x%x]: skip: 0x%lx, mapcount 0x%x\n",
+                           __func__, i, ea, gnt_mapcount(page));
+                       continue;
+               }
+               slot = find_map_slot(ea);
+               if (slot < 0) {
+                       printk(KERN_EMERG "%s: PTE not found: 0x%lx\n",
+                              __func__, ea);
+                       continue;
+               }
+
+               DBG("%s[0x%x]: 0x%lx: mapcount: 0x%x\n",
+                   __func__, i, ea, gnt_mapcount(page));
+               plpar_pte_remove(0, slot, 0, &dummy1, &dummy2);
+       }
+       local_irq_restore(flags);
+}
+
+static void gnttab_post_map_grant_ref(
+       struct gnttab_map_grant_ref *map, int count)
+{
+       int i;
+       long slot;
+       ulong flags;
+
+       /* paranoia */
+       local_irq_save(flags);
+
+       for (i = 0 ; i < count; i++) {
+               ulong pa = map[i].host_addr;
+               struct page *page;
+
+               if (map[i].status != GNTST_okay) {
+                       printk(KERN_EMERG "%s: status, skip\n", __func__);
+                       continue;
+               }
+
+               BUG_ON(pa < (foreign_map_pfn << PAGE_SHIFT));
+               BUG_ON(pa >= (foreign_map_pfn << PAGE_SHIFT) + 
+                      (foreign_map_pgs << PAGE_SHIFT));
+
+               page = virt_to_page(__va(pa));
+
+               if (gnt_map(page)) {
+#ifdef DEBUG                   
+                       /* we need to get smarted than this */
+                       slot = find_map_slot((ulong)__va(pa));
+                       if (slot >= 0) {
+                               DBG("%s: redundant 0x%lx\n", __func__, pa);
+                               continue;
+                       }
+#endif
+                       slot = map_to_linear(pa);
+                       DBG("%s[0x%x]: 0x%lx, mapcount:0x%x\n",
+                           __func__, i, pa, gnt_mapcount(page));
+
+               } else {
+                       DBG("%s[0x%x] skip 0x%lx, mapcount:0x%x\n",
+                           __func__, i, pa, gnt_mapcount(page));
+               }
+       }
+       local_irq_restore(flags);
+}
+
+int HYPERVISOR_grant_table_op(unsigned int cmd, void *op, unsigned int count)
+{
+       void *desc;
+       void *frame_list = NULL;
+       int argsize;
+       int ret = -ENOMEM;
+
+       switch (cmd) {
+       case GNTTABOP_map_grant_ref:
+               argsize = sizeof(struct gnttab_map_grant_ref);
+               break;
+       case GNTTABOP_unmap_grant_ref:
+               gnttab_pre_unmap_grant_ref(op, count);
+               argsize = sizeof(struct gnttab_unmap_grant_ref);
+               break;
+       case GNTTABOP_setup_table: {
+               struct gnttab_setup_table setup;
+
+               memcpy(&setup, op, sizeof(setup));
+               argsize = sizeof(setup);
+
+               frame_list = xencomm_map(
+                       xen_guest_handle(setup.frame_list),
+                       (sizeof(*xen_guest_handle(setup.frame_list)) 
+                       * setup.nr_frames));
+
+               if (frame_list == NULL)
+                       return -ENOMEM;
+
+               set_xen_guest_handle(setup.frame_list, frame_list);
+               memcpy(op, &setup, sizeof(setup));
+               }
+               break;
+       case GNTTABOP_dump_table:
+               argsize = sizeof(struct gnttab_dump_table);
+               break;
+       case GNTTABOP_transfer:
+               BUG();
+               argsize = sizeof(struct gnttab_transfer);
+               break;
+       case GNTTABOP_copy:
+               argsize = sizeof(struct gnttab_transfer);
+               break;
+       case GNTTABOP_query_size:
+               argsize = sizeof(struct gnttab_query_size);
+               break;
+       default:
+               printk(KERN_EMERG "%s: unknown grant table op %d\n",
+                      __func__, cmd);
+               return -ENOSYS;
+       }
+
+       desc = xencomm_map_no_alloc(op, argsize);
+       if (desc) {
+               ret = plpar_hcall_norets(XEN_MARK(__HYPERVISOR_grant_table_op),
+                                        cmd, desc, count);
+               if (!ret && cmd == GNTTABOP_map_grant_ref)
+                       gnttab_post_map_grant_ref(op, count);
+               xencomm_free(desc);
+       }
+       xencomm_free(frame_list);
+
+       return ret;
+}
+EXPORT_SYMBOL(HYPERVISOR_grant_table_op);
+
+static ulong find_grant_maps(void)
+{
+       struct device_node *xen;
+       u64 *gm;
+       u64 _gm[2];
+       u64 expect;
+
+       /* This value is currently hardcoded into the SLB logic that
+        * it written in assempler, See
+        * slb_miss_kernel_load_xen_linear for more information.
+        * Anything else and we can not run. */
+       expect = 34 - PAGE_SHIFT;
+
+       xen = of_find_node_by_path("/xen");
+
+       /* 
+        * The foreign is 2x2 Cells.
+        * The first entry is log2 of the base page frame.
+        * The second is the number of pages
+        */
+       gm = (u64 *)get_property(xen, "foreign-map", NULL);
+       if (gm == NULL) {
+               if (!is_initial_xendomain()) {
+                       printk("OF: /xen/foreign-map not present\n");
+                       _gm[0] = expect;
+                       _gm[1] = 2048;
+                       gm = _gm;
+               } else
+                       panic("OF: /xen/foreign-map must be present\n");
+       }
+
+       if (gm[0] != expect)
+               panic("foreign-map is 0x%lx, expect 0x%lx\n",
+                     gm[0], expect);
+
+       foreign_map_pfn = 1UL << gm[0];
+       return gm[1];
+}
+
+static void setup_foreign_segment(void)
+{
+       extern int *slb_miss_kernel_load_xen_nop;
+       ulong iaddr = (ulong)slb_miss_kernel_load_xen_nop;
+
+       /* By default Linux will branch around this logic we replace
+        * the branch with a NOP to turn the logic on */
+       *slb_miss_kernel_load_xen_nop = 0x60000000;
+       flush_icache_range(iaddr, iaddr + 4);
+}
+
+struct page *alloc_foreign_page(void)
+{
+       ulong bit;
+       do {
+               bit = find_first_zero_bit(foreign_map_bitmap,
+                                         foreign_map_pgs);
+               if (bit >= foreign_map_pgs)
+                       return NULL;
+       } while (test_and_set_bit(bit, foreign_map_bitmap) == 1);
+
+       return pfn_to_page(foreign_map_pfn + bit);
+}
+
+void free_foreign_page(struct page *page)
+{
+       ulong bit = page_to_pfn(page) - foreign_map_pfn;
+
+       BUG_ON(bit >= foreign_map_pgs);
+       BUG_ON(!test_bit(bit, foreign_map_bitmap));
+
+       clear_bit(bit, foreign_map_bitmap);
+}
+
+static void setup_grant_area(void)
+{
+       ulong pgs;
+       int err;
+       struct zone *zone;
+       struct pglist_data *pgdata;
+       int nid;
+
+       pgs = find_grant_maps();
+       setup_foreign_segment();
+
+       printk("%s: Xen VIO will use a foreign address space of 0x%lx pages\n",
+              __func__, pgs);
+
+       /* add pages to the zone */
+       nid = 0;
+       pgdata = NODE_DATA(nid);
+       zone = pgdata->node_zones;
+
+       err = __add_pages(zone, foreign_map_pfn, pgs);
+
+       if (err < 0) {
+               printk(KERN_EMERG "%s: add_pages(0x%lx, 0x%lx) = %d\n",
+                      __func__, foreign_map_pfn, pgs, err);
+               BUG();
+       }
+
+       /* create a bitmap to manage these pages */
+       foreign_map_bitmap = kmalloc(BITS_TO_LONGS(pgs) * sizeof(long),
+                                    GFP_KERNEL);
+       if (foreign_map_bitmap == NULL) {
+               printk(KERN_EMERG 
+                      "%s: could not allocate foreign_map_bitmap to "
+                      "manage 0x%lx foreign pages\n", __func__, pgs);
+               BUG();
+       }
+       /* I'm paranoid so make sure we assign the top bits so we
+        * don't give them away */
+       bitmap_fill(&foreign_map_bitmap[BITS_TO_LONGS(pgs) - 1],
+                   BITS_PER_LONG);
+       /* now clear all the real bits */
+       bitmap_zero(foreign_map_bitmap, pgs);
+
+       foreign_map_pgs = pgs;
+}
+
+void *arch_gnttab_alloc_shared(unsigned long *frames)
+{
+       void *shared;
+       ulong pa = frames[0] << PAGE_SHIFT;
+       static int resume;
+
+       shared = ioremap(pa, PAGE_SIZE * NR_GRANT_FRAMES);
+       BUG_ON(shared == NULL);
+       printk("%s: grant table at %p\n", __func__, shared);
+
+       /* no need to do the rest of this if we are resuming */
+       if (!resume)
+               setup_grant_area();
+
+       resume = 1;
+
+       return shared;
+}
diff -r 56e84a427523 -r e57b5bec937f arch/powerpc/platforms/xen/hcall.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/arch/powerpc/platforms/xen/hcall.c        Tue Jul 10 08:40:03 2007 -0600
@@ -0,0 +1,749 @@
+/*
+ * 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
+ *
+ * Copyright (C) IBM Corp. 2006, 2007
+ *
+ * Authors: Hollis Blanchard <hollisb@xxxxxxxxxx>
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/gfp.h>
+#include <linux/module.h>
+#include <xen/interface/xen.h>
+#include <xen/interface/domctl.h>
+#include <xen/interface/sysctl.h>
+#include <xen/interface/platform.h>
+#include <xen/interface/memory.h>
+#include <xen/interface/xencomm.h>
+#include <xen/interface/version.h>
+#include <xen/interface/sched.h>
+#include <xen/interface/event_channel.h>
+#include <xen/interface/physdev.h>
+#include <xen/interface/vcpu.h>
+#include <xen/interface/kexec.h>
+#include <xen/public/privcmd.h>
+#include <asm/hypercall.h>
+#include <asm/page.h>
+#include <asm/uaccess.h>
+#include <asm/hvcall.h>
+#include "setup.h"
+
+/* Xencomm notes:
+ *
+ * For kernel memory, we assume that virtually contiguous pages are also
+ * physically contiguous. This allows us to avoid creating descriptors for
+ * kernel hypercalls, such as console and event channel operations.
+ *
+ * In general, we need a xencomm descriptor to cover the top-level data
+ * structure (e.g. the domctl op), plus another for every embedded pointer to
+ * another data structure (i.e. for every GUEST_HANDLE).
+ */
+
+int HYPERVISOR_console_io(int cmd, int count, char *str)
+{
+       void *desc;
+       int rc;
+
+       desc = xencomm_map_no_alloc(str, count);
+       if (desc == NULL)
+               return -EINVAL;
+
+       rc = plpar_hcall_norets(XEN_MARK(__HYPERVISOR_console_io),
+                                 cmd, count, desc);
+
+       xencomm_free(desc);
+
+       return rc;
+}
+EXPORT_SYMBOL(HYPERVISOR_console_io);
+
+int HYPERVISOR_event_channel_op(int cmd, void *op)
+{
+       int rc;
+
+       void *desc = xencomm_map_no_alloc(op, sizeof(evtchn_op_t));
+       if (desc == NULL)
+               return -EINVAL;
+
+       rc = plpar_hcall_norets(XEN_MARK(__HYPERVISOR_event_channel_op),
+                               cmd, desc);
+
+       xencomm_free(desc);
+
+       return rc;
+
+}
+EXPORT_SYMBOL(HYPERVISOR_event_channel_op);
+
+int HYPERVISOR_xen_version(int cmd, void *arg)
+{
+       void *desc;
+       const unsigned long hcall = __HYPERVISOR_xen_version;
+       int argsize;
+       int rc;
+
+       switch (cmd) {
+       case XENVER_version:
+               /* do not actually pass an argument */
+               return plpar_hcall_norets(XEN_MARK(hcall), cmd, 0);
+       case XENVER_extraversion:
+               argsize = sizeof(xen_extraversion_t);
+               break;
+       case XENVER_compile_info:
+               argsize = sizeof(xen_compile_info_t);
+               break;
+       case XENVER_capabilities:
+               argsize = sizeof(xen_capabilities_info_t);
+               break;
+       case XENVER_changeset:
+               argsize = sizeof(xen_changeset_info_t);
+               break;
+       case XENVER_platform_parameters:
+               argsize = sizeof(xen_platform_parameters_t);
+               break;
+       case XENVER_pagesize:
+               if (arg == NULL)
+                       argsize = 0;
+               else
+                       argsize = sizeof(void *);
+               break;
+       case XENVER_get_features:
+               argsize = sizeof(xen_feature_info_t);
+               break;
+       default:
+               printk(KERN_ERR "%s: unknown version cmd %d\n", __func__, cmd);
+               return -ENOSYS;
+       }
+
+       /* desc could be NULL in the case of XENVER_pagesize with NULL arg */
+       desc = xencomm_map(arg, argsize);
+
+       rc = plpar_hcall_norets(XEN_MARK(hcall), cmd, desc);
+
+       xencomm_free(desc);
+
+       return rc;
+}
+EXPORT_SYMBOL(HYPERVISOR_xen_version);
+
+
+int HYPERVISOR_physdev_op(int cmd, void *op)
+{
+       void *desc = xencomm_map_no_alloc(op, sizeof(physdev_op_t));
+       int rc;
+
+       if (desc == NULL)
+               return -EINVAL;
+
+       rc = plpar_hcall_norets(XEN_MARK(__HYPERVISOR_physdev_op),
+                               cmd, desc);
+
+       xencomm_free(desc);
+
+       return rc;
+}
+EXPORT_SYMBOL(HYPERVISOR_physdev_op);
+
+int HYPERVISOR_sched_op(int cmd, void *arg)
+{
+       int argsize = 0;
+       int rc = -EINVAL;
+       void *desc;
+       evtchn_port_t *ports = NULL;
+
+       switch (cmd) {
+       case SCHEDOP_yield:
+       case SCHEDOP_block:
+               return plpar_hcall_norets(XEN_MARK(__HYPERVISOR_sched_op),
+                                         cmd, 0);
+               break;
+
+       case SCHEDOP_poll: {
+               struct sched_poll sched_poll;
+
+               argsize = sizeof(struct sched_poll);
+
+               memcpy(&sched_poll, arg, sizeof(sched_poll));
+
+               ports = xencomm_map(
+                               xen_guest_handle(sched_poll.ports),
+                               (sizeof(evtchn_port_t) * sched_poll.nr_ports));
+
+               if (ports == NULL)
+                       return -ENOMEM;
+
+               set_xen_guest_handle(sched_poll.ports, ports);
+               memcpy(arg, &sched_poll, sizeof(sched_poll));
+
+               }
+               break;
+       case SCHEDOP_shutdown:
+               argsize = sizeof(struct sched_shutdown);
+               break;
+       case SCHEDOP_remote_shutdown:
+               argsize = sizeof(struct sched_remote_shutdown);
+               break;
+       default:
+               printk(KERN_ERR "%s: unknown sched op %d\n", __func__, cmd);
+               return -ENOSYS;
+       }
+
+       desc = xencomm_map_no_alloc(arg, argsize);
+       if (desc) {
+               rc = plpar_hcall_norets(XEN_MARK(__HYPERVISOR_sched_op),
+                                       cmd, desc);
+               xencomm_free(desc);
+       }
+
+       xencomm_free(ports);
+
+       return rc;
+}
+EXPORT_SYMBOL(HYPERVISOR_sched_op);
+
+int HYPERVISOR_suspend(unsigned long srec)
+{
+       int cmd = SCHEDOP_shutdown;
+       struct sched_shutdown sched_shutdown = {
+               .reason = SHUTDOWN_suspend,
+       };
+       void *desc;
+
+       desc = xencomm_map_no_alloc(&sched_shutdown, sizeof(struct 
sched_shutdown));
+
+       return plpar_hcall_norets(XEN_MARK(__HYPERVISOR_sched_op),
+                                 cmd, desc, srec);
+}
+EXPORT_SYMBOL(HYPERVISOR_suspend);
+
+int HYPERVISOR_kexec_op(unsigned long op, void *args)
+{
+       unsigned long argsize;
+       void *desc;
+
+       switch (op) {
+               case KEXEC_CMD_kexec_get_range:
+                       argsize = sizeof(struct xen_kexec_range);
+                       break;
+               case KEXEC_CMD_kexec_load:
+                       argsize = sizeof(struct xen_kexec_load);
+                       break;
+               case KEXEC_CMD_kexec_unload:
+                       argsize = sizeof(struct xen_kexec_load);
+                       break;
+               case KEXEC_CMD_kexec:
+                       argsize = sizeof(struct xen_kexec_exec);
+                       break;
+               default:
+                       return -ENOSYS;
+       }
+       desc = xencomm_map_no_alloc(args, argsize);
+
+       return plpar_hcall_norets(XEN_MARK(__HYPERVISOR_kexec_op),
+                                 op, desc);
+}
+EXPORT_SYMBOL(HYPERVISOR_kexec_op);
+
+int HYPERVISOR_poll(
+       evtchn_port_t *ports, unsigned int nr_ports, u64 timeout)
+{
+       struct sched_poll sched_poll = {
+               .nr_ports = nr_ports,
+               .timeout = jiffies_to_ns(timeout)
+       };
+       set_xen_guest_handle(sched_poll.ports, ports);
+
+       return HYPERVISOR_sched_op(SCHEDOP_poll, &sched_poll);
+}
+EXPORT_SYMBOL(HYPERVISOR_poll);
+
+typedef ulong (mf_t)(ulong arg0, ...);
+
+static mf_t *multicall_funcs[] = {
+       [__HYPERVISOR_grant_table_op] = (mf_t *)HYPERVISOR_grant_table_op,
+};
+
+int HYPERVISOR_multicall(void *call_list, int nr_calls)
+{
+       /* we blow out the multicall because the xencomm stuff is jsut
+        * too tricky */
+       multicall_entry_t *mcl = (multicall_entry_t *)call_list;
+       multicall_entry_t *c;
+       int i;
+       mf_t *mf;
+       int res;
+       ulong flags;
+
+       /* let make sure all the calls are supported */
+       for (i = 0; i < nr_calls; i++) {
+               mf = multicall_funcs[mcl[i].op];
+               BUG_ON(mf == NULL);
+       }
+       /* disable interrupts until we are done all calls */
+       local_irq_save(flags);
+       for (i = 0; i < nr_calls; i++) {
+               /* lookup supported multicalls */
+               c = &mcl[i];
+               mf = multicall_funcs[c->op];
+               res = mf(c->args[0], c->args[1], c->args[2],
+                        c->args[3], c->args[4], c->args[5]);
+               c->result = res;
+       }
+       local_irq_restore(flags);
+       return 0;
+}
+EXPORT_SYMBOL(HYPERVISOR_multicall);
+
+
+/* privcmd operations: */
+
+static int xenppc_privcmd_domctl(privcmd_hypercall_t *hypercall)
+{
+       xen_domctl_t kern_op;
+       xen_domctl_t __user *user_op = (xen_domctl_t __user *)hypercall->arg[0];
+       void *op_desc;
+       void *desc = NULL;
+       int ret = 0;
+
+       if (copy_from_user(&kern_op, user_op, sizeof(xen_domctl_t)))
+               return -EFAULT;
+
+       if (kern_op.interface_version != XEN_DOMCTL_INTERFACE_VERSION) {
+               printk(KERN_WARNING "%s: %s %x != %x\n", __func__, 
current->comm,
+                               kern_op.interface_version, 
XEN_DOMCTL_INTERFACE_VERSION);
+               return -EACCES;
+       }
+
+       op_desc = xencomm_map(&kern_op, sizeof(xen_domctl_t));
+       if (op_desc == NULL)
+               return -ENOMEM;
+
+       switch (kern_op.cmd) {
+       case XEN_DOMCTL_createdomain:
+       case XEN_DOMCTL_destroydomain:
+       case XEN_DOMCTL_pausedomain:
+       case XEN_DOMCTL_unpausedomain:
+       case XEN_DOMCTL_getdomaininfo:
+               break;
+       case XEN_DOMCTL_getmemlist:
+               desc = xencomm_map(
+                       xen_guest_handle(kern_op.u.getmemlist.buffer),
+                       kern_op.u.getmemlist.max_pfns * sizeof(unsigned long));
+
+               if (desc == NULL)
+                       ret = -ENOMEM;
+
+               set_xen_guest_handle(kern_op.u.getmemlist.buffer,
+                                    desc);
+               break;
+       case XEN_DOMCTL_getpageframeinfo:
+               break;
+       case XEN_DOMCTL_getpageframeinfo2:
+               desc = xencomm_map(
+                       xen_guest_handle(kern_op.u.getpageframeinfo2.array),
+                       kern_op.u.getpageframeinfo2.num);
+
+               if (desc == NULL)
+                       ret = -ENOMEM;
+
+               set_xen_guest_handle(kern_op.u.getpageframeinfo2.array,
+                                    desc);
+               break;
+       case XEN_DOMCTL_shadow_op:
+
+               if (xen_guest_handle(kern_op.u.shadow_op.dirty_bitmap))
+               {
+                       desc = xencomm_map(
+                               
xen_guest_handle(kern_op.u.shadow_op.dirty_bitmap),
+                               kern_op.u.shadow_op.pages * sizeof(unsigned 
long));
+
+                       if (desc == NULL)
+                               ret = -ENOMEM;
+
+                       set_xen_guest_handle(kern_op.u.shadow_op.dirty_bitmap,
+                                        desc);
+               }
+               break;
+       case XEN_DOMCTL_max_mem:
+               break;
+       case XEN_DOMCTL_setvcpucontext:
+       case XEN_DOMCTL_getvcpucontext:
+               desc = xencomm_map(
+                       xen_guest_handle(kern_op.u.vcpucontext.ctxt),
+                       sizeof(vcpu_guest_context_t));
+
+               if (desc == NULL)
+                       ret = -ENOMEM;
+
+               set_xen_guest_handle(kern_op.u.vcpucontext.ctxt,
+                                    desc);
+               break;
+       case XEN_DOMCTL_getvcpuinfo:
+               break;
+       case XEN_DOMCTL_setvcpuaffinity:
+       case XEN_DOMCTL_getvcpuaffinity:
+               desc = xencomm_map(
+                       xen_guest_handle(kern_op.u.vcpuaffinity.cpumap.bitmap),
+                       (kern_op.u.vcpuaffinity.cpumap.nr_cpus + 7) / 8);
+
+               if (desc == NULL)
+                       ret = -ENOMEM;
+
+               set_xen_guest_handle(kern_op.u.vcpuaffinity.cpumap.bitmap,
+                                    desc);
+               break;
+       case XEN_DOMCTL_max_vcpus:
+       case XEN_DOMCTL_scheduler_op:
+       case XEN_DOMCTL_setdomainhandle:
+       case XEN_DOMCTL_setdebugging:
+       case XEN_DOMCTL_irq_permission:
+       case XEN_DOMCTL_iomem_permission:
+       case XEN_DOMCTL_ioport_permission:
+       case XEN_DOMCTL_hypercall_init:
+       case XEN_DOMCTL_arch_setup:
+       case XEN_DOMCTL_settimeoffset:
+       case XEN_DOMCTL_real_mode_area:
+               break;
+       default:
+               printk(KERN_ERR "%s: unknown domctl cmd %d\n", __func__, 
kern_op.cmd);
+               return -ENOSYS;
+       }
+
+       if (ret)
+               goto out; /* error mapping the nested pointer */
+
+       ret = plpar_hcall_norets(XEN_MARK(hypercall->op),op_desc);
+
+       if (copy_to_user(user_op, &kern_op, sizeof(xen_domctl_t)))
+               ret = -EFAULT;
+
+out:
+       xencomm_free(desc);
+       xencomm_free(op_desc);
+       return ret;
+}
+
+static int xenppc_privcmd_sysctl(privcmd_hypercall_t *hypercall)
+{
+       xen_sysctl_t kern_op;
+       xen_sysctl_t __user *user_op = (xen_sysctl_t __user *)hypercall->arg[0];
+       struct xencomm_desc *op_desc;
+       void *desc = NULL;
+       int ret = 0;
+
+       if (copy_from_user(&kern_op, user_op, sizeof(xen_sysctl_t)))
+               return -EFAULT;
+
+       if (kern_op.interface_version != XEN_SYSCTL_INTERFACE_VERSION) {
+               printk(KERN_WARNING "%s: %s %x != %x\n", __func__, 
current->comm,
+                               kern_op.interface_version, 
XEN_SYSCTL_INTERFACE_VERSION);
+               return -EACCES;
+       }
+
+       op_desc = xencomm_map(&kern_op, sizeof(xen_sysctl_t));
+
+       if (op_desc == NULL)
+               return -ENOMEM;
+
+       switch (kern_op.cmd) {
+       case XEN_SYSCTL_readconsole:
+               desc = xencomm_map(
+                       xen_guest_handle(kern_op.u.readconsole.buffer),
+                       kern_op.u.readconsole.count);
+
+               if (desc == NULL)
+                       ret = -ENOMEM;
+
+               set_xen_guest_handle(kern_op.u.readconsole.buffer,
+                                    desc);
+               break;
+       case XEN_SYSCTL_tbuf_op:
+       case XEN_SYSCTL_physinfo:
+       case XEN_SYSCTL_sched_id:
+               break;
+       case XEN_SYSCTL_perfc_op:
+               /* XXX this requires *two* embedded xencomm mappings (desc and 
val),
+                * and I don't feel like it right now. */
+               printk(KERN_ERR "%s: unknown sysctl cmd %d\n", __func__, 
kern_op.cmd);
+               return -ENOSYS;
+       case XEN_SYSCTL_getdomaininfolist:
+               desc = xencomm_map(
+                       xen_guest_handle(kern_op.u.getdomaininfolist.buffer),
+                       kern_op.u.getdomaininfolist.max_domains *
+                                       sizeof(xen_domctl_getdomaininfo_t));
+
+               if (desc == NULL)
+                       ret = -ENOMEM;
+
+               set_xen_guest_handle(kern_op.u.getdomaininfolist.buffer,
+                                    desc);
+               break;
+       default:
+               printk(KERN_ERR "%s: unknown sysctl cmd %d\n", __func__, 
kern_op.cmd);
+               return -ENOSYS;
+       }
+
+       if (ret)
+               goto out; /* error mapping the nested pointer */
+
+       ret = plpar_hcall_norets(XEN_MARK(hypercall->op), op_desc);
+
+       if (copy_to_user(user_op, &kern_op, sizeof(xen_sysctl_t)))
+               ret = -EFAULT;
+
+out:
+       xencomm_free(desc);
+       xencomm_free(op_desc);
+       return ret;
+}
+
+static int xenppc_privcmd_platform_op(privcmd_hypercall_t *hypercall)
+{
+       xen_platform_op_t kern_op;
+       xen_platform_op_t __user *user_op =
+                       (xen_platform_op_t __user *)hypercall->arg[0];
+       void *op_desc;
+       void *desc = NULL;
+       int ret = 0;
+
+       if (copy_from_user(&kern_op, user_op, sizeof(xen_platform_op_t)))
+               return -EFAULT;
+
+       if (kern_op.interface_version != XENPF_INTERFACE_VERSION) {
+               printk(KERN_WARNING "%s: %s %x != %x\n", __func__, 
current->comm,
+                               kern_op.interface_version, 
XENPF_INTERFACE_VERSION);
+               return -EACCES;
+       }
+
+       op_desc = xencomm_map(&kern_op, sizeof(xen_platform_op_t));
+
+       if (op_desc == NULL)
+               return -ENOMEM;
+
+       switch (kern_op.cmd) {
+       case XENPF_settime:
+       case XENPF_add_memtype:
+       case XENPF_del_memtype:
+       case XENPF_read_memtype:
+       case XENPF_microcode_update:
+       case XENPF_platform_quirk:
+               break;
+       default:
+               printk(KERN_ERR "%s: unknown platform_op cmd %d\n", __func__,
+                               kern_op.cmd);
+               return -ENOSYS;
+       }
+
+       if (ret)
+               goto out; /* error mapping the nested pointer */
+
+       ret = plpar_hcall_norets(XEN_MARK(hypercall->op), op_desc);
+
+       if (copy_to_user(user_op, &kern_op, sizeof(xen_platform_op_t)))
+               ret = -EFAULT;
+
+out:
+       xencomm_free(desc);
+       xencomm_free(op_desc);
+       return ret;
+}
+
+int HYPERVISOR_memory_op(unsigned int cmd, void *arg)
+{
+       int ret;
+       void *op_desc;
+       xen_memory_reservation_t *mop;
+
+
+       mop = (xen_memory_reservation_t *)arg;
+
+       op_desc = xencomm_map(mop, sizeof(xen_memory_reservation_t));
+
+       if (op_desc == NULL)
+               return -ENOMEM;
+
+       switch (cmd) {
+       case XENMEM_increase_reservation:
+       case XENMEM_decrease_reservation:
+       case XENMEM_populate_physmap: {
+               void *desc = NULL;
+
+               if (xen_guest_handle(mop->extent_start)) {
+                       desc = xencomm_map(
+                               xen_guest_handle(mop->extent_start),
+                               mop->nr_extents *
+                               sizeof(*xen_guest_handle(mop->extent_start)));
+
+                       if (desc == NULL) {
+                               ret = -ENOMEM;
+                               goto out;
+                       }
+
+                       set_xen_guest_handle(mop->extent_start,
+                                            desc);
+               }
+
+               ret = plpar_hcall_norets(XEN_MARK(__HYPERVISOR_memory_op),
+                                       cmd, op_desc);
+
+               xencomm_free(desc);
+               }
+               break;
+
+       case XENMEM_maximum_ram_page:
+               /* arg is NULL so we can call thru here */
+               ret = plpar_hcall_norets(XEN_MARK(__HYPERVISOR_memory_op),
+                                       cmd, NULL);
+               break;
+       default:
+               printk(KERN_ERR "%s: unknown memory op %d\n", __func__, cmd);
+               ret = -ENOSYS;
+       }
+
+out:
+       xencomm_free(op_desc);
+       return ret;
+}
+EXPORT_SYMBOL(HYPERVISOR_memory_op);
+
+static int xenppc_privcmd_memory_op(privcmd_hypercall_t *hypercall)
+{
+       xen_memory_reservation_t kern_op;
+       xen_memory_reservation_t __user *user_op;
+       const unsigned long cmd = hypercall->arg[0];
+       int ret = 0;
+
+       user_op = (xen_memory_reservation_t __user *)hypercall->arg[1];
+       if (copy_from_user(&kern_op, user_op,
+                          sizeof(xen_memory_reservation_t)))
+               return -EFAULT;
+
+       ret = HYPERVISOR_memory_op(cmd, &kern_op);
+       if (ret >= 0) {
+               if (copy_to_user(user_op, &kern_op,
+                                sizeof(xen_memory_reservation_t)))
+                       return -EFAULT;
+       }
+       return ret;
+}
+
+static int xenppc_privcmd_version(privcmd_hypercall_t *hypercall)
+{
+       return HYPERVISOR_xen_version(hypercall->arg[0],
+                       (void *)hypercall->arg[1]);
+}
+
+static int xenppc_privcmd_event_channel_op(privcmd_hypercall_t *hypercall)
+{
+       struct xencomm_desc *desc;
+       unsigned int argsize;
+       int ret;
+
+       switch (hypercall->arg[0]) {
+       case EVTCHNOP_alloc_unbound:
+               argsize = sizeof(evtchn_alloc_unbound_t);
+               break;
+
+       case EVTCHNOP_status:
+               argsize = sizeof(evtchn_status_t);
+               break;
+
+       default:
+               printk(KERN_ERR "%s: unknown EVTCHNOP (%ld)\n",
+                      __func__, hypercall->arg[0]);
+               return -EINVAL;
+       }
+
+       desc = xencomm_map((void *)hypercall->arg[1], argsize);
+
+       if (desc == NULL)
+               return -ENOMEM;
+
+       ret = plpar_hcall_norets(XEN_MARK(hypercall->op), hypercall->arg[0],
+                               desc);
+
+       xencomm_free(desc);
+       return ret;
+}
+
+/* The PowerPC hypervisor runs in a separate address space from Linux
+ * kernel/userspace, i.e. real mode. We must therefore translate userspace
+ * pointers to something the hypervisor can make sense of. */
+int privcmd_hypercall(privcmd_hypercall_t *hypercall)
+{
+       switch (hypercall->op) {
+       case __HYPERVISOR_domctl:
+               return xenppc_privcmd_domctl(hypercall);
+       case __HYPERVISOR_sysctl:
+               return xenppc_privcmd_sysctl(hypercall);
+       case __HYPERVISOR_platform_op:
+               return xenppc_privcmd_platform_op(hypercall);
+       case __HYPERVISOR_memory_op:
+               return xenppc_privcmd_memory_op(hypercall);
+       case __HYPERVISOR_xen_version:
+               return xenppc_privcmd_version(hypercall);
+       case __HYPERVISOR_event_channel_op:
+               return xenppc_privcmd_event_channel_op(hypercall);
+       default:
+               printk(KERN_ERR "%s: unknown hcall (%ld)\n", __func__, 
hypercall->op);
+               /* fallthru */
+               /* below are the hcalls we know will fail and its ok */
+       case __HYPERVISOR_acm_op:
+               return plpar_hcall_norets(XEN_MARK(hypercall->op),
+                               hypercall->arg[0],
+                               hypercall->arg[1],
+                               hypercall->arg[2],
+                               hypercall->arg[3],
+                               hypercall->arg[4]);
+       }
+}
+
+int HYPERVISOR_vcpu_op(int cmd, int vcpuid, void *extra_args)
+{
+       int argsize;
+       const unsigned long hcall = __HYPERVISOR_vcpu_op;
+       void *desc;
+       int rc;
+
+       switch (cmd) {
+       case  VCPUOP_initialise:
+               argsize = sizeof(vcpu_guest_context_t);
+               break;
+       case VCPUOP_up:
+       case VCPUOP_down:
+       case VCPUOP_is_up:
+               return plpar_hcall_norets(XEN_MARK(hcall), cmd, vcpuid, 0);
+
+       case VCPUOP_get_runstate_info:
+               argsize = sizeof (vcpu_runstate_info_t);
+               break;
+       default:
+               printk(KERN_ERR "%s: unknown version cmd %d\n", __func__, cmd);
+               return -ENOSYS;
+       }
+
+       desc = xencomm_map_no_alloc(extra_args, argsize);
+
+       if (desc == NULL)
+               return -EINVAL;
+
+       rc = plpar_hcall_norets(XEN_MARK(hcall), cmd, vcpuid, desc);
+
+       xencomm_free(desc);
+
+       return rc;
+}
diff -r 56e84a427523 -r e57b5bec937f arch/powerpc/platforms/xen/reboot.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/arch/powerpc/platforms/xen/reboot.c       Tue Jul 10 08:40:03 2007 -0600
@@ -0,0 +1,53 @@
+/*
+ * 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
+ *
+ * Copyright (C) IBM Corp. 2006
+ *
+ * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
+ */
+
+#include <linux/module.h>
+#include <xen/interface/xen.h>
+#include <xen/interface/io/console.h>
+#include <xen/xencons.h>
+#include <asm/hypervisor.h>
+#include <asm/machdep.h>
+
+static void domain_machine_restart(char * __unused)
+{
+       /* We really want to get pending console data out before we die. */
+       xencons_force_flush();
+       HYPERVISOR_shutdown(SHUTDOWN_reboot);
+}
+
+static void domain_machine_power_off(void)
+{
+       /* We really want to get pending console data out before we die. */
+       xencons_force_flush();
+       HYPERVISOR_shutdown(SHUTDOWN_poweroff);
+}
+
+void xen_reboot_init(struct machdep_calls *md)
+{
+       if (md != NULL) {
+               ppc_md.restart   = md->restart;
+               ppc_md.power_off = md->power_off;
+               ppc_md.halt      = md->halt;
+       } else {
+               ppc_md.restart   = domain_machine_restart;
+               ppc_md.power_off = domain_machine_power_off;
+               ppc_md.halt      = domain_machine_power_off;
+       }
+}
diff -r 56e84a427523 -r e57b5bec937f arch/powerpc/platforms/xen/setup.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/arch/powerpc/platforms/xen/setup.c        Tue Jul 10 08:40:03 2007 -0600
@@ -0,0 +1,324 @@
+/*
+ * 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
+ *
+ * Copyright (C) IBM Corp. 2006
+ *
+ * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
+ */
+
+#define DEBUG
+#define CONFIG_SHARE_MPIC
+
+#include <linux/module.h>
+#include <linux/rwsem.h>
+#include <linux/delay.h>
+#include <linux/console.h>
+#include <xen/interface/xen.h>
+#include <xen/interface/sched.h>
+#include <xen/evtchn.h>
+#include <xen/features.h>
+#include <xen/xencons.h>
+#include <asm/udbg.h>
+#include <asm/pgtable.h>
+#include <asm/prom.h>
+#include <asm/iommu.h>
+#include <asm/mmu.h>
+#include <asm/abs_addr.h>
+#include <asm/machdep.h>
+#include <asm/hypervisor.h>
+#include <asm/time.h>
+#include "setup.h"
+
+#ifdef DEBUG
+#define DBG(fmt...) udbg_printf(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+/* Apperently on other arches this could be used before its defined,
+ * this should not be the case in PPC */
+shared_info_t *HYPERVISOR_shared_info = (shared_info_t *)NULL;
+EXPORT_SYMBOL(HYPERVISOR_shared_info);
+
+/* Raw start-of-day parameters from the hypervisor. */
+static start_info_t xsi;
+start_info_t *xen_start_info;
+EXPORT_SYMBOL(xen_start_info);
+
+extern struct machdep_calls mach_maple_md;
+extern void maple_pci_init(void);
+
+static unsigned long foreign_mfn_flag;
+
+/* Must be called with &vma->vm_mm->mmap_sem locked for write */
+int direct_remap_pfn_range(struct vm_area_struct *vma,
+               unsigned long address, 
+               unsigned long mfn,
+               unsigned long size, 
+               pgprot_t prot,
+               domid_t  domid)
+{
+       int rc;
+
+       /* Set the MFN flag to tell Xen that this is not a PFN. */
+       printk("%s: mapping mfn 0x%lx (size 0x%lx) -> 0x%lx\n", __func__,
+                       mfn, size, mfn | foreign_mfn_flag);
+       mfn = mfn | foreign_mfn_flag;
+
+       WARN_ON(!rwsem_is_locked(&vma->vm_mm->mmap_sem));
+       rc = remap_pfn_range(vma, address, mfn, size, prot);
+
+       return rc;
+}
+
+static void __init xen_fw_feature_init(void)
+{
+       DBG(" -> %s\n", __func__);
+
+       powerpc_firmware_features = 0;
+
+       powerpc_firmware_features |= FW_FEATURE_LPAR;
+       powerpc_firmware_features |= FW_FEATURE_TCE | FW_FEATURE_DABR;
+               
+       printk(KERN_INFO "firmware_features = 0x%lx\n", 
+                       powerpc_firmware_features);
+
+       DBG(" <- %s\n", __func__);
+}
+
+/* if these were global then I could get them from the pseries/setup.c */
+static int pseries_set_dabr(unsigned long dabr)
+{
+       return plpar_hcall_norets(H_SET_DABR, dabr);
+}
+
+static int pseries_set_xdabr(unsigned long dabr)
+{
+       /* We want to catch accesses from kernel and userspace */
+       return plpar_hcall_norets(H_SET_XDABR, dabr,
+                       H_DABRX_KERNEL | H_DABRX_USER);
+}
+
+/* 
+ * Early initialization.
+ */
+static void __init xenppc_init_early(void)
+{
+       struct device_node *xen;
+
+       DBG(" -> %s\n", __func__);
+
+       xen = of_find_node_by_path("/xen");
+
+       xen_start_info = &xsi;
+
+       /* fill out start_info_t from devtree */
+       if ((char *)get_property(xen, "privileged", NULL))
+               xen_start_info->flags |= SIF_PRIVILEGED;
+       if ((char *)get_property(xen, "initdomain", NULL))
+               xen_start_info->flags |= SIF_INITDOMAIN;
+       xen_start_info->shared_info = *((u64 *)get_property(xen, 
+          "shared-info", NULL));
+
+       /* only look for store and console for guest domains */
+       if (xen_start_info->flags == 0) {
+               struct device_node *console = 
of_find_node_by_path("/xen/console");
+               struct device_node *store = of_find_node_by_path("/xen/store");
+
+               xen_start_info->store_mfn = (*((u64 *)get_property(store,
+                  "reg", NULL))) >> PAGE_SHIFT;
+               xen_start_info->store_evtchn = *((u32 *)get_property(store,
+                  "interrupts", NULL));
+               xen_start_info->console.domU.mfn = (*((u64 
*)get_property(console,
+                  "reg", NULL))) >> PAGE_SHIFT;
+               xen_start_info->console.domU.evtchn = *((u32 
*)get_property(console,
+                  "interrupts", NULL));
+       }
+
+       HYPERVISOR_shared_info = __va(xen_start_info->shared_info);
+
+       udbg_init_xen();
+
+       DBG("xen_start_info at %p\n", xen_start_info);
+       DBG("    magic          %s\n", xen_start_info->magic);
+       DBG("    flags          %x\n", xen_start_info->flags);
+       DBG("    shared_info    %lx, %p\n",
+           xen_start_info->shared_info, HYPERVISOR_shared_info);
+       DBG("    store_mfn      %llx\n", xen_start_info->store_mfn);
+       DBG("    store_evtchn   %x\n", xen_start_info->store_evtchn);
+       DBG("    console_mfn    %llx\n", xen_start_info->console.domU.mfn);
+       DBG("    console_evtchn %x\n", xen_start_info->console.domU.evtchn);
+
+       xen_setup_time(&mach_maple_md);
+
+       xencons_early_setup();
+       add_preferred_console("xvc", 0, NULL);
+
+       if (get_property(xen, "power-control", NULL))
+               xen_reboot_init(&mach_maple_md);
+       else
+               xen_reboot_init(NULL);
+
+       if (is_initial_xendomain()) {
+               u64 *mfnflag = (u64 *)get_property(xen, "mfn-flag", NULL);
+               if (mfnflag) {
+                       foreign_mfn_flag = (1UL << mfnflag[0]);
+                       printk("OF: using 0x%lx as foreign mfn flag\n", 
foreign_mfn_flag);
+               } else
+                       printk("OF: /xen/mfn-base must be present it build 
guests\n");
+       }
+
+       /* get the domain features */
+       setup_xen_features();
+
+       DBG("Hello World I'm Maple Xen-LPAR!\n");
+
+       if (firmware_has_feature(FW_FEATURE_DABR))
+               ppc_md.set_dabr = pseries_set_dabr;
+       else if (firmware_has_feature(FW_FEATURE_XDABR))
+               ppc_md.set_dabr = pseries_set_xdabr;
+
+       iommu_init_early_pSeries();
+
+       DBG(" <- %s\n", __func__);
+}
+
+/*
+ * this interface is limiting
+ */
+static int running_on_xen;
+int is_running_on_xen(void)
+{
+       return running_on_xen;
+}
+EXPORT_SYMBOL(is_running_on_xen);
+
+static void xenppc_power_save(void)
+{
+       /* SCHEDOP_yield could immediately return. Instead, we
+        * want to idle in the Xen idle domain, so use
+        * SCHEDOP_block with a one-shot timer. */
+       /* XXX do tickless stuff here. See
+        * linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c */
+       u64 now_ns = tb_to_ns(get_tb());
+       u64 offset_ns = jiffies_to_ns(1);
+       int rc;
+
+       rc = HYPERVISOR_set_timer_op(now_ns + offset_ns);
+       BUG_ON(rc != 0);
+
+       HYPERVISOR_sched_op(SCHEDOP_block, NULL);
+}
+
+void __init xenppc_setup_arch(void)
+{
+       /* init to some ~sane value until calibrate_delay() runs */
+       loops_per_jiffy = 50000000;
+
+       /* Lookup PCI hosts */
+       if (is_initial_xendomain())
+               maple_pci_init();
+
+#ifdef CONFIG_DUMMY_CONSOLE
+       conswitchp = &dummy_con;
+#endif
+#ifdef CONFIG_SMP
+       /* let them fly */
+       xen_setup_smp();
+#endif
+
+       printk(KERN_INFO "Using Xen idle loop\n");
+}
+
+static int __init xen_probe_flat_dt(unsigned long node,
+                                   const char *uname, int depth,
+                                   void *data)
+{
+       if (depth != 1)
+               return 0;
+       if (strcmp(uname, "xen") != 0)
+               return 0;
+
+       running_on_xen = 1;
+
+       return 1;
+}
+
+/*
+ * Called very early, MMU is off, device-tree isn't unflattened
+ */
+/* forward ref */
+struct machdep_calls __initdata xen_md;
+static int __init xenppc_probe(void)
+{
+       of_scan_flat_dt(xen_probe_flat_dt, NULL);
+
+       if (!running_on_xen)
+               return 0;
+
+       xen_fw_feature_init();
+
+       hpte_init_lpar();
+
+       return 1;
+}
+
+static void __init xenppc_progress(char *s, unsigned short hex)
+{
+       printk("*** %04x : %s\n", hex, s ? s : "");
+}
+
+unsigned int xenppc_get_irq(struct pt_regs *regs)
+{
+       evtchn_do_upcall(regs);
+       /* evtchn_do_upcall() handles all pending event channels directly, so 
there
+        * is nothing for do_IRQ() to do.
+        * XXX This means we aren't using IRQ stacks. */
+       return NO_IRQ;
+}
+
+#ifdef CONFIG_KEXEC
+void xen_machine_kexec(struct kimage *image)
+{
+       panic("%s(%p): called\n", __func__, image);
+}
+
+int xen_machine_kexec_prepare(struct kimage *image)
+{
+       panic("%s(%p): called\n", __func__, image);
+}
+
+void xen_machine_crash_shutdown(struct pt_regs *regs)
+{
+       panic("%s(%p): called\n", __func__, regs);
+}       
+#endif
+
+define_machine(xen) {
+       .name                   = "Xen-Maple",
+       .probe                  = xenppc_probe,
+       .setup_arch             = xenppc_setup_arch,
+       .init_early             = xenppc_init_early,
+       .init_IRQ               = xen_init_IRQ,
+       .get_irq                = xenppc_get_irq,
+       .calibrate_decr         = generic_calibrate_decr,
+       .progress               = xenppc_progress,
+       .power_save             = xenppc_power_save,
+#ifdef CONFIG_KEXEC
+       .machine_kexec          = xen_machine_kexec,
+       .machine_kexec_prepare  = xen_machine_kexec_prepare,
+       .machine_crash_shutdown = xen_machine_crash_shutdown,
+#endif
+};
diff -r 56e84a427523 -r e57b5bec937f arch/powerpc/platforms/xen/setup.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/arch/powerpc/platforms/xen/setup.h        Tue Jul 10 08:40:03 2007 -0600
@@ -0,0 +1,49 @@
+/*
+ * 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
+ *
+ * Copyright (C) IBM Corp. 2006
+ *
+ * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
+ */
+
+#include <asm/machdep.h>
+#include <asm/time.h>
+
+extern void evtchn_init_IRQ(void);
+extern void xen_init_IRQ(void);
+extern void xen_reboot_init(struct machdep_calls *);
+extern void xen_maple_init_IRQ(void);
+extern unsigned int xen_get_irq(struct pt_regs *regs);
+
+static inline u64 tb_to_ns(u64 tb)
+{
+       if (likely(tb_ticks_per_sec)) {
+               return tb * (1000000000UL / tb_ticks_per_sec);
+       }
+       return 0;
+}
+
+static inline u64 jiffies_to_ns(unsigned long j) 
+{
+       return j * (1000000000UL / HZ);
+}
+
+#define xen_guest_handle(hnd)  ((hnd).p)
+
+extern struct page *alloc_foreign_page(void);
+extern void free_foreign_page(struct page *page);
+
+extern void __init xen_setup_time(struct machdep_calls *host_md);
+extern void xen_setup_smp(void);
diff -r 56e84a427523 -r e57b5bec937f arch/powerpc/platforms/xen/smp.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/arch/powerpc/platforms/xen/smp.c  Tue Jul 10 08:40:03 2007 -0600
@@ -0,0 +1,444 @@
+/*
+ * 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
+ *
+ * Copyright (C) IBM Corp. 2006
+ *
+ * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
+ */
+
+#include <linux/kernel.h>
+#include <linux/config.h>
+#include <linux/bootmem.h>
+#include <linux/irq.h>
+#include <linux/smp.h>
+#include <xen/interface/xen.h>
+#include <xen/interface/vcpu.h>
+#include <xen/evtchn.h>
+#include <asm/prom.h>
+#include <asm/udbg.h>
+#include <asm/hypervisor.h>
+#include "setup.h"
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(fmt...) printk(KERN_EMERG fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+static inline void *xen_of_alloc(ulong size)
+{
+       if (mem_init_done)
+               return kmalloc(size, GFP_KERNEL);
+       return alloc_bootmem(size);
+}
+static inline void xen_of_free(void *ptr)
+{
+       /* if this happens with the boot allocator then we are screwed */
+       BUG_ON(!mem_init_done);
+       kfree(ptr);
+}
+
+static struct property *dup_prop(struct property *op)
+{
+       struct property *np;
+       void *p;
+       ulong sz;
+
+
+       /* allocate everything in one go in case it fails */
+       sz = sizeof (*np); /* prop node */
+       sz += strlen(op->name) + 1; /* prop name */
+       sz += op->length; /* prop value */
+               
+       p = xen_of_alloc(sz);
+       if (!p)
+               return NULL;
+       memset(p, 0, sz);
+
+       /* prop node first */
+       np = p;
+       p += sizeof (*np);
+
+       /* value next becuase we want it aligned */
+       np->value = p;
+       p += op->length;
+
+       /* name */
+       np->name = p;
+
+       /* copy it all */
+       strcpy(np->name, op->name);
+       np->length = op->length;
+       memcpy(np->value, op->value, np->length);
+
+       return np;
+}
+
+static int dup_properties(struct device_node *dst, struct device_node *src)
+{
+       struct property *op;
+       struct property *np;
+       struct property *lp;
+       int rc = 0;
+
+       DBG("%s: duping to new cpu node: %s\n", __func__, dst->full_name);
+
+       np = lp = NULL;
+       for (op = src->properties; op != 0; op = op->next) {
+               lp = np;
+               np = dup_prop(op);
+               if (!np)
+                       break;
+
+               prom_add_property(dst, np);
+       }
+
+       if (!np) {
+               DBG("%s: FAILED duping: %s\n", __func__, dst->full_name);
+               /* we could not allocate enuff so free what we have
+                * allocated */
+               rc = -ENOMEM;
+               for (op = dst->properties; lp && op != lp; op = op->next)
+                       xen_of_free(op);
+       }
+
+       return rc;
+}
+
+/* returns added device node so it can be added to procfs in the case
+ * of hotpluging */
+static struct device_node *xen_add_vcpu_node(struct device_node *boot_cpu,
+                                            uint cpu)
+{
+       struct device_node *new_cpu;
+       struct property *pp;
+       void *p;
+       int sz;
+       int type_sz;
+       int name_sz;
+
+       DBG("%s: boot cpu: %s\n", __func__, boot_cpu->full_name);
+
+       /* allocate in one shot in case we fail */
+       name_sz = strlen(boot_cpu->name) + 1;
+       type_sz = strlen(boot_cpu->type) + 1;
+
+       sz = sizeof (*new_cpu); /* the node */
+       sz += strlen(boot_cpu->full_name) + 3; /* full_name */
+       sz += name_sz; /* name */
+       sz += type_sz; /* type */
+
+       p = xen_of_alloc(sz);
+       if (!p)
+               return NULL;
+       memset(p, 0, sz);
+
+       /* the node */
+       new_cpu = p;
+       p += sizeof (*new_cpu);
+       
+       /* name */
+       new_cpu->name = p;
+       strcpy(new_cpu->name, boot_cpu->name);
+       p += name_sz;
+       
+       /* type */
+       new_cpu->type = p;
+       strcpy(new_cpu->type, boot_cpu->type);
+       p += type_sz;
+
+       /* full_name */
+       new_cpu->full_name = p;
+
+       /* assemble new full_name */
+       pp = of_find_property(boot_cpu, "name", NULL);
+       if (!pp)
+               panic("%s: no name prop\n", __func__);
+
+       DBG("%s: name is: %s = %s\n", __func__, pp->name, pp->value);
+       sprintf(new_cpu->full_name, "/cpus/%s@%u", pp->value, cpu);
+
+       if (dup_properties(new_cpu, boot_cpu)) {
+               xen_of_free(new_cpu);
+               return NULL;
+       }
+
+       /* fixup reg property */
+       DBG("%s: updating reg: %d\n", __func__, cpu);
+       pp = of_find_property(new_cpu, "reg", NULL);
+       if (!pp)
+               panic("%s: no reg prop\n", __func__);
+       *(int *)pp->value = cpu;
+
+       if (mem_init_done)
+               OF_MARK_DYNAMIC(new_cpu);
+
+       kref_init(&new_cpu->kref);
+
+       /* insert the node */
+       new_cpu->parent = of_get_parent(boot_cpu);
+       of_attach_node(new_cpu);
+       of_node_put(new_cpu->parent);
+
+       return new_cpu;
+}
+
+static void cpu_initialize_context(unsigned int vcpu, ulong entry)
+{
+       vcpu_guest_context_t ctxt;
+
+       memset(&ctxt.user_regs, 0x55, sizeof(ctxt.user_regs));
+
+       ctxt.user_regs.pc = entry;
+       ctxt.user_regs.msr = 0;
+       ctxt.user_regs.gprs[1] = 0; /* Linux uses its own stack */
+       ctxt.user_regs.gprs[3] = vcpu;
+
+       /* XXX verify this *** */
+       /* There is a buggy kernel that does not zero the "local_paca", so
+        * we must make sure this register is 0 */
+       ctxt.user_regs.gprs[13] = 0;
+
+       DBG("%s: initializing vcpu: %d\n", __func__, vcpu);
+
+       if (HYPERVISOR_vcpu_op(VCPUOP_initialise, vcpu, &ctxt))
+               panic("%s: VCPUOP_initialise failed, vcpu: %d\n",
+                      __func__, vcpu);
+
+}
+
+static int xen_start_vcpu(uint vcpu, ulong entry)
+{
+       DBG("%s: starting vcpu: %d\n", __func__, vcpu);
+
+       cpu_initialize_context(vcpu, entry);
+
+       DBG("%s: Spinning up vcpu: %d\n", __func__, vcpu);
+       return HYPERVISOR_vcpu_op(VCPUOP_up, vcpu, NULL);
+}
+
+extern void __secondary_hold(void);
+extern unsigned long __secondary_hold_spinloop;
+extern unsigned long __secondary_hold_acknowledge;
+
+static void xen_boot_secondary_vcpus(void)
+{
+       int vcpu;
+       int rc;
+       const unsigned long mark = (unsigned long)-1;
+       unsigned long *spinloop = &__secondary_hold_spinloop;
+       unsigned long *acknowledge = &__secondary_hold_acknowledge;
+#ifdef CONFIG_PPC64
+       /* __secondary_hold is actually a descriptor, not the text address */
+       unsigned long secondary_hold = __pa(*(unsigned long *)__secondary_hold);
+#else
+       unsigned long secondary_hold = __pa(__secondary_hold);
+#endif
+       struct device_node *boot_cpu;
+
+       DBG("%s: finding CPU node\n", __func__);
+       boot_cpu = of_find_node_by_type(NULL, "cpu");
+       if (!boot_cpu)
+               panic("%s: Cannot find Booting CPU node\n", __func__);
+
+       /* Set the common spinloop variable, so all of the secondary cpus
+        * will block when they are awakened from their OF spinloop.
+        * This must occur for both SMP and non SMP kernels, since OF will
+        * be trashed when we move the kernel.
+        */
+       *spinloop = 0;
+
+       DBG("%s: Searching for all vcpu numbers > 0\n", __func__);
+       /* try and start as many as we can */
+       for (vcpu = 1; vcpu < NR_CPUS; vcpu++) {
+               int i;
+
+               rc = HYPERVISOR_vcpu_op(VCPUOP_is_up, vcpu, NULL);
+               if (rc < 0)
+                       continue;
+
+               DBG("%s: Found vcpu: %d\n", __func__, vcpu);
+               /* Init the acknowledge var which will be reset by
+                * the secondary cpu when it awakens from its OF
+                * spinloop.
+                */
+               *acknowledge = mark;
+
+               DBG("%s: Starting vcpu: %d at pc: 0x%lx\n", __func__,
+                   vcpu, secondary_hold);
+               rc = xen_start_vcpu(vcpu, secondary_hold);
+               if (rc)
+                       panic("%s: xen_start_vpcu() failed\n", __func__);
+
+
+               DBG("%s: Waiting for ACK on vcpu: %d\n", __func__, vcpu);
+               for (i = 0; (i < 100000000) && (*acknowledge == mark); i++)
+                       mb();
+
+               if (*acknowledge == vcpu)
+                       DBG("%s: Recieved for ACK on vcpu: %d\n",
+                           __func__, vcpu);
+
+               xen_add_vcpu_node(boot_cpu, vcpu);
+
+               cpu_set(vcpu, cpu_present_map);
+               set_hard_smp_processor_id(vcpu, vcpu);
+       }
+       of_node_put(boot_cpu);
+       DBG("%s: end...\n", __func__);
+}
+
+static int __init smp_xen_probe(void)
+{
+       return cpus_weight(cpu_present_map);
+}
+
+static irqreturn_t xen_ppc_msg_reschedule(int irq, void *dev_id,
+                                         struct pt_regs *regs)
+{
+       smp_message_recv(PPC_MSG_RESCHEDULE, regs);
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t xen_ppc_msg_call_function(int irq, void *dev_id,
+                                            struct pt_regs *regs)
+{
+       smp_message_recv(PPC_MSG_CALL_FUNCTION, regs);
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t xen_ppc_msg_debugger_break(int irq, void *dev_id,
+                                         struct pt_regs *regs)
+{
+       smp_message_recv(PPC_MSG_DEBUGGER_BREAK, regs);
+       return IRQ_HANDLED;
+}
+
+struct message {
+       irqreturn_t (*f)(int, void *, struct pt_regs *);
+       int num;
+       char *name;
+};
+static struct message ipi_msgs[] = {
+       {
+               .num = PPC_MSG_RESCHEDULE,
+               .f = xen_ppc_msg_reschedule,
+               .name = "IPI-resched"
+       },
+       {
+               .num = PPC_MSG_CALL_FUNCTION,
+               .f = xen_ppc_msg_call_function,
+               .name = "IPI-function"
+               },
+       {
+               .num = PPC_MSG_DEBUGGER_BREAK,
+               .f = xen_ppc_msg_debugger_break,
+               .name = "IPI-debug"
+       }
+};
+
+DECLARE_PER_CPU(int, ipi_to_irq[NR_IPIS]);
+
+static void __devinit smp_xen_setup_cpu(int cpu)
+{
+       int irq;
+       int i;
+       const int nr_ipis = ARRAY_SIZE(__get_cpu_var(ipi_to_irq));
+
+       /* big scary include web could mess with our values, so we
+        * make sure they are sane */
+       BUG_ON(ARRAY_SIZE(ipi_msgs) > nr_ipis);
+
+       for (i = 0; i < ARRAY_SIZE(ipi_msgs); i++) {
+               BUG_ON(ipi_msgs[i].num >= nr_ipis);
+
+               irq = bind_ipi_to_irqhandler(ipi_msgs[i].num,
+                                            cpu,
+                                            ipi_msgs[i].f,
+                                            SA_INTERRUPT,
+                                            ipi_msgs[i].name,
+                                            NULL);
+               BUG_ON(irq < 0);
+               per_cpu(ipi_to_irq, cpu)[ipi_msgs[i].num] = irq;
+               DBG("%s: cpu: %d vector :%d irq: %d\n",
+                      __func__, cpu, ipi_msgs[i].num, irq);
+       }
+}
+
+static inline void send_IPI_one(unsigned int cpu, int vector)
+{
+       int irq;
+
+       irq = per_cpu(ipi_to_irq, cpu)[vector];
+       BUG_ON(irq < 0);
+
+       DBG("%s: cpu: %d vector :%d irq: %d!\n",
+              __func__, cpu, vector, irq);
+       DBG("%s: per_cpu[%p]: %d %d %d %d\n",
+              __func__, per_cpu(ipi_to_irq, cpu),
+              per_cpu(ipi_to_irq, cpu)[0],
+              per_cpu(ipi_to_irq, cpu)[1],
+              per_cpu(ipi_to_irq, cpu)[2],
+              per_cpu(ipi_to_irq, cpu)[3]);
+
+       notify_remote_via_irq(irq);
+}
+
+static void smp_xen_message_pass(int target, int msg)
+{
+       int cpu;
+
+       switch (msg) {
+       case PPC_MSG_RESCHEDULE:
+       case PPC_MSG_CALL_FUNCTION:
+       case PPC_MSG_DEBUGGER_BREAK:
+               break;
+       default:
+               panic("SMP %d: smp_message_pass: unknown msg %d\n",
+                      smp_processor_id(), msg);
+               return;
+       }
+       switch (target) {
+       case MSG_ALL:
+       case MSG_ALL_BUT_SELF:
+               for_each_online_cpu(cpu) {
+                       if (target == MSG_ALL_BUT_SELF &&
+                           cpu == smp_processor_id())
+                               continue;
+                       send_IPI_one(cpu, msg);
+               }
+               break;
+       default:
+               send_IPI_one(target, msg);
+               break;
+       }
+}
+
+static struct smp_ops_t xen_smp_ops = {
+       .probe          = smp_xen_probe,
+       .message_pass   = smp_xen_message_pass,
+       .kick_cpu       = smp_generic_kick_cpu,
+       .setup_cpu      = smp_xen_setup_cpu,
+};
+
+void xen_setup_smp(void)
+{
+       smp_ops = &xen_smp_ops;
+
+       xen_boot_secondary_vcpus();
+       smp_release_cpus();
+}
diff -r 56e84a427523 -r e57b5bec937f arch/powerpc/platforms/xen/time.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/arch/powerpc/platforms/xen/time.c Tue Jul 10 08:40:03 2007 -0600
@@ -0,0 +1,114 @@
+/*
+ * 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
+ *
+ * Copyright (C) IBM Corp. 2006
+ *
+ * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
+ */
+
+#include <linux/module.h>
+#include <linux/time.h>
+#include <linux/rtc.h>
+#include <asm/hypervisor.h>
+#include <asm/machdep.h>
+#include <asm/time.h>
+#include <asm/udbg.h>
+
+#ifdef DEBUG
+#define DBG(fmt...) printk(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+void time_resume(void)
+{
+       snapshot_timebase();
+}
+
+static inline ulong time_from_shared(void)
+{
+       ulong t;
+
+       DBG("tb_freq: %ld\n", ppc_tb_freq);
+
+       t = mftb() - HYPERVISOR_shared_info->arch.boot_timebase;
+       t /= ppc_tb_freq;
+       t += HYPERVISOR_shared_info->wc_sec;
+
+       return t;
+}
+
+static void (*host_md_get_rtc_time)(struct rtc_time *tm);
+static void xen_get_rtc_time(struct rtc_time *tm)
+{
+       if (is_initial_xendomain()) {
+               host_md_get_rtc_time(tm);
+               return;
+       } else {
+               ulong t;
+
+               t = time_from_shared();
+               to_tm(t, tm);
+       }
+}
+
+static int (*host_md_set_rtc_time)(struct rtc_time *tm);
+static int xen_set_rtc_time(struct rtc_time *tm)
+{
+       ulong sec;
+
+       if (is_initial_xendomain()) {
+               host_md_set_rtc_time(tm);
+               return 0;
+       }
+
+       sec = mktime(tm->tm_year, tm->tm_mon, tm->tm_mday,
+                    tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+       HYPERVISOR_shared_info->wc_sec = sec;
+       HYPERVISOR_shared_info->arch.boot_timebase = mftb();
+
+       return 0;
+}
+
+static unsigned long (*host_md_get_boot_time)(void);
+static unsigned long __init xen_get_boot_time(void)
+{
+       ulong t;
+
+       if (is_initial_xendomain()) {
+               t = host_md_get_boot_time();
+
+               HYPERVISOR_shared_info->wc_sec = t;
+               HYPERVISOR_shared_info->arch.boot_timebase = mftb();
+               DBG("%s: time: %ld\n", __func__, t);
+       } else {
+               t = time_from_shared();
+               DBG("%s: %ld\n", __func__, t);
+       }
+       return t;
+}
+
+void __init xen_setup_time(struct machdep_calls *host_md)
+{
+       ppc_md.get_boot_time = xen_get_boot_time;
+       host_md_get_boot_time = host_md->get_boot_time;
+
+       ppc_md.set_rtc_time = xen_set_rtc_time;
+       host_md_set_rtc_time = host_md->set_rtc_time;
+
+       ppc_md.get_rtc_time = xen_get_rtc_time;
+       host_md_get_rtc_time = host_md->get_rtc_time;
+}
diff -r 56e84a427523 -r e57b5bec937f arch/powerpc/platforms/xen/udbg_xen.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/arch/powerpc/platforms/xen/udbg_xen.c     Tue Jul 10 08:40:03 2007 -0600
@@ -0,0 +1,164 @@
+/*
+ * 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
+ *
+ * Copyright (C) IBM Corp. 2006
+ *
+ * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
+ */
+
+#include <linux/module.h>
+#include <xen/interface/xen.h>
+#include <xen/interface/io/console.h>
+#include <xen/evtchn.h>
+#include <asm/udbg.h>
+#include <asm/hypervisor.h>
+#include "setup.h"
+
+static void udbg_xen_wait(void)
+{
+       evtchn_port_t port = 0;
+
+       if (xen_start_info) {
+               port = xen_start_info->console.domU.evtchn;
+               clear_evtchn(port);
+       }
+       HYPERVISOR_poll(&port, 1, 10);
+}
+
+static int udbg_getc_xen(void)
+{
+       int ch;
+       for (;;) {
+               ch = udbg_getc_poll();
+               if (ch == -1) {
+                       udbg_xen_wait();
+               } else {
+                       return ch;
+               }
+       }
+}
+
+static void udbg_putc_dom0_xen(char c)
+{
+       unsigned long rc;
+
+       if (c == '\n')
+               udbg_putc_dom0_xen('\r');
+
+       do {
+               rc = HYPERVISOR_console_io(CONSOLEIO_write, 1, &c);
+       } while (rc < 0);
+}
+
+/* Buffered chars getc */
+static long inbuflen;
+static char inbuf[128];        /* Xen serial ring buffer */
+
+static int udbg_getc_poll_dom0_xen(void)
+{
+       /* The interface is tricky because it may return many chars.
+        * We save them statically for future calls to udbg_getc().
+        */
+       char ch, *buf = (char *)inbuf;
+       int i;
+
+       if (inbuflen == 0) {
+               /* get some more chars. */
+               inbuflen = HYPERVISOR_console_io(CONSOLEIO_read,
+                                                sizeof(inbuf), buf);
+       }
+
+       if (inbuflen == 0)
+               return -1;
+
+       ch = buf[0];
+       for (i = 1; i < inbuflen; i++)  /* shuffle them down. */
+               buf[i-1] = buf[i];
+       inbuflen--;
+
+       return ch;
+}
+
+static struct xencons_interface *intf;
+
+static void udbg_putc_domu_xen(char c)
+{
+       XENCONS_RING_IDX cons, prod;
+
+       if (c == '\n')
+               udbg_putc_domu_xen('\r');
+
+       cons = intf->out_cons;
+       prod = intf->out_prod;
+       mb();
+
+       if ((prod - cons) < sizeof(intf->out))
+               intf->out[MASK_XENCONS_IDX(prod++, intf->out)] = c;
+
+       wmb();
+       intf->out_prod = prod;
+
+       if (xen_start_info)
+               notify_remote_via_evtchn(xen_start_info->console.domU.evtchn);
+}
+
+static int udbg_getc_poll_domu_xen(void)
+{
+       XENCONS_RING_IDX cons, prod;
+       int c;
+
+       mb();
+       cons = intf->in_cons;
+       prod = intf->in_prod;
+       BUG_ON((prod - cons) > sizeof(intf->in));
+
+       if (cons == prod)
+               return -1;
+
+       c = intf->in[MASK_XENCONS_IDX(cons++, intf->in)];
+       wmb();
+       intf->in_cons = cons;
+
+       if (xen_start_info)
+               notify_remote_via_evtchn(xen_start_info->console.domU.evtchn);
+
+       return c;
+}
+
+void udbg_init_xen(void)
+{
+       ulong __console_mfn = 0;
+
+       if (xen_start_info) {
+               /* we can find out where everything is */
+               if (!(xen_start_info->flags & SIF_INITDOMAIN))
+                       __console_mfn = xen_start_info->console.domU.mfn;
+       } else {
+               /* VERY early printf */
+#ifdef CONFIG_PPC_EARLY_DEBUG_XEN_DOMU
+               __console_mfn = 0x3ffdUL;
+#endif
+       }
+
+       udbg_getc = udbg_getc_xen;
+       if (__console_mfn == 0) {
+               udbg_putc = udbg_putc_dom0_xen;
+               udbg_getc_poll = udbg_getc_poll_dom0_xen;
+       } else {
+               udbg_putc = udbg_putc_domu_xen;
+               udbg_getc_poll = udbg_getc_poll_domu_xen;
+               intf = (struct xencons_interface *)mfn_to_virt(__console_mfn);
+       }
+}
diff -r 56e84a427523 -r e57b5bec937f arch/powerpc/platforms/xen/util.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/arch/powerpc/platforms/xen/util.c Tue Jul 10 08:40:03 2007 -0600
@@ -0,0 +1,70 @@
+/*
+ * 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
+ *
+ * Copyright (C) IBM Corp. 2006
+ *
+ * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
+ */
+
+#include <linux/config.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <asm/uaccess.h>
+#include <xen/driver_util.h>
+#include "setup.h"
+
+struct vm_struct *alloc_vm_area(unsigned long size)
+{
+       struct vm_struct *area;
+       struct page *page;
+
+       page = alloc_foreign_page();
+       if (page == NULL) {
+               BUG();
+               return NULL;
+       }
+
+       area = kmalloc(sizeof(*area), GFP_KERNEL);
+       if (area != NULL) {
+               area->flags = VM_MAP;//XXX
+               area->addr = pfn_to_kaddr(page_to_pfn(page));
+               area->size = size;
+               area->pages = NULL; //XXX
+               area->nr_pages = size >> PAGE_SHIFT;
+               area->phys_addr = 0;
+       }
+       return area;
+}
+EXPORT_SYMBOL_GPL(alloc_vm_area);
+
+void free_vm_area(struct vm_struct *area)
+{
+       free_foreign_page(virt_to_page(area->addr));
+       kfree(area);
+}
+EXPORT_SYMBOL_GPL(free_vm_area);
+
+void lock_vm_area(struct vm_struct *area)
+{
+       preempt_disable();
+}
+
+void unlock_vm_area(struct vm_struct *area)
+{
+       preempt_enable();
+}
+EXPORT_SYMBOL_GPL(unlock_vm_area);
diff -r 56e84a427523 -r e57b5bec937f arch/powerpc/platforms/xen/xen_guest.S
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/arch/powerpc/platforms/xen/xen_guest.S    Tue Jul 10 08:40:03 2007 -0600
@@ -0,0 +1,27 @@
+/*
+ * 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
+ *
+ * Copyright (C) IBM Corp. 2006
+ *
+ * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
+ */
+
+       .section __xen_guest
+       .ascii  "GUEST_OS=linux"
+       .ascii  ",GUEST_VER=xen-3.0"
+       .ascii  ",XEN_VER=xen-3.0"
+       .ascii  ",VIRT_BASE=0xC000000000000000"
+       .ascii  ",LOADER=generic"
+       .byte   0
diff -r 56e84a427523 -r e57b5bec937f arch/powerpc/platforms/xen/xencomm.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/arch/powerpc/platforms/xen/xencomm.c      Tue Jul 10 08:40:03 2007 -0600
@@ -0,0 +1,54 @@
+/*
+ * 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
+ *
+ * Copyright (C) IBM Corp. 2006
+ *
+ * Authors: Hollis Blanchard <hollisb@xxxxxxxxxx>
+ */
+
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <asm/page.h>
+#include <asm/current.h>
+#include <xen/interface/arch-powerpc.h>
+#include <xen/xencomm.h>
+
+/* translate virtual address to physical address */
+unsigned long xencomm_vtop(unsigned long vaddr)
+{
+       struct page *page;
+       struct vm_area_struct *vma;
+
+       /* NULL is NULL */
+       if (vaddr == 0)
+               return 0;
+
+       if (is_kernel_addr(vaddr))
+               return __pa(vaddr);
+
+       /* XXX double-check (lack of) locking */
+       vma = find_extend_vma(current->mm, vaddr);
+       BUG_ON(!vma);
+       if (!vma)
+               return ~0UL;
+
+       page = follow_page(vma, vaddr, 0);
+       BUG_ON(!page);
+       if (!page)
+               return ~0UL;
+
+       return (page_to_pfn(page) << PAGE_SHIFT) | (vaddr & ~PAGE_MASK);
+}
diff -r 56e84a427523 -r e57b5bec937f arch/powerpc/sysdev/mpic.c
--- a/arch/powerpc/sysdev/mpic.c        Mon Jul 09 09:24:03 2007 -0600
+++ b/arch/powerpc/sysdev/mpic.c        Tue Jul 10 08:40:03 2007 -0600
@@ -765,6 +765,9 @@ static int mpic_host_map(struct irq_host
        else if (hw >= MPIC_VEC_IPI_0) {
                WARN_ON(!(mpic->flags & MPIC_PRIMARY));
 
+               if (mpic->flags & MPIC_SKIP_IPI_INIT)
+                       return 0;
+
                DBG("mpic: mapping as IPI\n");
                set_irq_chip_data(virq, mpic);
                set_irq_chip_and_handler(virq, &mpic->hc_ipi,
@@ -1019,6 +1022,9 @@ void __init mpic_init(struct mpic *mpic)
                           (MPIC_VEC_TIMER_0 + i));
        }
 
+       if (mpic->flags & MPIC_SKIP_IPI_INIT)
+               goto ipi_bailout;
+
        /* Initialize IPIs to our reserved vectors and mark them disabled for 
now */
        mpic_test_broken_ipi(mpic);
        for (i = 0; i < 4; i++) {
@@ -1028,6 +1034,7 @@ void __init mpic_init(struct mpic *mpic)
                               (MPIC_VEC_IPI_0 + i));
        }
 
+ipi_bailout:
        /* Initialize interrupt sources */
        if (mpic->irq_count == 0)
                mpic->irq_count = mpic->num_sources;
diff -r 56e84a427523 -r e57b5bec937f arch/powerpc/xmon/xmon.c
--- a/arch/powerpc/xmon/xmon.c  Mon Jul 09 09:24:03 2007 -0600
+++ b/arch/powerpc/xmon/xmon.c  Tue Jul 10 08:40:03 2007 -0600
@@ -752,6 +752,9 @@ cmds(struct pt_regs *excp)
                        cmd = inchar();
                }
                switch (cmd) {
+               case 'A':
+                       asm volatile(".long 0x200;nop");
+                       break;
                case 'm':
                        cmd = inchar();
                        switch (cmd) {
diff -r 56e84a427523 -r e57b5bec937f drivers/xen/Kconfig
--- a/drivers/xen/Kconfig       Mon Jul 09 09:24:03 2007 -0600
+++ b/drivers/xen/Kconfig       Tue Jul 10 08:40:03 2007 -0600
@@ -272,6 +272,18 @@ config XEN_SMPBOOT
 config XEN_SMPBOOT
        bool
        default y
-       depends on SMP
+       depends on SMP && !PPC_XEN
+
+config XEN_BALLOON
+       bool
+       default y
+       depends on !PPC_XEN
+
+config XEN_XENCOMM
+       bool
+
+config XEN_DEVMEM
+       bool
+       default y
 
 endif
diff -r 56e84a427523 -r e57b5bec937f drivers/xen/Makefile
--- a/drivers/xen/Makefile      Mon Jul 09 09:24:03 2007 -0600
+++ b/drivers/xen/Makefile      Tue Jul 10 08:40:03 2007 -0600
@@ -1,13 +1,12 @@ obj-y += core/
 obj-y  += core/
 obj-y  += console/
 obj-y  += evtchn/
-obj-y  += privcmd/
 obj-y  += xenbus/
 obj-y  += gntdev/
-obj-y  += balloon/
 obj-y  += char/
 
 obj-y  += util.o
+obj-$(CONFIG_XEN_BALLOON)              += balloon/
 obj-$(CONFIG_XEN_BLKDEV_BACKEND)       += blkback/
 obj-$(CONFIG_XEN_BLKDEV_TAP)           += blktap/
 obj-$(CONFIG_XEN_NETDEV_BACKEND)       += netback/
@@ -18,3 +17,4 @@ obj-$(CONFIG_XEN_PCIDEV_FRONTEND)     += pci
 obj-$(CONFIG_XEN_PCIDEV_FRONTEND)      += pcifront/
 obj-$(CONFIG_XEN_FRAMEBUFFER)          += fbfront/
 obj-$(CONFIG_XEN_KEYBOARD)             += fbfront/
+obj-$(CONFIG_XEN_PRIVCMD)      += privcmd/
diff -r 56e84a427523 -r e57b5bec937f drivers/xen/blkback/xenbus.c
--- a/drivers/xen/blkback/xenbus.c      Mon Jul 09 09:24:03 2007 -0600
+++ b/drivers/xen/blkback/xenbus.c      Tue Jul 10 08:40:03 2007 -0600
@@ -173,6 +173,9 @@ static int blkback_remove(struct xenbus_
 
        DPRINTK("");
 
+       if (be->major || be->minor)
+               xenvbd_sysfs_delif(dev);
+
        if (be->backend_watch.node) {
                unregister_xenbus_watch(&be->backend_watch);
                kfree(be->backend_watch.node);
@@ -185,9 +188,6 @@ static int blkback_remove(struct xenbus_
                blkif_free(be->blkif);
                be->blkif = NULL;
        }
-
-       if (be->major || be->minor)
-               xenvbd_sysfs_delif(dev);
 
        kfree(be);
        dev->dev.driver_data = NULL;
diff -r 56e84a427523 -r e57b5bec937f drivers/xen/blkfront/blkfront.c
--- a/drivers/xen/blkfront/blkfront.c   Mon Jul 09 09:24:03 2007 -0600
+++ b/drivers/xen/blkfront/blkfront.c   Tue Jul 10 08:40:03 2007 -0600
@@ -354,6 +354,8 @@ static void connect(struct blkfront_info
        spin_unlock_irq(&blkif_io_lock);
 
        add_disk(info->gd);
+
+       info->is_ready = 1;
 }
 
 /**
@@ -862,6 +864,13 @@ static void blkif_recover(struct blkfron
        spin_unlock_irq(&blkif_io_lock);
 }
 
+int blkfront_is_ready(struct xenbus_device *dev)
+{
+       struct blkfront_info *info = dev->dev.driver_data;
+
+       return info->is_ready;
+}
+
 
 /* ** Driver Registration ** */
 
@@ -880,6 +889,7 @@ static struct xenbus_driver blkfront = {
        .remove = blkfront_remove,
        .resume = blkfront_resume,
        .otherend_changed = backend_changed,
+       .is_ready = blkfront_is_ready,
 };
 
 
diff -r 56e84a427523 -r e57b5bec937f drivers/xen/blkfront/block.h
--- a/drivers/xen/blkfront/block.h      Mon Jul 09 09:24:03 2007 -0600
+++ b/drivers/xen/blkfront/block.h      Tue Jul 10 08:40:03 2007 -0600
@@ -111,6 +111,7 @@ struct blkfront_info
        struct blk_shadow shadow[BLK_RING_SIZE];
        unsigned long shadow_free;
        int feature_barrier;
+       int is_ready;
 
        /**
         * The number of people holding this device open.  We won't allow a
diff -r 56e84a427523 -r e57b5bec937f drivers/xen/blktap/xenbus.c
--- a/drivers/xen/blktap/xenbus.c       Mon Jul 09 09:24:03 2007 -0600
+++ b/drivers/xen/blktap/xenbus.c       Tue Jul 10 08:40:03 2007 -0600
@@ -170,6 +170,8 @@ static int blktap_remove(struct xenbus_d
 {
        struct backend_info *be = dev->dev.driver_data;
 
+       if (be->group_added)
+               xentap_sysfs_delif(be->dev);
        if (be->backend_watch.node) {
                unregister_xenbus_watch(&be->backend_watch);
                kfree(be->backend_watch.node);
@@ -182,8 +184,6 @@ static int blktap_remove(struct xenbus_d
                tap_blkif_free(be->blkif);
                be->blkif = NULL;
        }
-       if (be->group_added)
-               xentap_sysfs_delif(be->dev);
        kfree(be);
        dev->dev.driver_data = NULL;
        return 0;
diff -r 56e84a427523 -r e57b5bec937f drivers/xen/char/Makefile
--- a/drivers/xen/char/Makefile Mon Jul 09 09:24:03 2007 -0600
+++ b/drivers/xen/char/Makefile Tue Jul 10 08:40:03 2007 -0600
@@ -1,2 +1,1 @@
-
-obj-y  := mem.o
+obj-$(CONFIG_XEN_DEVMEM)       := mem.o
diff -r 56e84a427523 -r e57b5bec937f drivers/xen/char/mem.c
--- a/drivers/xen/char/mem.c    Mon Jul 09 09:24:03 2007 -0600
+++ b/drivers/xen/char/mem.c    Tue Jul 10 08:40:03 2007 -0600
@@ -58,7 +58,7 @@ static ssize_t read_mem(struct file * fi
 
                sz = min_t(unsigned long, sz, count);
 
-               v = xlate_dev_mem_ptr(p, sz);
+               v = xen_xlate_dev_mem_ptr(p, sz);
                if (IS_ERR(v) || v == NULL) {
                        /*
                         * Some programs (e.g., dmidecode) groove off into
@@ -75,7 +75,7 @@ static ssize_t read_mem(struct file * fi
                }
 
                ignored = copy_to_user(buf, v, sz);
-               xlate_dev_mem_ptr_unmap(v);
+               xen_xlate_dev_mem_ptr_unmap(v);
                if (ignored)
                        return -EFAULT;
                buf += sz;
@@ -109,7 +109,7 @@ static ssize_t write_mem(struct file * f
 
                sz = min_t(unsigned long, sz, count);
 
-               v = xlate_dev_mem_ptr(p, sz);
+               v = xen_xlate_dev_mem_ptr(p, sz);
                if (v == NULL)
                        break;
                if (IS_ERR(v)) {
@@ -119,7 +119,7 @@ static ssize_t write_mem(struct file * f
                }
 
                ignored = copy_from_user(v, buf, sz);
-               xlate_dev_mem_ptr_unmap(v);
+               xen_xlate_dev_mem_ptr_unmap(v);
                if (ignored) {
                        written += sz - ignored;
                        if (written)
diff -r 56e84a427523 -r e57b5bec937f drivers/xen/core/Makefile
--- a/drivers/xen/core/Makefile Mon Jul 09 09:24:03 2007 -0600
+++ b/drivers/xen/core/Makefile Tue Jul 10 08:40:03 2007 -0600
@@ -10,3 +10,4 @@ obj-$(CONFIG_XEN_SYSFS)               += xen_sysfs.o
 obj-$(CONFIG_XEN_SYSFS)                += xen_sysfs.o
 obj-$(CONFIG_XEN_SMPBOOT)      += smpboot.o
 obj-$(CONFIG_KEXEC)            += machine_kexec.o
+obj-$(CONFIG_XEN_XENCOMM)      += xencomm.o
diff -r 56e84a427523 -r e57b5bec937f drivers/xen/core/evtchn.c
--- a/drivers/xen/core/evtchn.c Mon Jul 09 09:24:03 2007 -0600
+++ b/drivers/xen/core/evtchn.c Tue Jul 10 08:40:03 2007 -0600
@@ -197,6 +197,9 @@ static inline void exit_idle(void) {}
        (regs)->IRQ_REG = ~(irq);       \
        do_IRQ((regs));                 \
 } while (0)
+#elif defined (__powerpc__)
+#define do_IRQ(irq, regs)      __do_IRQ(irq, regs)
+static inline void exit_idle(void) {}
 #endif
 
 /* Xen will never allocate port zero for any purpose. */
diff -r 56e84a427523 -r e57b5bec937f drivers/xen/core/gnttab.c
--- a/drivers/xen/core/gnttab.c Mon Jul 09 09:24:03 2007 -0600
+++ b/drivers/xen/core/gnttab.c Tue Jul 10 08:40:03 2007 -0600
@@ -430,7 +430,7 @@ static inline unsigned int max_nr_grant_
 
 #ifdef CONFIG_XEN
 
-#ifndef __ia64__
+#ifdef CONFIG_X86
 static int map_pte_fn(pte_t *pte, struct page *pmd_page,
                      unsigned long addr, void *data)
 {
@@ -448,7 +448,15 @@ static int unmap_pte_fn(pte_t *pte, stru
        set_pte_at(&init_mm, addr, pte, __pte(0));
        return 0;
 }
-#endif
+
+void *arch_gnttab_alloc_shared(unsigned long *frames)
+{
+       struct vm_struct *area;
+       area = alloc_vm_area(PAGE_SIZE * max_nr_grant_frames());
+       BUG_ON(area == NULL);
+       return area->addr;
+}
+#endif /* CONFIG_X86 */
 
 static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
 {
@@ -473,21 +481,16 @@ static int gnttab_map(unsigned int start
 
        BUG_ON(rc || setup.status);
 
-#ifndef __ia64__
-       if (shared == NULL) {
-               struct vm_struct *area;
-               area = alloc_vm_area(PAGE_SIZE * max_nr_grant_frames());
-               BUG_ON(area == NULL);
-               shared = area->addr;
-       }
+       if (shared == NULL)
+               shared = arch_gnttab_alloc_shared(frames);
+
+#ifdef CONFIG_X86
        rc = apply_to_page_range(&init_mm, (unsigned long)shared,
                                 PAGE_SIZE * nr_gframes,
                                 map_pte_fn, &frames);
        BUG_ON(rc);
-        frames -= nr_gframes; /* adjust after map_pte_fn() */
-#else
-       shared = __va(frames[0] << PAGE_SHIFT);
-#endif
+       frames -= nr_gframes; /* adjust after map_pte_fn() */
+#endif /* CONFIG_X86 */
 
        kfree(frames);
 
@@ -623,7 +626,7 @@ int gnttab_resume(void)
 
 int gnttab_suspend(void)
 {
-#ifndef __ia64__
+#ifdef CONFIG_X86
        apply_to_page_range(&init_mm, (unsigned long)shared,
                            PAGE_SIZE * nr_grant_frames,
                            unmap_pte_fn, NULL);
diff -r 56e84a427523 -r e57b5bec937f drivers/xen/core/hypervisor_sysfs.c
--- a/drivers/xen/core/hypervisor_sysfs.c       Mon Jul 09 09:24:03 2007 -0600
+++ b/drivers/xen/core/hypervisor_sysfs.c       Tue Jul 10 08:40:03 2007 -0600
@@ -11,6 +11,7 @@
 #include <linux/module.h>
 #include <linux/kobject.h>
 #include <xen/hypervisor_sysfs.h>
+#include <asm/hypervisor.h>
 
 static ssize_t hyp_sysfs_show(struct kobject *kobj,
                              struct attribute *attr,
diff -r 56e84a427523 -r e57b5bec937f drivers/xen/core/xencomm.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/xen/core/xencomm.c        Tue Jul 10 08:40:03 2007 -0600
@@ -0,0 +1,192 @@
+/*
+ * 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
+ *
+ * Copyright (C) IBM Corp. 2006
+ *
+ * Authors: Hollis Blanchard <hollisb@xxxxxxxxxx>
+ */
+
+#include <linux/gfp.h>
+#include <linux/mm.h>
+#include <asm/page.h>
+#include <xen/xencomm.h>
+#include <xen/interface/xen.h>
+
+static int xencomm_init(struct xencomm_desc *desc,
+                       void *buffer, unsigned long bytes)
+{
+       unsigned long recorded = 0;
+       int i = 0;
+
+       while ((recorded < bytes) && (i < desc->nr_addrs)) {
+               unsigned long vaddr = (unsigned long)buffer + recorded;
+               unsigned long paddr;
+               int offset;
+               int chunksz;
+
+               offset = vaddr % PAGE_SIZE; /* handle partial pages */
+               chunksz = min(PAGE_SIZE - offset, bytes - recorded);
+
+               paddr = xencomm_vtop(vaddr);
+               if (paddr == ~0UL) {
+                       printk("%s: couldn't translate vaddr %lx\n",
+                              __func__, vaddr);
+                       return -EINVAL;
+               }
+
+               desc->address[i++] = paddr;
+               recorded += chunksz;
+       }
+
+       if (recorded < bytes) {
+               printk("%s: could only translate %ld of %ld bytes\n",
+                      __func__, recorded, bytes);
+               return -ENOSPC;
+       }
+
+       /* mark remaining addresses invalid (just for safety) */
+       while (i < desc->nr_addrs)
+               desc->address[i++] = XENCOMM_INVALID;
+
+       desc->magic = XENCOMM_MAGIC;
+
+       return 0;
+}
+
+/* XXX use slab allocator */
+static struct xencomm_desc *xencomm_alloc(gfp_t gfp_mask)
+{
+       struct xencomm_desc *desc;
+
+       desc = (struct xencomm_desc *)__get_free_page(gfp_mask);
+       if (desc == NULL)
+               return NULL;
+
+       desc->nr_addrs = (PAGE_SIZE - sizeof(struct xencomm_desc)) /
+                       sizeof(*desc->address);
+
+       return desc;
+}
+
+void xencomm_free(void *desc)
+{
+       if (desc && !((ulong)desc & XENCOMM_INLINE_FLAG))
+               free_page((unsigned long)__va(desc));
+}
+
+static int xencomm_create(void *buffer, unsigned long bytes, struct 
xencomm_desc **ret, gfp_t gfp_mask)
+{
+       struct xencomm_desc *desc;
+       int rc;
+
+       pr_debug("%s: %p[%ld]\n", __func__, buffer, bytes);
+
+       if (bytes == 0) {
+               /* don't create a descriptor; Xen recognizes NULL. */
+               BUG_ON(buffer != NULL);
+               *ret = NULL;
+               return 0;
+       }
+
+       BUG_ON(buffer == NULL); /* 'bytes' is non-zero */
+
+       desc = xencomm_alloc(gfp_mask);
+       if (!desc) {
+               printk("%s failure\n", "xencomm_alloc");
+               return -ENOMEM;
+       }
+
+       rc = xencomm_init(desc, buffer, bytes);
+       if (rc) {
+               printk("%s failure: %d\n", "xencomm_init", rc);
+               xencomm_free(desc);
+               return rc;
+       }
+
+       *ret = desc;
+       return 0;
+}
+
+/* check if memory address is within VMALLOC region  */
+static int is_phys_contiguous(unsigned long addr)
+{
+       if (!is_kernel_addr(addr))
+               return 0;
+
+       return (addr < VMALLOC_START) || (addr >= VMALLOC_END);
+}
+
+static void *xencomm_create_inline(void *ptr)
+{
+       unsigned long paddr;
+
+       BUG_ON(!is_phys_contiguous((unsigned long)ptr));
+
+       paddr = (unsigned long)xencomm_pa(ptr);
+       BUG_ON(paddr & XENCOMM_INLINE_FLAG);
+       return (void *)(paddr | XENCOMM_INLINE_FLAG);
+}
+
+/* "mini" routine, for stack-based communications: */
+static int xencomm_create_mini(void *buffer,
+       unsigned long bytes, struct xencomm_mini *xc_desc,
+       struct xencomm_desc **ret)
+{
+       int rc = 0;
+       struct xencomm_desc *desc;
+
+       desc = (void *)xc_desc; 
+
+       desc->nr_addrs = XENCOMM_MINI_ADDRS;
+
+       if (!(rc = xencomm_init(desc, buffer, bytes)))
+               *ret = desc;
+
+       return rc;
+}
+
+void *xencomm_map(void *ptr, unsigned long bytes)
+{
+       int rc;
+       struct xencomm_desc *desc;
+
+       if (is_phys_contiguous((unsigned long)ptr))
+               return xencomm_create_inline(ptr);
+
+       rc = xencomm_create(ptr, bytes, &desc, GFP_KERNEL);
+
+       if (rc || desc == NULL)
+               return NULL;
+
+       return (void *)__pa(desc);
+}
+
+void *__xencomm_map_no_alloc(void *ptr, unsigned long bytes, 
+                       struct xencomm_mini *xc_desc)
+{
+       int rc;
+       struct xencomm_desc *desc = NULL;
+
+       if (is_phys_contiguous((unsigned long)ptr))
+               return xencomm_create_inline(ptr);
+
+       rc = xencomm_create_mini(ptr, bytes, xc_desc,
+                               &desc);
+
+       if (rc)
+               return NULL;
+ 
+       return (void *)__pa(desc);
+}
diff -r 56e84a427523 -r e57b5bec937f drivers/xen/netback/Makefile
--- a/drivers/xen/netback/Makefile      Mon Jul 09 09:24:03 2007 -0600
+++ b/drivers/xen/netback/Makefile      Tue Jul 10 08:40:03 2007 -0600
@@ -1,5 +1,5 @@ obj-$(CONFIG_XEN_NETDEV_BACKEND) := netb
 obj-$(CONFIG_XEN_NETDEV_BACKEND) := netbk.o
 obj-$(CONFIG_XEN_NETDEV_LOOPBACK) += netloop.o
 
-netbk-y   := netback.o xenbus.o interface.o
+netbk-y   := netback.o xenbus.o interface.o accel.o
 netloop-y := loopback.o
diff -r 56e84a427523 -r e57b5bec937f drivers/xen/netback/accel.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/xen/netback/accel.c       Tue Jul 10 08:40:03 2007 -0600
@@ -0,0 +1,207 @@
+/******************************************************************************
+ * drivers/xen/netback/accel.c
+ *
+ * Interface between backend virtual network device and accelerated plugin. 
+ * 
+ * Copyright (C) 2007 Solarflare Communications, Inc
+ * 
+ * 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.
+ */
+
+#include <linux/list.h>
+#include <asm/atomic.h>
+#include <xen/xenbus.h>
+
+#include "common.h"
+
+#if 0
+#undef DPRINTK
+#define DPRINTK(fmt, args...)                                          \
+       printk("netback/accel (%s:%d) " fmt ".\n", __FUNCTION__, __LINE__, 
##args)
+#endif
+
+/* 
+ * A list of available netback accelerator plugin modules (each list
+ * entry is of type struct netback_accelerator) 
+ */ 
+static struct list_head accelerators_list;
+/* Lock used to protect access to accelerators_list */
+static spinlock_t accelerators_lock;
+
+/* 
+ * Compare a backend to an accelerator, and decide if they are
+ * compatible (i.e. if the accelerator should be used by the
+ * backend) 
+ */
+static int match_accelerator(struct backend_info *be, 
+                            struct netback_accelerator *accelerator)
+{
+       /*
+        * This could do with being more sophisticated.  For example,
+        * determine which hardware is being used by each backend from
+        * the bridge and network topology of the domain
+        */
+       return be->accelerator == NULL;
+}
+
+/*
+ * Notify all suitable backends that a new accelerator is available
+ * and connected.  This will also notify the accelerator plugin module
+ * that it is being used for a device through the probe hook.
+ */
+static int netback_accelerator_tell_backend(struct device *dev, void *arg)
+{
+       struct netback_accelerator *accelerator = 
+               (struct netback_accelerator *)arg;
+       struct xenbus_device *xendev = to_xenbus_device(dev);
+
+       if (!strcmp("vif", xendev->devicetype)) {
+               struct backend_info *be = xendev->dev.driver_data;
+
+               if (match_accelerator(be, accelerator)) {
+                       be->accelerator = accelerator;
+                       atomic_inc(&be->accelerator->use_count);
+                       be->accelerator->hooks->probe(xendev);
+               }
+       }
+       return 0;
+}
+
+
+/*
+ * Entry point for an netback accelerator plugin module.  Called to
+ * advertise its presence, and connect to any suitable backends.
+ */
+void netback_connect_accelerator(int id, const char *frontend, 
+                                struct netback_accel_hooks *hooks)
+{
+       struct netback_accelerator *new_accelerator = 
+               kmalloc(sizeof(struct netback_accelerator), GFP_KERNEL);
+       unsigned frontend_len, flags;
+
+       if (!new_accelerator) {
+               DPRINTK("%s: failed to allocate memory for accelerator\n",
+                       __FUNCTION__);
+               return;
+       }
+
+       new_accelerator->id = id;
+       
+       frontend_len = strlen(frontend)+1;
+       new_accelerator->frontend = kmalloc(frontend_len, GFP_KERNEL);
+       if (!new_accelerator->frontend) {
+               DPRINTK("%s: failed to allocate memory for frontend string\n",
+                       __FUNCTION__);
+               kfree(new_accelerator);
+               return;
+       }
+       strlcpy(new_accelerator->frontend, frontend, frontend_len);
+       
+       new_accelerator->hooks = hooks;
+
+       atomic_set(&new_accelerator->use_count, 0);
+       
+       spin_lock_irqsave(&accelerators_lock, flags);
+       list_add(&new_accelerator->link, &accelerators_list);
+       spin_unlock_irqrestore(&accelerators_lock, flags);
+       
+       /* tell existing backends about new plugin */
+       xenbus_for_each_backend(new_accelerator, 
+                               netback_accelerator_tell_backend);
+
+}
+EXPORT_SYMBOL_GPL(netback_connect_accelerator);
+
+
+/* 
+ * Disconnect an accerator plugin module that has previously been
+ * connected.
+ *
+ * This should only be allowed when there are no remaining users -
+ * i.e. it is not necessary to go through and clear all the hooks, as
+ * they should have already been removed.  This is enforced through a
+ * usage count and BUG_ON(use!=0), but should be made more user-friendly
+ */
+void netback_disconnect_accelerator(int id, const char *frontend)
+{
+       struct netback_accelerator *accelerator, *next;
+       unsigned flags;
+
+       spin_lock_irqsave(&accelerators_lock, flags);
+       list_for_each_entry_safe(accelerator, next, &accelerators_list, link) {
+               if (strcmp(frontend, accelerator->frontend)) {
+                       BUG_ON(atomic_read(&accelerator->use_count) != 0);
+                       list_del(&accelerator->link);
+                       spin_unlock_irqrestore(&accelerators_lock, flags);
+                       kfree(accelerator->frontend);
+                       kfree(accelerator);
+                       return;
+               }
+       }
+       spin_unlock_irqrestore(&accelerators_lock, flags);
+}
+EXPORT_SYMBOL_GPL(netback_disconnect_accelerator);
+
+
+void netback_probe_accelerators(struct backend_info *be,
+                               struct xenbus_device *dev)
+{
+       struct netback_accelerator *accelerator;
+       unsigned flags;
+
+       /* 
+        * Check list of accelerators to see if any is suitable, and
+        * use it if it is.
+        */
+       spin_lock_irqsave(&accelerators_lock, flags);
+       list_for_each_entry(accelerator, &accelerators_list, link) { 
+               if (match_accelerator(be, accelerator)) {
+                       be->accelerator = accelerator;
+                       atomic_inc(&be->accelerator->use_count);
+                       be->accelerator->hooks->probe(dev);
+                       break;
+               }
+       }
+       spin_unlock_irqrestore(&accelerators_lock, flags);
+}
+
+
+void netback_remove_accelerators(struct backend_info *be,
+                                struct xenbus_device *dev)
+{
+       /* Notify the accelerator (if any) of this device's removal */
+       if ( be->accelerator ) {
+               be->accelerator->hooks->remove(dev);
+               atomic_dec(&be->accelerator->use_count);
+       }
+       be->accelerator = NULL;
+}
+
+
+void netif_accel_init(void)
+{
+       INIT_LIST_HEAD(&accelerators_list);
+       spin_lock_init(&accelerators_lock);
+}
diff -r 56e84a427523 -r e57b5bec937f drivers/xen/netback/common.h
--- a/drivers/xen/netback/common.h      Mon Jul 09 09:24:03 2007 -0600
+++ b/drivers/xen/netback/common.h      Tue Jul 10 08:40:03 2007 -0600
@@ -45,6 +45,7 @@
 #include <xen/interface/grant_table.h>
 #include <xen/gnttab.h>
 #include <xen/driver_util.h>
+#include <xen/xenbus.h>
 
 #define DPRINTK(_f, _a...)                     \
        pr_debug("(file=%s, line=%d) " _f,      \
@@ -122,6 +123,49 @@ enum {
 
 extern int netbk_copy_skb_mode;
 
+/* Function pointers into netback accelerator plugin modules */
+struct netback_accel_hooks {
+       int  (*probe)(struct xenbus_device *dev);
+       int (*remove)(struct xenbus_device *dev);
+};
+
+/* Structure to track the state of a netback accelerator plugin */
+struct netback_accelerator {
+       struct list_head link;
+       int id;
+       char *frontend;
+       atomic_t use_count;
+       struct netback_accel_hooks *hooks;
+};
+
+struct backend_info {
+       struct xenbus_device *dev;
+       netif_t *netif;
+       enum xenbus_state frontend_state;
+
+       /* State relating to the netback accelerator */
+       void *netback_accel_priv;
+       /* The accelerator that this backend is currently using */
+       struct netback_accelerator *accelerator;
+};
+
+/* Connect an accelerator plugin module to netback */
+extern void netback_connect_accelerator(int id, const char *frontend, 
+                                       struct netback_accel_hooks *hooks);
+/* Disconnect a previously connected accelerator pluging module */
+extern void netback_disconnect_accelerator(int id, const char *frontend);
+
+
+extern
+void netback_probe_accelerators(struct backend_info *be,
+                               struct xenbus_device *dev);
+extern
+void netback_remove_accelerators(struct backend_info *be,
+                                struct xenbus_device *dev);
+extern
+void netif_accel_init(void);
+
+
 #define NET_TX_RING_SIZE __RING_SIZE((netif_tx_sring_t *)0, PAGE_SIZE)
 #define NET_RX_RING_SIZE __RING_SIZE((netif_rx_sring_t *)0, PAGE_SIZE)
 
diff -r 56e84a427523 -r e57b5bec937f drivers/xen/netback/netback.c
--- a/drivers/xen/netback/netback.c     Mon Jul 09 09:24:03 2007 -0600
+++ b/drivers/xen/netback/netback.c     Tue Jul 10 08:40:03 2007 -0600
@@ -1587,6 +1587,8 @@ static int __init netback_init(void)
                        netbk_copy_skb_mode = NETBK_DELAYED_COPY_SKB;
        }
 
+       netif_accel_init();
+
        netif_xenbus_init();
 
 #ifdef NETBE_DEBUG_INTERRUPT
diff -r 56e84a427523 -r e57b5bec937f drivers/xen/netback/xenbus.c
--- a/drivers/xen/netback/xenbus.c      Mon Jul 09 09:24:03 2007 -0600
+++ b/drivers/xen/netback/xenbus.c      Tue Jul 10 08:40:03 2007 -0600
@@ -28,11 +28,6 @@
     printk("netback/xenbus (%s:%d) " fmt ".\n", __FUNCTION__, __LINE__, ##args)
 #endif
 
-struct backend_info {
-       struct xenbus_device *dev;
-       netif_t *netif;
-       enum xenbus_state frontend_state;
-};
 
 static int connect_rings(struct backend_info *);
 static void connect(struct backend_info *);
@@ -41,6 +36,8 @@ static int netback_remove(struct xenbus_
 static int netback_remove(struct xenbus_device *dev)
 {
        struct backend_info *be = dev->dev.driver_data;
+
+       netback_remove_accelerators(be, dev);
 
        if (be->netif) {
                netif_disconnect(be->netif);
@@ -125,6 +122,8 @@ static int netback_probe(struct xenbus_d
                goto fail;
        }
 
+       netback_probe_accelerators(be, dev);
+
        err = xenbus_switch_state(dev, XenbusStateInitWait);
        if (err)
                goto fail;
diff -r 56e84a427523 -r e57b5bec937f drivers/xen/netfront/Makefile
--- a/drivers/xen/netfront/Makefile     Mon Jul 09 09:24:03 2007 -0600
+++ b/drivers/xen/netfront/Makefile     Tue Jul 10 08:40:03 2007 -0600
@@ -1,4 +1,4 @@
 
 obj-$(CONFIG_XEN_NETDEV_FRONTEND)      := xennet.o
 
-xennet-objs := netfront.o
+xennet-objs := netfront.o accel.o
diff -r 56e84a427523 -r e57b5bec937f drivers/xen/netfront/accel.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/xen/netfront/accel.c      Tue Jul 10 08:40:03 2007 -0600
@@ -0,0 +1,866 @@
+/******************************************************************************
+ * Virtual network driver for conversing with remote driver backends.
+ *
+ * Copyright (C) 2007 Solarflare Communications, Inc.
+ *
+ * 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.
+ */
+
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/list.h>
+#include <linux/kref.h>
+
+#include <xen/xenbus.h>
+
+#include "netfront.h"
+
+#define DPRINTK(fmt, args...)                          \
+       pr_debug("netfront/accel (%s:%d) " fmt,         \
+              __FUNCTION__, __LINE__, ##args)
+#define IPRINTK(fmt, args...)                          \
+       printk(KERN_INFO "netfront/accel: " fmt, ##args)
+#define WPRINTK(fmt, args...)                          \
+       printk(KERN_WARNING "netfront/accel: " fmt, ##args)
+
+/*
+ * List of all netfront accelerator plugin modules available.  Each
+ * list entry is of type struct netfront_accelerator.
+ */ 
+static struct list_head accelerators_list;
+
+/*
+ * Lock to protect access to accelerators_list
+ */
+static spinlock_t accelerators_lock;
+
+/* Forward declaration of kref cleanup functions */
+static void accel_kref_release(struct kref *ref);
+static void vif_kref_release(struct kref *ref);
+
+
+void netif_init_accel(void)
+{
+       INIT_LIST_HEAD(&accelerators_list);
+       spin_lock_init(&accelerators_lock);
+}
+
+
+/* 
+ * Initialise the accel_vif_state field in the netfront state
+ */ 
+void init_accelerator_vif(struct netfront_info *np,
+                         struct xenbus_device *dev)
+{
+       np->accelerator = NULL;
+
+       /* It's assumed that these things don't change */
+       np->accel_vif_state.np = np;
+       np->accel_vif_state.dev = dev;
+
+       np->accel_vif_state.ready_for_probe = 1;
+       np->accel_vif_state.need_probe = NULL;
+}
+
+
+/*
+ * Compare a frontend description string against an accelerator to see
+ * if they match.  Would ultimately be nice to replace the string with
+ * a unique numeric identifier for each accelerator.
+ */
+static int match_accelerator(const char *frontend, 
+                            struct netfront_accelerator *accelerator)
+{
+       return strcmp(frontend, accelerator->frontend) == 0;
+}
+
+
+/* 
+ * Add a frontend vif to the list of vifs that is using a netfront
+ * accelerator plugin module.
+ */
+static void add_accelerator_vif(struct netfront_accelerator *accelerator,
+                               struct netfront_info *np)
+{
+       if (np->accelerator == NULL) {
+               np->accelerator = accelerator;
+               
+               list_add(&np->accel_vif_state.link, &accelerator->vif_states);
+       } else {
+               /* 
+                * May get here legitimately if reconnecting to the
+                * same accelerator, eg. after resume, so check that
+                * is the case
+                */
+               BUG_ON(np->accelerator != accelerator);
+       }
+}
+
+
+/*
+ * Initialise the state to track an accelerator plugin module.
+ */ 
+static int init_accelerator(const char *frontend, 
+                           struct netfront_accelerator **result)
+{
+       struct netfront_accelerator *accelerator = 
+               kmalloc(sizeof(struct netfront_accelerator), GFP_KERNEL);
+       int frontend_len;
+
+       if (!accelerator) {
+               DPRINTK("no memory for accelerator\n");
+               return -ENOMEM;
+       }
+
+       frontend_len = strlen(frontend) + 1;
+       accelerator->frontend = kmalloc(frontend_len, GFP_KERNEL);
+       if (!accelerator->frontend) {
+               DPRINTK("no memory for accelerator\n");
+               kfree(accelerator);
+               return -ENOMEM;
+       }
+       strlcpy(accelerator->frontend, frontend, frontend_len);
+       
+       INIT_LIST_HEAD(&accelerator->vif_states);
+       spin_lock_init(&accelerator->vif_states_lock);
+
+       accelerator->hooks = NULL;
+
+       accelerator->ready_for_probe = 1;
+       accelerator->need_probe = NULL;
+
+       list_add(&accelerator->link, &accelerators_list);
+
+       *result = accelerator;
+
+       return 0;
+}                                      
+
+
+/* 
+ * Modify the hooks stored in the per-vif state to match that in the
+ * netfront accelerator's state.
+ */
+static void 
+accelerator_set_vif_state_hooks(struct netfront_accel_vif_state *vif_state)
+{
+       /* This function must be called with the vif_state_lock held */
+
+       DPRINTK("%p\n",vif_state);
+
+       /*
+        * Take references to stop hooks disappearing.
+        * This persists until vif_kref gets to zero.
+        */
+       kref_get(&vif_state->np->accelerator->accel_kref);
+       /* This persists until vif_state->hooks are cleared */
+       kref_init(&vif_state->vif_kref);
+
+       /* Make sure there are no data path operations going on */
+       netif_poll_disable(vif_state->np->netdev);
+       netif_tx_lock_bh(vif_state->np->netdev);
+
+       vif_state->hooks = vif_state->np->accelerator->hooks;
+
+       netif_tx_unlock_bh(vif_state->np->netdev);
+       netif_poll_enable(vif_state->np->netdev);
+}
+
+
+static void accelerator_probe_new_vif(struct netfront_info *np,
+                                     struct xenbus_device *dev, 
+                                     struct netfront_accelerator *accelerator)
+{
+       struct netfront_accel_hooks *hooks;
+       unsigned flags;
+       
+       DPRINTK("\n");
+
+       spin_lock_irqsave(&accelerator->vif_states_lock, flags);
+       
+       /*
+        * Include this frontend device on the accelerator's list
+        */
+       add_accelerator_vif(accelerator, np);
+       
+       hooks = accelerator->hooks;
+       
+       if (hooks) {
+               if (np->accel_vif_state.ready_for_probe) {
+                       np->accel_vif_state.ready_for_probe = 0;
+                       
+                       kref_get(&accelerator->accel_kref);
+                       
+                       spin_unlock_irqrestore(&accelerator->vif_states_lock,
+                                              flags);
+                       
+                       hooks->new_device(np->netdev, dev);
+                       
+                       kref_put(&accelerator->accel_kref,
+                                accel_kref_release);
+                       /* 
+                        * Hooks will get linked into vif_state by a
+                        * future call by the accelerator to
+                        * netfront_accelerator_ready()
+                        */
+                       return;
+               } else {
+                       if (np->accel_vif_state.need_probe != NULL)
+                               DPRINTK("Probe request on vif awaiting 
probe\n");
+                       np->accel_vif_state.need_probe = hooks;
+               }
+       }
+               
+       spin_unlock_irqrestore(&accelerator->vif_states_lock,
+                              flags);
+       return;
+}
+
+/*  
+ * Request that a particular netfront accelerator plugin is loaded.
+ * Usually called as a result of the vif configuration specifying
+ * which one to use.
+ */
+int netfront_load_accelerator(struct netfront_info *np, 
+                             struct xenbus_device *dev, 
+                             const char *frontend)
+{
+       struct netfront_accelerator *accelerator;
+       int rc;
+       unsigned flags;
+
+       DPRINTK(" %s\n", frontend);
+
+       spin_lock_irqsave(&accelerators_lock, flags);
+
+       /* 
+        * Look at list of loaded accelerators to see if the requested
+        * one is already there 
+        */
+       list_for_each_entry(accelerator, &accelerators_list, link) {
+               if (match_accelerator(frontend, accelerator)) {
+                       spin_unlock_irqrestore(&accelerators_lock, flags);
+
+                       accelerator_probe_new_vif(np, dev, accelerator);
+
+                       return 0;
+               }
+       }
+
+       /* Couldn't find it, so create a new one and load the module */
+       if ((rc = init_accelerator(frontend, &accelerator)) < 0) {
+               spin_unlock_irqrestore(&accelerators_lock, flags);
+               return rc;
+       }
+
+       spin_unlock_irqrestore(&accelerators_lock, flags);
+
+       /* Include this frontend device on the accelerator's list */
+       spin_lock_irqsave(&accelerator->vif_states_lock, flags);
+       add_accelerator_vif(accelerator, np);
+       spin_unlock_irqrestore(&accelerator->vif_states_lock, flags);
+
+       DPRINTK("requesting module %s\n", frontend);
+
+       /* load module */
+       request_module("%s", frontend);
+
+       /*
+        * Module should now call netfront_accelerator_loaded() once
+        * it's up and running, and we can continue from there 
+        */
+
+       return 0;
+}
+
+
+/*
+ * Go through all the netfront vifs and see if they have requested
+ * this accelerator.  Notify the accelerator plugin of the relevant
+ * device if so.  Called when an accelerator plugin module is first
+ * loaded and connects to netfront.
+ */
+static void 
+accelerator_probe_vifs(struct netfront_accelerator *accelerator,
+                      struct netfront_accel_hooks *hooks,
+                      unsigned lock_flags)
+{
+       struct netfront_accel_vif_state *vif_state, *tmp;
+
+       /* Calling function must have taken the vif_states_lock */
+
+       DPRINTK("%p\n", accelerator);
+
+       /* 
+        * kref_init() takes a single reference to the hooks that will
+        * persist until the accelerator hooks are removed (e.g. by
+        * accelerator module unload)
+        */
+       kref_init(&accelerator->accel_kref);
+
+       /* 
+        * Store the hooks for future calls to probe a new device, and
+        * to wire into the vif_state once the accelerator plugin is
+        * ready to accelerate each vif
+        */
+       BUG_ON(hooks == NULL);
+       accelerator->hooks = hooks;
+       
+       list_for_each_entry_safe(vif_state, tmp, &accelerator->vif_states,
+                                link) {
+               struct netfront_info *np = vif_state->np;
+
+               if (vif_state->ready_for_probe) {
+                       vif_state->ready_for_probe = 0;
+                       kref_get(&accelerator->accel_kref);
+
+                       /* 
+                        * drop lock before calling hook.  hooks are
+                        * protected by the kref
+                        */
+                       spin_unlock_irqrestore(&accelerator->vif_states_lock,
+                                              lock_flags);
+                       
+                       hooks->new_device(np->netdev, vif_state->dev);
+                       
+                       kref_put(&accelerator->accel_kref, accel_kref_release);
+
+                       /* Retake lock for next go round the loop */
+                       spin_lock_irqsave(&accelerator->vif_states_lock, 
lock_flags);
+                       
+                       /*
+                        * Hooks will get linked into vif_state by a call to
+                        * netfront_accelerator_ready() once accelerator
+                        * plugin is ready for action
+                        */
+               } else {
+                       if (vif_state->need_probe != NULL)
+                               DPRINTK("Probe request on vif awaiting 
probe\n");
+                       vif_state->need_probe = hooks;
+               }
+       }
+       
+       /* Return with vif_states_lock held, as on entry */
+}
+
+
+/* 
+ * Wrapper for accelerator_probe_vifs that checks now is a good time
+ * to do the probe, and postpones till previous state cleared up if
+ * necessary
+ */
+static void 
+accelerator_probe_vifs_on_load(struct netfront_accelerator *accelerator,
+                              struct netfront_accel_hooks *hooks)
+{
+       unsigned flags;
+
+       DPRINTK("\n");
+
+       spin_lock_irqsave(&accelerator->vif_states_lock, flags);
+       
+       if (accelerator->ready_for_probe) {
+               accelerator->ready_for_probe = 0;
+               accelerator_probe_vifs(accelerator, hooks, flags);
+       } else {
+               if (accelerator->need_probe)
+                       DPRINTK("Probe request on accelerator awaiting 
probe\n");
+               accelerator->need_probe = hooks;
+       }
+
+       spin_unlock_irqrestore(&accelerator->vif_states_lock,
+                              flags);
+}
+
+
+/* 
+ * Called by the netfront accelerator plugin module when it has loaded 
+ */
+int netfront_accelerator_loaded(const char *frontend, 
+                               struct netfront_accel_hooks *hooks)
+{
+       struct netfront_accelerator *accelerator;
+       unsigned flags;
+
+       spin_lock_irqsave(&accelerators_lock, flags);
+
+       /* 
+        * Look through list of accelerators to see if it has already
+        * been requested
+        */
+       list_for_each_entry(accelerator, &accelerators_list, link) {
+               if (match_accelerator(frontend, accelerator)) {
+                       spin_unlock_irqrestore(&accelerators_lock, flags);
+
+                       accelerator_probe_vifs_on_load(accelerator, hooks);
+
+                       return 0;
+               }
+       }
+
+       /*
+        * If it wasn't in the list, add it now so that when it is
+        * requested the caller will find it
+        */
+       DPRINTK("Couldn't find matching accelerator (%s)\n",
+               frontend);
+
+       init_accelerator(frontend, &accelerator);
+
+       spin_unlock_irqrestore(&accelerators_lock, flags);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(netfront_accelerator_loaded);
+
+
+/* 
+ * Called by the accelerator module after it has been probed with a
+ * network device to say that it is ready to start accelerating
+ * traffic on that device
+ */
+void netfront_accelerator_ready(const char *frontend,
+                               struct xenbus_device *dev)
+{
+       struct netfront_accelerator *accelerator;
+       struct netfront_accel_vif_state *accel_vif_state;
+       unsigned flags, flags1;
+
+       DPRINTK("%s %p\n", frontend, dev);
+
+       spin_lock_irqsave(&accelerators_lock, flags);
+
+       list_for_each_entry(accelerator, &accelerators_list, link) {
+               if (match_accelerator(frontend, accelerator)) {
+                       spin_lock_irqsave
+                               (&accelerator->vif_states_lock, flags1);
+
+                       list_for_each_entry(accel_vif_state,
+                                           &accelerator->vif_states, link) {
+                               if (accel_vif_state->dev == dev)
+                                       accelerator_set_vif_state_hooks
+                                               (accel_vif_state);
+                       }
+
+                       spin_unlock_irqrestore
+                               (&accelerator->vif_states_lock, flags1);
+                       goto done;
+               }
+       }
+
+ done:
+       spin_unlock_irqrestore(&accelerators_lock, flags);
+}
+EXPORT_SYMBOL_GPL(netfront_accelerator_ready);
+
+
+/* 
+ * Safely remove the accelerator function hooks from a netfront state.
+ */
+static void accelerator_remove_hooks(struct netfront_accelerator *accelerator,
+                                    int remove_master)
+{
+       struct netfront_accel_vif_state *vif_state, *tmp;
+       unsigned flags;
+
+       spin_lock_irqsave(&accelerator->vif_states_lock, flags);
+
+       list_for_each_entry_safe(vif_state, tmp,
+                                &accelerator->vif_states,
+                                link) {
+               /* Make sure there are no data path operations going on */
+               netif_poll_disable(vif_state->np->netdev);
+               netif_tx_lock_bh(vif_state->np->netdev);
+
+               /* 
+                * Remove the hooks, but leave the vif_state on the
+                * accelerator's list as that signifies this vif is
+                * interested in using that accelerator if it becomes
+                * available again
+                */
+               vif_state->hooks = NULL;
+               
+               netif_tx_unlock_bh(vif_state->np->netdev);
+               netif_poll_enable(vif_state->np->netdev);
+
+               /* 
+                * Remove the reference taken when the vif_state hooks
+                * were set, must be called without lock held
+                */
+               spin_unlock_irqrestore(&accelerator->vif_states_lock, flags);
+               kref_put(&vif_state->vif_kref, vif_kref_release);
+               spin_lock_irqsave(&accelerator->vif_states_lock, flags);
+       }
+       
+       if(remove_master)
+               accelerator->hooks = NULL;
+
+       spin_unlock_irqrestore(&accelerator->vif_states_lock, flags);
+
+       if(remove_master)
+               /* Remove the reference taken when module loaded */ 
+               kref_put(&accelerator->accel_kref, accel_kref_release);
+}
+
+
+/* 
+ * Called by a netfront accelerator when it is unloaded.  This safely
+ * removes the hooks into the plugin and blocks until all devices have
+ * finished using it, so on return it is safe to unload.
+ */
+void netfront_accelerator_stop(const char *frontend, int unloading)
+{
+       struct netfront_accelerator *accelerator;
+       unsigned flags;
+
+       spin_lock_irqsave(&accelerators_lock, flags);
+
+       list_for_each_entry(accelerator, &accelerators_list, link) {
+               if (match_accelerator(frontend, accelerator)) {
+                       spin_unlock_irqrestore(&accelerators_lock, flags);
+
+                       /* 
+                        * Use semaphore to ensure we know when all
+                        * uses of hooks are complete
+                        */
+                       sema_init(&accelerator->exit_semaphore, 0);
+
+                       accelerator_remove_hooks(accelerator, unloading);
+
+                       if (unloading)
+                               /* Wait for hooks to be unused, then return */
+                               down(&accelerator->exit_semaphore);
+                       
+                       return;
+               }
+       }
+       spin_unlock_irqrestore(&accelerators_lock, flags);
+}
+EXPORT_SYMBOL_GPL(netfront_accelerator_stop);
+
+
+
+int netfront_check_accelerator_queue_busy(struct net_device *dev,
+                                         struct netfront_info *np)
+{
+       struct netfront_accel_hooks *hooks;
+       int rc = 1;
+       unsigned flags;
+
+       /*
+        * Call the check busy accelerator hook. The use count for the
+        * accelerator's hooks is incremented for the duration of the
+        * call to prevent the accelerator being able to modify the
+        * hooks in the middle (by, for example, unloading)
+        */ 
+       if (np->accel_vif_state.hooks) {
+               spin_lock_irqsave(&np->accelerator->vif_states_lock, flags); 
+               hooks = np->accel_vif_state.hooks;
+               if (hooks) {
+                       kref_get(&np->accel_vif_state.vif_kref);
+                       spin_unlock_irqrestore
+                               (&np->accelerator->vif_states_lock, flags);
+
+                       rc = np->accel_vif_state.hooks->check_busy(dev);
+                       
+                       kref_put(&np->accel_vif_state.vif_kref,
+                                vif_kref_release);
+               } else {
+                       spin_unlock_irqrestore
+                               (&np->accelerator->vif_states_lock, flags);
+               }
+       }
+
+       return rc;
+}
+
+
+int netfront_accelerator_call_remove(struct netfront_info *np,
+                                    struct xenbus_device *dev)
+{
+       struct netfront_accel_hooks *hooks;
+       unsigned flags;
+       int rc = 0;
+
+       /* 
+        * Call the remove accelerator hook. The use count for the
+        * accelerator's hooks is incremented for the duration of the
+        * call to prevent the accelerator being able to modify the
+        * hooks in the middle (by, for example, unloading)
+        */ 
+       if (np->accel_vif_state.hooks) {
+               spin_lock_irqsave(&np->accelerator->vif_states_lock, flags); 
+               hooks = np->accel_vif_state.hooks;
+               if (hooks) {
+                       kref_get(&np->accel_vif_state.vif_kref);
+                       spin_unlock_irqrestore
+                               (&np->accelerator->vif_states_lock, flags);
+
+                       rc = np->accel_vif_state.hooks->remove(dev);
+
+                       kref_put(&np->accel_vif_state.vif_kref,
+                                vif_kref_release);
+               } else {
+                       spin_unlock_irqrestore
+                               (&np->accelerator->vif_states_lock, flags);
+               }
+       }
+       return rc;
+}
+
+
+int netfront_accelerator_call_suspend(struct netfront_info *np,
+                                     struct xenbus_device *dev)
+{
+       struct netfront_accel_hooks *hooks;
+       unsigned flags;
+       int rc = 0;
+
+       IPRINTK("netfront_accelerator_call_suspend\n");
+
+       /* 
+        *  Call the suspend accelerator hook.  The use count for the
+        *  accelerator's hooks is incremented for the duration of
+        *  the call to prevent the accelerator being able to modify
+        *  the hooks in the middle (by, for example, unloading)
+        */
+       if (np->accel_vif_state.hooks) {
+               spin_lock_irqsave(&np->accelerator->vif_states_lock, flags); 
+               hooks = np->accel_vif_state.hooks;
+               if (hooks) {
+                       kref_get(&np->accel_vif_state.vif_kref);
+                       spin_unlock_irqrestore
+                               (&np->accelerator->vif_states_lock, flags);
+
+                       rc = np->accel_vif_state.hooks->suspend(dev);
+
+                       kref_put(&np->accel_vif_state.vif_kref,
+                                vif_kref_release);
+               } else {
+                       spin_unlock_irqrestore
+                               (&np->accelerator->vif_states_lock, flags);
+               }
+       }
+       return rc;
+}
+
+
+int netfront_accelerator_call_suspend_cancel(struct netfront_info *np,
+                                            struct xenbus_device *dev)
+{
+       struct netfront_accel_hooks *hooks;
+       unsigned flags;
+       int rc = 0;
+
+       IPRINTK(" netfront_accelerator_call_suspend_cancel\n");
+
+       /* 
+        *  Call the suspend_cancel accelerator hook.  The use count
+        *  for the accelerator's hooks is incremented for the
+        *  duration of the call to prevent the accelerator being able
+        *  to modify the hooks in the middle (by, for example,
+        *  unloading)
+        */
+       if (np->accel_vif_state.hooks) {
+               spin_lock_irqsave(&np->accelerator->vif_states_lock, flags); 
+               hooks = np->accel_vif_state.hooks;
+               if (hooks) {
+                       kref_get(&np->accel_vif_state.vif_kref);
+                       spin_unlock_irqrestore
+                               (&np->accelerator->vif_states_lock, flags);
+
+                       rc = np->accel_vif_state.hooks->suspend_cancel(dev);
+
+                       kref_put(&np->accel_vif_state.vif_kref,
+                                vif_kref_release);
+               } else {
+                       spin_unlock_irqrestore
+                               (&np->accelerator->vif_states_lock, flags);
+               }
+       }
+       return rc;
+}
+
+
+int netfront_accelerator_call_resume(struct netfront_info *np,
+                                    struct xenbus_device *dev)
+{
+       struct netfront_accel_hooks *hooks;
+       unsigned flags;
+       int rc = 0;
+
+       /* 
+        *  Call the resume accelerator hook.  The use count for the
+        *  accelerator's hooks is incremented for the duration of
+        *  the call to prevent the accelerator being able to modify
+        *  the hooks in the middle (by, for example, unloading)
+        */
+       if (np->accel_vif_state.hooks) {
+               spin_lock_irqsave(&np->accelerator->vif_states_lock, flags); 
+               hooks = np->accel_vif_state.hooks;
+               if (hooks) {
+                       kref_get(&np->accel_vif_state.vif_kref);
+                       spin_unlock_irqrestore
+                               (&np->accelerator->vif_states_lock, flags);
+
+                       rc = np->accel_vif_state.hooks->resume(dev);
+
+                       kref_put(&np->accel_vif_state.vif_kref,
+                                vif_kref_release);
+               } else {
+                       spin_unlock_irqrestore
+                               (&np->accelerator->vif_states_lock, flags);
+               }
+       }
+       return rc;
+}
+
+
+void netfront_accelerator_call_backend_changed(struct netfront_info *np,
+                                              struct xenbus_device *dev,
+                                              enum xenbus_state backend_state)
+{
+       struct netfront_accel_hooks *hooks;
+       unsigned flags;
+
+       /* 
+        * Call the backend_changed accelerator hook. The use count
+        * for the accelerator's hooks is incremented for the duration
+        * of the call to prevent the accelerator being able to modify
+        * the hooks in the middle (by, for example, unloading)
+        */
+       if (np->accel_vif_state.hooks) {
+               spin_lock_irqsave(&np->accelerator->vif_states_lock, flags); 
+               hooks = np->accel_vif_state.hooks;
+               if (hooks) {
+                       kref_get(&np->accel_vif_state.vif_kref);
+                       spin_unlock_irqrestore
+                               (&np->accelerator->vif_states_lock, flags);
+
+                       np->accel_vif_state.hooks->backend_changed
+                               (dev, backend_state);
+
+                       kref_put(&np->accel_vif_state.vif_kref,
+                                vif_kref_release);
+               } else {
+                       spin_unlock_irqrestore
+                               (&np->accelerator->vif_states_lock, flags);
+               }
+       }
+}
+
+
+void netfront_accelerator_call_stop_napi_irq(struct netfront_info *np,
+                                            struct net_device *dev)
+{
+       struct netfront_accel_hooks *hooks;
+       unsigned flags;
+
+       /* 
+        * Call the stop_napi_interrupts accelerator hook.  The use
+        * count for the accelerator's hooks is incremented for the
+        * duration of the call to prevent the accelerator being able
+        * to modify the hooks in the middle (by, for example,
+        * unloading)
+        */
+
+       if (np->accel_vif_state.hooks) {
+               spin_lock_irqsave(&np->accelerator->vif_states_lock, flags); 
+               hooks = np->accel_vif_state.hooks;
+               if (hooks) {
+                       kref_get(&np->accel_vif_state.vif_kref);
+                       spin_unlock_irqrestore
+                               (&np->accelerator->vif_states_lock, flags);
+
+                       np->accel_vif_state.hooks->stop_napi_irq(dev);
+               
+                       kref_put(&np->accel_vif_state.vif_kref,
+                                vif_kref_release);
+               } else {
+                       spin_unlock_irqrestore
+                               (&np->accelerator->vif_states_lock, flags);
+               }
+       }
+}
+
+
+/* 
+ * Once all users of hooks have kref_put()'d we can signal that it's
+ * safe to unload
+ */ 
+static void accel_kref_release(struct kref *ref)
+{
+       struct netfront_accelerator *accelerator =
+               container_of(ref, struct netfront_accelerator, accel_kref);
+       struct netfront_accel_hooks *hooks;
+       unsigned flags;
+
+       DPRINTK("%p\n", accelerator);
+
+       /* Signal that all users of hooks are done */
+       up(&accelerator->exit_semaphore);
+
+       spin_lock_irqsave(&accelerator->vif_states_lock, flags);
+       if (accelerator->need_probe) {
+               hooks = accelerator->need_probe;
+               accelerator->need_probe = NULL;
+               accelerator_probe_vifs(accelerator, hooks, flags);
+       } 
+       else
+               accelerator->ready_for_probe = 1;
+
+       spin_unlock_irqrestore(&accelerator->vif_states_lock, flags);
+}
+
+
+static void vif_kref_release(struct kref *ref)
+{
+       struct netfront_accel_vif_state *vif_state = 
+               container_of(ref, struct netfront_accel_vif_state, vif_kref);
+       struct netfront_accel_hooks *hooks;
+       unsigned flags;
+
+       DPRINTK("%p\n", vif_state);
+
+       /* 
+        * Now that this vif has finished using the hooks, it can
+        * decrement the accelerator's global copy ref count 
+        */
+       kref_put(&vif_state->np->accelerator->accel_kref, accel_kref_release);
+
+       spin_lock_irqsave(&vif_state->np->accelerator->vif_states_lock, flags);
+       if (vif_state->need_probe) {
+               hooks = vif_state->need_probe;
+               vif_state->need_probe = NULL;
+               spin_unlock_irqrestore
+                       (&vif_state->np->accelerator->vif_states_lock, flags);
+               hooks->new_device(vif_state->np->netdev, vif_state->dev);
+       } else {
+               vif_state->ready_for_probe = 1;
+               spin_unlock_irqrestore
+                       (&vif_state->np->accelerator->vif_states_lock, flags);
+       }
+}
+
diff -r 56e84a427523 -r e57b5bec937f drivers/xen/netfront/netfront.c
--- a/drivers/xen/netfront/netfront.c   Mon Jul 09 09:24:03 2007 -0600
+++ b/drivers/xen/netfront/netfront.c   Tue Jul 10 08:40:03 2007 -0600
@@ -3,6 +3,7 @@
  *
  * Copyright (c) 2002-2005, K A Fraser
  * Copyright (c) 2005, XenSource Ltd
+ * Copyright (C) 2007 Solarflare Communications, Inc.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License version 2
@@ -62,6 +63,7 @@
 #include <asm/uaccess.h>
 #include <xen/interface/grant_table.h>
 #include <xen/gnttab.h>
+#include <xen/hypercall.h>
 
 #ifdef HAVE_XEN_PLATFORM_COMPAT_H
 #include <xen/platform-compat.h>
@@ -73,6 +75,8 @@ struct netfront_cb {
 };
 
 #define NETFRONT_SKB_CB(skb)   ((struct netfront_cb *)((skb)->cb))
+
+#include "netfront.h"
 
 /*
  * Mutually-exclusive module options to select receive data path:
@@ -144,57 +148,6 @@ static inline int netif_needs_gso(struct
 
 #define GRANT_INVALID_REF      0
 
-#define NET_TX_RING_SIZE __RING_SIZE((struct netif_tx_sring *)0, PAGE_SIZE)
-#define NET_RX_RING_SIZE __RING_SIZE((struct netif_rx_sring *)0, PAGE_SIZE)
-
-struct netfront_info {
-       struct list_head list;
-       struct net_device *netdev;
-
-       struct net_device_stats stats;
-
-       struct netif_tx_front_ring tx;
-       struct netif_rx_front_ring rx;
-
-       spinlock_t   tx_lock;
-       spinlock_t   rx_lock;
-
-       unsigned int irq;
-       unsigned int copying_receiver;
-       unsigned int carrier;
-
-       /* Receive-ring batched refills. */
-#define RX_MIN_TARGET 8
-#define RX_DFL_MIN_TARGET 64
-#define RX_MAX_TARGET min_t(int, NET_RX_RING_SIZE, 256)
-       unsigned rx_min_target, rx_max_target, rx_target;
-       struct sk_buff_head rx_batch;
-
-       struct timer_list rx_refill_timer;
-
-       /*
-        * {tx,rx}_skbs store outstanding skbuffs. The first entry in tx_skbs
-        * is an index into a chain of free entries.
-        */
-       struct sk_buff *tx_skbs[NET_TX_RING_SIZE+1];
-       struct sk_buff *rx_skbs[NET_RX_RING_SIZE];
-
-#define TX_MAX_TARGET min_t(int, NET_RX_RING_SIZE, 256)
-       grant_ref_t gref_tx_head;
-       grant_ref_t grant_tx_ref[NET_TX_RING_SIZE + 1];
-       grant_ref_t gref_rx_head;
-       grant_ref_t grant_rx_ref[NET_RX_RING_SIZE];
-
-       struct xenbus_device *xbdev;
-       int tx_ring_ref;
-       int rx_ring_ref;
-       u8 mac[ETH_ALEN];
-
-       unsigned long rx_pfn_array[NET_RX_RING_SIZE];
-       struct multicall_entry rx_mcl[NET_RX_RING_SIZE+1];
-       struct mmu_update rx_mmu[NET_RX_RING_SIZE];
-};
-
 struct netfront_rx_info {
        struct netif_rx_response rx;
        struct netif_extra_info extras[XEN_NETIF_EXTRA_TYPE_MAX - 1];
@@ -334,6 +287,8 @@ static int __devexit netfront_remove(str
 
        DPRINTK("%s\n", dev->nodename);
 
+       netfront_accelerator_call_remove(info, dev);
+
        netif_disconnect_backend(info);
 
        del_timer_sync(&info->rx_refill_timer);
@@ -346,6 +301,21 @@ static int __devexit netfront_remove(str
 
        return 0;
 }
+
+
+static int netfront_suspend(struct xenbus_device *dev)
+{
+       struct netfront_info *info = dev->dev.driver_data;
+       return netfront_accelerator_call_suspend(info, dev);
+}
+
+
+static int netfront_suspend_cancel(struct xenbus_device *dev)
+{
+       struct netfront_info *info = dev->dev.driver_data;
+       return netfront_accelerator_call_suspend_cancel(info, dev);
+}
+
 
 /**
  * We are reconnecting to the backend, due to a suspend/resume, or a backend
@@ -358,6 +328,8 @@ static int netfront_resume(struct xenbus
        struct netfront_info *info = dev->dev.driver_data;
 
        DPRINTK("%s\n", dev->nodename);
+
+       netfront_accelerator_call_resume(info, dev);
 
        netif_disconnect_backend(info);
        return 0;
@@ -577,6 +549,8 @@ static void backend_changed(struct xenbu
                xenbus_frontend_closed(dev);
                break;
        }
+
+       netfront_accelerator_call_backend_changed(np, dev, backend_state);
 }
 
 /** Send a packet on a net device to encourage switches to learn the
@@ -613,15 +587,29 @@ static inline int netfront_tx_slot_avail
                (TX_MAX_TARGET - MAX_SKB_FRAGS - 2));
 }
 
+
 static inline void network_maybe_wake_tx(struct net_device *dev)
 {
        struct netfront_info *np = netdev_priv(dev);
 
        if (unlikely(netif_queue_stopped(dev)) &&
            netfront_tx_slot_available(np) &&
-           likely(netif_running(dev)))
+           likely(netif_running(dev)) &&
+           netfront_check_accelerator_queue_busy(dev, np))
                netif_wake_queue(dev);
 }
+
+
+int netfront_check_queue_busy(struct net_device *dev)
+{
+       struct netfront_info *np = netdev_priv(dev);
+
+       return unlikely(netif_queue_stopped(dev)) &&
+               netfront_tx_slot_available(np) &&
+               likely(netif_running(dev));
+}
+EXPORT_SYMBOL(netfront_check_queue_busy);
+
 
 static int network_open(struct net_device *dev)
 {
@@ -633,8 +621,11 @@ static int network_open(struct net_devic
        if (netfront_carrier_ok(np)) {
                network_alloc_rx_buffers(dev);
                np->rx.sring->rsp_event = np->rx.rsp_cons + 1;
-               if (RING_HAS_UNCONSUMED_RESPONSES(&np->rx))
+               if (RING_HAS_UNCONSUMED_RESPONSES(&np->rx)){
+                       netfront_accelerator_call_stop_napi_irq(np, dev);
+
                        netif_rx_schedule(dev);
+               }
        }
        spin_unlock_bh(&np->rx_lock);
 
@@ -702,6 +693,10 @@ static void rx_refill_timeout(unsigned l
 static void rx_refill_timeout(unsigned long data)
 {
        struct net_device *dev = (struct net_device *)data;
+       struct netfront_info *np = netdev_priv(dev);
+
+       netfront_accelerator_call_stop_napi_irq(np, dev);
+
        netif_rx_schedule(dev);
 }
 
@@ -941,6 +936,13 @@ static int network_start_xmit(struct sk_
        unsigned int offset = offset_in_page(data);
        unsigned int len = skb_headlen(skb);
 
+       /* Check the fast path, if hooks are available */
+       if (np->accel_vif_state.hooks && 
+           np->accel_vif_state.hooks->start_xmit(skb, dev)) { 
+               /* Fast path has sent this packet */ 
+               return 0; 
+       } 
+
        frags += (offset + len + PAGE_SIZE - 1) / PAGE_SIZE;
        if (unlikely(frags > MAX_SKB_FRAGS + 1)) {
                printk(KERN_ALERT "xennet: skb rides the rocket: %d frags\n",
@@ -1044,8 +1046,11 @@ static irqreturn_t netif_int(int irq, vo
        if (likely(netfront_carrier_ok(np))) {
                network_tx_buf_gc(dev);
                /* Under tx_lock: protects access to rx shared-ring indexes. */
-               if (RING_HAS_UNCONSUMED_RESPONSES(&np->rx))
+               if (RING_HAS_UNCONSUMED_RESPONSES(&np->rx)) {
+                       netfront_accelerator_call_stop_napi_irq(np, dev);
+
                        netif_rx_schedule(dev);
+               }
        }
 
        spin_unlock_irqrestore(&np->tx_lock, flags);
@@ -1305,7 +1310,7 @@ static int netif_poll(struct net_device 
        struct netif_extra_info *extras = rinfo.extras;
        RING_IDX i, rp;
        struct multicall_entry *mcl;
-       int work_done, budget, more_to_do = 1;
+       int work_done, budget, more_to_do = 1, accel_more_to_do = 1;
        struct sk_buff_head rxq;
        struct sk_buff_head errq;
        struct sk_buff_head tmpq;
@@ -1472,6 +1477,20 @@ err:
 
        network_alloc_rx_buffers(dev);
 
+       if (work_done < budget) {
+               /* there's some spare capacity, try the accelerated path */
+               int accel_budget = budget - work_done;
+               int accel_budget_start = accel_budget;
+
+               if (np->accel_vif_state.hooks) { 
+                       accel_more_to_do =  
+                               np->accel_vif_state.hooks->netdev_poll 
+                               (dev, &accel_budget); 
+                       work_done += (accel_budget_start - accel_budget); 
+               } else
+                       accel_more_to_do = 0;
+       }
+
        *pbudget   -= work_done;
        dev->quota -= work_done;
 
@@ -1479,15 +1498,26 @@ err:
                local_irq_save(flags);
 
                RING_FINAL_CHECK_FOR_RESPONSES(&np->rx, more_to_do);
-               if (!more_to_do)
+
+               if (!more_to_do && !accel_more_to_do && 
+                   np->accel_vif_state.hooks) {
+                       /* 
+                        *  Slow path has nothing more to do, see if
+                        *  fast path is likewise
+                        */
+                       accel_more_to_do = 
+                               np->accel_vif_state.hooks->start_napi_irq(dev);
+               }
+
+               if (!more_to_do && !accel_more_to_do)
                        __netif_rx_complete(dev);
 
                local_irq_restore(flags);
        }
 
        spin_unlock(&np->rx_lock);
-
-       return more_to_do;
+       
+       return more_to_do | accel_more_to_do;
 }
 
 static void netif_release_tx_bufs(struct netfront_info *np)
@@ -1687,7 +1717,9 @@ static int network_connect(struct net_de
        struct sk_buff *skb;
        grant_ref_t ref;
        netif_rx_request_t *req;
-       unsigned int feature_rx_copy, feature_rx_flip;
+       unsigned int feature_rx_copy, feature_rx_flip, feature_accel;
+       char *accel_frontend;
+       int accel_len;
 
        err = xenbus_scanf(XBT_NIL, np->xbdev->otherend,
                           "feature-rx-copy", "%u", &feature_rx_copy);
@@ -1698,6 +1730,12 @@ static int network_connect(struct net_de
        if (err != 1)
                feature_rx_flip = 1;
 
+       feature_accel = 1;
+       accel_frontend = xenbus_read(XBT_NIL, np->xbdev->otherend, 
+                                    "accel", &accel_len);
+       if (IS_ERR(accel_frontend)) 
+               feature_accel = 0;
+
        /*
         * Copy packets on receive path if:
         *  (a) This was requested by user, and the backend supports it; or
@@ -1710,9 +1748,14 @@ static int network_connect(struct net_de
        if (err)
                return err;
 
+       if (feature_accel) {
+               netfront_load_accelerator(np, np->xbdev, accel_frontend);
+               kfree(accel_frontend);
+       }
+
        xennet_set_features(dev);
 
-       IPRINTK("device %s has %sing receive path.\n",
+       DPRINTK("device %s has %sing receive path.\n",
                dev->name, np->copying_receiver ? "copy" : "flipp");
 
        spin_lock_bh(&np->rx_lock);
@@ -1956,6 +1999,8 @@ static struct net_device * __devinit cre
        spin_lock_init(&np->tx_lock);
        spin_lock_init(&np->rx_lock);
 
+       init_accelerator_vif(np, dev);
+
        skb_queue_head_init(&np->rx_batch);
        np->rx_target     = RX_DFL_MIN_TARGET;
        np->rx_min_target = RX_DFL_MIN_TARGET;
@@ -2081,6 +2126,8 @@ static struct xenbus_driver netfront = {
        .ids = netfront_ids,
        .probe = netfront_probe,
        .remove = __devexit_p(netfront_remove),
+       .suspend = netfront_suspend,
+       .suspend_cancel = netfront_suspend_cancel,
        .resume = netfront_resume,
        .otherend_changed = backend_changed,
 };
@@ -2110,6 +2157,8 @@ static int __init netif_init(void)
        if (is_initial_xendomain())
                return 0;
 
+       netif_init_accel();
+
        IPRINTK("Initialising virtual ethernet driver.\n");
 
        (void)register_inetaddr_notifier(&notifier_inetdev);
diff -r 56e84a427523 -r e57b5bec937f drivers/xen/netfront/netfront.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/xen/netfront/netfront.h   Tue Jul 10 08:40:03 2007 -0600
@@ -0,0 +1,297 @@
+/******************************************************************************
+ * Virtual network driver for conversing with remote driver backends.
+ *
+ * Copyright (c) 2002-2005, K A Fraser
+ * Copyright (c) 2005, XenSource Ltd
+ * Copyright (C) 2007 Solarflare Communications, Inc.
+ *
+ * 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 NETFRONT_H
+#define NETFRONT_H
+
+#include <xen/interface/io/netif.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/list.h>
+#include <linux/kref.h>
+
+#define NET_TX_RING_SIZE __RING_SIZE((struct netif_tx_sring *)0, PAGE_SIZE)
+#define NET_RX_RING_SIZE __RING_SIZE((struct netif_rx_sring *)0, PAGE_SIZE)
+
+#include <xen/xenbus.h>
+
+/* 
+ * Function pointer table for hooks into a network acceleration
+ * plugin.  These are called at appropriate points from the netfront
+ * driver 
+ */
+struct netfront_accel_hooks {
+       /* 
+        * new_device: Accelerator hook to ask the plugin to support a
+        * new network interface
+        */
+       int (*new_device)(struct net_device *net_dev, struct xenbus_device 
*dev);
+       /*
+        * suspend, suspend_cancel, resume, remove: Equivalent to the
+        * normal xenbus_* callbacks
+        */
+       int (*suspend)(struct xenbus_device *dev);
+       int (*suspend_cancel)(struct xenbus_device *dev);
+       int (*resume)(struct xenbus_device *dev);
+       int (*remove)(struct xenbus_device *dev);
+       /* 
+        * backend_changed: Callback from watch based on backend's
+        * xenbus state changing
+        */
+       void (*backend_changed)(struct xenbus_device *dev,
+                               enum xenbus_state backend_state);
+       /*
+        * The net_device is being polled, check the accelerated
+        * hardware for any pending packets
+        */
+       int (*netdev_poll)(struct net_device *dev, int *pbudget);
+       /*
+        * start_xmit: Used to give the accelerated plugin the option
+        * of sending a packet.  Returns non-zero if has done so, or
+        * zero to decline and force the packet onto normal send
+        * path
+        */
+       int (*start_xmit)(struct sk_buff *skb, struct net_device *dev);
+       /* 
+        * start/stop_napi_interrupts Used by netfront to indicate
+        * when napi interrupts should be enabled or disabled 
+        */
+       int (*start_napi_irq)(struct net_device *dev);
+       void (*stop_napi_irq)(struct net_device *dev);
+       /* 
+        * Called before re-enabling the TX queue to check the fast
+        * path has slots too
+        */
+       int (*check_busy)(struct net_device *dev);
+};
+
+/* 
+ * Per-netfront device state for the accelerator.  This is used to
+ * allow efficient per-netfront device access to the accelerator
+ * hooks 
+ */
+struct netfront_accel_vif_state {
+       struct list_head link;
+
+       struct xenbus_device *dev;
+       struct netfront_info *np;
+       struct netfront_accel_hooks *hooks;
+
+       /* 
+        * Protect against removal of hooks while in use.  
+        */
+       struct kref vif_kref;
+
+       unsigned ready_for_probe;
+       struct netfront_accel_hooks *need_probe;
+}; 
+
+/* 
+ * Per-accelerator state stored in netfront.  These form a list that
+ * is used to track which devices are accelerated by which plugins,
+ * and what plugins are available/have been requested 
+ */
+struct netfront_accelerator {
+       /* Used to make a list */
+       struct list_head link;
+       /* ID of the accelerator */
+       int id;
+       /*
+        * String describing the accelerator.  Currently this is the
+        * name of the accelerator module.  This is provided by the
+        * backend accelerator through xenstore 
+        */
+       char *frontend;
+       /* The hooks into the accelerator plugin module */
+       struct netfront_accel_hooks *hooks;
+       /* 
+        * Protect against removal of hooks while in use.  
+        */
+       struct kref accel_kref;
+       /* 
+        * List of per-netfront device state (struct
+        * netfront_accel_vif_state) for each netfront device that is
+        * using this accelerator
+        */
+       struct list_head vif_states;
+       spinlock_t vif_states_lock;
+       /* 
+        * Semaphore to signal that all users of this accelerator have
+        * finished using it before module is unloaded
+        */
+       struct semaphore exit_semaphore; 
+
+       unsigned ready_for_probe;
+       struct netfront_accel_hooks *need_probe;
+};
+
+struct netfront_info {
+       struct list_head list;
+       struct net_device *netdev;
+
+       struct net_device_stats stats;
+
+       struct netif_tx_front_ring tx;
+       struct netif_rx_front_ring rx;
+
+       spinlock_t   tx_lock;
+       spinlock_t   rx_lock;
+
+       unsigned int irq;
+       unsigned int copying_receiver;
+       unsigned int carrier;
+
+       /* Receive-ring batched refills. */
+#define RX_MIN_TARGET 8
+#define RX_DFL_MIN_TARGET 64
+#define RX_MAX_TARGET min_t(int, NET_RX_RING_SIZE, 256)
+       unsigned rx_min_target, rx_max_target, rx_target;
+       struct sk_buff_head rx_batch;
+
+       struct timer_list rx_refill_timer;
+
+       /*
+        * {tx,rx}_skbs store outstanding skbuffs. The first entry in tx_skbs
+        * is an index into a chain of free entries.
+        */
+       struct sk_buff *tx_skbs[NET_TX_RING_SIZE+1];
+       struct sk_buff *rx_skbs[NET_RX_RING_SIZE];
+
+#define TX_MAX_TARGET min_t(int, NET_RX_RING_SIZE, 256)
+       grant_ref_t gref_tx_head;
+       grant_ref_t grant_tx_ref[NET_TX_RING_SIZE + 1];
+       grant_ref_t gref_rx_head;
+       grant_ref_t grant_rx_ref[NET_RX_RING_SIZE];
+
+       struct xenbus_device *xbdev;
+       int tx_ring_ref;
+       int rx_ring_ref;
+       u8 mac[ETH_ALEN];
+
+       unsigned long rx_pfn_array[NET_RX_RING_SIZE];
+       struct multicall_entry rx_mcl[NET_RX_RING_SIZE+1];
+       struct mmu_update rx_mmu[NET_RX_RING_SIZE];
+
+       /* Private pointer to state internal to accelerator module */
+       void *accel_priv;
+       /* The accelerator used by this netfront device */
+       struct netfront_accelerator *accelerator;
+       /* The accelerator state for this netfront device */
+       struct netfront_accel_vif_state accel_vif_state;
+};
+
+
+/* Exported Functions */
+
+/*
+ * Called by an accelerator plugin module when it has loaded.
+ *
+ * frontend: the string describing the accelerator, currently the module name 
+ * hooks: the hooks for netfront to use to call into the accelerator
+ */
+extern int netfront_accelerator_loaded(const char *frontend, 
+                                      struct netfront_accel_hooks *hooks);
+
+/* 
+ * Called when an accelerator plugin is ready to accelerate a device *
+ * that has been passed to it from netfront using the "new_device"
+ * hook.
+ *
+ * frontend: the string describing the accelerator. Must match the
+ * one passed to netfront_accelerator_loaded()
+ * dev: the xenbus device the plugin was asked to accelerate
+ */
+extern void netfront_accelerator_ready(const char *frontend,
+                                      struct xenbus_device *dev);
+
+/* 
+ * Called by an accelerator plugin module when it is about to unload.
+ *
+ * frontend: the string describing the accelerator.  Must match the
+ * one passed to netfront_accelerator_loaded()
+ *
+ * wait: 1 => wait for all users of module to complete before
+ * returning, thus making it safe to unload on return
+ */ 
+extern void netfront_accelerator_stop(const char *frontend, int wait);
+
+/* 
+ * Called by an accelerator before waking the net device's TX queue to
+ * ensure the slow path has available slots.  Returns true if OK to
+ * wake, false if still busy 
+ */
+extern int netfront_check_queue_busy(struct net_device *net_dev);
+
+
+
+/* Internal-to-netfront Functions */
+
+/* 
+ * Call into accelerator and check to see if it has tx space before we
+ * wake the net device's TX queue.  Returns true if OK to wake, false
+ * if still busy
+ */ 
+extern 
+int netfront_check_accelerator_queue_busy(struct net_device *dev,
+                                         struct netfront_info *np);
+extern
+int netfront_accelerator_call_remove(struct netfront_info *np,
+                                    struct xenbus_device *dev);
+extern
+int netfront_accelerator_call_suspend(struct netfront_info *np,
+                                     struct xenbus_device *dev);
+extern
+int netfront_accelerator_call_suspend_cancel(struct netfront_info *np,
+                                            struct xenbus_device *dev);
+extern
+int netfront_accelerator_call_resume(struct netfront_info *np,
+                                    struct xenbus_device *dev);
+extern
+void netfront_accelerator_call_backend_changed(struct netfront_info *np,
+                                              struct xenbus_device *dev,
+                                              enum xenbus_state backend_state);
+extern
+void netfront_accelerator_call_stop_napi_irq(struct netfront_info *np,
+                                            struct net_device *dev);
+
+extern
+int netfront_load_accelerator(struct netfront_info *np, 
+                             struct xenbus_device *dev, 
+                             const char *frontend);
+
+extern
+void netif_init_accel(void);
+
+extern
+void init_accelerator_vif(struct netfront_info *np,
+                         struct xenbus_device *dev);
+#endif /* NETFRONT_H */
diff -r 56e84a427523 -r e57b5bec937f drivers/xen/privcmd/Makefile
--- a/drivers/xen/privcmd/Makefile      Mon Jul 09 09:24:03 2007 -0600
+++ b/drivers/xen/privcmd/Makefile      Tue Jul 10 08:40:03 2007 -0600
@@ -1,2 +1,3 @@
 
-obj-$(CONFIG_XEN_PRIVCMD)      := privcmd.o
+obj-y  += privcmd.o
+obj-$(CONFIG_COMPAT)   += compat_privcmd.o
diff -r 56e84a427523 -r e57b5bec937f drivers/xen/privcmd/compat_privcmd.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/xen/privcmd/compat_privcmd.c      Tue Jul 10 08:40:03 2007 -0600
@@ -0,0 +1,73 @@
+/*
+ * 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
+ *
+ * Copyright (C) IBM Corp. 2006
+ *
+ * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
+ */
+
+#include <linux/config.h>
+#include <linux/compat.h>
+#include <linux/ioctl.h>
+#include <linux/syscalls.h>
+#include <asm/hypervisor.h>
+#include <asm/uaccess.h>
+#include <xen/public/privcmd.h>
+#include <xen/compat_ioctl.h>
+
+int privcmd_ioctl_32(int fd, unsigned int cmd, unsigned long arg)
+{
+       int ret;
+
+       switch (cmd) {
+       case IOCTL_PRIVCMD_MMAP_32: {
+               struct privcmd_mmap *p;
+               struct privcmd_mmap_32 *p32;
+               struct privcmd_mmap_32 n32;
+
+               p32 = compat_ptr(arg);
+               p = compat_alloc_user_space(sizeof(*p));
+               if (copy_from_user(&n32, p32, sizeof(n32)) ||
+                   put_user(n32.num, &p->num) ||
+                   put_user(n32.dom, &p->dom) ||
+                   put_user(compat_ptr(n32.entry), &p->entry))
+                       return -EFAULT;
+               
+               ret = sys_ioctl(fd, IOCTL_PRIVCMD_MMAP, (unsigned long)p);
+       }
+               break;
+       case IOCTL_PRIVCMD_MMAPBATCH_32: {
+               struct privcmd_mmapbatch *p;
+               struct privcmd_mmapbatch_32 *p32;
+               struct privcmd_mmapbatch_32 n32;
+
+               p32 = compat_ptr(arg);
+               p = compat_alloc_user_space(sizeof(*p));
+               if (copy_from_user(&n32, p32, sizeof(n32)) ||
+                   put_user(n32.num, &p->num) ||
+                   put_user(n32.dom, &p->dom) ||
+                   put_user(n32.addr, &p->addr) ||
+                   put_user(compat_ptr(n32.arr), &p->arr))
+                       return -EFAULT;
+               
+               ret = sys_ioctl(fd, IOCTL_PRIVCMD_MMAPBATCH, (unsigned long)p);
+       }
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+       return ret;
+}
diff -r 56e84a427523 -r e57b5bec937f drivers/xen/privcmd/privcmd.c
--- a/drivers/xen/privcmd/privcmd.c     Mon Jul 09 09:24:03 2007 -0600
+++ b/drivers/xen/privcmd/privcmd.c     Tue Jul 10 08:40:03 2007 -0600
@@ -29,6 +29,7 @@
 #include <xen/public/privcmd.h>
 #include <xen/interface/xen.h>
 #include <xen/xen_proc.h>
+#include <xen/features.h>
 
 static struct proc_dir_entry *privcmd_intf;
 static struct proc_dir_entry *capabilities_intf;
@@ -86,7 +87,7 @@ static int privcmd_ioctl(struct inode *i
                                "g" (hypercall.arg[4])
                                : "r8", "r10", "memory" );
                }
-#elif defined (__ia64__)
+#else
                ret = privcmd_hypercall(&hypercall);
 #endif
        }
@@ -111,7 +112,7 @@ static int privcmd_ioctl(struct inode *i
                if (copy_from_user(&msg, p, sizeof(msg)))
                        return -EFAULT;
 
-               down_read(&mm->mmap_sem);
+               down_write(&mm->mmap_sem);
 
                vma = find_vma(mm, msg.va);
                rc = -EINVAL;
@@ -153,7 +154,7 @@ static int privcmd_ioctl(struct inode *i
                rc = 0;
 
        mmap_out:
-               up_read(&mm->mmap_sem);
+               up_write(&mm->mmap_sem);
                ret = rc;
        }
        break;
@@ -176,14 +177,14 @@ static int privcmd_ioctl(struct inode *i
                if ((m.num <= 0) || (nr_pages > (LONG_MAX >> PAGE_SHIFT)))
                        return -EINVAL;
 
-               down_read(&mm->mmap_sem);
+               down_write(&mm->mmap_sem);
 
                vma = find_vma(mm, m.addr);
                if (!vma ||
                    (m.addr != vma->vm_start) ||
                    ((m.addr + (nr_pages << PAGE_SHIFT)) != vma->vm_end) ||
                    !privcmd_enforce_singleshot_mapping(vma)) {
-                       up_read(&mm->mmap_sem);
+                       up_write(&mm->mmap_sem);
                        return -EINVAL;
                }
 
@@ -191,7 +192,7 @@ static int privcmd_ioctl(struct inode *i
                addr = m.addr;
                for (i = 0; i < nr_pages; i++, addr += PAGE_SIZE, p++) {
                        if (get_user(mfn, p)) {
-                               up_read(&mm->mmap_sem);
+                               up_write(&mm->mmap_sem);
                                return -EFAULT;
                        }
 
@@ -202,7 +203,7 @@ static int privcmd_ioctl(struct inode *i
                                put_user(0xF0000000 | mfn, p);
                }
 
-               up_read(&mm->mmap_sem);
+               up_write(&mm->mmap_sem);
                ret = 0;
        }
        break;
diff -r 56e84a427523 -r e57b5bec937f drivers/xen/util.c
--- a/drivers/xen/util.c        Mon Jul 09 09:24:03 2007 -0600
+++ b/drivers/xen/util.c        Tue Jul 10 08:40:03 2007 -0600
@@ -22,9 +22,7 @@ struct class *get_xen_class(void)
 }
 EXPORT_SYMBOL_GPL(get_xen_class);
 
-/* Todo: merge ia64 ('auto-translate physmap') versions of these functions. */
-#ifndef __ia64__
-
+#ifdef CONFIG_X86
 static int f(pte_t *pte, struct page *pmd_page, unsigned long addr, void *data)
 {
        /* apply_to_page_range() does all the hard work. */
@@ -50,9 +48,7 @@ struct vm_struct *alloc_vm_area(unsigned
        }
 
        /* Map page directories into every address space. */
-#ifdef CONFIG_X86
        vmalloc_sync_all();
-#endif
 
        return area;
 }
@@ -66,5 +62,4 @@ void free_vm_area(struct vm_struct *area
        kfree(area);
 }
 EXPORT_SYMBOL_GPL(free_vm_area);
-
-#endif /* !__ia64__ */
+#endif /* CONFIG_X86 */
diff -r 56e84a427523 -r e57b5bec937f drivers/xen/xenbus/xenbus_probe.c
--- a/drivers/xen/xenbus/xenbus_probe.c Mon Jul 09 09:24:03 2007 -0600
+++ b/drivers/xen/xenbus/xenbus_probe.c Tue Jul 10 08:40:03 2007 -0600
@@ -4,6 +4,7 @@
  * Copyright (C) 2005 Rusty Russell, IBM Corporation
  * Copyright (C) 2005 Mike Wray, Hewlett-Packard
  * Copyright (C) 2005, 2006 XenSource Ltd
+ * Copyright (C) 2007 Solarflare Communications, Inc.
  * 
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License version 2
@@ -993,6 +994,7 @@ static int is_disconnected_device(struct
 {
        struct xenbus_device *xendev = to_xenbus_device(dev);
        struct device_driver *drv = data;
+       struct xenbus_driver *xendrv;
 
        /*
         * A device with no driver will never connect. We care only about
@@ -1005,7 +1007,9 @@ static int is_disconnected_device(struct
        if (drv && (dev->driver != drv))
                return 0;
 
-       return (xendev->state != XenbusStateConnected);
+       xendrv = to_xenbus_driver(dev->driver);
+       return (xendev->state != XenbusStateConnected ||
+               (xendrv->is_ready && !xendrv->is_ready(xendev)));
 }
 
 static int exists_disconnected_device(struct device_driver *drv)
@@ -1085,3 +1089,9 @@ static int __init boot_wait_for_devices(
 
 late_initcall(boot_wait_for_devices);
 #endif
+
+int xenbus_for_each_frontend(void *arg, int (*fn)(struct device *, void *))
+{
+       return bus_for_each_dev(&xenbus_frontend.bus, NULL, arg, fn);
+}
+EXPORT_SYMBOL_GPL(xenbus_for_each_frontend);
diff -r 56e84a427523 -r e57b5bec937f drivers/xen/xenbus/xenbus_probe_backend.c
--- a/drivers/xen/xenbus/xenbus_probe_backend.c Mon Jul 09 09:24:03 2007 -0600
+++ b/drivers/xen/xenbus/xenbus_probe_backend.c Tue Jul 10 08:40:03 2007 -0600
@@ -4,6 +4,7 @@
  * Copyright (C) 2005 Rusty Russell, IBM Corporation
  * Copyright (C) 2005 Mike Wray, Hewlett-Packard
  * Copyright (C) 2005, 2006 XenSource Ltd
+ * Copyright (C) 2007 Solarflare Communications, Inc.
  * 
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License version 2
@@ -285,3 +286,9 @@ void xenbus_backend_device_register(void
                       xenbus_backend.error);
        }
 }
+
+int xenbus_for_each_backend(void *arg, int (*fn)(struct device *, void *))
+{
+       return bus_for_each_dev(&xenbus_backend.bus, NULL, arg, fn);
+}
+EXPORT_SYMBOL_GPL(xenbus_for_each_backend);
diff -r 56e84a427523 -r e57b5bec937f fs/compat_ioctl.c
--- a/fs/compat_ioctl.c Mon Jul 09 09:24:03 2007 -0600
+++ b/fs/compat_ioctl.c Tue Jul 10 08:40:03 2007 -0600
@@ -123,6 +123,11 @@
 #include <linux/dvb/frontend.h>
 #include <linux/dvb/video.h>
 #include <linux/lp.h>
+
+#include <xen/interface/xen.h>
+#include <xen/public/evtchn.h>
+#include <xen/public/privcmd.h>
+#include <xen/compat_ioctl.h>
 
 /* Aiee. Someone does not find a difference between int and long */
 #define EXT2_IOC32_GETFLAGS               _IOR('f', 1, int)
@@ -2948,6 +2953,18 @@ COMPATIBLE_IOCTL(LPRESET)
 /*LPGETSTATS not implemented, but no kernels seem to compile it in anyways*/
 COMPATIBLE_IOCTL(LPGETFLAGS)
 HANDLE_IOCTL(LPSETTIMEOUT, lp_timeout_trans)
+
+#ifdef CONFIG_XEN
+HANDLE_IOCTL(IOCTL_PRIVCMD_MMAP_32, privcmd_ioctl_32)
+HANDLE_IOCTL(IOCTL_PRIVCMD_MMAPBATCH_32, privcmd_ioctl_32)
+COMPATIBLE_IOCTL(IOCTL_PRIVCMD_HYPERCALL)
+COMPATIBLE_IOCTL(IOCTL_EVTCHN_BIND_VIRQ)
+COMPATIBLE_IOCTL(IOCTL_EVTCHN_BIND_INTERDOMAIN)
+COMPATIBLE_IOCTL(IOCTL_EVTCHN_BIND_UNBOUND_PORT)
+COMPATIBLE_IOCTL(IOCTL_EVTCHN_UNBIND)
+COMPATIBLE_IOCTL(IOCTL_EVTCHN_NOTIFY)
+COMPATIBLE_IOCTL(IOCTL_EVTCHN_RESET)
+#endif
 };
 
 int ioctl_table_size = ARRAY_SIZE(ioctl_start);
diff -r 56e84a427523 -r e57b5bec937f include/asm-i386/mach-xen/asm/dma-mapping.h
--- a/include/asm-i386/mach-xen/asm/dma-mapping.h       Mon Jul 09 09:24:03 
2007 -0600
+++ b/include/asm-i386/mach-xen/asm/dma-mapping.h       Tue Jul 10 08:40:03 
2007 -0600
@@ -23,11 +23,11 @@ address_needs_mapping(struct device *hwd
 }
 
 static inline int
-range_straddles_page_boundary(void *p, size_t size)
+range_straddles_page_boundary(paddr_t p, size_t size)
 {
        extern unsigned long *contiguous_bitmap;
-       return (((((unsigned long)p & ~PAGE_MASK) + size) > PAGE_SIZE) &&
-               !test_bit(__pa(p) >> PAGE_SHIFT, contiguous_bitmap));
+       return ((((p & ~PAGE_MASK) + size) > PAGE_SIZE) &&
+               !test_bit(p >> PAGE_SHIFT, contiguous_bitmap));
 }
 
 #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
diff -r 56e84a427523 -r e57b5bec937f include/asm-i386/mach-xen/asm/io.h
--- a/include/asm-i386/mach-xen/asm/io.h        Mon Jul 09 09:24:03 2007 -0600
+++ b/include/asm-i386/mach-xen/asm/io.h        Tue Jul 10 08:40:03 2007 -0600
@@ -53,8 +53,8 @@
  * Convert a physical pointer to a virtual kernel pointer for /dev/mem
  * access
  */
-#define xlate_dev_mem_ptr(p, sz)       ioremap(p, sz)
-#define xlate_dev_mem_ptr_unmap(p)     iounmap(p)
+#define xen_xlate_dev_mem_ptr(p, sz)   ioremap(p, sz)
+#define xen_xlate_dev_mem_ptr_unmap(p) iounmap(p)
 
 /*
  * Convert a virtual cached pointer to an uncached pointer
diff -r 56e84a427523 -r e57b5bec937f include/asm-ia64/uaccess.h
--- a/include/asm-ia64/uaccess.h        Mon Jul 09 09:24:03 2007 -0600
+++ b/include/asm-ia64/uaccess.h        Tue Jul 10 08:40:03 2007 -0600
@@ -382,7 +382,7 @@ xlate_dev_mem_ptr (unsigned long p)
 }
 #else
 static __inline__ char *
-xlate_dev_mem_ptr (unsigned long p, ssize_t sz)
+xen_xlate_dev_mem_ptr (unsigned long p, ssize_t sz)
 {
        unsigned long pfn = p >> PAGE_SHIFT;
 
@@ -393,7 +393,7 @@ xlate_dev_mem_ptr (unsigned long p, ssiz
 }
 
 static __inline__ void
-xlate_dev_mem_ptr_unmap (char* v)
+xen_xlate_dev_mem_ptr_unmap (char* v)
 {
        if (REGION_NUMBER(v) == RGN_UNCACHED)
                iounmap(v);
diff -r 56e84a427523 -r e57b5bec937f include/asm-powerpc/io.h
--- a/include/asm-powerpc/io.h  Mon Jul 09 09:24:03 2007 -0600
+++ b/include/asm-powerpc/io.h  Tue Jul 10 08:40:03 2007 -0600
@@ -457,6 +457,9 @@ out:
  */
 #define xlate_dev_mem_ptr(p)   __va(p)
 
+#define xen_xlate_dev_mem_ptr(p,sz)    xlate_dev_mem_ptr(p)
+#define xen_xlate_dev_mem_ptr_unmap(p)
+
 /*
  * Convert a virtual cached pointer to an uncached pointer
  */
diff -r 56e84a427523 -r e57b5bec937f include/asm-powerpc/mpic.h
--- a/include/asm-powerpc/mpic.h        Mon Jul 09 09:24:03 2007 -0600
+++ b/include/asm-powerpc/mpic.h        Tue Jul 10 08:40:03 2007 -0600
@@ -305,6 +305,8 @@ struct mpic
 #define MPIC_SPV_EOI                   0x00000020
 /* No passthrough disable */
 #define MPIC_NO_PTHROU_DIS             0x00000040
+/* Skip reset of IPI vectors during init */
+#define MPIC_SKIP_IPI_INIT             0x00000080
 
 /* MPIC HW modification ID */
 #define MPIC_REGSET_MASK               0xf0000000
diff -r 56e84a427523 -r e57b5bec937f include/asm-powerpc/page.h
--- a/include/asm-powerpc/page.h        Mon Jul 09 09:24:03 2007 -0600
+++ b/include/asm-powerpc/page.h        Tue Jul 10 08:40:03 2007 -0600
@@ -194,6 +194,15 @@ struct vm_area_struct;
 struct vm_area_struct;
 extern const char *arch_vma_name(struct vm_area_struct *vma);
 
+#define arch_free_page(_page, _order)       \
+({                      \
+       int foreign = PageForeign(_page);   \
+       if (foreign) \
+               PageForeignDestructor(_page);   \
+       foreign; \
+})
+#define HAVE_ARCH_FREE_PAGE
+
 #include <asm-generic/memory_model.h>
 #endif /* __ASSEMBLY__ */
 
diff -r 56e84a427523 -r e57b5bec937f include/asm-powerpc/udbg.h
--- a/include/asm-powerpc/udbg.h        Mon Jul 09 09:24:03 2007 -0600
+++ b/include/asm-powerpc/udbg.h        Tue Jul 10 08:40:03 2007 -0600
@@ -42,6 +42,7 @@ extern void __init udbg_init_pmac_realmo
 extern void __init udbg_init_pmac_realmode(void);
 extern void __init udbg_init_maple_realmode(void);
 extern void __init udbg_init_iseries(void);
+extern void __init udbg_init_xen(void);
 extern void __init udbg_init_rtas_panel(void);
 extern void __init udbg_init_rtas_console(void);
 
diff -r 56e84a427523 -r e57b5bec937f include/asm-powerpc/xen/asm/gnttab_dma.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/include/asm-powerpc/xen/asm/gnttab_dma.h  Tue Jul 10 08:40:03 2007 -0600
@@ -0,0 +1,29 @@
+/*
+ * 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
+ *
+ * Copyright 2007 IBM Corp.
+ *
+ * Authors: Hollis Blanchard <hollisb@xxxxxxxxxx>
+ */
+
+#ifndef _ASM_PPC_GNTTAB_DMA_H
+#define _ASM_PPC_GNTTAB_DMA_H
+
+static inline int gnttab_dma_local_pfn(struct page *page)
+{
+       return 0;
+}
+
+#endif /* _ASM_PPC_GNTTAB_DMA_H */
diff -r 56e84a427523 -r e57b5bec937f include/asm-powerpc/xen/asm/hypercall.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/include/asm-powerpc/xen/asm/hypercall.h   Tue Jul 10 08:40:03 2007 -0600
@@ -0,0 +1,90 @@
+/******************************************************************************
+ * hypercall.h
+ * 
+ * Linux-specific hypervisor handling.
+ * 
+ * Copyright (c) 2002-2004, K A Fraser
+ * 
+ * This file may be distributed separately from the Linux kernel, or
+ * incorporated into other software packages, subject to the following license:
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Copyright 2007 IBM Corp.
+ *
+ * Authors: Hollis Blanchard <hollisb@xxxxxxxxxx>
+ *          Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
+ */
+
+#ifndef __HYPERCALL_H__
+#define __HYPERCALL_H__
+
+#include <asm/hvcall.h>
+#include <asm/page.h>
+#include <xen/xencomm.h>
+#include <xen/interface/xen.h>
+#include <xen/interface/sched.h>
+
+#define XEN_MARK(a)((a) | (~0UL << 16))
+
+extern int HYPERVISOR_console_io(int cmd, int count, char *str);
+extern int HYPERVISOR_event_channel_op(int cmd, void *op);
+extern int HYPERVISOR_xen_version(int cmd, void *arg);
+extern int HYPERVISOR_physdev_op(int cmd, void *op);
+extern int HYPERVISOR_grant_table_op(unsigned int cmd, void *uop,
+               unsigned int count);
+extern int HYPERVISOR_vcpu_op(int cmd, int vcpuid, void *extra_args);
+extern int HYPERVISOR_memory_op(unsigned int cmd, void *arg);
+extern int HYPERVISOR_multicall(void *call_list, int nr_calls);
+
+extern int HYPERVISOR_sched_op(int cmd, void *arg);
+extern int HYPERVISOR_poll(
+       evtchn_port_t *ports, unsigned int nr_ports, u64 timeout);
+
+static inline int HYPERVISOR_shutdown(unsigned int reason)
+{
+       struct sched_shutdown sched_shutdown = {
+               .reason = reason
+       };
+
+       return HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown);
+}
+
+static inline int HYPERVISOR_set_timer_op(unsigned long arg)
+{
+       return plpar_hcall_norets(XEN_MARK(__HYPERVISOR_set_timer_op), arg);
+}
+
+extern int HYPERVISOR_suspend(unsigned long srec);
+extern int HYPERVISOR_kexec_op(unsigned long op, void *args);
+static inline unsigned long HYPERVISOR_hvm_op(int op, void *arg) {
+       return -ENOSYS;
+}
+
+static inline int
+HYPERVISOR_mmu_update(
+       mmu_update_t *req, int count, int *success_count, domid_t domid)
+{
+       return -ENOSYS;
+}
+
+struct privcmd_hypercall;
+extern int privcmd_hypercall(struct privcmd_hypercall *hypercall);
+
+#endif /*  __HYPERCALL_H__ */
diff -r 56e84a427523 -r e57b5bec937f include/asm-powerpc/xen/asm/hypervisor.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/include/asm-powerpc/xen/asm/hypervisor.h  Tue Jul 10 08:40:03 2007 -0600
@@ -0,0 +1,276 @@
+/******************************************************************************
+ * hypervisor.h
+ * 
+ * Linux-specific hypervisor handling.
+ * 
+ * Copyright (c) 2002-2004, K A Fraser
+ * 
+ * This file may be distributed separately from the Linux kernel, or
+ * incorporated into other software packages, subject to the following license:
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef __HYPERVISOR_H__
+#define __HYPERVISOR_H__
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <xen/interface/xen.h>
+#include <asm/ptrace.h>
+#include <asm/page.h>
+#include <asm/irq.h>
+
+extern shared_info_t *HYPERVISOR_shared_info;
+
+/* arch/xen/i386/kernel/setup.c */
+extern start_info_t *xen_start_info;
+
+#ifdef CONFIG_XEN_PRIVILEGED_GUEST
+#define is_initial_xendomain() (xen_start_info && \
+                               (xen_start_info->flags & SIF_INITDOMAIN))
+#else
+#define is_initial_xendomain() 0
+#endif
+
+/* arch/xen/kernel/evtchn.c */
+/* Force a proper event-channel callback from Xen. */
+void force_evtchn_callback(void);
+
+/* arch/xen/kernel/process.c */
+void xen_cpu_idle (void);
+
+/* arch/xen/i386/kernel/hypervisor.c */
+void do_hypervisor_callback(struct pt_regs *regs);
+
+/* arch/xen/i386/kernel/head.S */
+void lgdt_finish(void);
+
+/* arch/xen/i386/mm/hypervisor.c */
+/*
+ * NB. ptr values should be PHYSICAL, not MACHINE. 'vals' should be already
+ * be MACHINE addresses.
+ */
+
+void xen_pt_switch(unsigned long ptr);
+void xen_new_user_pt(unsigned long ptr); /* x86_64 only */
+void xen_load_gs(unsigned int selector); /* x86_64 only */
+void xen_tlb_flush(void);
+void xen_invlpg(unsigned long ptr);
+
+#ifndef CONFIG_XEN_SHADOW_MODE
+void xen_l1_entry_update(pte_t *ptr, pte_t val);
+void xen_l2_entry_update(pmd_t *ptr, pmd_t val);
+void xen_l3_entry_update(pud_t *ptr, pud_t val); /* x86_64/PAE */
+void xen_l4_entry_update(pgd_t *ptr, pgd_t val); /* x86_64 only */
+void xen_pgd_pin(unsigned long ptr);
+void xen_pgd_unpin(unsigned long ptr);
+void xen_pud_pin(unsigned long ptr); /* x86_64 only */
+void xen_pud_unpin(unsigned long ptr); /* x86_64 only */
+void xen_pmd_pin(unsigned long ptr); /* x86_64 only */
+void xen_pmd_unpin(unsigned long ptr); /* x86_64 only */
+void xen_pte_pin(unsigned long ptr);
+void xen_pte_unpin(unsigned long ptr);
+#else
+#define xen_l1_entry_update(_p, _v) set_pte((_p), (_v))
+#define xen_l2_entry_update(_p, _v) set_pgd((_p), (_v))
+#define xen_pgd_pin(_p)   ((void)0)
+#define xen_pgd_unpin(_p) ((void)0)
+#define xen_pte_pin(_p)   ((void)0)
+#define xen_pte_unpin(_p) ((void)0)
+#endif
+
+void xen_set_ldt(unsigned long ptr, unsigned long bytes);
+void xen_machphys_update(unsigned long mfn, unsigned long pfn);
+
+#ifdef CONFIG_SMP
+#include <linux/cpumask.h>
+void xen_tlb_flush_all(void);
+void xen_invlpg_all(unsigned long ptr);
+void xen_tlb_flush_mask(cpumask_t *mask);
+void xen_invlpg_mask(cpumask_t *mask, unsigned long ptr);
+#endif
+
+/* Returns zero on success else negative errno. */
+static inline int xen_create_contiguous_region(
+    unsigned long vstart, unsigned int order, unsigned int address_bits)
+{
+       return 0;
+}
+static inline void xen_destroy_contiguous_region(
+    unsigned long vstart, unsigned int order)
+{
+       return;
+}
+
+#include <asm/hypercall.h>
+
+/* BEGIN: all of these need a new home */
+struct vm_area_struct;
+int direct_remap_pfn_range(struct vm_area_struct *vma,  unsigned long address,
+                          unsigned long mfn, unsigned long size,
+                          pgprot_t prot, domid_t  domid);
+#define        pfn_to_mfn(x)   (x)
+#define        mfn_to_pfn(x)   (x)
+#define phys_to_machine(phys) ((maddr_t)(phys))
+#define phys_to_machine_mapping_valid(pfn) (1)
+
+/* VIRT <-> MACHINE conversion */
+#define virt_to_machine(v)     (phys_to_machine(__pa(v)))
+#define machine_to_virt(m)     (__va(m))
+#define virt_to_mfn(v)         (pfn_to_mfn(__pa(v) >> PAGE_SHIFT))
+#define mfn_to_virt(m)         (__va(mfn_to_pfn(m) << PAGE_SHIFT))
+
+
+#define PIRQ_BASE              0
+#define NR_PIRQS               256
+
+#define DYNIRQ_BASE            (PIRQ_BASE + NR_PIRQS)
+#define NR_DYNIRQS             256
+
+#define NR_IPIS 4              /* PPC_MSG_DEBUGGER_BREAK + 1 */
+
+#if NR_IRQS < (NR_PIRQS + NR_DYNIRQS)
+#error to many Xen IRQs
+#endif
+
+#define NR_IRQ_VECTORS         NR_IRQS
+
+#define pirq_to_irq(_x)                ((_x) + PIRQ_BASE)
+#define irq_to_pirq(_x)                ((_x) - PIRQ_BASE)
+
+#define dynirq_to_irq(_x)      ((_x) + DYNIRQ_BASE)
+#define irq_to_dynirq(_x)      ((_x) - DYNIRQ_BASE)
+
+
+/* END:  all of these need a new home */
+
+#if defined(CONFIG_X86_64)
+#define MULTI_UVMFLAGS_INDEX 2
+#define MULTI_UVMDOMID_INDEX 3
+#else
+#define MULTI_UVMFLAGS_INDEX 3
+#define MULTI_UVMDOMID_INDEX 4
+#endif
+
+extern int is_running_on_xen(void);
+
+static inline void
+MULTI_update_va_mapping(
+    multicall_entry_t *mcl, unsigned long va,
+    pte_t new_val, unsigned long flags)
+{
+    mcl->op = __HYPERVISOR_update_va_mapping;
+    mcl->args[0] = va;
+#if defined(CONFIG_X86_64)
+    mcl->args[1] = new_val.pte;
+    mcl->args[2] = flags;
+#elif defined(CONFIG_X86_PAE)
+    mcl->args[1] = new_val.pte_low;
+    mcl->args[2] = new_val.pte_high;
+    mcl->args[3] = flags;
+#elif defined(CONFIG_PPC64)
+    mcl->args[1] = pte_val(new_val);
+    mcl->args[2] = 0;
+    mcl->args[3] = flags;
+#else
+    mcl->args[1] = new_val.pte_low;
+    mcl->args[2] = 0;
+    mcl->args[3] = flags;
+#endif
+}
+
+static inline void
+MULTI_update_va_mapping_otherdomain(
+    multicall_entry_t *mcl, unsigned long va,
+    pte_t new_val, unsigned long flags, domid_t domid)
+{
+    mcl->op = __HYPERVISOR_update_va_mapping_otherdomain;
+    mcl->args[0] = va;
+#if defined(CONFIG_X86_64)
+    mcl->args[1] = new_val.pte;
+    mcl->args[2] = flags;
+    mcl->args[3] = domid;
+#elif defined(CONFIG_X86_PAE)
+    mcl->args[1] = new_val.pte_low;
+    mcl->args[2] = new_val.pte_high;
+    mcl->args[3] = flags;
+    mcl->args[4] = domid;
+#elif defined(CONFIG_PPC64)
+    mcl->args[1] = pte_val(new_val);
+    mcl->args[2] = 0;
+    mcl->args[3] = flags;
+    mcl->args[4] = domid;
+#else
+    mcl->args[1] = new_val.pte_low;
+    mcl->args[2] = 0;
+    mcl->args[3] = flags;
+    mcl->args[4] = domid;
+#endif
+}
+
+#define INVALID_P2M_ENTRY (~0UL)
+#define FOREIGN_FRAME(m) (INVALID_P2M_ENTRY)
+static inline void set_phys_to_machine(unsigned long pfn, unsigned long mfn)
+{
+       if (pfn != mfn && mfn != INVALID_P2M_ENTRY)
+               printk(KERN_EMERG "%s: pfn: 0x%lx mfn: 0x%lx\n",
+                      __func__, pfn, mfn);
+       
+       return;
+}
+#define pfn_pte_ma(pfn, prot)  __pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
+
+typedef unsigned long maddr_t;
+typedef unsigned long paddr_t;
+
+#ifdef CONFIG_XEN_SCRUB_PAGES
+
+static inline void scrub_pages(void *p, unsigned n)
+{
+       unsigned i;
+
+       for (i = 0; i < n; i++) {
+               clear_page(p);
+               p += PAGE_SIZE;
+       }
+}
+#else
+#define scrub_pages(_p,_n) ((void)0)
+#endif
+
+/*
+ * for blktap.c
+ * int create_lookup_pte_addr(struct mm_struct *mm, 
+ *                            unsigned long address,
+ *                            uint64_t *ptep);
+ */
+#define create_lookup_pte_addr(mm, address, ptep)                      \
+       ({                                                              \
+               printk(KERN_EMERG                                       \
+                      "%s:%d "                                         \
+                      "create_lookup_pte_addr() isn't supported.\n",   \
+                      __func__, __LINE__);                             \
+               BUG();                                                  \
+               (-ENOSYS);                                              \
+       })
+
+#endif /* __HYPERVISOR_H__ */
diff -r 56e84a427523 -r e57b5bec937f include/asm-powerpc/xen/asm/maddr.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/include/asm-powerpc/xen/asm/maddr.h       Tue Jul 10 08:40:03 2007 -0600
@@ -0,0 +1,7 @@
+#ifndef _POWERPC_MADDR_H
+#define _POWERPC_MADDR_H
+
+#include <xen/features.h>
+#include <xen/interface/xen.h>
+
+#endif
diff -r 56e84a427523 -r e57b5bec937f include/asm-powerpc/xen/asm/synch_bitops.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/include/asm-powerpc/xen/asm/synch_bitops.h        Tue Jul 10 08:40:03 
2007 -0600
@@ -0,0 +1,100 @@
+/*
+ * 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
+ *
+ * Copyright 2006 IBM Corp.
+ *
+ * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
+ */
+
+#ifndef  __SYNCH_BITOPS_H__
+#define __SYNCH_BITOPS_H__
+
+#include <linux/config.h>
+#include <xen/interface/xen.h>
+
+#ifdef CONFIG_SMP
+#include <asm/bitops.h>
+
+#define synch_change_bit(a,b) change_bit(a,b)
+#define synch_clear_bit(a,b) clear_bit(a,b)
+#define synch_const_test_bit(a,b) const_test_bit(a,b) 
+#define synch_set_bit(a,b) set_bit(a,b)
+#define synch_test_and_set_bit(a,b) test_and_set_bit(a,b)
+#define synch_test_and_change_bit(a,b) test_and_change_bit(a,b)
+#define synch_test_and_clear_bit(a,b) test_and_clear_bit(a,b)
+#define synch_test_bit(a,b) test_bit(a,b)
+
+static __inline__ unsigned long
+__synch_cmpxchg_u16(volatile unsigned short *p, unsigned long old, unsigned 
long new)
+{
+       int idx;
+       volatile unsigned int *xp = (unsigned int *)((ulong)p & ~(0x3UL));
+       union {
+               unsigned int word;
+               struct {
+                       unsigned short s[2];
+               }s;
+       } xold, xnew;
+
+       /* we could start the reservation here and copy the u32
+        * assembler, but I don't think it will gain us a whole
+        * lot. */
+       xold.word = *xp;
+       xnew.word = xold.word;
+       idx = ((ulong)p >> 1) & 0x1;
+       xold.s.s[idx] = old;
+       xnew.s.s[idx] = new;
+
+       return __cmpxchg_u32(xp, xold.word, xnew.word);
+}
+
+/*
+ * This function doesn't exist, so you'll get a linker error
+ * if something tries to do an invalid xchg().
+ */
+extern void __synch_cmpxchg_called_with_bad_pointer(void);
+static __inline__ unsigned long
+__synch_cmpxchg(volatile void *ptr, unsigned long old, unsigned long new,
+              unsigned int size)
+{
+       switch (size) {
+       case 2:
+               return __synch_cmpxchg_u16(ptr, old, new);
+       case 4:
+               return __cmpxchg_u32(ptr, old, new);
+#ifdef CONFIG_PPC64
+       case 8:
+               return __cmpxchg_u64(ptr, old, new);
+#endif
+       }
+       __synch_cmpxchg_called_with_bad_pointer();
+       return old;
+}
+
+#define synch_cmpxchg(ptr,o,n)                                          \
+  ({                                                                    \
+     __typeof__(*(ptr)) _o_ = (o);                                      \
+     __typeof__(*(ptr)) _n_ = (n);                                      \
+     (__typeof__(*(ptr))) __synch_cmpxchg((ptr), (unsigned long)_o_,           
 \
+                                   (unsigned long)_n_, sizeof(*(ptr))); \
+  })
+
+#define synch_cmpxchg_subword(ptr,o,n) __synch_cmpxchg_u16((ptr), (o), (n))
+
+#else
+#error "this only works for CONFIG_SMP"
+#endif
+
+#endif /* __SYNCH_BITOPS_H__ */
diff -r 56e84a427523 -r e57b5bec937f include/asm-x86_64/mach-xen/asm/io.h
--- a/include/asm-x86_64/mach-xen/asm/io.h      Mon Jul 09 09:24:03 2007 -0600
+++ b/include/asm-x86_64/mach-xen/asm/io.h      Tue Jul 10 08:40:03 2007 -0600
@@ -315,8 +315,8 @@ extern int iommu_bio_merge;
  * Convert a physical pointer to a virtual kernel pointer for /dev/mem
  * access
  */
-#define xlate_dev_mem_ptr(p, sz)       ioremap(p, sz)
-#define xlate_dev_mem_ptr_unmap(p)     iounmap(p)
+#define xen_xlate_dev_mem_ptr(p, sz)   ioremap(p, sz)
+#define xen_xlate_dev_mem_ptr_unmap(p) iounmap(p)
 
 /*
  * Convert a virtual cached pointer to an uncached pointer
diff -r 56e84a427523 -r e57b5bec937f include/xen/compat_ioctl.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/include/xen/compat_ioctl.h        Tue Jul 10 08:40:03 2007 -0600
@@ -0,0 +1,45 @@
+/*
+ * 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Copyright IBM Corp. 2007
+ *
+ * Authors: Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
+ *          Hollis Blanchard <hollisb@xxxxxxxxxx>
+ */
+
+#ifndef __LINUX_XEN_COMPAT_H__ 
+#define __LINUX_XEN_COMPAT_H__ 
+
+#include <linux/compat.h>
+
+extern int privcmd_ioctl_32(int fd, unsigned int cmd, unsigned long arg);
+struct privcmd_mmap_32 {
+       int num;
+       domid_t dom;
+       compat_uptr_t entry;
+};
+
+struct privcmd_mmapbatch_32 {
+       int num;     /* number of pages to populate */
+       domid_t dom; /* target domain */
+       __u64 addr;  /* virtual address */
+       compat_uptr_t arr; /* array of mfns - top nibble set on err */
+};
+#define IOCTL_PRIVCMD_MMAP_32                   \
+       _IOC(_IOC_NONE, 'P', 2, sizeof(struct privcmd_mmap_32))
+#define IOCTL_PRIVCMD_MMAPBATCH_32                  \
+       _IOC(_IOC_NONE, 'P', 3, sizeof(struct privcmd_mmapbatch_32))
+
+#endif /* __LINUX_XEN_COMPAT_H__ */
diff -r 56e84a427523 -r e57b5bec937f include/xen/gnttab.h
--- a/include/xen/gnttab.h      Mon Jul 09 09:24:03 2007 -0600
+++ b/include/xen/gnttab.h      Tue Jul 10 08:40:03 2007 -0600
@@ -117,6 +117,8 @@ int gnttab_suspend(void);
 int gnttab_suspend(void);
 int gnttab_resume(void);
 
+void *arch_gnttab_alloc_shared(unsigned long *frames);
+
 static inline void
 gnttab_set_map_op(struct gnttab_map_grant_ref *map, maddr_t addr,
                  uint32_t flags, grant_ref_t ref, domid_t domid)
diff -r 56e84a427523 -r e57b5bec937f include/xen/interface/sysctl.h
--- a/include/xen/interface/sysctl.h    Mon Jul 09 09:24:03 2007 -0600
+++ b/include/xen/interface/sysctl.h    Tue Jul 10 08:40:03 2007 -0600
@@ -34,7 +34,7 @@
 #include "xen.h"
 #include "domctl.h"
 
-#define XEN_SYSCTL_INTERFACE_VERSION 0x00000003
+#define XEN_SYSCTL_INTERFACE_VERSION 0x00000004
 
 /*
  * Read console content from Xen buffer ring.
@@ -76,6 +76,7 @@ DEFINE_XEN_GUEST_HANDLE(xen_sysctl_tbuf_
  */
 #define XEN_SYSCTL_physinfo          3
 struct xen_sysctl_physinfo {
+    /* IN variables. */
     uint32_t threads_per_core;
     uint32_t cores_per_socket;
     uint32_t sockets_per_node;
@@ -85,6 +86,23 @@ struct xen_sysctl_physinfo {
     uint64_aligned_t free_pages;
     uint64_aligned_t scrub_pages;
     uint32_t hw_cap[8];
+
+    /* IN/OUT variables. */
+    /*
+     * IN: maximum addressable entry in the caller-provided cpu_to_node array.
+     * OUT: largest cpu identifier in the system.
+     * If OUT is greater than IN then the cpu_to_node array is truncated!
+     */
+    uint32_t max_cpu_id;
+    /*
+     * If not NULL, this array is filled with node identifier for each cpu.
+     * If a cpu has no node information (e.g., cpu not present) then the
+     * sentinel value ~0u is written.
+     * The size of this array is specified by the caller in @max_cpu_id.
+     * If the actual @max_cpu_id is smaller than the array then the trailing
+     * elements of the array will not be written by the sysctl.
+     */
+    XEN_GUEST_HANDLE_64(uint32_t) cpu_to_node;
 };
 typedef struct xen_sysctl_physinfo xen_sysctl_physinfo_t;
 DEFINE_XEN_GUEST_HANDLE(xen_sysctl_physinfo_t);
@@ -140,9 +158,7 @@ typedef struct xen_sysctl_getdomaininfol
 typedef struct xen_sysctl_getdomaininfolist xen_sysctl_getdomaininfolist_t;
 DEFINE_XEN_GUEST_HANDLE(xen_sysctl_getdomaininfolist_t);
 
-/*
- * Inject debug keys into Xen.
- */
+/* Inject debug keys into Xen. */
 #define XEN_SYSCTL_debug_keys        7
 struct xen_sysctl_debug_keys {
     /* IN variables. */
@@ -151,6 +167,23 @@ struct xen_sysctl_debug_keys {
 };
 typedef struct xen_sysctl_debug_keys xen_sysctl_debug_keys_t;
 DEFINE_XEN_GUEST_HANDLE(xen_sysctl_debug_keys_t);
+
+/* Get physical CPU information. */
+#define XEN_SYSCTL_getcpuinfo        8
+struct xen_sysctl_cpuinfo {
+    uint64_t idletime;
+};
+typedef struct xen_sysctl_cpuinfo xen_sysctl_cpuinfo_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_cpuinfo_t); 
+struct xen_sysctl_getcpuinfo {
+    /* IN variables. */
+    uint32_t max_cpus;
+    XEN_GUEST_HANDLE_64(xen_sysctl_cpuinfo_t) info;
+    /* OUT variables. */
+    uint32_t nr_cpus;
+}; 
+typedef struct xen_sysctl_getcpuinfo xen_sysctl_getcpuinfo_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_getcpuinfo_t); 
 
 struct xen_sysctl {
     uint32_t cmd;
@@ -163,6 +196,7 @@ struct xen_sysctl {
         struct xen_sysctl_perfc_op          perfc_op;
         struct xen_sysctl_getdomaininfolist getdomaininfolist;
         struct xen_sysctl_debug_keys        debug_keys;
+        struct xen_sysctl_getcpuinfo        getcpuinfo;
         uint8_t                             pad[128];
     } u;
 };
diff -r 56e84a427523 -r e57b5bec937f include/xen/xenbus.h
--- a/include/xen/xenbus.h      Mon Jul 09 09:24:03 2007 -0600
+++ b/include/xen/xenbus.h      Tue Jul 10 08:40:03 2007 -0600
@@ -106,6 +106,7 @@ struct xenbus_driver {
        int (*uevent)(struct xenbus_device *, char **, int, char *, int);
        struct device_driver driver;
        int (*read_otherend_details)(struct xenbus_device *dev);
+       int (*is_ready)(struct xenbus_device *dev);
 };
 
 static inline struct xenbus_driver *to_xenbus_driver(struct device_driver *drv)
@@ -299,4 +300,7 @@ int xenbus_dev_is_online(struct xenbus_d
 int xenbus_dev_is_online(struct xenbus_device *dev);
 int xenbus_frontend_closed(struct xenbus_device *dev);
 
+int xenbus_for_each_backend(void *arg, int (*fn)(struct device *, void *));
+int xenbus_for_each_frontend(void *arg, int (*fn)(struct device *, void *));
+
 #endif /* _XEN_XENBUS_H */
diff -r 56e84a427523 -r e57b5bec937f include/xen/xencomm.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/include/xen/xencomm.h     Tue Jul 10 08:40:03 2007 -0600
@@ -0,0 +1,51 @@
+/*
+ * 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
+ *
+ * Copyright (C) IBM Corp. 2006
+ *
+ * Authors: Hollis Blanchard <hollisb@xxxxxxxxxx>
+ *          Jerone Young <jyoung5@xxxxxxxxxx>
+ */
+
+#ifndef _LINUX_XENCOMM_H_
+#define _LINUX_XENCOMM_H_
+
+#include <xen/interface/xencomm.h>
+
+#define XENCOMM_MINI_ADDRS 3
+struct xencomm_mini {
+       struct xencomm_desc _desc;
+       uint64_t address[XENCOMM_MINI_ADDRS];
+};
+
+extern void xencomm_free(void *desc);
+extern void *xencomm_map(void *ptr, unsigned long bytes);
+extern void *__xencomm_map_no_alloc(void *ptr, unsigned long bytes, 
+                               struct xencomm_mini *xc_area);
+
+#define xencomm_map_no_alloc(ptr, bytes) \
+       ({struct xencomm_mini xc_desc\
+               __attribute__((__aligned__(sizeof(struct xencomm_mini))));\
+               __xencomm_map_no_alloc(ptr, bytes, &xc_desc);})
+
+/* provided by architecture code: */
+extern unsigned long xencomm_vtop(unsigned long vaddr);
+
+static inline void *xencomm_pa(void *ptr)
+{
+       return (void *)xencomm_vtop((unsigned long)ptr);
+}
+
+#endif /* _LINUX_XENCOMM_H_ */

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.