diff options
Diffstat (limited to 'arch/ia64')
120 files changed, 6110 insertions, 686 deletions
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 48e496f..7fa8f61 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -7,6 +7,8 @@ mainmenu "IA-64 Linux Kernel Configuration" source "init/Kconfig" +source "kernel/Kconfig.freezer" + menu "Processor type and features" config IA64 @@ -21,6 +23,7 @@ config IA64 select HAVE_KRETPROBES select HAVE_DMA_ATTRS select HAVE_KVM + select HAVE_ARCH_TRACEHOOK default y help The Itanium Processor Family is Intel's 64-bit successor to @@ -60,14 +63,6 @@ config RWSEM_XCHGADD_ALGORITHM bool default y -config ARCH_HAS_ILOG2_U32 - bool - default n - -config ARCH_HAS_ILOG2_U64 - bool - default n - config HUGETLB_PAGE_SIZE_VARIABLE bool depends on HUGETLB_PAGE @@ -104,7 +99,7 @@ config GENERIC_IOMAP bool default y -config SCHED_NO_NO_OMIT_FRAME_POINTER +config SCHED_OMIT_FRAME_POINTER bool default y @@ -116,6 +111,33 @@ config AUDIT_ARCH bool default y +menuconfig PARAVIRT_GUEST + bool "Paravirtualized guest support" + help + Say Y here to get to see options related to running Linux under + various hypervisors. This option alone does not add any kernel code. + + If you say N, all options in this submenu will be skipped and disabled. + +if PARAVIRT_GUEST + +config PARAVIRT + bool "Enable paravirtualization code" + depends on PARAVIRT_GUEST + default y + bool + default y + help + This changes the kernel so it can modify itself when it is run + under a hypervisor, potentially improving performance significantly + over full virtualization. However, when run without a hypervisor + the kernel is theoretically slower and slightly larger. + + +source "arch/ia64/xen/Kconfig" + +endif + choice prompt "System type" default IA64_GENERIC @@ -125,6 +147,8 @@ config IA64_GENERIC select NUMA select ACPI_NUMA select SWIOTLB + select PCI_MSI + select DMAR help This selects the system type of your hardware. A "generic" kernel will run on any supported IA-64 system. However, if you configure @@ -132,11 +156,13 @@ config IA64_GENERIC generic For any supported IA-64 system DIG-compliant For DIG ("Developer's Interface Guide") compliant systems + DIG+Intel+IOMMU For DIG systems with Intel IOMMU HP-zx1/sx1000 For HP systems HP-zx1/sx1000+swiotlb For HP systems with (broken) DMA-constrained devices. SGI-SN2 For SGI Altix systems SGI-UV For SGI UV systems Ski-simulator For the HP simulator <http://www.hpl.hp.com/research/linux/ski/> + Xen-domU For xen domU system If you don't know what to do, choose "generic". @@ -144,6 +170,11 @@ config IA64_DIG bool "DIG-compliant" select SWIOTLB +config IA64_DIG_VTD + bool "DIG+Intel+IOMMU" + select DMAR + select PCI_MSI + config IA64_HP_ZX1 bool "HP-zx1/sx1000" help @@ -187,6 +218,10 @@ config IA64_HP_SIM bool "Ski-simulator" select SWIOTLB +config IA64_XEN_GUEST + bool "Xen guest" + depends on XEN + endchoice choice @@ -551,7 +586,7 @@ source "fs/Kconfig.binfmt" endmenu -menu "Power management and ACPI" +menu "Power management and ACPI options" source "kernel/power/Kconfig" @@ -589,6 +624,16 @@ source "drivers/pci/hotplug/Kconfig" source "drivers/pcmcia/Kconfig" +config DMAR + bool "Support for DMA Remapping Devices (EXPERIMENTAL)" + depends on IA64_GENERIC && ACPI && EXPERIMENTAL + help + DMA remapping (DMAR) devices support enables independent address + translations for Direct Memory Access (DMA) from devices. + These DMA remapping devices are reported via ACPI tables + and include PCI device scope covered by these DMA + remapping devices. + endmenu endif @@ -597,6 +642,8 @@ source "net/Kconfig" source "drivers/Kconfig" +source "arch/ia64/hp/sim/Kconfig" + config MSPEC tristate "Memory special operations driver" depends on IA64 @@ -608,6 +655,12 @@ config MSPEC source "fs/Kconfig" +source "arch/ia64/Kconfig.debug" + +source "security/Kconfig" + +source "crypto/Kconfig" + source "arch/ia64/kvm/Kconfig" source "lib/Kconfig" @@ -634,11 +687,3 @@ config IRQ_PER_CPU config IOMMU_HELPER def_bool (IA64_HP_ZX1 || IA64_HP_ZX1_SWIOTLB || IA64_GENERIC || SWIOTLB) - -source "arch/ia64/hp/sim/Kconfig" - -source "arch/ia64/Kconfig.debug" - -source "security/Kconfig" - -source "crypto/Kconfig" diff --git a/arch/ia64/Makefile b/arch/ia64/Makefile index 905d25b..58a7e46a 100644 --- a/arch/ia64/Makefile +++ b/arch/ia64/Makefile @@ -53,12 +53,15 @@ libs-y += arch/ia64/lib/ core-y += arch/ia64/kernel/ arch/ia64/mm/ core-$(CONFIG_IA32_SUPPORT) += arch/ia64/ia32/ core-$(CONFIG_IA64_DIG) += arch/ia64/dig/ +core-$(CONFIG_IA64_DIG_VTD) += arch/ia64/dig/ core-$(CONFIG_IA64_GENERIC) += arch/ia64/dig/ core-$(CONFIG_IA64_HP_ZX1) += arch/ia64/dig/ core-$(CONFIG_IA64_HP_ZX1_SWIOTLB) += arch/ia64/dig/ +core-$(CONFIG_IA64_XEN_GUEST) += arch/ia64/dig/ core-$(CONFIG_IA64_SGI_SN2) += arch/ia64/sn/ core-$(CONFIG_IA64_SGI_UV) += arch/ia64/uv/ core-$(CONFIG_KVM) += arch/ia64/kvm/ +core-$(CONFIG_XEN) += arch/ia64/xen/ drivers-$(CONFIG_PCI) += arch/ia64/pci/ drivers-$(CONFIG_IA64_HP_SIM) += arch/ia64/hp/sim/ diff --git a/arch/ia64/configs/generic_defconfig b/arch/ia64/configs/generic_defconfig index 9f48397..27eb676 100644 --- a/arch/ia64/configs/generic_defconfig +++ b/arch/ia64/configs/generic_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.27-rc1 -# Mon Aug 4 15:38:01 2008 +# Linux kernel version: 2.6.28-rc7 +# Mon Dec 8 08:12:07 2008 # CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" @@ -26,6 +26,7 @@ CONFIG_LOG_BUF_SHIFT=20 CONFIG_CGROUPS=y # CONFIG_CGROUP_DEBUG is not set # CONFIG_CGROUP_NS is not set +# CONFIG_CGROUP_FREEZER is not set # CONFIG_CGROUP_DEVICE is not set CONFIG_CPUSETS=y # CONFIG_GROUP_SCHED is not set @@ -46,7 +47,6 @@ CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SYSCTL=y # CONFIG_EMBEDDED is not set CONFIG_SYSCTL_SYSCALL=y -CONFIG_SYSCTL_SYSCALL_CHECK=y CONFIG_KALLSYMS=y CONFIG_KALLSYMS_ALL=y # CONFIG_KALLSYMS_EXTRA_PASS is not set @@ -63,7 +63,9 @@ CONFIG_SIGNALFD=y CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y +CONFIG_AIO=y CONFIG_VM_EVENT_COUNTERS=y +CONFIG_PCI_QUIRKS=y CONFIG_SLUB_DEBUG=y # CONFIG_SLAB is not set CONFIG_SLUB=y @@ -72,15 +74,11 @@ CONFIG_SLUB=y # CONFIG_MARKERS is not set CONFIG_HAVE_OPROFILE=y # CONFIG_KPROBES is not set -# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set -# CONFIG_HAVE_IOREMAP_PROT is not set CONFIG_HAVE_KPROBES=y CONFIG_HAVE_KRETPROBES=y -# CONFIG_HAVE_ARCH_TRACEHOOK is not set +CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_USE_GENERIC_SMP_HELPERS=y -# CONFIG_HAVE_CLK is not set -CONFIG_PROC_PAGE_MONITOR=y # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set CONFIG_SLABINFO=y CONFIG_RT_MUTEXES=y @@ -113,6 +111,7 @@ CONFIG_DEFAULT_AS=y # CONFIG_DEFAULT_NOOP is not set CONFIG_DEFAULT_IOSCHED="anticipatory" CONFIG_CLASSIC_RCU=y +# CONFIG_FREEZER is not set # # Processor type and features @@ -125,8 +124,6 @@ CONFIG_MMU=y CONFIG_SWIOTLB=y CONFIG_IOMMU_HELPER=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y -# CONFIG_ARCH_HAS_ILOG2_U32 is not set -# CONFIG_ARCH_HAS_ILOG2_U64 is not set CONFIG_HUGETLB_PAGE_SIZE_VARIABLE=y CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_CALIBRATE_DELAY=y @@ -139,13 +136,16 @@ CONFIG_GENERIC_IOMAP=y CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y CONFIG_IA64_UNCACHED_ALLOCATOR=y CONFIG_AUDIT_ARCH=y +# CONFIG_PARAVIRT_GUEST is not set CONFIG_IA64_GENERIC=y # CONFIG_IA64_DIG is not set +# CONFIG_IA64_DIG_VTD is not set # CONFIG_IA64_HP_ZX1 is not set # CONFIG_IA64_HP_ZX1_SWIOTLB is not set # CONFIG_IA64_SGI_SN2 is not set # CONFIG_IA64_SGI_UV is not set # CONFIG_IA64_HP_SIM is not set +# CONFIG_IA64_XEN_GUEST is not set # CONFIG_ITANIUM is not set CONFIG_MCKINLEY=y # CONFIG_IA64_PAGE_SIZE_4KB is not set @@ -182,16 +182,17 @@ CONFIG_DISCONTIGMEM_MANUAL=y CONFIG_DISCONTIGMEM=y CONFIG_FLAT_NODE_MEM_MAP=y CONFIG_NEED_MULTIPLE_NODES=y -# CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 CONFIG_MIGRATION=y CONFIG_RESOURCES_64BIT=y +CONFIG_PHYS_ADDR_T_64BIT=y CONFIG_ZONE_DMA_FLAG=1 CONFIG_BOUNCE=y CONFIG_NR_QUICK=1 CONFIG_VIRT_TO_BUS=y +CONFIG_UNEVICTABLE_LRU=y CONFIG_MMU_NOTIFIER=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y CONFIG_ARCH_DISCONTIGMEM_ENABLE=y @@ -231,10 +232,12 @@ CONFIG_EFI_VARS=y CONFIG_EFI_PCDP=y CONFIG_DMIID=y CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +# CONFIG_HAVE_AOUT is not set CONFIG_BINFMT_MISC=m # -# Power management and ACPI +# Power management and ACPI options # CONFIG_PM=y # CONFIG_PM_DEBUG is not set @@ -246,7 +249,6 @@ CONFIG_ACPI_PROC_EVENT=y CONFIG_ACPI_BUTTON=m CONFIG_ACPI_FAN=m CONFIG_ACPI_DOCK=y -# CONFIG_ACPI_BAY is not set CONFIG_ACPI_PROCESSOR=m CONFIG_ACPI_HOTPLUG_CPU=y CONFIG_ACPI_THERMAL=m @@ -254,9 +256,7 @@ CONFIG_ACPI_NUMA=y # CONFIG_ACPI_CUSTOM_DSDT is not set CONFIG_ACPI_BLACKLIST_YEAR=0 # CONFIG_ACPI_DEBUG is not set -CONFIG_ACPI_EC=y # CONFIG_ACPI_PCI_SLOT is not set -CONFIG_ACPI_POWER=y CONFIG_ACPI_SYSTEM=y CONFIG_ACPI_CONTAINER=m @@ -273,7 +273,7 @@ CONFIG_PCI_DOMAINS=y CONFIG_PCI_SYSCALL=y # CONFIG_PCIEPORTBUS is not set CONFIG_ARCH_SUPPORTS_MSI=y -# CONFIG_PCI_MSI is not set +CONFIG_PCI_MSI=y CONFIG_PCI_LEGACY=y # CONFIG_PCI_DEBUG is not set CONFIG_HOTPLUG_PCI=m @@ -284,6 +284,7 @@ CONFIG_HOTPLUG_PCI_ACPI=m # CONFIG_HOTPLUG_PCI_SHPC is not set # CONFIG_HOTPLUG_PCI_SGI is not set # CONFIG_PCCARD is not set +CONFIG_DMAR=y CONFIG_NET=y # @@ -331,6 +332,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # CONFIG_TIPC is not set # CONFIG_ATM is not set # CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set # CONFIG_VLAN_8021Q is not set # CONFIG_DECNET is not set # CONFIG_LLC2 is not set @@ -351,11 +353,10 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # CONFIG_IRDA is not set # CONFIG_BT is not set # CONFIG_AF_RXRPC is not set - -# -# Wireless -# +# CONFIG_PHONET is not set +CONFIG_WIRELESS=y # CONFIG_CFG80211 is not set +CONFIG_WIRELESS_OLD_REGULATORY=y # CONFIG_WIRELESS_EXT is not set # CONFIG_MAC80211 is not set # CONFIG_IEEE80211 is not set @@ -383,7 +384,7 @@ CONFIG_PROC_EVENTS=y # CONFIG_MTD is not set # CONFIG_PARPORT is not set CONFIG_PNP=y -# CONFIG_PNP_DEBUG is not set +# CONFIG_PNP_DEBUG_MESSAGES is not set # # Protocols @@ -417,10 +418,9 @@ CONFIG_SGI_XP=m # CONFIG_HP_ILO is not set CONFIG_SGI_GRU=m # CONFIG_SGI_GRU_DEBUG is not set +# CONFIG_C2PORT is not set CONFIG_HAVE_IDE=y CONFIG_IDE=y -CONFIG_IDE_MAX_HWIFS=4 -CONFIG_BLK_DEV_IDE=y # # Please see Documentation/ide/ide.txt for help/info on IDE drives @@ -428,12 +428,12 @@ CONFIG_BLK_DEV_IDE=y CONFIG_IDE_TIMINGS=y CONFIG_IDE_ATAPI=y # CONFIG_BLK_DEV_IDE_SATA is not set -CONFIG_BLK_DEV_IDEDISK=y -# CONFIG_IDEDISK_MULTI_MODE is not set +CONFIG_IDE_GD=y +CONFIG_IDE_GD_ATA=y +# CONFIG_IDE_GD_ATAPI is not set CONFIG_BLK_DEV_IDECD=y CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS=y # CONFIG_BLK_DEV_IDETAPE is not set -CONFIG_BLK_DEV_IDEFLOPPY=y CONFIG_BLK_DEV_IDESCSI=m # CONFIG_BLK_DEV_IDEACPI is not set # CONFIG_IDE_TASK_IOCTL is not set @@ -703,6 +703,9 @@ CONFIG_TULIP=m # CONFIG_IBM_NEW_EMAC_RGMII is not set # CONFIG_IBM_NEW_EMAC_TAH is not set # CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set CONFIG_NET_PCI=y # CONFIG_PCNET32 is not set # CONFIG_AMD8111_ETH is not set @@ -723,11 +726,11 @@ CONFIG_E100=m # CONFIG_TLAN is not set # CONFIG_VIA_RHINE is not set # CONFIG_SC92031 is not set +# CONFIG_ATL2 is not set CONFIG_NETDEV_1000=y # CONFIG_ACENIC is not set # CONFIG_DL2K is not set CONFIG_E1000=y -# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set # CONFIG_E1000E is not set # CONFIG_IP1000 is not set CONFIG_IGB=y @@ -745,18 +748,22 @@ CONFIG_TIGON3=y # CONFIG_QLA3XXX is not set # CONFIG_ATL1 is not set # CONFIG_ATL1E is not set +# CONFIG_JME is not set CONFIG_NETDEV_10000=y # CONFIG_CHELSIO_T1 is not set # CONFIG_CHELSIO_T3 is not set +# CONFIG_ENIC is not set # CONFIG_IXGBE is not set # CONFIG_IXGB is not set # CONFIG_S2IO is not set # CONFIG_MYRI10GE is not set # CONFIG_NETXEN_NIC is not set # CONFIG_NIU is not set +# CONFIG_MLX4_EN is not set # CONFIG_MLX4_CORE is not set # CONFIG_TEHUTI is not set # CONFIG_BNX2X is not set +# CONFIG_QLGE is not set # CONFIG_SFC is not set # CONFIG_TR is not set @@ -824,9 +831,11 @@ CONFIG_MOUSE_PS2_LOGIPS2PP=y CONFIG_MOUSE_PS2_SYNAPTICS=y CONFIG_MOUSE_PS2_LIFEBOOK=y CONFIG_MOUSE_PS2_TRACKPOINT=y +# CONFIG_MOUSE_PS2_ELANTECH is not set # CONFIG_MOUSE_PS2_TOUCHKIT is not set # CONFIG_MOUSE_SERIAL is not set # CONFIG_MOUSE_APPLETOUCH is not set +# CONFIG_MOUSE_BCM5974 is not set # CONFIG_MOUSE_VSXXXAA is not set # CONFIG_INPUT_JOYSTICK is not set # CONFIG_INPUT_TABLET is not set @@ -940,15 +949,16 @@ CONFIG_HWMON=y # CONFIG_SENSORS_VT8231 is not set # CONFIG_SENSORS_W83627HF is not set # CONFIG_SENSORS_W83627EHF is not set +# CONFIG_SENSORS_LIS3LV02D is not set # CONFIG_HWMON_DEBUG_CHIP is not set CONFIG_THERMAL=m # CONFIG_THERMAL_HWMON is not set # CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y # # Sonics Silicon Backplane # -CONFIG_SSB_POSSIBLE=y # CONFIG_SSB is not set # @@ -957,6 +967,8 @@ CONFIG_SSB_POSSIBLE=y # CONFIG_MFD_CORE is not set # CONFIG_MFD_SM501 is not set # CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_REGULATOR is not set # # Multimedia devices @@ -1007,6 +1019,7 @@ CONFIG_VGA_CONSOLE=y # CONFIG_VGACON_SOFT_SCROLLBACK is not set CONFIG_DUMMY_CONSOLE=y CONFIG_SOUND=m +CONFIG_SOUND_OSS_CORE=y CONFIG_SND=m CONFIG_SND_TIMER=m CONFIG_SND_PCM=m @@ -1111,8 +1124,7 @@ CONFIG_HID=y # USB Input Devices # CONFIG_USB_HID=m -# CONFIG_USB_HIDINPUT_POWERBOOK is not set -# CONFIG_HID_FF is not set +# CONFIG_HID_PID is not set # CONFIG_USB_HIDDEV is not set # @@ -1120,6 +1132,34 @@ CONFIG_USB_HID=m # # CONFIG_USB_KBD is not set # CONFIG_USB_MOUSE is not set + +# +# Special HID drivers +# +CONFIG_HID_COMPAT=y +CONFIG_HID_A4TECH=m +CONFIG_HID_APPLE=m +CONFIG_HID_BELKIN=m +CONFIG_HID_BRIGHT=m +CONFIG_HID_CHERRY=m +CONFIG_HID_CHICONY=m +CONFIG_HID_CYPRESS=m +CONFIG_HID_DELL=m +CONFIG_HID_EZKEY=m +CONFIG_HID_GYRATION=m +CONFIG_HID_LOGITECH=m +# CONFIG_LOGITECH_FF is not set +# CONFIG_LOGIRUMBLEPAD2_FF is not set +CONFIG_HID_MICROSOFT=m +CONFIG_HID_MONTEREY=m +CONFIG_HID_PANTHERLORD=m +# CONFIG_PANTHERLORD_FF is not set +CONFIG_HID_PETALYNX=m +CONFIG_HID_SAMSUNG=m +CONFIG_HID_SONY=m +CONFIG_HID_SUNPLUS=m +# CONFIG_THRUSTMASTER_FF is not set +# CONFIG_ZEROPLUS_FF is not set CONFIG_USB_SUPPORT=y CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB_ARCH_HAS_OHCI=y @@ -1136,6 +1176,9 @@ CONFIG_USB_DEVICE_CLASS=y # CONFIG_USB_DYNAMIC_MINORS is not set # CONFIG_USB_SUSPEND is not set # CONFIG_USB_OTG is not set +CONFIG_USB_MON=y +# CONFIG_USB_WUSB is not set +# CONFIG_USB_WUSB_CBAF is not set # # USB Host Controller Drivers @@ -1153,6 +1196,12 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y CONFIG_USB_UHCI_HCD=m # CONFIG_USB_SL811_HCD is not set # CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_WHCI_HCD is not set +# CONFIG_USB_HWA_HCD is not set + +# +# Enable Host or Gadget support to see Inventra options +# # # USB Device Class drivers @@ -1160,13 +1209,14 @@ CONFIG_USB_UHCI_HCD=m # CONFIG_USB_ACM is not set # CONFIG_USB_PRINTER is not set # CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set # -# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed; # # -# may also be needed; see USB_STORAGE Help for more information +# see USB_STORAGE Help for more information # CONFIG_USB_STORAGE=m # CONFIG_USB_STORAGE_DEBUG is not set @@ -1189,7 +1239,6 @@ CONFIG_USB_STORAGE=m # # CONFIG_USB_MDC800 is not set # CONFIG_USB_MICROTEK is not set -CONFIG_USB_MON=y # # USB port drivers @@ -1202,7 +1251,7 @@ CONFIG_USB_MON=y # CONFIG_USB_EMI62 is not set # CONFIG_USB_EMI26 is not set # CONFIG_USB_ADUTUX is not set -# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_SEVSEG is not set # CONFIG_USB_RIO500 is not set # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_LCD is not set @@ -1220,7 +1269,9 @@ CONFIG_USB_MON=y # CONFIG_USB_IOWARRIOR is not set # CONFIG_USB_TEST is not set # CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_VST is not set # CONFIG_USB_GADGET is not set +# CONFIG_UWB is not set # CONFIG_MMC is not set # CONFIG_MEMSTICK is not set # CONFIG_NEW_LEDS is not set @@ -1244,6 +1295,15 @@ CONFIG_INFINIBAND_IPOIB_DEBUG=y # CONFIG_RTC_CLASS is not set # CONFIG_DMADEVICES is not set # CONFIG_UIO is not set +# CONFIG_STAGING is not set +CONFIG_STAGING_EXCLUDE_BUILD=y + +# +# HP Simulator drivers +# +# CONFIG_HP_SIMETH is not set +# CONFIG_HP_SIMSERIAL is not set +# CONFIG_HP_SIMSCSI is not set CONFIG_MSPEC=m # @@ -1258,7 +1318,7 @@ CONFIG_EXT3_FS=y CONFIG_EXT3_FS_XATTR=y CONFIG_EXT3_FS_POSIX_ACL=y CONFIG_EXT3_FS_SECURITY=y -# CONFIG_EXT4DEV_FS is not set +# CONFIG_EXT4_FS is not set CONFIG_JBD=y CONFIG_FS_MBCACHE=y CONFIG_REISERFS_FS=y @@ -1269,6 +1329,7 @@ CONFIG_REISERFS_FS_POSIX_ACL=y CONFIG_REISERFS_FS_SECURITY=y # CONFIG_JFS_FS is not set CONFIG_FS_POSIX_ACL=y +CONFIG_FILE_LOCKING=y CONFIG_XFS_FS=y # CONFIG_XFS_QUOTA is not set # CONFIG_XFS_POSIX_ACL is not set @@ -1280,8 +1341,8 @@ CONFIG_DNOTIFY=y CONFIG_INOTIFY=y CONFIG_INOTIFY_USER=y # CONFIG_QUOTA is not set -CONFIG_AUTOFS_FS=y -CONFIG_AUTOFS4_FS=y +CONFIG_AUTOFS_FS=m +CONFIG_AUTOFS4_FS=m # CONFIG_FUSE_FS is not set # @@ -1312,6 +1373,7 @@ CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y CONFIG_PROC_VMCORE=y CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y CONFIG_SYSFS=y CONFIG_TMPFS=y # CONFIG_TMPFS_POSIX_ACL is not set @@ -1354,6 +1416,7 @@ CONFIG_NFS_COMMON=y CONFIG_SUNRPC=m CONFIG_SUNRPC_GSS=m CONFIG_SUNRPC_XPRT_RDMA=m +# CONFIG_SUNRPC_REGISTER_V4 is not set CONFIG_RPCSEC_GSS_KRB5=m # CONFIG_RPCSEC_GSS_SPKM3 is not set CONFIG_SMB_FS=m @@ -1431,38 +1494,6 @@ CONFIG_NLS_KOI8_R=m CONFIG_NLS_KOI8_U=m CONFIG_NLS_UTF8=m # CONFIG_DLM is not set -CONFIG_HAVE_KVM=y -CONFIG_VIRTUALIZATION=y -# CONFIG_KVM is not set - -# -# Library routines -# -CONFIG_BITREVERSE=y -# CONFIG_GENERIC_FIND_FIRST_BIT is not set -# CONFIG_CRC_CCITT is not set -# CONFIG_CRC16 is not set -CONFIG_CRC_T10DIF=y -CONFIG_CRC_ITU_T=m -CONFIG_CRC32=y -# CONFIG_CRC7 is not set -# CONFIG_LIBCRC32C is not set -CONFIG_GENERIC_ALLOCATOR=y -CONFIG_PLIST=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT=y -CONFIG_HAS_DMA=y -CONFIG_GENERIC_HARDIRQS=y -CONFIG_GENERIC_IRQ_PROBE=y -CONFIG_GENERIC_PENDING_IRQ=y -CONFIG_IRQ_PER_CPU=y - -# -# HP Simulator drivers -# -# CONFIG_HP_SIMETH is not set -# CONFIG_HP_SIMSERIAL is not set -# CONFIG_HP_SIMSCSI is not set # # Kernel hacking @@ -1501,8 +1532,19 @@ CONFIG_DEBUG_MEMORY_INIT=y # CONFIG_DEBUG_SG is not set # CONFIG_BOOT_PRINTK_DELAY is not set # CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_CPU_STALL_DETECTOR is not set # CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set # CONFIG_FAULT_INJECTION is not set +CONFIG_SYSCTL_SYSCALL_CHECK=y + +# +# Tracers +# +# CONFIG_SCHED_TRACER is not set +# CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_BOOT_TRACER is not set +# CONFIG_DYNAMIC_PRINTK_DEBUG is not set # CONFIG_SAMPLES is not set CONFIG_IA64_GRANULE_16MB=y # CONFIG_IA64_GRANULE_64MB is not set @@ -1517,14 +1559,19 @@ CONFIG_SYSVIPC_COMPAT=y # # CONFIG_KEYS is not set # CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set # CONFIG_SECURITY_FILE_CAPABILITIES is not set CONFIG_CRYPTO=y # # Crypto core or helper # +# CONFIG_CRYPTO_FIPS is not set CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_AEAD=m CONFIG_CRYPTO_BLKCIPHER=m +CONFIG_CRYPTO_HASH=m +CONFIG_CRYPTO_RNG=m CONFIG_CRYPTO_MANAGER=m # CONFIG_CRYPTO_GF128MUL is not set # CONFIG_CRYPTO_NULL is not set @@ -1597,5 +1644,36 @@ CONFIG_CRYPTO_DES=m # # CONFIG_CRYPTO_DEFLATE is not set # CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRYPTO_HW=y # CONFIG_CRYPTO_DEV_HIFN_795X is not set +CONFIG_HAVE_KVM=y +CONFIG_VIRTUALIZATION=y +# CONFIG_KVM is not set +# CONFIG_VIRTIO_PCI is not set +# CONFIG_VIRTIO_BALLOON is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +CONFIG_CRC_T10DIF=y +CONFIG_CRC_ITU_T=m +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_PENDING_IRQ=y +CONFIG_IRQ_PER_CPU=y diff --git a/arch/ia64/configs/tiger_defconfig b/arch/ia64/configs/tiger_defconfig index 797acf9..c522edf 100644 --- a/arch/ia64/configs/tiger_defconfig +++ b/arch/ia64/configs/tiger_defconfig @@ -172,6 +172,8 @@ CONFIG_DMIID=y CONFIG_BINFMT_ELF=y CONFIG_BINFMT_MISC=m +# CONFIG_DMAR is not set + # # Power management and ACPI # diff --git a/arch/ia64/dig/Makefile b/arch/ia64/dig/Makefile index 971cd78..5c02838 100644 --- a/arch/ia64/dig/Makefile +++ b/arch/ia64/dig/Makefile @@ -6,4 +6,9 @@ # obj-y := setup.o +ifeq ($(CONFIG_DMAR), y) +obj-$(CONFIG_IA64_GENERIC) += machvec.o machvec_vtd.o dig_vtd_iommu.o +else obj-$(CONFIG_IA64_GENERIC) += machvec.o +endif +obj-$(CONFIG_IA64_DIG_VTD) += dig_vtd_iommu.o diff --git a/arch/ia64/dig/dig_vtd_iommu.c b/arch/ia64/dig/dig_vtd_iommu.c new file mode 100644 index 0000000..1c8a079 --- /dev/null +++ b/arch/ia64/dig/dig_vtd_iommu.c @@ -0,0 +1,59 @@ +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/intel-iommu.h> + +void * +vtd_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, + gfp_t flags) +{ + return intel_alloc_coherent(dev, size, dma_handle, flags); +} +EXPORT_SYMBOL_GPL(vtd_alloc_coherent); + +void +vtd_free_coherent(struct device *dev, size_t size, void *vaddr, + dma_addr_t dma_handle) +{ + intel_free_coherent(dev, size, vaddr, dma_handle); +} +EXPORT_SYMBOL_GPL(vtd_free_coherent); + +dma_addr_t +vtd_map_single_attrs(struct device *dev, void *addr, size_t size, + int dir, struct dma_attrs *attrs) +{ + return intel_map_single(dev, (phys_addr_t)addr, size, dir); +} +EXPORT_SYMBOL_GPL(vtd_map_single_attrs); + +void +vtd_unmap_single_attrs(struct device *dev, dma_addr_t iova, size_t size, + int dir, struct dma_attrs *attrs) +{ + intel_unmap_single(dev, iova, size, dir); +} +EXPORT_SYMBOL_GPL(vtd_unmap_single_attrs); + +int +vtd_map_sg_attrs(struct device *dev, struct scatterlist *sglist, int nents, + int dir, struct dma_attrs *attrs) +{ + return intel_map_sg(dev, sglist, nents, dir); +} +EXPORT_SYMBOL_GPL(vtd_map_sg_attrs); + +void +vtd_unmap_sg_attrs(struct device *dev, struct scatterlist *sglist, + int nents, int dir, struct dma_attrs *attrs) +{ + intel_unmap_sg(dev, sglist, nents, dir); +} +EXPORT_SYMBOL_GPL(vtd_unmap_sg_attrs); + +int +vtd_dma_mapping_error(struct device *dev, dma_addr_t dma_addr) +{ + return 0; +} +EXPORT_SYMBOL_GPL(vtd_dma_mapping_error); diff --git a/arch/ia64/dig/machvec_vtd.c b/arch/ia64/dig/machvec_vtd.c new file mode 100644 index 0000000..7cd3eb4 --- /dev/null +++ b/arch/ia64/dig/machvec_vtd.c @@ -0,0 +1,3 @@ +#define MACHVEC_PLATFORM_NAME dig_vtd +#define MACHVEC_PLATFORM_HEADER <asm/machvec_dig_vtd.h> +#include <asm/machvec_init.h> diff --git a/arch/ia64/hp/common/hwsw_iommu.c b/arch/ia64/hp/common/hwsw_iommu.c index 88b6e6f..2769dbf 100644 --- a/arch/ia64/hp/common/hwsw_iommu.c +++ b/arch/ia64/hp/common/hwsw_iommu.c @@ -13,19 +13,12 @@ */ #include <linux/device.h> +#include <linux/swiotlb.h> #include <asm/machvec.h> /* swiotlb declarations & definitions: */ extern int swiotlb_late_init_with_default_size (size_t size); -extern ia64_mv_dma_alloc_coherent swiotlb_alloc_coherent; -extern ia64_mv_dma_free_coherent swiotlb_free_coherent; -extern ia64_mv_dma_map_single_attrs swiotlb_map_single_attrs; -extern ia64_mv_dma_unmap_single_attrs swiotlb_unmap_single_attrs; -extern ia64_mv_dma_map_sg_attrs swiotlb_map_sg_attrs; -extern ia64_mv_dma_unmap_sg_attrs swiotlb_unmap_sg_attrs; -extern ia64_mv_dma_supported swiotlb_dma_supported; -extern ia64_mv_dma_mapping_error swiotlb_dma_mapping_error; /* hwiommu declarations & definitions: */ diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c index 4956be4..d98f0f4 100644 --- a/arch/ia64/hp/common/sba_iommu.c +++ b/arch/ia64/hp/common/sba_iommu.c @@ -2070,14 +2070,13 @@ sba_init(void) if (!ia64_platform_is("hpzx1") && !ia64_platform_is("hpzx1_swiotlb")) return 0; -#if defined(CONFIG_IA64_GENERIC) && defined(CONFIG_CRASH_DUMP) && \ - defined(CONFIG_PROC_FS) +#if defined(CONFIG_IA64_GENERIC) /* If we are booting a kdump kernel, the sba_iommu will * cause devices that were not shutdown properly to MCA * as soon as they are turned back on. Our only option for * a successful kdump kernel boot is to use the swiotlb. */ - if (elfcorehdr_addr < ELFCORE_ADDR_MAX) { + if (is_kdump_kernel()) { if (swiotlb_late_init_with_default_size(64 * (1<<20)) != 0) panic("Unable to initialize software I/O TLB:" " Try machvec=dig boot option"); diff --git a/arch/ia64/hp/sim/Kconfig b/arch/ia64/hp/sim/Kconfig index f92306b..8d513a8 100644 --- a/arch/ia64/hp/sim/Kconfig +++ b/arch/ia64/hp/sim/Kconfig @@ -4,6 +4,7 @@ menu "HP Simulator drivers" config HP_SIMETH bool "Simulated Ethernet " + depends on NET config HP_SIMSERIAL bool "Simulated serial driver support" diff --git a/arch/ia64/hp/sim/simeth.c b/arch/ia64/hp/sim/simeth.c index 3d47839..e4d8fde 100644 --- a/arch/ia64/hp/sim/simeth.c +++ b/arch/ia64/hp/sim/simeth.c @@ -167,6 +167,15 @@ netdev_read(int fd, unsigned char *buf, unsigned int len) return ia64_ssc(fd, __pa(buf), len, 0, SSC_NETDEV_RECV); } +static const struct net_device_ops simeth_netdev_ops = { + .ndo_open = simeth_open, + .ndo_stop = simeth_close, + .ndo_start_xmit = simeth_tx, + .ndo_get_stats = simeth_get_stats, + .ndo_set_multicast_list = set_multicast_list, /* not yet used */ + +}; + /* * Function shared with module code, so cannot be in init section * @@ -206,14 +215,10 @@ simeth_probe1(void) memcpy(dev->dev_addr, mac_addr, sizeof(mac_addr)); - local = dev->priv; + local = netdev_priv(dev); local->simfd = fd; /* keep track of underlying file descriptor */ - dev->open = simeth_open; - dev->stop = simeth_close; - dev->hard_start_xmit = simeth_tx; - dev->get_stats = simeth_get_stats; - dev->set_multicast_list = set_multicast_list; /* no yet used */ + dev->netdev_ops = &simeth_netdev_ops; err = register_netdev(dev); if (err) { @@ -325,7 +330,7 @@ simeth_device_event(struct notifier_block *this,unsigned long event, void *ptr) * we get DOWN then UP. */ - local = dev->priv; + local = netdev_priv(dev); /* now do it for real */ r = event == NETDEV_UP ? netdev_attach(local->simfd, dev->irq, ntohl(ifa->ifa_local)): @@ -380,7 +385,7 @@ frame_print(unsigned char *from, unsigned char *frame, int len) static int simeth_tx(struct sk_buff *skb, struct net_device *dev) { - struct simeth_local *local = dev->priv; + struct simeth_local *local = netdev_priv(dev); #if 0 /* ensure we have at least ETH_ZLEN bytes (min frame size) */ @@ -443,7 +448,7 @@ simeth_rx(struct net_device *dev) int len; int rcv_count = SIMETH_RECV_MAX; - local = dev->priv; + local = netdev_priv(dev); /* * the loop concept has been borrowed from other drivers * looks to me like it's a throttling thing to avoid pushing to many @@ -507,7 +512,7 @@ simeth_interrupt(int irq, void *dev_id) static struct net_device_stats * simeth_get_stats(struct net_device *dev) { - struct simeth_local *local = dev->priv; + struct simeth_local *local = netdev_priv(dev); return &local->stats; } diff --git a/arch/ia64/ia32/audit.c b/arch/ia64/ia32/audit.c index 5e901c7..5c93ddd 100644 --- a/arch/ia64/ia32/audit.c +++ b/arch/ia64/ia32/audit.c @@ -1,4 +1,4 @@ -#include <asm-x86/unistd_32.h> +#include "../../x86/include/asm/unistd_32.h" unsigned ia32_dir_class[] = { #include <asm-generic/audit_dir_write.h> diff --git a/arch/ia64/ia32/binfmt_elf32.c b/arch/ia64/ia32/binfmt_elf32.c index 4f0c30c..f92bdaa 100644 --- a/arch/ia64/ia32/binfmt_elf32.c +++ b/arch/ia64/ia32/binfmt_elf32.c @@ -41,7 +41,7 @@ randomize_stack_top(unsigned long stack_top); #define elf_map elf32_map #undef SET_PERSONALITY -#define SET_PERSONALITY(ex, ibcs2) elf32_set_personality() +#define SET_PERSONALITY(ex) elf32_set_personality() #define elf_read_implies_exec(ex, have_pt_gnu_stack) (!(have_pt_gnu_stack)) diff --git a/arch/ia64/ia32/ia32_entry.S b/arch/ia64/ia32/ia32_entry.S index ff88c48..a8cf199 100644 --- a/arch/ia64/ia32/ia32_entry.S +++ b/arch/ia64/ia32/ia32_entry.S @@ -108,6 +108,11 @@ GLOBAL_ENTRY(ia32_trace_syscall) ;; st8 [r2]=r3 // initialize return code to -ENOSYS br.call.sptk.few rp=syscall_trace_enter // give parent a chance to catch syscall args + cmp.lt p6,p0=r8,r0 // check tracehook + adds r2=IA64_PT_REGS_R8_OFFSET+16,sp // r2 = &pt_regs.r8 + ;; +(p6) st8.spill [r2]=r8 // store return value in slot for r8 +(p6) br.spnt.few .ret4 .ret2: // Need to reload arguments (they may be changed by the tracing process) adds r2=IA64_PT_REGS_R1_OFFSET+16,sp // r2 = &pt_regs.r1 adds r3=IA64_PT_REGS_R13_OFFSET+16,sp // r3 = &pt_regs.r13 @@ -199,10 +204,10 @@ ia32_syscall_table: data8 sys_setuid /* 16-bit version */ data8 sys_getuid /* 16-bit version */ data8 compat_sys_stime /* 25 */ - data8 sys32_ptrace + data8 compat_sys_ptrace data8 sys32_alarm data8 sys_ni_syscall - data8 sys32_pause + data8 sys_pause data8 compat_sys_utime /* 30 */ data8 sys_ni_syscall /* old stty syscall holder */ data8 sys_ni_syscall /* old gtty syscall holder */ @@ -215,7 +220,7 @@ ia32_syscall_table: data8 sys_mkdir data8 sys_rmdir /* 40 */ data8 sys_dup - data8 sys32_pipe + data8 sys_pipe data8 compat_sys_times data8 sys_ni_syscall /* old prof syscall holder */ data8 sys32_brk /* 45 */ @@ -251,8 +256,8 @@ ia32_syscall_table: data8 compat_sys_setrlimit /* 75 */ data8 compat_sys_old_getrlimit data8 compat_sys_getrusage - data8 sys32_gettimeofday - data8 sys32_settimeofday + data8 compat_sys_gettimeofday + data8 compat_sys_settimeofday data8 sys32_getgroups16 /* 80 */ data8 sys32_setgroups16 data8 sys32_old_select diff --git a/arch/ia64/ia32/ia32priv.h b/arch/ia64/ia32/ia32priv.h index dd0c536..0f15349 100644 --- a/arch/ia64/ia32/ia32priv.h +++ b/arch/ia64/ia32/ia32priv.h @@ -332,8 +332,8 @@ void ia64_elf32_init(struct pt_regs *regs); #define ELF_PLATFORM NULL #ifdef __KERNEL__ -# define SET_PERSONALITY(EX,IBCS2) \ - (current->personality = (IBCS2) ? PER_SVR4 : PER_LINUX) +# define SET_PERSONALITY(EX) \ + (current->personality = PER_LINUX) #endif #define IA32_EFLAG 0x200 diff --git a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c index bf196cb..16ef61a 100644 --- a/arch/ia64/ia32/sys_ia32.c +++ b/arch/ia64/ia32/sys_ia32.c @@ -118,41 +118,6 @@ sys32_execve (char __user *name, compat_uptr_t __user *argv, compat_uptr_t __use return error; } -int cp_compat_stat(struct kstat *stat, struct compat_stat __user *ubuf) -{ - compat_ino_t ino; - int err; - - if ((u64) stat->size > MAX_NON_LFS || - !old_valid_dev(stat->dev) || - !old_valid_dev(stat->rdev)) - return -EOVERFLOW; - - ino = stat->ino; - if (sizeof(ino) < sizeof(stat->ino) && ino != stat->ino) - return -EOVERFLOW; - - if (clear_user(ubuf, sizeof(*ubuf))) - return -EFAULT; - - err = __put_user(old_encode_dev(stat->dev), &ubuf->st_dev); - err |= __put_user(ino, &ubuf->st_ino); - err |= __put_user(stat->mode, &ubuf->st_mode); - err |= __put_user(stat->nlink, &ubuf->st_nlink); - err |= __put_user(high2lowuid(stat->uid), &ubuf->st_uid); - err |= __put_user(high2lowgid(stat->gid), &ubuf->st_gid); - err |= __put_user(old_encode_dev(stat->rdev), &ubuf->st_rdev); - err |= __put_user(stat->size, &ubuf->st_size); - err |= __put_user(stat->atime.tv_sec, &ubuf->st_atime); - err |= __put_user(stat->atime.tv_nsec, &ubuf->st_atime_nsec); - err |= __put_user(stat->mtime.tv_sec, &ubuf->st_mtime); - err |= __put_user(stat->mtime.tv_nsec, &ubuf->st_mtime_nsec); - err |= __put_user(stat->ctime.tv_sec, &ubuf->st_ctime); - err |= __put_user(stat->ctime.tv_nsec, &ubuf->st_ctime_nsec); - err |= __put_user(stat->blksize, &ubuf->st_blksize); - err |= __put_user(stat->blocks, &ubuf->st_blocks); - return err; -} #if PAGE_SHIFT > IA32_PAGE_SHIFT @@ -1133,83 +1098,12 @@ sys32_mremap (unsigned int addr, unsigned int old_len, unsigned int new_len, return ret; } -asmlinkage long -sys32_pipe (int __user *fd) -{ - int retval; - int fds[2]; - - retval = do_pipe_flags(fds, 0); - if (retval) - goto out; - if (copy_to_user(fd, fds, sizeof(fds))) - retval = -EFAULT; - out: - return retval; -} - -static inline long -get_tv32 (struct timeval *o, struct compat_timeval __user *i) -{ - return (!access_ok(VERIFY_READ, i, sizeof(*i)) || - (__get_user(o->tv_sec, &i->tv_sec) | __get_user(o->tv_usec, &i->tv_usec))); -} - -static inline long -put_tv32 (struct compat_timeval __user *o, struct timeval *i) -{ - return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) || - (__put_user(i->tv_sec, &o->tv_sec) | __put_user(i->tv_usec, &o->tv_usec))); -} - asmlinkage unsigned long sys32_alarm (unsigned int seconds) { return alarm_setitimer(seconds); } -/* Translations due to time_t size differences. Which affects all - sorts of things, like timeval and itimerval. */ - -extern struct timezone sys_tz; - -asmlinkage long -sys32_gettimeofday (struct compat_timeval __user *tv, struct timezone __user *tz) -{ - if (tv) { - struct timeval ktv; - do_gettimeofday(&ktv); - if (put_tv32(tv, &ktv)) - return -EFAULT; - } - if (tz) { - if (copy_to_user(tz, &sys_tz, sizeof(sys_tz))) - return -EFAULT; - } - return 0; -} - -asmlinkage long -sys32_settimeofday (struct compat_timeval __user *tv, struct timezone __user *tz) -{ - struct timeval ktv; - struct timespec kts; - struct timezone ktz; - - if (tv) { - if (get_tv32(&ktv, tv)) - return -EFAULT; - kts.tv_sec = ktv.tv_sec; - kts.tv_nsec = ktv.tv_usec * 1000; - } - if (tz) { - if (copy_from_user(&ktz, tz, sizeof(ktz))) - return -EFAULT; - } - - return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL); -} - struct sel_arg_struct { unsigned int n; unsigned int inp; @@ -1300,25 +1194,6 @@ sys32_waitpid (int pid, unsigned int *stat_addr, int options) return compat_sys_wait4(pid, stat_addr, options, NULL); } -static unsigned int -ia32_peek (struct task_struct *child, unsigned long addr, unsigned int *val) -{ - size_t copied; - unsigned int ret; - - copied = access_process_vm(child, addr, val, sizeof(*val), 0); - return (copied != sizeof(ret)) ? -EIO : 0; -} - -static unsigned int -ia32_poke (struct task_struct *child, unsigned long addr, unsigned int val) -{ - - if (access_process_vm(child, addr, &val, sizeof(val), 1) != sizeof(val)) - return -EIO; - return 0; -} - /* * The order in which registers are stored in the ptrace regs structure */ @@ -1616,49 +1491,15 @@ restore_ia32_fpxstate (struct task_struct *tsk, struct ia32_user_fxsr_struct __u return 0; } -asmlinkage long -sys32_ptrace (int request, pid_t pid, unsigned int addr, unsigned int data) +long compat_arch_ptrace(struct task_struct *child, compat_long_t request, + compat_ulong_t caddr, compat_ulong_t cdata) { - struct task_struct *child; - unsigned int value, tmp; + unsigned long addr = caddr; + unsigned long data = cdata; + unsigned int tmp; long i, ret; - lock_kernel(); - if (request == PTRACE_TRACEME) { - ret = ptrace_traceme(); - goto out; - } - - child = ptrace_get_task_struct(pid); - if (IS_ERR(child)) { - ret = PTR_ERR(child); - goto out; - } - - if (request == PTRACE_ATTACH) { - ret = sys_ptrace(request, pid, addr, data); - goto out_tsk; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - goto out_tsk; - switch (request) { - case PTRACE_PEEKTEXT: - case PTRACE_PEEKDATA: /* read word at location addr */ - ret = ia32_peek(child, addr, &value); - if (ret == 0) - ret = put_user(value, (unsigned int __user *) compat_ptr(data)); - else - ret = -EIO; - goto out_tsk; - - case PTRACE_POKETEXT: - case PTRACE_POKEDATA: /* write the word at location addr */ - ret = ia32_poke(child, addr, data); - goto out_tsk; - case PTRACE_PEEKUSR: /* read word at addr in USER area */ ret = -EIO; if ((addr & 3) || addr > 17*sizeof(int)) @@ -1723,27 +1564,9 @@ sys32_ptrace (int request, pid_t pid, unsigned int addr, unsigned int data) compat_ptr(data)); break; - case PTRACE_GETEVENTMSG: - ret = put_user(child->ptrace_message, (unsigned int __user *) compat_ptr(data)); - break; - - case PTRACE_SYSCALL: /* continue, stop after next syscall */ - case PTRACE_CONT: /* restart after signal. */ - case PTRACE_KILL: - case PTRACE_SINGLESTEP: /* execute chile for one instruction */ - case PTRACE_DETACH: /* detach a process */ - ret = sys_ptrace(request, pid, addr, data); - break; - default: - ret = ptrace_request(child, request, addr, data); - break; - + return compat_ptrace_request(child, request, caddr, cdata); } - out_tsk: - put_task_struct(child); - out: - unlock_kernel(); return ret; } @@ -1795,14 +1618,6 @@ out: } asmlinkage int -sys32_pause (void) -{ - current->state = TASK_INTERRUPTIBLE; - schedule(); - return -ERESTARTNOHAND; -} - -asmlinkage int sys32_msync (unsigned int start, unsigned int len, int flags) { unsigned int addr; @@ -1952,25 +1767,24 @@ groups16_from_user(struct group_info *group_info, short __user *grouplist) asmlinkage long sys32_getgroups16 (int gidsetsize, short __user *grouplist) { + const struct cred *cred = current_cred(); int i; if (gidsetsize < 0) return -EINVAL; - get_group_info(current->group_info); - i = current->group_info->ngroups; + i = cred->group_info->ngroups; if (gidsetsize) { if (i > gidsetsize) { i = -EINVAL; goto out; } - if (groups16_to_user(grouplist, current->group_info)) { + if (groups16_to_user(grouplist, cred->group_info)) { i = -EFAULT; goto out; } } out: - put_group_info(current->group_info); return i; } diff --git a/arch/ia64/include/asm/break.h b/arch/ia64/include/asm/break.h index f034020..e90c40e 100644 --- a/arch/ia64/include/asm/break.h +++ b/arch/ia64/include/asm/break.h @@ -20,4 +20,13 @@ */ #define __IA64_BREAK_SYSCALL 0x100000 +/* + * Xen specific break numbers: + */ +#define __IA64_XEN_HYPERCALL 0x1000 +/* [__IA64_XEN_HYPERPRIVOP_START, __IA64_XEN_HYPERPRIVOP_MAX] is used + for xen hyperprivops */ +#define __IA64_XEN_HYPERPRIVOP_START 0x1 +#define __IA64_XEN_HYPERPRIVOP_MAX 0x1a + #endif /* _ASM_IA64_BREAK_H */ diff --git a/arch/ia64/include/asm/cacheflush.h b/arch/ia64/include/asm/cacheflush.h index afcfbda..c8ce271 100644 --- a/arch/ia64/include/asm/cacheflush.h +++ b/arch/ia64/include/asm/cacheflush.h @@ -34,6 +34,8 @@ do { \ #define flush_dcache_mmap_unlock(mapping) do { } while (0) extern void flush_icache_range (unsigned long start, unsigned long end); +extern void clflush_cache_range(void *addr, int size); + #define flush_icache_user_range(vma, page, user_addr, len) \ do { \ diff --git a/arch/ia64/include/asm/device.h b/arch/ia64/include/asm/device.h index 3db6daf..41ab85d 100644 --- a/arch/ia64/include/asm/device.h +++ b/arch/ia64/include/asm/device.h @@ -10,6 +10,9 @@ struct dev_archdata { #ifdef CONFIG_ACPI void *acpi_handle; #endif +#ifdef CONFIG_DMAR + void *iommu; /* hook for IOMMU specific extension */ +#endif }; #endif /* _ASM_IA64_DEVICE_H */ diff --git a/arch/ia64/include/asm/dma-mapping.h b/arch/ia64/include/asm/dma-mapping.h index 06ff1ba..bbab7e2 100644 --- a/arch/ia64/include/asm/dma-mapping.h +++ b/arch/ia64/include/asm/dma-mapping.h @@ -7,6 +7,49 @@ */ #include <asm/machvec.h> #include <linux/scatterlist.h> +#include <asm/swiotlb.h> + +struct dma_mapping_ops { + int (*mapping_error)(struct device *dev, + dma_addr_t dma_addr); + void* (*alloc_coherent)(struct device *dev, size_t size, + dma_addr_t *dma_handle, gfp_t gfp); + void (*free_coherent)(struct device *dev, size_t size, + void *vaddr, dma_addr_t dma_handle); + dma_addr_t (*map_single)(struct device *hwdev, unsigned long ptr, + size_t size, int direction); + void (*unmap_single)(struct device *dev, dma_addr_t addr, + size_t size, int direction); + void (*sync_single_for_cpu)(struct device *hwdev, + dma_addr_t dma_handle, size_t size, + int direction); + void (*sync_single_for_device)(struct device *hwdev, + dma_addr_t dma_handle, size_t size, + int direction); + void (*sync_single_range_for_cpu)(struct device *hwdev, + dma_addr_t dma_handle, unsigned long offset, + size_t size, int direction); + void (*sync_single_range_for_device)(struct device *hwdev, + dma_addr_t dma_handle, unsigned long offset, + size_t size, int direction); + void (*sync_sg_for_cpu)(struct device *hwdev, + struct scatterlist *sg, int nelems, + int direction); + void (*sync_sg_for_device)(struct device *hwdev, + struct scatterlist *sg, int nelems, + int direction); + int (*map_sg)(struct device *hwdev, struct scatterlist *sg, + int nents, int direction); + void (*unmap_sg)(struct device *hwdev, + struct scatterlist *sg, int nents, + int direction); + int (*dma_supported_op)(struct device *hwdev, u64 mask); + int is_phys; +}; + +extern struct dma_mapping_ops *dma_ops; +extern struct ia64_machine_vector ia64_mv; +extern void set_iommu_machvec(void); #define dma_alloc_coherent(dev, size, handle, gfp) \ platform_dma_alloc_coherent(dev, size, handle, (gfp) | GFP_DMA) @@ -96,4 +139,11 @@ dma_cache_sync (struct device *dev, void *vaddr, size_t size, #define dma_is_consistent(d, h) (1) /* all we do is coherent memory... */ +static inline struct dma_mapping_ops *get_dma_ops(struct device *dev) +{ + return dma_ops; +} + + + #endif /* _ASM_IA64_DMA_MAPPING_H */ diff --git a/arch/ia64/include/asm/elf.h b/arch/ia64/include/asm/elf.h index 2acb6b6..86eddee 100644 --- a/arch/ia64/include/asm/elf.h +++ b/arch/ia64/include/asm/elf.h @@ -202,7 +202,7 @@ extern void ia64_elf_core_copy_regs (struct pt_regs *src, elf_gregset_t dst); relevant until we have real hardware to play with... */ #define ELF_PLATFORM NULL -#define SET_PERSONALITY(ex, ibcs2) set_personality(PER_LINUX) +#define SET_PERSONALITY(ex) set_personality(PER_LINUX) #define elf_read_implies_exec(ex, executable_stack) \ ((executable_stack!=EXSTACK_DISABLE_X) && ((ex).e_flags & EF_IA_64_LINUX_EXECUTABLE_STACK) != 0) diff --git a/arch/ia64/include/asm/intrinsics.h b/arch/ia64/include/asm/intrinsics.h index 47d686d..a3e44a5 100644 --- a/arch/ia64/include/asm/intrinsics.h +++ b/arch/ia64/include/asm/intrinsics.h @@ -226,7 +226,7 @@ extern long ia64_cmpxchg_called_with_bad_pointer (void); /************************************************/ #define ia64_ssm IA64_INTRINSIC_MACRO(ssm) #define ia64_rsm IA64_INTRINSIC_MACRO(rsm) -#define ia64_getreg IA64_INTRINSIC_API(getreg) +#define ia64_getreg IA64_INTRINSIC_MACRO(getreg) #define ia64_setreg IA64_INTRINSIC_API(setreg) #define ia64_set_rr IA64_INTRINSIC_API(set_rr) #define ia64_get_rr IA64_INTRINSIC_API(get_rr) diff --git a/arch/ia64/include/asm/io.h b/arch/ia64/include/asm/io.h index 7f25750..0d9d16e 100644 --- a/arch/ia64/include/asm/io.h +++ b/arch/ia64/include/asm/io.h @@ -434,28 +434,4 @@ extern void memset_io(volatile void __iomem *s, int c, long n); # endif /* __KERNEL__ */ -/* - * Enabling BIO_VMERGE_BOUNDARY forces us to turn off I/O MMU bypassing. It is said that - * BIO-level virtual merging can give up to 4% performance boost (not verified for ia64). - * On the other hand, we know that I/O MMU bypassing gives ~8% performance improvement on - * SPECweb-like workloads on zx1-based machines. Thus, for now we favor I/O MMU bypassing - * over BIO-level virtual merging. - */ -extern unsigned long ia64_max_iommu_merge_mask; -#if 1 -#define BIO_VMERGE_BOUNDARY 0 -#else -/* - * It makes no sense at all to have this BIO_VMERGE_BOUNDARY macro here. Should be - * replaced by dma_merge_mask() or something of that sort. Note: the only way - * BIO_VMERGE_BOUNDARY is used is to mask off bits. Effectively, our definition gets - * expanded into: - * - * addr & ((ia64_max_iommu_merge_mask + 1) - 1) == (addr & ia64_max_iommu_vmerge_mask) - * - * which is precisely what we want. - */ -#define BIO_VMERGE_BOUNDARY (ia64_max_iommu_merge_mask + 1) -#endif - #endif /* _ASM_IA64_IO_H */ diff --git a/arch/ia64/include/asm/iommu.h b/arch/ia64/include/asm/iommu.h new file mode 100644 index 0000000..0490794 --- /dev/null +++ b/arch/ia64/include/asm/iommu.h @@ -0,0 +1,15 @@ +#ifndef _ASM_IA64_IOMMU_H +#define _ASM_IA64_IOMMU_H 1 + +#define cpu_has_x2apic 0 +/* 10 seconds */ +#define DMAR_OPERATION_TIMEOUT (((cycles_t) local_cpu_data->itc_freq)*10) + +extern void pci_iommu_shutdown(void); +extern void no_iommu_init(void); +extern int force_iommu, no_iommu; +extern int iommu_detected; +extern void iommu_dma_init(void); +extern void machvec_init(const char *name); + +#endif diff --git a/arch/ia64/include/asm/kregs.h b/arch/ia64/include/asm/kregs.h index aefcdfe..39e65f6 100644 --- a/arch/ia64/include/asm/kregs.h +++ b/arch/ia64/include/asm/kregs.h @@ -32,7 +32,7 @@ #define IA64_TR_CURRENT_STACK 1 /* dtr1: maps kernel's memory- & register-stacks */ #define IA64_TR_ALLOC_BASE 2 /* itr&dtr: Base of dynamic TR resource*/ -#define IA64_TR_ALLOC_MAX 32 /* Max number for dynamic use*/ +#define IA64_TR_ALLOC_MAX 64 /* Max number for dynamic use*/ /* Processor status register bits: */ #define IA64_PSR_BE_BIT 1 diff --git a/arch/ia64/include/asm/kvm_host.h b/arch/ia64/include/asm/kvm_host.h index 1efe513..c60d324 100644 --- a/arch/ia64/include/asm/kvm_host.h +++ b/arch/ia64/include/asm/kvm_host.h @@ -132,7 +132,7 @@ #define GPFN_IOSAPIC (4UL << 60) /* IOSAPIC base */ #define GPFN_LEGACY_IO (5UL << 60) /* Legacy I/O base */ #define GPFN_GFW (6UL << 60) /* Guest Firmware */ -#define GPFN_HIGH_MMIO (7UL << 60) /* High MMIO range */ +#define GPFN_PHYS_MMIO (7UL << 60) /* Directed MMIO Range */ #define GPFN_IO_MASK (7UL << 60) /* Guest pfn is I/O type */ #define GPFN_INV_MASK (1UL << 63) /* Guest pfn is invalid */ @@ -365,7 +365,8 @@ struct kvm_vcpu_arch { long itc_offset; unsigned long itc_check; unsigned long timer_check; - unsigned long timer_pending; + unsigned int timer_pending; + unsigned int timer_fired; unsigned long vrr[8]; unsigned long ibr[8]; @@ -413,6 +414,13 @@ struct kvm_arch { struct kvm_ioapic *vioapic; struct kvm_vm_stat stat; struct kvm_sal_data rdv_sal_data; + + struct list_head assigned_dev_head; + struct dmar_domain *intel_iommu_domain; + struct hlist_head irq_ack_notifier_list; + + unsigned long irq_sources_bitmap; + unsigned long irq_states[KVM_IOAPIC_NUM_PINS]; }; union cpuid3_t { diff --git a/arch/ia64/include/asm/machvec.h b/arch/ia64/include/asm/machvec.h index 2b850cc..59c17e4 100644 --- a/arch/ia64/include/asm/machvec.h +++ b/arch/ia64/include/asm/machvec.h @@ -11,6 +11,7 @@ #define _ASM_IA64_MACHVEC_H #include <linux/types.h> +#include <linux/swiotlb.h> /* forward declarations: */ struct device; @@ -120,6 +121,8 @@ extern void machvec_tlb_migrate_finish (struct mm_struct *); # include <asm/machvec_hpsim.h> # elif defined (CONFIG_IA64_DIG) # include <asm/machvec_dig.h> +# elif defined(CONFIG_IA64_DIG_VTD) +# include <asm/machvec_dig_vtd.h> # elif defined (CONFIG_IA64_HP_ZX1) # include <asm/machvec_hpzx1.h> # elif defined (CONFIG_IA64_HP_ZX1_SWIOTLB) @@ -128,6 +131,8 @@ extern void machvec_tlb_migrate_finish (struct mm_struct *); # include <asm/machvec_sn2.h> # elif defined (CONFIG_IA64_SGI_UV) # include <asm/machvec_uv.h> +# elif defined (CONFIG_IA64_XEN_GUEST) +# include <asm/machvec_xen.h> # elif defined (CONFIG_IA64_GENERIC) # ifdef MACHVEC_PLATFORM_HEADER @@ -294,27 +299,6 @@ extern void machvec_init_from_cmdline(const char *cmdline); # endif /* CONFIG_IA64_GENERIC */ /* - * Declare default routines which aren't declared anywhere else: - */ -extern ia64_mv_dma_init swiotlb_init; -extern ia64_mv_dma_alloc_coherent swiotlb_alloc_coherent; -extern ia64_mv_dma_free_coherent swiotlb_free_coherent; -extern ia64_mv_dma_map_single swiotlb_map_single; -extern ia64_mv_dma_map_single_attrs swiotlb_map_single_attrs; -extern ia64_mv_dma_unmap_single swiotlb_unmap_single; -extern ia64_mv_dma_unmap_single_attrs swiotlb_unmap_single_attrs; -extern ia64_mv_dma_map_sg swiotlb_map_sg; -extern ia64_mv_dma_map_sg_attrs swiotlb_map_sg_attrs; -extern ia64_mv_dma_unmap_sg swiotlb_unmap_sg; -extern ia64_mv_dma_unmap_sg_attrs swiotlb_unmap_sg_attrs; -extern ia64_mv_dma_sync_single_for_cpu swiotlb_sync_single_for_cpu; -extern ia64_mv_dma_sync_sg_for_cpu swiotlb_sync_sg_for_cpu; -extern ia64_mv_dma_sync_single_for_device swiotlb_sync_single_for_device; -extern ia64_mv_dma_sync_sg_for_device swiotlb_sync_sg_for_device; -extern ia64_mv_dma_mapping_error swiotlb_dma_mapping_error; -extern ia64_mv_dma_supported swiotlb_dma_supported; - -/* * Define default versions so we can extend machvec for new platforms without having * to update the machvec files for all existing platforms. */ diff --git a/arch/ia64/include/asm/machvec_dig_vtd.h b/arch/ia64/include/asm/machvec_dig_vtd.h new file mode 100644 index 0000000..3400b56 --- /dev/null +++ b/arch/ia64/include/asm/machvec_dig_vtd.h @@ -0,0 +1,38 @@ +#ifndef _ASM_IA64_MACHVEC_DIG_VTD_h +#define _ASM_IA64_MACHVEC_DIG_VTD_h + +extern ia64_mv_setup_t dig_setup; +extern ia64_mv_dma_alloc_coherent vtd_alloc_coherent; +extern ia64_mv_dma_free_coherent vtd_free_coherent; +extern ia64_mv_dma_map_single_attrs vtd_map_single_attrs; +extern ia64_mv_dma_unmap_single_attrs vtd_unmap_single_attrs; +extern ia64_mv_dma_map_sg_attrs vtd_map_sg_attrs; +extern ia64_mv_dma_unmap_sg_attrs vtd_unmap_sg_attrs; +extern ia64_mv_dma_supported iommu_dma_supported; +extern ia64_mv_dma_mapping_error vtd_dma_mapping_error; +extern ia64_mv_dma_init pci_iommu_alloc; + +/* + * This stuff has dual use! + * + * For a generic kernel, the macros are used to initialize the + * platform's machvec structure. When compiling a non-generic kernel, + * the macros are used directly. + */ +#define platform_name "dig_vtd" +#define platform_setup dig_setup +#define platform_dma_init pci_iommu_alloc +#define platform_dma_alloc_coherent vtd_alloc_coherent +#define platform_dma_free_coherent vtd_free_coherent +#define platform_dma_map_single_attrs vtd_map_single_attrs +#define platform_dma_unmap_single_attrs vtd_unmap_single_attrs +#define platform_dma_map_sg_attrs vtd_map_sg_attrs +#define platform_dma_unmap_sg_attrs vtd_unmap_sg_attrs +#define platform_dma_sync_single_for_cpu machvec_dma_sync_single +#define platform_dma_sync_sg_for_cpu machvec_dma_sync_sg +#define platform_dma_sync_single_for_device machvec_dma_sync_single +#define platform_dma_sync_sg_for_device machvec_dma_sync_sg +#define platform_dma_supported iommu_dma_supported +#define platform_dma_mapping_error vtd_dma_mapping_error + +#endif /* _ASM_IA64_MACHVEC_DIG_VTD_h */ diff --git a/arch/ia64/include/asm/machvec_init.h b/arch/ia64/include/asm/machvec_init.h index 7f21249..ef964b2 100644 --- a/arch/ia64/include/asm/machvec_init.h +++ b/arch/ia64/include/asm/machvec_init.h @@ -1,3 +1,4 @@ +#include <asm/iommu.h> #include <asm/machvec.h> extern ia64_mv_send_ipi_t ia64_send_ipi; diff --git a/arch/ia64/include/asm/machvec_xen.h b/arch/ia64/include/asm/machvec_xen.h new file mode 100644 index 0000000..55f9228 --- /dev/null +++ b/arch/ia64/include/asm/machvec_xen.h @@ -0,0 +1,22 @@ +#ifndef _ASM_IA64_MACHVEC_XEN_h +#define _ASM_IA64_MACHVEC_XEN_h + +extern ia64_mv_setup_t dig_setup; +extern ia64_mv_cpu_init_t xen_cpu_init; +extern ia64_mv_irq_init_t xen_irq_init; +extern ia64_mv_send_ipi_t xen_platform_send_ipi; + +/* + * This stuff has dual use! + * + * For a generic kernel, the macros are used to initialize the + * platform's machvec structure. When compiling a non-generic kernel, + * the macros are used directly. + */ +#define platform_name "xen" +#define platform_setup dig_setup +#define platform_cpu_init xen_cpu_init +#define platform_irq_init xen_irq_init +#define platform_send_ipi xen_platform_send_ipi + +#endif /* _ASM_IA64_MACHVEC_XEN_h */ diff --git a/arch/ia64/include/asm/meminit.h b/arch/ia64/include/asm/meminit.h index 7245a57..c0cea37 100644 --- a/arch/ia64/include/asm/meminit.h +++ b/arch/ia64/include/asm/meminit.h @@ -18,10 +18,11 @@ * - crash dumping code reserved region * - Kernel memory map built from EFI memory map * - ELF core header + * - xen start info if CONFIG_XEN * * More could be added if necessary */ -#define IA64_MAX_RSVD_REGIONS 8 +#define IA64_MAX_RSVD_REGIONS 9 struct rsvd_region { unsigned long start; /* virtual address of beginning of element */ @@ -47,7 +48,6 @@ extern int reserve_elfcorehdr(unsigned long *start, unsigned long *end); */ #define GRANULEROUNDDOWN(n) ((n) & ~(IA64_GRANULE_SIZE-1)) #define GRANULEROUNDUP(n) (((n)+IA64_GRANULE_SIZE-1) & ~(IA64_GRANULE_SIZE-1)) -#define ORDERROUNDDOWN(n) ((n) & ~((PAGE_SIZE<<MAX_ORDER)-1)) #ifdef CONFIG_NUMA extern void call_pernode_memory (unsigned long start, unsigned long len, void *func); diff --git a/arch/ia64/include/asm/native/inst.h b/arch/ia64/include/asm/native/inst.h index c8efbf7..0a1026c 100644 --- a/arch/ia64/include/asm/native/inst.h +++ b/arch/ia64/include/asm/native/inst.h @@ -36,8 +36,13 @@ ;; \ movl clob = PARAVIRT_POISON; \ ;; +# define CLOBBER_PRED(pred_clob) \ + ;; \ + cmp.eq pred_clob, p0 = r0, r0 \ + ;; #else -# define CLOBBER(clob) /* nothing */ +# define CLOBBER(clob) /* nothing */ +# define CLOBBER_PRED(pred_clob) /* nothing */ #endif #define MOV_FROM_IFA(reg) \ @@ -136,7 +141,8 @@ #define SSM_PSR_I(pred, pred_clob, clob) \ (pred) ssm psr.i \ - CLOBBER(clob) + CLOBBER(clob) \ + CLOBBER_PRED(pred_clob) #define RSM_PSR_I(pred, clob0, clob1) \ (pred) rsm psr.i \ diff --git a/arch/ia64/include/asm/native/pvchk_inst.h b/arch/ia64/include/asm/native/pvchk_inst.h new file mode 100644 index 0000000..b8e6eb1 --- /dev/null +++ b/arch/ia64/include/asm/native/pvchk_inst.h @@ -0,0 +1,263 @@ +#ifndef _ASM_NATIVE_PVCHK_INST_H +#define _ASM_NATIVE_PVCHK_INST_H + +/****************************************************************************** + * arch/ia64/include/asm/native/pvchk_inst.h + * Checker for paravirtualizations of privileged operations. + * + * Copyright (C) 2005 Hewlett-Packard Co + * Dan Magenheimer <dan.magenheimer@hp.com> + * + * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp> + * VA Linux Systems Japan K.K. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/********************************************** + * Instructions paravirtualized for correctness + **********************************************/ + +/* "fc" and "thash" are privilege-sensitive instructions, meaning they + * may have different semantics depending on whether they are executed + * at PL0 vs PL!=0. When paravirtualized, these instructions mustn't + * be allowed to execute directly, lest incorrect semantics result. + */ + +#define fc .error "fc should not be used directly." +#define thash .error "thash should not be used directly." + +/* Note that "ttag" and "cover" are also privilege-sensitive; "ttag" + * is not currently used (though it may be in a long-format VHPT system!) + * and the semantics of cover only change if psr.ic is off which is very + * rare (and currently non-existent outside of assembly code + */ +#define ttag .error "ttag should not be used directly." +#define cover .error "cover should not be used directly." + +/* There are also privilege-sensitive registers. These registers are + * readable at any privilege level but only writable at PL0. + */ +#define cpuid .error "cpuid should not be used directly." +#define pmd .error "pmd should not be used directly." + +/* + * mov ar.eflag = + * mov = ar.eflag + */ + +/********************************************** + * Instructions paravirtualized for performance + **********************************************/ +/* + * Those instructions include '.' which can't be handled by cpp. + * or can't be handled by cpp easily. + * They are handled by sed instead of cpp. + */ + +/* for .S + * itc.i + * itc.d + * + * bsw.0 + * bsw.1 + * + * ssm psr.ic | PSR_DEFAULT_BITS + * ssm psr.ic + * rsm psr.ic + * ssm psr.i + * rsm psr.i + * rsm psr.i | psr.ic + * rsm psr.dt + * ssm psr.dt + * + * mov = cr.ifa + * mov = cr.itir + * mov = cr.isr + * mov = cr.iha + * mov = cr.ipsr + * mov = cr.iim + * mov = cr.iip + * mov = cr.ivr + * mov = psr + * + * mov cr.ifa = + * mov cr.itir = + * mov cr.iha = + * mov cr.ipsr = + * mov cr.ifs = + * mov cr.iip = + * mov cr.kr = + */ + +/* for intrinsics + * ssm psr.i + * rsm psr.i + * mov = psr + * mov = ivr + * mov = tpr + * mov cr.itm = + * mov eoi = + * mov rr[] = + * mov = rr[] + * mov = kr + * mov kr = + * ptc.ga + */ + +/************************************************************* + * define paravirtualized instrcution macros as nop to ingore. + * and check whether arguments are appropriate. + *************************************************************/ + +/* check whether reg is a regular register */ +.macro is_rreg_in reg + .ifc "\reg", "r0" + nop 0 + .exitm + .endif + ;; + mov \reg = r0 + ;; +.endm +#define IS_RREG_IN(reg) is_rreg_in reg ; + +#define IS_RREG_OUT(reg) \ + ;; \ + mov reg = r0 \ + ;; + +#define IS_RREG_CLOB(reg) IS_RREG_OUT(reg) + +/* check whether pred is a predicate register */ +#define IS_PRED_IN(pred) \ + ;; \ + (pred) nop 0 \ + ;; + +#define IS_PRED_OUT(pred) \ + ;; \ + cmp.eq pred, p0 = r0, r0 \ + ;; + +#define IS_PRED_CLOB(pred) IS_PRED_OUT(pred) + + +#define DO_SAVE_MIN(__COVER, SAVE_IFS, EXTRA, WORKAROUND) \ + nop 0 +#define MOV_FROM_IFA(reg) \ + IS_RREG_OUT(reg) +#define MOV_FROM_ITIR(reg) \ + IS_RREG_OUT(reg) +#define MOV_FROM_ISR(reg) \ + IS_RREG_OUT(reg) +#define MOV_FROM_IHA(reg) \ + IS_RREG_OUT(reg) +#define MOV_FROM_IPSR(pred, reg) \ + IS_PRED_IN(pred) \ + IS_RREG_OUT(reg) +#define MOV_FROM_IIM(reg) \ + IS_RREG_OUT(reg) +#define MOV_FROM_IIP(reg) \ + IS_RREG_OUT(reg) +#define MOV_FROM_IVR(reg, clob) \ + IS_RREG_OUT(reg) \ + IS_RREG_CLOB(clob) +#define MOV_FROM_PSR(pred, reg, clob) \ + IS_PRED_IN(pred) \ + IS_RREG_OUT(reg) \ + IS_RREG_CLOB(clob) +#define MOV_TO_IFA(reg, clob) \ + IS_RREG_IN(reg) \ + IS_RREG_CLOB(clob) +#define MOV_TO_ITIR(pred, reg, clob) \ + IS_PRED_IN(pred) \ + IS_RREG_IN(reg) \ + IS_RREG_CLOB(clob) +#define MOV_TO_IHA(pred, reg, clob) \ + IS_PRED_IN(pred) \ + IS_RREG_IN(reg) \ + IS_RREG_CLOB(clob) +#define MOV_TO_IPSR(pred, reg, clob) \ + IS_PRED_IN(pred) \ + IS_RREG_IN(reg) \ + IS_RREG_CLOB(clob) +#define MOV_TO_IFS(pred, reg, clob) \ + IS_PRED_IN(pred) \ + IS_RREG_IN(reg) \ + IS_RREG_CLOB(clob) +#define MOV_TO_IIP(reg, clob) \ + IS_RREG_IN(reg) \ + IS_RREG_CLOB(clob) +#define MOV_TO_KR(kr, reg, clob0, clob1) \ + IS_RREG_IN(reg) \ + IS_RREG_CLOB(clob0) \ + IS_RREG_CLOB(clob1) +#define ITC_I(pred, reg, clob) \ + IS_PRED_IN(pred) \ + IS_RREG_IN(reg) \ + IS_RREG_CLOB(clob) +#define ITC_D(pred, reg, clob) \ + IS_PRED_IN(pred) \ + IS_RREG_IN(reg) \ + IS_RREG_CLOB(clob) +#define ITC_I_AND_D(pred_i, pred_d, reg, clob) \ + IS_PRED_IN(pred_i) \ + IS_PRED_IN(pred_d) \ + IS_RREG_IN(reg) \ + IS_RREG_CLOB(clob) +#define THASH(pred, reg0, reg1, clob) \ + IS_PRED_IN(pred) \ + IS_RREG_OUT(reg0) \ + IS_RREG_IN(reg1) \ + IS_RREG_CLOB(clob) +#define SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(clob0, clob1) \ + IS_RREG_CLOB(clob0) \ + IS_RREG_CLOB(clob1) +#define SSM_PSR_IC_AND_SRLZ_D(clob0, clob1) \ + IS_RREG_CLOB(clob0) \ + IS_RREG_CLOB(clob1) +#define RSM_PSR_IC(clob) \ + IS_RREG_CLOB(clob) +#define SSM_PSR_I(pred, pred_clob, clob) \ + IS_PRED_IN(pred) \ + IS_PRED_CLOB(pred_clob) \ + IS_RREG_CLOB(clob) +#define RSM_PSR_I(pred, clob0, clob1) \ + IS_PRED_IN(pred) \ + IS_RREG_CLOB(clob0) \ + IS_RREG_CLOB(clob1) +#define RSM_PSR_I_IC(clob0, clob1, clob2) \ + IS_RREG_CLOB(clob0) \ + IS_RREG_CLOB(clob1) \ + IS_RREG_CLOB(clob2) +#define RSM_PSR_DT \ + nop 0 +#define SSM_PSR_DT_AND_SRLZ_I \ + nop 0 +#define BSW_0(clob0, clob1, clob2) \ + IS_RREG_CLOB(clob0) \ + IS_RREG_CLOB(clob1) \ + IS_RREG_CLOB(clob2) +#define BSW_1(clob0, clob1) \ + IS_RREG_CLOB(clob0) \ + IS_RREG_CLOB(clob1) +#define COVER \ + nop 0 +#define RFI \ + br.ret.sptk.many rp /* defining nop causes dependency error */ + +#endif /* _ASM_NATIVE_PVCHK_INST_H */ diff --git a/arch/ia64/include/asm/paravirt.h b/arch/ia64/include/asm/paravirt.h index 660cab0..2bf3636 100644 --- a/arch/ia64/include/asm/paravirt.h +++ b/arch/ia64/include/asm/paravirt.h @@ -117,7 +117,7 @@ static inline void paravirt_post_smp_prepare_boot_cpu(void) struct pv_iosapic_ops { void (*pcat_compat_init)(void); - struct irq_chip *(*get_irq_chip)(unsigned long trigger); + struct irq_chip *(*__get_irq_chip)(unsigned long trigger); unsigned int (*__read)(char __iomem *iosapic, unsigned int reg); void (*__write)(char __iomem *iosapic, unsigned int reg, u32 val); @@ -135,7 +135,7 @@ iosapic_pcat_compat_init(void) static inline struct irq_chip* iosapic_get_irq_chip(unsigned long trigger) { - return pv_iosapic_ops.get_irq_chip(trigger); + return pv_iosapic_ops.__get_irq_chip(trigger); } static inline unsigned int diff --git a/arch/ia64/include/asm/paravirt_privop.h b/arch/ia64/include/asm/paravirt_privop.h index d577aac..33c8e55 100644 --- a/arch/ia64/include/asm/paravirt_privop.h +++ b/arch/ia64/include/asm/paravirt_privop.h @@ -78,6 +78,18 @@ extern unsigned long ia64_native_getreg_func(int regnum); ia64_native_rsm(mask); \ } while (0) +/* returned ip value should be the one in the caller, + * not in __paravirt_getreg() */ +#define paravirt_getreg(reg) \ + ({ \ + unsigned long res; \ + if ((reg) == _IA64_REG_IP) \ + res = ia64_native_getreg(_IA64_REG_IP); \ + else \ + res = pv_cpu_ops.getreg(reg); \ + res; \ + }) + /****************************************************************************** * replacement of hand written assembly codes. */ diff --git a/arch/ia64/include/asm/pci.h b/arch/ia64/include/asm/pci.h index 0149097..1d660d8 100644 --- a/arch/ia64/include/asm/pci.h +++ b/arch/ia64/include/asm/pci.h @@ -95,16 +95,8 @@ extern int pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma, enum pci_mmap_state mmap_state, int write_combine); #define HAVE_PCI_LEGACY extern int pci_mmap_legacy_page_range(struct pci_bus *bus, - struct vm_area_struct *vma); -extern ssize_t pci_read_legacy_io(struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, loff_t off, size_t count); -extern ssize_t pci_write_legacy_io(struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, loff_t off, size_t count); -extern int pci_mmap_legacy_mem(struct kobject *kobj, - struct bin_attribute *attr, - struct vm_area_struct *vma); + struct vm_area_struct *vma, + enum pci_mmap_state mmap_state); #define pci_get_legacy_mem platform_pci_get_legacy_mem #define pci_legacy_read platform_pci_legacy_read @@ -164,4 +156,7 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel) return channel ? isa_irq_to_vector(15) : isa_irq_to_vector(14); } +#ifdef CONFIG_DMAR +extern void pci_iommu_alloc(void); +#endif #endif /* _ASM_IA64_PCI_H */ diff --git a/arch/ia64/include/asm/ptrace.h b/arch/ia64/include/asm/ptrace.h index 15f8dcf..14055c6 100644 --- a/arch/ia64/include/asm/ptrace.h +++ b/arch/ia64/include/asm/ptrace.h @@ -240,6 +240,12 @@ struct switch_stack { */ # define instruction_pointer(regs) ((regs)->cr_iip + ia64_psr(regs)->ri) +static inline unsigned long user_stack_pointer(struct pt_regs *regs) +{ + /* FIXME: should this be bspstore + nr_dirty regs? */ + return regs->ar_bspstore; +} + #define regs_return_value(regs) ((regs)->r8) /* Conserve space in histogram by encoding slot bits in address diff --git a/arch/ia64/include/asm/pvclock-abi.h b/arch/ia64/include/asm/pvclock-abi.h new file mode 100644 index 0000000..44ef9ef --- /dev/null +++ b/arch/ia64/include/asm/pvclock-abi.h @@ -0,0 +1,48 @@ +/* + * same structure to x86's + * Hopefully asm-x86/pvclock-abi.h would be moved to somewhere more generic. + * For now, define same duplicated definitions. + */ + +#ifndef _ASM_IA64__PVCLOCK_ABI_H +#define _ASM_IA64__PVCLOCK_ABI_H +#ifndef __ASSEMBLY__ + +/* + * These structs MUST NOT be changed. + * They are the ABI between hypervisor and guest OS. + * Both Xen and KVM are using this. + * + * pvclock_vcpu_time_info holds the system time and the tsc timestamp + * of the last update. So the guest can use the tsc delta to get a + * more precise system time. There is one per virtual cpu. + * + * pvclock_wall_clock references the point in time when the system + * time was zero (usually boot time), thus the guest calculates the + * current wall clock by adding the system time. + * + * Protocol for the "version" fields is: hypervisor raises it (making + * it uneven) before it starts updating the fields and raises it again + * (making it even) when it is done. Thus the guest can make sure the + * time values it got are consistent by checking the version before + * and after reading them. + */ + +struct pvclock_vcpu_time_info { + u32 version; + u32 pad0; + u64 tsc_timestamp; + u64 system_time; + u32 tsc_to_system_mul; + s8 tsc_shift; + u8 pad[3]; +} __attribute__((__packed__)); /* 32 bytes */ + +struct pvclock_wall_clock { + u32 version; + u32 sec; + u32 nsec; +} __attribute__((__packed__)); + +#endif /* __ASSEMBLY__ */ +#endif /* _ASM_IA64__PVCLOCK_ABI_H */ diff --git a/arch/ia64/include/asm/sal.h b/arch/ia64/include/asm/sal.h index ea310c0..966797a 100644 --- a/arch/ia64/include/asm/sal.h +++ b/arch/ia64/include/asm/sal.h @@ -337,11 +337,24 @@ typedef struct sal_log_record_header { #define sal_log_severity_fatal 1 #define sal_log_severity_corrected 2 +/* + * Error Recovery Info (ERI) bit decode. From SAL Spec section B.2.2 Table B-3 + * Error Section Error_Recovery_Info Field Definition. + */ +#define ERI_NOT_VALID 0x0 /* Error Recovery Field is not valid */ +#define ERI_NOT_ACCESSIBLE 0x30 /* Resource not accessible */ +#define ERI_CONTAINMENT_WARN 0x22 /* Corrupt data propagated */ +#define ERI_UNCORRECTED_ERROR 0x20 /* Uncorrected error */ +#define ERI_COMPONENT_RESET 0x24 /* Component must be reset */ +#define ERI_CORR_ERROR_LOG 0x21 /* Corrected error, needs logging */ +#define ERI_CORR_ERROR_THRESH 0x29 /* Corrected error threshold exceeded */ + /* Definition of log section header structures */ typedef struct sal_log_sec_header { efi_guid_t guid; /* Unique Section ID */ sal_log_revision_t revision; /* Major and Minor revision of Section */ - u16 reserved; + u8 error_recovery_info; /* Platform error recovery status */ + u8 reserved; u32 len; /* Section length */ } sal_log_section_hdr_t; diff --git a/arch/ia64/include/asm/sn/sn_sal.h b/arch/ia64/include/asm/sn/sn_sal.h index 57e649d..e310fc0 100644 --- a/arch/ia64/include/asm/sn/sn_sal.h +++ b/arch/ia64/include/asm/sn/sn_sal.h @@ -90,6 +90,8 @@ #define SN_SAL_SET_CPU_NUMBER 0x02000068 #define SN_SAL_KERNEL_LAUNCH_EVENT 0x02000069 +#define SN_SAL_WATCHLIST_ALLOC 0x02000070 +#define SN_SAL_WATCHLIST_FREE 0x02000071 /* * Service-specific constants @@ -1185,4 +1187,47 @@ ia64_sn_kernel_launch_event(void) SAL_CALL_NOLOCK(rv, SN_SAL_KERNEL_LAUNCH_EVENT, 0, 0, 0, 0, 0, 0, 0); return rv.status; } + +union sn_watchlist_u { + u64 val; + struct { + u64 blade : 16, + size : 32, + filler : 16; + }; +}; + +static inline int +sn_mq_watchlist_alloc(int blade, void *mq, unsigned int mq_size, + unsigned long *intr_mmr_offset) +{ + struct ia64_sal_retval rv; + unsigned long addr; + union sn_watchlist_u size_blade; + int watchlist; + + addr = (unsigned long)mq; + size_blade.size = mq_size; + size_blade.blade = blade; + + /* + * bios returns watchlist number or negative error number. + */ + ia64_sal_oemcall_nolock(&rv, SN_SAL_WATCHLIST_ALLOC, addr, + size_blade.val, (u64)intr_mmr_offset, + (u64)&watchlist, 0, 0, 0); + if (rv.status < 0) + return rv.status; + + return watchlist; +} + +static inline int +sn_mq_watchlist_free(int blade, int watchlist_num) +{ + struct ia64_sal_retval rv; + ia64_sal_oemcall_nolock(&rv, SN_SAL_WATCHLIST_FREE, blade, + watchlist_num, 0, 0, 0, 0, 0); + return rv.status; +} #endif /* _ASM_IA64_SN_SN_SAL_H */ diff --git a/arch/ia64/include/asm/swiotlb.h b/arch/ia64/include/asm/swiotlb.h new file mode 100644 index 0000000..fb79423 --- /dev/null +++ b/arch/ia64/include/asm/swiotlb.h @@ -0,0 +1,56 @@ +#ifndef ASM_IA64__SWIOTLB_H +#define ASM_IA64__SWIOTLB_H + +#include <linux/dma-mapping.h> + +/* SWIOTLB interface */ + +extern dma_addr_t swiotlb_map_single(struct device *hwdev, void *ptr, + size_t size, int dir); +extern void *swiotlb_alloc_coherent(struct device *hwdev, size_t size, + dma_addr_t *dma_handle, gfp_t flags); +extern void swiotlb_unmap_single(struct device *hwdev, dma_addr_t dev_addr, + size_t size, int dir); +extern void swiotlb_sync_single_for_cpu(struct device *hwdev, + dma_addr_t dev_addr, + size_t size, int dir); +extern void swiotlb_sync_single_for_device(struct device *hwdev, + dma_addr_t dev_addr, + size_t size, int dir); +extern void swiotlb_sync_single_range_for_cpu(struct device *hwdev, + dma_addr_t dev_addr, + unsigned long offset, + size_t size, int dir); +extern void swiotlb_sync_single_range_for_device(struct device *hwdev, + dma_addr_t dev_addr, + unsigned long offset, + size_t size, int dir); +extern void swiotlb_sync_sg_for_cpu(struct device *hwdev, + struct scatterlist *sg, int nelems, + int dir); +extern void swiotlb_sync_sg_for_device(struct device *hwdev, + struct scatterlist *sg, int nelems, + int dir); +extern int swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg, + int nents, int direction); +extern void swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sg, + int nents, int direction); +extern int swiotlb_dma_mapping_error(struct device *hwdev, dma_addr_t dma_addr); +extern void swiotlb_free_coherent(struct device *hwdev, size_t size, + void *vaddr, dma_addr_t dma_handle); +extern int swiotlb_dma_supported(struct device *hwdev, u64 mask); +extern void swiotlb_init(void); + +extern int swiotlb_force; + +#ifdef CONFIG_SWIOTLB +extern int swiotlb; +extern void pci_swiotlb_init(void); +#else +#define swiotlb 0 +static inline void pci_swiotlb_init(void) +{ +} +#endif + +#endif /* ASM_IA64__SWIOTLB_H */ diff --git a/arch/ia64/include/asm/sync_bitops.h b/arch/ia64/include/asm/sync_bitops.h new file mode 100644 index 0000000..593c12e --- /dev/null +++ b/arch/ia64/include/asm/sync_bitops.h @@ -0,0 +1,51 @@ +#ifndef _ASM_IA64_SYNC_BITOPS_H +#define _ASM_IA64_SYNC_BITOPS_H + +/* + * Copyright (C) 2008 Isaku Yamahata <yamahata at valinux co jp> + * + * Based on synch_bitops.h which Dan Magenhaimer wrote. + * + * bit operations which provide guaranteed strong synchronisation + * when communicating with Xen or other guest OSes running on other CPUs. + */ + +static inline void sync_set_bit(int nr, volatile void *addr) +{ + set_bit(nr, addr); +} + +static inline void sync_clear_bit(int nr, volatile void *addr) +{ + clear_bit(nr, addr); +} + +static inline void sync_change_bit(int nr, volatile void *addr) +{ + change_bit(nr, addr); +} + +static inline int sync_test_and_set_bit(int nr, volatile void *addr) +{ + return test_and_set_bit(nr, addr); +} + +static inline int sync_test_and_clear_bit(int nr, volatile void *addr) +{ + return test_and_clear_bit(nr, addr); +} + +static inline int sync_test_and_change_bit(int nr, volatile void *addr) +{ + return test_and_change_bit(nr, addr); +} + +static inline int sync_test_bit(int nr, const volatile void *addr) +{ + return test_bit(nr, addr); +} + +#define sync_cmpxchg(ptr, old, new) \ + ((__typeof__(*(ptr)))cmpxchg_acq((ptr), (old), (new))) + +#endif /* _ASM_IA64_SYNC_BITOPS_H */ diff --git a/arch/ia64/include/asm/syscall.h b/arch/ia64/include/asm/syscall.h new file mode 100644 index 0000000..2f758a4 --- /dev/null +++ b/arch/ia64/include/asm/syscall.h @@ -0,0 +1,163 @@ +/* + * Access to user system call parameters and results + * + * Copyright (C) 2008 Intel Corp. Shaohua Li <shaohua.li@intel.com> + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU General Public License v.2. + * + * See asm-generic/syscall.h for descriptions of what we must do here. + */ + +#ifndef _ASM_SYSCALL_H +#define _ASM_SYSCALL_H 1 + +#include <linux/sched.h> +#include <linux/err.h> + +static inline long syscall_get_nr(struct task_struct *task, + struct pt_regs *regs) +{ + if ((long)regs->cr_ifs < 0) /* Not a syscall */ + return -1; + +#ifdef CONFIG_IA32_SUPPORT + if (IS_IA32_PROCESS(regs)) + return regs->r1; +#endif + + return regs->r15; +} + +static inline void syscall_rollback(struct task_struct *task, + struct pt_regs *regs) +{ +#ifdef CONFIG_IA32_SUPPORT + if (IS_IA32_PROCESS(regs)) + regs->r8 = regs->r1; +#endif + + /* do nothing */ +} + +static inline long syscall_get_error(struct task_struct *task, + struct pt_regs *regs) +{ +#ifdef CONFIG_IA32_SUPPORT + if (IS_IA32_PROCESS(regs)) + return regs->r8; +#endif + + return regs->r10 == -1 ? regs->r8:0; +} + +static inline long syscall_get_return_value(struct task_struct *task, + struct pt_regs *regs) +{ + return regs->r8; +} + +static inline void syscall_set_return_value(struct task_struct *task, + struct pt_regs *regs, + int error, long val) +{ +#ifdef CONFIG_IA32_SUPPORT + if (IS_IA32_PROCESS(regs)) { + regs->r8 = (long) error ? error : val; + return; + } +#endif + + if (error) { + /* error < 0, but ia64 uses > 0 return value */ + regs->r8 = -error; + regs->r10 = -1; + } else { + regs->r8 = val; + regs->r10 = 0; + } +} + +extern void ia64_syscall_get_set_arguments(struct task_struct *task, + struct pt_regs *regs, unsigned int i, unsigned int n, + unsigned long *args, int rw); +static inline void syscall_get_arguments(struct task_struct *task, + struct pt_regs *regs, + unsigned int i, unsigned int n, + unsigned long *args) +{ + BUG_ON(i + n > 6); + +#ifdef CONFIG_IA32_SUPPORT + if (IS_IA32_PROCESS(regs)) { + switch (i + n) { + case 6: + if (!n--) break; + *args++ = regs->r13; + case 5: + if (!n--) break; + *args++ = regs->r15; + case 4: + if (!n--) break; + *args++ = regs->r14; + case 3: + if (!n--) break; + *args++ = regs->r10; + case 2: + if (!n--) break; + *args++ = regs->r9; + case 1: + if (!n--) break; + *args++ = regs->r11; + case 0: + if (!n--) break; + default: + BUG(); + break; + } + + return; + } +#endif + ia64_syscall_get_set_arguments(task, regs, i, n, args, 0); +} + +static inline void syscall_set_arguments(struct task_struct *task, + struct pt_regs *regs, + unsigned int i, unsigned int n, + unsigned long *args) +{ + BUG_ON(i + n > 6); + +#ifdef CONFIG_IA32_SUPPORT + if (IS_IA32_PROCESS(regs)) { + switch (i + n) { + case 6: + if (!n--) break; + regs->r13 = *args++; + case 5: + if (!n--) break; + regs->r15 = *args++; + case 4: + if (!n--) break; + regs->r14 = *args++; + case 3: + if (!n--) break; + regs->r10 = *args++; + case 2: + if (!n--) break; + regs->r9 = *args++; + case 1: + if (!n--) break; + regs->r11 = *args++; + case 0: + if (!n--) break; + } + + return; + } +#endif + ia64_syscall_get_set_arguments(task, regs, i, n, args, 1); +} +#endif /* _ASM_SYSCALL_H */ diff --git a/arch/ia64/include/asm/thread_info.h b/arch/ia64/include/asm/thread_info.h index 7c60fcd..ae69226 100644 --- a/arch/ia64/include/asm/thread_info.h +++ b/arch/ia64/include/asm/thread_info.h @@ -87,9 +87,6 @@ struct thread_info { #define alloc_task_struct() ((struct task_struct *)__get_free_pages(GFP_KERNEL | __GFP_COMP, KERNEL_STACK_SIZE_ORDER)) #define free_task_struct(tsk) free_pages((unsigned long) (tsk), KERNEL_STACK_SIZE_ORDER) -#define tsk_set_notify_resume(tsk) \ - set_ti_thread_flag(task_thread_info(tsk), TIF_NOTIFY_RESUME) -extern void tsk_clear_notify_resume(struct task_struct *tsk); #endif /* !__ASSEMBLY */ /* diff --git a/arch/ia64/include/asm/timex.h b/arch/ia64/include/asm/timex.h index 05a6baf..4e03cfe 100644 --- a/arch/ia64/include/asm/timex.h +++ b/arch/ia64/include/asm/timex.h @@ -39,4 +39,6 @@ get_cycles (void) return ret; } +extern void ia64_cpu_local_tick (void); + #endif /* _ASM_IA64_TIMEX_H */ diff --git a/arch/ia64/include/asm/unistd.h b/arch/ia64/include/asm/unistd.h index d535833..f791576 100644 --- a/arch/ia64/include/asm/unistd.h +++ b/arch/ia64/include/asm/unistd.h @@ -337,6 +337,7 @@ # define __ARCH_WANT_SYS_NICE # define __ARCH_WANT_SYS_OLD_GETRLIMIT # define __ARCH_WANT_SYS_OLDUMOUNT +# define __ARCH_WANT_SYS_PAUSE # define __ARCH_WANT_SYS_SIGPENDING # define __ARCH_WANT_SYS_SIGPROCMASK # define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND diff --git a/arch/ia64/include/asm/xen/events.h b/arch/ia64/include/asm/xen/events.h new file mode 100644 index 0000000..7324878 --- /dev/null +++ b/arch/ia64/include/asm/xen/events.h @@ -0,0 +1,50 @@ +/****************************************************************************** + * arch/ia64/include/asm/xen/events.h + * + * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp> + * VA Linux Systems Japan K.K. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#ifndef _ASM_IA64_XEN_EVENTS_H +#define _ASM_IA64_XEN_EVENTS_H + +enum ipi_vector { + XEN_RESCHEDULE_VECTOR, + XEN_IPI_VECTOR, + XEN_CMCP_VECTOR, + XEN_CPEP_VECTOR, + + XEN_NR_IPIS, +}; + +static inline int xen_irqs_disabled(struct pt_regs *regs) +{ + return !(ia64_psr(regs)->i); +} + +static inline void xen_do_IRQ(int irq, struct pt_regs *regs) +{ + struct pt_regs *old_regs; + old_regs = set_irq_regs(regs); + irq_enter(); + __do_IRQ(irq); + irq_exit(); + set_irq_regs(old_regs); +} +#define irq_ctx_init(cpu) do { } while (0) + +#endif /* _ASM_IA64_XEN_EVENTS_H */ diff --git a/arch/ia64/include/asm/xen/grant_table.h b/arch/ia64/include/asm/xen/grant_table.h new file mode 100644 index 0000000..2b1fae0 --- /dev/null +++ b/arch/ia64/include/asm/xen/grant_table.h @@ -0,0 +1,29 @@ +/****************************************************************************** + * arch/ia64/include/asm/xen/grant_table.h + * + * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp> + * VA Linux Systems Japan K.K. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef _ASM_IA64_XEN_GRANT_TABLE_H +#define _ASM_IA64_XEN_GRANT_TABLE_H + +struct vm_struct *xen_alloc_vm_area(unsigned long size); +void xen_free_vm_area(struct vm_struct *area); + +#endif /* _ASM_IA64_XEN_GRANT_TABLE_H */ diff --git a/arch/ia64/include/asm/xen/hypercall.h b/arch/ia64/include/asm/xen/hypercall.h new file mode 100644 index 0000000..96fc623 --- /dev/null +++ b/arch/ia64/include/asm/xen/hypercall.h @@ -0,0 +1,265 @@ +/****************************************************************************** + * hypercall.h + * + * Linux-specific hypervisor handling. + * + * Copyright (c) 2002-2004, K A Fraser + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation; or, when distributed + * separately from the Linux kernel or incorporated into other + * software packages, subject to the following license: + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this source file (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef _ASM_IA64_XEN_HYPERCALL_H +#define _ASM_IA64_XEN_HYPERCALL_H + +#include <xen/interface/xen.h> +#include <xen/interface/physdev.h> +#include <xen/interface/sched.h> +#include <asm/xen/xcom_hcall.h> +struct xencomm_handle; +extern unsigned long __hypercall(unsigned long a1, unsigned long a2, + unsigned long a3, unsigned long a4, + unsigned long a5, unsigned long cmd); + +/* + * Assembler stubs for hyper-calls. + */ + +#define _hypercall0(type, name) \ +({ \ + long __res; \ + __res = __hypercall(0, 0, 0, 0, 0, __HYPERVISOR_##name);\ + (type)__res; \ +}) + +#define _hypercall1(type, name, a1) \ +({ \ + long __res; \ + __res = __hypercall((unsigned long)a1, \ + 0, 0, 0, 0, __HYPERVISOR_##name); \ + (type)__res; \ +}) + +#define _hypercall2(type, name, a1, a2) \ +({ \ + long __res; \ + __res = __hypercall((unsigned long)a1, \ + (unsigned long)a2, \ + 0, 0, 0, __HYPERVISOR_##name); \ + (type)__res; \ +}) + +#define _hypercall3(type, name, a1, a2, a3) \ +({ \ + long __res; \ + __res = __hypercall((unsigned long)a1, \ + (unsigned long)a2, \ + (unsigned long)a3, \ + 0, 0, __HYPERVISOR_##name); \ + (type)__res; \ +}) + +#define _hypercall4(type, name, a1, a2, a3, a4) \ +({ \ + long __res; \ + __res = __hypercall((unsigned long)a1, \ + (unsigned long)a2, \ + (unsigned long)a3, \ + (unsigned long)a4, \ + 0, __HYPERVISOR_##name); \ + (type)__res; \ +}) + +#define _hypercall5(type, name, a1, a2, a3, a4, a5) \ +({ \ + long __res; \ + __res = __hypercall((unsigned long)a1, \ + (unsigned long)a2, \ + (unsigned long)a3, \ + (unsigned long)a4, \ + (unsigned long)a5, \ + __HYPERVISOR_##name); \ + (type)__res; \ +}) + + +static inline int +xencomm_arch_hypercall_sched_op(int cmd, struct xencomm_handle *arg) +{ + return _hypercall2(int, sched_op_new, cmd, arg); +} + +static inline long +HYPERVISOR_set_timer_op(u64 timeout) +{ + unsigned long timeout_hi = (unsigned long)(timeout >> 32); + unsigned long timeout_lo = (unsigned long)timeout; + return _hypercall2(long, set_timer_op, timeout_lo, timeout_hi); +} + +static inline int +xencomm_arch_hypercall_multicall(struct xencomm_handle *call_list, + int nr_calls) +{ + return _hypercall2(int, multicall, call_list, nr_calls); +} + +static inline int +xencomm_arch_hypercall_memory_op(unsigned int cmd, struct xencomm_handle *arg) +{ + return _hypercall2(int, memory_op, cmd, arg); +} + +static inline int +xencomm_arch_hypercall_event_channel_op(int cmd, struct xencomm_handle *arg) +{ + return _hypercall2(int, event_channel_op, cmd, arg); +} + +static inline int +xencomm_arch_hypercall_xen_version(int cmd, struct xencomm_handle *arg) +{ + return _hypercall2(int, xen_version, cmd, arg); +} + +static inline int +xencomm_arch_hypercall_console_io(int cmd, int count, + struct xencomm_handle *str) +{ + return _hypercall3(int, console_io, cmd, count, str); +} + +static inline int +xencomm_arch_hypercall_physdev_op(int cmd, struct xencomm_handle *arg) +{ + return _hypercall2(int, physdev_op, cmd, arg); +} + +static inline int +xencomm_arch_hypercall_grant_table_op(unsigned int cmd, + struct xencomm_handle *uop, + unsigned int count) +{ + return _hypercall3(int, grant_table_op, cmd, uop, count); +} + +int HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count); + +extern int xencomm_arch_hypercall_suspend(struct xencomm_handle *arg); + +static inline int +xencomm_arch_hypercall_callback_op(int cmd, struct xencomm_handle *arg) +{ + return _hypercall2(int, callback_op, cmd, arg); +} + +static inline long +xencomm_arch_hypercall_vcpu_op(int cmd, int cpu, void *arg) +{ + return _hypercall3(long, vcpu_op, cmd, cpu, arg); +} + +static inline int +HYPERVISOR_physdev_op(int cmd, void *arg) +{ + switch (cmd) { + case PHYSDEVOP_eoi: + return _hypercall1(int, ia64_fast_eoi, + ((struct physdev_eoi *)arg)->irq); + default: + return xencomm_hypercall_physdev_op(cmd, arg); + } +} + +static inline long +xencomm_arch_hypercall_opt_feature(struct xencomm_handle *arg) +{ + return _hypercall1(long, opt_feature, arg); +} + +/* for balloon driver */ +#define HYPERVISOR_update_va_mapping(va, new_val, flags) (0) + +/* Use xencomm to do hypercalls. */ +#define HYPERVISOR_sched_op xencomm_hypercall_sched_op +#define HYPERVISOR_event_channel_op xencomm_hypercall_event_channel_op +#define HYPERVISOR_callback_op xencomm_hypercall_callback_op +#define HYPERVISOR_multicall xencomm_hypercall_multicall +#define HYPERVISOR_xen_version xencomm_hypercall_xen_version +#define HYPERVISOR_console_io xencomm_hypercall_console_io +#define HYPERVISOR_memory_op xencomm_hypercall_memory_op +#define HYPERVISOR_suspend xencomm_hypercall_suspend +#define HYPERVISOR_vcpu_op xencomm_hypercall_vcpu_op +#define HYPERVISOR_opt_feature xencomm_hypercall_opt_feature + +/* to compile gnttab_copy_grant_page() in drivers/xen/core/gnttab.c */ +#define HYPERVISOR_mmu_update(req, count, success_count, domid) ({ BUG(); 0; }) + +static inline int +HYPERVISOR_shutdown( + unsigned int reason) +{ + struct sched_shutdown sched_shutdown = { + .reason = reason + }; + + int rc = HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown); + + return rc; +} + +/* for netfront.c, netback.c */ +#define MULTI_UVMFLAGS_INDEX 0 /* XXX any value */ + +static inline void +MULTI_update_va_mapping( + struct multicall_entry *mcl, unsigned long va, + pte_t new_val, unsigned long flags) +{ + mcl->op = __HYPERVISOR_update_va_mapping; + mcl->result = 0; +} + +static inline void +MULTI_grant_table_op(struct multicall_entry *mcl, unsigned int cmd, + void *uop, unsigned int count) +{ + mcl->op = __HYPERVISOR_grant_table_op; + mcl->args[0] = cmd; + mcl->args[1] = (unsigned long)uop; + mcl->args[2] = count; +} + +static inline void +MULTI_mmu_update(struct multicall_entry *mcl, struct mmu_update *req, + int count, int *success_count, domid_t domid) +{ + mcl->op = __HYPERVISOR_mmu_update; + mcl->args[0] = (unsigned long)req; + mcl->args[1] = count; + mcl->args[2] = (unsigned long)success_count; + mcl->args[3] = domid; +} + +#endif /* _ASM_IA64_XEN_HYPERCALL_H */ diff --git a/arch/ia64/include/asm/xen/hypervisor.h b/arch/ia64/include/asm/xen/hypervisor.h new file mode 100644 index 0000000..7a804e8 --- /dev/null +++ b/arch/ia64/include/asm/xen/hypervisor.h @@ -0,0 +1,89 @@ +/****************************************************************************** + * hypervisor.h + * + * Linux-specific hypervisor handling. + * + * Copyright (c) 2002-2004, K A Fraser + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation; or, when distributed + * separately from the Linux kernel or incorporated into other + * software packages, subject to the following license: + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this source file (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef _ASM_IA64_XEN_HYPERVISOR_H +#define _ASM_IA64_XEN_HYPERVISOR_H + +#ifdef CONFIG_XEN + +#include <linux/init.h> +#include <xen/interface/xen.h> +#include <xen/interface/version.h> /* to compile feature.c */ +#include <xen/features.h> /* to comiple xen-netfront.c */ +#include <asm/xen/hypercall.h> + +/* xen_domain_type is set before executing any C code by early_xen_setup */ +enum xen_domain_type { + XEN_NATIVE, + XEN_PV_DOMAIN, + XEN_HVM_DOMAIN, +}; + +extern enum xen_domain_type xen_domain_type; + +#define xen_domain() (xen_domain_type != XEN_NATIVE) +#define xen_pv_domain() (xen_domain_type == XEN_PV_DOMAIN) +#define xen_initial_domain() (xen_pv_domain() && \ + (xen_start_info->flags & SIF_INITDOMAIN)) +#define xen_hvm_domain() (xen_domain_type == XEN_HVM_DOMAIN) + +/* deprecated. remove this */ +#define is_running_on_xen() (xen_domain_type == XEN_PV_DOMAIN) + +extern struct shared_info *HYPERVISOR_shared_info; +extern struct start_info *xen_start_info; + +void __init xen_setup_vcpu_info_placement(void); +void force_evtchn_callback(void); + +/* for drivers/xen/balloon/balloon.c */ +#ifdef CONFIG_XEN_SCRUB_PAGES +#define scrub_pages(_p, _n) memset((void *)(_p), 0, (_n) << PAGE_SHIFT) +#else +#define scrub_pages(_p, _n) ((void)0) +#endif + +/* For setup_arch() in arch/ia64/kernel/setup.c */ +void xen_ia64_enable_opt_feature(void); + +#else /* CONFIG_XEN */ + +#define xen_domain() (0) +#define xen_pv_domain() (0) +#define xen_initial_domain() (0) +#define xen_hvm_domain() (0) +#define is_running_on_xen() (0) /* deprecated. remove this */ +#endif + +#define is_initial_xendomain() (0) /* deprecated. remove this */ + +#endif /* _ASM_IA64_XEN_HYPERVISOR_H */ diff --git a/arch/ia64/include/asm/xen/inst.h b/arch/ia64/include/asm/xen/inst.h new file mode 100644 index 0000000..19c2ae1 --- /dev/null +++ b/arch/ia64/include/asm/xen/inst.h @@ -0,0 +1,458 @@ +/****************************************************************************** + * arch/ia64/include/asm/xen/inst.h + * + * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp> + * VA Linux Systems Japan K.K. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <asm/xen/privop.h> + +#define ia64_ivt xen_ivt +#define DO_SAVE_MIN XEN_DO_SAVE_MIN + +#define __paravirt_switch_to xen_switch_to +#define __paravirt_leave_syscall xen_leave_syscall +#define __paravirt_work_processed_syscall xen_work_processed_syscall +#define __paravirt_leave_kernel xen_leave_kernel +#define __paravirt_pending_syscall_end xen_work_pending_syscall_end +#define __paravirt_work_processed_syscall_target \ + xen_work_processed_syscall + +#define MOV_FROM_IFA(reg) \ + movl reg = XSI_IFA; \ + ;; \ + ld8 reg = [reg] + +#define MOV_FROM_ITIR(reg) \ + movl reg = XSI_ITIR; \ + ;; \ + ld8 reg = [reg] + +#define MOV_FROM_ISR(reg) \ + movl reg = XSI_ISR; \ + ;; \ + ld8 reg = [reg] + +#define MOV_FROM_IHA(reg) \ + movl reg = XSI_IHA; \ + ;; \ + ld8 reg = [reg] + +#define MOV_FROM_IPSR(pred, reg) \ +(pred) movl reg = XSI_IPSR; \ + ;; \ +(pred) ld8 reg = [reg] + +#define MOV_FROM_IIM(reg) \ + movl reg = XSI_IIM; \ + ;; \ + ld8 reg = [reg] + +#define MOV_FROM_IIP(reg) \ + movl reg = XSI_IIP; \ + ;; \ + ld8 reg = [reg] + +.macro __MOV_FROM_IVR reg, clob + .ifc "\reg", "r8" + XEN_HYPER_GET_IVR + .exitm + .endif + .ifc "\clob", "r8" + XEN_HYPER_GET_IVR + ;; + mov \reg = r8 + .exitm + .endif + + mov \clob = r8 + ;; + XEN_HYPER_GET_IVR + ;; + mov \reg = r8 + ;; + mov r8 = \clob +.endm +#define MOV_FROM_IVR(reg, clob) __MOV_FROM_IVR reg, clob + +.macro __MOV_FROM_PSR pred, reg, clob + .ifc "\reg", "r8" + (\pred) XEN_HYPER_GET_PSR; + .exitm + .endif + .ifc "\clob", "r8" + (\pred) XEN_HYPER_GET_PSR + ;; + (\pred) mov \reg = r8 + .exitm + .endif + + (\pred) mov \clob = r8 + (\pred) XEN_HYPER_GET_PSR + ;; + (\pred) mov \reg = r8 + (\pred) mov r8 = \clob +.endm +#define MOV_FROM_PSR(pred, reg, clob) __MOV_FROM_PSR pred, reg, clob + + +#define MOV_TO_IFA(reg, clob) \ + movl clob = XSI_IFA; \ + ;; \ + st8 [clob] = reg \ + +#define MOV_TO_ITIR(pred, reg, clob) \ +(pred) movl clob = XSI_ITIR; \ + ;; \ +(pred) st8 [clob] = reg + +#define MOV_TO_IHA(pred, reg, clob) \ +(pred) movl clob = XSI_IHA; \ + ;; \ +(pred) st8 [clob] = reg + +#define MOV_TO_IPSR(pred, reg, clob) \ +(pred) movl clob = XSI_IPSR; \ + ;; \ +(pred) st8 [clob] = reg; \ + ;; + +#define MOV_TO_IFS(pred, reg, clob) \ +(pred) movl clob = XSI_IFS; \ + ;; \ +(pred) st8 [clob] = reg; \ + ;; + +#define MOV_TO_IIP(reg, clob) \ + movl clob = XSI_IIP; \ + ;; \ + st8 [clob] = reg + +.macro ____MOV_TO_KR kr, reg, clob0, clob1 + .ifc "\clob0", "r9" + .error "clob0 \clob0 must not be r9" + .endif + .ifc "\clob1", "r8" + .error "clob1 \clob1 must not be r8" + .endif + + .ifnc "\reg", "r9" + .ifnc "\clob1", "r9" + mov \clob1 = r9 + .endif + mov r9 = \reg + .endif + .ifnc "\clob0", "r8" + mov \clob0 = r8 + .endif + mov r8 = \kr + ;; + XEN_HYPER_SET_KR + + .ifnc "\reg", "r9" + .ifnc "\clob1", "r9" + mov r9 = \clob1 + .endif + .endif + .ifnc "\clob0", "r8" + mov r8 = \clob0 + .endif +.endm + +.macro __MOV_TO_KR kr, reg, clob0, clob1 + .ifc "\clob0", "r9" + ____MOV_TO_KR \kr, \reg, \clob1, \clob0 + .exitm + .endif + .ifc "\clob1", "r8" + ____MOV_TO_KR \kr, \reg, \clob1, \clob0 + .exitm + .endif + + ____MOV_TO_KR \kr, \reg, \clob0, \clob1 +.endm + +#define MOV_TO_KR(kr, reg, clob0, clob1) \ + __MOV_TO_KR IA64_KR_ ## kr, reg, clob0, clob1 + + +.macro __ITC_I pred, reg, clob + .ifc "\reg", "r8" + (\pred) XEN_HYPER_ITC_I + .exitm + .endif + .ifc "\clob", "r8" + (\pred) mov r8 = \reg + ;; + (\pred) XEN_HYPER_ITC_I + .exitm + .endif + + (\pred) mov \clob = r8 + (\pred) mov r8 = \reg + ;; + (\pred) XEN_HYPER_ITC_I + ;; + (\pred) mov r8 = \clob + ;; +.endm +#define ITC_I(pred, reg, clob) __ITC_I pred, reg, clob + +.macro __ITC_D pred, reg, clob + .ifc "\reg", "r8" + (\pred) XEN_HYPER_ITC_D + ;; + .exitm + .endif + .ifc "\clob", "r8" + (\pred) mov r8 = \reg + ;; + (\pred) XEN_HYPER_ITC_D + ;; + .exitm + .endif + + (\pred) mov \clob = r8 + (\pred) mov r8 = \reg + ;; + (\pred) XEN_HYPER_ITC_D + ;; + (\pred) mov r8 = \clob + ;; +.endm +#define ITC_D(pred, reg, clob) __ITC_D pred, reg, clob + +.macro __ITC_I_AND_D pred_i, pred_d, reg, clob + .ifc "\reg", "r8" + (\pred_i)XEN_HYPER_ITC_I + ;; + (\pred_d)XEN_HYPER_ITC_D + ;; + .exitm + .endif + .ifc "\clob", "r8" + mov r8 = \reg + ;; + (\pred_i)XEN_HYPER_ITC_I + ;; + (\pred_d)XEN_HYPER_ITC_D + ;; + .exitm + .endif + + mov \clob = r8 + mov r8 = \reg + ;; + (\pred_i)XEN_HYPER_ITC_I + ;; + (\pred_d)XEN_HYPER_ITC_D + ;; + mov r8 = \clob + ;; +.endm +#define ITC_I_AND_D(pred_i, pred_d, reg, clob) \ + __ITC_I_AND_D pred_i, pred_d, reg, clob + +.macro __THASH pred, reg0, reg1, clob + .ifc "\reg0", "r8" + (\pred) mov r8 = \reg1 + (\pred) XEN_HYPER_THASH + .exitm + .endc + .ifc "\reg1", "r8" + (\pred) XEN_HYPER_THASH + ;; + (\pred) mov \reg0 = r8 + ;; + .exitm + .endif + .ifc "\clob", "r8" + (\pred) mov r8 = \reg1 + (\pred) XEN_HYPER_THASH + ;; + (\pred) mov \reg0 = r8 + ;; + .exitm + .endif + + (\pred) mov \clob = r8 + (\pred) mov r8 = \reg1 + (\pred) XEN_HYPER_THASH + ;; + (\pred) mov \reg0 = r8 + (\pred) mov r8 = \clob + ;; +.endm +#define THASH(pred, reg0, reg1, clob) __THASH pred, reg0, reg1, clob + +#define SSM_PSR_IC_AND_DEFAULT_BITS_AND_SRLZ_I(clob0, clob1) \ + mov clob0 = 1; \ + movl clob1 = XSI_PSR_IC; \ + ;; \ + st4 [clob1] = clob0 \ + ;; + +#define SSM_PSR_IC_AND_SRLZ_D(clob0, clob1) \ + ;; \ + srlz.d; \ + mov clob1 = 1; \ + movl clob0 = XSI_PSR_IC; \ + ;; \ + st4 [clob0] = clob1 + +#define RSM_PSR_IC(clob) \ + movl clob = XSI_PSR_IC; \ + ;; \ + st4 [clob] = r0; \ + ;; + +/* pred will be clobbered */ +#define MASK_TO_PEND_OFS (-1) +#define SSM_PSR_I(pred, pred_clob, clob) \ +(pred) movl clob = XSI_PSR_I_ADDR \ + ;; \ +(pred) ld8 clob = [clob] \ + ;; \ + /* if (pred) vpsr.i = 1 */ \ + /* if (pred) (vcpu->vcpu_info->evtchn_upcall_mask)=0 */ \ +(pred) st1 [clob] = r0, MASK_TO_PEND_OFS \ + ;; \ + /* if (vcpu->vcpu_info->evtchn_upcall_pending) */ \ +(pred) ld1 clob = [clob] \ + ;; \ +(pred) cmp.ne.unc pred_clob, p0 = clob, r0 \ + ;; \ +(pred_clob)XEN_HYPER_SSM_I /* do areal ssm psr.i */ + +#define RSM_PSR_I(pred, clob0, clob1) \ + movl clob0 = XSI_PSR_I_ADDR; \ + mov clob1 = 1; \ + ;; \ + ld8 clob0 = [clob0]; \ + ;; \ +(pred) st1 [clob0] = clob1 + +#define RSM_PSR_I_IC(clob0, clob1, clob2) \ + movl clob0 = XSI_PSR_I_ADDR; \ + movl clob1 = XSI_PSR_IC; \ + ;; \ + ld8 clob0 = [clob0]; \ + mov clob2 = 1; \ + ;; \ + /* note: clears both vpsr.i and vpsr.ic! */ \ + st1 [clob0] = clob2; \ + st4 [clob1] = r0; \ + ;; + +#define RSM_PSR_DT \ + XEN_HYPER_RSM_PSR_DT + +#define SSM_PSR_DT_AND_SRLZ_I \ + XEN_HYPER_SSM_PSR_DT + +#define BSW_0(clob0, clob1, clob2) \ + ;; \ + /* r16-r31 all now hold bank1 values */ \ + mov clob2 = ar.unat; \ + movl clob0 = XSI_BANK1_R16; \ + movl clob1 = XSI_BANK1_R16 + 8; \ + ;; \ +.mem.offset 0, 0; st8.spill [clob0] = r16, 16; \ +.mem.offset 8, 0; st8.spill [clob1] = r17, 16; \ + ;; \ +.mem.offset 0, 0; st8.spill [clob0] = r18, 16; \ +.mem.offset 8, 0; st8.spill [clob1] = r19, 16; \ + ;; \ +.mem.offset 0, 0; st8.spill [clob0] = r20, 16; \ +.mem.offset 8, 0; st8.spill [clob1] = r21, 16; \ + ;; \ +.mem.offset 0, 0; st8.spill [clob0] = r22, 16; \ +.mem.offset 8, 0; st8.spill [clob1] = r23, 16; \ + ;; \ +.mem.offset 0, 0; st8.spill [clob0] = r24, 16; \ +.mem.offset 8, 0; st8.spill [clob1] = r25, 16; \ + ;; \ +.mem.offset 0, 0; st8.spill [clob0] = r26, 16; \ +.mem.offset 8, 0; st8.spill [clob1] = r27, 16; \ + ;; \ +.mem.offset 0, 0; st8.spill [clob0] = r28, 16; \ +.mem.offset 8, 0; st8.spill [clob1] = r29, 16; \ + ;; \ +.mem.offset 0, 0; st8.spill [clob0] = r30, 16; \ +.mem.offset 8, 0; st8.spill [clob1] = r31, 16; \ + ;; \ + mov clob1 = ar.unat; \ + movl clob0 = XSI_B1NAT; \ + ;; \ + st8 [clob0] = clob1; \ + mov ar.unat = clob2; \ + movl clob0 = XSI_BANKNUM; \ + ;; \ + st4 [clob0] = r0 + + + /* FIXME: THIS CODE IS NOT NaT SAFE! */ +#define XEN_BSW_1(clob) \ + mov clob = ar.unat; \ + movl r30 = XSI_B1NAT; \ + ;; \ + ld8 r30 = [r30]; \ + mov r31 = 1; \ + ;; \ + mov ar.unat = r30; \ + movl r30 = XSI_BANKNUM; \ + ;; \ + st4 [r30] = r31; \ + movl r30 = XSI_BANK1_R16; \ + movl r31 = XSI_BANK1_R16+8; \ + ;; \ + ld8.fill r16 = [r30], 16; \ + ld8.fill r17 = [r31], 16; \ + ;; \ + ld8.fill r18 = [r30], 16; \ + ld8.fill r19 = [r31], 16; \ + ;; \ + ld8.fill r20 = [r30], 16; \ + ld8.fill r21 = [r31], 16; \ + ;; \ + ld8.fill r22 = [r30], 16; \ + ld8.fill r23 = [r31], 16; \ + ;; \ + ld8.fill r24 = [r30], 16; \ + ld8.fill r25 = [r31], 16; \ + ;; \ + ld8.fill r26 = [r30], 16; \ + ld8.fill r27 = [r31], 16; \ + ;; \ + ld8.fill r28 = [r30], 16; \ + ld8.fill r29 = [r31], 16; \ + ;; \ + ld8.fill r30 = [r30]; \ + ld8.fill r31 = [r31]; \ + ;; \ + mov ar.unat = clob + +#define BSW_1(clob0, clob1) XEN_BSW_1(clob1) + + +#define COVER \ + XEN_HYPER_COVER + +#define RFI \ + XEN_HYPER_RFI; \ + dv_serialize_data diff --git a/arch/ia64/include/asm/xen/interface.h b/arch/ia64/include/asm/xen/interface.h new file mode 100644 index 0000000..f00fab40 --- /dev/null +++ b/arch/ia64/include/asm/xen/interface.h @@ -0,0 +1,346 @@ +/****************************************************************************** + * arch-ia64/hypervisor-if.h + * + * Guest OS interface to IA64 Xen. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Copyright by those who contributed. (in alphabetical order) + * + * Anthony Xu <anthony.xu@intel.com> + * Eddie Dong <eddie.dong@intel.com> + * Fred Yang <fred.yang@intel.com> + * Kevin Tian <kevin.tian@intel.com> + * Alex Williamson <alex.williamson@hp.com> + * Chris Wright <chrisw@sous-sol.org> + * Christian Limpach <Christian.Limpach@cl.cam.ac.uk> + * Dietmar Hahn <dietmar.hahn@fujitsu-siemens.com> + * Hollis Blanchard <hollisb@us.ibm.com> + * Isaku Yamahata <yamahata@valinux.co.jp> + * Jan Beulich <jbeulich@novell.com> + * John Levon <john.levon@sun.com> + * Kazuhiro Suzuki <kaz@jp.fujitsu.com> + * Keir Fraser <keir.fraser@citrix.com> + * Kouya Shimura <kouya@jp.fujitsu.com> + * Masaki Kanno <kanno.masaki@jp.fujitsu.com> + * Matt Chapman <matthewc@hp.com> + * Matthew Chapman <matthewc@hp.com> + * Samuel Thibault <samuel.thibault@eu.citrix.com> + * Tomonari Horikoshi <t.horikoshi@jp.fujitsu.com> + * Tristan Gingold <tgingold@free.fr> + * Tsunehisa Doi <Doi.Tsunehisa@jp.fujitsu.com> + * Yutaka Ezaki <yutaka.ezaki@jp.fujitsu.com> + * Zhang Xin <xing.z.zhang@intel.com> + * Zhang xiantao <xiantao.zhang@intel.com> + * dan.magenheimer@hp.com + * ian.pratt@cl.cam.ac.uk + * michael.fetterman@cl.cam.ac.uk + */ + +#ifndef _ASM_IA64_XEN_INTERFACE_H +#define _ASM_IA64_XEN_INTERFACE_H + +#define __DEFINE_GUEST_HANDLE(name, type) \ + typedef struct { type *p; } __guest_handle_ ## name + +#define DEFINE_GUEST_HANDLE_STRUCT(name) \ + __DEFINE_GUEST_HANDLE(name, struct name) +#define DEFINE_GUEST_HANDLE(name) __DEFINE_GUEST_HANDLE(name, name) +#define GUEST_HANDLE(name) __guest_handle_ ## name +#define GUEST_HANDLE_64(name) GUEST_HANDLE(name) +#define set_xen_guest_handle(hnd, val) do { (hnd).p = val; } while (0) + +#ifndef __ASSEMBLY__ +/* Guest handles for primitive C types. */ +__DEFINE_GUEST_HANDLE(uchar, unsigned char); +__DEFINE_GUEST_HANDLE(uint, unsigned int); +__DEFINE_GUEST_HANDLE(ulong, unsigned long); +__DEFINE_GUEST_HANDLE(u64, unsigned long); +DEFINE_GUEST_HANDLE(char); +DEFINE_GUEST_HANDLE(int); +DEFINE_GUEST_HANDLE(long); +DEFINE_GUEST_HANDLE(void); + +typedef unsigned long xen_pfn_t; +DEFINE_GUEST_HANDLE(xen_pfn_t); +#define PRI_xen_pfn "lx" +#endif + +/* Arch specific VIRQs definition */ +#define VIRQ_ITC VIRQ_ARCH_0 /* V. Virtual itc timer */ +#define VIRQ_MCA_CMC VIRQ_ARCH_1 /* MCA cmc interrupt */ +#define VIRQ_MCA_CPE VIRQ_ARCH_2 /* MCA cpe interrupt */ + +/* Maximum number of virtual CPUs in multi-processor guests. */ +/* keep sizeof(struct shared_page) <= PAGE_SIZE. + * this is checked in arch/ia64/xen/hypervisor.c. */ +#define MAX_VIRT_CPUS 64 + +#ifndef __ASSEMBLY__ + +#define INVALID_MFN (~0UL) + +union vac { + unsigned long value; + struct { + int a_int:1; + int a_from_int_cr:1; + int a_to_int_cr:1; + int a_from_psr:1; + int a_from_cpuid:1; + int a_cover:1; + int a_bsw:1; + long reserved:57; + }; +}; + +union vdc { + unsigned long value; + struct { + int d_vmsw:1; + int d_extint:1; + int d_ibr_dbr:1; + int d_pmc:1; + int d_to_pmd:1; + int d_itm:1; + long reserved:58; + }; +}; + +struct mapped_regs { + union vac vac; + union vdc vdc; + unsigned long virt_env_vaddr; + unsigned long reserved1[29]; + unsigned long vhpi; + unsigned long reserved2[95]; + union { + unsigned long vgr[16]; + unsigned long bank1_regs[16]; /* bank1 regs (r16-r31) + when bank0 active */ + }; + union { + unsigned long vbgr[16]; + unsigned long bank0_regs[16]; /* bank0 regs (r16-r31) + when bank1 active */ + }; + unsigned long vnat; + unsigned long vbnat; + unsigned long vcpuid[5]; + unsigned long reserved3[11]; + unsigned long vpsr; + unsigned long vpr; + unsigned long reserved4[76]; + union { + unsigned long vcr[128]; + struct { + unsigned long dcr; /* CR0 */ + unsigned long itm; + unsigned long iva; + unsigned long rsv1[5]; + unsigned long pta; /* CR8 */ + unsigned long rsv2[7]; + unsigned long ipsr; /* CR16 */ + unsigned long isr; + unsigned long rsv3; + unsigned long iip; + unsigned long ifa; + unsigned long itir; + unsigned long iipa; + unsigned long ifs; + unsigned long iim; /* CR24 */ + unsigned long iha; + unsigned long rsv4[38]; + unsigned long lid; /* CR64 */ + unsigned long ivr; + unsigned long tpr; + unsigned long eoi; + unsigned long irr[4]; + unsigned long itv; /* CR72 */ + unsigned long pmv; + unsigned long cmcv; + unsigned long rsv5[5]; + unsigned long lrr0; /* CR80 */ + unsigned long lrr1; + unsigned long rsv6[46]; + }; + }; + union { + unsigned long reserved5[128]; + struct { + unsigned long precover_ifs; + unsigned long unat; /* not sure if this is needed + until NaT arch is done */ + int interrupt_collection_enabled; /* virtual psr.ic */ + + /* virtual interrupt deliverable flag is + * evtchn_upcall_mask in shared info area now. + * interrupt_mask_addr is the address + * of evtchn_upcall_mask for current vcpu + */ + unsigned char *interrupt_mask_addr; + int pending_interruption; + unsigned char vpsr_pp; + unsigned char vpsr_dfh; + unsigned char hpsr_dfh; + unsigned char hpsr_mfh; + unsigned long reserved5_1[4]; + int metaphysical_mode; /* 1 = use metaphys mapping + 0 = use virtual */ + int banknum; /* 0 or 1, which virtual + register bank is active */ + unsigned long rrs[8]; /* region registers */ + unsigned long krs[8]; /* kernel registers */ + unsigned long tmp[16]; /* temp registers + (e.g. for hyperprivops) */ + }; + }; +}; + +struct arch_vcpu_info { + /* nothing */ +}; + +/* + * This structure is used for magic page in domain pseudo physical address + * space and the result of XENMEM_machine_memory_map. + * As the XENMEM_machine_memory_map result, + * xen_memory_map::nr_entries indicates the size in bytes + * including struct xen_ia64_memmap_info. Not the number of entries. + */ +struct xen_ia64_memmap_info { + uint64_t efi_memmap_size; /* size of EFI memory map */ + uint64_t efi_memdesc_size; /* size of an EFI memory map + * descriptor */ + uint32_t efi_memdesc_version; /* memory descriptor version */ + void *memdesc[0]; /* array of efi_memory_desc_t */ +}; + +struct arch_shared_info { + /* PFN of the start_info page. */ + unsigned long start_info_pfn; + + /* Interrupt vector for event channel. */ + int evtchn_vector; + + /* PFN of memmap_info page */ + unsigned int memmap_info_num_pages; /* currently only = 1 case is + supported. */ + unsigned long memmap_info_pfn; + + uint64_t pad[31]; +}; + +struct xen_callback { + unsigned long ip; +}; +typedef struct xen_callback xen_callback_t; + +#endif /* !__ASSEMBLY__ */ + +/* Size of the shared_info area (this is not related to page size). */ +#define XSI_SHIFT 14 +#define XSI_SIZE (1 << XSI_SHIFT) +/* Log size of mapped_regs area (64 KB - only 4KB is used). */ +#define XMAPPEDREGS_SHIFT 12 +#define XMAPPEDREGS_SIZE (1 << XMAPPEDREGS_SHIFT) +/* Offset of XASI (Xen arch shared info) wrt XSI_BASE. */ +#define XMAPPEDREGS_OFS XSI_SIZE + +/* Hyperprivops. */ +#define HYPERPRIVOP_START 0x1 +#define HYPERPRIVOP_RFI (HYPERPRIVOP_START + 0x0) +#define HYPERPRIVOP_RSM_DT (HYPERPRIVOP_START + 0x1) +#define HYPERPRIVOP_SSM_DT (HYPERPRIVOP_START + 0x2) +#define HYPERPRIVOP_COVER (HYPERPRIVOP_START + 0x3) +#define HYPERPRIVOP_ITC_D (HYPERPRIVOP_START + 0x4) +#define HYPERPRIVOP_ITC_I (HYPERPRIVOP_START + 0x5) +#define HYPERPRIVOP_SSM_I (HYPERPRIVOP_START + 0x6) +#define HYPERPRIVOP_GET_IVR (HYPERPRIVOP_START + 0x7) +#define HYPERPRIVOP_GET_TPR (HYPERPRIVOP_START + 0x8) +#define HYPERPRIVOP_SET_TPR (HYPERPRIVOP_START + 0x9) +#define HYPERPRIVOP_EOI (HYPERPRIVOP_START + 0xa) +#define HYPERPRIVOP_SET_ITM (HYPERPRIVOP_START + 0xb) +#define HYPERPRIVOP_THASH (HYPERPRIVOP_START + 0xc) +#define HYPERPRIVOP_PTC_GA (HYPERPRIVOP_START + 0xd) +#define HYPERPRIVOP_ITR_D (HYPERPRIVOP_START + 0xe) +#define HYPERPRIVOP_GET_RR (HYPERPRIVOP_START + 0xf) +#define HYPERPRIVOP_SET_RR (HYPERPRIVOP_START + 0x10) +#define HYPERPRIVOP_SET_KR (HYPERPRIVOP_START + 0x11) +#define HYPERPRIVOP_FC (HYPERPRIVOP_START + 0x12) +#define HYPERPRIVOP_GET_CPUID (HYPERPRIVOP_START + 0x13) +#define HYPERPRIVOP_GET_PMD (HYPERPRIVOP_START + 0x14) +#define HYPERPRIVOP_GET_EFLAG (HYPERPRIVOP_START + 0x15) +#define HYPERPRIVOP_SET_EFLAG (HYPERPRIVOP_START + 0x16) +#define HYPERPRIVOP_RSM_BE (HYPERPRIVOP_START + 0x17) +#define HYPERPRIVOP_GET_PSR (HYPERPRIVOP_START + 0x18) +#define HYPERPRIVOP_SET_RR0_TO_RR4 (HYPERPRIVOP_START + 0x19) +#define HYPERPRIVOP_MAX (0x1a) + +/* Fast and light hypercalls. */ +#define __HYPERVISOR_ia64_fast_eoi __HYPERVISOR_arch_1 + +/* Xencomm macros. */ +#define XENCOMM_INLINE_MASK 0xf800000000000000UL +#define XENCOMM_INLINE_FLAG 0x8000000000000000UL + +#ifndef __ASSEMBLY__ + +/* + * Optimization features. + * The hypervisor may do some special optimizations for guests. This hypercall + * can be used to switch on/of these special optimizations. + */ +#define __HYPERVISOR_opt_feature 0x700UL + +#define XEN_IA64_OPTF_OFF 0x0 +#define XEN_IA64_OPTF_ON 0x1 + +/* + * If this feature is switched on, the hypervisor inserts the + * tlb entries without calling the guests traphandler. + * This is useful in guests using region 7 for identity mapping + * like the linux kernel does. + */ +#define XEN_IA64_OPTF_IDENT_MAP_REG7 1 + +/* Identity mapping of region 4 addresses in HVM. */ +#define XEN_IA64_OPTF_IDENT_MAP_REG4 2 + +/* Identity mapping of region 5 addresses in HVM. */ +#define XEN_IA64_OPTF_IDENT_MAP_REG5 3 + +#define XEN_IA64_OPTF_IDENT_MAP_NOT_SET (0) + +struct xen_ia64_opt_feature { + unsigned long cmd; /* Which feature */ + unsigned char on; /* Switch feature on/off */ + union { + struct { + /* The page protection bit mask of the pte. + * This will be or'ed with the pte. */ + unsigned long pgprot; + unsigned long key; /* A protection key for itir.*/ + }; + }; +}; + +#endif /* __ASSEMBLY__ */ + +#endif /* _ASM_IA64_XEN_INTERFACE_H */ diff --git a/arch/ia64/include/asm/xen/irq.h b/arch/ia64/include/asm/xen/irq.h new file mode 100644 index 0000000..a904509 --- /dev/null +++ b/arch/ia64/include/asm/xen/irq.h @@ -0,0 +1,44 @@ +/****************************************************************************** + * arch/ia64/include/asm/xen/irq.h + * + * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp> + * VA Linux Systems Japan K.K. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef _ASM_IA64_XEN_IRQ_H +#define _ASM_IA64_XEN_IRQ_H + +/* + * The flat IRQ space is divided into two regions: + * 1. A one-to-one mapping of real physical IRQs. This space is only used + * if we have physical device-access privilege. This region is at the + * start of the IRQ space so that existing device drivers do not need + * to be modified to translate physical IRQ numbers into our IRQ space. + * 3. A dynamic mapping of inter-domain and Xen-sourced virtual IRQs. These + * are bound using the provided bind/unbind functions. + */ + +#define XEN_PIRQ_BASE 0 +#define XEN_NR_PIRQS 256 + +#define XEN_DYNIRQ_BASE (XEN_PIRQ_BASE + XEN_NR_PIRQS) +#define XEN_NR_DYNIRQS (NR_CPUS * 8) + +#define XEN_NR_IRQS (XEN_NR_PIRQS + XEN_NR_DYNIRQS) + +#endif /* _ASM_IA64_XEN_IRQ_H */ diff --git a/arch/ia64/include/asm/xen/minstate.h b/arch/ia64/include/asm/xen/minstate.h new file mode 100644 index 0000000..4d92d9b --- /dev/null +++ b/arch/ia64/include/asm/xen/minstate.h @@ -0,0 +1,134 @@ +/* + * DO_SAVE_MIN switches to the kernel stacks (if necessary) and saves + * the minimum state necessary that allows us to turn psr.ic back + * on. + * + * Assumed state upon entry: + * psr.ic: off + * r31: contains saved predicates (pr) + * + * Upon exit, the state is as follows: + * psr.ic: off + * r2 = points to &pt_regs.r16 + * r8 = contents of ar.ccv + * r9 = contents of ar.csd + * r10 = contents of ar.ssd + * r11 = FPSR_DEFAULT + * r12 = kernel sp (kernel virtual address) + * r13 = points to current task_struct (kernel virtual address) + * p15 = TRUE if psr.i is set in cr.ipsr + * predicate registers (other than p2, p3, and p15), b6, r3, r14, r15: + * preserved + * CONFIG_XEN note: p6/p7 are not preserved + * + * Note that psr.ic is NOT turned on by this macro. This is so that + * we can pass interruption state as arguments to a handler. + */ +#define XEN_DO_SAVE_MIN(__COVER,SAVE_IFS,EXTRA,WORKAROUND) \ + mov r16=IA64_KR(CURRENT); /* M */ \ + mov r27=ar.rsc; /* M */ \ + mov r20=r1; /* A */ \ + mov r25=ar.unat; /* M */ \ + MOV_FROM_IPSR(p0,r29); /* M */ \ + MOV_FROM_IIP(r28); /* M */ \ + mov r21=ar.fpsr; /* M */ \ + mov r26=ar.pfs; /* I */ \ + __COVER; /* B;; (or nothing) */ \ + adds r16=IA64_TASK_THREAD_ON_USTACK_OFFSET,r16; \ + ;; \ + ld1 r17=[r16]; /* load current->thread.on_ustack flag */ \ + st1 [r16]=r0; /* clear current->thread.on_ustack flag */ \ + adds r1=-IA64_TASK_THREAD_ON_USTACK_OFFSET,r16 \ + /* switch from user to kernel RBS: */ \ + ;; \ + invala; /* M */ \ + /* SAVE_IFS;*/ /* see xen special handling below */ \ + cmp.eq pKStk,pUStk=r0,r17; /* are we in kernel mode already? */ \ + ;; \ +(pUStk) mov ar.rsc=0; /* set enforced lazy mode, pl 0, little-endian, loadrs=0 */ \ + ;; \ +(pUStk) mov.m r24=ar.rnat; \ +(pUStk) addl r22=IA64_RBS_OFFSET,r1; /* compute base of RBS */ \ +(pKStk) mov r1=sp; /* get sp */ \ + ;; \ +(pUStk) lfetch.fault.excl.nt1 [r22]; \ +(pUStk) addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r1; /* compute base of memory stack */ \ +(pUStk) mov r23=ar.bspstore; /* save ar.bspstore */ \ + ;; \ +(pUStk) mov ar.bspstore=r22; /* switch to kernel RBS */ \ +(pKStk) addl r1=-IA64_PT_REGS_SIZE,r1; /* if in kernel mode, use sp (r12) */ \ + ;; \ +(pUStk) mov r18=ar.bsp; \ +(pUStk) mov ar.rsc=0x3; /* set eager mode, pl 0, little-endian, loadrs=0 */ \ + adds r17=2*L1_CACHE_BYTES,r1; /* really: biggest cache-line size */ \ + adds r16=PT(CR_IPSR),r1; \ + ;; \ + lfetch.fault.excl.nt1 [r17],L1_CACHE_BYTES; \ + st8 [r16]=r29; /* save cr.ipsr */ \ + ;; \ + lfetch.fault.excl.nt1 [r17]; \ + tbit.nz p15,p0=r29,IA64_PSR_I_BIT; \ + mov r29=b0 \ + ;; \ + WORKAROUND; \ + adds r16=PT(R8),r1; /* initialize first base pointer */ \ + adds r17=PT(R9),r1; /* initialize second base pointer */ \ +(pKStk) mov r18=r0; /* make sure r18 isn't NaT */ \ + ;; \ +.mem.offset 0,0; st8.spill [r16]=r8,16; \ +.mem.offset 8,0; st8.spill [r17]=r9,16; \ + ;; \ +.mem.offset 0,0; st8.spill [r16]=r10,24; \ + movl r8=XSI_PRECOVER_IFS; \ +.mem.offset 8,0; st8.spill [r17]=r11,24; \ + ;; \ + /* xen special handling for possibly lazy cover */ \ + /* SAVE_MIN case in dispatch_ia32_handler: mov r30=r0 */ \ + ld8 r30=[r8]; \ +(pUStk) sub r18=r18,r22; /* r18=RSE.ndirty*8 */ \ + st8 [r16]=r28,16; /* save cr.iip */ \ + ;; \ + st8 [r17]=r30,16; /* save cr.ifs */ \ + mov r8=ar.ccv; \ + mov r9=ar.csd; \ + mov r10=ar.ssd; \ + movl r11=FPSR_DEFAULT; /* L-unit */ \ + ;; \ + st8 [r16]=r25,16; /* save ar.unat */ \ + st8 [r17]=r26,16; /* save ar.pfs */ \ + shl r18=r18,16; /* compute ar.rsc to be used for "loadrs" */ \ + ;; \ + st8 [r16]=r27,16; /* save ar.rsc */ \ +(pUStk) st8 [r17]=r24,16; /* save ar.rnat */ \ +(pKStk) adds r17=16,r17; /* skip over ar_rnat field */ \ + ;; /* avoid RAW on r16 & r17 */ \ +(pUStk) st8 [r16]=r23,16; /* save ar.bspstore */ \ + st8 [r17]=r31,16; /* save predicates */ \ +(pKStk) adds r16=16,r16; /* skip over ar_bspstore field */ \ + ;; \ + st8 [r16]=r29,16; /* save b0 */ \ + st8 [r17]=r18,16; /* save ar.rsc value for "loadrs" */ \ + cmp.eq pNonSys,pSys=r0,r0 /* initialize pSys=0, pNonSys=1 */ \ + ;; \ +.mem.offset 0,0; st8.spill [r16]=r20,16; /* save original r1 */ \ +.mem.offset 8,0; st8.spill [r17]=r12,16; \ + adds r12=-16,r1; /* switch to kernel memory stack (with 16 bytes of scratch) */ \ + ;; \ +.mem.offset 0,0; st8.spill [r16]=r13,16; \ +.mem.offset 8,0; st8.spill [r17]=r21,16; /* save ar.fpsr */ \ + mov r13=IA64_KR(CURRENT); /* establish `current' */ \ + ;; \ +.mem.offset 0,0; st8.spill [r16]=r15,16; \ +.mem.offset 8,0; st8.spill [r17]=r14,16; \ + ;; \ +.mem.offset 0,0; st8.spill [r16]=r2,16; \ +.mem.offset 8,0; st8.spill [r17]=r3,16; \ + ACCOUNT_GET_STAMP \ + adds r2=IA64_PT_REGS_R16_OFFSET,r1; \ + ;; \ + EXTRA; \ + movl r1=__gp; /* establish kernel global pointer */ \ + ;; \ + ACCOUNT_SYS_ENTER \ + BSW_1(r3,r14); /* switch back to bank 1 (must be last in insn group) */ \ + ;; diff --git a/arch/ia64/include/asm/xen/page.h b/arch/ia64/include/asm/xen/page.h new file mode 100644 index 0000000..03441a78 --- /dev/null +++ b/arch/ia64/include/asm/xen/page.h @@ -0,0 +1,65 @@ +/****************************************************************************** + * arch/ia64/include/asm/xen/page.h + * + * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp> + * VA Linux Systems Japan K.K. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef _ASM_IA64_XEN_PAGE_H +#define _ASM_IA64_XEN_PAGE_H + +#define INVALID_P2M_ENTRY (~0UL) + +static inline unsigned long mfn_to_pfn(unsigned long mfn) +{ + return mfn; +} + +static inline unsigned long pfn_to_mfn(unsigned long pfn) +{ + return pfn; +} + +#define phys_to_machine_mapping_valid(_x) (1) + +static inline void *mfn_to_virt(unsigned long mfn) +{ + return __va(mfn << PAGE_SHIFT); +} + +static inline unsigned long virt_to_mfn(void *virt) +{ + return __pa(virt) >> PAGE_SHIFT; +} + +/* for tpmfront.c */ +static inline unsigned long virt_to_machine(void *virt) +{ + return __pa(virt); +} + +static inline void set_phys_to_machine(unsigned long pfn, unsigned long mfn) +{ + /* nothing */ +} + +#define pte_mfn(_x) pte_pfn(_x) +#define mfn_pte(_x, _y) __pte_ma(0) /* unmodified use */ +#define __pte_ma(_x) ((pte_t) {(_x)}) /* unmodified use */ + +#endif /* _ASM_IA64_XEN_PAGE_H */ diff --git a/arch/ia64/include/asm/xen/privop.h b/arch/ia64/include/asm/xen/privop.h new file mode 100644 index 0000000..71ec754 --- /dev/null +++ b/arch/ia64/include/asm/xen/privop.h @@ -0,0 +1,129 @@ +#ifndef _ASM_IA64_XEN_PRIVOP_H +#define _ASM_IA64_XEN_PRIVOP_H + +/* + * Copyright (C) 2005 Hewlett-Packard Co + * Dan Magenheimer <dan.magenheimer@hp.com> + * + * Paravirtualizations of privileged operations for Xen/ia64 + * + * + * inline privop and paravirt_alt support + * Copyright (c) 2007 Isaku Yamahata <yamahata at valinux co jp> + * VA Linux Systems Japan K.K. + * + */ + +#ifndef __ASSEMBLY__ +#include <linux/types.h> /* arch-ia64.h requires uint64_t */ +#endif +#include <asm/xen/interface.h> + +/* At 1 MB, before per-cpu space but still addressable using addl instead + of movl. */ +#define XSI_BASE 0xfffffffffff00000 + +/* Address of mapped regs. */ +#define XMAPPEDREGS_BASE (XSI_BASE + XSI_SIZE) + +#ifdef __ASSEMBLY__ +#define XEN_HYPER_RFI break HYPERPRIVOP_RFI +#define XEN_HYPER_RSM_PSR_DT break HYPERPRIVOP_RSM_DT +#define XEN_HYPER_SSM_PSR_DT break HYPERPRIVOP_SSM_DT +#define XEN_HYPER_COVER break HYPERPRIVOP_COVER +#define XEN_HYPER_ITC_D break HYPERPRIVOP_ITC_D +#define XEN_HYPER_ITC_I break HYPERPRIVOP_ITC_I +#define XEN_HYPER_SSM_I break HYPERPRIVOP_SSM_I +#define XEN_HYPER_GET_IVR break HYPERPRIVOP_GET_IVR +#define XEN_HYPER_THASH break HYPERPRIVOP_THASH +#define XEN_HYPER_ITR_D break HYPERPRIVOP_ITR_D +#define XEN_HYPER_SET_KR break HYPERPRIVOP_SET_KR +#define XEN_HYPER_GET_PSR break HYPERPRIVOP_GET_PSR +#define XEN_HYPER_SET_RR0_TO_RR4 break HYPERPRIVOP_SET_RR0_TO_RR4 + +#define XSI_IFS (XSI_BASE + XSI_IFS_OFS) +#define XSI_PRECOVER_IFS (XSI_BASE + XSI_PRECOVER_IFS_OFS) +#define XSI_IFA (XSI_BASE + XSI_IFA_OFS) +#define XSI_ISR (XSI_BASE + XSI_ISR_OFS) +#define XSI_IIM (XSI_BASE + XSI_IIM_OFS) +#define XSI_ITIR (XSI_BASE + XSI_ITIR_OFS) +#define XSI_PSR_I_ADDR (XSI_BASE + XSI_PSR_I_ADDR_OFS) +#define XSI_PSR_IC (XSI_BASE + XSI_PSR_IC_OFS) +#define XSI_IPSR (XSI_BASE + XSI_IPSR_OFS) +#define XSI_IIP (XSI_BASE + XSI_IIP_OFS) +#define XSI_B1NAT (XSI_BASE + XSI_B1NATS_OFS) +#define XSI_BANK1_R16 (XSI_BASE + XSI_BANK1_R16_OFS) +#define XSI_BANKNUM (XSI_BASE + XSI_BANKNUM_OFS) +#define XSI_IHA (XSI_BASE + XSI_IHA_OFS) +#endif + +#ifndef __ASSEMBLY__ + +/************************************************/ +/* Instructions paravirtualized for correctness */ +/************************************************/ + +/* "fc" and "thash" are privilege-sensitive instructions, meaning they + * may have different semantics depending on whether they are executed + * at PL0 vs PL!=0. When paravirtualized, these instructions mustn't + * be allowed to execute directly, lest incorrect semantics result. */ +extern void xen_fc(unsigned long addr); +extern unsigned long xen_thash(unsigned long addr); + +/* Note that "ttag" and "cover" are also privilege-sensitive; "ttag" + * is not currently used (though it may be in a long-format VHPT system!) + * and the semantics of cover only change if psr.ic is off which is very + * rare (and currently non-existent outside of assembly code */ + +/* There are also privilege-sensitive registers. These registers are + * readable at any privilege level but only writable at PL0. */ +extern unsigned long xen_get_cpuid(int index); +extern unsigned long xen_get_pmd(int index); + +extern unsigned long xen_get_eflag(void); /* see xen_ia64_getreg */ +extern void xen_set_eflag(unsigned long); /* see xen_ia64_setreg */ + +/************************************************/ +/* Instructions paravirtualized for performance */ +/************************************************/ + +/* Xen uses memory-mapped virtual privileged registers for access to many + * performance-sensitive privileged registers. Some, like the processor + * status register (psr), are broken up into multiple memory locations. + * Others, like "pend", are abstractions based on privileged registers. + * "Pend" is guaranteed to be set if reading cr.ivr would return a + * (non-spurious) interrupt. */ +#define XEN_MAPPEDREGS ((struct mapped_regs *)XMAPPEDREGS_BASE) + +#define XSI_PSR_I \ + (*XEN_MAPPEDREGS->interrupt_mask_addr) +#define xen_get_virtual_psr_i() \ + (!XSI_PSR_I) +#define xen_set_virtual_psr_i(_val) \ + ({ XSI_PSR_I = (uint8_t)(_val) ? 0 : 1; }) +#define xen_set_virtual_psr_ic(_val) \ + ({ XEN_MAPPEDREGS->interrupt_collection_enabled = _val ? 1 : 0; }) +#define xen_get_virtual_pend() \ + (*(((uint8_t *)XEN_MAPPEDREGS->interrupt_mask_addr) - 1)) + +/* Although all privileged operations can be left to trap and will + * be properly handled by Xen, some are frequent enough that we use + * hyperprivops for performance. */ +extern unsigned long xen_get_psr(void); +extern unsigned long xen_get_ivr(void); +extern unsigned long xen_get_tpr(void); +extern void xen_hyper_ssm_i(void); +extern void xen_set_itm(unsigned long); +extern void xen_set_tpr(unsigned long); +extern void xen_eoi(unsigned long); +extern unsigned long xen_get_rr(unsigned long index); +extern void xen_set_rr(unsigned long index, unsigned long val); +extern void xen_set_rr0_to_rr4(unsigned long val0, unsigned long val1, + unsigned long val2, unsigned long val3, + unsigned long val4); +extern void xen_set_kr(unsigned long index, unsigned long val); +extern void xen_ptcga(unsigned long addr, unsigned long size); + +#endif /* !__ASSEMBLY__ */ + +#endif /* _ASM_IA64_XEN_PRIVOP_H */ diff --git a/arch/ia64/include/asm/xen/xcom_hcall.h b/arch/ia64/include/asm/xen/xcom_hcall.h new file mode 100644 index 0000000..20b2950 --- /dev/null +++ b/arch/ia64/include/asm/xen/xcom_hcall.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2006 Tristan Gingold <tristan.gingold@bull.net>, Bull SAS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _ASM_IA64_XEN_XCOM_HCALL_H +#define _ASM_IA64_XEN_XCOM_HCALL_H + +/* These function creates inline or mini descriptor for the parameters and + calls the corresponding xencomm_arch_hypercall_X. + Architectures should defines HYPERVISOR_xxx as xencomm_hypercall_xxx unless + they want to use their own wrapper. */ +extern int xencomm_hypercall_console_io(int cmd, int count, char *str); + +extern int xencomm_hypercall_event_channel_op(int cmd, void *op); + +extern int xencomm_hypercall_xen_version(int cmd, void *arg); + +extern int xencomm_hypercall_physdev_op(int cmd, void *op); + +extern int xencomm_hypercall_grant_table_op(unsigned int cmd, void *op, + unsigned int count); + +extern int xencomm_hypercall_sched_op(int cmd, void *arg); + +extern int xencomm_hypercall_multicall(void *call_list, int nr_calls); + +extern int xencomm_hypercall_callback_op(int cmd, void *arg); + +extern int xencomm_hypercall_memory_op(unsigned int cmd, void *arg); + +extern int xencomm_hypercall_suspend(unsigned long srec); + +extern long xencomm_hypercall_vcpu_op(int cmd, int cpu, void *arg); + +extern long xencomm_hypercall_opt_feature(void *arg); + +#endif /* _ASM_IA64_XEN_XCOM_HCALL_H */ diff --git a/arch/ia64/include/asm/xen/xencomm.h b/arch/ia64/include/asm/xen/xencomm.h new file mode 100644 index 0000000..cded677 --- /dev/null +++ b/arch/ia64/include/asm/xen/xencomm.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2006 Hollis Blanchard <hollisb@us.ibm.com>, IBM Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _ASM_IA64_XEN_XENCOMM_H +#define _ASM_IA64_XEN_XENCOMM_H + +#include <xen/xencomm.h> +#include <asm/pgtable.h> + +/* Must be called before any hypercall. */ +extern void xencomm_initialize(void); +extern int xencomm_is_initialized(void); + +/* Check if virtual contiguity means physical contiguity + * where the passed address is a pointer value in virtual address. + * On ia64, identity mapping area in region 7 or the piece of region 5 + * that is mapped by itr[IA64_TR_KERNEL]/dtr[IA64_TR_KERNEL] + */ +static inline int xencomm_is_phys_contiguous(unsigned long addr) +{ + return (PAGE_OFFSET <= addr && + addr < (PAGE_OFFSET + (1UL << IA64_MAX_PHYS_BITS))) || + (KERNEL_START <= addr && + addr < KERNEL_START + KERNEL_TR_PAGE_SIZE); +} + +#endif /* _ASM_IA64_XEN_XENCOMM_H */ diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile index 87fea11..c381ea9 100644 --- a/arch/ia64/kernel/Makefile +++ b/arch/ia64/kernel/Makefile @@ -42,6 +42,10 @@ obj-$(CONFIG_IA64_ESI) += esi.o ifneq ($(CONFIG_IA64_ESI),) obj-y += esi_stub.o # must be in kernel proper endif +obj-$(CONFIG_DMAR) += pci-dma.o +ifeq ($(CONFIG_DMAR), y) +obj-$(CONFIG_SWIOTLB) += pci-swiotlb.o +endif # The gate DSO image is built using a special linker script. targets += gate.so gate-syms.o @@ -112,5 +116,23 @@ clean-files += $(objtree)/include/asm-ia64/nr-irqs.h ASM_PARAVIRT_OBJS = ivt.o entry.o define paravirtualized_native AFLAGS_$(1) += -D__IA64_ASM_PARAVIRTUALIZED_NATIVE +AFLAGS_pvchk-sed-$(1) += -D__IA64_ASM_PARAVIRTUALIZED_PVCHECK +extra-y += pvchk-$(1) endef $(foreach obj,$(ASM_PARAVIRT_OBJS),$(eval $(call paravirtualized_native,$(obj)))) + +# +# Checker for paravirtualizations of privileged operations. +# +quiet_cmd_pv_check_sed = PVCHK $@ +define cmd_pv_check_sed + sed -f $(srctree)/arch/$(SRCARCH)/scripts/pvcheck.sed $< > $@ +endef + +$(obj)/pvchk-sed-%.s: $(src)/%.S $(srctree)/arch/$(SRCARCH)/scripts/pvcheck.sed FORCE + $(call if_changed_dep,as_s_S) +$(obj)/pvchk-%.s: $(obj)/pvchk-sed-%.s FORCE + $(call if_changed,pv_check_sed) +$(obj)/pvchk-%.o: $(obj)/pvchk-%.s FORCE + $(call if_changed,as_o_S) +.PRECIOUS: $(obj)/pvchk-sed-%.s $(obj)/pvchk-%.s $(obj)/pvchk-%.o diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c index 5d1eb7e..bd7acc7 100644 --- a/arch/ia64/kernel/acpi.c +++ b/arch/ia64/kernel/acpi.c @@ -52,6 +52,7 @@ #include <asm/numa.h> #include <asm/sal.h> #include <asm/cyclone.h> +#include <asm/xen/hypervisor.h> #define BAD_MADT_ENTRY(entry, end) ( \ (!entry) || (unsigned long)entry + sizeof(*entry) > end || \ @@ -91,6 +92,9 @@ acpi_get_sysname(void) struct acpi_table_rsdp *rsdp; struct acpi_table_xsdt *xsdt; struct acpi_table_header *hdr; +#ifdef CONFIG_DMAR + u64 i, nentries; +#endif rsdp_phys = acpi_find_rsdp(); if (!rsdp_phys) { @@ -121,7 +125,21 @@ acpi_get_sysname(void) return "uv"; else return "sn2"; + } else if (xen_pv_domain() && !strcmp(hdr->oem_id, "XEN")) { + return "xen"; + } + +#ifdef CONFIG_DMAR + /* Look for Intel IOMMU */ + nentries = (hdr->length - sizeof(*hdr)) / + sizeof(xsdt->table_offset_entry[0]); + for (i = 0; i < nentries; i++) { + hdr = __va(xsdt->table_offset_entry[i]); + if (strncmp(hdr->signature, ACPI_SIG_DMAR, + sizeof(ACPI_SIG_DMAR) - 1) == 0) + return "dig_vtd"; } +#endif return "dig"; #else @@ -137,6 +155,10 @@ acpi_get_sysname(void) return "uv"; # elif defined (CONFIG_IA64_DIG) return "dig"; +# elif defined (CONFIG_IA64_XEN_GUEST) + return "xen"; +# elif defined(CONFIG_IA64_DIG_VTD) + return "dig_vtd"; # else # error Unknown platform. Fix acpi.c. # endif @@ -656,6 +678,30 @@ static int __init acpi_parse_fadt(struct acpi_table_header *table) return 0; } +int __init early_acpi_boot_init(void) +{ + int ret; + + /* + * do a partial walk of MADT to determine how many CPUs + * we have including offline CPUs + */ + if (acpi_table_parse(ACPI_SIG_MADT, acpi_parse_madt)) { + printk(KERN_ERR PREFIX "Can't find MADT\n"); + return 0; + } + + ret = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_SAPIC, + acpi_parse_lsapic, NR_CPUS); + if (ret < 1) + printk(KERN_ERR PREFIX + "Error parsing MADT - no LAPIC entries\n"); + + return 0; +} + + + int __init acpi_boot_init(void) { @@ -679,11 +725,6 @@ int __init acpi_boot_init(void) printk(KERN_ERR PREFIX "Error parsing LAPIC address override entry\n"); - if (acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_SAPIC, acpi_parse_lsapic, NR_CPUS) - < 1) - printk(KERN_ERR PREFIX - "Error parsing MADT - no LAPIC entries\n"); - if (acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_NMI, acpi_parse_lapic_nmi, 0) < 0) printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n"); diff --git a/arch/ia64/kernel/asm-offsets.c b/arch/ia64/kernel/asm-offsets.c index 94c44b1..742dbb1 100644 --- a/arch/ia64/kernel/asm-offsets.c +++ b/arch/ia64/kernel/asm-offsets.c @@ -16,6 +16,9 @@ #include <asm/sigcontext.h> #include <asm/mca.h> +#include <asm/xen/interface.h> +#include <asm/xen/hypervisor.h> + #include "../kernel/sigframe.h" #include "../kernel/fsyscall_gtod_data.h" @@ -286,4 +289,32 @@ void foo(void) offsetof (struct itc_jitter_data_t, itc_jitter)); DEFINE(IA64_ITC_LASTCYCLE_OFFSET, offsetof (struct itc_jitter_data_t, itc_lastcycle)); + +#ifdef CONFIG_XEN + BLANK(); + + DEFINE(XEN_NATIVE_ASM, XEN_NATIVE); + DEFINE(XEN_PV_DOMAIN_ASM, XEN_PV_DOMAIN); + +#define DEFINE_MAPPED_REG_OFS(sym, field) \ + DEFINE(sym, (XMAPPEDREGS_OFS + offsetof(struct mapped_regs, field))) + + DEFINE_MAPPED_REG_OFS(XSI_PSR_I_ADDR_OFS, interrupt_mask_addr); + DEFINE_MAPPED_REG_OFS(XSI_IPSR_OFS, ipsr); + DEFINE_MAPPED_REG_OFS(XSI_IIP_OFS, iip); + DEFINE_MAPPED_REG_OFS(XSI_IFS_OFS, ifs); + DEFINE_MAPPED_REG_OFS(XSI_PRECOVER_IFS_OFS, precover_ifs); + DEFINE_MAPPED_REG_OFS(XSI_ISR_OFS, isr); + DEFINE_MAPPED_REG_OFS(XSI_IFA_OFS, ifa); + DEFINE_MAPPED_REG_OFS(XSI_IIPA_OFS, iipa); + DEFINE_MAPPED_REG_OFS(XSI_IIM_OFS, iim); + DEFINE_MAPPED_REG_OFS(XSI_IHA_OFS, iha); + DEFINE_MAPPED_REG_OFS(XSI_ITIR_OFS, itir); + DEFINE_MAPPED_REG_OFS(XSI_PSR_IC_OFS, interrupt_collection_enabled); + DEFINE_MAPPED_REG_OFS(XSI_BANKNUM_OFS, banknum); + DEFINE_MAPPED_REG_OFS(XSI_BANK0_R16_OFS, bank0_regs[0]); + DEFINE_MAPPED_REG_OFS(XSI_BANK1_R16_OFS, bank1_regs[0]); + DEFINE_MAPPED_REG_OFS(XSI_B0NATS_OFS, vbnat); + DEFINE_MAPPED_REG_OFS(XSI_B1NATS_OFS, vnat); +#endif /* CONFIG_XEN */ } diff --git a/arch/ia64/kernel/crash_dump.c b/arch/ia64/kernel/crash_dump.c index da60e90..23e9129 100644 --- a/arch/ia64/kernel/crash_dump.c +++ b/arch/ia64/kernel/crash_dump.c @@ -8,10 +8,14 @@ #include <linux/errno.h> #include <linux/types.h> +#include <linux/crash_dump.h> #include <asm/page.h> #include <asm/uaccess.h> +/* Stores the physical address of elf header of crash image. */ +unsigned long long elfcorehdr_addr = ELFCORE_ADDR_MAX; + /** * copy_oldmem_page - copy one page from "oldmem" * @pfn: page frame number to be copied diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c index 51b75ce..efaff15 100644 --- a/arch/ia64/kernel/efi.c +++ b/arch/ia64/kernel/efi.c @@ -1335,7 +1335,7 @@ kdump_find_rsvd_region (unsigned long size, struct rsvd_region *r, int n) } #endif -#ifdef CONFIG_PROC_VMCORE +#ifdef CONFIG_CRASH_DUMP /* locate the size find a the descriptor at a certain address */ unsigned long __init vmcore_find_descriptor_size (unsigned long address) diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index 0dd6c14..d435f4a 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S @@ -499,6 +499,7 @@ GLOBAL_ENTRY(prefetch_stack) END(prefetch_stack) GLOBAL_ENTRY(kernel_execve) + rum psr.ac mov r15=__NR_execve // put syscall number in place break __BREAK_SYSCALL br.ret.sptk.many rp @@ -534,6 +535,11 @@ GLOBAL_ENTRY(ia64_trace_syscall) stf.spill [r16]=f10 stf.spill [r17]=f11 br.call.sptk.many rp=syscall_trace_enter // give parent a chance to catch syscall args + cmp.lt p6,p0=r8,r0 // check tracehook + adds r2=PT(R8)+16,sp // r2 = &pt_regs.r8 + adds r3=PT(R10)+16,sp // r3 = &pt_regs.r10 + mov r10=0 +(p6) br.cond.sptk strace_error // syscall failed -> adds r16=PT(F6)+16,sp adds r17=PT(F7)+16,sp ;; diff --git a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S index 66e491d..59301c4 100644 --- a/arch/ia64/kernel/head.S +++ b/arch/ia64/kernel/head.S @@ -260,7 +260,7 @@ start_ap: * Switch into virtual mode: */ movl r16=(IA64_PSR_IT|IA64_PSR_IC|IA64_PSR_DT|IA64_PSR_RT|IA64_PSR_DFH|IA64_PSR_BN \ - |IA64_PSR_DI) + |IA64_PSR_DI|IA64_PSR_AC) ;; mov cr.ipsr=r16 movl r17=1f diff --git a/arch/ia64/kernel/ivt.S b/arch/ia64/kernel/ivt.S index 416a952..f675d8e3 100644 --- a/arch/ia64/kernel/ivt.S +++ b/arch/ia64/kernel/ivt.S @@ -580,7 +580,7 @@ ENTRY(dirty_bit) mov b0=r29 // restore b0 ;; st8 [r17]=r18 // store back updated PTE - itc.d r18 // install updated PTE + ITC_D(p0, r18, r16) // install updated PTE #endif mov pr=r31,-1 // restore pr RFI @@ -646,7 +646,7 @@ ENTRY(iaccess_bit) mov b0=r29 // restore b0 ;; st8 [r17]=r18 // store back updated PTE - itc.i r18 // install updated PTE + ITC_I(p0, r18, r16) // install updated PTE #endif /* !CONFIG_SMP */ mov pr=r31,-1 RFI @@ -698,7 +698,7 @@ ENTRY(daccess_bit) or r18=_PAGE_A,r18 // set the accessed bit ;; st8 [r17]=r18 // store back updated PTE - itc.d r18 // install updated PTE + ITC_D(p0, r18, r16) // install updated PTE #endif mov b0=r29 // restore b0 mov pr=r31,-1 diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c index 7dd96c1..bab1de2 100644 --- a/arch/ia64/kernel/mca.c +++ b/arch/ia64/kernel/mca.c @@ -1139,7 +1139,7 @@ ia64_mca_modify_original_stack(struct pt_regs *regs, return previous_current; no_mod: - printk(KERN_INFO "cpu %d, %s %s, original stack not modified\n", + mprintk(KERN_INFO "cpu %d, %s %s, original stack not modified\n", smp_processor_id(), type, msg); return previous_current; } diff --git a/arch/ia64/kernel/mca_drv.c b/arch/ia64/kernel/mca_drv.c index fab1d21..f94aaa8 100644 --- a/arch/ia64/kernel/mca_drv.c +++ b/arch/ia64/kernel/mca_drv.c @@ -158,7 +158,7 @@ mca_handler_bh(unsigned long paddr, void *iip, unsigned long ipsr) ia64_mlogbuf_dump(); printk(KERN_ERR "OS_MCA: process [cpu %d, pid: %d, uid: %d, " "iip: %p, psr: 0x%lx,paddr: 0x%lx](%s) encounters MCA.\n", - raw_smp_processor_id(), current->pid, current->uid, + raw_smp_processor_id(), current->pid, current_uid(), iip, ipsr, paddr, current->comm); spin_lock(&mca_bh_lock); diff --git a/arch/ia64/kernel/msi_ia64.c b/arch/ia64/kernel/msi_ia64.c index 60c6ef6..702a09c 100644 --- a/arch/ia64/kernel/msi_ia64.c +++ b/arch/ia64/kernel/msi_ia64.c @@ -5,6 +5,7 @@ #include <linux/pci.h> #include <linux/irq.h> #include <linux/msi.h> +#include <linux/dmar.h> #include <asm/smp.h> /* @@ -162,3 +163,82 @@ void arch_teardown_msi_irq(unsigned int irq) return ia64_teardown_msi_irq(irq); } + +#ifdef CONFIG_DMAR +#ifdef CONFIG_SMP +static void dmar_msi_set_affinity(unsigned int irq, cpumask_t mask) +{ + struct irq_cfg *cfg = irq_cfg + irq; + struct msi_msg msg; + int cpu = first_cpu(mask); + + + if (!cpu_online(cpu)) + return; + + if (irq_prepare_move(irq, cpu)) + return; + + dmar_msi_read(irq, &msg); + + msg.data &= ~MSI_DATA_VECTOR_MASK; + msg.data |= MSI_DATA_VECTOR(cfg->vector); + msg.address_lo &= ~MSI_ADDR_DESTID_MASK; + msg.address_lo |= MSI_ADDR_DESTID_CPU(cpu_physical_id(cpu)); + + dmar_msi_write(irq, &msg); + irq_desc[irq].affinity = mask; +} +#endif /* CONFIG_SMP */ + +struct irq_chip dmar_msi_type = { + .name = "DMAR_MSI", + .unmask = dmar_msi_unmask, + .mask = dmar_msi_mask, + .ack = ia64_ack_msi_irq, +#ifdef CONFIG_SMP + .set_affinity = dmar_msi_set_affinity, +#endif + .retrigger = ia64_msi_retrigger_irq, +}; + +static int +msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg) +{ + struct irq_cfg *cfg = irq_cfg + irq; + unsigned dest; + cpumask_t mask; + + cpus_and(mask, irq_to_domain(irq), cpu_online_map); + dest = cpu_physical_id(first_cpu(mask)); + + msg->address_hi = 0; + msg->address_lo = + MSI_ADDR_HEADER | + MSI_ADDR_DESTMODE_PHYS | + MSI_ADDR_REDIRECTION_CPU | + MSI_ADDR_DESTID_CPU(dest); + + msg->data = + MSI_DATA_TRIGGER_EDGE | + MSI_DATA_LEVEL_ASSERT | + MSI_DATA_DELIVERY_FIXED | + MSI_DATA_VECTOR(cfg->vector); + return 0; +} + +int arch_setup_dmar_msi(unsigned int irq) +{ + int ret; + struct msi_msg msg; + + ret = msi_compose_msg(NULL, irq, &msg); + if (ret < 0) + return ret; + dmar_msi_write(irq, &msg); + set_irq_chip_and_handler_name(irq, &dmar_msi_type, handle_edge_irq, + "edge"); + return 0; +} +#endif /* CONFIG_DMAR */ + diff --git a/arch/ia64/kernel/nr-irqs.c b/arch/ia64/kernel/nr-irqs.c index 8273afc..ee56457 100644 --- a/arch/ia64/kernel/nr-irqs.c +++ b/arch/ia64/kernel/nr-irqs.c @@ -10,6 +10,7 @@ #include <linux/kbuild.h> #include <linux/threads.h> #include <asm/native/irq.h> +#include <asm/xen/irq.h> void foo(void) { diff --git a/arch/ia64/kernel/paravirt.c b/arch/ia64/kernel/paravirt.c index afaf5b9..9f14c16 100644 --- a/arch/ia64/kernel/paravirt.c +++ b/arch/ia64/kernel/paravirt.c @@ -130,7 +130,7 @@ ia64_native_getreg_func(int regnum) unsigned long res = -1; switch (regnum) { CASE_GET_REG(GP); - CASE_GET_REG(IP); + /*CASE_GET_REG(IP);*/ /* returned ip value shouldn't be constant */ CASE_GET_REG(PSR); CASE_GET_REG(TP); CASE_GET_REG(SP); @@ -332,7 +332,7 @@ ia64_native_iosapic_write(char __iomem *iosapic, unsigned int reg, u32 val) struct pv_iosapic_ops pv_iosapic_ops = { .pcat_compat_init = ia64_native_iosapic_pcat_compat_init, - .get_irq_chip = ia64_native_iosapic_get_irq_chip, + .__get_irq_chip = ia64_native_iosapic_get_irq_chip, .__read = ia64_native_iosapic_read, .__write = ia64_native_iosapic_write, diff --git a/arch/ia64/kernel/paravirt_inst.h b/arch/ia64/kernel/paravirt_inst.h index 5cad6fb..64d6d81 100644 --- a/arch/ia64/kernel/paravirt_inst.h +++ b/arch/ia64/kernel/paravirt_inst.h @@ -20,7 +20,9 @@ * */ -#ifdef __IA64_ASM_PARAVIRTUALIZED_XEN +#ifdef __IA64_ASM_PARAVIRTUALIZED_PVCHECK +#include <asm/native/pvchk_inst.h> +#elif defined(__IA64_ASM_PARAVIRTUALIZED_XEN) #include <asm/xen/inst.h> #include <asm/xen/minstate.h> #else diff --git a/arch/ia64/kernel/pci-dma.c b/arch/ia64/kernel/pci-dma.c new file mode 100644 index 0000000..2a92f63 --- /dev/null +++ b/arch/ia64/kernel/pci-dma.c @@ -0,0 +1,119 @@ +/* + * Dynamic DMA mapping support. + */ + +#include <linux/types.h> +#include <linux/mm.h> +#include <linux/string.h> +#include <linux/pci.h> +#include <linux/module.h> +#include <linux/dmar.h> +#include <asm/iommu.h> +#include <asm/machvec.h> +#include <linux/dma-mapping.h> + +#include <asm/system.h> + +#ifdef CONFIG_DMAR + +#include <linux/kernel.h> + +#include <asm/page.h> + +dma_addr_t bad_dma_address __read_mostly; +EXPORT_SYMBOL(bad_dma_address); + +static int iommu_sac_force __read_mostly; + +int no_iommu __read_mostly; +#ifdef CONFIG_IOMMU_DEBUG +int force_iommu __read_mostly = 1; +#else +int force_iommu __read_mostly; +#endif + +/* Set this to 1 if there is a HW IOMMU in the system */ +int iommu_detected __read_mostly; + +/* Dummy device used for NULL arguments (normally ISA). Better would + be probably a smaller DMA mask, but this is bug-to-bug compatible + to i386. */ +struct device fallback_dev = { + .bus_id = "fallback device", + .coherent_dma_mask = DMA_32BIT_MASK, + .dma_mask = &fallback_dev.coherent_dma_mask, +}; + +void __init pci_iommu_alloc(void) +{ + /* + * The order of these functions is important for + * fall-back/fail-over reasons + */ + detect_intel_iommu(); + +#ifdef CONFIG_SWIOTLB + pci_swiotlb_init(); +#endif +} + +static int __init pci_iommu_init(void) +{ + if (iommu_detected) + intel_iommu_init(); + + return 0; +} + +/* Must execute after PCI subsystem */ +fs_initcall(pci_iommu_init); + +void pci_iommu_shutdown(void) +{ + return; +} + +void __init +iommu_dma_init(void) +{ + return; +} + +struct dma_mapping_ops *dma_ops; +EXPORT_SYMBOL(dma_ops); + +int iommu_dma_supported(struct device *dev, u64 mask) +{ + struct dma_mapping_ops *ops = get_dma_ops(dev); + + if (ops->dma_supported_op) + return ops->dma_supported_op(dev, mask); + + /* Copied from i386. Doesn't make much sense, because it will + only work for pci_alloc_coherent. + The caller just has to use GFP_DMA in this case. */ + if (mask < DMA_24BIT_MASK) + return 0; + + /* Tell the device to use SAC when IOMMU force is on. This + allows the driver to use cheaper accesses in some cases. + + Problem with this is that if we overflow the IOMMU area and + return DAC as fallback address the device may not handle it + correctly. + + As a special case some controllers have a 39bit address + mode that is as efficient as 32bit (aic79xx). Don't force + SAC for these. Assume all masks <= 40 bits are of this + type. Normally this doesn't make any difference, but gives + more gentle handling of IOMMU overflow. */ + if (iommu_sac_force && (mask >= DMA_40BIT_MASK)) { + dev_info(dev, "Force SAC with mask %lx\n", mask); + return 0; + } + + return 1; +} +EXPORT_SYMBOL(iommu_dma_supported); + +#endif diff --git a/arch/ia64/kernel/pci-swiotlb.c b/arch/ia64/kernel/pci-swiotlb.c new file mode 100644 index 0000000..16c5051 --- /dev/null +++ b/arch/ia64/kernel/pci-swiotlb.c @@ -0,0 +1,46 @@ +/* Glue code to lib/swiotlb.c */ + +#include <linux/pci.h> +#include <linux/cache.h> +#include <linux/module.h> +#include <linux/dma-mapping.h> + +#include <asm/swiotlb.h> +#include <asm/dma.h> +#include <asm/iommu.h> +#include <asm/machvec.h> + +int swiotlb __read_mostly; +EXPORT_SYMBOL(swiotlb); + +struct dma_mapping_ops swiotlb_dma_ops = { + .mapping_error = swiotlb_dma_mapping_error, + .alloc_coherent = swiotlb_alloc_coherent, + .free_coherent = swiotlb_free_coherent, + .map_single = swiotlb_map_single, + .unmap_single = swiotlb_unmap_single, + .sync_single_for_cpu = swiotlb_sync_single_for_cpu, + .sync_single_for_device = swiotlb_sync_single_for_device, + .sync_single_range_for_cpu = swiotlb_sync_single_range_for_cpu, + .sync_single_range_for_device = swiotlb_sync_single_range_for_device, + .sync_sg_for_cpu = swiotlb_sync_sg_for_cpu, + .sync_sg_for_device = swiotlb_sync_sg_for_device, + .map_sg = swiotlb_map_sg, + .unmap_sg = swiotlb_unmap_sg, + .dma_supported_op = swiotlb_dma_supported, +}; + +void __init pci_swiotlb_init(void) +{ + if (!iommu_detected) { +#ifdef CONFIG_IA64_GENERIC + swiotlb = 1; + printk(KERN_INFO "PCI-DMA: Re-initialize machine vector.\n"); + machvec_init("dig"); + swiotlb_init(); + dma_ops = &swiotlb_dma_ops; +#else + panic("Unable to find Intel IOMMU"); +#endif + } +} diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c index fc8f350..0e49975 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c @@ -40,6 +40,7 @@ #include <linux/capability.h> #include <linux/rcupdate.h> #include <linux/completion.h> +#include <linux/tracehook.h> #include <asm/errno.h> #include <asm/intrinsics.h> @@ -1994,11 +1995,6 @@ pfm_close(struct inode *inode, struct file *filp) return -EBADF; } - if (filp->f_flags & FASYNC) { - DPRINT(("cleaning up async_queue=%p\n", ctx->ctx_async_queue)); - pfm_do_fasync(-1, filp, ctx, 0); - } - PROTECT_CTX(ctx, flags); state = ctx->ctx_state; @@ -2224,8 +2220,8 @@ pfm_alloc_file(pfm_context_t *ctx) DPRINT(("new inode ino=%ld @%p\n", inode->i_ino, inode)); inode->i_mode = S_IFCHR|S_IRUGO; - inode->i_uid = current->fsuid; - inode->i_gid = current->fsgid; + inode->i_uid = current_fsuid(); + inode->i_gid = current_fsgid(); sprintf(name, "[%lu]", inode->i_ino); this.name = name; @@ -2403,22 +2399,33 @@ error_kmem: static int pfm_bad_permissions(struct task_struct *task) { + const struct cred *tcred; + uid_t uid = current_uid(); + gid_t gid = current_gid(); + int ret; + + rcu_read_lock(); + tcred = __task_cred(task); + /* inspired by ptrace_attach() */ DPRINT(("cur: uid=%d gid=%d task: euid=%d suid=%d uid=%d egid=%d sgid=%d\n", - current->uid, - current->gid, - task->euid, - task->suid, - task->uid, - task->egid, - task->sgid)); - - return ((current->uid != task->euid) - || (current->uid != task->suid) - || (current->uid != task->uid) - || (current->gid != task->egid) - || (current->gid != task->sgid) - || (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE); + uid, + gid, + tcred->euid, + tcred->suid, + tcred->uid, + tcred->egid, + tcred->sgid)); + + ret = ((uid != tcred->euid) + || (uid != tcred->suid) + || (uid != tcred->uid) + || (gid != tcred->egid) + || (gid != tcred->sgid) + || (gid != tcred->gid)) && !capable(CAP_SYS_PTRACE); + + rcu_read_unlock(); + return ret; } static int @@ -3684,7 +3691,7 @@ pfm_restart(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs) PFM_SET_WORK_PENDING(task, 1); - tsk_set_notify_resume(task); + set_notify_resume(task); /* * XXX: send reschedule if task runs on another CPU @@ -5044,8 +5051,6 @@ pfm_handle_work(void) PFM_SET_WORK_PENDING(current, 0); - tsk_clear_notify_resume(current); - regs = task_pt_regs(current); /* @@ -5414,7 +5419,7 @@ pfm_overflow_handler(struct task_struct *task, pfm_context_t *ctx, u64 pmc0, str * when coming from ctxsw, current still points to the * previous task, therefore we must work with task and not current. */ - tsk_set_notify_resume(task); + set_notify_resume(task); } /* * defer until state is changed (shorten spin window). the context is locked diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c index 3ab8373..c571627 100644 --- a/arch/ia64/kernel/process.c +++ b/arch/ia64/kernel/process.c @@ -28,6 +28,7 @@ #include <linux/delay.h> #include <linux/kdebug.h> #include <linux/utsname.h> +#include <linux/tracehook.h> #include <asm/cpu.h> #include <asm/delay.h> @@ -160,21 +161,6 @@ show_regs (struct pt_regs *regs) show_stack(NULL, NULL); } -void tsk_clear_notify_resume(struct task_struct *tsk) -{ -#ifdef CONFIG_PERFMON - if (tsk->thread.pfm_needs_checking) - return; -#endif - if (test_ti_thread_flag(task_thread_info(tsk), TIF_RESTORE_RSE)) - return; - clear_ti_thread_flag(task_thread_info(tsk), TIF_NOTIFY_RESUME); -} - -/* - * do_notify_resume_user(): - * Called from notify_resume_user at entry.S, with interrupts disabled. - */ void do_notify_resume_user(sigset_t *unused, struct sigscratch *scr, long in_syscall) { @@ -203,6 +189,11 @@ do_notify_resume_user(sigset_t *unused, struct sigscratch *scr, long in_syscall) ia64_do_signal(scr, in_syscall); } + if (test_thread_flag(TIF_NOTIFY_RESUME)) { + clear_thread_flag(TIF_NOTIFY_RESUME); + tracehook_notify_resume(&scr->pt); + } + /* copy user rbs to kernel rbs */ if (unlikely(test_thread_flag(TIF_RESTORE_RSE))) { local_irq_enable(); /* force interrupt enable */ @@ -251,7 +242,6 @@ default_idle (void) /* We don't actually take CPU down, just spin without interrupts. */ static inline void play_dead(void) { - extern void ia64_cpu_local_tick (void); unsigned int this_cpu = smp_processor_id(); /* Ack it */ diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c index 2a9943b..92c9689 100644 --- a/arch/ia64/kernel/ptrace.c +++ b/arch/ia64/kernel/ptrace.c @@ -22,6 +22,7 @@ #include <linux/signal.h> #include <linux/regset.h> #include <linux/elf.h> +#include <linux/tracehook.h> #include <asm/pgtable.h> #include <asm/processor.h> @@ -603,7 +604,7 @@ void ia64_ptrace_stop(void) { if (test_and_set_tsk_thread_flag(current, TIF_RESTORE_RSE)) return; - tsk_set_notify_resume(current); + set_notify_resume(current); unw_init_running(do_sync_rbs, ia64_sync_user_rbs); } @@ -613,7 +614,6 @@ void ia64_ptrace_stop(void) void ia64_sync_krbs(void) { clear_tsk_thread_flag(current, TIF_RESTORE_RSE); - tsk_clear_notify_resume(current); unw_init_running(do_sync_rbs, ia64_sync_kernel_rbs); } @@ -644,7 +644,7 @@ ptrace_attach_sync_user_rbs (struct task_struct *child) spin_lock_irq(&child->sighand->siglock); if (child->state == TASK_STOPPED && !test_and_set_tsk_thread_flag(child, TIF_RESTORE_RSE)) { - tsk_set_notify_resume(child); + set_notify_resume(child); child->state = TASK_TRACED; stopped = 1; @@ -1232,37 +1232,16 @@ arch_ptrace (struct task_struct *child, long request, long addr, long data) } -static void -syscall_trace (void) -{ - /* - * The 0x80 provides a way for the tracing parent to - * distinguish between a syscall stop and SIGTRAP delivery. - */ - ptrace_notify(SIGTRAP - | ((current->ptrace & PT_TRACESYSGOOD) ? 0x80 : 0)); - - /* - * This isn't the same as continuing with a signal, but it - * will do for normal use. strace only continues with a - * signal if the stopping signal is not SIGTRAP. -brl - */ - if (current->exit_code) { - send_sig(current->exit_code, current, 1); - current->exit_code = 0; - } -} - /* "asmlinkage" so the input arguments are preserved... */ -asmlinkage void +asmlinkage long syscall_trace_enter (long arg0, long arg1, long arg2, long arg3, long arg4, long arg5, long arg6, long arg7, struct pt_regs regs) { - if (test_thread_flag(TIF_SYSCALL_TRACE) - && (current->ptrace & PT_PTRACED)) - syscall_trace(); + if (test_thread_flag(TIF_SYSCALL_TRACE)) + if (tracehook_report_syscall_entry(®s)) + return -ENOSYS; /* copy user rbs to kernel rbs */ if (test_thread_flag(TIF_RESTORE_RSE)) @@ -1283,6 +1262,7 @@ syscall_trace_enter (long arg0, long arg1, long arg2, long arg3, audit_syscall_entry(arch, syscall, arg0, arg1, arg2, arg3); } + return 0; } /* "asmlinkage" so the input arguments are preserved... */ @@ -1292,6 +1272,8 @@ syscall_trace_leave (long arg0, long arg1, long arg2, long arg3, long arg4, long arg5, long arg6, long arg7, struct pt_regs regs) { + int step; + if (unlikely(current->audit_context)) { int success = AUDITSC_RESULT(regs.r10); long result = regs.r8; @@ -1301,10 +1283,9 @@ syscall_trace_leave (long arg0, long arg1, long arg2, long arg3, audit_syscall_exit(success, result); } - if ((test_thread_flag(TIF_SYSCALL_TRACE) - || test_thread_flag(TIF_SINGLESTEP)) - && (current->ptrace & PT_PTRACED)) - syscall_trace(); + step = test_thread_flag(TIF_SINGLESTEP); + if (step || test_thread_flag(TIF_SYSCALL_TRACE)) + tracehook_report_syscall_exit(®s, step); /* copy user rbs to kernel rbs */ if (test_thread_flag(TIF_RESTORE_RSE)) @@ -1940,7 +1921,7 @@ gpregs_writeback(struct task_struct *target, { if (test_and_set_tsk_thread_flag(target, TIF_RESTORE_RSE)) return 0; - tsk_set_notify_resume(target); + set_notify_resume(target); return do_regset_call(do_gpregs_writeback, target, regset, 0, 0, NULL, NULL); } @@ -2199,3 +2180,68 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *tsk) #endif return &user_ia64_view; } + +struct syscall_get_set_args { + unsigned int i; + unsigned int n; + unsigned long *args; + struct pt_regs *regs; + int rw; +}; + +static void syscall_get_set_args_cb(struct unw_frame_info *info, void *data) +{ + struct syscall_get_set_args *args = data; + struct pt_regs *pt = args->regs; + unsigned long *krbs, cfm, ndirty; + int i, count; + + if (unw_unwind_to_user(info) < 0) + return; + + cfm = pt->cr_ifs; + krbs = (unsigned long *)info->task + IA64_RBS_OFFSET/8; + ndirty = ia64_rse_num_regs(krbs, krbs + (pt->loadrs >> 19)); + + count = 0; + if (in_syscall(pt)) + count = min_t(int, args->n, cfm & 0x7f); + + for (i = 0; i < count; i++) { + if (args->rw) + *ia64_rse_skip_regs(krbs, ndirty + i + args->i) = + args->args[i]; + else + args->args[i] = *ia64_rse_skip_regs(krbs, + ndirty + i + args->i); + } + + if (!args->rw) { + while (i < args->n) { + args->args[i] = 0; + i++; + } + } +} + +void ia64_syscall_get_set_arguments(struct task_struct *task, + struct pt_regs *regs, unsigned int i, unsigned int n, + unsigned long *args, int rw) +{ + struct syscall_get_set_args data = { + .i = i, + .n = n, + .args = args, + .regs = regs, + .rw = rw, + }; + + if (task == current) + unw_init_running(syscall_get_set_args_cb, &data); + else { + struct unw_frame_info ufi; + memset(&ufi, 0, sizeof(ufi)); + unw_init_from_blocked_task(&ufi, task); + syscall_get_set_args_cb(&ufi, &data); + } +} diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index de636b2..865af27 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c @@ -116,6 +116,13 @@ unsigned int num_io_spaces; */ #define I_CACHE_STRIDE_SHIFT 5 /* Safest way to go: 32 bytes by 32 bytes */ unsigned long ia64_i_cache_stride_shift = ~0; +/* + * "clflush_cache_range()" needs to know what processor dependent stride size to + * use when it flushes cache lines including both d-cache and i-cache. + */ +/* Safest way to go: 32 bytes by 32 bytes */ +#define CACHE_STRIDE_SHIFT 5 +unsigned long ia64_cache_stride_shift = ~0; /* * The merge_mask variable needs to be set to (max(iommu_page_size(iommu)) - 1). This @@ -352,7 +359,7 @@ reserve_memory (void) } #endif -#ifdef CONFIG_PROC_VMCORE +#ifdef CONFIG_CRASH_DUMP if (reserve_elfcorehdr(&rsvd_region[n].start, &rsvd_region[n].end) == 0) n++; @@ -478,7 +485,12 @@ static __init int setup_nomca(char *s) } early_param("nomca", setup_nomca); -#ifdef CONFIG_PROC_VMCORE +/* + * Note: elfcorehdr_addr is not just limited to vmcore. It is also used by + * is_kdump_kernel() to determine if we are booting after a panic. Hence + * ifdef it under CONFIG_CRASH_DUMP and not CONFIG_PROC_VMCORE. + */ +#ifdef CONFIG_CRASH_DUMP /* elfcorehdr= specifies the location of elf core header * stored by the crashed kernel. */ @@ -502,11 +514,11 @@ int __init reserve_elfcorehdr(unsigned long *start, unsigned long *end) * to work properly. */ - if (elfcorehdr_addr >= ELFCORE_ADDR_MAX) + if (!is_vmcore_usable()) return -EINVAL; if ((length = vmcore_find_descriptor_size(elfcorehdr_addr)) == 0) { - elfcorehdr_addr = ELFCORE_ADDR_MAX; + vmcore_unusable(); return -EINVAL; } @@ -549,8 +561,12 @@ setup_arch (char **cmdline_p) #ifdef CONFIG_ACPI /* Initialize the ACPI boot-time table parser */ acpi_table_init(); + early_acpi_boot_init(); # ifdef CONFIG_ACPI_NUMA acpi_numa_init(); +#ifdef CONFIG_ACPI_HOTPLUG_CPU + prefill_possible_map(); +#endif per_cpu_scan_finalize((cpus_weight(early_cpu_possible_map) == 0 ? 32 : cpus_weight(early_cpu_possible_map)), additional_cpus > 0 ? additional_cpus : 0); @@ -841,19 +857,17 @@ void __init setup_per_cpu_areas (void) { /* start_kernel() requires this... */ -#ifdef CONFIG_ACPI_HOTPLUG_CPU - prefill_possible_map(); -#endif } /* - * Calculate the max. cache line size. + * Do the following calculations: * - * In addition, the minimum of the i-cache stride sizes is calculated for - * "flush_icache_range()". + * 1. the max. cache line size. + * 2. the minimum of the i-cache stride sizes for "flush_icache_range()". + * 3. the minimum of the cache stride sizes for "clflush_cache_range()". */ static void __cpuinit -get_max_cacheline_size (void) +get_cache_info(void) { unsigned long line_size, max = 1; u64 l, levels, unique_caches; @@ -867,12 +881,14 @@ get_max_cacheline_size (void) max = SMP_CACHE_BYTES; /* Safest setup for "flush_icache_range()" */ ia64_i_cache_stride_shift = I_CACHE_STRIDE_SHIFT; + /* Safest setup for "clflush_cache_range()" */ + ia64_cache_stride_shift = CACHE_STRIDE_SHIFT; goto out; } for (l = 0; l < levels; ++l) { - status = ia64_pal_cache_config_info(l, /* cache_type (data_or_unified)= */ 2, - &cci); + /* cache_type (data_or_unified)=2 */ + status = ia64_pal_cache_config_info(l, 2, &cci); if (status != 0) { printk(KERN_ERR "%s: ia64_pal_cache_config_info(l=%lu, 2) failed (status=%ld)\n", @@ -880,15 +896,21 @@ get_max_cacheline_size (void) max = SMP_CACHE_BYTES; /* The safest setup for "flush_icache_range()" */ cci.pcci_stride = I_CACHE_STRIDE_SHIFT; + /* The safest setup for "clflush_cache_range()" */ + ia64_cache_stride_shift = CACHE_STRIDE_SHIFT; cci.pcci_unified = 1; + } else { + if (cci.pcci_stride < ia64_cache_stride_shift) + ia64_cache_stride_shift = cci.pcci_stride; + + line_size = 1 << cci.pcci_line_size; + if (line_size > max) + max = line_size; } - line_size = 1 << cci.pcci_line_size; - if (line_size > max) - max = line_size; + if (!cci.pcci_unified) { - status = ia64_pal_cache_config_info(l, - /* cache_type (instruction)= */ 1, - &cci); + /* cache_type (instruction)=1*/ + status = ia64_pal_cache_config_info(l, 1, &cci); if (status != 0) { printk(KERN_ERR "%s: ia64_pal_cache_config_info(l=%lu, 1) failed (status=%ld)\n", @@ -942,7 +964,7 @@ cpu_init (void) } #endif - get_max_cacheline_size(); + get_cache_info(); /* * We can't pass "local_cpu_data" to identify_cpu() because we haven't called diff --git a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c index 19c5a78..e1821ca 100644 --- a/arch/ia64/kernel/signal.c +++ b/arch/ia64/kernel/signal.c @@ -11,6 +11,7 @@ #include <linux/kernel.h> #include <linux/mm.h> #include <linux/ptrace.h> +#include <linux/tracehook.h> #include <linux/sched.h> #include <linux/signal.h> #include <linux/smp.h> @@ -228,7 +229,7 @@ ia64_rt_sigreturn (struct sigscratch *scr) si.si_errno = 0; si.si_code = SI_KERNEL; si.si_pid = task_pid_vnr(current); - si.si_uid = current->uid; + si.si_uid = current_uid(); si.si_addr = sc; force_sig_info(SIGSEGV, &si, current); return retval; @@ -325,7 +326,7 @@ force_sigsegv_info (int sig, void __user *addr) si.si_errno = 0; si.si_code = SI_KERNEL; si.si_pid = task_pid_vnr(current); - si.si_uid = current->uid; + si.si_uid = current_uid(); si.si_addr = addr; force_sig_info(SIGSEGV, &si, current); return 0; @@ -439,6 +440,13 @@ handle_signal (unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigse sigaddset(¤t->blocked, sig); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); + + /* + * Let tracing know that we've done the handler setup. + */ + tracehook_signal_handler(sig, info, ka, &scr->pt, + test_thread_flag(TIF_SINGLESTEP)); + return 1; } diff --git a/arch/ia64/kernel/topology.c b/arch/ia64/kernel/topology.c index 26228e2..c75b914 100644 --- a/arch/ia64/kernel/topology.c +++ b/arch/ia64/kernel/topology.c @@ -53,10 +53,12 @@ int __ref arch_register_cpu(int num) } EXPORT_SYMBOL(arch_register_cpu); -void arch_unregister_cpu(int num) +void __ref arch_unregister_cpu(int num) { unregister_cpu(&sysfs_cpus[num].cpu); +#ifdef CONFIG_ACPI unmap_cpu_from_node(num, cpu_to_node(num)); +#endif } EXPORT_SYMBOL(arch_unregister_cpu); #else diff --git a/arch/ia64/kvm/Kconfig b/arch/ia64/kvm/Kconfig index 7914e48..f833a0b 100644 --- a/arch/ia64/kvm/Kconfig +++ b/arch/ia64/kvm/Kconfig @@ -20,6 +20,8 @@ if VIRTUALIZATION config KVM tristate "Kernel-based Virtual Machine (KVM) support" depends on HAVE_KVM && EXPERIMENTAL + # for device assignment: + depends on PCI select PREEMPT_NOTIFIERS select ANON_INODES ---help--- @@ -46,4 +48,6 @@ config KVM_INTEL config KVM_TRACE bool +source drivers/virtio/Kconfig + endif # VIRTUALIZATION diff --git a/arch/ia64/kvm/Makefile b/arch/ia64/kvm/Makefile index bf22fb9..92cef66 100644 --- a/arch/ia64/kvm/Makefile +++ b/arch/ia64/kvm/Makefile @@ -29,13 +29,18 @@ define cmd_offsets echo ""; \ echo "#endif" ) > $@ endef + # We use internal rules to avoid the "is up to date" message from make -arch/ia64/kvm/asm-offsets.s: arch/ia64/kvm/asm-offsets.c +arch/ia64/kvm/asm-offsets.s: arch/ia64/kvm/asm-offsets.c \ + $(wildcard $(srctree)/arch/ia64/include/asm/*.h)\ + $(wildcard $(srctree)/include/linux/*.h) $(call if_changed_dep,cc_s_c) $(obj)/$(offsets-file): arch/ia64/kvm/asm-offsets.s $(call cmd,offsets) +FORCE : $(obj)/$(offsets-file) + # # Makefile for Kernel-based Virtual Machine module # @@ -44,13 +49,16 @@ EXTRA_CFLAGS += -Ivirt/kvm -Iarch/ia64/kvm/ EXTRA_AFLAGS += -Ivirt/kvm -Iarch/ia64/kvm/ common-objs = $(addprefix ../../../virt/kvm/, kvm_main.o ioapic.o \ - coalesced_mmio.o) + coalesced_mmio.o irq_comm.o) + +ifeq ($(CONFIG_DMAR),y) +common-objs += $(addprefix ../../../virt/kvm/, vtd.o) +endif kvm-objs := $(common-objs) kvm-ia64.o kvm_fw.o obj-$(CONFIG_KVM) += kvm.o -FORCE : $(obj)/$(offsets-file) -EXTRA_CFLAGS_vcpu.o += -mfixed-range=f2-f5,f12-f127 +CFLAGS_vcpu.o += -mfixed-range=f2-f5,f12-f127 kvm-intel-objs = vmm.o vmm_ivt.o trampoline.o vcpu.o optvfault.o mmio.o \ vtlb.o process.o #Add link memcpy and memset to avoid possible structure assignment error diff --git a/arch/ia64/kvm/irq.h b/arch/ia64/kvm/irq.h new file mode 100644 index 0000000..c6786e8 --- /dev/null +++ b/arch/ia64/kvm/irq.h @@ -0,0 +1,31 @@ +/* + * irq.h: In-kernel interrupt controller related definitions + * Copyright (c) 2008, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307 USA. + * + * Authors: + * Xiantao Zhang <xiantao.zhang@intel.com> + * + */ + +#ifndef __IRQ_H +#define __IRQ_H + +static inline int irqchip_in_kernel(struct kvm *kvm) +{ + return 1; +} + +#endif diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c index cd0d1a7..af1464f 100644 --- a/arch/ia64/kvm/kvm-ia64.c +++ b/arch/ia64/kvm/kvm-ia64.c @@ -31,6 +31,7 @@ #include <linux/bitops.h> #include <linux/hrtimer.h> #include <linux/uaccess.h> +#include <linux/intel-iommu.h> #include <asm/pgtable.h> #include <asm/gcc_intrin.h> @@ -45,6 +46,7 @@ #include "iodev.h" #include "ioapic.h" #include "lapic.h" +#include "irq.h" static unsigned long kvm_vmm_base; static unsigned long kvm_vsa_base; @@ -179,12 +181,16 @@ int kvm_dev_ioctl_check_extension(long ext) switch (ext) { case KVM_CAP_IRQCHIP: case KVM_CAP_USER_MEMORY: + case KVM_CAP_MP_STATE: r = 1; break; case KVM_CAP_COALESCED_MMIO: r = KVM_COALESCED_MMIO_PAGE_OFFSET; break; + case KVM_CAP_IOMMU: + r = intel_iommu_found(); + break; default: r = 0; } @@ -379,6 +385,7 @@ static int handle_global_purge(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) struct kvm *kvm = vcpu->kvm; struct call_data call_data; int i; + call_data.ptc_g_data = p->u.ptc_g_data; for (i = 0; i < KVM_MAX_VCPUS; i++) { @@ -412,33 +419,41 @@ int kvm_emulate_halt(struct kvm_vcpu *vcpu) ktime_t kt; long itc_diff; unsigned long vcpu_now_itc; - unsigned long expires; struct hrtimer *p_ht = &vcpu->arch.hlt_timer; unsigned long cyc_per_usec = local_cpu_data->cyc_per_usec; struct vpd *vpd = to_host(vcpu->kvm, vcpu->arch.vpd); - vcpu_now_itc = ia64_getreg(_IA64_REG_AR_ITC) + vcpu->arch.itc_offset; + if (irqchip_in_kernel(vcpu->kvm)) { - if (time_after(vcpu_now_itc, vpd->itm)) { - vcpu->arch.timer_check = 1; - return 1; - } - itc_diff = vpd->itm - vcpu_now_itc; - if (itc_diff < 0) - itc_diff = -itc_diff; + vcpu_now_itc = ia64_getreg(_IA64_REG_AR_ITC) + vcpu->arch.itc_offset; - expires = div64_u64(itc_diff, cyc_per_usec); - kt = ktime_set(0, 1000 * expires); - vcpu->arch.ht_active = 1; - hrtimer_start(p_ht, kt, HRTIMER_MODE_ABS); + if (time_after(vcpu_now_itc, vpd->itm)) { + vcpu->arch.timer_check = 1; + return 1; + } + itc_diff = vpd->itm - vcpu_now_itc; + if (itc_diff < 0) + itc_diff = -itc_diff; + + expires = div64_u64(itc_diff, cyc_per_usec); + kt = ktime_set(0, 1000 * expires); + + down_read(&vcpu->kvm->slots_lock); + vcpu->arch.ht_active = 1; + hrtimer_start(p_ht, kt, HRTIMER_MODE_ABS); - if (irqchip_in_kernel(vcpu->kvm)) { vcpu->arch.mp_state = KVM_MP_STATE_HALTED; kvm_vcpu_block(vcpu); hrtimer_cancel(p_ht); vcpu->arch.ht_active = 0; + if (test_and_clear_bit(KVM_REQ_UNHALT, &vcpu->requests)) + if (vcpu->arch.mp_state == KVM_MP_STATE_HALTED) + vcpu->arch.mp_state = + KVM_MP_STATE_RUNNABLE; + up_read(&vcpu->kvm->slots_lock); + if (vcpu->arch.mp_state != KVM_MP_STATE_RUNNABLE) return -EINTR; return 1; @@ -478,10 +493,6 @@ static int (*kvm_vti_exit_handlers[])(struct kvm_vcpu *vcpu, static const int kvm_vti_max_exit_handlers = sizeof(kvm_vti_exit_handlers)/sizeof(*kvm_vti_exit_handlers); -static void kvm_prepare_guest_switch(struct kvm_vcpu *vcpu) -{ -} - static uint32_t kvm_get_exit_reason(struct kvm_vcpu *vcpu) { struct exit_ctl_data *p_exit_data; @@ -594,8 +605,6 @@ static int __vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) again: preempt_disable(); - - kvm_prepare_guest_switch(vcpu); local_irq_disable(); if (signal_pending(current)) { @@ -608,7 +617,7 @@ again: vcpu->guest_mode = 1; kvm_guest_enter(); - + down_read(&vcpu->kvm->slots_lock); r = vti_vcpu_run(vcpu, kvm_run); if (r < 0) { local_irq_enable(); @@ -628,9 +637,8 @@ again: * But we need to prevent reordering, hence this barrier(): */ barrier(); - kvm_guest_exit(); - + up_read(&vcpu->kvm->slots_lock); preempt_enable(); r = kvm_handle_exit(kvm_run, vcpu); @@ -665,15 +673,16 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) vcpu_load(vcpu); + if (vcpu->sigset_active) + sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved); + if (unlikely(vcpu->arch.mp_state == KVM_MP_STATE_UNINITIALIZED)) { kvm_vcpu_block(vcpu); - vcpu_put(vcpu); - return -EAGAIN; + clear_bit(KVM_REQ_UNHALT, &vcpu->requests); + r = -EAGAIN; + goto out; } - if (vcpu->sigset_active) - sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved); - if (vcpu->mmio_needed) { memcpy(vcpu->mmio_data, kvm_run->mmio.data, 8); kvm_set_mmio_data(vcpu); @@ -681,7 +690,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) vcpu->mmio_needed = 0; } r = __vcpu_run(vcpu, kvm_run); - +out: if (vcpu->sigset_active) sigprocmask(SIG_SETMASK, &sigsaved, NULL); @@ -771,6 +780,10 @@ static void kvm_init_vm(struct kvm *kvm) */ kvm_build_io_pmt(kvm); + INIT_LIST_HEAD(&kvm->arch.assigned_dev_head); + + /* Reserve bit 0 of irq_sources_bitmap for userspace irq source */ + set_bit(KVM_USERSPACE_IRQ_SOURCE_ID, &kvm->arch.irq_sources_bitmap); } struct kvm *kvm_arch_create_vm(void) @@ -934,9 +947,8 @@ long kvm_arch_vm_ioctl(struct file *filp, goto out; if (irqchip_in_kernel(kvm)) { mutex_lock(&kvm->lock); - kvm_ioapic_set_irq(kvm->arch.vioapic, - irq_event.irq, - irq_event.level); + kvm_set_irq(kvm, KVM_USERSPACE_IRQ_SOURCE_ID, + irq_event.irq, irq_event.level); mutex_unlock(&kvm->lock); r = 0; } @@ -1107,7 +1119,7 @@ static void kvm_migrate_hlt_timer(struct kvm_vcpu *vcpu) struct hrtimer *p_ht = &vcpu->arch.hlt_timer; if (hrtimer_cancel(p_ht)) - hrtimer_start(p_ht, p_ht->expires, HRTIMER_MODE_ABS); + hrtimer_start_expires(p_ht, HRTIMER_MODE_ABS); } static enum hrtimer_restart hlt_timer_fn(struct hrtimer *data) @@ -1116,15 +1128,16 @@ static enum hrtimer_restart hlt_timer_fn(struct hrtimer *data) wait_queue_head_t *q; vcpu = container_of(data, struct kvm_vcpu, arch.hlt_timer); + q = &vcpu->wq; + if (vcpu->arch.mp_state != KVM_MP_STATE_HALTED) goto out; - q = &vcpu->wq; - if (waitqueue_active(q)) { - vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE; + if (waitqueue_active(q)) wake_up_interruptible(q); - } + out: + vcpu->arch.timer_fired = 1; vcpu->arch.timer_check = 1; return HRTIMER_NORESTART; } @@ -1334,6 +1347,10 @@ static void kvm_release_vm_pages(struct kvm *kvm) void kvm_arch_destroy_vm(struct kvm *kvm) { + kvm_iommu_unmap_guest(kvm); +#ifdef KVM_CAP_DEVICE_ASSIGNMENT + kvm_free_all_assigned_devices(kvm); +#endif kfree(kvm->arch.vioapic); kvm_release_vm_pages(kvm); kvm_free_physmem(kvm); @@ -1435,17 +1452,24 @@ int kvm_arch_set_memory_region(struct kvm *kvm, int user_alloc) { unsigned long i; - struct page *page; + unsigned long pfn; int npages = mem->memory_size >> PAGE_SHIFT; struct kvm_memory_slot *memslot = &kvm->memslots[mem->slot]; unsigned long base_gfn = memslot->base_gfn; for (i = 0; i < npages; i++) { - page = gfn_to_page(kvm, base_gfn + i); - kvm_set_pmt_entry(kvm, base_gfn + i, - page_to_pfn(page) << PAGE_SHIFT, - _PAGE_AR_RWX|_PAGE_MA_WB); - memslot->rmap[i] = (unsigned long)page; + pfn = gfn_to_pfn(kvm, base_gfn + i); + if (!kvm_is_mmio_pfn(pfn)) { + kvm_set_pmt_entry(kvm, base_gfn + i, + pfn << PAGE_SHIFT, + _PAGE_AR_RWX | _PAGE_MA_WB); + memslot->rmap[i] = (unsigned long)pfn_to_page(pfn); + } else { + kvm_set_pmt_entry(kvm, base_gfn + i, + GPFN_PHYS_MMIO | (pfn << PAGE_SHIFT), + _PAGE_MA_UC); + memslot->rmap[i] = 0; + } } return 0; @@ -1682,12 +1706,14 @@ static void vcpu_kick_intr(void *info) void kvm_vcpu_kick(struct kvm_vcpu *vcpu) { int ipi_pcpu = vcpu->cpu; + int cpu = get_cpu(); if (waitqueue_active(&vcpu->wq)) wake_up_interruptible(&vcpu->wq); - if (vcpu->guest_mode) + if (vcpu->guest_mode && cpu != ipi_pcpu) smp_call_function_single(ipi_pcpu, vcpu_kick_intr, vcpu, 0); + put_cpu(); } int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 trig) @@ -1697,13 +1723,7 @@ int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 trig) if (!test_and_set_bit(vec, &vpd->irr[0])) { vcpu->arch.irq_new_pending = 1; - if (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE) - kvm_vcpu_kick(vcpu); - else if (vcpu->arch.mp_state == KVM_MP_STATE_HALTED) { - vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE; - if (waitqueue_active(&vcpu->wq)) - wake_up_interruptible(&vcpu->wq); - } + kvm_vcpu_kick(vcpu); return 1; } return 0; @@ -1773,7 +1793,7 @@ int kvm_cpu_has_interrupt(struct kvm_vcpu *vcpu) int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu) { - return 0; + return vcpu->arch.timer_fired; } gfn_t unalias_gfn(struct kvm *kvm, gfn_t gfn) @@ -1789,11 +1809,43 @@ int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu) int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu, struct kvm_mp_state *mp_state) { - return -EINVAL; + vcpu_load(vcpu); + mp_state->mp_state = vcpu->arch.mp_state; + vcpu_put(vcpu); + return 0; +} + +static int vcpu_reset(struct kvm_vcpu *vcpu) +{ + int r; + long psr; + local_irq_save(psr); + r = kvm_insert_vmm_mapping(vcpu); + if (r) + goto fail; + + vcpu->arch.launched = 0; + kvm_arch_vcpu_uninit(vcpu); + r = kvm_arch_vcpu_init(vcpu); + if (r) + goto fail; + + kvm_purge_vmm_mapping(vcpu); + r = 0; +fail: + local_irq_restore(psr); + return r; } int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu, struct kvm_mp_state *mp_state) { - return -EINVAL; + int r = 0; + + vcpu_load(vcpu); + vcpu->arch.mp_state = mp_state->mp_state; + if (vcpu->arch.mp_state == KVM_MP_STATE_UNINITIALIZED) + r = vcpu_reset(vcpu); + vcpu_put(vcpu); + return r; } diff --git a/arch/ia64/kvm/kvm_fw.c b/arch/ia64/kvm/kvm_fw.c index 0c69d9e..cb7600b 100644 --- a/arch/ia64/kvm/kvm_fw.c +++ b/arch/ia64/kvm/kvm_fw.c @@ -286,6 +286,12 @@ static u64 kvm_get_pal_call_index(struct kvm_vcpu *vcpu) return index; } +static void prepare_for_halt(struct kvm_vcpu *vcpu) +{ + vcpu->arch.timer_pending = 1; + vcpu->arch.timer_fired = 0; +} + int kvm_pal_emul(struct kvm_vcpu *vcpu, struct kvm_run *run) { @@ -304,11 +310,10 @@ int kvm_pal_emul(struct kvm_vcpu *vcpu, struct kvm_run *run) break; case PAL_HALT_LIGHT: { - vcpu->arch.timer_pending = 1; INIT_PAL_STATUS_SUCCESS(result); + prepare_for_halt(vcpu); if (kvm_highest_pending_irq(vcpu) == -1) ret = kvm_emulate_halt(vcpu); - } break; diff --git a/arch/ia64/kvm/kvm_minstate.h b/arch/ia64/kvm/kvm_minstate.h index 13980d9..2cc41d1 100644 --- a/arch/ia64/kvm/kvm_minstate.h +++ b/arch/ia64/kvm/kvm_minstate.h @@ -50,27 +50,18 @@ #define PAL_VSA_SYNC_READ \ /* begin to call pal vps sync_read */ \ +{.mii; \ add r25 = VMM_VPD_BASE_OFFSET, r21; \ - adds r20 = VMM_VCPU_VSA_BASE_OFFSET, r21; /* entry point */ \ + nop 0x0; \ + mov r24=ip; \ ;; \ +} \ +{.mmb \ + add r24=0x20, r24; \ ld8 r25 = [r25]; /* read vpd base */ \ - ld8 r20 = [r20]; \ - ;; \ - add r20 = PAL_VPS_SYNC_READ,r20; \ - ;; \ -{ .mii; \ - nop 0x0; \ - mov r24 = ip; \ - mov b0 = r20; \ + br.cond.sptk kvm_vps_sync_read; /*call the service*/ \ ;; \ }; \ -{ .mmb; \ - add r24 = 0x20, r24; \ - nop 0x0; \ - br.cond.sptk b0; /* call the service */ \ - ;; \ -}; - #define KVM_MINSTATE_GET_CURRENT(reg) mov reg=r21 diff --git a/arch/ia64/kvm/optvfault.S b/arch/ia64/kvm/optvfault.S index e4f15d6..32254ce 100644 --- a/arch/ia64/kvm/optvfault.S +++ b/arch/ia64/kvm/optvfault.S @@ -1,9 +1,12 @@ /* - * arch/ia64/vmx/optvfault.S + * arch/ia64/kvm/optvfault.S * optimize virtualization fault handler * * Copyright (C) 2006 Intel Co * Xuefei Xu (Anthony Xu) <anthony.xu@intel.com> + * Copyright (C) 2008 Intel Co + * Add the support for Tukwila processors. + * Xiantao Zhang <xiantao.zhang@intel.com> */ #include <asm/asmmacro.h> @@ -20,6 +23,98 @@ #define ACCE_MOV_TO_PSR #define ACCE_THASH +#define VMX_VPS_SYNC_READ \ + add r16=VMM_VPD_BASE_OFFSET,r21; \ + mov r17 = b0; \ + mov r18 = r24; \ + mov r19 = r25; \ + mov r20 = r31; \ + ;; \ +{.mii; \ + ld8 r16 = [r16]; \ + nop 0x0; \ + mov r24 = ip; \ + ;; \ +}; \ +{.mmb; \ + add r24=0x20, r24; \ + mov r25 =r16; \ + br.sptk.many kvm_vps_sync_read; \ +}; \ + mov b0 = r17; \ + mov r24 = r18; \ + mov r25 = r19; \ + mov r31 = r20 + +ENTRY(kvm_vps_entry) + adds r29 = VMM_VCPU_VSA_BASE_OFFSET,r21 + ;; + ld8 r29 = [r29] + ;; + add r29 = r29, r30 + ;; + mov b0 = r29 + br.sptk.many b0 +END(kvm_vps_entry) + +/* + * Inputs: + * r24 : return address + * r25 : vpd + * r29 : scratch + * + */ +GLOBAL_ENTRY(kvm_vps_sync_read) + movl r30 = PAL_VPS_SYNC_READ + ;; + br.sptk.many kvm_vps_entry +END(kvm_vps_sync_read) + +/* + * Inputs: + * r24 : return address + * r25 : vpd + * r29 : scratch + * + */ +GLOBAL_ENTRY(kvm_vps_sync_write) + movl r30 = PAL_VPS_SYNC_WRITE + ;; + br.sptk.many kvm_vps_entry +END(kvm_vps_sync_write) + +/* + * Inputs: + * r23 : pr + * r24 : guest b0 + * r25 : vpd + * + */ +GLOBAL_ENTRY(kvm_vps_resume_normal) + movl r30 = PAL_VPS_RESUME_NORMAL + ;; + mov pr=r23,-2 + br.sptk.many kvm_vps_entry +END(kvm_vps_resume_normal) + +/* + * Inputs: + * r23 : pr + * r24 : guest b0 + * r25 : vpd + * r17 : isr + */ +GLOBAL_ENTRY(kvm_vps_resume_handler) + movl r30 = PAL_VPS_RESUME_HANDLER + ;; + ld8 r26=[r25] + shr r17=r17,IA64_ISR_IR_BIT + ;; + dep r26=r17,r26,63,1 // bit 63 of r26 indicate whether enable CFLE + mov pr=r23,-2 + br.sptk.many kvm_vps_entry +END(kvm_vps_resume_handler) + //mov r1=ar3 GLOBAL_ENTRY(kvm_asm_mov_from_ar) #ifndef ACCE_MOV_FROM_AR @@ -157,11 +252,11 @@ GLOBAL_ENTRY(kvm_asm_rsm) #ifndef ACCE_RSM br.many kvm_virtualization_fault_back #endif - add r16=VMM_VPD_BASE_OFFSET,r21 + VMX_VPS_SYNC_READ + ;; extr.u r26=r25,6,21 extr.u r27=r25,31,2 ;; - ld8 r16=[r16] extr.u r28=r25,36,1 dep r26=r27,r26,21,2 ;; @@ -196,7 +291,7 @@ GLOBAL_ENTRY(kvm_asm_rsm) tbit.nz p6,p0=r23,0 ;; tbit.z.or p6,p0=r26,IA64_PSR_DT_BIT - (p6) br.dptk kvm_resume_to_guest + (p6) br.dptk kvm_resume_to_guest_with_sync ;; add r26=VMM_VCPU_META_RR0_OFFSET,r21 add r27=VMM_VCPU_META_RR0_OFFSET+8,r21 @@ -212,7 +307,7 @@ GLOBAL_ENTRY(kvm_asm_rsm) mov rr[r28]=r27 ;; srlz.d - br.many kvm_resume_to_guest + br.many kvm_resume_to_guest_with_sync END(kvm_asm_rsm) @@ -221,11 +316,11 @@ GLOBAL_ENTRY(kvm_asm_ssm) #ifndef ACCE_SSM br.many kvm_virtualization_fault_back #endif - add r16=VMM_VPD_BASE_OFFSET,r21 + VMX_VPS_SYNC_READ + ;; extr.u r26=r25,6,21 extr.u r27=r25,31,2 ;; - ld8 r16=[r16] extr.u r28=r25,36,1 dep r26=r27,r26,21,2 ;; //r26 is imm24 @@ -271,7 +366,7 @@ kvm_asm_ssm_1: tbit.nz p6,p0=r29,IA64_PSR_I_BIT ;; tbit.z.or p6,p0=r19,IA64_PSR_I_BIT - (p6) br.dptk kvm_resume_to_guest + (p6) br.dptk kvm_resume_to_guest_with_sync ;; add r29=VPD_VTPR_START_OFFSET,r16 add r30=VPD_VHPI_START_OFFSET,r16 @@ -286,7 +381,7 @@ kvm_asm_ssm_1: ;; cmp.gt p6,p0=r30,r17 (p6) br.dpnt.few kvm_asm_dispatch_vexirq - br.many kvm_resume_to_guest + br.many kvm_resume_to_guest_with_sync END(kvm_asm_ssm) @@ -295,10 +390,9 @@ GLOBAL_ENTRY(kvm_asm_mov_to_psr) #ifndef ACCE_MOV_TO_PSR br.many kvm_virtualization_fault_back #endif - add r16=VMM_VPD_BASE_OFFSET,r21 - extr.u r26=r25,13,7 //r2 + VMX_VPS_SYNC_READ ;; - ld8 r16=[r16] + extr.u r26=r25,13,7 //r2 addl r20=@gprel(asm_mov_from_reg),gp ;; adds r30=kvm_asm_mov_to_psr_back-asm_mov_from_reg,r20 @@ -374,7 +468,7 @@ kvm_asm_mov_to_psr_1: ;; tbit.nz.or p6,p0=r17,IA64_PSR_I_BIT tbit.z.or p6,p0=r30,IA64_PSR_I_BIT - (p6) br.dpnt.few kvm_resume_to_guest + (p6) br.dpnt.few kvm_resume_to_guest_with_sync ;; add r29=VPD_VTPR_START_OFFSET,r16 add r30=VPD_VHPI_START_OFFSET,r16 @@ -389,13 +483,29 @@ kvm_asm_mov_to_psr_1: ;; cmp.gt p6,p0=r30,r17 (p6) br.dpnt.few kvm_asm_dispatch_vexirq - br.many kvm_resume_to_guest + br.many kvm_resume_to_guest_with_sync END(kvm_asm_mov_to_psr) ENTRY(kvm_asm_dispatch_vexirq) //increment iip + mov r17 = b0 + mov r18 = r31 +{.mii + add r25=VMM_VPD_BASE_OFFSET,r21 + nop 0x0 + mov r24 = ip + ;; +} +{.mmb + add r24 = 0x20, r24 + ld8 r25 = [r25] + br.sptk.many kvm_vps_sync_write +} + mov b0 =r17 mov r16=cr.ipsr + mov r31 = r18 + mov r19 = 37 ;; extr.u r17=r16,IA64_PSR_RI_BIT,2 tbit.nz p6,p7=r16,IA64_PSR_RI_BIT+1 @@ -435,25 +545,31 @@ GLOBAL_ENTRY(kvm_asm_thash) ;; kvm_asm_thash_back1: shr.u r23=r19,61 // get RR number - adds r25=VMM_VCPU_VRR0_OFFSET,r21 // get vcpu->arch.vrr[0]'s addr + adds r28=VMM_VCPU_VRR0_OFFSET,r21 // get vcpu->arch.vrr[0]'s addr adds r16=VMM_VPD_VPTA_OFFSET,r16 // get vpta ;; - shladd r27=r23,3,r25 // get vcpu->arch.vrr[r23]'s addr + shladd r27=r23,3,r28 // get vcpu->arch.vrr[r23]'s addr ld8 r17=[r16] // get PTA mov r26=1 ;; - extr.u r29=r17,2,6 // get pta.size - ld8 r25=[r27] // get vcpu->arch.vrr[r23]'s value + extr.u r29=r17,2,6 // get pta.size + ld8 r28=[r27] // get vcpu->arch.vrr[r23]'s value ;; - extr.u r25=r25,2,6 // get rr.ps + mov b0=r24 + //Fallback to C if pta.vf is set + tbit.nz p6,p0=r17, 8 + ;; + (p6) mov r24=EVENT_THASH + (p6) br.cond.dpnt.many kvm_virtualization_fault_back + extr.u r28=r28,2,6 // get rr.ps shl r22=r26,r29 // 1UL << pta.size ;; - shr.u r23=r19,r25 // vaddr >> rr.ps + shr.u r23=r19,r28 // vaddr >> rr.ps adds r26=3,r29 // pta.size + 3 shl r27=r17,3 // pta << 3 ;; shl r23=r23,3 // (vaddr >> rr.ps) << 3 - shr.u r27=r27,r26 // (pta << 3) >> (pta.size+3) + shr.u r27=r27,r26 // (pta << 3) >> (pta.size+3) movl r16=7<<61 ;; adds r22=-1,r22 // (1UL << pta.size) - 1 @@ -724,6 +840,29 @@ END(asm_mov_from_reg) * r31: pr * r24: b0 */ +ENTRY(kvm_resume_to_guest_with_sync) + adds r19=VMM_VPD_BASE_OFFSET,r21 + mov r16 = r31 + mov r17 = r24 + ;; +{.mii + ld8 r25 =[r19] + nop 0x0 + mov r24 = ip + ;; +} +{.mmb + add r24 =0x20, r24 + nop 0x0 + br.sptk.many kvm_vps_sync_write +} + + mov r31 = r16 + mov r24 =r17 + ;; + br.sptk.many kvm_resume_to_guest +END(kvm_resume_to_guest_with_sync) + ENTRY(kvm_resume_to_guest) adds r16 = VMM_VCPU_SAVED_GP_OFFSET,r21 ;; @@ -755,12 +894,15 @@ ENTRY(kvm_resume_to_guest) ;; ld8 r19=[r19] mov b0=r29 - cmp.ne p6,p7 = r0,r0 + mov r27=cr.isr ;; - tbit.z p6,p7 = r19,IA64_PSR_IC_BIT // p1=vpsr.ic + tbit.z p6,p7 = r19,IA64_PSR_IC_BIT // p7=vpsr.ic + shr r27=r27,IA64_ISR_IR_BIT ;; (p6) ld8 r26=[r25] (p7) mov b0=r28 + ;; + (p6) dep r26=r27,r26,63,1 mov pr=r31,-2 br.sptk.many b0 // call pal service ;; diff --git a/arch/ia64/kvm/process.c b/arch/ia64/kvm/process.c index 5a33f7e..8008173 100644 --- a/arch/ia64/kvm/process.c +++ b/arch/ia64/kvm/process.c @@ -713,7 +713,7 @@ void leave_hypervisor_tail(void) if (!(VCPU(v, itv) & (1 << 16))) { vcpu_pend_interrupt(v, VCPU(v, itv) & 0xff); - VMX(v, itc_check) = 0; + VMX(v, itc_check) = 0; } else { v->arch.timer_pending = 1; } @@ -962,9 +962,9 @@ static void kvm_do_resume_op(struct kvm_vcpu *vcpu) void vmm_transition(struct kvm_vcpu *vcpu) { ia64_call_vsa(PAL_VPS_SAVE, (unsigned long)vcpu->arch.vpd, - 0, 0, 0, 0, 0, 0); + 1, 0, 0, 0, 0, 0); vmm_trampoline(&vcpu->arch.guest, &vcpu->arch.host); ia64_call_vsa(PAL_VPS_RESTORE, (unsigned long)vcpu->arch.vpd, - 0, 0, 0, 0, 0, 0); + 1, 0, 0, 0, 0, 0); kvm_do_resume_op(vcpu); } diff --git a/arch/ia64/kvm/vcpu.h b/arch/ia64/kvm/vcpu.h index b0fcfb6..e9b2a4e 100644 --- a/arch/ia64/kvm/vcpu.h +++ b/arch/ia64/kvm/vcpu.h @@ -313,21 +313,21 @@ static inline void vcpu_set_tr(struct thash_data *trp, u64 pte, u64 itir, trp->rid = rid; } -extern u64 kvm_lookup_mpa(u64 gpfn); -extern u64 kvm_gpa_to_mpa(u64 gpa); - -/* Return I/O type if trye */ -#define __gpfn_is_io(gpfn) \ - ({ \ - u64 pte, ret = 0; \ - pte = kvm_lookup_mpa(gpfn); \ - if (!(pte & GPFN_INV_MASK)) \ - ret = pte & GPFN_IO_MASK; \ - ret; \ - }) +extern u64 kvm_get_mpt_entry(u64 gpfn); +/* Return I/ */ +static inline u64 __gpfn_is_io(u64 gpfn) +{ + u64 pte; + pte = kvm_get_mpt_entry(gpfn); + if (!(pte & GPFN_INV_MASK)) { + pte = pte & GPFN_IO_MASK; + if (pte != GPFN_PHYS_MMIO) + return pte; + } + return 0; +} #endif - #define IA64_NO_FAULT 0 #define IA64_FAULT 1 @@ -384,6 +384,10 @@ extern u64 kvm_gpa_to_mpa(u64 gpa); #define MODE_IND(psr) \ (((psr).it << 2) + ((psr).dt << 1) + (psr).rt) +#ifndef CONFIG_SMP +#define _vmm_raw_spin_lock(x) do {}while(0) +#define _vmm_raw_spin_unlock(x) do {}while(0) +#else #define _vmm_raw_spin_lock(x) \ do { \ __u32 *ia64_spinlock_ptr = (__u32 *) (x); \ @@ -403,6 +407,7 @@ extern u64 kvm_gpa_to_mpa(u64 gpa); do { barrier(); \ ((spinlock_t *)x)->raw_lock.lock = 0; } \ while (0) +#endif void vmm_spin_lock(spinlock_t *lock); void vmm_spin_unlock(spinlock_t *lock); diff --git a/arch/ia64/kvm/vmm_ivt.S b/arch/ia64/kvm/vmm_ivt.S index 3ee5f48..c1d7251 100644 --- a/arch/ia64/kvm/vmm_ivt.S +++ b/arch/ia64/kvm/vmm_ivt.S @@ -1261,11 +1261,6 @@ kvm_rse_clear_invalid: adds r19=VMM_VPD_VPSR_OFFSET,r18 ;; ld8 r19=[r19] //vpsr - adds r20=VMM_VCPU_VSA_BASE_OFFSET,r21 - ;; - ld8 r20=[r20] - ;; -//vsa_sync_write_start mov r25=r18 adds r16= VMM_VCPU_GP_OFFSET,r21 ;; @@ -1274,10 +1269,7 @@ kvm_rse_clear_invalid: ;; add r24=r24,r16 ;; - add r16=PAL_VPS_SYNC_WRITE,r20 - ;; - mov b0=r16 - br.cond.sptk b0 // call the service + br.sptk.many kvm_vps_sync_write // call the service ;; END(ia64_leave_hypervisor) // fall through @@ -1288,28 +1280,15 @@ GLOBAL_ENTRY(ia64_vmm_entry) * r17:cr.isr * r18:vpd * r19:vpsr - * r20:__vsa_base * r22:b0 * r23:predicate */ mov r24=r22 mov r25=r18 tbit.nz p1,p2 = r19,IA64_PSR_IC_BIT // p1=vpsr.ic + (p1) br.cond.sptk.few kvm_vps_resume_normal + (p2) br.cond.sptk.many kvm_vps_resume_handler ;; - (p1) add r29=PAL_VPS_RESUME_NORMAL,r20 - (p1) br.sptk.many ia64_vmm_entry_out - ;; - tbit.nz p1,p2 = r17,IA64_ISR_IR_BIT //p1=cr.isr.ir - ;; - (p1) add r29=PAL_VPS_RESUME_NORMAL,r20 - (p2) add r29=PAL_VPS_RESUME_HANDLER,r20 - (p2) ld8 r26=[r25] - ;; -ia64_vmm_entry_out: - mov pr=r23,-2 - mov b0=r29 - ;; - br.cond.sptk b0 // call pal service END(ia64_vmm_entry) @@ -1376,6 +1355,9 @@ GLOBAL_ENTRY(vmm_reset_entry) //set up ipsr, iip, vpd.vpsr, dcr // For IPSR: it/dt/rt=1, i/ic=1, si=1, vm/bn=1 // For DCR: all bits 0 + bsw.0 + ;; + mov r21 =r13 adds r14=-VMM_PT_REGS_SIZE, r12 ;; movl r6=0x501008826000 // IPSR dt/rt/it:1;i/ic:1, si:1, vm/bn:1 @@ -1387,12 +1369,6 @@ GLOBAL_ENTRY(vmm_reset_entry) ;; srlz.i ;; - bsw.0 - ;; - mov r21 =r13 - ;; - bsw.1 - ;; mov ar.rsc = 0 ;; flushrs @@ -1406,12 +1382,9 @@ GLOBAL_ENTRY(vmm_reset_entry) ld8 r1 = [r20] ;; mov cr.iip=r4 - ;; adds r16=VMM_VPD_BASE_OFFSET,r13 - adds r20=VMM_VCPU_VSA_BASE_OFFSET,r13 ;; ld8 r18=[r16] - ld8 r20=[r20] ;; adds r19=VMM_VPD_VPSR_OFFSET,r18 ;; diff --git a/arch/ia64/kvm/vtlb.c b/arch/ia64/kvm/vtlb.c index def4576..e22b933 100644 --- a/arch/ia64/kvm/vtlb.c +++ b/arch/ia64/kvm/vtlb.c @@ -390,7 +390,7 @@ void thash_purge_entries_remote(struct kvm_vcpu *v, u64 va, u64 ps) u64 translate_phy_pte(u64 *pte, u64 itir, u64 va) { - u64 ps, ps_mask, paddr, maddr; + u64 ps, ps_mask, paddr, maddr, io_mask; union pte_flags phy_pte; ps = itir_ps(itir); @@ -398,8 +398,9 @@ u64 translate_phy_pte(u64 *pte, u64 itir, u64 va) phy_pte.val = *pte; paddr = *pte; paddr = ((paddr & _PAGE_PPN_MASK) & ps_mask) | (va & ~ps_mask); - maddr = kvm_lookup_mpa(paddr >> PAGE_SHIFT); - if (maddr & GPFN_IO_MASK) { + maddr = kvm_get_mpt_entry(paddr >> PAGE_SHIFT); + io_mask = maddr & GPFN_IO_MASK; + if (io_mask && (io_mask != GPFN_PHYS_MMIO)) { *pte |= VTLB_PTE_IO; return -1; } @@ -418,7 +419,7 @@ int thash_purge_and_insert(struct kvm_vcpu *v, u64 pte, u64 itir, u64 ifa, int type) { u64 ps; - u64 phy_pte; + u64 phy_pte, io_mask, index; union ia64_rr vrr, mrr; int ret = 0; @@ -426,13 +427,16 @@ int thash_purge_and_insert(struct kvm_vcpu *v, u64 pte, u64 itir, vrr.val = vcpu_get_rr(v, ifa); mrr.val = ia64_get_rr(ifa); + index = (pte & _PAGE_PPN_MASK) >> PAGE_SHIFT; + io_mask = kvm_get_mpt_entry(index) & GPFN_IO_MASK; phy_pte = translate_phy_pte(&pte, itir, ifa); /* Ensure WB attribute if pte is related to a normal mem page, * which is required by vga acceleration since qemu maps shared * vram buffer with WB. */ - if (!(pte & VTLB_PTE_IO) && ((pte & _PAGE_MA_MASK) != _PAGE_MA_NAT)) { + if (!(pte & VTLB_PTE_IO) && ((pte & _PAGE_MA_MASK) != _PAGE_MA_NAT) && + io_mask != GPFN_PHYS_MMIO) { pte &= ~_PAGE_MA_MASK; phy_pte &= ~_PAGE_MA_MASK; } @@ -566,12 +570,19 @@ void thash_init(struct thash_cb *hcb, u64 sz) } } -u64 kvm_lookup_mpa(u64 gpfn) +u64 kvm_get_mpt_entry(u64 gpfn) { u64 *base = (u64 *) KVM_P2M_BASE; return *(base + gpfn); } +u64 kvm_lookup_mpa(u64 gpfn) +{ + u64 maddr; + maddr = kvm_get_mpt_entry(gpfn); + return maddr&_PAGE_PPN_MASK; +} + u64 kvm_gpa_to_mpa(u64 gpa) { u64 pte = kvm_lookup_mpa(gpa >> PAGE_SHIFT); diff --git a/arch/ia64/lib/flush.S b/arch/ia64/lib/flush.S index 2a0d27f..1d8c888 100644 --- a/arch/ia64/lib/flush.S +++ b/arch/ia64/lib/flush.S @@ -60,3 +60,58 @@ GLOBAL_ENTRY(flush_icache_range) mov ar.lc=r3 // restore ar.lc br.ret.sptk.many rp END(flush_icache_range) + + /* + * clflush_cache_range(start,size) + * + * Flush cache lines from start to start+size-1. + * + * Must deal with range from start to start+size-1 but nothing else + * (need to be careful not to touch addresses that may be + * unmapped). + * + * Note: "in0" and "in1" are preserved for debugging purposes. + */ + .section .kprobes.text,"ax" +GLOBAL_ENTRY(clflush_cache_range) + + .prologue + alloc r2=ar.pfs,2,0,0,0 + movl r3=ia64_cache_stride_shift + mov r21=1 + add r22=in1,in0 + ;; + ld8 r20=[r3] // r20: stride shift + sub r22=r22,r0,1 // last byte address + ;; + shr.u r23=in0,r20 // start / (stride size) + shr.u r22=r22,r20 // (last byte address) / (stride size) + shl r21=r21,r20 // r21: stride size of the i-cache(s) + ;; + sub r8=r22,r23 // number of strides - 1 + shl r24=r23,r20 // r24: addresses for "fc" = + // "start" rounded down to stride + // boundary + .save ar.lc,r3 + mov r3=ar.lc // save ar.lc + ;; + + .body + mov ar.lc=r8 + ;; + /* + * 32 byte aligned loop, even number of (actually 2) bundles + */ +.Loop_fc: + fc r24 // issuable on M0 only + add r24=r21,r24 // we flush "stride size" bytes per iteration + nop.i 0 + br.cloop.sptk.few .Loop_fc + ;; + sync.i + ;; + srlz.i + ;; + mov ar.lc=r3 // restore ar.lc + br.ret.sptk.many rp +END(clflush_cache_range) diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c index d8c5fcd..d85ba98 100644 --- a/arch/ia64/mm/discontig.c +++ b/arch/ia64/mm/discontig.c @@ -635,7 +635,6 @@ static __init int count_node_pages(unsigned long start, unsigned long len, int n (min(end, __pa(MAX_DMA_ADDRESS)) - start) >>PAGE_SHIFT; #endif start = GRANULEROUNDDOWN(start); - start = ORDERROUNDDOWN(start); end = GRANULEROUNDUP(end); mem_data[node].max_pfn = max(mem_data[node].max_pfn, end >> PAGE_SHIFT); diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c index f482a90..054bcd9 100644 --- a/arch/ia64/mm/init.c +++ b/arch/ia64/mm/init.c @@ -700,23 +700,6 @@ int arch_add_memory(int nid, u64 start, u64 size) return ret; } -#ifdef CONFIG_MEMORY_HOTREMOVE -int remove_memory(u64 start, u64 size) -{ - unsigned long start_pfn, end_pfn; - unsigned long timeout = 120 * HZ; - int ret; - start_pfn = start >> PAGE_SHIFT; - end_pfn = start_pfn + (size >> PAGE_SHIFT); - ret = offline_pages(start_pfn, end_pfn, timeout); - if (ret) - goto out; - /* we can free mem_map at this point */ -out: - return ret; -} -EXPORT_SYMBOL_GPL(remove_memory); -#endif /* CONFIG_MEMORY_HOTREMOVE */ #endif /* diff --git a/arch/ia64/mm/tlb.c b/arch/ia64/mm/tlb.c index 8caf424..bd9818a 100644 --- a/arch/ia64/mm/tlb.c +++ b/arch/ia64/mm/tlb.c @@ -362,9 +362,13 @@ ia64_tlb_init (void) per_cpu(ia64_tr_num, cpu) = vm_info_1.pal_vm_info_1_s.max_dtr_entry+1; if (per_cpu(ia64_tr_num, cpu) > IA64_TR_ALLOC_MAX) { + static int justonce = 1; per_cpu(ia64_tr_num, cpu) = IA64_TR_ALLOC_MAX; - printk(KERN_DEBUG "TR register number exceeds IA64_TR_ALLOC_MAX!" - "IA64_TR_ALLOC_MAX should be extended\n"); + if (justonce) { + justonce = 0; + printk(KERN_DEBUG "TR register number exceeds " + "IA64_TR_ALLOC_MAX!\n"); + } } } diff --git a/arch/ia64/oprofile/init.c b/arch/ia64/oprofile/init.c index 125a602..31b545c 100644 --- a/arch/ia64/oprofile/init.c +++ b/arch/ia64/oprofile/init.c @@ -12,11 +12,11 @@ #include <linux/init.h> #include <linux/errno.h> -extern int perfmon_init(struct oprofile_operations * ops); +extern int perfmon_init(struct oprofile_operations *ops); extern void perfmon_exit(void); extern void ia64_backtrace(struct pt_regs * const regs, unsigned int depth); -int __init oprofile_arch_init(struct oprofile_operations * ops) +int __init oprofile_arch_init(struct oprofile_operations *ops) { int ret = -ENODEV; diff --git a/arch/ia64/oprofile/perfmon.c b/arch/ia64/oprofile/perfmon.c index bc41dd3..192d3e8 100644 --- a/arch/ia64/oprofile/perfmon.c +++ b/arch/ia64/oprofile/perfmon.c @@ -56,7 +56,7 @@ static pfm_buffer_fmt_t oprofile_fmt = { }; -static char * get_cpu_type(void) +static char *get_cpu_type(void) { __u8 family = local_cpu_data->family; @@ -75,7 +75,7 @@ static char * get_cpu_type(void) static int using_perfmon; -int perfmon_init(struct oprofile_operations * ops) +int perfmon_init(struct oprofile_operations *ops) { int ret = pfm_register_buffer_fmt(&oprofile_fmt); if (ret) diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index 7545037..211fcfd 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c @@ -614,12 +614,17 @@ char *ia64_pci_get_legacy_mem(struct pci_bus *bus) * vector to get the base address. */ int -pci_mmap_legacy_page_range(struct pci_bus *bus, struct vm_area_struct *vma) +pci_mmap_legacy_page_range(struct pci_bus *bus, struct vm_area_struct *vma, + enum pci_mmap_state mmap_state) { unsigned long size = vma->vm_end - vma->vm_start; pgprot_t prot; char *addr; + /* We only support mmap'ing of legacy memory space */ + if (mmap_state != pci_mmap_mem) + return -ENOSYS; + /* * Avoid attribute aliasing. See Documentation/ia64/aliasing.txt * for more details. diff --git a/arch/ia64/scripts/pvcheck.sed b/arch/ia64/scripts/pvcheck.sed new file mode 100644 index 0000000..ba66ac2 --- /dev/null +++ b/arch/ia64/scripts/pvcheck.sed @@ -0,0 +1,32 @@ +# +# Checker for paravirtualizations of privileged operations. +# +s/ssm.*psr\.ic.*/.warning \"ssm psr.ic should not be used directly\"/g +s/rsm.*psr\.ic.*/.warning \"rsm psr.ic should not be used directly\"/g +s/ssm.*psr\.i.*/.warning \"ssm psr.i should not be used directly\"/g +s/rsm.*psr\.i.*/.warning \"rsm psr.i should not be used directly\"/g +s/ssm.*psr\.dt.*/.warning \"ssm psr.dt should not be used directly\"/g +s/rsm.*psr\.dt.*/.warning \"rsm psr.dt should not be used directly\"/g +s/mov.*=.*cr\.ifa/.warning \"cr.ifa should not used directly\"/g +s/mov.*=.*cr\.itir/.warning \"cr.itir should not used directly\"/g +s/mov.*=.*cr\.isr/.warning \"cr.isr should not used directly\"/g +s/mov.*=.*cr\.iha/.warning \"cr.iha should not used directly\"/g +s/mov.*=.*cr\.ipsr/.warning \"cr.ipsr should not used directly\"/g +s/mov.*=.*cr\.iim/.warning \"cr.iim should not used directly\"/g +s/mov.*=.*cr\.iip/.warning \"cr.iip should not used directly\"/g +s/mov.*=.*cr\.ivr/.warning \"cr.ivr should not used directly\"/g +s/mov.*=[^\.]*psr/.warning \"psr should not used directly\"/g # avoid ar.fpsr +s/mov.*=.*ar\.eflags/.warning \"ar.eflags should not used directly\"/g +s/mov.*cr\.ifa.*=.*/.warning \"cr.ifa should not used directly\"/g +s/mov.*cr\.itir.*=.*/.warning \"cr.itir should not used directly\"/g +s/mov.*cr\.iha.*=.*/.warning \"cr.iha should not used directly\"/g +s/mov.*cr\.ipsr.*=.*/.warning \"cr.ipsr should not used directly\"/g +s/mov.*cr\.ifs.*=.*/.warning \"cr.ifs should not used directly\"/g +s/mov.*cr\.iip.*=.*/.warning \"cr.iip should not used directly\"/g +s/mov.*cr\.kr.*=.*/.warning \"cr.kr should not used directly\"/g +s/mov.*ar\.eflags.*=.*/.warning \"ar.eflags should not used directly\"/g +s/itc\.i.*/.warning \"itc.i should not be used directly.\"/g +s/itc\.d.*/.warning \"itc.d should not be used directly.\"/g +s/bsw\.0/.warning \"bsw.0 should not be used directly.\"/g +s/bsw\.1/.warning \"bsw.1 should not be used directly.\"/g +s/ptc\.ga.*/.warning \"ptc.ga should not be used directly.\"/g diff --git a/arch/ia64/sn/kernel/io_acpi_init.c b/arch/ia64/sn/kernel/io_acpi_init.c index 6568942..bc610a6 100644 --- a/arch/ia64/sn/kernel/io_acpi_init.c +++ b/arch/ia64/sn/kernel/io_acpi_init.c @@ -232,7 +232,7 @@ exit: static unsigned int get_host_devfn(acpi_handle device_handle, acpi_handle rootbus_handle) { - unsigned long adr; + unsigned long long adr; acpi_handle child; unsigned int devfn; int function; @@ -292,8 +292,8 @@ get_host_devfn(acpi_handle device_handle, acpi_handle rootbus_handle) static acpi_status find_matching_device(acpi_handle handle, u32 lvl, void *context, void **rv) { - unsigned long bbn = -1; - unsigned long adr; + unsigned long long bbn = -1; + unsigned long long adr; acpi_handle parent = NULL; acpi_status status; unsigned int devfn; @@ -348,7 +348,7 @@ sn_acpi_get_pcidev_info(struct pci_dev *dev, struct pcidev_info **pcidev_info, unsigned int host_devfn; struct sn_pcidev_match pcidev_match; acpi_handle rootbus_handle; - unsigned long segment; + unsigned long long segment; acpi_status status; rootbus_handle = PCI_CONTROLLER(dev)->acpi_handle; @@ -357,7 +357,7 @@ sn_acpi_get_pcidev_info(struct pci_dev *dev, struct pcidev_info **pcidev_info, if (ACPI_SUCCESS(status)) { if (segment != pci_domain_nr(dev)) { printk(KERN_ERR - "%s: Segment number mismatch, 0x%lx vs 0x%x for: ", + "%s: Segment number mismatch, 0x%llx vs 0x%x for: ", __func__, segment, pci_domain_nr(dev)); acpi_ns_print_node_pathname(rootbus_handle, NULL); printk("\n"); diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c index c3aa851..4e1801b 100644 --- a/arch/ia64/sn/kernel/io_init.c +++ b/arch/ia64/sn/kernel/io_init.c @@ -292,7 +292,7 @@ EXPORT_SYMBOL(sn_io_slot_fixup); * sn_pci_controller_fixup() - This routine sets up a bus's resources * consistent with the Linux PCI abstraction layer. */ -static void +static void __init sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus) { s64 status = 0; diff --git a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c index 96c31b4..0c66dbd 100644 --- a/arch/ia64/sn/kernel/irq.c +++ b/arch/ia64/sn/kernel/irq.c @@ -5,7 +5,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (c) 2000-2007 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2008 Silicon Graphics, Inc. All Rights Reserved. */ #include <linux/irq.h> @@ -375,6 +375,7 @@ void sn_irq_fixup(struct pci_dev *pci_dev, struct sn_irq_info *sn_irq_info) int cpu = nasid_slice_to_cpuid(nasid, slice); #ifdef CONFIG_SMP int cpuphys; + irq_desc_t *desc; #endif pci_dev_get(pci_dev); @@ -391,6 +392,12 @@ void sn_irq_fixup(struct pci_dev *pci_dev, struct sn_irq_info *sn_irq_info) #ifdef CONFIG_SMP cpuphys = cpu_physical_id(cpu); set_irq_affinity_info(sn_irq_info->irq_irq, cpuphys, 0); + desc = irq_to_desc(sn_irq_info->irq_irq); + /* + * Affinity was set by the PROM, prevent it from + * being reset by the request_irq() path. + */ + desc->status |= IRQ_AFFINITY_SET; #endif } diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c index bb1d249..02c5b8a 100644 --- a/arch/ia64/sn/kernel/setup.c +++ b/arch/ia64/sn/kernel/setup.c @@ -200,7 +200,7 @@ static int __cpuinitdata shub_1_1_found; * Set flag for enabling shub specific wars */ -static inline int __init is_shub_1_1(int nasid) +static inline int __cpuinit is_shub_1_1(int nasid) { unsigned long id; int rev; @@ -212,7 +212,7 @@ static inline int __init is_shub_1_1(int nasid) return rev <= 2; } -static void __init sn_check_for_wars(void) +static void __cpuinit sn_check_for_wars(void) { int cnode; @@ -512,7 +512,6 @@ static void __init sn_init_pdas(char **cmdline_p) for_each_online_node(cnode) { nodepdaindr[cnode] = alloc_bootmem_node(NODE_DATA(cnode), sizeof(nodepda_t)); - memset(nodepdaindr[cnode], 0, sizeof(nodepda_t)); memset(nodepdaindr[cnode]->phys_cpuid, -1, sizeof(nodepdaindr[cnode]->phys_cpuid)); spin_lock_init(&nodepdaindr[cnode]->ptc_lock); @@ -521,11 +520,9 @@ static void __init sn_init_pdas(char **cmdline_p) /* * Allocate & initialize nodepda for TIOs. For now, put them on node 0. */ - for (cnode = num_online_nodes(); cnode < num_cnodes; cnode++) { + for (cnode = num_online_nodes(); cnode < num_cnodes; cnode++) nodepdaindr[cnode] = alloc_bootmem_node(NODE_DATA(0), sizeof(nodepda_t)); - memset(nodepdaindr[cnode], 0, sizeof(nodepda_t)); - } /* * Now copy the array of nodepda pointers to each nodepda. diff --git a/arch/ia64/uv/kernel/setup.c b/arch/ia64/uv/kernel/setup.c index cf5f28a..7a5ae63 100644 --- a/arch/ia64/uv/kernel/setup.c +++ b/arch/ia64/uv/kernel/setup.c @@ -19,6 +19,12 @@ EXPORT_PER_CPU_SYMBOL_GPL(__uv_hub_info); #ifdef CONFIG_IA64_SGI_UV int sn_prom_type; +long sn_partition_id; +EXPORT_SYMBOL(sn_partition_id); +long sn_coherency_id; +EXPORT_SYMBOL_GPL(sn_coherency_id); +long sn_region_size; +EXPORT_SYMBOL(sn_region_size); #endif struct redir_addr { diff --git a/arch/ia64/xen/Kconfig b/arch/ia64/xen/Kconfig new file mode 100644 index 0000000..f1683a2 --- /dev/null +++ b/arch/ia64/xen/Kconfig @@ -0,0 +1,26 @@ +# +# This Kconfig describes xen/ia64 options +# + +config XEN + bool "Xen hypervisor support" + default y + depends on PARAVIRT && MCKINLEY && IA64_PAGE_SIZE_16KB && EXPERIMENTAL + select XEN_XENCOMM + select NO_IDLE_HZ + + # those are required to save/restore. + select ARCH_SUSPEND_POSSIBLE + select SUSPEND + select PM_SLEEP + help + Enable Xen hypervisor support. Resulting kernel runs + both as a guest OS on Xen and natively on hardware. + +config XEN_XENCOMM + depends on XEN + bool + +config NO_IDLE_HZ + depends on XEN + bool diff --git a/arch/ia64/xen/Makefile b/arch/ia64/xen/Makefile new file mode 100644 index 0000000..0ad0224 --- /dev/null +++ b/arch/ia64/xen/Makefile @@ -0,0 +1,22 @@ +# +# Makefile for Xen components +# + +obj-y := hypercall.o xenivt.o xensetup.o xen_pv_ops.o irq_xen.o \ + hypervisor.o xencomm.o xcom_hcall.o grant-table.o time.o suspend.o + +obj-$(CONFIG_IA64_GENERIC) += machvec.o + +AFLAGS_xenivt.o += -D__IA64_ASM_PARAVIRTUALIZED_XEN + +# xen multi compile +ASM_PARAVIRT_MULTI_COMPILE_SRCS = ivt.S entry.S +ASM_PARAVIRT_OBJS = $(addprefix xen-,$(ASM_PARAVIRT_MULTI_COMPILE_SRCS:.S=.o)) +obj-y += $(ASM_PARAVIRT_OBJS) +define paravirtualized_xen +AFLAGS_$(1) += -D__IA64_ASM_PARAVIRTUALIZED_XEN +endef +$(foreach o,$(ASM_PARAVIRT_OBJS),$(eval $(call paravirtualized_xen,$(o)))) + +$(obj)/xen-%.o: $(src)/../kernel/%.S FORCE + $(call if_changed_dep,as_o_S) diff --git a/arch/ia64/xen/grant-table.c b/arch/ia64/xen/grant-table.c new file mode 100644 index 0000000..777dd9a --- /dev/null +++ b/arch/ia64/xen/grant-table.c @@ -0,0 +1,155 @@ +/****************************************************************************** + * arch/ia64/xen/grant-table.c + * + * Copyright (c) 2006 Isaku Yamahata <yamahata at valinux co jp> + * VA Linux Systems Japan K.K. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <linux/module.h> +#include <linux/vmalloc.h> +#include <linux/mm.h> + +#include <xen/interface/xen.h> +#include <xen/interface/memory.h> +#include <xen/grant_table.h> + +#include <asm/xen/hypervisor.h> + +struct vm_struct *xen_alloc_vm_area(unsigned long size) +{ + int order; + unsigned long virt; + unsigned long nr_pages; + struct vm_struct *area; + + order = get_order(size); + virt = __get_free_pages(GFP_KERNEL, order); + if (virt == 0) + goto err0; + nr_pages = 1 << order; + scrub_pages(virt, nr_pages); + + area = kmalloc(sizeof(*area), GFP_KERNEL); + if (area == NULL) + goto err1; + + area->flags = VM_IOREMAP; + area->addr = (void *)virt; + area->size = size; + area->pages = NULL; + area->nr_pages = nr_pages; + area->phys_addr = 0; /* xenbus_map_ring_valloc uses this field! */ + + return area; + +err1: + free_pages(virt, order); +err0: + return NULL; +} +EXPORT_SYMBOL_GPL(xen_alloc_vm_area); + +void xen_free_vm_area(struct vm_struct *area) +{ + unsigned int order = get_order(area->size); + unsigned long i; + unsigned long phys_addr = __pa(area->addr); + + /* This area is used for foreign page mappping. + * So underlying machine page may not be assigned. */ + for (i = 0; i < (1 << order); i++) { + unsigned long ret; + unsigned long gpfn = (phys_addr >> PAGE_SHIFT) + i; + struct xen_memory_reservation reservation = { + .nr_extents = 1, + .address_bits = 0, + .extent_order = 0, + .domid = DOMID_SELF + }; + set_xen_guest_handle(reservation.extent_start, &gpfn); + ret = HYPERVISOR_memory_op(XENMEM_populate_physmap, + &reservation); + BUG_ON(ret != 1); + } + free_pages((unsigned long)area->addr, order); + kfree(area); +} +EXPORT_SYMBOL_GPL(xen_free_vm_area); + + +/**************************************************************************** + * grant table hack + * cmd: GNTTABOP_xxx + */ + +int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes, + unsigned long max_nr_gframes, + struct grant_entry **__shared) +{ + *__shared = __va(frames[0] << PAGE_SHIFT); + return 0; +} + +void arch_gnttab_unmap_shared(struct grant_entry *shared, + unsigned long nr_gframes) +{ + /* nothing */ +} + +static void +gnttab_map_grant_ref_pre(struct gnttab_map_grant_ref *uop) +{ + uint32_t flags; + + flags = uop->flags; + + if (flags & GNTMAP_host_map) { + if (flags & GNTMAP_application_map) { + printk(KERN_DEBUG + "GNTMAP_application_map is not supported yet: " + "flags 0x%x\n", flags); + BUG(); + } + if (flags & GNTMAP_contains_pte) { + printk(KERN_DEBUG + "GNTMAP_contains_pte is not supported yet: " + "flags 0x%x\n", flags); + BUG(); + } + } else if (flags & GNTMAP_device_map) { + printk("GNTMAP_device_map is not supported yet 0x%x\n", flags); + BUG(); /* not yet. actually this flag is not used. */ + } else { + BUG(); + } +} + +int +HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count) +{ + if (cmd == GNTTABOP_map_grant_ref) { + unsigned int i; + for (i = 0; i < count; i++) { + gnttab_map_grant_ref_pre( + (struct gnttab_map_grant_ref *)uop + i); + } + } + return xencomm_hypercall_grant_table_op(cmd, uop, count); +} + +EXPORT_SYMBOL(HYPERVISOR_grant_table_op); diff --git a/arch/ia64/xen/hypercall.S b/arch/ia64/xen/hypercall.S new file mode 100644 index 0000000..45e02bb --- /dev/null +++ b/arch/ia64/xen/hypercall.S @@ -0,0 +1,91 @@ +/* + * Support routines for Xen hypercalls + * + * Copyright (C) 2005 Dan Magenheimer <dan.magenheimer@hp.com> + * Copyright (C) 2008 Yaozu (Eddie) Dong <eddie.dong@intel.com> + */ + +#include <asm/asmmacro.h> +#include <asm/intrinsics.h> +#include <asm/xen/privop.h> + +/* + * Hypercalls without parameter. + */ +#define __HCALL0(name,hcall) \ + GLOBAL_ENTRY(name); \ + break hcall; \ + br.ret.sptk.many rp; \ + END(name) + +/* + * Hypercalls with 1 parameter. + */ +#define __HCALL1(name,hcall) \ + GLOBAL_ENTRY(name); \ + mov r8=r32; \ + break hcall; \ + br.ret.sptk.many rp; \ + END(name) + +/* + * Hypercalls with 2 parameters. + */ +#define __HCALL2(name,hcall) \ + GLOBAL_ENTRY(name); \ + mov r8=r32; \ + mov r9=r33; \ + break hcall; \ + br.ret.sptk.many rp; \ + END(name) + +__HCALL0(xen_get_psr, HYPERPRIVOP_GET_PSR) +__HCALL0(xen_get_ivr, HYPERPRIVOP_GET_IVR) +__HCALL0(xen_get_tpr, HYPERPRIVOP_GET_TPR) +__HCALL0(xen_hyper_ssm_i, HYPERPRIVOP_SSM_I) + +__HCALL1(xen_set_tpr, HYPERPRIVOP_SET_TPR) +__HCALL1(xen_eoi, HYPERPRIVOP_EOI) +__HCALL1(xen_thash, HYPERPRIVOP_THASH) +__HCALL1(xen_set_itm, HYPERPRIVOP_SET_ITM) +__HCALL1(xen_get_rr, HYPERPRIVOP_GET_RR) +__HCALL1(xen_fc, HYPERPRIVOP_FC) +__HCALL1(xen_get_cpuid, HYPERPRIVOP_GET_CPUID) +__HCALL1(xen_get_pmd, HYPERPRIVOP_GET_PMD) + +__HCALL2(xen_ptcga, HYPERPRIVOP_PTC_GA) +__HCALL2(xen_set_rr, HYPERPRIVOP_SET_RR) +__HCALL2(xen_set_kr, HYPERPRIVOP_SET_KR) + +#ifdef CONFIG_IA32_SUPPORT +__HCALL0(xen_get_eflag, HYPERPRIVOP_GET_EFLAG) +__HCALL1(xen_set_eflag, HYPERPRIVOP_SET_EFLAG) // refer SDM vol1 3.1.8 +#endif /* CONFIG_IA32_SUPPORT */ + +GLOBAL_ENTRY(xen_set_rr0_to_rr4) + mov r8=r32 + mov r9=r33 + mov r10=r34 + mov r11=r35 + mov r14=r36 + XEN_HYPER_SET_RR0_TO_RR4 + br.ret.sptk.many rp + ;; +END(xen_set_rr0_to_rr4) + +GLOBAL_ENTRY(xen_send_ipi) + mov r14=r32 + mov r15=r33 + mov r2=0x400 + break 0x1000 + ;; + br.ret.sptk.many rp + ;; +END(xen_send_ipi) + +GLOBAL_ENTRY(__hypercall) + mov r2=r37 + break 0x1000 + br.ret.sptk.many b0 + ;; +END(__hypercall) diff --git a/arch/ia64/xen/hypervisor.c b/arch/ia64/xen/hypervisor.c new file mode 100644 index 0000000..cac4d97 --- /dev/null +++ b/arch/ia64/xen/hypervisor.c @@ -0,0 +1,96 @@ +/****************************************************************************** + * arch/ia64/xen/hypervisor.c + * + * Copyright (c) 2006 Isaku Yamahata <yamahata at valinux co jp> + * VA Linux Systems Japan K.K. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <linux/efi.h> +#include <asm/xen/hypervisor.h> +#include <asm/xen/privop.h> + +#include "irq_xen.h" + +struct shared_info *HYPERVISOR_shared_info __read_mostly = + (struct shared_info *)XSI_BASE; +EXPORT_SYMBOL(HYPERVISOR_shared_info); + +DEFINE_PER_CPU(struct vcpu_info *, xen_vcpu); + +struct start_info *xen_start_info; +EXPORT_SYMBOL(xen_start_info); + +EXPORT_SYMBOL(xen_domain_type); + +EXPORT_SYMBOL(__hypercall); + +/* Stolen from arch/x86/xen/enlighten.c */ +/* + * Flag to determine whether vcpu info placement is available on all + * VCPUs. We assume it is to start with, and then set it to zero on + * the first failure. This is because it can succeed on some VCPUs + * and not others, since it can involve hypervisor memory allocation, + * or because the guest failed to guarantee all the appropriate + * constraints on all VCPUs (ie buffer can't cross a page boundary). + * + * Note that any particular CPU may be using a placed vcpu structure, + * but we can only optimise if the all are. + * + * 0: not available, 1: available + */ + +static void __init xen_vcpu_setup(int cpu) +{ + /* + * WARNING: + * before changing MAX_VIRT_CPUS, + * check that shared_info fits on a page + */ + BUILD_BUG_ON(sizeof(struct shared_info) > PAGE_SIZE); + per_cpu(xen_vcpu, cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu]; +} + +void __init xen_setup_vcpu_info_placement(void) +{ + int cpu; + + for_each_possible_cpu(cpu) + xen_vcpu_setup(cpu); +} + +void __cpuinit +xen_cpu_init(void) +{ + xen_smp_intr_init(); +} + +/************************************************************************** + * opt feature + */ +void +xen_ia64_enable_opt_feature(void) +{ + /* Enable region 7 identity map optimizations in Xen */ + struct xen_ia64_opt_feature optf; + + optf.cmd = XEN_IA64_OPTF_IDENT_MAP_REG7; + optf.on = XEN_IA64_OPTF_ON; + optf.pgprot = pgprot_val(PAGE_KERNEL); + optf.key = 0; /* No key on linux. */ + HYPERVISOR_opt_feature(&optf); +} diff --git a/arch/ia64/xen/irq_xen.c b/arch/ia64/xen/irq_xen.c new file mode 100644 index 0000000..af93aad --- /dev/null +++ b/arch/ia64/xen/irq_xen.c @@ -0,0 +1,435 @@ +/****************************************************************************** + * arch/ia64/xen/irq_xen.c + * + * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp> + * VA Linux Systems Japan K.K. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <linux/cpu.h> + +#include <xen/interface/xen.h> +#include <xen/interface/callback.h> +#include <xen/events.h> + +#include <asm/xen/privop.h> + +#include "irq_xen.h" + +/*************************************************************************** + * pv_irq_ops + * irq operations + */ + +static int +xen_assign_irq_vector(int irq) +{ + struct physdev_irq irq_op; + + irq_op.irq = irq; + if (HYPERVISOR_physdev_op(PHYSDEVOP_alloc_irq_vector, &irq_op)) + return -ENOSPC; + + return irq_op.vector; +} + +static void +xen_free_irq_vector(int vector) +{ + struct physdev_irq irq_op; + + if (vector < IA64_FIRST_DEVICE_VECTOR || + vector > IA64_LAST_DEVICE_VECTOR) + return; + + irq_op.vector = vector; + if (HYPERVISOR_physdev_op(PHYSDEVOP_free_irq_vector, &irq_op)) + printk(KERN_WARNING "%s: xen_free_irq_vecotr fail vector=%d\n", + __func__, vector); +} + + +static DEFINE_PER_CPU(int, timer_irq) = -1; +static DEFINE_PER_CPU(int, ipi_irq) = -1; +static DEFINE_PER_CPU(int, resched_irq) = -1; +static DEFINE_PER_CPU(int, cmc_irq) = -1; +static DEFINE_PER_CPU(int, cmcp_irq) = -1; +static DEFINE_PER_CPU(int, cpep_irq) = -1; +#define NAME_SIZE 15 +static DEFINE_PER_CPU(char[NAME_SIZE], timer_name); +static DEFINE_PER_CPU(char[NAME_SIZE], ipi_name); +static DEFINE_PER_CPU(char[NAME_SIZE], resched_name); +static DEFINE_PER_CPU(char[NAME_SIZE], cmc_name); +static DEFINE_PER_CPU(char[NAME_SIZE], cmcp_name); +static DEFINE_PER_CPU(char[NAME_SIZE], cpep_name); +#undef NAME_SIZE + +struct saved_irq { + unsigned int irq; + struct irqaction *action; +}; +/* 16 should be far optimistic value, since only several percpu irqs + * are registered early. + */ +#define MAX_LATE_IRQ 16 +static struct saved_irq saved_percpu_irqs[MAX_LATE_IRQ]; +static unsigned short late_irq_cnt; +static unsigned short saved_irq_cnt; +static int xen_slab_ready; + +#ifdef CONFIG_SMP +/* Dummy stub. Though we may check XEN_RESCHEDULE_VECTOR before __do_IRQ, + * it ends up to issue several memory accesses upon percpu data and + * thus adds unnecessary traffic to other paths. + */ +static irqreturn_t +xen_dummy_handler(int irq, void *dev_id) +{ + + return IRQ_HANDLED; +} + +static struct irqaction xen_ipi_irqaction = { + .handler = handle_IPI, + .flags = IRQF_DISABLED, + .name = "IPI" +}; + +static struct irqaction xen_resched_irqaction = { + .handler = xen_dummy_handler, + .flags = IRQF_DISABLED, + .name = "resched" +}; + +static struct irqaction xen_tlb_irqaction = { + .handler = xen_dummy_handler, + .flags = IRQF_DISABLED, + .name = "tlb_flush" +}; +#endif + +/* + * This is xen version percpu irq registration, which needs bind + * to xen specific evtchn sub-system. One trick here is that xen + * evtchn binding interface depends on kmalloc because related + * port needs to be freed at device/cpu down. So we cache the + * registration on BSP before slab is ready and then deal them + * at later point. For rest instances happening after slab ready, + * we hook them to xen evtchn immediately. + * + * FIXME: MCA is not supported by far, and thus "nomca" boot param is + * required. + */ +static void +__xen_register_percpu_irq(unsigned int cpu, unsigned int vec, + struct irqaction *action, int save) +{ + irq_desc_t *desc; + int irq = 0; + + if (xen_slab_ready) { + switch (vec) { + case IA64_TIMER_VECTOR: + snprintf(per_cpu(timer_name, cpu), + sizeof(per_cpu(timer_name, cpu)), + "%s%d", action->name, cpu); + irq = bind_virq_to_irqhandler(VIRQ_ITC, cpu, + action->handler, action->flags, + per_cpu(timer_name, cpu), action->dev_id); + per_cpu(timer_irq, cpu) = irq; + break; + case IA64_IPI_RESCHEDULE: + snprintf(per_cpu(resched_name, cpu), + sizeof(per_cpu(resched_name, cpu)), + "%s%d", action->name, cpu); + irq = bind_ipi_to_irqhandler(XEN_RESCHEDULE_VECTOR, cpu, + action->handler, action->flags, + per_cpu(resched_name, cpu), action->dev_id); + per_cpu(resched_irq, cpu) = irq; + break; + case IA64_IPI_VECTOR: + snprintf(per_cpu(ipi_name, cpu), + sizeof(per_cpu(ipi_name, cpu)), + "%s%d", action->name, cpu); + irq = bind_ipi_to_irqhandler(XEN_IPI_VECTOR, cpu, + action->handler, action->flags, + per_cpu(ipi_name, cpu), action->dev_id); + per_cpu(ipi_irq, cpu) = irq; + break; + case IA64_CMC_VECTOR: + snprintf(per_cpu(cmc_name, cpu), + sizeof(per_cpu(cmc_name, cpu)), + "%s%d", action->name, cpu); + irq = bind_virq_to_irqhandler(VIRQ_MCA_CMC, cpu, + action->handler, + action->flags, + per_cpu(cmc_name, cpu), + action->dev_id); + per_cpu(cmc_irq, cpu) = irq; + break; + case IA64_CMCP_VECTOR: + snprintf(per_cpu(cmcp_name, cpu), + sizeof(per_cpu(cmcp_name, cpu)), + "%s%d", action->name, cpu); + irq = bind_ipi_to_irqhandler(XEN_CMCP_VECTOR, cpu, + action->handler, + action->flags, + per_cpu(cmcp_name, cpu), + action->dev_id); + per_cpu(cmcp_irq, cpu) = irq; + break; + case IA64_CPEP_VECTOR: + snprintf(per_cpu(cpep_name, cpu), + sizeof(per_cpu(cpep_name, cpu)), + "%s%d", action->name, cpu); + irq = bind_ipi_to_irqhandler(XEN_CPEP_VECTOR, cpu, + action->handler, + action->flags, + per_cpu(cpep_name, cpu), + action->dev_id); + per_cpu(cpep_irq, cpu) = irq; + break; + case IA64_CPE_VECTOR: + case IA64_MCA_RENDEZ_VECTOR: + case IA64_PERFMON_VECTOR: + case IA64_MCA_WAKEUP_VECTOR: + case IA64_SPURIOUS_INT_VECTOR: + /* No need to complain, these aren't supported. */ + break; + default: + printk(KERN_WARNING "Percpu irq %d is unsupported " + "by xen!\n", vec); + break; + } + BUG_ON(irq < 0); + + if (irq > 0) { + /* + * Mark percpu. Without this, migrate_irqs() will + * mark the interrupt for migrations and trigger it + * on cpu hotplug. + */ + desc = irq_desc + irq; + desc->status |= IRQ_PER_CPU; + } + } + + /* For BSP, we cache registered percpu irqs, and then re-walk + * them when initializing APs + */ + if (!cpu && save) { + BUG_ON(saved_irq_cnt == MAX_LATE_IRQ); + saved_percpu_irqs[saved_irq_cnt].irq = vec; + saved_percpu_irqs[saved_irq_cnt].action = action; + saved_irq_cnt++; + if (!xen_slab_ready) + late_irq_cnt++; + } +} + +static void +xen_register_percpu_irq(ia64_vector vec, struct irqaction *action) +{ + __xen_register_percpu_irq(smp_processor_id(), vec, action, 1); +} + +static void +xen_bind_early_percpu_irq(void) +{ + int i; + + xen_slab_ready = 1; + /* There's no race when accessing this cached array, since only + * BSP will face with such step shortly + */ + for (i = 0; i < late_irq_cnt; i++) + __xen_register_percpu_irq(smp_processor_id(), + saved_percpu_irqs[i].irq, + saved_percpu_irqs[i].action, 0); +} + +/* FIXME: There's no obvious point to check whether slab is ready. So + * a hack is used here by utilizing a late time hook. + */ + +#ifdef CONFIG_HOTPLUG_CPU +static int __devinit +unbind_evtchn_callback(struct notifier_block *nfb, + unsigned long action, void *hcpu) +{ + unsigned int cpu = (unsigned long)hcpu; + + if (action == CPU_DEAD) { + /* Unregister evtchn. */ + if (per_cpu(cpep_irq, cpu) >= 0) { + unbind_from_irqhandler(per_cpu(cpep_irq, cpu), NULL); + per_cpu(cpep_irq, cpu) = -1; + } + if (per_cpu(cmcp_irq, cpu) >= 0) { + unbind_from_irqhandler(per_cpu(cmcp_irq, cpu), NULL); + per_cpu(cmcp_irq, cpu) = -1; + } + if (per_cpu(cmc_irq, cpu) >= 0) { + unbind_from_irqhandler(per_cpu(cmc_irq, cpu), NULL); + per_cpu(cmc_irq, cpu) = -1; + } + if (per_cpu(ipi_irq, cpu) >= 0) { + unbind_from_irqhandler(per_cpu(ipi_irq, cpu), NULL); + per_cpu(ipi_irq, cpu) = -1; + } + if (per_cpu(resched_irq, cpu) >= 0) { + unbind_from_irqhandler(per_cpu(resched_irq, cpu), + NULL); + per_cpu(resched_irq, cpu) = -1; + } + if (per_cpu(timer_irq, cpu) >= 0) { + unbind_from_irqhandler(per_cpu(timer_irq, cpu), NULL); + per_cpu(timer_irq, cpu) = -1; + } + } + return NOTIFY_OK; +} + +static struct notifier_block unbind_evtchn_notifier = { + .notifier_call = unbind_evtchn_callback, + .priority = 0 +}; +#endif + +void xen_smp_intr_init_early(unsigned int cpu) +{ +#ifdef CONFIG_SMP + unsigned int i; + + for (i = 0; i < saved_irq_cnt; i++) + __xen_register_percpu_irq(cpu, saved_percpu_irqs[i].irq, + saved_percpu_irqs[i].action, 0); +#endif +} + +void xen_smp_intr_init(void) +{ +#ifdef CONFIG_SMP + unsigned int cpu = smp_processor_id(); + struct callback_register event = { + .type = CALLBACKTYPE_event, + .address = { .ip = (unsigned long)&xen_event_callback }, + }; + + if (cpu == 0) { + /* Initialization was already done for boot cpu. */ +#ifdef CONFIG_HOTPLUG_CPU + /* Register the notifier only once. */ + register_cpu_notifier(&unbind_evtchn_notifier); +#endif + return; + } + + /* This should be piggyback when setup vcpu guest context */ + BUG_ON(HYPERVISOR_callback_op(CALLBACKOP_register, &event)); +#endif /* CONFIG_SMP */ +} + +void __init +xen_irq_init(void) +{ + struct callback_register event = { + .type = CALLBACKTYPE_event, + .address = { .ip = (unsigned long)&xen_event_callback }, + }; + + xen_init_IRQ(); + BUG_ON(HYPERVISOR_callback_op(CALLBACKOP_register, &event)); + late_time_init = xen_bind_early_percpu_irq; +} + +void +xen_platform_send_ipi(int cpu, int vector, int delivery_mode, int redirect) +{ +#ifdef CONFIG_SMP + /* TODO: we need to call vcpu_up here */ + if (unlikely(vector == ap_wakeup_vector)) { + /* XXX + * This should be in __cpu_up(cpu) in ia64 smpboot.c + * like x86. But don't want to modify it, + * keep it untouched. + */ + xen_smp_intr_init_early(cpu); + + xen_send_ipi(cpu, vector); + /* vcpu_prepare_and_up(cpu); */ + return; + } +#endif + + switch (vector) { + case IA64_IPI_VECTOR: + xen_send_IPI_one(cpu, XEN_IPI_VECTOR); + break; + case IA64_IPI_RESCHEDULE: + xen_send_IPI_one(cpu, XEN_RESCHEDULE_VECTOR); + break; + case IA64_CMCP_VECTOR: + xen_send_IPI_one(cpu, XEN_CMCP_VECTOR); + break; + case IA64_CPEP_VECTOR: + xen_send_IPI_one(cpu, XEN_CPEP_VECTOR); + break; + case IA64_TIMER_VECTOR: { + /* this is used only once by check_sal_cache_flush() + at boot time */ + static int used = 0; + if (!used) { + xen_send_ipi(cpu, IA64_TIMER_VECTOR); + used = 1; + break; + } + /* fallthrough */ + } + default: + printk(KERN_WARNING "Unsupported IPI type 0x%x\n", + vector); + notify_remote_via_irq(0); /* defaults to 0 irq */ + break; + } +} + +static void __init +xen_register_ipi(void) +{ +#ifdef CONFIG_SMP + register_percpu_irq(IA64_IPI_VECTOR, &xen_ipi_irqaction); + register_percpu_irq(IA64_IPI_RESCHEDULE, &xen_resched_irqaction); + register_percpu_irq(IA64_IPI_LOCAL_TLB_FLUSH, &xen_tlb_irqaction); +#endif +} + +static void +xen_resend_irq(unsigned int vector) +{ + (void)resend_irq_on_evtchn(vector); +} + +const struct pv_irq_ops xen_irq_ops __initdata = { + .register_ipi = xen_register_ipi, + + .assign_irq_vector = xen_assign_irq_vector, + .free_irq_vector = xen_free_irq_vector, + .register_percpu_irq = xen_register_percpu_irq, + + .resend_irq = xen_resend_irq, +}; diff --git a/arch/ia64/xen/irq_xen.h b/arch/ia64/xen/irq_xen.h new file mode 100644 index 0000000..26110f3 --- /dev/null +++ b/arch/ia64/xen/irq_xen.h @@ -0,0 +1,34 @@ +/****************************************************************************** + * arch/ia64/xen/irq_xen.h + * + * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp> + * VA Linux Systems Japan K.K. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef IRQ_XEN_H +#define IRQ_XEN_H + +extern void (*late_time_init)(void); +extern char xen_event_callback; +void __init xen_init_IRQ(void); + +extern const struct pv_irq_ops xen_irq_ops __initdata; +extern void xen_smp_intr_init(void); +extern void xen_send_ipi(int cpu, int vec); + +#endif /* IRQ_XEN_H */ diff --git a/arch/ia64/xen/machvec.c b/arch/ia64/xen/machvec.c new file mode 100644 index 0000000..4ad588a --- /dev/null +++ b/arch/ia64/xen/machvec.c @@ -0,0 +1,4 @@ +#define MACHVEC_PLATFORM_NAME xen +#define MACHVEC_PLATFORM_HEADER <asm/machvec_xen.h> +#include <asm/machvec_init.h> + diff --git a/arch/ia64/xen/suspend.c b/arch/ia64/xen/suspend.c new file mode 100644 index 0000000..fd66b04 --- /dev/null +++ b/arch/ia64/xen/suspend.c @@ -0,0 +1,64 @@ +/****************************************************************************** + * arch/ia64/xen/suspend.c + * + * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp> + * VA Linux Systems Japan K.K. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * suspend/resume + */ + +#include <xen/xen-ops.h> +#include <asm/xen/hypervisor.h> +#include "time.h" + +void +xen_mm_pin_all(void) +{ + /* nothing */ +} + +void +xen_mm_unpin_all(void) +{ + /* nothing */ +} + +void xen_pre_device_suspend(void) +{ + /* nothing */ +} + +void +xen_pre_suspend() +{ + /* nothing */ +} + +void +xen_post_suspend(int suspend_cancelled) +{ + if (suspend_cancelled) + return; + + xen_ia64_enable_opt_feature(); + /* add more if necessary */ +} + +void xen_arch_resume(void) +{ + xen_timer_resume_on_aps(); +} diff --git a/arch/ia64/xen/time.c b/arch/ia64/xen/time.c new file mode 100644 index 0000000..d15a94c --- /dev/null +++ b/arch/ia64/xen/time.c @@ -0,0 +1,213 @@ +/****************************************************************************** + * arch/ia64/xen/time.c + * + * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp> + * VA Linux Systems Japan K.K. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <linux/delay.h> +#include <linux/kernel_stat.h> +#include <linux/posix-timers.h> +#include <linux/irq.h> +#include <linux/clocksource.h> + +#include <asm/timex.h> + +#include <asm/xen/hypervisor.h> + +#include <xen/interface/vcpu.h> + +#include "../kernel/fsyscall_gtod_data.h" + +DEFINE_PER_CPU(struct vcpu_runstate_info, runstate); +DEFINE_PER_CPU(unsigned long, processed_stolen_time); +DEFINE_PER_CPU(unsigned long, processed_blocked_time); + +/* taken from i386/kernel/time-xen.c */ +static void xen_init_missing_ticks_accounting(int cpu) +{ + struct vcpu_register_runstate_memory_area area; + struct vcpu_runstate_info *runstate = &per_cpu(runstate, cpu); + int rc; + + memset(runstate, 0, sizeof(*runstate)); + + area.addr.v = runstate; + rc = HYPERVISOR_vcpu_op(VCPUOP_register_runstate_memory_area, cpu, + &area); + WARN_ON(rc && rc != -ENOSYS); + + per_cpu(processed_blocked_time, cpu) = runstate->time[RUNSTATE_blocked]; + per_cpu(processed_stolen_time, cpu) = runstate->time[RUNSTATE_runnable] + + runstate->time[RUNSTATE_offline]; +} + +/* + * Runstate accounting + */ +/* stolen from arch/x86/xen/time.c */ +static void get_runstate_snapshot(struct vcpu_runstate_info *res) +{ + u64 state_time; + struct vcpu_runstate_info *state; + + BUG_ON(preemptible()); + + state = &__get_cpu_var(runstate); + + /* + * The runstate info is always updated by the hypervisor on + * the current CPU, so there's no need to use anything + * stronger than a compiler barrier when fetching it. + */ + do { + state_time = state->state_entry_time; + rmb(); + *res = *state; + rmb(); + } while (state->state_entry_time != state_time); +} + +#define NS_PER_TICK (1000000000LL/HZ) + +static unsigned long +consider_steal_time(unsigned long new_itm) +{ + unsigned long stolen, blocked; + unsigned long delta_itm = 0, stolentick = 0; + int cpu = smp_processor_id(); + struct vcpu_runstate_info runstate; + struct task_struct *p = current; + + get_runstate_snapshot(&runstate); + + /* + * Check for vcpu migration effect + * In this case, itc value is reversed. + * This causes huge stolen value. + * This function just checks and reject this effect. + */ + if (!time_after_eq(runstate.time[RUNSTATE_blocked], + per_cpu(processed_blocked_time, cpu))) + blocked = 0; + + if (!time_after_eq(runstate.time[RUNSTATE_runnable] + + runstate.time[RUNSTATE_offline], + per_cpu(processed_stolen_time, cpu))) + stolen = 0; + + if (!time_after(delta_itm + new_itm, ia64_get_itc())) + stolentick = ia64_get_itc() - new_itm; + + do_div(stolentick, NS_PER_TICK); + stolentick++; + + do_div(stolen, NS_PER_TICK); + + if (stolen > stolentick) + stolen = stolentick; + + stolentick -= stolen; + do_div(blocked, NS_PER_TICK); + + if (blocked > stolentick) + blocked = stolentick; + + if (stolen > 0 || blocked > 0) { + account_steal_time(NULL, jiffies_to_cputime(stolen)); + account_steal_time(idle_task(cpu), jiffies_to_cputime(blocked)); + run_local_timers(); + + if (rcu_pending(cpu)) + rcu_check_callbacks(cpu, user_mode(get_irq_regs())); + + scheduler_tick(); + run_posix_cpu_timers(p); + delta_itm += local_cpu_data->itm_delta * (stolen + blocked); + + if (cpu == time_keeper_id) { + write_seqlock(&xtime_lock); + do_timer(stolen + blocked); + local_cpu_data->itm_next = delta_itm + new_itm; + write_sequnlock(&xtime_lock); + } else { + local_cpu_data->itm_next = delta_itm + new_itm; + } + per_cpu(processed_stolen_time, cpu) += NS_PER_TICK * stolen; + per_cpu(processed_blocked_time, cpu) += NS_PER_TICK * blocked; + } + return delta_itm; +} + +static int xen_do_steal_accounting(unsigned long *new_itm) +{ + unsigned long delta_itm; + delta_itm = consider_steal_time(*new_itm); + *new_itm += delta_itm; + if (time_after(*new_itm, ia64_get_itc()) && delta_itm) + return 1; + + return 0; +} + +static void xen_itc_jitter_data_reset(void) +{ + u64 lcycle, ret; + + do { + lcycle = itc_jitter_data.itc_lastcycle; + ret = cmpxchg(&itc_jitter_data.itc_lastcycle, lcycle, 0); + } while (unlikely(ret != lcycle)); +} + +struct pv_time_ops xen_time_ops __initdata = { + .init_missing_ticks_accounting = xen_init_missing_ticks_accounting, + .do_steal_accounting = xen_do_steal_accounting, + .clocksource_resume = xen_itc_jitter_data_reset, +}; + +/* Called after suspend, to resume time. */ +static void xen_local_tick_resume(void) +{ + /* Just trigger a tick. */ + ia64_cpu_local_tick(); + touch_softlockup_watchdog(); +} + +void +xen_timer_resume(void) +{ + unsigned int cpu; + + xen_local_tick_resume(); + + for_each_online_cpu(cpu) + xen_init_missing_ticks_accounting(cpu); +} + +static void ia64_cpu_local_tick_fn(void *unused) +{ + xen_local_tick_resume(); + xen_init_missing_ticks_accounting(smp_processor_id()); +} + +void +xen_timer_resume_on_aps(void) +{ + smp_call_function(&ia64_cpu_local_tick_fn, NULL, 1); +} diff --git a/arch/ia64/xen/time.h b/arch/ia64/xen/time.h new file mode 100644 index 0000000..f98d7e1 --- /dev/null +++ b/arch/ia64/xen/time.h @@ -0,0 +1,24 @@ +/****************************************************************************** + * arch/ia64/xen/time.h + * + * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp> + * VA Linux Systems Japan K.K. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +extern struct pv_time_ops xen_time_ops __initdata; +void xen_timer_resume_on_aps(void); diff --git a/arch/ia64/xen/xcom_hcall.c b/arch/ia64/xen/xcom_hcall.c new file mode 100644 index 0000000..ccaf743 --- /dev/null +++ b/arch/ia64/xen/xcom_hcall.c @@ -0,0 +1,441 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Tristan Gingold <tristan.gingold@bull.net> + * + * Copyright (c) 2007 + * Isaku Yamahata <yamahata at valinux co jp> + * VA Linux Systems Japan K.K. + * consolidate mini and inline version. + */ + +#include <linux/module.h> +#include <xen/interface/xen.h> +#include <xen/interface/memory.h> +#include <xen/interface/grant_table.h> +#include <xen/interface/callback.h> +#include <xen/interface/vcpu.h> +#include <asm/xen/hypervisor.h> +#include <asm/xen/xencomm.h> + +/* Xencomm notes: + * This file defines hypercalls to be used by xencomm. The hypercalls simply + * create inlines or mini descriptors for pointers and then call the raw arch + * hypercall xencomm_arch_hypercall_XXX + * + * If the arch wants to directly use these hypercalls, simply define macros + * in asm/xen/hypercall.h, eg: + * #define HYPERVISOR_sched_op xencomm_hypercall_sched_op + * + * The arch may also define HYPERVISOR_xxx as a function and do more operations + * before/after doing the hypercall. + * + * Note: because only inline or mini descriptors are created these functions + * must only be called with in kernel memory parameters. + */ + +int +xencomm_hypercall_console_io(int cmd, int count, char *str) +{ + /* xen early printk uses console io hypercall before + * xencomm initialization. In that case, we just ignore it. + */ + if (!xencomm_is_initialized()) + return 0; + + return xencomm_arch_hypercall_console_io + (cmd, count, xencomm_map_no_alloc(str, count)); +} +EXPORT_SYMBOL_GPL(xencomm_hypercall_console_io); + +int +xencomm_hypercall_event_channel_op(int cmd, void *op) +{ + struct xencomm_handle *desc; + desc = xencomm_map_no_alloc(op, sizeof(struct evtchn_op)); + if (desc == NULL) + return -EINVAL; + + return xencomm_arch_hypercall_event_channel_op(cmd, desc); +} +EXPORT_SYMBOL_GPL(xencomm_hypercall_event_channel_op); + +int +xencomm_hypercall_xen_version(int cmd, void *arg) +{ + struct xencomm_handle *desc; + unsigned int argsize; + + switch (cmd) { + case XENVER_version: + /* do not actually pass an argument */ + return xencomm_arch_hypercall_xen_version(cmd, 0); + case XENVER_extraversion: + argsize = sizeof(struct xen_extraversion); + break; + case XENVER_compile_info: + argsize = sizeof(struct xen_compile_info); + break; + case XENVER_capabilities: + argsize = sizeof(struct xen_capabilities_info); + break; + case XENVER_changeset: + argsize = sizeof(struct xen_changeset_info); + break; + case XENVER_platform_parameters: + argsize = sizeof(struct xen_platform_parameters); + break; + case XENVER_get_features: + argsize = (arg == NULL) ? 0 : sizeof(struct xen_feature_info); + break; + + default: + printk(KERN_DEBUG + "%s: unknown version op %d\n", __func__, cmd); + return -ENOSYS; + } + + desc = xencomm_map_no_alloc(arg, argsize); + if (desc == NULL) + return -EINVAL; + + return xencomm_arch_hypercall_xen_version(cmd, desc); +} +EXPORT_SYMBOL_GPL(xencomm_hypercall_xen_version); + +int +xencomm_hypercall_physdev_op(int cmd, void *op) +{ + unsigned int argsize; + + switch (cmd) { + case PHYSDEVOP_apic_read: + case PHYSDEVOP_apic_write: + argsize = sizeof(struct physdev_apic); + break; + case PHYSDEVOP_alloc_irq_vector: + case PHYSDEVOP_free_irq_vector: + argsize = sizeof(struct physdev_irq); + break; + case PHYSDEVOP_irq_status_query: + argsize = sizeof(struct physdev_irq_status_query); + break; + + default: + printk(KERN_DEBUG + "%s: unknown physdev op %d\n", __func__, cmd); + return -ENOSYS; + } + + return xencomm_arch_hypercall_physdev_op + (cmd, xencomm_map_no_alloc(op, argsize)); +} + +static int +xencommize_grant_table_op(struct xencomm_mini **xc_area, + unsigned int cmd, void *op, unsigned int count, + struct xencomm_handle **desc) +{ + struct xencomm_handle *desc1; + unsigned int argsize; + + switch (cmd) { + case GNTTABOP_map_grant_ref: + argsize = sizeof(struct gnttab_map_grant_ref); + break; + case GNTTABOP_unmap_grant_ref: + argsize = sizeof(struct gnttab_unmap_grant_ref); + break; + case GNTTABOP_setup_table: + { + struct gnttab_setup_table *setup = op; + + argsize = sizeof(*setup); + + if (count != 1) + return -EINVAL; + desc1 = __xencomm_map_no_alloc + (xen_guest_handle(setup->frame_list), + setup->nr_frames * + sizeof(*xen_guest_handle(setup->frame_list)), + *xc_area); + if (desc1 == NULL) + return -EINVAL; + (*xc_area)++; + set_xen_guest_handle(setup->frame_list, (void *)desc1); + break; + } + case GNTTABOP_dump_table: + argsize = sizeof(struct gnttab_dump_table); + break; + case GNTTABOP_transfer: + argsize = sizeof(struct gnttab_transfer); + break; + case GNTTABOP_copy: + argsize = sizeof(struct gnttab_copy); + break; + case GNTTABOP_query_size: + argsize = sizeof(struct gnttab_query_size); + break; + default: + printk(KERN_DEBUG "%s: unknown hypercall grant table op %d\n", + __func__, cmd); + BUG(); + } + + *desc = __xencomm_map_no_alloc(op, count * argsize, *xc_area); + if (*desc == NULL) + return -EINVAL; + (*xc_area)++; + + return 0; +} + +int +xencomm_hypercall_grant_table_op(unsigned int cmd, void *op, + unsigned int count) +{ + int rc; + struct xencomm_handle *desc; + XENCOMM_MINI_ALIGNED(xc_area, 2); + + rc = xencommize_grant_table_op(&xc_area, cmd, op, count, &desc); + if (rc) + return rc; + + return xencomm_arch_hypercall_grant_table_op(cmd, desc, count); +} +EXPORT_SYMBOL_GPL(xencomm_hypercall_grant_table_op); + +int +xencomm_hypercall_sched_op(int cmd, void *arg) +{ + struct xencomm_handle *desc; + unsigned int argsize; + + switch (cmd) { + case SCHEDOP_yield: + case SCHEDOP_block: + argsize = 0; + break; + case SCHEDOP_shutdown: + argsize = sizeof(struct sched_shutdown); + break; + case SCHEDOP_poll: + { + struct sched_poll *poll = arg; + struct xencomm_handle *ports; + + argsize = sizeof(struct sched_poll); + ports = xencomm_map_no_alloc(xen_guest_handle(poll->ports), + sizeof(*xen_guest_handle(poll->ports))); + + set_xen_guest_handle(poll->ports, (void *)ports); + break; + } + default: + printk(KERN_DEBUG "%s: unknown sched op %d\n", __func__, cmd); + return -ENOSYS; + } + + desc = xencomm_map_no_alloc(arg, argsize); + if (desc == NULL) + return -EINVAL; + + return xencomm_arch_hypercall_sched_op(cmd, desc); +} +EXPORT_SYMBOL_GPL(xencomm_hypercall_sched_op); + +int +xencomm_hypercall_multicall(void *call_list, int nr_calls) +{ + int rc; + int i; + struct multicall_entry *mce; + struct xencomm_handle *desc; + XENCOMM_MINI_ALIGNED(xc_area, nr_calls * 2); + + for (i = 0; i < nr_calls; i++) { + mce = (struct multicall_entry *)call_list + i; + + switch (mce->op) { + case __HYPERVISOR_update_va_mapping: + case __HYPERVISOR_mmu_update: + /* No-op on ia64. */ + break; + case __HYPERVISOR_grant_table_op: + rc = xencommize_grant_table_op + (&xc_area, + mce->args[0], (void *)mce->args[1], + mce->args[2], &desc); + if (rc) + return rc; + mce->args[1] = (unsigned long)desc; + break; + case __HYPERVISOR_memory_op: + default: + printk(KERN_DEBUG + "%s: unhandled multicall op entry op %lu\n", + __func__, mce->op); + return -ENOSYS; + } + } + + desc = xencomm_map_no_alloc(call_list, + nr_calls * sizeof(struct multicall_entry)); + if (desc == NULL) + return -EINVAL; + + return xencomm_arch_hypercall_multicall(desc, nr_calls); +} +EXPORT_SYMBOL_GPL(xencomm_hypercall_multicall); + +int +xencomm_hypercall_callback_op(int cmd, void *arg) +{ + unsigned int argsize; + switch (cmd) { + case CALLBACKOP_register: + argsize = sizeof(struct callback_register); + break; + case CALLBACKOP_unregister: + argsize = sizeof(struct callback_unregister); + break; + default: + printk(KERN_DEBUG + "%s: unknown callback op %d\n", __func__, cmd); + return -ENOSYS; + } + + return xencomm_arch_hypercall_callback_op + (cmd, xencomm_map_no_alloc(arg, argsize)); +} + +static int +xencommize_memory_reservation(struct xencomm_mini *xc_area, + struct xen_memory_reservation *mop) +{ + struct xencomm_handle *desc; + + desc = __xencomm_map_no_alloc(xen_guest_handle(mop->extent_start), + mop->nr_extents * + sizeof(*xen_guest_handle(mop->extent_start)), + xc_area); + if (desc == NULL) + return -EINVAL; + + set_xen_guest_handle(mop->extent_start, (void *)desc); + return 0; +} + +int +xencomm_hypercall_memory_op(unsigned int cmd, void *arg) +{ + GUEST_HANDLE(xen_pfn_t) extent_start_va[2] = { {NULL}, {NULL} }; + struct xen_memory_reservation *xmr = NULL; + int rc; + struct xencomm_handle *desc; + unsigned int argsize; + XENCOMM_MINI_ALIGNED(xc_area, 2); + + switch (cmd) { + case XENMEM_increase_reservation: + case XENMEM_decrease_reservation: + case XENMEM_populate_physmap: + xmr = (struct xen_memory_reservation *)arg; + set_xen_guest_handle(extent_start_va[0], + xen_guest_handle(xmr->extent_start)); + + argsize = sizeof(*xmr); + rc = xencommize_memory_reservation(xc_area, xmr); + if (rc) + return rc; + xc_area++; + break; + + case XENMEM_maximum_ram_page: + argsize = 0; + break; + + case XENMEM_add_to_physmap: + argsize = sizeof(struct xen_add_to_physmap); + break; + + default: + printk(KERN_DEBUG "%s: unknown memory op %d\n", __func__, cmd); + return -ENOSYS; + } + + desc = xencomm_map_no_alloc(arg, argsize); + if (desc == NULL) + return -EINVAL; + + rc = xencomm_arch_hypercall_memory_op(cmd, desc); + + switch (cmd) { + case XENMEM_increase_reservation: + case XENMEM_decrease_reservation: + case XENMEM_populate_physmap: + set_xen_guest_handle(xmr->extent_start, + xen_guest_handle(extent_start_va[0])); + break; + } + + return rc; +} +EXPORT_SYMBOL_GPL(xencomm_hypercall_memory_op); + +int +xencomm_hypercall_suspend(unsigned long srec) +{ + struct sched_shutdown arg; + + arg.reason = SHUTDOWN_suspend; + + return xencomm_arch_hypercall_sched_op( + SCHEDOP_shutdown, xencomm_map_no_alloc(&arg, sizeof(arg))); +} + +long +xencomm_hypercall_vcpu_op(int cmd, int cpu, void *arg) +{ + unsigned int argsize; + switch (cmd) { + case VCPUOP_register_runstate_memory_area: { + struct vcpu_register_runstate_memory_area *area = + (struct vcpu_register_runstate_memory_area *)arg; + argsize = sizeof(*arg); + set_xen_guest_handle(area->addr.h, + (void *)xencomm_map_no_alloc(area->addr.v, + sizeof(area->addr.v))); + break; + } + + default: + printk(KERN_DEBUG "%s: unknown vcpu op %d\n", __func__, cmd); + return -ENOSYS; + } + + return xencomm_arch_hypercall_vcpu_op(cmd, cpu, + xencomm_map_no_alloc(arg, argsize)); +} + +long +xencomm_hypercall_opt_feature(void *arg) +{ + return xencomm_arch_hypercall_opt_feature( + xencomm_map_no_alloc(arg, + sizeof(struct xen_ia64_opt_feature))); +} diff --git a/arch/ia64/xen/xen_pv_ops.c b/arch/ia64/xen/xen_pv_ops.c new file mode 100644 index 0000000..04cd123 --- /dev/null +++ b/arch/ia64/xen/xen_pv_ops.c @@ -0,0 +1,364 @@ +/****************************************************************************** + * arch/ia64/xen/xen_pv_ops.c + * + * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp> + * VA Linux Systems Japan K.K. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <linux/console.h> +#include <linux/irq.h> +#include <linux/kernel.h> +#include <linux/pm.h> + +#include <asm/xen/hypervisor.h> +#include <asm/xen/xencomm.h> +#include <asm/xen/privop.h> + +#include "irq_xen.h" +#include "time.h" + +/*************************************************************************** + * general info + */ +static struct pv_info xen_info __initdata = { + .kernel_rpl = 2, /* or 1: determin at runtime */ + .paravirt_enabled = 1, + .name = "Xen/ia64", +}; + +#define IA64_RSC_PL_SHIFT 2 +#define IA64_RSC_PL_BIT_SIZE 2 +#define IA64_RSC_PL_MASK \ + (((1UL << IA64_RSC_PL_BIT_SIZE) - 1) << IA64_RSC_PL_SHIFT) + +static void __init +xen_info_init(void) +{ + /* Xenified Linux/ia64 may run on pl = 1 or 2. + * determin at run time. */ + unsigned long rsc = ia64_getreg(_IA64_REG_AR_RSC); + unsigned int rpl = (rsc & IA64_RSC_PL_MASK) >> IA64_RSC_PL_SHIFT; + xen_info.kernel_rpl = rpl; +} + +/*************************************************************************** + * pv_init_ops + * initialization hooks. + */ + +static void +xen_panic_hypercall(struct unw_frame_info *info, void *arg) +{ + current->thread.ksp = (__u64)info->sw - 16; + HYPERVISOR_shutdown(SHUTDOWN_crash); + /* we're never actually going to get here... */ +} + +static int +xen_panic_event(struct notifier_block *this, unsigned long event, void *ptr) +{ + unw_init_running(xen_panic_hypercall, NULL); + /* we're never actually going to get here... */ + return NOTIFY_DONE; +} + +static struct notifier_block xen_panic_block = { + xen_panic_event, NULL, 0 /* try to go last */ +}; + +static void xen_pm_power_off(void) +{ + local_irq_disable(); + HYPERVISOR_shutdown(SHUTDOWN_poweroff); +} + +static void __init +xen_banner(void) +{ + printk(KERN_INFO + "Running on Xen! pl = %d start_info_pfn=0x%lx nr_pages=%ld " + "flags=0x%x\n", + xen_info.kernel_rpl, + HYPERVISOR_shared_info->arch.start_info_pfn, + xen_start_info->nr_pages, xen_start_info->flags); +} + +static int __init +xen_reserve_memory(struct rsvd_region *region) +{ + region->start = (unsigned long)__va( + (HYPERVISOR_shared_info->arch.start_info_pfn << PAGE_SHIFT)); + region->end = region->start + PAGE_SIZE; + return 1; +} + +static void __init +xen_arch_setup_early(void) +{ + struct shared_info *s; + BUG_ON(!xen_pv_domain()); + + s = HYPERVISOR_shared_info; + xen_start_info = __va(s->arch.start_info_pfn << PAGE_SHIFT); + + /* Must be done before any hypercall. */ + xencomm_initialize(); + + xen_setup_features(); + /* Register a call for panic conditions. */ + atomic_notifier_chain_register(&panic_notifier_list, + &xen_panic_block); + pm_power_off = xen_pm_power_off; + + xen_ia64_enable_opt_feature(); +} + +static void __init +xen_arch_setup_console(char **cmdline_p) +{ + add_preferred_console("xenboot", 0, NULL); + add_preferred_console("tty", 0, NULL); + /* use hvc_xen */ + add_preferred_console("hvc", 0, NULL); + +#if !defined(CONFIG_VT) || !defined(CONFIG_DUMMY_CONSOLE) + conswitchp = NULL; +#endif +} + +static int __init +xen_arch_setup_nomca(void) +{ + return 1; +} + +static void __init +xen_post_smp_prepare_boot_cpu(void) +{ + xen_setup_vcpu_info_placement(); +} + +static const struct pv_init_ops xen_init_ops __initdata = { + .banner = xen_banner, + + .reserve_memory = xen_reserve_memory, + + .arch_setup_early = xen_arch_setup_early, + .arch_setup_console = xen_arch_setup_console, + .arch_setup_nomca = xen_arch_setup_nomca, + + .post_smp_prepare_boot_cpu = xen_post_smp_prepare_boot_cpu, +}; + +/*************************************************************************** + * pv_cpu_ops + * intrinsics hooks. + */ + +static void xen_setreg(int regnum, unsigned long val) +{ + switch (regnum) { + case _IA64_REG_AR_KR0 ... _IA64_REG_AR_KR7: + xen_set_kr(regnum - _IA64_REG_AR_KR0, val); + break; +#ifdef CONFIG_IA32_SUPPORT + case _IA64_REG_AR_EFLAG: + xen_set_eflag(val); + break; +#endif + case _IA64_REG_CR_TPR: + xen_set_tpr(val); + break; + case _IA64_REG_CR_ITM: + xen_set_itm(val); + break; + case _IA64_REG_CR_EOI: + xen_eoi(val); + break; + default: + ia64_native_setreg_func(regnum, val); + break; + } +} + +static unsigned long xen_getreg(int regnum) +{ + unsigned long res; + + switch (regnum) { + case _IA64_REG_PSR: + res = xen_get_psr(); + break; +#ifdef CONFIG_IA32_SUPPORT + case _IA64_REG_AR_EFLAG: + res = xen_get_eflag(); + break; +#endif + case _IA64_REG_CR_IVR: + res = xen_get_ivr(); + break; + case _IA64_REG_CR_TPR: + res = xen_get_tpr(); + break; + default: + res = ia64_native_getreg_func(regnum); + break; + } + return res; +} + +/* turning on interrupts is a bit more complicated.. write to the + * memory-mapped virtual psr.i bit first (to avoid race condition), + * then if any interrupts were pending, we have to execute a hyperprivop + * to ensure the pending interrupt gets delivered; else we're done! */ +static void +xen_ssm_i(void) +{ + int old = xen_get_virtual_psr_i(); + xen_set_virtual_psr_i(1); + barrier(); + if (!old && xen_get_virtual_pend()) + xen_hyper_ssm_i(); +} + +/* turning off interrupts can be paravirtualized simply by writing + * to a memory-mapped virtual psr.i bit (implemented as a 16-bit bool) */ +static void +xen_rsm_i(void) +{ + xen_set_virtual_psr_i(0); + barrier(); +} + +static unsigned long +xen_get_psr_i(void) +{ + return xen_get_virtual_psr_i() ? IA64_PSR_I : 0; +} + +static void +xen_intrin_local_irq_restore(unsigned long mask) +{ + if (mask & IA64_PSR_I) + xen_ssm_i(); + else + xen_rsm_i(); +} + +static const struct pv_cpu_ops xen_cpu_ops __initdata = { + .fc = xen_fc, + .thash = xen_thash, + .get_cpuid = xen_get_cpuid, + .get_pmd = xen_get_pmd, + .getreg = xen_getreg, + .setreg = xen_setreg, + .ptcga = xen_ptcga, + .get_rr = xen_get_rr, + .set_rr = xen_set_rr, + .set_rr0_to_rr4 = xen_set_rr0_to_rr4, + .ssm_i = xen_ssm_i, + .rsm_i = xen_rsm_i, + .get_psr_i = xen_get_psr_i, + .intrin_local_irq_restore + = xen_intrin_local_irq_restore, +}; + +/****************************************************************************** + * replacement of hand written assembly codes. + */ + +extern char xen_switch_to; +extern char xen_leave_syscall; +extern char xen_work_processed_syscall; +extern char xen_leave_kernel; + +const struct pv_cpu_asm_switch xen_cpu_asm_switch = { + .switch_to = (unsigned long)&xen_switch_to, + .leave_syscall = (unsigned long)&xen_leave_syscall, + .work_processed_syscall = (unsigned long)&xen_work_processed_syscall, + .leave_kernel = (unsigned long)&xen_leave_kernel, +}; + +/*************************************************************************** + * pv_iosapic_ops + * iosapic read/write hooks. + */ +static void +xen_pcat_compat_init(void) +{ + /* nothing */ +} + +static struct irq_chip* +xen_iosapic_get_irq_chip(unsigned long trigger) +{ + return NULL; +} + +static unsigned int +xen_iosapic_read(char __iomem *iosapic, unsigned int reg) +{ + struct physdev_apic apic_op; + int ret; + + apic_op.apic_physbase = (unsigned long)iosapic - + __IA64_UNCACHED_OFFSET; + apic_op.reg = reg; + ret = HYPERVISOR_physdev_op(PHYSDEVOP_apic_read, &apic_op); + if (ret) + return ret; + return apic_op.value; +} + +static void +xen_iosapic_write(char __iomem *iosapic, unsigned int reg, u32 val) +{ + struct physdev_apic apic_op; + + apic_op.apic_physbase = (unsigned long)iosapic - + __IA64_UNCACHED_OFFSET; + apic_op.reg = reg; + apic_op.value = val; + HYPERVISOR_physdev_op(PHYSDEVOP_apic_write, &apic_op); +} + +static const struct pv_iosapic_ops xen_iosapic_ops __initdata = { + .pcat_compat_init = xen_pcat_compat_init, + .__get_irq_chip = xen_iosapic_get_irq_chip, + + .__read = xen_iosapic_read, + .__write = xen_iosapic_write, +}; + +/*************************************************************************** + * pv_ops initialization + */ + +void __init +xen_setup_pv_ops(void) +{ + xen_info_init(); + pv_info = xen_info; + pv_init_ops = xen_init_ops; + pv_cpu_ops = xen_cpu_ops; + pv_iosapic_ops = xen_iosapic_ops; + pv_irq_ops = xen_irq_ops; + pv_time_ops = xen_time_ops; + + paravirt_cpu_asm_init(&xen_cpu_asm_switch); +} diff --git a/arch/ia64/xen/xencomm.c b/arch/ia64/xen/xencomm.c new file mode 100644 index 0000000..1f5d7ac --- /dev/null +++ b/arch/ia64/xen/xencomm.c @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2006 Hollis Blanchard <hollisb@us.ibm.com>, IBM Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/mm.h> + +static unsigned long kernel_virtual_offset; +static int is_xencomm_initialized; + +/* for xen early printk. It uses console io hypercall which uses xencomm. + * However early printk may use it before xencomm initialization. + */ +int +xencomm_is_initialized(void) +{ + return is_xencomm_initialized; +} + +void +xencomm_initialize(void) +{ + kernel_virtual_offset = KERNEL_START - ia64_tpa(KERNEL_START); + is_xencomm_initialized = 1; +} + +/* Translate virtual address to physical address. */ +unsigned long +xencomm_vtop(unsigned long vaddr) +{ + struct page *page; + struct vm_area_struct *vma; + + if (vaddr == 0) + return 0UL; + + if (REGION_NUMBER(vaddr) == 5) { + pgd_t *pgd; + pud_t *pud; + pmd_t *pmd; + pte_t *ptep; + + /* On ia64, TASK_SIZE refers to current. It is not initialized + during boot. + Furthermore the kernel is relocatable and __pa() doesn't + work on addresses. */ + if (vaddr >= KERNEL_START + && vaddr < (KERNEL_START + KERNEL_TR_PAGE_SIZE)) + return vaddr - kernel_virtual_offset; + + /* In kernel area -- virtually mapped. */ + pgd = pgd_offset_k(vaddr); + if (pgd_none(*pgd) || pgd_bad(*pgd)) + return ~0UL; + + pud = pud_offset(pgd, vaddr); + if (pud_none(*pud) || pud_bad(*pud)) + return ~0UL; + + pmd = pmd_offset(pud, vaddr); + if (pmd_none(*pmd) || pmd_bad(*pmd)) + return ~0UL; + + ptep = pte_offset_kernel(pmd, vaddr); + if (!ptep) + return ~0UL; + + return (pte_val(*ptep) & _PFN_MASK) | (vaddr & ~PAGE_MASK); + } + + if (vaddr > TASK_SIZE) { + /* percpu variables */ + if (REGION_NUMBER(vaddr) == 7 && + REGION_OFFSET(vaddr) >= (1ULL << IA64_MAX_PHYS_BITS)) + ia64_tpa(vaddr); + + /* kernel address */ + return __pa(vaddr); + } + + /* XXX double-check (lack of) locking */ + vma = find_extend_vma(current->mm, vaddr); + if (!vma) + return ~0UL; + + /* We assume the page is modified. */ + page = follow_page(vma, vaddr, FOLL_WRITE | FOLL_TOUCH); + if (!page) + return ~0UL; + + return (page_to_pfn(page) << PAGE_SHIFT) | (vaddr & ~PAGE_MASK); +} diff --git a/arch/ia64/xen/xenivt.S b/arch/ia64/xen/xenivt.S new file mode 100644 index 0000000..3e71d50 --- /dev/null +++ b/arch/ia64/xen/xenivt.S @@ -0,0 +1,52 @@ +/* + * arch/ia64/xen/ivt.S + * + * Copyright (C) 2005 Hewlett-Packard Co + * Dan Magenheimer <dan.magenheimer@hp.com> + * + * Copyright (c) 2008 Isaku Yamahata <yamahata at valinux co jp> + * VA Linux Systems Japan K.K. + * pv_ops. + */ + +#include <asm/asmmacro.h> +#include <asm/kregs.h> +#include <asm/pgtable.h> + +#include "../kernel/minstate.h" + + .section .text,"ax" +GLOBAL_ENTRY(xen_event_callback) + mov r31=pr // prepare to save predicates + ;; + SAVE_MIN_WITH_COVER // uses r31; defines r2 and r3 + ;; + movl r3=XSI_PSR_IC + mov r14=1 + ;; + st4 [r3]=r14 + ;; + adds r3=8,r2 // set up second base pointer for SAVE_REST + srlz.i // ensure everybody knows psr.ic is back on + ;; + SAVE_REST + ;; +1: + alloc r14=ar.pfs,0,0,1,0 // must be first in an insn group + add out0=16,sp // pass pointer to pt_regs as first arg + ;; + br.call.sptk.many b0=xen_evtchn_do_upcall + ;; + movl r20=XSI_PSR_I_ADDR + ;; + ld8 r20=[r20] + ;; + adds r20=-1,r20 // vcpu_info->evtchn_upcall_pending + ;; + ld1 r20=[r20] + ;; + cmp.ne p6,p0=r20,r0 // if there are pending events, + (p6) br.spnt.few 1b // call evtchn_do_upcall again. + br.sptk.many xen_leave_kernel // we know ia64_leave_kernel is + // paravirtualized as xen_leave_kernel +END(xen_event_callback) diff --git a/arch/ia64/xen/xensetup.S b/arch/ia64/xen/xensetup.S new file mode 100644 index 0000000..28fed1f --- /dev/null +++ b/arch/ia64/xen/xensetup.S @@ -0,0 +1,83 @@ +/* + * Support routines for Xen + * + * Copyright (C) 2005 Dan Magenheimer <dan.magenheimer@hp.com> + */ + +#include <asm/processor.h> +#include <asm/asmmacro.h> +#include <asm/pgtable.h> +#include <asm/system.h> +#include <asm/paravirt.h> +#include <asm/xen/privop.h> +#include <linux/elfnote.h> +#include <linux/init.h> +#include <xen/interface/elfnote.h> + + .section .data.read_mostly + .align 8 + .global xen_domain_type +xen_domain_type: + data4 XEN_NATIVE_ASM + .previous + + __INIT +ENTRY(startup_xen) + // Calculate load offset. + // The constant, LOAD_OFFSET, can't be used because the boot + // loader doesn't always load to the LMA specified by the vmlinux.lds. + mov r9=ip // must be the first instruction to make sure + // that r9 = the physical address of startup_xen. + // Usually r9 = startup_xen - LOAD_OFFSET + movl r8=startup_xen + ;; + sub r9=r9,r8 // Usually r9 = -LOAD_OFFSET. + + mov r10=PARAVIRT_HYPERVISOR_TYPE_XEN + movl r11=_start + ;; + add r11=r11,r9 + movl r8=hypervisor_type + ;; + add r8=r8,r9 + mov b0=r11 + ;; + st8 [r8]=r10 + br.cond.sptk.many b0 + ;; +END(startup_xen) + + ELFNOTE(Xen, XEN_ELFNOTE_GUEST_OS, .asciz "linux") + ELFNOTE(Xen, XEN_ELFNOTE_GUEST_VERSION, .asciz "2.6") + ELFNOTE(Xen, XEN_ELFNOTE_XEN_VERSION, .asciz "xen-3.0") + ELFNOTE(Xen, XEN_ELFNOTE_ENTRY, data8.ua startup_xen - LOAD_OFFSET) + +#define isBP p3 // are we the Bootstrap Processor? + + .text + +GLOBAL_ENTRY(xen_setup_hook) + mov r8=XEN_PV_DOMAIN_ASM +(isBP) movl r9=xen_domain_type;; +(isBP) st4 [r9]=r8 + movl r10=xen_ivt;; + + mov cr.iva=r10 + + /* Set xsi base. */ +#define FW_HYPERCALL_SET_SHARED_INFO_VA 0x600 +(isBP) mov r2=FW_HYPERCALL_SET_SHARED_INFO_VA +(isBP) movl r28=XSI_BASE;; +(isBP) break 0x1000;; + + /* setup pv_ops */ +(isBP) mov r4=rp + ;; +(isBP) br.call.sptk.many rp=xen_setup_pv_ops + ;; +(isBP) mov rp=r4 + ;; + + br.ret.sptk.many rp + ;; +END(xen_setup_hook) |