Merge branch 'stable/xen-pcifront-0.8.2' of git://git.kernel.org/pub/scm/linux/kernel...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 29 Oct 2010 00:11:17 +0000 (17:11 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 29 Oct 2010 00:11:17 +0000 (17:11 -0700)
  and branch 'for-linus' of git://xenbits.xen.org/people/sstabellini/linux-pvhvm

* 'for-linus' of git://xenbits.xen.org/people/sstabellini/linux-pvhvm:
  xen: register xen pci notifier
  xen: initialize cpu masks for pv guests in xen_smp_init
  xen: add a missing #include to arch/x86/pci/xen.c
  xen: mask the MTRR feature from the cpuid
  xen: make hvc_xen console work for dom0.
  xen: add the direct mapping area for ISA bus access
  xen: Initialize xenbus for dom0.
  xen: use vcpu_ops to setup cpu masks
  xen: map a dummy page for local apic and ioapic in xen_set_fixmap
  xen: remap MSIs into pirqs when running as initial domain
  xen: remap GSIs as pirqs when running as initial domain
  xen: introduce XEN_DOM0 as a silent option
  xen: map MSIs into pirqs
  xen: support GSI -> pirq remapping in PV on HVM guests
  xen: add xen hvm acpi_register_gsi variant
  acpi: use indirect call to register gsi in different modes
  xen: implement xen_hvm_register_pirq
  xen: get the maximum number of pirqs from xen
  xen: support pirq != irq

* 'stable/xen-pcifront-0.8.2' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen: (27 commits)
  X86/PCI: Remove the dependency on isapnp_disable.
  xen: Update Makefile with CONFIG_BLOCK dependency for biomerge.c
  MAINTAINERS: Add myself to the Xen Hypervisor Interface and remove Chris Wright.
  x86: xen: Sanitse irq handling (part two)
  swiotlb-xen: On x86-32 builts, select SWIOTLB instead of depending on it.
  MAINTAINERS: Add myself for Xen PCI and Xen SWIOTLB maintainer.
  xen/pci: Request ACS when Xen-SWIOTLB is activated.
  xen-pcifront: Xen PCI frontend driver.
  xenbus: prevent warnings on unhandled enumeration values
  xenbus: Xen paravirtualised PCI hotplug support.
  xen/x86/PCI: Add support for the Xen PCI subsystem
  x86: Introduce x86_msi_ops
  msi: Introduce default_[teardown|setup]_msi_irqs with fallback.
  x86/PCI: Export pci_walk_bus function.
  x86/PCI: make sure _PAGE_IOMAP it set on pci mappings
  x86/PCI: Clean up pci_cache_line_size
  xen: fix shared irq device passthrough
  xen: Provide a variant of xen_poll_irq with timeout.
  xen: Find an unbound irq number in reverse order (high to low).
  xen: statically initialize cpu_evtchn_mask_p
  ...

Fix up trivial conflicts in drivers/pci/Makefile

18 files changed:
1  2 
MAINTAINERS
arch/x86/Kconfig
arch/x86/include/asm/io.h
arch/x86/kernel/apic/io_apic.c
arch/x86/pci/i386.c
arch/x86/xen/Kconfig
arch/x86/xen/enlighten.c
arch/x86/xen/mmu.c
arch/x86/xen/pci-swiotlb-xen.c
arch/x86/xen/setup.c
arch/x86/xen/smp.c
drivers/block/xen-blkfront.c
drivers/char/hvc_xen.c
drivers/net/xen-netfront.c
drivers/pci/Makefile
drivers/pci/bus.c
drivers/xen/events.c
drivers/xen/xenbus/xenbus_probe.c

diff --combined MAINTAINERS
index b60de4b2713ca8795bee390da003308c2a1ca886,30b3e163cd101e18a7bd4f6becefbcd573fcd018..cb8b580203524baa077ee0bea390efb3d559c4c4
@@@ -157,11 -157,9 +157,11 @@@ S:       Maintaine
  F:    drivers/net/r8169.c
  
  8250/16?50 (AND CLONE UARTS) SERIAL DRIVER
 +M:    Greg Kroah-Hartman <gregkh@suse.de>
  L:    linux-serial@vger.kernel.org
  W:    http://serial.sourceforge.net
 -S:    Orphan
 +S:    Maintained
 +T:    quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
  F:    drivers/serial/8250*
  F:    include/linux/serial_8250.h
  
@@@ -243,6 -241,21 +243,6 @@@ F:        drivers/pnp/pnpacpi
  F:    include/linux/acpi.h
  F:    include/acpi/
  
 -ACPI BATTERY DRIVERS
 -M:    Alexey Starikovskiy <astarikovskiy@suse.de>
 -L:    linux-acpi@vger.kernel.org
 -W:    http://www.lesswatts.org/projects/acpi/
 -S:    Supported
 -F:    drivers/acpi/battery.c
 -F:    drivers/acpi/*sbs*
 -
 -ACPI EC DRIVER
 -M:    Alexey Starikovskiy <astarikovskiy@suse.de>
 -L:    linux-acpi@vger.kernel.org
 -W:    http://www.lesswatts.org/projects/acpi/
 -S:    Supported
 -F:    drivers/acpi/ec.c
 -
  ACPI FAN DRIVER
  M:    Zhang Rui <rui.zhang@intel.com>
  L:    linux-acpi@vger.kernel.org
@@@ -432,7 -445,7 +432,7 @@@ AMS (Apple Motion Sensor) DRIVE
  M:    Stelian Pop <stelian@popies.net>
  M:    Michael Hanselmann <linux-kernel@hansmi.ch>
  S:    Supported
 -F:    drivers/hwmon/ams/
 +F:    drivers/macintosh/ams/
  
  AMSO1100 RNIC DRIVER
  M:    Tom Tucker <tom@opengridcomputing.com>
@@@ -642,7 -655,7 +642,7 @@@ ARM/FARADAY FA526 POR
  M:    Hans Ulli Kroll <ulli.kroll@googlemail.com>
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
  S:    Maintained
 -T:    git://git.berlios.de/gemini-board
 +T:    git git://git.berlios.de/gemini-board
  F:    arch/arm/mm/*-fa*
  
  ARM/FOOTBRIDGE ARCHITECTURE
@@@ -657,7 -670,7 +657,7 @@@ ARM/FREESCALE IMX / MXC ARM ARCHITECTUR
  M:    Sascha Hauer <kernel@pengutronix.de>
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
  S:    Maintained
 -T:    git://git.pengutronix.de/git/imx/linux-2.6.git
 +T:    git git://git.pengutronix.de/git/imx/linux-2.6.git
  F:    arch/arm/mach-mx*/
  F:    arch/arm/plat-mxc/
  
@@@ -695,7 -708,8 +695,7 @@@ ARM/INCOME PXA270 SUPPOR
  M:    Marek Vasut <marek.vasut@gmail.com>
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
  S:    Maintained
 -F:    arch/arm/mach-pxa/income.c
 -F:    arch/arm/mach-pxa/include/mach-pxa/income.h
 +F:    arch/arm/mach-pxa/colibri-pxa270-income.c
  
  ARM/INTEL IOP32X ARM ARCHITECTURE
  M:    Lennert Buytenhek <kernel@wantstofly.org>
@@@ -742,7 -756,13 +742,7 @@@ L:        linux-arm-kernel@lists.infradead.or
  S:    Maintained
  F:    arch/arm/mach-ixp4xx/
  
 -ARM/INTEL RESEARCH IMOTE 2 MACHINE SUPPORT
 -M:    Jonathan Cameron <jic23@cam.ac.uk>
 -L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 -S:    Maintained
 -F:    arch/arm/mach-pxa/imote2.c
 -
 -ARM/INTEL RESEARCH STARGATE 2 MACHINE SUPPORT
 +ARM/INTEL RESEARCH IMOTE/STARGATE 2 MACHINE SUPPORT
  M:    Jonathan Cameron <jic23@cam.ac.uk>
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
  S:    Maintained
@@@ -907,20 -927,40 +907,20 @@@ W:      http://www.fluff.org/ben/linux
  S:    Maintained
  F:    arch/arm/mach-s3c2410/
  
 -ARM/S3C2440 ARM ARCHITECTURE
 +ARM/S3C244x ARM ARCHITECTURE
  M:    Ben Dooks <ben-linux@fluff.org>
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
  W:    http://www.fluff.org/ben/linux/
  S:    Maintained
  F:    arch/arm/mach-s3c2440/
 -
 -ARM/S3C2442 ARM ARCHITECTURE
 -M:    Ben Dooks <ben-linux@fluff.org>
 -L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 -W:    http://www.fluff.org/ben/linux/
 -S:    Maintained
 -F:    arch/arm/mach-s3c2442/
 -
 -ARM/S3C2443 ARM ARCHITECTURE
 -M:    Ben Dooks <ben-linux@fluff.org>
 -L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 -W:    http://www.fluff.org/ben/linux/
 -S:    Maintained
  F:    arch/arm/mach-s3c2443/
  
 -ARM/S3C6400 ARM ARCHITECTURE
 -M:    Ben Dooks <ben-linux@fluff.org>
 -L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 -W:    http://www.fluff.org/ben/linux/
 -S:    Maintained
 -F:    arch/arm/mach-s3c6400/
 -
 -ARM/S3C6410 ARM ARCHITECTURE
 +ARM/S3C64xx ARM ARCHITECTURE
  M:    Ben Dooks <ben-linux@fluff.org>
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
  W:    http://www.fluff.org/ben/linux/
  S:    Maintained
 -F:    arch/arm/mach-s3c6410/
 +F:    arch/arm/mach-s3c64xx/
  
  ARM/S5P ARM ARCHITECTURES
  M:    Kukjin Kim <kgene.kim@samsung.com>
@@@ -950,23 -990,11 +950,23 @@@ S:      Supporte
  F:    arch/arm/mach-shmobile/
  F:    drivers/sh/
  
 +ARM/TELECHIPS ARM ARCHITECTURE
 +M:    "Hans J. Koch" <hjk@linutronix.de>
 +L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 +S:    Maintained
 +F:    arch/arm/plat-tcc/
 +F:    arch/arm/mach-tcc8k/
 +
  ARM/TECHNOLOGIC SYSTEMS TS7250 MACHINE SUPPORT
  M:    Lennert Buytenhek <kernel@wantstofly.org>
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
  S:    Maintained
  
 +ARM/TETON BGA MACHINE SUPPORT
 +M:    Mark F. Brown <mark.brown314@gmail.com>
 +L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 +S:    Maintained
 +
  ARM/THECUS N2100 MACHINE SUPPORT
  M:    Lennert Buytenhek <kernel@wantstofly.org>
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@@ -1109,13 -1137,6 +1109,13 @@@ W:    http://wireless.kernel.org/en/users/
  S:    Maintained
  F:    drivers/net/wireless/ath/ar9170/
  
 +CARL9170 LINUX COMMUNITY WIRELESS DRIVER
 +M:    Christian Lamparter <chunkeey@googlemail.com>
 +L:    linux-wireless@vger.kernel.org
 +W:    http://wireless.kernel.org/en/users/Drivers/carl9170
 +S:    Maintained
 +F:    drivers/net/wireless/ath/carl9170/
 +
  ATK0110 HWMON DRIVER
  M:    Luca Tettamanti <kronos.it@gmail.com>
  L:    lm-sensors@lm-sensors.org
@@@ -1340,19 -1361,16 +1340,19 @@@ F:   drivers/mtd/devices/block2mtd.
  
  BLUETOOTH DRIVERS
  M:    Marcel Holtmann <marcel@holtmann.org>
 +M:    Gustavo F. Padovan <padovan@profusion.mobi>
  L:    linux-bluetooth@vger.kernel.org
  W:    http://www.bluez.org/
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/padovan/bluetooth-2.6.git
  S:    Maintained
  F:    drivers/bluetooth/
  
  BLUETOOTH SUBSYSTEM
  M:    Marcel Holtmann <marcel@holtmann.org>
 +M:    Gustavo F. Padovan <padovan@profusion.mobi>
  L:    linux-bluetooth@vger.kernel.org
  W:    http://www.bluez.org/
 -T:    git git://git.kernel.org/pub/scm/linux/kernel/git/holtmann/bluetooth-2.6.git
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/padovan/bluetooth-2.6.git
  S:    Maintained
  F:    net/bluetooth/
  F:    include/net/bluetooth/
@@@ -1391,27 -1409,12 +1391,27 @@@ L:   netdev@vger.kernel.or
  S:    Supported
  F:    drivers/net/tg3.*
  
 +BROADCOM BRCM80211 IEEE802.11n WIRELESS DRIVER
 +M:    Brett Rudley <brudley@broadcom.com>
 +M:    Henry Ptasinski <henryp@broadcom.com>
 +M:    Nohee Ko <noheek@broadcom.com>
 +L:    linux-wireless@vger.kernel.org
 +S:    Supported
 +F:    drivers/staging/brcm80211/
 +
  BROCADE BFA FC SCSI DRIVER
  M:    Jing Huang <huangj@brocade.com>
  L:    linux-scsi@vger.kernel.org
  S:    Supported
  F:    drivers/scsi/bfa/
  
 +BROCADE BNA 10 GIGABIT ETHERNET DRIVER
 +M:    Rasesh Mody <rmody@brocade.com>
 +M:    Debashis Dutt <ddutt@brocade.com>
 +L:    netdev@vger.kernel.org
 +S:    Supported
 +F:    drivers/net/bna/
 +
  BSG (block layer generic sg v4 driver)
  M:    FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
  L:    linux-scsi@vger.kernel.org
@@@ -1524,12 -1527,11 +1524,12 @@@ T:   git git://git.kernel.org/pub/scm/lin
  S:    Supported
  F:    Documentation/filesystems/ceph.txt
  F:    fs/ceph
 +F:    net/ceph
 +F:    include/linux/ceph
  
  CERTIFIED WIRELESS USB (WUSB) SUBSYSTEM:
 -M:    David Vrabel <david.vrabel@csr.com>
  L:    linux-usb@vger.kernel.org
 -S:    Supported
 +S:    Orphan
  F:    Documentation/usb/WUSB-Design-overview.txt
  F:    Documentation/usb/wusb-cbaf
  F:    drivers/usb/host/hwa-hc.c
@@@ -1568,9 -1570,9 +1568,9 @@@ S:      Supporte
  F:    scripts/checkpatch.pl
  
  CISCO VIC ETHERNET NIC DRIVER
 -M:    Scott Feldman <scofeldm@cisco.com>
  M:    Vasanthy Kolluri <vkolluri@cisco.com>
  M:    Roopa Prabhu <roprabhu@cisco.com>
 +M:    David Wang <dwang2@cisco.com>
  S:    Supported
  F:    drivers/net/enic/
  
@@@ -1613,7 -1615,7 +1613,7 @@@ F:      drivers/platform/x86/classmate-lapto
  COCCINELLE/Semantic Patches (SmPL)
  M:    Julia Lawall <julia@diku.dk>
  M:    Gilles Muller <Gilles.Muller@lip6.fr>
 -M:    Nicolas Palix <npalix@diku.dk>
 +M:    Nicolas Palix <npalix.work@gmail.com>
  L:    cocci@diku.dk (moderated for non-subscribers)
  W:    http://coccinelle.lip6.fr/
  S:    Supported
@@@ -2048,16 -2050,14 +2048,16 @@@ F:   drivers/block/drbd
  F:    lib/lru_cache.c
  F:    Documentation/blockdev/drbd/
  
 -DRIVER CORE, KOBJECTS, AND SYSFS
 +DRIVER CORE, KOBJECTS, DEBUGFS AND SYSFS
  M:    Greg Kroah-Hartman <gregkh@suse.de>
  T:    quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
  S:    Supported
  F:    Documentation/kobject.txt
  F:    drivers/base/
  F:    fs/sysfs/
 +F:    fs/debugfs/
  F:    include/linux/kobj*
 +F:    include/linux/debugfs.h
  F:    lib/kobj*
  
  DRM DRIVERS
@@@ -2068,15 -2068,6 +2068,15 @@@ S:    Maintaine
  F:    drivers/gpu/drm/
  F:    include/drm/
  
 +INTEL DRM DRIVERS (excluding Poulsbo, Moorestown and derivative chipsets)
 +M:    Chris Wilson <chris@chris-wilson.co.uk>
 +L:    intel-gfx@lists.freedesktop.org
 +L:    dri-devel@lists.freedesktop.org
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/ickle/drm-intel.git
 +S:    Supported
 +F:    drivers/gpu/drm/i915
 +F:    include/drm/i915*
 +
  DSCC4 DRIVER
  M:    Francois Romieu <romieu@fr.zoreil.com>
  L:    netdev@vger.kernel.org
@@@ -2186,13 -2177,6 +2186,13 @@@ W:    bluesmoke.sourceforge.ne
  S:    Maintained
  F:    drivers/edac/i5400_edac.c
  
 +EDAC-I7300
 +M:    Mauro Carvalho Chehab <mchehab@redhat.com>
 +L:    linux-edac@vger.kernel.org
 +W:    bluesmoke.sourceforge.net
 +S:    Maintained
 +F:    drivers/edac/i7300_edac.c
 +
  EDAC-I7CORE
  M:    Mauro Carvalho Chehab <mchehab@redhat.com>
  L:    linux-edac@vger.kernel.org
@@@ -2620,10 -2604,10 +2620,10 @@@ F:   drivers/net/greth
  
  HARD DRIVE ACTIVE PROTECTION SYSTEM (HDAPS) DRIVER
  M:    Frank Seidel <frank@f-seidel.de>
 -L:    lm-sensors@lm-sensors.org
 +L:    platform-driver-x86@vger.kernel.org
  W:    http://www.kernel.org/pub/linux/kernel/people/fseidel/hdaps/
  S:    Maintained
 -F:    drivers/hwmon/hdaps.c
 +F:    drivers/platform/x86/hdaps.c
  
  HWPOISON MEMORY FAILURE HANDLING
  M:    Andi Kleen <andi@firstfloor.org>
@@@ -2920,12 -2904,6 +2920,12 @@@ M:    Brian King <brking@us.ibm.com
  S:    Supported
  F:    drivers/scsi/ipr.*
  
 +IBM Power Virtual Ethernet Device Driver
 +M:    Santiago Leon <santil@linux.vnet.ibm.com>
 +L:    netdev@vger.kernel.org
 +S:    Supported
 +F:    drivers/net/ibmveth.*
 +
  IBM ServeRAID RAID DRIVER
  P:    Jack Hammer
  M:    Dave Jeffery <ipslinux@adaptec.com>
@@@ -2990,7 -2968,7 +2990,7 @@@ M:      Roland Dreier <rolandd@cisco.com
  M:    Sean Hefty <sean.hefty@intel.com>
  M:    Hal Rosenstock <hal.rosenstock@gmail.com>
  L:    linux-rdma@vger.kernel.org
 -W:    http://www.openib.org/
 +W:    http://www.openfabrics.org/
  Q:    http://patchwork.kernel.org/project/linux-rdma/list/
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband.git
  S:    Supported
@@@ -3184,7 -3162,7 +3184,7 @@@ F:      drivers/net/ioc3-eth.
  
  IOC3 SERIAL DRIVER
  M:    Pat Gefre <pfg@sgi.com>
 -L:    linux-mips@linux-mips.org
 +L:    linux-serial@vger.kernel.org
  S:    Maintained
  F:    drivers/serial/ioc3_serial.c
  
@@@ -3359,12 -3337,6 +3359,12 @@@ F:    fs/jbd*
  F:    include/linux/ext*jbd*.h
  F:    include/linux/jbd*.h
  
 +JSM Neo PCI based serial card
 +M:    Breno Leitao <leitao@linux.vnet.ibm.com>
 +L:    linux-serial@vger.kernel.org
 +S:    Maintained
 +F:    drivers/serial/jsm/
 +
  K8TEMP HARDWARE MONITORING DRIVER
  M:    Rudolf Marek <r.marek@assembler.cz>
  L:    lm-sensors@lm-sensors.org
@@@ -3391,8 -3363,8 +3391,8 @@@ F:      Documentation/kdump
  KERNEL AUTOMOUNTER (AUTOFS)
  M:    "H. Peter Anvin" <hpa@zytor.com>
  L:    autofs@linux.kernel.org
 -S:    Odd Fixes
 -F:    fs/autofs/
 +S:    Obsolete
 +F:    drivers/staging/autofs/
  
  KERNEL AUTOMOUNTER v4 (AUTOFS4)
  M:    Ian Kent <raven@themaw.net>
@@@ -3415,7 -3387,7 +3415,7 @@@ F:      scripts/package
  
  KERNEL JANITORS
  L:    kernel-janitors@vger.kernel.org
 -W:    http://janitor.kernelnewbies.org/
 +W:    http://kernelnewbies.org/KernelJanitors
  S:    Odd Fixes
  
  KERNEL NFSD, SUNRPC, AND LOCKD SERVERS
@@@ -3740,13 -3712,6 +3740,13 @@@ L:    linux-scsi@vger.kernel.or
  S:    Maintained
  F:    drivers/scsi/sym53c8xx_2/
  
 +LTC4261 HARDWARE MONITOR DRIVER
 +M:    Guenter Roeck <linux@roeck-us.net>
 +L:    lm-sensors@lm-sensors.org
 +S:    Maintained
 +F:    Documentation/hwmon/ltc4261
 +F:    drivers/hwmon/ltc4261.c
 +
  LTP (Linux Test Project)
  M:    Rishikesh K Rajak <risrajak@linux.vnet.ibm.com>
  M:    Garrett Cooper <yanegomi@gmail.com>
@@@ -3842,7 -3807,7 +3842,7 @@@ F:      drivers/net/wireless/mwl8k.
  MARVELL SOC MMC/SD/SDIO CONTROLLER DRIVER
  M:    Nicolas Pitre <nico@fluxnic.net>
  S:    Odd Fixes
 -F: drivers/mmc/host/mvsdio.*
 +F:    drivers/mmc/host/mvsdio.*
  
  MARVELL YUKON / SYSKONNECT DRIVER
  M:    Mirko Lindner <mlindner@syskonnect.de>
@@@ -4403,12 -4368,13 +4403,12 @@@ F:   Documentation/filesystems/dlmfs.tx
  F:    fs/ocfs2/
  
  ORINOCO DRIVER
 -M:    Pavel Roskin <proski@gnu.org>
 -M:    David Gibson <hermes@gibson.dropbear.id.au>
  L:    linux-wireless@vger.kernel.org
  L:    orinoco-users@lists.sourceforge.net
  L:    orinoco-devel@lists.sourceforge.net
 +W:    http://linuxwireless.org/en/users/Drivers/orinoco
  W:    http://www.nongnu.org/orinoco/
 -S:    Maintained
 +S:    Orphan
  F:    drivers/net/wireless/orinoco/
  
  OSD LIBRARY and FILESYSTEM
@@@ -4441,22 -4407,13 +4441,22 @@@ L:   linux-i2c@vger.kernel.or
  S:    Maintained
  F:    drivers/i2c/busses/i2c-pasemi.c
  
 +PADATA PARALLEL EXECUTION MECHANISM
 +M:    Steffen Klassert <steffen.klassert@secunet.com>
 +L:    linux-kernel@vger.kernel.org
 +L:    linux-crypto@vger.kernel.org
 +S:    Maintained
 +F:    kernel/padata.c
 +F:    include/linux/padata.h
 +F:    Documentation/padata.txt
 +
  PANASONIC LAPTOP ACPI EXTRAS DRIVER
  M:    Harald Welte <laforge@gnumonks.org>
  L:    platform-driver-x86@vger.kernel.org
  S:    Maintained
  F:    drivers/platform/x86/panasonic-laptop.c
  
 -PANASONIC MN10300/AM33 PORT
 +PANASONIC MN10300/AM33/AM34 PORT
  M:    David Howells <dhowells@redhat.com>
  M:    Koichi Yasutake <yasutake.koichi@jp.panasonic.com>
  L:    linux-am33-list@redhat.com (moderated for non-subscribers)
@@@ -4529,12 -4486,6 +4529,12 @@@ S:    Maintaine
  F:    drivers/leds/leds-pca9532.c
  F:    include/linux/leds-pca9532.h
  
 +PCA9541 I2C BUS MASTER SELECTOR DRIVER
 +M:    Guenter Roeck <guenter.roeck@ericsson.com>
 +L:    linux-i2c@vger.kernel.org
 +S:    Maintained
 +F:    drivers/i2c/muxes/pca9541.c
 +
  PCA9564/PCA9665 I2C BUS DRIVER
  M:    Wolfram Sang <w.sang@pengutronix.de>
  L:    linux-i2c@vger.kernel.org
@@@ -4583,13 -4534,6 +4583,13 @@@ L:    netdev@vger.kernel.or
  S:    Maintained
  F:    drivers/net/pcnet32.c
  
 +PCRYPT PARALLEL CRYPTO ENGINE
 +M:    Steffen Klassert <steffen.klassert@secunet.com>
 +L:    linux-crypto@vger.kernel.org
 +S:    Maintained
 +F:    crypto/pcrypt.c
 +F:    include/crypto/pcrypt.h
 +
  PER-TASK DELAY ACCOUNTING
  M:    Balbir Singh <balbir@linux.vnet.ibm.com>
  S:    Maintained
@@@ -4618,14 -4562,6 +4618,14 @@@ L:    linux-abi-devel@lists.sourceforge.ne
  S:    Maintained
  F:    include/linux/personality.h
  
 +PHONET PROTOCOL
 +M:    Remi Denis-Courmont <remi.denis-courmont@nokia.com>
 +S:    Supported
 +F:    Documentation/networking/phonet.txt
 +F:    include/linux/phonet.h
 +F:    include/net/phonet/
 +F:    net/phonet/
 +
  PHRAM MTD DRIVER
  M:    Joern Engel <joern@lazybastard.org>
  L:    linux-mtd@lists.infradead.org
@@@ -4875,15 -4811,6 +4875,15 @@@ F:    fs/qnx4
  F:    include/linux/qnx4_fs.h
  F:    include/linux/qnxtypes.h
  
 +RADOS BLOCK DEVICE (RBD)
 +F:    include/linux/qnxtypes.h
 +M:    Yehuda Sadeh <yehuda@hq.newdream.net>
 +M:    Sage Weil <sage@newdream.net>
 +M:    ceph-devel@vger.kernel.org
 +S:    Supported
 +F:    drivers/block/rbd.c
 +F:    drivers/block/rbd_types.h
 +
  RADEON FRAMEBUFFER DISPLAY DRIVER
  M:    Benjamin Herrenschmidt <benh@kernel.crashing.org>
  L:    linux-fbdev@vger.kernel.org
@@@ -4933,7 -4860,7 +4933,7 @@@ RCUTORTURE MODUL
  M:    Josh Triplett <josh@freedesktop.org>
  M:    "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
  S:    Supported
 -T:    git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-2.6-rcu.git
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-2.6-rcu.git
  F:    Documentation/RCU/torture.txt
  F:    kernel/rcutorture.c
  
@@@ -4958,7 -4885,7 +4958,7 @@@ M:      Dipankar Sarma <dipankar@in.ibm.com
  M:    "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
  W:    http://www.rdrop.com/users/paulmck/rclock/
  S:    Supported
 -T:    git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-2.6-rcu.git
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-2.6-rcu.git
  F:    Documentation/RCU/
  F:    include/linux/rcu*
  F:    include/linux/srcu*
@@@ -5148,16 -5075,6 +5148,16 @@@ W:    http://www.kernel.d
  S:    Maintained
  F:    drivers/scsi/sr*
  
 +SCSI RDMA PROTOCOL (SRP) INITIATOR
 +M:    David Dillow <dillowda@ornl.gov>
 +L:    linux-rdma@vger.kernel.org
 +S:    Supported
 +W:    http://www.openfabrics.org
 +Q:    http://patchwork.kernel.org/project/linux-rdma/list/
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/dad/srp-initiator.git
 +F:    drivers/infiniband/ulp/srp/
 +F:    include/scsi/srp.h
 +
  SCSI SG DRIVER
  M:    Doug Gilbert <dgilbert@interlog.com>
  L:    linux-scsi@vger.kernel.org
@@@ -5380,8 -5297,8 +5380,8 @@@ F:      drivers/*/*s3c2410
  F:    drivers/*/*/*s3c2410*
  
  TI DAVINCI MACHINE SUPPORT
 -P:    Kevin Hilman
 -M:    davinci-linux-open-source@linux.davincidsp.com
 +M:    Kevin Hilman <khilman@deeprootsystems.com>
 +L:    davinci-linux-open-source@linux.davincidsp.com (subscribers-only)
  Q:    http://patchwork.kernel.org/project/linux-davinci/list/
  S:    Supported
  F:    arch/arm/mach-davinci
@@@ -5675,7 -5592,7 +5675,7 @@@ S:      Maintaine
  
  STAGING SUBSYSTEM
  M:    Greg Kroah-Hartman <gregkh@suse.de>
 -T:    quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging-next-2.6.git
  L:    devel@driverdev.osuosl.org
  S:    Maintained
  F:    drivers/staging/
@@@ -5982,9 -5899,13 +5982,9 @@@ F:     Documentation/filesystems/ufs.tx
  F:    fs/ufs/
  
  ULTRA-WIDEBAND (UWB) SUBSYSTEM:
 -M:    David Vrabel <david.vrabel@csr.com>
  L:    linux-usb@vger.kernel.org
 -S:    Supported
 +S:    Orphan
  F:    drivers/uwb/
 -X:    drivers/uwb/wlp/
 -X:    drivers/uwb/i1480/i1480u-wlp/
 -X:    drivers/uwb/i1480/i1480-wlp.h
  F:    include/linux/uwb.h
  F:    include/linux/uwb/
  
@@@ -6019,14 -5940,6 +6019,14 @@@ S:    Maintaine
  F:    Documentation/usb/acm.txt
  F:    drivers/usb/class/cdc-acm.*
  
 +USB ATTACHED SCSI
 +M:    Matthew Wilcox <willy@linux.intel.com>
 +M:    Sarah Sharp <sarah.a.sharp@linux.intel.com>
 +L:    linux-usb@vger.kernel.org
 +L:    linux-scsi@vger.kernel.org
 +S:    Supported
 +F:    drivers/usb/storage/uas.c
 +
  USB BLOCK DRIVER (UB ub)
  M:    Pete Zaitcev <zaitcev@redhat.com>
  L:    linux-usb@vger.kernel.org
@@@ -6126,6 -6039,13 +6126,6 @@@ L:     linux-usb@vger.kernel.or
  S:    Maintained
  F:    drivers/usb/serial/option.c
  
 -USB OV511 DRIVER
 -M:    Mark McClelland <mmcclell@bigfoot.com>
 -L:    linux-usb@vger.kernel.org
 -W:    http://alpha.dyndns.org/ov511/
 -S:    Maintained
 -F:    drivers/media/video/ov511.*
 -
  USB PEGASUS DRIVER
  M:    Petko Manolov <petkan@users.sourceforge.net>
  L:    linux-usb@vger.kernel.org
@@@ -6286,6 -6206,16 +6286,6 @@@ S:     Supporte
  F:    drivers/usb/host/xhci*
  F:    drivers/usb/host/pci-quirks*
  
 -USB ZC0301 DRIVER
 -M:    Luca Risolia <luca.risolia@studio.unibo.it>
 -L:    linux-usb@vger.kernel.org
 -L:    linux-media@vger.kernel.org
 -T:    git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
 -W:    http://www.linux-projects.org
 -S:    Maintained
 -F:    Documentation/video4linux/zc0301.txt
 -F:    drivers/media/video/zc0301/
 -
  USB ZD1201 DRIVER
  L:    linux-wireless@vger.kernel.org
  W:    http://linux-lc100020.sourceforge.net
@@@ -6465,12 -6395,6 +6465,12 @@@ S:    Maintaine
  F:    Documentation/hwmon/w83793
  F:    drivers/hwmon/w83793.c
  
 +W83795 HARDWARE MONITORING DRIVER
 +M:    Jean Delvare <khali@linux-fr.org>
 +L:    lm-sensors@lm-sensors.org
 +S:    Maintained
 +F:    drivers/hwmon/w83795.c
 +
  W83L51xD SD/MMC CARD INTERFACE DRIVER
  M:    Pierre Ossman <pierre@ossman.eu>
  S:    Maintained
@@@ -6509,27 -6433,36 +6509,27 @@@ F:   include/linux/wimax/debug.
  F:    include/net/wimax.h
  F:    net/wimax/
  
 -WIMEDIA LLC PROTOCOL (WLP) SUBSYSTEM
 -M:    David Vrabel <david.vrabel@csr.com>
 -L:    netdev@vger.kernel.org
 -S:    Maintained
 -F:    include/linux/wlp.h
 -F:    drivers/uwb/wlp/
 -F:    drivers/uwb/i1480/i1480u-wlp/
 -F:    drivers/uwb/i1480/i1480-wlp.h
 -
  WISTRON LAPTOP BUTTON DRIVER
  M:    Miloslav Trmac <mitr@volny.cz>
  S:    Maintained
  F:    drivers/input/misc/wistron_btns.c
  
  WL1251 WIRELESS DRIVER
 -M:    Kalle Valo <kalle.valo@iki.fi>
 +M:    Kalle Valo <kvalo@adurom.com>
  L:    linux-wireless@vger.kernel.org
  W:    http://wireless.kernel.org
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
  S:    Maintained
 -F:    drivers/net/wireless/wl12xx/*
 -X:    drivers/net/wireless/wl12xx/wl1271*
 +F:    drivers/net/wireless/wl1251/*
  
  WL1271 WIRELESS DRIVER
  M:    Luciano Coelho <luciano.coelho@nokia.com>
  L:    linux-wireless@vger.kernel.org
  W:    http://wireless.kernel.org
 -T:    git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/luca/wl12xx.git
  S:    Maintained
  F:    drivers/net/wireless/wl12xx/wl1271*
 +F:    include/linux/wl12xx.h
  
  WL3501 WIRELESS PCMCIA CARD DRIVER
  M:    Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
@@@ -6595,11 -6528,25 +6595,25 @@@ T:   git git://git.kernel.org/pub/scm/lin
  S:    Maintained
  F:    drivers/platform/x86
  
+ XEN PCI SUBSYSTEM
+ M:    Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
+ L:    xen-devel@lists.xensource.com
+ S:    Supported
+ F:    arch/x86/pci/*xen*
+ F:    drivers/pci/*xen*
+ XEN SWIOTLB SUBSYSTEM
+ M:    Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
+ L:    xen-devel@lists.xensource.com
+ S:    Supported
+ F:    arch/x86/xen/*swiotlb*
+ F:    drivers/xen/*swiotlb*
  XEN HYPERVISOR INTERFACE
- M:    Jeremy Fitzhardinge <jeremy@xensource.com>
- M:    Chris Wright <chrisw@sous-sol.org>
+ M:    Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
+ M:    Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
+ L:    xen-devel@lists.xen.org
  L:    virtualization@lists.osdl.org
- L:    xen-devel@lists.xensource.com
  S:    Supported
  F:    arch/x86/xen/
  F:    drivers/*/xen-*front.c
@@@ -6676,20 -6623,6 +6690,20 @@@ M:    "Maciej W. Rozycki" <macro@linux-mip
  S:    Maintained
  F:    drivers/serial/zs.*
  
 +GRE DEMULTIPLEXER DRIVER
 +M:    Dmitry Kozlov <xeb@mail.ru>
 +L:    netdev@vger.kernel.org
 +S:    Maintained
 +F:    net/ipv4/gre.c
 +F:    include/net/gre.h
 +
 +PPTP DRIVER
 +M:    Dmitry Kozlov <xeb@mail.ru>
 +L:    netdev@vger.kernel.org
 +S:    Maintained
 +F:    drivers/net/pptp.c
 +W:    http://sourceforge.net/projects/accel-pptp
 +
  THE REST
  M:    Linus Torvalds <torvalds@linux-foundation.org>
  L:    linux-kernel@vger.kernel.org
diff --combined arch/x86/Kconfig
index e0963f52bfdd9e72bd5705d872198fa7b0eebd5a,74ea59d34076ac148409431c252a94a71d111622..e8327686d3c55d86adb19b3c9c83bc9869e5c3cf
@@@ -1,3 -1,6 +1,3 @@@
 -# x86 configuration
 -mainmenu "Linux Kernel Configuration for x86"
 -
  # Select 32 or 64 bit
  config 64BIT
        bool "64-bit kernel" if ARCH = "x86"
@@@ -22,17 -25,14 +22,17 @@@ config X8
        select HAVE_IDE
        select HAVE_OPROFILE
        select HAVE_PERF_EVENTS if (!M386 && !M486)
 +      select HAVE_IRQ_WORK
        select HAVE_IOREMAP_PROT
        select HAVE_KPROBES
 +      select HAVE_MEMBLOCK
        select ARCH_WANT_OPTIONAL_GPIOLIB
        select ARCH_WANT_FRAME_POINTERS
        select HAVE_DMA_ATTRS
        select HAVE_KRETPROBES
        select HAVE_OPTPROBES
        select HAVE_FTRACE_MCOUNT_RECORD
 +      select HAVE_C_RECORDMCOUNT
        select HAVE_DYNAMIC_FTRACE
        select HAVE_FUNCTION_TRACER
        select HAVE_FUNCTION_GRAPH_TRACER
@@@ -59,8 -59,6 +59,8 @@@
        select ANON_INODES
        select HAVE_ARCH_KMEMCHECK
        select HAVE_USER_RETURN_NOTIFIER
 +      select HAVE_ARCH_JUMP_LABEL
 +      select HAVE_TEXT_POKE_SMP
        select HAVE_GENERIC_HARDIRQS
        select HAVE_SPARSE_IRQ
        select GENERIC_IRQ_PROBE
@@@ -199,6 -197,9 +199,6 @@@ config ARCH_SUPPORTS_OPTIMIZED_INLININ
  config ARCH_SUPPORTS_DEBUG_PAGEALLOC
        def_bool y
  
 -config HAVE_EARLY_RES
 -      def_bool y
 -
  config HAVE_INTEL_TXT
        def_bool y
        depends on EXPERIMENTAL && DMAR && ACPI
@@@ -344,7 -345,6 +344,7 @@@ endi
  
  config X86_VSMP
        bool "ScaleMP vSMP"
 +      select PARAVIRT_GUEST
        select PARAVIRT
        depends on X86_64 && PCI
        depends on X86_EXTENDED_PLATFORM
@@@ -490,6 -490,25 +490,6 @@@ if PARAVIRT_GUES
  
  source "arch/x86/xen/Kconfig"
  
 -config VMI
 -      bool "VMI Guest support (DEPRECATED)"
 -      select PARAVIRT
 -      depends on X86_32
 -      ---help---
 -        VMI provides a paravirtualized interface to the VMware ESX server
 -        (it could be used by other hypervisors in theory too, but is not
 -        at the moment), by linking the kernel to a GPL-ed ROM module
 -        provided by the hypervisor.
 -
 -        As of September 2009, VMware has started a phased retirement
 -        of this feature from VMware's products. Please see
 -        feature-removal-schedule.txt for details.  If you are
 -        planning to enable this option, please note that you cannot
 -        live migrate a VMI enabled VM to a future VMware product,
 -        which doesn't support VMI. So if you expect your kernel to
 -        seamlessly migrate to newer VMware products, keep this
 -        disabled.
 -
  config KVM_CLOCK
        bool "KVM paravirtualized clock"
        select PARAVIRT
@@@ -544,7 -563,16 +544,7 @@@ config PARAVIRT_DEBU
          a paravirt_op is missing when it is called.
  
  config NO_BOOTMEM
 -      default y
 -      bool "Disable Bootmem code"
 -      ---help---
 -        Use early_res directly instead of bootmem before slab is ready.
 -              - allocator (buddy) [generic]
 -              - early allocator (bootmem) [generic]
 -              - very early allocator (reserve_early*()) [x86]
 -              - very very early allocator (early brk model) [x86]
 -        So reduce one layer between early allocator to final allocator
 -
 +      def_bool y
  
  config MEMTEST
        bool "Memtest"
@@@ -615,7 -643,7 +615,7 @@@ config GART_IOMM
        bool "GART IOMMU support" if EMBEDDED
        default y
        select SWIOTLB
 -      depends on X86_64 && PCI && K8_NB
 +      depends on X86_64 && PCI && AMD_NB
        ---help---
          Support for full DMA access of devices with 32bit memory access only
          on systems with more than 3GB. This is usually needed for USB,
@@@ -740,17 -768,6 +740,17 @@@ config SCHED_M
          making when dealing with multi-core CPU chips at a cost of slightly
          increased overhead in some places. If unsure say N here.
  
 +config IRQ_TIME_ACCOUNTING
 +      bool "Fine granularity task level IRQ time accounting"
 +      default n
 +      ---help---
 +        Select this option to enable fine granularity task irq time
 +        accounting. This is done by reading a timestamp on each
 +        transitions between softirq and hardirq state, so there can be a
 +        small performance impact.
 +
 +        If in doubt, say N here.
 +
  source "kernel/Kconfig.preempt"
  
  config X86_UP_APIC
@@@ -1104,9 -1121,6 +1104,9 @@@ config X86_PA
  config ARCH_PHYS_ADDR_T_64BIT
        def_bool X86_64 || X86_PAE
  
 +config ARCH_DMA_ADDR_T_64BIT
 +      def_bool X86_64 || HIGHMEM64G
 +
  config DIRECT_GBPAGES
        bool "Enable 1GB pages for kernel pagetables" if EMBEDDED
        default y
@@@ -1285,34 -1299,25 +1285,34 @@@ config X86_BOOTPARAM_MEMORY_CORRUPTION_
          Set whether the default state of memory_corruption_check is
          on or off.
  
 -config X86_RESERVE_LOW_64K
 -      bool "Reserve low 64K of RAM on AMI/Phoenix BIOSen"
 -      default y
 +config X86_RESERVE_LOW
 +      int "Amount of low memory, in kilobytes, to reserve for the BIOS"
 +      default 64
 +      range 4 640
        ---help---
 -        Reserve the first 64K of physical RAM on BIOSes that are known
 -        to potentially corrupt that memory range. A numbers of BIOSes are
 -        known to utilize this area during suspend/resume, so it must not
 -        be used by the kernel.
 +        Specify the amount of low memory to reserve for the BIOS.
 +
 +        The first page contains BIOS data structures that the kernel
 +        must not use, so that page must always be reserved.
  
 -        Set this to N if you are absolutely sure that you trust the BIOS
 -        to get all its memory reservations and usages right.
 +        By default we reserve the first 64K of physical RAM, as a
 +        number of BIOSes are known to corrupt that memory range
 +        during events such as suspend/resume or monitor cable
 +        insertion, so it must not be used by the kernel.
  
 -        If you have doubts about the BIOS (e.g. suspend/resume does not
 -        work or there's kernel crashes after certain hardware hotplug
 -        events) and it's not AMI or Phoenix, then you might want to enable
 -        X86_CHECK_BIOS_CORRUPTION=y to allow the kernel to check typical
 -        corruption patterns.
 +        You can set this to 4 if you are absolutely sure that you
 +        trust the BIOS to get all its memory reservations and usages
 +        right.  If you know your BIOS have problems beyond the
 +        default 64K area, you can set this to 640 to avoid using the
 +        entire low memory range.
  
 -        Say Y if unsure.
 +        If you have doubts about the BIOS (e.g. suspend/resume does
 +        not work or there's kernel crashes after certain hardware
 +        hotplug events) then you might want to enable
 +        X86_CHECK_BIOS_CORRUPTION=y to allow the kernel to check
 +        typical corruption patterns.
 +
 +        Leave this to the default value of 64 if you are unsure.
  
  config MATH_EMULATION
        bool
@@@ -1868,7 -1873,7 +1868,7 @@@ config PCI_GODIREC
        bool "Direct"
  
  config PCI_GOOLPC
 -      bool "OLPC"
 +      bool "OLPC XO-1"
        depends on OLPC
  
  config PCI_GOANY
@@@ -1893,6 -1898,11 +1893,11 @@@ config PCI_OLP
        def_bool y
        depends on PCI && OLPC && (PCI_GOOLPC || PCI_GOANY)
  
+ config PCI_XEN
+       def_bool y
+       depends on PCI && XEN
+       select SWIOTLB_XEN
  config PCI_DOMAINS
        def_bool y
        depends on PCI
@@@ -2029,21 -2039,14 +2034,21 @@@ config SCx200HR_TIME
  config OLPC
        bool "One Laptop Per Child support"
        select GPIOLIB
 +      select OLPC_OPENFIRMWARE
        ---help---
          Add support for detecting the unique features of the OLPC
          XO hardware.
  
 +config OLPC_XO1
 +      tristate "OLPC XO-1 support"
 +      depends on OLPC && PCI
 +      ---help---
 +        Add support for non-essential features of the OLPC XO-1 laptop.
 +
  config OLPC_OPENFIRMWARE
        bool "Support for OLPC's Open Firmware"
        depends on !X86_64 && !X86_PAE
 -      default y if OLPC
 +      default n
        help
          This option adds support for the implementation of Open Firmware
          that is used on the OLPC XO-1 Children's Machine.
  
  endif # X86_32
  
 -config K8_NB
 +config AMD_NB
        def_bool y
        depends on CPU_SUP_AMD && PCI
  
@@@ -2100,10 -2103,6 +2105,10 @@@ config HAVE_ATOMIC_IOMA
        def_bool y
        depends on X86_32
  
 +config HAVE_TEXT_POKE_SMP
 +      bool
 +      select STOP_MACHINE if SMP
 +
  source "net/Kconfig"
  
  source "drivers/Kconfig"
index f0203f4791a8924a94a31d92fe78c298c3f3dd64,0ad29d4015654f059f068ee79c0f7680cf931208..072273082528c3bcff89ca88d9d98e26567c38df
@@@ -41,6 -41,8 +41,8 @@@
  #include <asm-generic/int-ll64.h>
  #include <asm/page.h>
  
+ #include <xen/xen.h>
  #define build_mmio_read(name, size, type, reg, barrier) \
  static inline type name(const volatile void __iomem *addr) \
  { type ret; asm volatile("mov" size " %1,%0":reg (ret) \
@@@ -206,7 -208,6 +208,7 @@@ static inline void __iomem *ioremap(res
  
  extern void iounmap(volatile void __iomem *addr);
  
 +extern void set_iounmap_nonlazy(void);
  
  #ifdef __KERNEL__
  
@@@ -349,8 -350,18 +351,19 @@@ extern void __iomem *early_memremap(res
                                    unsigned long size);
  extern void early_iounmap(void __iomem *addr, unsigned long size);
  extern void fixup_early_ioremap(void);
 +extern bool is_early_ioremap_ptep(pte_t *ptep);
  
+ #ifdef CONFIG_XEN
+ struct bio_vec;
+ extern bool xen_biovec_phys_mergeable(const struct bio_vec *vec1,
+                                     const struct bio_vec *vec2);
+ #define BIOVEC_PHYS_MERGEABLE(vec1, vec2)                             \
+       (__BIOVEC_PHYS_MERGEABLE(vec1, vec2) &&                         \
+        (!xen_domain() || xen_biovec_phys_mergeable(vec1, vec2)))
+ #endif        /* CONFIG_XEN */
  #define IO_SPACE_LIMIT 0xffff
  
  #endif /* _ASM_X86_IO_H */
index 8ae808d110f445f352ca686faf3a29d9d93bfa50,0885a412073785285575e453e966adfb1aa18a02..0929191d83cf5264751fbfffd19554f78f986848
@@@ -3109,8 -3109,7 +3109,8 @@@ void destroy_irq(unsigned int irq
  
        irq_set_status_flags(irq, IRQ_NOREQUEST|IRQ_NOPROBE);
  
 -      free_irte(irq);
 +      if (intr_remapping_enabled)
 +              free_irte(irq);
        raw_spin_lock_irqsave(&vector_lock, flags);
        __clear_irq_vector(irq, cfg);
        raw_spin_unlock_irqrestore(&vector_lock, flags);
@@@ -3331,7 -3330,7 +3331,7 @@@ static int setup_msi_irq(struct pci_de
        return 0;
  }
  
- int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
+ int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
  {
        int node, ret, sub_handle, index = 0;
        unsigned int irq, irq_want;
@@@ -3389,7 -3388,7 +3389,7 @@@ error
        return ret;
  }
  
- void arch_teardown_msi_irq(unsigned int irq)
+ void native_teardown_msi_irq(unsigned int irq)
  {
        destroy_irq(irq);
  }
@@@ -3650,6 -3649,11 +3650,11 @@@ void __init probe_nr_irqs_gsi(void
        printk(KERN_DEBUG "nr_irqs_gsi: %d\n", nr_irqs_gsi);
  }
  
+ int get_nr_irqs_gsi(void)
+ {
+       return nr_irqs_gsi;
+ }
  #ifdef CONFIG_SPARSE_IRQ
  int __init arch_probe_nr_irqs(void)
  {
diff --combined arch/x86/pci/i386.c
index 826140af3c3c9b6ad640743c999996a4e88f1a4e,8379c2c3d076e8d2a7ee44c580af7fa06ad71d86..c4bb261c106e16eaeab09092a9942418dba61133
@@@ -65,21 -65,16 +65,21 @@@ pcibios_align_resource(void *data, cons
                        resource_size_t size, resource_size_t align)
  {
        struct pci_dev *dev = data;
 -      resource_size_t start = res->start;
 +      resource_size_t start = round_down(res->end - size + 1, align);
  
        if (res->flags & IORESOURCE_IO) {
 -              if (skip_isa_ioresource_align(dev))
 -                      return start;
 -              if (start & 0x300)
 -                      start = (start + 0x3ff) & ~0x3ff;
 +
 +              /*
 +               * If we're avoiding ISA aliases, the largest contiguous I/O
 +               * port space is 256 bytes.  Clearing bits 9 and 10 preserves
 +               * all 256-byte and smaller alignments, so the result will
 +               * still be correctly aligned.
 +               */
 +              if (!skip_isa_ioresource_align(dev))
 +                      start &= ~0x300;
        } else if (res->flags & IORESOURCE_MEM) {
                if (start < BIOS_END)
 -                      start = BIOS_END;
 +                      start = res->end;       /* fail; no space */
        }
        return start;
  }
@@@ -316,6 -311,8 +316,8 @@@ int pci_mmap_page_range(struct pci_dev 
                 */
                prot |= _PAGE_CACHE_UC_MINUS;
  
+       prot |= _PAGE_IOMAP;    /* creating a mapping for IO */
        vma->vm_page_prot = __pgprot(prot);
  
        if (io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
diff --combined arch/x86/xen/Kconfig
index 90a7f5ad6916418e621ce1a7d3422125d0aacd5c,a234b9a71ab461ce63eab7deece3c1d9a534ffce..5b54892e4bc3c13b72f05187d8c7ec4d8752081a
@@@ -13,18 -13,31 +13,28 @@@ config XE
          kernel to boot in a paravirtualized environment under the
          Xen hypervisor.
  
+ config XEN_DOM0
+       def_bool y
+       depends on XEN && PCI_XEN && SWIOTLB_XEN
+       depends on X86_LOCAL_APIC && X86_IO_APIC && ACPI && PCI
+ # Dummy symbol since people have come to rely on the PRIVILEGED_GUEST
+ # name in tools.
+ config XEN_PRIVILEGED_GUEST
+       def_bool XEN_DOM0
  config XEN_PVHVM
        def_bool y
        depends on XEN
        depends on X86_LOCAL_APIC
  
  config XEN_MAX_DOMAIN_MEMORY
 -       int "Maximum allowed size of a domain in gigabytes"
 -       default 8 if X86_32
 -       default 32 if X86_64
 +       int
 +       default 128
         depends on XEN
         help
 -         The pseudo-physical to machine address array is sized
 -         according to the maximum possible memory size of a Xen
 -         domain.  This array uses 1 page per gigabyte, so there's no
 -         need to be too stingy here.
 +         This only affects the sizing of some bss arrays, the unused
 +         portions of which are freed.
  
  config XEN_SAVE_RESTORE
         bool
diff --combined arch/x86/xen/enlighten.c
index 70ddeaeb1ef366c7e84ba520488f85a546d3e40a,d48a32b10a3cdbd6c3bb8b9af75de8a3a55c0ab1..235c0f4d3861da6f1c9d64ded710c7c2176cf895
@@@ -30,7 -30,6 +30,7 @@@
  #include <linux/console.h>
  #include <linux/pci.h>
  #include <linux/gfp.h>
 +#include <linux/memblock.h>
  
  #include <xen/xen.h>
  #include <xen/interface/xen.h>
@@@ -46,6 -45,7 +46,7 @@@
  #include <asm/paravirt.h>
  #include <asm/apic.h>
  #include <asm/page.h>
+ #include <asm/xen/pci.h>
  #include <asm/xen/hypercall.h>
  #include <asm/xen/hypervisor.h>
  #include <asm/fixmap.h>
@@@ -59,6 -59,7 +60,6 @@@
  #include <asm/pgtable.h>
  #include <asm/tlbflush.h>
  #include <asm/reboot.h>
 -#include <asm/setup.h>
  #include <asm/stackprotector.h>
  #include <asm/hypervisor.h>
  
@@@ -135,6 -136,9 +136,6 @@@ static void xen_vcpu_setup(int cpu
        info.mfn = arbitrary_virt_to_mfn(vcpup);
        info.offset = offset_in_page(vcpup);
  
 -      printk(KERN_DEBUG "trying to map vcpu_info %d at %p, mfn %llx, offset %d\n",
 -             cpu, vcpup, info.mfn, info.offset);
 -
        /* Check to see if the hypervisor will put the vcpu_info
           structure where we want it, which allows direct access via
           a percpu-variable. */
                /* This cpu is using the registered vcpu info, even if
                   later ones fail to. */
                per_cpu(xen_vcpu, cpu) = vcpup;
 -
 -              printk(KERN_DEBUG "cpu %d using vcpu_info at %p\n",
 -                     cpu, vcpup);
        }
  }
  
@@@ -236,6 -243,7 +237,7 @@@ static __init void xen_init_cpuid_mask(
        cpuid_leaf1_edx_mask =
                ~((1 << X86_FEATURE_MCE)  |  /* disable MCE */
                  (1 << X86_FEATURE_MCA)  |  /* disable MCA */
+                 (1 << X86_FEATURE_MTRR) |  /* disable MTRR */
                  (1 << X86_FEATURE_ACC));   /* thermal monitoring */
  
        if (!xen_initial_domain())
@@@ -829,11 -837,6 +831,11 @@@ static int xen_write_msr_safe(unsigned 
                   Xen console noise. */
                break;
  
 +      case MSR_IA32_CR_PAT:
 +              if (smp_processor_id() == 0)
 +                      xen_set_pat(((u64)high << 32) | low);
 +              break;
 +
        default:
                ret = native_write_msr_safe(msr, low, high);
        }
@@@ -872,6 -875,8 +874,6 @@@ void xen_setup_vcpu_info_placement(void
        /* xen_vcpu_setup managed to place the vcpu_info within the
           percpu area for all cpus, so make use of it */
        if (have_vcpu_info_placement) {
 -              printk(KERN_INFO "Xen: using vcpu_info placement\n");
 -
                pv_irq_ops.save_fl = __PV_IS_CALLEE_SAVE(xen_save_fl_direct);
                pv_irq_ops.restore_fl = __PV_IS_CALLEE_SAVE(xen_restore_fl_direct);
                pv_irq_ops.irq_disable = __PV_IS_CALLEE_SAVE(xen_irq_disable_direct);
@@@ -1015,7 -1020,7 +1017,7 @@@ static void xen_reboot(int reason
        struct sched_shutdown r = { .reason = reason };
  
  #ifdef CONFIG_SMP
 -      smp_send_stop();
 +      stop_other_cpus();
  #endif
  
        if (HYPERVISOR_sched_op(SCHEDOP_shutdown, &r))
@@@ -1180,14 -1185,10 +1182,15 @@@ asmlinkage void __init xen_start_kernel
        local_irq_disable();
        early_boot_irqs_off();
  
 +      memblock_init();
 +
        xen_raw_console_write("mapping kernel into physical memory\n");
        pgd = xen_setup_kernel_pagetable(pgd, xen_start_info->nr_pages);
+       xen_ident_map_ISA();
  
 +      /* Allocate and initialize top and mid mfn levels for p2m structure */
 +      xen_build_mfn_list_list();
 +
        init_mm.pgd = pgd;
  
        /* keep using Xen gdt for now; no urgent need to change it */
                add_preferred_console("xenboot", 0, NULL);
                add_preferred_console("tty", 0, NULL);
                add_preferred_console("hvc", 0, NULL);
+               if (pci_xen)
+                       x86_init.pci.arch_init = pci_xen_init;
        } else {
                /* Make sure ACS will be enabled */
                pci_request_acs();
diff --combined arch/x86/xen/mmu.c
index 9631c90907ebd67b5522cac2c224cf445cfe7856,eed9c7cee4b79b9cb4249eb2154c68dbbb6ad803..c237b810b03ff8871e1291f149b3ca379b2af48c
@@@ -45,7 -45,6 +45,7 @@@
  #include <linux/vmalloc.h>
  #include <linux/module.h>
  #include <linux/gfp.h>
 +#include <linux/memblock.h>
  
  #include <asm/pgtable.h>
  #include <asm/tlbflush.h>
@@@ -56,8 -55,6 +56,8 @@@
  #include <asm/e820.h>
  #include <asm/linkage.h>
  #include <asm/page.h>
 +#include <asm/init.h>
 +#include <asm/pat.h>
  
  #include <asm/xen/hypercall.h>
  #include <asm/xen/hypervisor.h>
@@@ -141,8 -138,7 +141,8 @@@ static inline void check_zero(void
   * large enough to allocate page table pages to allocate the rest.
   * Each page can map 2MB.
   */
 -static pte_t level1_ident_pgt[PTRS_PER_PTE * 4] __page_aligned_bss;
 +#define LEVEL1_IDENT_ENTRIES  (PTRS_PER_PTE * 4)
 +static RESERVE_BRK_ARRAY(pte_t, level1_ident_pgt, LEVEL1_IDENT_ENTRIES);
  
  #ifdef CONFIG_X86_64
  /* l3 pud for userspace vsyscall mapping */
@@@ -173,182 -169,49 +173,182 @@@ DEFINE_PER_CPU(unsigned long, xen_curre
   */
  #define USER_LIMIT    ((STACK_TOP_MAX + PGDIR_SIZE - 1) & PGDIR_MASK)
  
 +/*
 + * Xen leaves the responsibility for maintaining p2m mappings to the
 + * guests themselves, but it must also access and update the p2m array
 + * during suspend/resume when all the pages are reallocated.
 + *
 + * The p2m table is logically a flat array, but we implement it as a
 + * three-level tree to allow the address space to be sparse.
 + *
 + *                               Xen
 + *                                |
 + *     p2m_top              p2m_top_mfn
 + *       /  \                   /   \
 + * p2m_mid p2m_mid    p2m_mid_mfn p2m_mid_mfn
 + *    / \      / \         /           /
 + *  p2m p2m p2m p2m p2m p2m p2m ...
 + *
 + * The p2m_mid_mfn pages are mapped by p2m_top_mfn_p.
 + *
 + * The p2m_top and p2m_top_mfn levels are limited to 1 page, so the
 + * maximum representable pseudo-physical address space is:
 + *  P2M_TOP_PER_PAGE * P2M_MID_PER_PAGE * P2M_PER_PAGE pages
 + *
 + * P2M_PER_PAGE depends on the architecture, as a mfn is always
 + * unsigned long (8 bytes on 64-bit, 4 bytes on 32), leading to
 + * 512 and 1024 entries respectively. 
 + */
 +
 +unsigned long xen_max_p2m_pfn __read_mostly;
  
 -#define P2M_ENTRIES_PER_PAGE  (PAGE_SIZE / sizeof(unsigned long))
 -#define TOP_ENTRIES           (MAX_DOMAIN_PAGES / P2M_ENTRIES_PER_PAGE)
 +#define P2M_PER_PAGE          (PAGE_SIZE / sizeof(unsigned long))
 +#define P2M_MID_PER_PAGE      (PAGE_SIZE / sizeof(unsigned long *))
 +#define P2M_TOP_PER_PAGE      (PAGE_SIZE / sizeof(unsigned long **))
  
 -/* Placeholder for holes in the address space */
 -static unsigned long p2m_missing[P2M_ENTRIES_PER_PAGE] __page_aligned_data =
 -              { [ 0 ... P2M_ENTRIES_PER_PAGE-1 ] = ~0UL };
 +#define MAX_P2M_PFN           (P2M_TOP_PER_PAGE * P2M_MID_PER_PAGE * P2M_PER_PAGE)
  
 - /* Array of pointers to pages containing p2m entries */
 -static unsigned long *p2m_top[TOP_ENTRIES] __page_aligned_data =
 -              { [ 0 ... TOP_ENTRIES - 1] = &p2m_missing[0] };
 +/* Placeholders for holes in the address space */
 +static RESERVE_BRK_ARRAY(unsigned long, p2m_missing, P2M_PER_PAGE);
 +static RESERVE_BRK_ARRAY(unsigned long *, p2m_mid_missing, P2M_MID_PER_PAGE);
 +static RESERVE_BRK_ARRAY(unsigned long, p2m_mid_missing_mfn, P2M_MID_PER_PAGE);
  
 -/* Arrays of p2m arrays expressed in mfns used for save/restore */
 -static unsigned long p2m_top_mfn[TOP_ENTRIES] __page_aligned_bss;
 +static RESERVE_BRK_ARRAY(unsigned long **, p2m_top, P2M_TOP_PER_PAGE);
 +static RESERVE_BRK_ARRAY(unsigned long, p2m_top_mfn, P2M_TOP_PER_PAGE);
 +static RESERVE_BRK_ARRAY(unsigned long *, p2m_top_mfn_p, P2M_TOP_PER_PAGE);
  
 -static unsigned long p2m_top_mfn_list[TOP_ENTRIES / P2M_ENTRIES_PER_PAGE]
 -      __page_aligned_bss;
 +RESERVE_BRK(p2m_mid, PAGE_SIZE * (MAX_DOMAIN_PAGES / (P2M_PER_PAGE * P2M_MID_PER_PAGE)));
 +RESERVE_BRK(p2m_mid_mfn, PAGE_SIZE * (MAX_DOMAIN_PAGES / (P2M_PER_PAGE * P2M_MID_PER_PAGE)));
  
  static inline unsigned p2m_top_index(unsigned long pfn)
  {
 -      BUG_ON(pfn >= MAX_DOMAIN_PAGES);
 -      return pfn / P2M_ENTRIES_PER_PAGE;
 +      BUG_ON(pfn >= MAX_P2M_PFN);
 +      return pfn / (P2M_MID_PER_PAGE * P2M_PER_PAGE);
 +}
 +
 +static inline unsigned p2m_mid_index(unsigned long pfn)
 +{
 +      return (pfn / P2M_PER_PAGE) % P2M_MID_PER_PAGE;
  }
  
  static inline unsigned p2m_index(unsigned long pfn)
  {
 -      return pfn % P2M_ENTRIES_PER_PAGE;
 +      return pfn % P2M_PER_PAGE;
  }
  
 -/* Build the parallel p2m_top_mfn structures */
 +static void p2m_top_init(unsigned long ***top)
 +{
 +      unsigned i;
 +
 +      for (i = 0; i < P2M_TOP_PER_PAGE; i++)
 +              top[i] = p2m_mid_missing;
 +}
 +
 +static void p2m_top_mfn_init(unsigned long *top)
 +{
 +      unsigned i;
 +
 +      for (i = 0; i < P2M_TOP_PER_PAGE; i++)
 +              top[i] = virt_to_mfn(p2m_mid_missing_mfn);
 +}
 +
 +static void p2m_top_mfn_p_init(unsigned long **top)
 +{
 +      unsigned i;
 +
 +      for (i = 0; i < P2M_TOP_PER_PAGE; i++)
 +              top[i] = p2m_mid_missing_mfn;
 +}
 +
 +static void p2m_mid_init(unsigned long **mid)
 +{
 +      unsigned i;
 +
 +      for (i = 0; i < P2M_MID_PER_PAGE; i++)
 +              mid[i] = p2m_missing;
 +}
 +
 +static void p2m_mid_mfn_init(unsigned long *mid)
 +{
 +      unsigned i;
 +
 +      for (i = 0; i < P2M_MID_PER_PAGE; i++)
 +              mid[i] = virt_to_mfn(p2m_missing);
 +}
 +
 +static void p2m_init(unsigned long *p2m)
 +{
 +      unsigned i;
 +
 +      for (i = 0; i < P2M_MID_PER_PAGE; i++)
 +              p2m[i] = INVALID_P2M_ENTRY;
 +}
 +
 +/*
 + * Build the parallel p2m_top_mfn and p2m_mid_mfn structures
 + *
 + * This is called both at boot time, and after resuming from suspend:
 + * - At boot time we're called very early, and must use extend_brk()
 + *   to allocate memory.
 + *
 + * - After resume we're called from within stop_machine, but the mfn
 + *   tree should alreay be completely allocated.
 + */
  void xen_build_mfn_list_list(void)
  {
 -      unsigned pfn, idx;
 +      unsigned long pfn;
  
 -      for (pfn = 0; pfn < MAX_DOMAIN_PAGES; pfn += P2M_ENTRIES_PER_PAGE) {
 -              unsigned topidx = p2m_top_index(pfn);
 +      /* Pre-initialize p2m_top_mfn to be completely missing */
 +      if (p2m_top_mfn == NULL) {
 +              p2m_mid_missing_mfn = extend_brk(PAGE_SIZE, PAGE_SIZE);
 +              p2m_mid_mfn_init(p2m_mid_missing_mfn);
 +
 +              p2m_top_mfn_p = extend_brk(PAGE_SIZE, PAGE_SIZE);
 +              p2m_top_mfn_p_init(p2m_top_mfn_p);
  
 -              p2m_top_mfn[topidx] = virt_to_mfn(p2m_top[topidx]);
 +              p2m_top_mfn = extend_brk(PAGE_SIZE, PAGE_SIZE);
 +              p2m_top_mfn_init(p2m_top_mfn);
 +      } else {
 +              /* Reinitialise, mfn's all change after migration */
 +              p2m_mid_mfn_init(p2m_mid_missing_mfn);
        }
  
 -      for (idx = 0; idx < ARRAY_SIZE(p2m_top_mfn_list); idx++) {
 -              unsigned topidx = idx * P2M_ENTRIES_PER_PAGE;
 -              p2m_top_mfn_list[idx] = virt_to_mfn(&p2m_top_mfn[topidx]);
 +      for (pfn = 0; pfn < xen_max_p2m_pfn; pfn += P2M_PER_PAGE) {
 +              unsigned topidx = p2m_top_index(pfn);
 +              unsigned mididx = p2m_mid_index(pfn);
 +              unsigned long **mid;
 +              unsigned long *mid_mfn_p;
 +
 +              mid = p2m_top[topidx];
 +              mid_mfn_p = p2m_top_mfn_p[topidx];
 +
 +              /* Don't bother allocating any mfn mid levels if
 +               * they're just missing, just update the stored mfn,
 +               * since all could have changed over a migrate.
 +               */
 +              if (mid == p2m_mid_missing) {
 +                      BUG_ON(mididx);
 +                      BUG_ON(mid_mfn_p != p2m_mid_missing_mfn);
 +                      p2m_top_mfn[topidx] = virt_to_mfn(p2m_mid_missing_mfn);
 +                      pfn += (P2M_MID_PER_PAGE - 1) * P2M_PER_PAGE;
 +                      continue;
 +              }
 +
 +              if (mid_mfn_p == p2m_mid_missing_mfn) {
 +                      /*
 +                       * XXX boot-time only!  We should never find
 +                       * missing parts of the mfn tree after
 +                       * runtime.  extend_brk() will BUG if we call
 +                       * it too late.
 +                       */
 +                      mid_mfn_p = extend_brk(PAGE_SIZE, PAGE_SIZE);
 +                      p2m_mid_mfn_init(mid_mfn_p);
 +
 +                      p2m_top_mfn_p[topidx] = mid_mfn_p;
 +              }
 +
 +              p2m_top_mfn[topidx] = virt_to_mfn(mid_mfn_p);
 +              mid_mfn_p[mididx] = virt_to_mfn(mid[mididx]);
        }
  }
  
@@@ -357,8 -220,8 +357,8 @@@ void xen_setup_mfn_list_list(void
        BUG_ON(HYPERVISOR_shared_info == &xen_dummy_shared_info);
  
        HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list =
 -              virt_to_mfn(p2m_top_mfn_list);
 -      HYPERVISOR_shared_info->arch.max_pfn = xen_start_info->nr_pages;
 +              virt_to_mfn(p2m_top_mfn);
 +      HYPERVISOR_shared_info->arch.max_pfn = xen_max_p2m_pfn;
  }
  
  /* Set up p2m_top to point to the domain-builder provided p2m pages */
@@@ -366,176 -229,98 +366,176 @@@ void __init xen_build_dynamic_phys_to_m
  {
        unsigned long *mfn_list = (unsigned long *)xen_start_info->mfn_list;
        unsigned long max_pfn = min(MAX_DOMAIN_PAGES, xen_start_info->nr_pages);
 -      unsigned pfn;
 +      unsigned long pfn;
 +
 +      xen_max_p2m_pfn = max_pfn;
  
 -      for (pfn = 0; pfn < max_pfn; pfn += P2M_ENTRIES_PER_PAGE) {
 +      p2m_missing = extend_brk(PAGE_SIZE, PAGE_SIZE);
 +      p2m_init(p2m_missing);
 +
 +      p2m_mid_missing = extend_brk(PAGE_SIZE, PAGE_SIZE);
 +      p2m_mid_init(p2m_mid_missing);
 +
 +      p2m_top = extend_brk(PAGE_SIZE, PAGE_SIZE);
 +      p2m_top_init(p2m_top);
 +
 +      /*
 +       * The domain builder gives us a pre-constructed p2m array in
 +       * mfn_list for all the pages initially given to us, so we just
 +       * need to graft that into our tree structure.
 +       */
 +      for (pfn = 0; pfn < max_pfn; pfn += P2M_PER_PAGE) {
                unsigned topidx = p2m_top_index(pfn);
 +              unsigned mididx = p2m_mid_index(pfn);
  
 -              p2m_top[topidx] = &mfn_list[pfn];
 -      }
 +              if (p2m_top[topidx] == p2m_mid_missing) {
 +                      unsigned long **mid = extend_brk(PAGE_SIZE, PAGE_SIZE);
 +                      p2m_mid_init(mid);
 +
 +                      p2m_top[topidx] = mid;
 +              }
  
 -      xen_build_mfn_list_list();
 +              p2m_top[topidx][mididx] = &mfn_list[pfn];
 +      }
  }
  
  unsigned long get_phys_to_machine(unsigned long pfn)
  {
 -      unsigned topidx, idx;
 +      unsigned topidx, mididx, idx;
  
 -      if (unlikely(pfn >= MAX_DOMAIN_PAGES))
 +      if (unlikely(pfn >= MAX_P2M_PFN))
                return INVALID_P2M_ENTRY;
  
        topidx = p2m_top_index(pfn);
 +      mididx = p2m_mid_index(pfn);
        idx = p2m_index(pfn);
 -      return p2m_top[topidx][idx];
 +
 +      return p2m_top[topidx][mididx][idx];
  }
  EXPORT_SYMBOL_GPL(get_phys_to_machine);
  
 -/* install a  new p2m_top page */
 -bool install_p2mtop_page(unsigned long pfn, unsigned long *p)
 +static void *alloc_p2m_page(void)
  {
 -      unsigned topidx = p2m_top_index(pfn);
 -      unsigned long **pfnp, *mfnp;
 -      unsigned i;
 +      return (void *)__get_free_page(GFP_KERNEL | __GFP_REPEAT);
 +}
  
 -      pfnp = &p2m_top[topidx];
 -      mfnp = &p2m_top_mfn[topidx];
 +static void free_p2m_page(void *p)
 +{
 +      free_page((unsigned long)p);
 +}
  
 -      for (i = 0; i < P2M_ENTRIES_PER_PAGE; i++)
 -              p[i] = INVALID_P2M_ENTRY;
 +/* 
 + * Fully allocate the p2m structure for a given pfn.  We need to check
 + * that both the top and mid levels are allocated, and make sure the
 + * parallel mfn tree is kept in sync.  We may race with other cpus, so
 + * the new pages are installed with cmpxchg; if we lose the race then
 + * simply free the page we allocated and use the one that's there.
 + */
 +static bool alloc_p2m(unsigned long pfn)
 +{
 +      unsigned topidx, mididx;
 +      unsigned long ***top_p, **mid;
 +      unsigned long *top_mfn_p, *mid_mfn;
  
 -      if (cmpxchg(pfnp, p2m_missing, p) == p2m_missing) {
 -              *mfnp = virt_to_mfn(p);
 -              return true;
 +      topidx = p2m_top_index(pfn);
 +      mididx = p2m_mid_index(pfn);
 +
 +      top_p = &p2m_top[topidx];
 +      mid = *top_p;
 +
 +      if (mid == p2m_mid_missing) {
 +              /* Mid level is missing, allocate a new one */
 +              mid = alloc_p2m_page();
 +              if (!mid)
 +                      return false;
 +
 +              p2m_mid_init(mid);
 +
 +              if (cmpxchg(top_p, p2m_mid_missing, mid) != p2m_mid_missing)
 +                      free_p2m_page(mid);
        }
  
 -      return false;
 -}
 +      top_mfn_p = &p2m_top_mfn[topidx];
 +      mid_mfn = p2m_top_mfn_p[topidx];
  
 -static void alloc_p2m(unsigned long pfn)
 -{
 -      unsigned long *p;
 +      BUG_ON(virt_to_mfn(mid_mfn) != *top_mfn_p);
 +
 +      if (mid_mfn == p2m_mid_missing_mfn) {
 +              /* Separately check the mid mfn level */
 +              unsigned long missing_mfn;
 +              unsigned long mid_mfn_mfn;
 +
 +              mid_mfn = alloc_p2m_page();
 +              if (!mid_mfn)
 +                      return false;
  
 -      p = (void *)__get_free_page(GFP_KERNEL | __GFP_NOFAIL);
 -      BUG_ON(p == NULL);
 +              p2m_mid_mfn_init(mid_mfn);
  
 -      if (!install_p2mtop_page(pfn, p))
 -              free_page((unsigned long)p);
 +              missing_mfn = virt_to_mfn(p2m_mid_missing_mfn);
 +              mid_mfn_mfn = virt_to_mfn(mid_mfn);
 +              if (cmpxchg(top_mfn_p, missing_mfn, mid_mfn_mfn) != missing_mfn)
 +                      free_p2m_page(mid_mfn);
 +              else
 +                      p2m_top_mfn_p[topidx] = mid_mfn;
 +      }
 +
 +      if (p2m_top[topidx][mididx] == p2m_missing) {
 +              /* p2m leaf page is missing */
 +              unsigned long *p2m;
 +
 +              p2m = alloc_p2m_page();
 +              if (!p2m)
 +                      return false;
 +
 +              p2m_init(p2m);
 +
 +              if (cmpxchg(&mid[mididx], p2m_missing, p2m) != p2m_missing)
 +                      free_p2m_page(p2m);
 +              else
 +                      mid_mfn[mididx] = virt_to_mfn(p2m);
 +      }
 +
 +      return true;
  }
  
  /* Try to install p2m mapping; fail if intermediate bits missing */
  bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn)
  {
 -      unsigned topidx, idx;
 +      unsigned topidx, mididx, idx;
  
 -      if (unlikely(pfn >= MAX_DOMAIN_PAGES)) {
 +      if (unlikely(pfn >= MAX_P2M_PFN)) {
                BUG_ON(mfn != INVALID_P2M_ENTRY);
                return true;
        }
  
        topidx = p2m_top_index(pfn);
 -      if (p2m_top[topidx] == p2m_missing) {
 -              if (mfn == INVALID_P2M_ENTRY)
 -                      return true;
 -              return false;
 -      }
 -
 +      mididx = p2m_mid_index(pfn);
        idx = p2m_index(pfn);
 -      p2m_top[topidx][idx] = mfn;
 +
 +      if (p2m_top[topidx][mididx] == p2m_missing)
 +              return mfn == INVALID_P2M_ENTRY;
 +
 +      p2m_top[topidx][mididx][idx] = mfn;
  
        return true;
  }
  
 -void set_phys_to_machine(unsigned long pfn, unsigned long mfn)
 +bool set_phys_to_machine(unsigned long pfn, unsigned long mfn)
  {
        if (unlikely(xen_feature(XENFEAT_auto_translated_physmap))) {
                BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY);
 -              return;
 +              return true;
        }
  
        if (unlikely(!__set_phys_to_machine(pfn, mfn)))  {
 -              alloc_p2m(pfn);
 +              if (!alloc_p2m(pfn))
 +                      return false;
  
                if (!__set_phys_to_machine(pfn, mfn))
 -                      BUG();
 +                      return false;
        }
 +
 +      return true;
  }
  
  unsigned long arbitrary_virt_to_mfn(void *vaddr)
@@@ -574,8 -359,7 +574,8 @@@ void make_lowmem_page_readonly(void *va
        unsigned int level;
  
        pte = lookup_address(address, &level);
 -      BUG_ON(pte == NULL);
 +      if (pte == NULL)
 +              return;         /* vaddr missing */
  
        ptev = pte_wrprotect(*pte);
  
@@@ -590,8 -374,7 +590,8 @@@ void make_lowmem_page_readwrite(void *v
        unsigned int level;
  
        pte = lookup_address(address, &level);
 -      BUG_ON(pte == NULL);
 +      if (pte == NULL)
 +              return;         /* vaddr missing */
  
        ptev = pte_mkwrite(*pte);
  
@@@ -612,7 -395,7 +612,7 @@@ static bool xen_iomap_pte(pte_t pte
        return pte_flags(pte) & _PAGE_IOMAP;
  }
  
 -static void xen_set_iomap_pte(pte_t *ptep, pte_t pteval)
 +void xen_set_domain_pte(pte_t *ptep, pte_t pteval, unsigned domid)
  {
        struct multicall_space mcs;
        struct mmu_update *u;
        u->ptr = arbitrary_virt_to_machine(ptep).maddr;
        u->val = pte_val_ma(pteval);
  
 -      MULTI_mmu_update(mcs.mc, mcs.args, 1, NULL, DOMID_IO);
 +      MULTI_mmu_update(mcs.mc, mcs.args, 1, NULL, domid);
  
        xen_mc_issue(PARAVIRT_LAZY_MMU);
  }
 +EXPORT_SYMBOL_GPL(xen_set_domain_pte);
 +
 +static void xen_set_iomap_pte(pte_t *ptep, pte_t pteval)
 +{
 +      xen_set_domain_pte(ptep, pteval, DOMID_IO);
 +}
  
  static void xen_extend_mmu_update(const struct mmu_update *update)
  {
@@@ -780,20 -557,7 +780,20 @@@ static pteval_t pte_pfn_to_mfn(pteval_
        if (val & _PAGE_PRESENT) {
                unsigned long pfn = (val & PTE_PFN_MASK) >> PAGE_SHIFT;
                pteval_t flags = val & PTE_FLAGS_MASK;
 -              val = ((pteval_t)pfn_to_mfn(pfn) << PAGE_SHIFT) | flags;
 +              unsigned long mfn = pfn_to_mfn(pfn);
 +
 +              /*
 +               * If there's no mfn for the pfn, then just create an
 +               * empty non-present pte.  Unfortunately this loses
 +               * information about the original pfn, so
 +               * pte_mfn_to_pfn is asymmetric.
 +               */
 +              if (unlikely(mfn == INVALID_P2M_ENTRY)) {
 +                      mfn = 0;
 +                      flags = 0;
 +              }
 +
 +              val = ((pteval_t)mfn << PAGE_SHIFT) | flags;
        }
  
        return val;
@@@ -815,18 -579,10 +815,18 @@@ static pteval_t iomap_pte(pteval_t val
  
  pteval_t xen_pte_val(pte_t pte)
  {
 -      if (xen_initial_domain() && (pte.pte & _PAGE_IOMAP))
 -              return pte.pte;
 +      pteval_t pteval = pte.pte;
  
 -      return pte_mfn_to_pfn(pte.pte);
 +      /* If this is a WC pte, convert back from Xen WC to Linux WC */
 +      if ((pteval & (_PAGE_PAT | _PAGE_PCD | _PAGE_PWT)) == _PAGE_PAT) {
 +              WARN_ON(!pat_enabled);
 +              pteval = (pteval & ~_PAGE_PAT) | _PAGE_PWT;
 +      }
 +
 +      if (xen_initial_domain() && (pteval & _PAGE_IOMAP))
 +              return pteval;
 +
 +      return pte_mfn_to_pfn(pteval);
  }
  PV_CALLEE_SAVE_REGS_THUNK(xen_pte_val);
  
@@@ -836,48 -592,10 +836,48 @@@ pgdval_t xen_pgd_val(pgd_t pgd
  }
  PV_CALLEE_SAVE_REGS_THUNK(xen_pgd_val);
  
 +/*
 + * Xen's PAT setup is part of its ABI, though I assume entries 6 & 7
 + * are reserved for now, to correspond to the Intel-reserved PAT
 + * types.
 + *
 + * We expect Linux's PAT set as follows:
 + *
 + * Idx  PTE flags        Linux    Xen    Default
 + * 0                     WB       WB     WB
 + * 1            PWT      WC       WT     WT
 + * 2        PCD          UC-      UC-    UC-
 + * 3        PCD PWT      UC       UC     UC
 + * 4    PAT              WB       WC     WB
 + * 5    PAT     PWT      WC       WP     WT
 + * 6    PAT PCD          UC-      UC     UC-
 + * 7    PAT PCD PWT      UC       UC     UC
 + */
 +
 +void xen_set_pat(u64 pat)
 +{
 +      /* We expect Linux to use a PAT setting of
 +       * UC UC- WC WB (ignoring the PAT flag) */
 +      WARN_ON(pat != 0x0007010600070106ull);
 +}
 +
  pte_t xen_make_pte(pteval_t pte)
  {
        phys_addr_t addr = (pte & PTE_PFN_MASK);
  
 +      /* If Linux is trying to set a WC pte, then map to the Xen WC.
 +       * If _PAGE_PAT is set, then it probably means it is really
 +       * _PAGE_PSE, so avoid fiddling with the PAT mapping and hope
 +       * things work out OK...
 +       *
 +       * (We should never see kernel mappings with _PAGE_PSE set,
 +       * but we could see hugetlbfs mappings, I think.).
 +       */
 +      if (pat_enabled && !WARN_ON(pte & _PAGE_PAT)) {
 +              if ((pte & (_PAGE_PCD | _PAGE_PWT)) == _PAGE_PWT)
 +                      pte = (pte & ~(_PAGE_PCD | _PAGE_PWT)) | _PAGE_PAT;
 +      }
 +
        /*
         * Unprivileged domains are allowed to do IOMAPpings for
         * PCI passthrough, but not map ISA space.  The ISA
@@@ -1790,25 -1508,13 +1790,25 @@@ static void xen_pgd_free(struct mm_stru
  #endif
  }
  
 -#ifdef CONFIG_X86_32
  static __init pte_t mask_rw_pte(pte_t *ptep, pte_t pte)
  {
 +      unsigned long pfn = pte_pfn(pte);
 +
 +#ifdef CONFIG_X86_32
        /* If there's an existing pte, then don't allow _PAGE_RW to be set */
        if (pte_val_ma(*ptep) & _PAGE_PRESENT)
                pte = __pte_ma(((pte_val_ma(*ptep) & _PAGE_RW) | ~_PAGE_RW) &
                               pte_val_ma(pte));
 +#endif
 +
 +      /*
 +       * If the new pfn is within the range of the newly allocated
 +       * kernel pagetable, and it isn't being mapped into an
 +       * early_ioremap fixmap slot, make sure it is RO.
 +       */
 +      if (!is_early_ioremap_ptep(ptep) &&
 +          pfn >= e820_table_start && pfn < e820_table_end)
 +              pte = pte_wrprotect(pte);
  
        return pte;
  }
@@@ -1821,6 -1527,7 +1821,6 @@@ static __init void xen_set_pte_init(pte
  
        xen_set_pte(ptep, pte);
  }
 -#endif
  
  static void pin_pagetable_pfn(unsigned cmd, unsigned long pfn)
  {
@@@ -1975,6 -1682,7 +1975,7 @@@ static void *m2v(phys_addr_t maddr
        return __ka(m2p(maddr));
  }
  
+ /* Set the page permissions on an identity-mapped pages */
  static void set_page_prot(void *addr, pgprot_t prot)
  {
        unsigned long pfn = __pa(addr) >> PAGE_SHIFT;
@@@ -1990,9 -1698,6 +1991,9 @@@ static __init void xen_map_identity_ear
        unsigned ident_pte;
        unsigned long pfn;
  
 +      level1_ident_pgt = extend_brk(sizeof(pte_t) * LEVEL1_IDENT_ENTRIES,
 +                                    PAGE_SIZE);
 +
        ident_pte = 0;
        pfn = 0;
        for (pmdidx = 0; pmdidx < PTRS_PER_PMD && pfn < max_pfn; pmdidx++) {
                        pte_page = m2v(pmd[pmdidx].pmd);
                else {
                        /* Check for free pte pages */
 -                      if (ident_pte == ARRAY_SIZE(level1_ident_pgt))
 +                      if (ident_pte == LEVEL1_IDENT_ENTRIES)
                                break;
  
                        pte_page = &level1_ident_pgt[ident_pte];
@@@ -2110,7 -1815,7 +2111,7 @@@ __init pgd_t *xen_setup_kernel_pagetabl
        __xen_write_cr3(true, __pa(pgd));
        xen_mc_issue(PARAVIRT_LAZY_CPU);
  
 -      reserve_early(__pa(xen_start_info->pt_base),
 +      memblock_x86_reserve_range(__pa(xen_start_info->pt_base),
                      __pa(xen_start_info->pt_base +
                           xen_start_info->nr_pt_frames * PAGE_SIZE),
                      "XEN PAGETABLES");
        return pgd;
  }
  #else /* !CONFIG_X86_64 */
 -static pmd_t level2_kernel_pgt[PTRS_PER_PMD] __page_aligned_bss;
 +static RESERVE_BRK_ARRAY(pmd_t, level2_kernel_pgt, PTRS_PER_PMD);
  
  __init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd,
                                         unsigned long max_pfn)
  {
        pmd_t *kernel_pmd;
  
 +      level2_kernel_pgt = extend_brk(sizeof(pmd_t *) * PTRS_PER_PMD, PAGE_SIZE);
 +
        max_pfn_mapped = PFN_DOWN(__pa(xen_start_info->pt_base) +
                                  xen_start_info->nr_pt_frames * PAGE_SIZE +
                                  512*1024);
  
        pin_pagetable_pfn(MMUEXT_PIN_L3_TABLE, PFN_DOWN(__pa(swapper_pg_dir)));
  
 -      reserve_early(__pa(xen_start_info->pt_base),
 +      memblock_x86_reserve_range(__pa(xen_start_info->pt_base),
                      __pa(xen_start_info->pt_base +
                           xen_start_info->nr_pt_frames * PAGE_SIZE),
                      "XEN PAGETABLES");
  }
  #endif        /* CONFIG_X86_64 */
  
+ static unsigned char dummy_mapping[PAGE_SIZE] __page_aligned_bss;
  static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot)
  {
        pte_t pte;
  # endif
  #else
        case VSYSCALL_LAST_PAGE ... VSYSCALL_FIRST_PAGE:
- #endif
- #ifdef CONFIG_X86_LOCAL_APIC
-       case FIX_APIC_BASE:     /* maps dummy local APIC */
  #endif
        case FIX_TEXT_POKE0:
        case FIX_TEXT_POKE1:
                pte = pfn_pte(phys, prot);
                break;
  
+ #ifdef CONFIG_X86_LOCAL_APIC
+       case FIX_APIC_BASE:     /* maps dummy local APIC */
+               pte = pfn_pte(PFN_DOWN(__pa(dummy_mapping)), PAGE_KERNEL);
+               break;
+ #endif
+ #ifdef CONFIG_X86_IO_APIC
+       case FIX_IO_APIC_BASE_0 ... FIX_IO_APIC_BASE_END:
+               /*
+                * We just don't map the IO APIC - all access is via
+                * hypercalls.  Keep the address in the pte for reference.
+                */
+               pte = pfn_pte(PFN_DOWN(__pa(dummy_mapping)), PAGE_KERNEL);
+               break;
+ #endif
        case FIX_PARAVIRT_BOOTMAP:
                /* This is an MFN, but it isn't an IO mapping from the
                   IO domain */
  #endif
  }
  
+ __init void xen_ident_map_ISA(void)
+ {
+       unsigned long pa;
+       /*
+        * If we're dom0, then linear map the ISA machine addresses into
+        * the kernel's address space.
+        */
+       if (!xen_initial_domain())
+               return;
+       xen_raw_printk("Xen: setup ISA identity maps\n");
+       for (pa = ISA_START_ADDRESS; pa < ISA_END_ADDRESS; pa += PAGE_SIZE) {
+               pte_t pte = mfn_pte(PFN_DOWN(pa), PAGE_KERNEL_IO);
+               if (HYPERVISOR_update_va_mapping(PAGE_OFFSET + pa, pte, 0))
+                       BUG();
+       }
+       xen_flush_tlb();
+ }
  static __init void xen_post_allocator_init(void)
  {
        pv_mmu_ops.set_pte = xen_set_pte;
@@@ -2267,9 -2008,14 +2306,9 @@@ static const struct pv_mmu_ops xen_mmu_
        .alloc_pte = xen_alloc_pte_init,
        .release_pte = xen_release_pte_init,
        .alloc_pmd = xen_alloc_pmd_init,
 -      .alloc_pmd_clone = paravirt_nop,
        .release_pmd = xen_release_pmd_init,
  
 -#ifdef CONFIG_X86_64
 -      .set_pte = xen_set_pte,
 -#else
        .set_pte = xen_set_pte_init,
 -#endif
        .set_pte_at = xen_set_pte_at,
        .set_pmd = xen_set_pmd_hyper,
  
@@@ -2320,6 -2066,8 +2359,8 @@@ void __init xen_init_mmu_ops(void
        pv_mmu_ops = xen_mmu_ops;
  
        vmap_lazy_unmap = false;
+       memset(dummy_mapping, 0xff, PAGE_SIZE);
  }
  
  /* Protected by xen_reservation_lock. */
@@@ -2552,72 -2300,6 +2593,72 @@@ void __init xen_hvm_init_mmu_ops(void
  }
  #endif
  
 +#define REMAP_BATCH_SIZE 16
 +
 +struct remap_data {
 +      unsigned long mfn;
 +      pgprot_t prot;
 +      struct mmu_update *mmu_update;
 +};
 +
 +static int remap_area_mfn_pte_fn(pte_t *ptep, pgtable_t token,
 +                               unsigned long addr, void *data)
 +{
 +      struct remap_data *rmd = data;
 +      pte_t pte = pte_mkspecial(pfn_pte(rmd->mfn++, rmd->prot));
 +
 +      rmd->mmu_update->ptr = arbitrary_virt_to_machine(ptep).maddr;
 +      rmd->mmu_update->val = pte_val_ma(pte);
 +      rmd->mmu_update++;
 +
 +      return 0;
 +}
 +
 +int xen_remap_domain_mfn_range(struct vm_area_struct *vma,
 +                             unsigned long addr,
 +                             unsigned long mfn, int nr,
 +                             pgprot_t prot, unsigned domid)
 +{
 +      struct remap_data rmd;
 +      struct mmu_update mmu_update[REMAP_BATCH_SIZE];
 +      int batch;
 +      unsigned long range;
 +      int err = 0;
 +
 +      prot = __pgprot(pgprot_val(prot) | _PAGE_IOMAP);
 +
 +      vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP;
 +
 +      rmd.mfn = mfn;
 +      rmd.prot = prot;
 +
 +      while (nr) {
 +              batch = min(REMAP_BATCH_SIZE, nr);
 +              range = (unsigned long)batch << PAGE_SHIFT;
 +
 +              rmd.mmu_update = mmu_update;
 +              err = apply_to_page_range(vma->vm_mm, addr, range,
 +                                        remap_area_mfn_pte_fn, &rmd);
 +              if (err)
 +                      goto out;
 +
 +              err = -EFAULT;
 +              if (HYPERVISOR_mmu_update(mmu_update, batch, NULL, domid) < 0)
 +                      goto out;
 +
 +              nr -= batch;
 +              addr += range;
 +      }
 +
 +      err = 0;
 +out:
 +
 +      flush_tlb_all();
 +
 +      return err;
 +}
 +EXPORT_SYMBOL_GPL(xen_remap_domain_mfn_range);
 +
  #ifdef CONFIG_XEN_DEBUG_FS
  
  static struct dentry *d_mmu_debug;
index 22471001b74c48dc26e499a549d4eb8549ed48e3,be4d80a6fae9d3bd267a9a748771cd5f7522dc2e..bfd0632fe65ec79e593aa66a14e77b66152737e4
@@@ -1,11 -1,11 +1,12 @@@
  /* Glue code to lib/swiotlb-xen.c */
  
  #include <linux/dma-mapping.h>
+ #include <linux/pci.h>
  #include <xen/swiotlb-xen.h>
  
  #include <asm/xen/hypervisor.h>
  #include <xen/xen.h>
 +#include <asm/iommu_table.h>
  
  int xen_swiotlb __read_mostly;
  
@@@ -55,9 -55,8 +56,12 @@@ void __init pci_xen_swiotlb_init(void
        if (xen_swiotlb) {
                xen_swiotlb_init(1);
                dma_ops = &xen_swiotlb_dma_ops;
+               /* Make sure ACS will be enabled */
+               pci_request_acs();
        }
  }
 +IOMMU_INIT_FINISH(pci_xen_swiotlb_detect,
 +                0,
 +                pci_xen_swiotlb_init,
 +                0);
diff --combined arch/x86/xen/setup.c
index 105db2501050483901a3ba9be6b37310b4152481,62ceb7864017167659527f92f5d5f97f46028aea..b1dbdaa23ecc2a632003382c0c9e4e1d6819e386
@@@ -8,7 -8,6 +8,7 @@@
  #include <linux/sched.h>
  #include <linux/mm.h>
  #include <linux/pm.h>
 +#include <linux/memblock.h>
  
  #include <asm/elf.h>
  #include <asm/vdso.h>
  #include <asm/xen/hypervisor.h>
  #include <asm/xen/hypercall.h>
  
 +#include <xen/xen.h>
  #include <xen/page.h>
  #include <xen/interface/callback.h>
 +#include <xen/interface/memory.h>
  #include <xen/interface/physdev.h>
  #include <xen/interface/memory.h>
  #include <xen/features.h>
@@@ -36,39 -33,6 +36,39 @@@ extern void xen_sysenter_target(void)
  extern void xen_syscall_target(void);
  extern void xen_syscall32_target(void);
  
 +/* Amount of extra memory space we add to the e820 ranges */
 +phys_addr_t xen_extra_mem_start, xen_extra_mem_size;
 +
 +/* 
 + * The maximum amount of extra memory compared to the base size.  The
 + * main scaling factor is the size of struct page.  At extreme ratios
 + * of base:extra, all the base memory can be filled with page
 + * structures for the extra memory, leaving no space for anything
 + * else.
 + * 
 + * 10x seems like a reasonable balance between scaling flexibility and
 + * leaving a practically usable system.
 + */
 +#define EXTRA_MEM_RATIO               (10)
 +
 +static __init void xen_add_extra_mem(unsigned long pages)
 +{
 +      u64 size = (u64)pages * PAGE_SIZE;
 +      u64 extra_start = xen_extra_mem_start + xen_extra_mem_size;
 +
 +      if (!pages)
 +              return;
 +
 +      e820_add_region(extra_start, size, E820_RAM);
 +      sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
 +
 +      memblock_x86_reserve_range(extra_start, extra_start + size, "XEN EXTRA");
 +
 +      xen_extra_mem_size += size;
 +
 +      xen_max_p2m_pfn = PFN_DOWN(extra_start + size);
 +}
 +
  static unsigned long __init xen_release_chunk(phys_addr_t start_addr,
                                              phys_addr_t end_addr)
  {
@@@ -140,70 -104,24 +140,73 @@@ static unsigned long __init xen_return_
  /**
   * machine_specific_memory_setup - Hook for machine specific memory setup.
   **/
 -
  char * __init xen_memory_setup(void)
  {
 +      static struct e820entry map[E820MAX] __initdata;
 +
        unsigned long max_pfn = xen_start_info->nr_pages;
 +      unsigned long long mem_end;
 +      int rc;
 +      struct xen_memory_map memmap;
 +      unsigned long extra_pages = 0;
 +      unsigned long extra_limit;
 +      int i;
 +      int op;
  
        max_pfn = min(MAX_DOMAIN_PAGES, max_pfn);
 +      mem_end = PFN_PHYS(max_pfn);
 +
 +      memmap.nr_entries = E820MAX;
 +      set_xen_guest_handle(memmap.buffer, map);
 +
 +      op = xen_initial_domain() ?
 +              XENMEM_machine_memory_map :
 +              XENMEM_memory_map;
 +      rc = HYPERVISOR_memory_op(op, &memmap);
 +      if (rc == -ENOSYS) {
 +              memmap.nr_entries = 1;
 +              map[0].addr = 0ULL;
 +              map[0].size = mem_end;
 +              /* 8MB slack (to balance backend allocations). */
 +              map[0].size += 8ULL << 20;
 +              map[0].type = E820_RAM;
 +              rc = 0;
 +      }
 +      BUG_ON(rc);
  
        e820.nr_map = 0;
 +      xen_extra_mem_start = mem_end;
 +      for (i = 0; i < memmap.nr_entries; i++) {
 +              unsigned long long end = map[i].addr + map[i].size;
 +
 +              if (map[i].type == E820_RAM) {
 +                      if (map[i].addr < mem_end && end > mem_end) {
 +                              /* Truncate region to max_mem. */
 +                              u64 delta = end - mem_end;
 +
 +                              map[i].size -= delta;
 +                              extra_pages += PFN_DOWN(delta);
 +
 +                              end = mem_end;
 +                      }
 +              }
 +
 +              if (end > xen_extra_mem_start)
 +                      xen_extra_mem_start = end;
  
 -      e820_add_region(0, PFN_PHYS((u64)max_pfn), E820_RAM);
 +              /* If region is non-RAM or below mem_end, add what remains */
 +              if ((map[i].type != E820_RAM || map[i].addr < mem_end) &&
 +                  map[i].size > 0)
 +                      e820_add_region(map[i].addr, map[i].size, map[i].type);
 +      }
  
        /*
         * Even though this is normal, usable memory under Xen, reserve
         * ISA memory anyway because too many things think they can poke
         * about in there.
+        *
+        * In a dom0 kernel, this region is identity mapped with the
+        * hardware ISA area, so it really is out of bounds.
         */
        e820_add_region(ISA_START_ADDRESS, ISA_END_ADDRESS - ISA_START_ADDRESS,
                        E820_RESERVED);
         *  - xen_start_info
         * See comment above "struct start_info" in <xen/interface/xen.h>
         */
 -      reserve_early(__pa(xen_start_info->mfn_list),
 +      memblock_x86_reserve_range(__pa(xen_start_info->mfn_list),
                      __pa(xen_start_info->pt_base),
                        "XEN START INFO");
  
        sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
  
 -      xen_return_unused_memory(xen_start_info->nr_pages, &e820);
 +      extra_pages += xen_return_unused_memory(xen_start_info->nr_pages, &e820);
 +
 +      /*
 +       * Clamp the amount of extra memory to a EXTRA_MEM_RATIO
 +       * factor the base size.  On non-highmem systems, the base
 +       * size is the full initial memory allocation; on highmem it
 +       * is limited to the max size of lowmem, so that it doesn't
 +       * get completely filled.
 +       *
 +       * In principle there could be a problem in lowmem systems if
 +       * the initial memory is also very large with respect to
 +       * lowmem, but we won't try to deal with that here.
 +       */
 +      extra_limit = min(EXTRA_MEM_RATIO * min(max_pfn, PFN_DOWN(MAXMEM)),
 +                        max_pfn + extra_pages);
 +
 +      if (extra_limit >= max_pfn)
 +              extra_pages = extra_limit - max_pfn;
 +      else
 +              extra_pages = 0;
 +
 +      if (!xen_initial_domain())
 +              xen_add_extra_mem(extra_pages);
  
        return "Xen";
  }
@@@ -367,7 -263,5 +370,5 @@@ void __init xen_arch_setup(void
  
        pm_idle = xen_idle;
  
-       paravirt_disable_iospace();
        fiddle_vdso();
  }
diff --combined arch/x86/xen/smp.c
index f4d01003146581c1f58cf4835ed989de7854def5,834dfeb54e310b297b6f180a70deee67752b9f68..72a4c79590459f58c6532b89dd74112654cb7608
@@@ -28,6 -28,7 +28,7 @@@
  #include <asm/xen/interface.h>
  #include <asm/xen/hypercall.h>
  
+ #include <xen/xen.h>
  #include <xen/page.h>
  #include <xen/events.h>
  
@@@ -156,11 -157,35 +157,35 @@@ static void __init xen_fill_possible_ma
  {
        int i, rc;
  
+       if (xen_initial_domain())
+               return;
+       for (i = 0; i < nr_cpu_ids; i++) {
+               rc = HYPERVISOR_vcpu_op(VCPUOP_is_up, i, NULL);
+               if (rc >= 0) {
+                       num_processors++;
+                       set_cpu_possible(i, true);
+               }
+       }
+ }
+ static void __init xen_filter_cpu_maps(void)
+ {
+       int i, rc;
+       if (!xen_initial_domain())
+               return;
+       num_processors = 0;
+       disabled_cpus = 0;
        for (i = 0; i < nr_cpu_ids; i++) {
                rc = HYPERVISOR_vcpu_op(VCPUOP_is_up, i, NULL);
                if (rc >= 0) {
                        num_processors++;
                        set_cpu_possible(i, true);
+               } else {
+                       set_cpu_possible(i, false);
+                       set_cpu_present(i, false);
                }
        }
  }
@@@ -174,6 -199,7 +199,7 @@@ static void __init xen_smp_prepare_boot
           old memory can be recycled */
        make_lowmem_page_readwrite(xen_initial_gdt);
  
+       xen_filter_cpu_maps();
        xen_setup_vcpu_info_placement();
  }
  
@@@ -400,9 -426,9 +426,9 @@@ static void stop_self(void *v
        BUG();
  }
  
 -static void xen_smp_send_stop(void)
 +static void xen_stop_other_cpus(int wait)
  {
 -      smp_call_function(stop_self, NULL, 0);
 +      smp_call_function(stop_self, NULL, wait);
  }
  
  static void xen_smp_send_reschedule(int cpu)
@@@ -470,7 -496,7 +496,7 @@@ static const struct smp_ops xen_smp_op
        .cpu_disable = xen_cpu_disable,
        .play_dead = xen_play_dead,
  
 -      .smp_send_stop = xen_smp_send_stop,
 +      .stop_other_cpus = xen_stop_other_cpus,
        .smp_send_reschedule = xen_smp_send_reschedule,
  
        .send_call_func_ipi = xen_smp_send_call_function_ipi,
index 4b33a18c32e0c91959442deab466741b7e245ddf,c4e9d817caaa68b8a30ffccf5d9b77a113c6719a..06e2812ba12405dc0a63eea531943b53c4aa067b
@@@ -41,7 -41,7 +41,7 @@@
  #include <linux/cdrom.h>
  #include <linux/module.h>
  #include <linux/slab.h>
 -#include <linux/smp_lock.h>
 +#include <linux/mutex.h>
  #include <linux/scatterlist.h>
  
  #include <xen/xen.h>
@@@ -69,7 -69,6 +69,7 @@@ struct blk_shadow 
        unsigned long frame[BLKIF_MAX_SEGMENTS_PER_REQUEST];
  };
  
 +static DEFINE_MUTEX(blkfront_mutex);
  static const struct block_device_operations xlvbd_block_fops;
  
  #define BLK_RING_SIZE __RING_SIZE((struct blkif_sring *)0, PAGE_SIZE)
@@@ -96,7 -95,7 +96,7 @@@ struct blkfront_inf
        struct gnttab_free_callback callback;
        struct blk_shadow shadow[BLK_RING_SIZE];
        unsigned long shadow_free;
 -      int feature_barrier;
 +      unsigned int feature_flush;
        int is_ready;
  };
  
@@@ -419,12 -418,26 +419,12 @@@ static int xlvbd_init_blk_queue(struct 
  }
  
  
 -static int xlvbd_barrier(struct blkfront_info *info)
 +static void xlvbd_flush(struct blkfront_info *info)
  {
 -      int err;
 -      const char *barrier;
 -
 -      switch (info->feature_barrier) {
 -      case QUEUE_ORDERED_DRAIN:       barrier = "enabled (drain)"; break;
 -      case QUEUE_ORDERED_TAG:         barrier = "enabled (tag)"; break;
 -      case QUEUE_ORDERED_NONE:        barrier = "disabled"; break;
 -      default:                        return -EINVAL;
 -      }
 -
 -      err = blk_queue_ordered(info->rq, info->feature_barrier);
 -
 -      if (err)
 -              return err;
 -
 +      blk_queue_flush(info->rq, info->feature_flush);
        printk(KERN_INFO "blkfront: %s: barriers %s\n",
 -             info->gd->disk_name, barrier);
 -      return 0;
 +             info->gd->disk_name,
 +             info->feature_flush ? "enabled" : "disabled");
  }
  
  
@@@ -503,7 -516,7 +503,7 @@@ static int xlvbd_alloc_gendisk(blkif_se
        info->rq = gd->queue;
        info->gd = gd;
  
 -      xlvbd_barrier(info);
 +      xlvbd_flush(info);
  
        if (vdisk_info & VDISK_READONLY)
                set_disk_ro(gd, 1);
@@@ -649,8 -662,8 +649,8 @@@ static irqreturn_t blkif_interrupt(int 
                                printk(KERN_WARNING "blkfront: %s: write barrier op failed\n",
                                       info->gd->disk_name);
                                error = -EOPNOTSUPP;
 -                              info->feature_barrier = QUEUE_ORDERED_NONE;
 -                              xlvbd_barrier(info);
 +                              info->feature_flush = 0;
 +                              xlvbd_flush(info);
                        }
                        /* fall through */
                case BLKIF_OP_READ:
@@@ -1063,20 -1076,20 +1063,20 @@@ static void blkfront_connect(struct blk
        /*
         * If there's no "feature-barrier" defined, then it means
         * we're dealing with a very old backend which writes
 -       * synchronously; draining will do what needs to get done.
 +       * synchronously; nothing to do.
         *
 -       * If there are barriers, then we can do full queued writes
 -       * with tagged barriers.
 -       *
 -       * If barriers are not supported, then there's no much we can
 -       * do, so just set ordering to NONE.
 +       * If there are barriers, then we use flush.
         */
 -      if (err)
 -              info->feature_barrier = QUEUE_ORDERED_DRAIN;
 -      else if (barrier)
 -              info->feature_barrier = QUEUE_ORDERED_TAG;
 -      else
 -              info->feature_barrier = QUEUE_ORDERED_NONE;
 +      info->feature_flush = 0;
 +
 +      /*
 +       * The driver doesn't properly handled empty flushes, so
 +       * lets disable barrier support for now.
 +       */
 +#if 0
 +      if (!err && barrier)
 +              info->feature_flush = REQ_FLUSH;
 +#endif
  
        err = xlvbd_alloc_gendisk(sectors, info, binfo, sector_size);
        if (err) {
@@@ -1112,6 -1125,8 +1112,8 @@@ static void blkback_changed(struct xenb
        case XenbusStateInitialising:
        case XenbusStateInitWait:
        case XenbusStateInitialised:
+       case XenbusStateReconfiguring:
+       case XenbusStateReconfigured:
        case XenbusStateUnknown:
        case XenbusStateClosed:
                break;
@@@ -1188,7 -1203,7 +1190,7 @@@ static int blkif_open(struct block_devi
        struct blkfront_info *info;
        int err = 0;
  
 -      lock_kernel();
 +      mutex_lock(&blkfront_mutex);
  
        info = disk->private_data;
        if (!info) {
        mutex_unlock(&info->mutex);
  
  out:
 -      unlock_kernel();
 +      mutex_unlock(&blkfront_mutex);
        return err;
  }
  
@@@ -1216,7 -1231,7 +1218,7 @@@ static int blkif_release(struct gendis
        struct block_device *bdev;
        struct xenbus_device *xbdev;
  
 -      lock_kernel();
 +      mutex_lock(&blkfront_mutex);
  
        bdev = bdget_disk(disk, 0);
        bdput(bdev);
        }
  
  out:
 -      unlock_kernel();
 +      mutex_unlock(&blkfront_mutex);
        return 0;
  }
  
diff --combined drivers/char/hvc_xen.c
index 6b8e6d18a8e6e7c8c44b2644ed7c72beb953f1f5,1f7e13a43a880f24cc88085cc766abf62e9384ed..3740e327f1802f0e63bd1cdffba4107cbbf55c7e
@@@ -74,12 -74,11 +74,12 @@@ static int __write_console(const char *
        wmb();                  /* write ring before updating pointer */
        intf->out_prod = prod;
  
 -      notify_daemon();
 +      if (sent)
 +              notify_daemon();
        return sent;
  }
  
- static int write_console(uint32_t vtermno, const char *data, int len)
+ static int domU_write_console(uint32_t vtermno, const char *data, int len)
  {
        int ret = len;
  
        return ret;
  }
  
- static int read_console(uint32_t vtermno, char *buf, int len)
+ static int domU_read_console(uint32_t vtermno, char *buf, int len)
  {
        struct xencons_interface *intf = xencons_interface();
        XENCONS_RING_IDX cons, prod;
        return recv;
  }
  
- static const struct hv_ops hvc_ops = {
-       .get_chars = read_console,
-       .put_chars = write_console,
+ static struct hv_ops domU_hvc_ops = {
+       .get_chars = domU_read_console,
+       .put_chars = domU_write_console,
        .notifier_add = notifier_add_irq,
        .notifier_del = notifier_del_irq,
        .notifier_hangup = notifier_hangup_irq,
  };
  
- static int __init xen_init(void)
+ static int dom0_read_console(uint32_t vtermno, char *buf, int len)
+ {
+       return HYPERVISOR_console_io(CONSOLEIO_read, len, buf);
+ }
+ /*
+  * Either for a dom0 to write to the system console, or a domU with a
+  * debug version of Xen
+  */
+ static int dom0_write_console(uint32_t vtermno, const char *str, int len)
+ {
+       int rc = HYPERVISOR_console_io(CONSOLEIO_write, len, (char *)str);
+       if (rc < 0)
+               return 0;
+       return len;
+ }
+ static struct hv_ops dom0_hvc_ops = {
+       .get_chars = dom0_read_console,
+       .put_chars = dom0_write_console,
+       .notifier_add = notifier_add_irq,
+       .notifier_del = notifier_del_irq,
+       .notifier_hangup = notifier_hangup_irq,
+ };
+ static int __init xen_hvc_init(void)
  {
        struct hvc_struct *hp;
+       struct hv_ops *ops;
  
-       if (!xen_pv_domain() ||
-           xen_initial_domain() ||
-           !xen_start_info->console.domU.evtchn)
+       if (!xen_pv_domain())
                return -ENODEV;
  
-       xencons_irq = bind_evtchn_to_irq(xen_start_info->console.domU.evtchn);
+       if (xen_initial_domain()) {
+               ops = &dom0_hvc_ops;
+               xencons_irq = bind_virq_to_irq(VIRQ_CONSOLE, 0);
+       } else {
+               if (!xen_start_info->console.domU.evtchn)
+                       return -ENODEV;
+               ops = &domU_hvc_ops;
+               xencons_irq = bind_evtchn_to_irq(xen_start_info->console.domU.evtchn);
+       }
        if (xencons_irq < 0)
                xencons_irq = 0; /* NO_IRQ */
  
-       hp = hvc_alloc(HVC_COOKIE, xencons_irq, &hvc_ops, 256);
+       hp = hvc_alloc(HVC_COOKIE, xencons_irq, ops, 256);
        if (IS_ERR(hp))
                return PTR_ERR(hp);
  
@@@ -161,7 -194,7 +195,7 @@@ void xen_console_resume(void
                rebind_evtchn_irq(xen_start_info->console.domU.evtchn, xencons_irq);
  }
  
- static void __exit xen_fini(void)
+ static void __exit xen_hvc_fini(void)
  {
        if (hvc)
                hvc_remove(hvc);
  
  static int xen_cons_init(void)
  {
+       struct hv_ops *ops;
        if (!xen_pv_domain())
                return 0;
  
-       hvc_instantiate(HVC_COOKIE, 0, &hvc_ops);
+       if (xen_initial_domain())
+               ops = &dom0_hvc_ops;
+       else
+               ops = &domU_hvc_ops;
+       hvc_instantiate(HVC_COOKIE, 0, ops);
        return 0;
  }
  
- module_init(xen_init);
- module_exit(xen_fini);
+ module_init(xen_hvc_init);
+ module_exit(xen_hvc_fini);
  console_initcall(xen_cons_init);
  
- static void raw_console_write(const char *str, int len)
- {
-       while(len > 0) {
-               int rc = HYPERVISOR_console_io(CONSOLEIO_write, len, (char *)str);
-               if (rc <= 0)
-                       break;
-               str += rc;
-               len -= rc;
-       }
- }
  #ifdef CONFIG_EARLY_PRINTK
  static void xenboot_write_console(struct console *console, const char *string,
                                  unsigned len)
        unsigned int linelen, off = 0;
        const char *pos;
  
-       raw_console_write(string, len);
+       dom0_write_console(0, string, len);
+       if (xen_initial_domain())
+               return;
  
-       write_console(0, "(early) ", 8);
+       domU_write_console(0, "(early) ", 8);
        while (off < len && NULL != (pos = strchr(string+off, '\n'))) {
                linelen = pos-string+off;
                if (off + linelen > len)
                        break;
-               write_console(0, string+off, linelen);
-               write_console(0, "\r\n", 2);
+               domU_write_console(0, string+off, linelen);
+               domU_write_console(0, "\r\n", 2);
                off += linelen + 1;
        }
        if (off < len)
-               write_console(0, string+off, len-off);
+               domU_write_console(0, string+off, len-off);
  }
  
  struct console xenboot_console = {
  
  void xen_raw_console_write(const char *str)
  {
-       raw_console_write(str, strlen(str));
+       dom0_write_console(0, str, strlen(str));
  }
  
  void xen_raw_printk(const char *fmt, ...)
index 630fb866476811b4b69cd7eab6f1cfce0aee346a,cb6e112989d87af8fcef85eb8985b31eb2b7aae6..458bb57914a32d57948ff425508f6b40ac2de7e1
@@@ -135,7 -135,7 +135,7 @@@ static void skb_entry_set_link(union sk
  static int skb_entry_is_link(const union skb_entry *list)
  {
        BUILD_BUG_ON(sizeof(list->skb) != sizeof(list->link));
 -      return ((unsigned long)list->skb < PAGE_OFFSET);
 +      return (unsigned long)list->skb < PAGE_OFFSET;
  }
  
  /*
@@@ -203,8 -203,8 +203,8 @@@ static void rx_refill_timeout(unsigned 
  
  static int netfront_tx_slot_available(struct netfront_info *np)
  {
 -      return ((np->tx.req_prod_pvt - np->tx.rsp_cons) <
 -              (TX_MAX_TARGET - MAX_SKB_FRAGS - 2));
 +      return (np->tx.req_prod_pvt - np->tx.rsp_cons) <
 +              (TX_MAX_TARGET - MAX_SKB_FRAGS - 2);
  }
  
  static void xennet_maybe_wake_tx(struct net_device *dev)
@@@ -1395,7 -1395,7 +1395,7 @@@ static int setup_netfront(struct xenbus
  }
  
  /* Common code used when first setting up, and when resuming. */
 -static int talk_to_backend(struct xenbus_device *dev,
 +static int talk_to_netback(struct xenbus_device *dev,
                           struct netfront_info *info)
  {
        const char *message;
@@@ -1545,7 -1545,7 +1545,7 @@@ static int xennet_connect(struct net_de
                return -ENODEV;
        }
  
 -      err = talk_to_backend(np->xbdev, np);
 +      err = talk_to_netback(np->xbdev, np);
        if (err)
                return err;
  
  /**
   * Callback received when the backend's state changes.
   */
 -static void backend_changed(struct xenbus_device *dev,
 +static void netback_changed(struct xenbus_device *dev,
                            enum xenbus_state backend_state)
  {
        struct netfront_info *np = dev_get_drvdata(&dev->dev);
        switch (backend_state) {
        case XenbusStateInitialising:
        case XenbusStateInitialised:
+       case XenbusStateReconfiguring:
+       case XenbusStateReconfigured:
        case XenbusStateConnected:
        case XenbusStateUnknown:
        case XenbusStateClosed:
@@@ -1801,7 -1803,7 +1803,7 @@@ static struct xenbus_driver netfront_dr
        .probe = netfront_probe,
        .remove = __devexit_p(xennet_remove),
        .resume = netfront_resume,
 -      .otherend_changed = backend_changed,
 +      .otherend_changed = netback_changed,
  };
  
  static int __init netif_init(void)
diff --combined drivers/pci/Makefile
index dcd7ace9221ea86d679f14f2557f874e15c53e4b,d5e27050c4e3b7687f271fec691568d0c2520750..f01e344cf4bd673c059044698f50896836d26fad
@@@ -65,4 -65,8 +65,6 @@@ obj-$(CONFIG_PCI_SYSCALL) += syscall.
  
  obj-$(CONFIG_PCI_STUB) += pci-stub.o
  
 -ifeq ($(CONFIG_PCI_DEBUG),y)
 -EXTRA_CFLAGS += -DDEBUG
 -endif
+ obj-$(CONFIG_XEN_PCIDEV_FRONTEND) += xen-pcifront.o
 +ccflags-$(CONFIG_PCI_DEBUG) := -DDEBUG
diff --combined drivers/pci/bus.c
index 172bf26e068006af26319e521283a2cb41b73ac6,69546e9213dd7727d7b0db8f9cd56d1772ea7431..5624db8c9ad0c511880ca16daf99f4dfb26c3769
@@@ -64,49 -64,6 +64,49 @@@ void pci_bus_remove_resources(struct pc
        }
  }
  
 +/*
 + * Find the highest-address bus resource below the cursor "res".  If the
 + * cursor is NULL, return the highest resource.
 + */
 +static struct resource *pci_bus_find_resource_prev(struct pci_bus *bus,
 +                                                 unsigned int type,
 +                                                 struct resource *res)
 +{
 +      struct resource *r, *prev = NULL;
 +      int i;
 +
 +      pci_bus_for_each_resource(bus, r, i) {
 +              if (!r)
 +                      continue;
 +
 +              if ((r->flags & IORESOURCE_TYPE_BITS) != type)
 +                      continue;
 +
 +              /* If this resource is at or past the cursor, skip it */
 +              if (res) {
 +                      if (r == res)
 +                              continue;
 +                      if (r->end > res->end)
 +                              continue;
 +                      if (r->end == res->end && r->start > res->start)
 +                              continue;
 +              }
 +
 +              if (!prev)
 +                      prev = r;
 +
 +              /*
 +               * A small resource is higher than a large one that ends at
 +               * the same address.
 +               */
 +              if (r->end > prev->end ||
 +                  (r->end == prev->end && r->start > prev->start))
 +                      prev = r;
 +      }
 +
 +      return prev;
 +}
 +
  /**
   * pci_bus_alloc_resource - allocate a resource from a parent bus
   * @bus: PCI bus
@@@ -132,10 -89,9 +132,10 @@@ pci_bus_alloc_resource(struct pci_bus *
                                          resource_size_t),
                void *alignf_data)
  {
 -      int i, ret = -ENOMEM;
 +      int ret = -ENOMEM;
        struct resource *r;
        resource_size_t max = -1;
 +      unsigned int type = res->flags & IORESOURCE_TYPE_BITS;
  
        type_mask |= IORESOURCE_IO | IORESOURCE_MEM;
  
        if (!(res->flags & IORESOURCE_MEM_64))
                max = PCIBIOS_MAX_MEM_32;
  
 -      pci_bus_for_each_resource(bus, r, i) {
 -              if (!r)
 -                      continue;
 -
 +      /* Look for space at highest addresses first */
 +      r = pci_bus_find_resource_prev(bus, type, NULL);
 +      for ( ; r; r = pci_bus_find_resource_prev(bus, type, r)) {
                /* type_mask must match */
                if ((res->flags ^ r->flags) & type_mask)
                        continue;
@@@ -342,6 -299,7 +342,7 @@@ void pci_walk_bus(struct pci_bus *top, 
        }
        up_read(&pci_bus_sem);
  }
+ EXPORT_SYMBOL_GPL(pci_walk_bus);
  
  EXPORT_SYMBOL(pci_bus_alloc_resource);
  EXPORT_SYMBOL_GPL(pci_bus_add_device);
diff --combined drivers/xen/events.c
index 347f17edad77bab15f1e5ca286a833a3a8392906,93e98ffe71aede661a5655adeeeb1cfb9ea6c371..97612f548a8e821c82821cb84218917dce136d03
@@@ -16,7 -16,7 +16,7 @@@
   *    (typically dom0).
   * 2. VIRQs, typically used for timers.  These are per-cpu events.
   * 3. IPIs.
-  * 4. Hardware interrupts. Not supported at present.
+  * 4. PIRQs - Hardware interrupts.
   *
   * Jeremy Fitzhardinge <jeremy@xensource.com>, XenSource Inc, 2007
   */
  #include <linux/string.h>
  #include <linux/bootmem.h>
  #include <linux/slab.h>
+ #include <linux/irqnr.h>
+ #include <linux/pci.h>
  
  #include <asm/desc.h>
  #include <asm/ptrace.h>
  #include <asm/irq.h>
  #include <asm/idle.h>
+ #include <asm/io_apic.h>
  #include <asm/sync_bitops.h>
+ #include <asm/xen/pci.h>
  #include <asm/xen/hypercall.h>
  #include <asm/xen/hypervisor.h>
  
@@@ -73,7 -77,8 +77,8 @@@ enum xen_irq_type 
   * event channel - irq->event channel mapping
   * cpu - cpu this event channel is bound to
   * index - type-specific information:
-  *    PIRQ - vector, with MSB being "needs EIO"
+  *    PIRQ - vector, with MSB being "needs EIO", or physical IRQ of the HVM
+  *           guest, or GSI (real passthrough IRQ) of the device.
   *    VIRQ - virq number
   *    IPI - IPI vector
   *    EVTCHN -
@@@ -88,21 -93,30 +93,30 @@@ struct irq_inf
                unsigned short virq;
                enum ipi_vector ipi;
                struct {
+                       unsigned short pirq;
                        unsigned short gsi;
-                       unsigned short vector;
+                       unsigned char vector;
+                       unsigned char flags;
                } pirq;
        } u;
  };
+ #define PIRQ_NEEDS_EOI        (1 << 0)
+ #define PIRQ_SHAREABLE        (1 << 1)
  
- static struct irq_info irq_info[NR_IRQS];
+ static struct irq_info *irq_info;
+ static int *pirq_to_irq;
+ static int nr_pirqs;
  
- static int evtchn_to_irq[NR_EVENT_CHANNELS] = {
-       [0 ... NR_EVENT_CHANNELS-1] = -1
- };
+ static int *evtchn_to_irq;
  struct cpu_evtchn_s {
        unsigned long bits[NR_EVENT_CHANNELS/BITS_PER_LONG];
  };
- static struct cpu_evtchn_s *cpu_evtchn_mask_p;
+ static __initdata struct cpu_evtchn_s init_evtchn_mask = {
+       .bits[0 ... (NR_EVENT_CHANNELS/BITS_PER_LONG)-1] = ~0ul,
+ };
+ static struct cpu_evtchn_s *cpu_evtchn_mask_p = &init_evtchn_mask;
  static inline unsigned long *cpu_evtchn_mask(int cpu)
  {
        return cpu_evtchn_mask_p[cpu].bits;
  
  static struct irq_chip xen_dynamic_chip;
  static struct irq_chip xen_percpu_chip;
+ static struct irq_chip xen_pirq_chip;
  
  /* Constructor for packed IRQ information. */
  static struct irq_info mk_unbound_info(void)
@@@ -138,11 -153,12 +153,12 @@@ static struct irq_info mk_virq_info(uns
                        .cpu = 0, .u.virq = virq };
  }
  
- static struct irq_info mk_pirq_info(unsigned short evtchn,
+ static struct irq_info mk_pirq_info(unsigned short evtchn, unsigned short pirq,
                                    unsigned short gsi, unsigned short vector)
  {
        return (struct irq_info) { .type = IRQT_PIRQ, .evtchn = evtchn,
-                       .cpu = 0, .u.pirq = { .gsi = gsi, .vector = vector } };
+                       .cpu = 0,
+                       .u.pirq = { .pirq = pirq, .gsi = gsi, .vector = vector } };
  }
  
  /*
@@@ -184,6 -200,16 +200,16 @@@ static unsigned virq_from_irq(unsigned 
        return info->u.virq;
  }
  
+ static unsigned pirq_from_irq(unsigned irq)
+ {
+       struct irq_info *info = info_for_irq(irq);
+       BUG_ON(info == NULL);
+       BUG_ON(info->type != IRQT_PIRQ);
+       return info->u.pirq.pirq;
+ }
  static unsigned gsi_from_irq(unsigned irq)
  {
        struct irq_info *info = info_for_irq(irq);
@@@ -225,6 -251,15 +251,15 @@@ static unsigned int cpu_from_evtchn(uns
        return ret;
  }
  
+ static bool pirq_needs_eoi(unsigned irq)
+ {
+       struct irq_info *info = info_for_irq(irq);
+       BUG_ON(info->type != IRQT_PIRQ);
+       return info->u.pirq.flags & PIRQ_NEEDS_EOI;
+ }
  static inline unsigned long active_evtchns(unsigned int cpu,
                                           struct shared_info *sh,
                                           unsigned int idx)
@@@ -261,7 -296,7 +296,7 @@@ static void init_evtchn_cpu_bindings(vo
        }
  #endif
  
 -      memset(cpu_evtchn_mask(0), ~0, sizeof(cpu_evtchn_mask(0)));
 +      memset(cpu_evtchn_mask(0), ~0, sizeof(struct cpu_evtchn_s));
  }
  
  static inline void clear_evtchn(int port)
@@@ -336,12 -371,40 +371,40 @@@ static void unmask_evtchn(int port
        put_cpu();
  }
  
+ static int get_nr_hw_irqs(void)
+ {
+       int ret = 1;
+ #ifdef CONFIG_X86_IO_APIC
+       ret = get_nr_irqs_gsi();
+ #endif
+       return ret;
+ }
+ /* callers of this function should make sure that PHYSDEVOP_get_nr_pirqs
+  * succeeded otherwise nr_pirqs won't hold the right value */
+ static int find_unbound_pirq(void)
+ {
+       int i;
+       for (i = nr_pirqs-1; i >= 0; i--) {
+               if (pirq_to_irq[i] < 0)
+                       return i;
+       }
+       return -1;
+ }
  static int find_unbound_irq(void)
  {
        struct irq_data *data;
        int irq, res;
+       int start = get_nr_hw_irqs();
  
-       for (irq = 0; irq < nr_irqs; irq++) {
+       if (start == nr_irqs)
+               goto no_irqs;
+       /* nr_irqs is a magic value. Must not use it.*/
+       for (irq = nr_irqs-1; irq > start; irq--) {
                data = irq_get_irq_data(irq);
                /* only 0->15 have init'd desc; handle irq > 16 */
                if (!data)
                        return irq;
        }
  
-       if (irq == nr_irqs)
-               panic("No available IRQ to bind to: increase nr_irqs!\n");
+       if (irq == start)
+               goto no_irqs;
  
        res = irq_alloc_desc_at(irq, 0);
  
                return -1;
  
        return irq;
+ no_irqs:
+       panic("No available IRQ to bind to: increase nr_irqs!\n");
+ }
+ static bool identity_mapped_irq(unsigned irq)
+ {
+       /* identity map all the hardware irqs */
+       return irq < get_nr_hw_irqs();
+ }
+ static void pirq_unmask_notify(int irq)
+ {
+       struct physdev_eoi eoi = { .irq = pirq_from_irq(irq) };
+       if (unlikely(pirq_needs_eoi(irq))) {
+               int rc = HYPERVISOR_physdev_op(PHYSDEVOP_eoi, &eoi);
+               WARN_ON(rc);
+       }
+ }
+ static void pirq_query_unmask(int irq)
+ {
+       struct physdev_irq_status_query irq_status;
+       struct irq_info *info = info_for_irq(irq);
+       BUG_ON(info->type != IRQT_PIRQ);
+       irq_status.irq = pirq_from_irq(irq);
+       if (HYPERVISOR_physdev_op(PHYSDEVOP_irq_status_query, &irq_status))
+               irq_status.flags = 0;
+       info->u.pirq.flags &= ~PIRQ_NEEDS_EOI;
+       if (irq_status.flags & XENIRQSTAT_needs_eoi)
+               info->u.pirq.flags |= PIRQ_NEEDS_EOI;
+ }
+ static bool probing_irq(int irq)
+ {
+       struct irq_desc *desc = irq_to_desc(irq);
+       return desc && desc->action == NULL;
+ }
+ static unsigned int startup_pirq(unsigned int irq)
+ {
+       struct evtchn_bind_pirq bind_pirq;
+       struct irq_info *info = info_for_irq(irq);
+       int evtchn = evtchn_from_irq(irq);
+       int rc;
+       BUG_ON(info->type != IRQT_PIRQ);
+       if (VALID_EVTCHN(evtchn))
+               goto out;
+       bind_pirq.pirq = pirq_from_irq(irq);
+       /* NB. We are happy to share unless we are probing. */
+       bind_pirq.flags = info->u.pirq.flags & PIRQ_SHAREABLE ?
+                                       BIND_PIRQ__WILL_SHARE : 0;
+       rc = HYPERVISOR_event_channel_op(EVTCHNOP_bind_pirq, &bind_pirq);
+       if (rc != 0) {
+               if (!probing_irq(irq))
+                       printk(KERN_INFO "Failed to obtain physical IRQ %d\n",
+                              irq);
+               return 0;
+       }
+       evtchn = bind_pirq.port;
+       pirq_query_unmask(irq);
+       evtchn_to_irq[evtchn] = irq;
+       bind_evtchn_to_cpu(evtchn, 0);
+       info->evtchn = evtchn;
+ out:
+       unmask_evtchn(evtchn);
+       pirq_unmask_notify(irq);
+       return 0;
+ }
+ static void shutdown_pirq(unsigned int irq)
+ {
+       struct evtchn_close close;
+       struct irq_info *info = info_for_irq(irq);
+       int evtchn = evtchn_from_irq(irq);
+       BUG_ON(info->type != IRQT_PIRQ);
+       if (!VALID_EVTCHN(evtchn))
+               return;
+       mask_evtchn(evtchn);
+       close.port = evtchn;
+       if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) != 0)
+               BUG();
+       bind_evtchn_to_cpu(evtchn, 0);
+       evtchn_to_irq[evtchn] = -1;
+       info->evtchn = 0;
+ }
+ static void enable_pirq(unsigned int irq)
+ {
+       startup_pirq(irq);
+ }
+ static void disable_pirq(unsigned int irq)
+ {
+ }
+ static void ack_pirq(unsigned int irq)
+ {
+       int evtchn = evtchn_from_irq(irq);
+       move_native_irq(irq);
+       if (VALID_EVTCHN(evtchn)) {
+               mask_evtchn(evtchn);
+               clear_evtchn(evtchn);
+       }
+ }
+ static void end_pirq(unsigned int irq)
+ {
+       int evtchn = evtchn_from_irq(irq);
+       struct irq_desc *desc = irq_to_desc(irq);
+       if (WARN_ON(!desc))
+               return;
+       if ((desc->status & (IRQ_DISABLED|IRQ_PENDING)) ==
+           (IRQ_DISABLED|IRQ_PENDING)) {
+               shutdown_pirq(irq);
+       } else if (VALID_EVTCHN(evtchn)) {
+               unmask_evtchn(evtchn);
+               pirq_unmask_notify(irq);
+       }
+ }
+ static int find_irq_by_gsi(unsigned gsi)
+ {
+       int irq;
+       for (irq = 0; irq < nr_irqs; irq++) {
+               struct irq_info *info = info_for_irq(irq);
+               if (info == NULL || info->type != IRQT_PIRQ)
+                       continue;
+               if (gsi_from_irq(irq) == gsi)
+                       return irq;
+       }
+       return -1;
+ }
+ int xen_allocate_pirq(unsigned gsi, int shareable, char *name)
+ {
+       return xen_map_pirq_gsi(gsi, gsi, shareable, name);
+ }
+ /* xen_map_pirq_gsi might allocate irqs from the top down, as a
+  * consequence don't assume that the irq number returned has a low value
+  * or can be used as a pirq number unless you know otherwise.
+  *
+  * One notable exception is when xen_map_pirq_gsi is called passing an
+  * hardware gsi as argument, in that case the irq number returned
+  * matches the gsi number passed as second argument.
+  *
+  * Note: We don't assign an event channel until the irq actually started
+  * up.  Return an existing irq if we've already got one for the gsi.
+  */
+ int xen_map_pirq_gsi(unsigned pirq, unsigned gsi, int shareable, char *name)
+ {
+       int irq = 0;
+       struct physdev_irq irq_op;
+       spin_lock(&irq_mapping_update_lock);
+       if ((pirq > nr_pirqs) || (gsi > nr_irqs)) {
+               printk(KERN_WARNING "xen_map_pirq_gsi: %s %s is incorrect!\n",
+                       pirq > nr_pirqs ? "nr_pirqs" :"",
+                       gsi > nr_irqs ? "nr_irqs" : "");
+               goto out;
+       }
+       irq = find_irq_by_gsi(gsi);
+       if (irq != -1) {
+               printk(KERN_INFO "xen_map_pirq_gsi: returning irq %d for gsi %u\n",
+                      irq, gsi);
+               goto out;       /* XXX need refcount? */
+       }
+       /* If we are a PV guest, we don't have GSIs (no ACPI passed). Therefore
+        * we are using the !xen_initial_domain() to drop in the function.*/
+       if (identity_mapped_irq(gsi) || (!xen_initial_domain() &&
+                               xen_pv_domain())) {
+               irq = gsi;
+               irq_alloc_desc_at(irq, 0);
+       } else
+               irq = find_unbound_irq();
+       set_irq_chip_and_handler_name(irq, &xen_pirq_chip,
+                                     handle_level_irq, name);
+       irq_op.irq = irq;
+       irq_op.vector = 0;
+       /* Only the privileged domain can do this. For non-priv, the pcifront
+        * driver provides a PCI bus that does the call to do exactly
+        * this in the priv domain. */
+       if (xen_initial_domain() &&
+           HYPERVISOR_physdev_op(PHYSDEVOP_alloc_irq_vector, &irq_op)) {
+               irq_free_desc(irq);
+               irq = -ENOSPC;
+               goto out;
+       }
+       irq_info[irq] = mk_pirq_info(0, pirq, gsi, irq_op.vector);
+       irq_info[irq].u.pirq.flags |= shareable ? PIRQ_SHAREABLE : 0;
+       pirq_to_irq[pirq] = irq;
+ out:
+       spin_unlock(&irq_mapping_update_lock);
+       return irq;
+ }
+ #ifdef CONFIG_PCI_MSI
+ #include <linux/msi.h>
+ #include "../pci/msi.h"
+ void xen_allocate_pirq_msi(char *name, int *irq, int *pirq)
+ {
+       spin_lock(&irq_mapping_update_lock);
+       *irq = find_unbound_irq();
+       if (*irq == -1)
+               goto out;
+       *pirq = find_unbound_pirq();
+       if (*pirq == -1)
+               goto out;
+       set_irq_chip_and_handler_name(*irq, &xen_pirq_chip,
+                                     handle_level_irq, name);
+       irq_info[*irq] = mk_pirq_info(0, *pirq, 0, 0);
+       pirq_to_irq[*pirq] = *irq;
+ out:
+       spin_unlock(&irq_mapping_update_lock);
+ }
+ int xen_create_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int type)
+ {
+       int irq = -1;
+       struct physdev_map_pirq map_irq;
+       int rc;
+       int pos;
+       u32 table_offset, bir;
+       memset(&map_irq, 0, sizeof(map_irq));
+       map_irq.domid = DOMID_SELF;
+       map_irq.type = MAP_PIRQ_TYPE_MSI;
+       map_irq.index = -1;
+       map_irq.pirq = -1;
+       map_irq.bus = dev->bus->number;
+       map_irq.devfn = dev->devfn;
+       if (type == PCI_CAP_ID_MSIX) {
+               pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
+               pci_read_config_dword(dev, msix_table_offset_reg(pos),
+                                       &table_offset);
+               bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK);
+               map_irq.table_base = pci_resource_start(dev, bir);
+               map_irq.entry_nr = msidesc->msi_attrib.entry_nr;
+       }
+       spin_lock(&irq_mapping_update_lock);
+       irq = find_unbound_irq();
+       if (irq == -1)
+               goto out;
+       rc = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq);
+       if (rc) {
+               printk(KERN_WARNING "xen map irq failed %d\n", rc);
+               irq_free_desc(irq);
+               irq = -1;
+               goto out;
+       }
+       irq_info[irq] = mk_pirq_info(0, map_irq.pirq, 0, map_irq.index);
+       set_irq_chip_and_handler_name(irq, &xen_pirq_chip,
+                       handle_level_irq,
+                       (type == PCI_CAP_ID_MSIX) ? "msi-x":"msi");
+ out:
+       spin_unlock(&irq_mapping_update_lock);
+       return irq;
+ }
+ #endif
+ int xen_destroy_irq(int irq)
+ {
+       struct irq_desc *desc;
+       struct physdev_unmap_pirq unmap_irq;
+       struct irq_info *info = info_for_irq(irq);
+       int rc = -ENOENT;
+       spin_lock(&irq_mapping_update_lock);
+       desc = irq_to_desc(irq);
+       if (!desc)
+               goto out;
+       if (xen_initial_domain()) {
+               unmap_irq.pirq = info->u.pirq.gsi;
+               unmap_irq.domid = DOMID_SELF;
+               rc = HYPERVISOR_physdev_op(PHYSDEVOP_unmap_pirq, &unmap_irq);
+               if (rc) {
+                       printk(KERN_WARNING "unmap irq failed %d\n", rc);
+                       goto out;
+               }
+       }
+       irq_info[irq] = mk_unbound_info();
+       irq_free_desc(irq);
+ out:
+       spin_unlock(&irq_mapping_update_lock);
+       return rc;
+ }
+ int xen_vector_from_irq(unsigned irq)
+ {
+       return vector_from_irq(irq);
+ }
+ int xen_gsi_from_irq(unsigned irq)
+ {
+       return gsi_from_irq(irq);
  }
  
  int bind_evtchn_to_irq(unsigned int evtchn)
                irq = find_unbound_irq();
  
                set_irq_chip_and_handler_name(irq, &xen_dynamic_chip,
 -                                            handle_edge_irq, "event");
 +                                            handle_fasteoi_irq, "event");
  
                evtchn_to_irq[evtchn] = irq;
                irq_info[irq] = mk_evtchn_info(evtchn);
@@@ -425,7 -839,7 +839,7 @@@ static int bind_ipi_to_irq(unsigned in
  }
  
  
static int bind_virq_to_irq(unsigned int virq, unsigned int cpu)
+ int bind_virq_to_irq(unsigned int virq, unsigned int cpu)
  {
        struct evtchn_bind_virq bind_virq;
        int evtchn, irq;
        irq = per_cpu(virq_to_irq, cpu)[virq];
  
        if (irq == -1) {
 +              irq = find_unbound_irq();
 +
 +              set_irq_chip_and_handler_name(irq, &xen_percpu_chip,
 +                                            handle_percpu_irq, "virq");
 +
                bind_virq.virq = virq;
                bind_virq.vcpu = cpu;
                if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq,
                        BUG();
                evtchn = bind_virq.port;
  
 -              irq = find_unbound_irq();
 -
 -              set_irq_chip_and_handler_name(irq, &xen_percpu_chip,
 -                                            handle_percpu_irq, "virq");
 -
                evtchn_to_irq[evtchn] = irq;
                irq_info[irq] = mk_virq_info(evtchn, virq);
  
@@@ -578,75 -992,41 +992,75 @@@ irqreturn_t xen_debug_interrupt(int irq
  {
        struct shared_info *sh = HYPERVISOR_shared_info;
        int cpu = smp_processor_id();
 +      unsigned long *cpu_evtchn = cpu_evtchn_mask(cpu);
        int i;
        unsigned long flags;
        static DEFINE_SPINLOCK(debug_lock);
 +      struct vcpu_info *v;
  
        spin_lock_irqsave(&debug_lock, flags);
  
 -      printk("vcpu %d\n  ", cpu);
 +      printk("\nvcpu %d\n  ", cpu);
  
        for_each_online_cpu(i) {
 -              struct vcpu_info *v = per_cpu(xen_vcpu, i);
 -              printk("%d: masked=%d pending=%d event_sel %08lx\n  ", i,
 -                      (get_irq_regs() && i == cpu) ? xen_irqs_disabled(get_irq_regs()) : v->evtchn_upcall_mask,
 -                      v->evtchn_upcall_pending,
 -                      v->evtchn_pending_sel);
 +              int pending;
 +              v = per_cpu(xen_vcpu, i);
 +              pending = (get_irq_regs() && i == cpu)
 +                      ? xen_irqs_disabled(get_irq_regs())
 +                      : v->evtchn_upcall_mask;
 +              printk("%d: masked=%d pending=%d event_sel %0*lx\n  ", i,
 +                     pending, v->evtchn_upcall_pending,
 +                     (int)(sizeof(v->evtchn_pending_sel)*2),
 +                     v->evtchn_pending_sel);
 +      }
 +      v = per_cpu(xen_vcpu, cpu);
 +
 +      printk("\npending:\n   ");
 +      for (i = ARRAY_SIZE(sh->evtchn_pending)-1; i >= 0; i--)
 +              printk("%0*lx%s", (int)sizeof(sh->evtchn_pending[0])*2,
 +                     sh->evtchn_pending[i],
 +                     i % 8 == 0 ? "\n   " : " ");
 +      printk("\nglobal mask:\n   ");
 +      for (i = ARRAY_SIZE(sh->evtchn_mask)-1; i >= 0; i--)
 +              printk("%0*lx%s",
 +                     (int)(sizeof(sh->evtchn_mask[0])*2),
 +                     sh->evtchn_mask[i],
 +                     i % 8 == 0 ? "\n   " : " ");
 +
 +      printk("\nglobally unmasked:\n   ");
 +      for (i = ARRAY_SIZE(sh->evtchn_mask)-1; i >= 0; i--)
 +              printk("%0*lx%s", (int)(sizeof(sh->evtchn_mask[0])*2),
 +                     sh->evtchn_pending[i] & ~sh->evtchn_mask[i],
 +                     i % 8 == 0 ? "\n   " : " ");
 +
 +      printk("\nlocal cpu%d mask:\n   ", cpu);
 +      for (i = (NR_EVENT_CHANNELS/BITS_PER_LONG)-1; i >= 0; i--)
 +              printk("%0*lx%s", (int)(sizeof(cpu_evtchn[0])*2),
 +                     cpu_evtchn[i],
 +                     i % 8 == 0 ? "\n   " : " ");
 +
 +      printk("\nlocally unmasked:\n   ");
 +      for (i = ARRAY_SIZE(sh->evtchn_mask)-1; i >= 0; i--) {
 +              unsigned long pending = sh->evtchn_pending[i]
 +                      & ~sh->evtchn_mask[i]
 +                      & cpu_evtchn[i];
 +              printk("%0*lx%s", (int)(sizeof(sh->evtchn_mask[0])*2),
 +                     pending, i % 8 == 0 ? "\n   " : " ");
        }
 -      printk("pending:\n   ");
 -      for(i = ARRAY_SIZE(sh->evtchn_pending)-1; i >= 0; i--)
 -              printk("%08lx%s", sh->evtchn_pending[i],
 -                      i % 8 == 0 ? "\n   " : " ");
 -      printk("\nmasks:\n   ");
 -      for(i = ARRAY_SIZE(sh->evtchn_mask)-1; i >= 0; i--)
 -              printk("%08lx%s", sh->evtchn_mask[i],
 -                      i % 8 == 0 ? "\n   " : " ");
 -
 -      printk("\nunmasked:\n   ");
 -      for(i = ARRAY_SIZE(sh->evtchn_mask)-1; i >= 0; i--)
 -              printk("%08lx%s", sh->evtchn_pending[i] & ~sh->evtchn_mask[i],
 -                      i % 8 == 0 ? "\n   " : " ");
  
        printk("\npending list:\n");
 -      for(i = 0; i < NR_EVENT_CHANNELS; i++) {
 +      for (i = 0; i < NR_EVENT_CHANNELS; i++) {
                if (sync_test_bit(i, sh->evtchn_pending)) {
 -                      printk("  %d: event %d -> irq %d\n",
 +                      int word_idx = i / BITS_PER_LONG;
 +                      printk("  %d: event %d -> irq %d%s%s%s\n",
                               cpu_from_evtchn(i), i,
 -                             evtchn_to_irq[i]);
 +                             evtchn_to_irq[i],
 +                             sync_test_bit(word_idx, &v->evtchn_pending_sel)
 +                                           ? "" : " l2-clear",
 +                             !sync_test_bit(i, sh->evtchn_mask)
 +                                           ? "" : " globally-masked",
 +                             sync_test_bit(i, cpu_evtchn)
 +                                           ? "" : " locally-masked");
                }
        }
  
@@@ -697,9 -1077,6 +1111,9 @@@ static void __xen_evtchn_do_upcall(void
                                int irq = evtchn_to_irq[port];
                                struct irq_desc *desc;
  
 +                              mask_evtchn(port);
 +                              clear_evtchn(port);
 +
                                if (irq != -1) {
                                        desc = irq_to_desc(irq);
                                        if (desc)
@@@ -837,10 -1214,10 +1251,10 @@@ static void ack_dynirq(unsigned int irq
  {
        int evtchn = evtchn_from_irq(irq);
  
 -      move_native_irq(irq);
 +      move_masked_irq(irq);
  
        if (VALID_EVTCHN(evtchn))
 -              clear_evtchn(evtchn);
 +              unmask_evtchn(evtchn);
  }
  
  static int retrigger_dynirq(unsigned int irq)
@@@ -928,7 -1305,7 +1342,7 @@@ void xen_clear_irq_pending(int irq
        if (VALID_EVTCHN(evtchn))
                clear_evtchn(evtchn);
  }
+ EXPORT_SYMBOL(xen_clear_irq_pending);
  void xen_set_irq_pending(int irq)
  {
        int evtchn = evtchn_from_irq(irq);
@@@ -948,9 -1325,9 +1362,9 @@@ bool xen_test_irq_pending(int irq
        return ret;
  }
  
- /* Poll waiting for an irq to become pending.  In the usual case, the
-    irq will be disabled so it won't deliver an interrupt. */
- void xen_poll_irq(int irq)
+ /* Poll waiting for an irq to become pending with timeout.  In the usual case,
+  * the irq will be disabled so it won't deliver an interrupt. */
+ void xen_poll_irq_timeout(int irq, u64 timeout)
  {
        evtchn_port_t evtchn = evtchn_from_irq(irq);
  
                struct sched_poll poll;
  
                poll.nr_ports = 1;
-               poll.timeout = 0;
+               poll.timeout = timeout;
                set_xen_guest_handle(poll.ports, &evtchn);
  
                if (HYPERVISOR_sched_op(SCHEDOP_poll, &poll) != 0)
                        BUG();
        }
  }
+ EXPORT_SYMBOL(xen_poll_irq_timeout);
+ /* Poll waiting for an irq to become pending.  In the usual case, the
+  * irq will be disabled so it won't deliver an interrupt. */
+ void xen_poll_irq(int irq)
+ {
+       xen_poll_irq_timeout(irq, 0 /* no timeout */);
+ }
  
  void xen_irq_resume(void)
  {
@@@ -996,11 -1380,31 +1417,31 @@@ static struct irq_chip xen_dynamic_chi
        .mask           = disable_dynirq,
        .unmask         = enable_dynirq,
  
 -      .ack            = ack_dynirq,
 +      .eoi            = ack_dynirq,
        .set_affinity   = set_affinity_irq,
        .retrigger      = retrigger_dynirq,
  };
  
+ static struct irq_chip xen_pirq_chip __read_mostly = {
+       .name           = "xen-pirq",
+       .startup        = startup_pirq,
+       .shutdown       = shutdown_pirq,
+       .enable         = enable_pirq,
+       .unmask         = enable_pirq,
+       .disable        = disable_pirq,
+       .mask           = disable_pirq,
+       .ack            = ack_pirq,
+       .end            = end_pirq,
+       .set_affinity   = set_affinity_irq,
+       .retrigger      = retrigger_dynirq,
+ };
  static struct irq_chip xen_percpu_chip __read_mostly = {
        .name           = "xen-percpu",
  
@@@ -1051,11 -1455,32 +1492,32 @@@ void xen_callback_vector(void) {
  
  void __init xen_init_IRQ(void)
  {
-       int i;
+       int i, rc;
+       struct physdev_nr_pirqs op_nr_pirqs;
  
        cpu_evtchn_mask_p = kcalloc(nr_cpu_ids, sizeof(struct cpu_evtchn_s),
                                    GFP_KERNEL);
-       BUG_ON(cpu_evtchn_mask_p == NULL);
+       irq_info = kcalloc(nr_irqs, sizeof(*irq_info), GFP_KERNEL);
+       rc = HYPERVISOR_physdev_op(PHYSDEVOP_get_nr_pirqs, &op_nr_pirqs);
+       if (rc < 0) {
+               nr_pirqs = nr_irqs;
+               if (rc != -ENOSYS)
+                       printk(KERN_WARNING "PHYSDEVOP_get_nr_pirqs returned rc=%d\n", rc);
+       } else {
+               if (xen_pv_domain() && !xen_initial_domain())
+                       nr_pirqs = max((int)op_nr_pirqs.nr_pirqs, nr_irqs);
+               else
+                       nr_pirqs = op_nr_pirqs.nr_pirqs;
+       }
+       pirq_to_irq = kcalloc(nr_pirqs, sizeof(*pirq_to_irq), GFP_KERNEL);
+       for (i = 0; i < nr_pirqs; i++)
+               pirq_to_irq[i] = -1;
+       evtchn_to_irq = kcalloc(NR_EVENT_CHANNELS, sizeof(*evtchn_to_irq),
+                                   GFP_KERNEL);
+       for (i = 0; i < NR_EVENT_CHANNELS; i++)
+               evtchn_to_irq[i] = -1;
  
        init_evtchn_cpu_bindings();
  
        if (xen_hvm_domain()) {
                xen_callback_vector();
                native_init_IRQ();
+               /* pci_xen_hvm_init must be called after native_init_IRQ so that
+                * __acpi_register_gsi can point at the right function */
+               pci_xen_hvm_init();
        } else {
                irq_ctx_init(smp_processor_id());
+               if (xen_initial_domain())
+                       xen_setup_pirqs();
        }
  }
index 132939f3602014abb1c9c62e3c97236fd7d45e02,d242610597c06445d0a311afed9b2bbb929728fe..deb9c4ba3a938b2d80bf72a0a4ae55799794c7f2
  
  
  int xen_store_evtchn;
 -EXPORT_SYMBOL(xen_store_evtchn);
 +EXPORT_SYMBOL_GPL(xen_store_evtchn);
  
  struct xenstore_domain_interface *xen_store_interface;
 +EXPORT_SYMBOL_GPL(xen_store_interface);
 +
  static unsigned long xen_store_mfn;
  
  static BLOCKING_NOTIFIER_HEAD(xenstore_chain);
@@@ -803,6 -801,7 +803,7 @@@ device_initcall(xenbus_probe_initcall)
  static int __init xenbus_init(void)
  {
        int err = 0;
+       unsigned long page = 0;
  
        DPRINTK("");
  
         * Domain0 doesn't have a store_evtchn or store_mfn yet.
         */
        if (xen_initial_domain()) {
-               /* dom0 not yet supported */
+               struct evtchn_alloc_unbound alloc_unbound;
+               /* Allocate Xenstore page */
+               page = get_zeroed_page(GFP_KERNEL);
+               if (!page)
+                       goto out_error;
+               xen_store_mfn = xen_start_info->store_mfn =
+                       pfn_to_mfn(virt_to_phys((void *)page) >>
+                                  PAGE_SHIFT);
+               /* Next allocate a local port which xenstored can bind to */
+               alloc_unbound.dom        = DOMID_SELF;
+               alloc_unbound.remote_dom = 0;
+               err = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound,
+                                                 &alloc_unbound);
+               if (err == -ENOSYS)
+                       goto out_error;
+               BUG_ON(err);
+               xen_store_evtchn = xen_start_info->store_evtchn =
+                       alloc_unbound.port;
+               xen_store_interface = mfn_to_virt(xen_store_mfn);
        } else {
                if (xen_hvm_domain()) {
                        uint64_t v = 0;
        bus_unregister(&xenbus_frontend.bus);
  
    out_error:
+       if (page != 0)
+               free_page(page);
        return err;
  }