WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

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

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [linux-2.6.18-xen] merge with linux-2.6.18-xen.hg
From: "Xen patchbot-linux-2.6.18-xen" <patchbot-linux-2.6.18-xen@xxxxxxxxxxxxxxxxxxx>
Date: Fri, 27 Jul 2007 02:27:52 -0700
Delivery-date: Fri, 27 Jul 2007 02:26:09 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# 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

<Prev in Thread] Current Thread [Next in Thread>