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