diff options
Diffstat (limited to 'arch')
131 files changed, 3026 insertions, 927 deletions
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index cb782ac1c35d..c51e6ce42e7a 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
| @@ -139,9 +139,11 @@ config PPC | |||
| 139 | select ARCH_HAS_ELF_RANDOMIZE | 139 | select ARCH_HAS_ELF_RANDOMIZE |
| 140 | select ARCH_HAS_FORTIFY_SOURCE | 140 | select ARCH_HAS_FORTIFY_SOURCE |
| 141 | select ARCH_HAS_GCOV_PROFILE_ALL | 141 | select ARCH_HAS_GCOV_PROFILE_ALL |
| 142 | select ARCH_HAS_PMEM_API if PPC64 | ||
| 142 | select ARCH_HAS_SCALED_CPUTIME if VIRT_CPU_ACCOUNTING_NATIVE | 143 | select ARCH_HAS_SCALED_CPUTIME if VIRT_CPU_ACCOUNTING_NATIVE |
| 143 | select ARCH_HAS_SG_CHAIN | 144 | select ARCH_HAS_SG_CHAIN |
| 144 | select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST | 145 | select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST |
| 146 | select ARCH_HAS_UACCESS_FLUSHCACHE if PPC64 | ||
| 145 | select ARCH_HAS_UBSAN_SANITIZE_ALL | 147 | select ARCH_HAS_UBSAN_SANITIZE_ALL |
| 146 | select ARCH_HAS_ZONE_DEVICE if PPC_BOOK3S_64 | 148 | select ARCH_HAS_ZONE_DEVICE if PPC_BOOK3S_64 |
| 147 | select ARCH_HAVE_NMI_SAFE_CMPXCHG | 149 | select ARCH_HAVE_NMI_SAFE_CMPXCHG |
| @@ -335,7 +337,7 @@ config PPC_OF_PLATFORM_PCI | |||
| 335 | default n | 337 | default n |
| 336 | 338 | ||
| 337 | config ARCH_SUPPORTS_DEBUG_PAGEALLOC | 339 | config ARCH_SUPPORTS_DEBUG_PAGEALLOC |
| 338 | depends on PPC32 || PPC_STD_MMU_64 | 340 | depends on PPC32 || PPC_BOOK3S_64 |
| 339 | def_bool y | 341 | def_bool y |
| 340 | 342 | ||
| 341 | config ARCH_SUPPORTS_UPROBES | 343 | config ARCH_SUPPORTS_UPROBES |
| @@ -722,7 +724,7 @@ config PPC_16K_PAGES | |||
| 722 | 724 | ||
| 723 | config PPC_64K_PAGES | 725 | config PPC_64K_PAGES |
| 724 | bool "64k page size" | 726 | bool "64k page size" |
| 725 | depends on !PPC_FSL_BOOK3E && (44x || PPC_STD_MMU_64 || PPC_BOOK3E_64) | 727 | depends on !PPC_FSL_BOOK3E && (44x || PPC_BOOK3S_64 || PPC_BOOK3E_64) |
| 726 | select HAVE_ARCH_SOFT_DIRTY if PPC_BOOK3S_64 | 728 | select HAVE_ARCH_SOFT_DIRTY if PPC_BOOK3S_64 |
| 727 | 729 | ||
| 728 | config PPC_256K_PAGES | 730 | config PPC_256K_PAGES |
| @@ -781,7 +783,7 @@ config FORCE_MAX_ZONEORDER | |||
| 781 | 783 | ||
| 782 | config PPC_SUBPAGE_PROT | 784 | config PPC_SUBPAGE_PROT |
| 783 | bool "Support setting protections for 4k subpages" | 785 | bool "Support setting protections for 4k subpages" |
| 784 | depends on PPC_STD_MMU_64 && PPC_64K_PAGES | 786 | depends on PPC_BOOK3S_64 && PPC_64K_PAGES |
| 785 | help | 787 | help |
| 786 | This option adds support for a system call to allow user programs | 788 | This option adds support for a system call to allow user programs |
| 787 | to set access permissions (read/write, readonly, or no access) | 789 | to set access permissions (read/write, readonly, or no access) |
diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug index be1c8c5beb61..657c33cd4eee 100644 --- a/arch/powerpc/Kconfig.debug +++ b/arch/powerpc/Kconfig.debug | |||
| @@ -370,4 +370,10 @@ config PPC_HTDUMP | |||
| 370 | def_bool y | 370 | def_bool y |
| 371 | depends on PPC_PTDUMP && PPC_BOOK3S | 371 | depends on PPC_PTDUMP && PPC_BOOK3S |
| 372 | 372 | ||
| 373 | config PPC_FAST_ENDIAN_SWITCH | ||
| 374 | bool "Deprecated fast endian-switch syscall" | ||
| 375 | depends on DEBUG_KERNEL && PPC_BOOK3S_64 | ||
| 376 | help | ||
| 377 | If you're unsure what this is, say N. | ||
| 378 | |||
| 373 | endmenu | 379 | endmenu |
diff --git a/arch/powerpc/boot/dts/acadia.dts b/arch/powerpc/boot/dts/acadia.dts index 57291f61ffe7..86266159521e 100644 --- a/arch/powerpc/boot/dts/acadia.dts +++ b/arch/powerpc/boot/dts/acadia.dts | |||
| @@ -183,7 +183,7 @@ | |||
| 183 | usb@ef603000 { | 183 | usb@ef603000 { |
| 184 | compatible = "ohci-be"; | 184 | compatible = "ohci-be"; |
| 185 | reg = <0xef603000 0x80>; | 185 | reg = <0xef603000 0x80>; |
| 186 | interrupts-parent = <&UIC0>; | 186 | interrupt-parent = <&UIC0>; |
| 187 | interrupts = <0xd 0x4 0xe 0x4>; | 187 | interrupts = <0xd 0x4 0xe 0x4>; |
| 188 | }; | 188 | }; |
| 189 | 189 | ||
diff --git a/arch/powerpc/configs/powernv_defconfig b/arch/powerpc/configs/powernv_defconfig index caee834760d2..4891bbed6258 100644 --- a/arch/powerpc/configs/powernv_defconfig +++ b/arch/powerpc/configs/powernv_defconfig | |||
| @@ -192,6 +192,7 @@ CONFIG_IPMI_DEVICE_INTERFACE=y | |||
| 192 | CONFIG_IPMI_POWERNV=y | 192 | CONFIG_IPMI_POWERNV=y |
| 193 | CONFIG_RAW_DRIVER=y | 193 | CONFIG_RAW_DRIVER=y |
| 194 | CONFIG_MAX_RAW_DEVS=1024 | 194 | CONFIG_MAX_RAW_DEVS=1024 |
| 195 | CONFIG_I2C_CHARDEV=y | ||
| 195 | CONFIG_DRM=y | 196 | CONFIG_DRM=y |
| 196 | CONFIG_DRM_AST=y | 197 | CONFIG_DRM_AST=y |
| 197 | CONFIG_FIRMWARE_EDID=y | 198 | CONFIG_FIRMWARE_EDID=y |
| @@ -295,6 +296,7 @@ CONFIG_FUNCTION_GRAPH_TRACER=y | |||
| 295 | CONFIG_SCHED_TRACER=y | 296 | CONFIG_SCHED_TRACER=y |
| 296 | CONFIG_FTRACE_SYSCALLS=y | 297 | CONFIG_FTRACE_SYSCALLS=y |
| 297 | CONFIG_BLK_DEV_IO_TRACE=y | 298 | CONFIG_BLK_DEV_IO_TRACE=y |
| 299 | CONFIG_PPC_EMULATED_STATS=y | ||
| 298 | CONFIG_CODE_PATCHING_SELFTEST=y | 300 | CONFIG_CODE_PATCHING_SELFTEST=y |
| 299 | CONFIG_FTR_FIXUP_SELFTEST=y | 301 | CONFIG_FTR_FIXUP_SELFTEST=y |
| 300 | CONFIG_MSI_BITMAP_SELFTEST=y | 302 | CONFIG_MSI_BITMAP_SELFTEST=y |
diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig index 3d935969e5a2..bde2cd1005a2 100644 --- a/arch/powerpc/configs/pseries_defconfig +++ b/arch/powerpc/configs/pseries_defconfig | |||
| @@ -193,6 +193,7 @@ CONFIG_VIRTIO_CONSOLE=m | |||
| 193 | CONFIG_IBM_BSR=m | 193 | CONFIG_IBM_BSR=m |
| 194 | CONFIG_RAW_DRIVER=y | 194 | CONFIG_RAW_DRIVER=y |
| 195 | CONFIG_MAX_RAW_DEVS=1024 | 195 | CONFIG_MAX_RAW_DEVS=1024 |
| 196 | CONFIG_I2C_CHARDEV=y | ||
| 196 | CONFIG_FB=y | 197 | CONFIG_FB=y |
| 197 | CONFIG_FIRMWARE_EDID=y | 198 | CONFIG_FIRMWARE_EDID=y |
| 198 | CONFIG_FB_OF=y | 199 | CONFIG_FB_OF=y |
diff --git a/arch/powerpc/configs/skiroot_defconfig b/arch/powerpc/configs/skiroot_defconfig new file mode 100644 index 000000000000..6bd5e7261335 --- /dev/null +++ b/arch/powerpc/configs/skiroot_defconfig | |||
| @@ -0,0 +1,232 @@ | |||
| 1 | CONFIG_PPC64=y | ||
| 2 | CONFIG_ALTIVEC=y | ||
| 3 | CONFIG_VSX=y | ||
| 4 | CONFIG_NR_CPUS=2048 | ||
| 5 | CONFIG_CPU_LITTLE_ENDIAN=y | ||
| 6 | # CONFIG_SWAP is not set | ||
| 7 | CONFIG_SYSVIPC=y | ||
| 8 | CONFIG_POSIX_MQUEUE=y | ||
| 9 | # CONFIG_CROSS_MEMORY_ATTACH is not set | ||
| 10 | CONFIG_NO_HZ=y | ||
| 11 | CONFIG_HIGH_RES_TIMERS=y | ||
| 12 | CONFIG_TASKSTATS=y | ||
| 13 | CONFIG_TASK_DELAY_ACCT=y | ||
| 14 | CONFIG_TASK_XACCT=y | ||
| 15 | CONFIG_TASK_IO_ACCOUNTING=y | ||
| 16 | CONFIG_IKCONFIG=y | ||
| 17 | CONFIG_IKCONFIG_PROC=y | ||
| 18 | CONFIG_LOG_BUF_SHIFT=20 | ||
| 19 | CONFIG_RELAY=y | ||
| 20 | CONFIG_BLK_DEV_INITRD=y | ||
| 21 | # CONFIG_RD_GZIP is not set | ||
| 22 | # CONFIG_RD_BZIP2 is not set | ||
| 23 | # CONFIG_RD_LZMA is not set | ||
| 24 | # CONFIG_RD_LZO is not set | ||
| 25 | # CONFIG_RD_LZ4 is not set | ||
| 26 | CONFIG_CC_OPTIMIZE_FOR_SIZE=y | ||
| 27 | CONFIG_PERF_EVENTS=y | ||
| 28 | # CONFIG_COMPAT_BRK is not set | ||
| 29 | CONFIG_JUMP_LABEL=y | ||
| 30 | CONFIG_STRICT_KERNEL_RWX=y | ||
| 31 | CONFIG_MODULES=y | ||
| 32 | CONFIG_MODULE_UNLOAD=y | ||
| 33 | CONFIG_MODULE_SIG=y | ||
| 34 | CONFIG_MODULE_SIG_FORCE=y | ||
| 35 | CONFIG_MODULE_SIG_SHA512=y | ||
| 36 | CONFIG_PARTITION_ADVANCED=y | ||
| 37 | # CONFIG_IOSCHED_DEADLINE is not set | ||
| 38 | # CONFIG_PPC_PSERIES is not set | ||
| 39 | CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y | ||
| 40 | CONFIG_CPU_IDLE=y | ||
| 41 | CONFIG_HZ_100=y | ||
| 42 | CONFIG_KEXEC=y | ||
| 43 | CONFIG_IRQ_ALL_CPUS=y | ||
| 44 | CONFIG_NUMA=y | ||
| 45 | # CONFIG_COMPACTION is not set | ||
| 46 | # CONFIG_MIGRATION is not set | ||
| 47 | # CONFIG_BOUNCE is not set | ||
| 48 | CONFIG_PPC_64K_PAGES=y | ||
| 49 | CONFIG_SCHED_SMT=y | ||
| 50 | CONFIG_CMDLINE_BOOL=y | ||
| 51 | CONFIG_CMDLINE="console=tty0 console=hvc0 powersave=off" | ||
| 52 | # CONFIG_SECCOMP is not set | ||
| 53 | CONFIG_NET=y | ||
| 54 | CONFIG_PACKET=y | ||
| 55 | CONFIG_UNIX=y | ||
| 56 | CONFIG_INET=y | ||
| 57 | CONFIG_IP_MULTICAST=y | ||
| 58 | CONFIG_NET_IPIP=y | ||
| 59 | CONFIG_SYN_COOKIES=y | ||
| 60 | # CONFIG_INET_XFRM_MODE_TRANSPORT is not set | ||
| 61 | # CONFIG_INET_XFRM_MODE_TUNNEL is not set | ||
| 62 | # CONFIG_INET_XFRM_MODE_BEET is not set | ||
| 63 | # CONFIG_IPV6 is not set | ||
| 64 | CONFIG_DNS_RESOLVER=y | ||
| 65 | # CONFIG_WIRELESS is not set | ||
| 66 | CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" | ||
| 67 | CONFIG_DEVTMPFS=y | ||
| 68 | CONFIG_DEVTMPFS_MOUNT=y | ||
| 69 | CONFIG_MTD=m | ||
| 70 | CONFIG_MTD_POWERNV_FLASH=m | ||
| 71 | CONFIG_BLK_DEV_LOOP=y | ||
| 72 | CONFIG_BLK_DEV_RAM=y | ||
| 73 | CONFIG_BLK_DEV_RAM_SIZE=65536 | ||
| 74 | CONFIG_VIRTIO_BLK=m | ||
| 75 | CONFIG_BLK_DEV_NVME=m | ||
| 76 | CONFIG_EEPROM_AT24=y | ||
| 77 | # CONFIG_CXL is not set | ||
| 78 | CONFIG_BLK_DEV_SD=m | ||
| 79 | CONFIG_BLK_DEV_SR=m | ||
| 80 | CONFIG_BLK_DEV_SR_VENDOR=y | ||
| 81 | CONFIG_CHR_DEV_SG=m | ||
| 82 | CONFIG_SCSI_CONSTANTS=y | ||
| 83 | CONFIG_SCSI_SCAN_ASYNC=y | ||
| 84 | CONFIG_SCSI_FC_ATTRS=y | ||
| 85 | CONFIG_SCSI_CXGB3_ISCSI=m | ||
| 86 | CONFIG_SCSI_CXGB4_ISCSI=m | ||
| 87 | CONFIG_SCSI_BNX2_ISCSI=m | ||
| 88 | CONFIG_BE2ISCSI=m | ||
| 89 | CONFIG_SCSI_AACRAID=m | ||
| 90 | CONFIG_MEGARAID_NEWGEN=y | ||
| 91 | CONFIG_MEGARAID_MM=m | ||
| 92 | CONFIG_MEGARAID_MAILBOX=m | ||
| 93 | CONFIG_MEGARAID_SAS=m | ||
| 94 | CONFIG_SCSI_MPT2SAS=m | ||
| 95 | CONFIG_SCSI_IPR=m | ||
| 96 | # CONFIG_SCSI_IPR_TRACE is not set | ||
| 97 | # CONFIG_SCSI_IPR_DUMP is not set | ||
| 98 | CONFIG_SCSI_QLA_FC=m | ||
| 99 | CONFIG_SCSI_QLA_ISCSI=m | ||
| 100 | CONFIG_SCSI_LPFC=m | ||
| 101 | CONFIG_SCSI_VIRTIO=m | ||
| 102 | CONFIG_SCSI_DH=y | ||
| 103 | CONFIG_SCSI_DH_ALUA=m | ||
| 104 | CONFIG_ATA=y | ||
| 105 | CONFIG_SATA_AHCI=y | ||
| 106 | # CONFIG_ATA_SFF is not set | ||
| 107 | CONFIG_MD=y | ||
| 108 | CONFIG_BLK_DEV_MD=m | ||
| 109 | CONFIG_MD_LINEAR=m | ||
| 110 | CONFIG_MD_RAID0=m | ||
| 111 | CONFIG_MD_RAID1=m | ||
| 112 | CONFIG_MD_RAID10=m | ||
| 113 | CONFIG_MD_RAID456=m | ||
| 114 | CONFIG_MD_MULTIPATH=m | ||
| 115 | CONFIG_MD_FAULTY=m | ||
| 116 | CONFIG_BLK_DEV_DM=m | ||
| 117 | CONFIG_DM_CRYPT=m | ||
| 118 | CONFIG_DM_SNAPSHOT=m | ||
| 119 | CONFIG_DM_MIRROR=m | ||
| 120 | CONFIG_DM_ZERO=m | ||
| 121 | CONFIG_DM_MULTIPATH=m | ||
| 122 | CONFIG_ACENIC=m | ||
| 123 | CONFIG_ACENIC_OMIT_TIGON_I=y | ||
| 124 | CONFIG_TIGON3=y | ||
| 125 | CONFIG_BNX2X=m | ||
| 126 | CONFIG_CHELSIO_T1=y | ||
| 127 | CONFIG_BE2NET=m | ||
| 128 | CONFIG_S2IO=m | ||
| 129 | CONFIG_E100=m | ||
| 130 | CONFIG_E1000=m | ||
| 131 | CONFIG_E1000E=m | ||
| 132 | CONFIG_IXGB=m | ||
| 133 | CONFIG_IXGBE=m | ||
| 134 | CONFIG_MLX4_EN=m | ||
| 135 | CONFIG_MLX5_CORE=m | ||
| 136 | CONFIG_MLX5_CORE_EN=y | ||
| 137 | CONFIG_MYRI10GE=m | ||
| 138 | CONFIG_QLGE=m | ||
| 139 | CONFIG_NETXEN_NIC=m | ||
| 140 | CONFIG_SFC=m | ||
| 141 | # CONFIG_USB_NET_DRIVERS is not set | ||
| 142 | # CONFIG_WLAN is not set | ||
| 143 | CONFIG_INPUT_EVDEV=y | ||
| 144 | CONFIG_INPUT_MISC=y | ||
| 145 | # CONFIG_SERIO_SERPORT is not set | ||
| 146 | # CONFIG_DEVMEM is not set | ||
| 147 | CONFIG_SERIAL_8250=y | ||
| 148 | CONFIG_SERIAL_8250_CONSOLE=y | ||
| 149 | CONFIG_IPMI_HANDLER=y | ||
| 150 | CONFIG_IPMI_DEVICE_INTERFACE=y | ||
| 151 | CONFIG_IPMI_POWERNV=y | ||
| 152 | CONFIG_HW_RANDOM=y | ||
| 153 | CONFIG_TCG_TIS_I2C_NUVOTON=y | ||
| 154 | # CONFIG_I2C_COMPAT is not set | ||
| 155 | CONFIG_I2C_CHARDEV=y | ||
| 156 | # CONFIG_I2C_HELPER_AUTO is not set | ||
| 157 | CONFIG_DRM=y | ||
| 158 | CONFIG_DRM_RADEON=y | ||
| 159 | CONFIG_DRM_AST=m | ||
| 160 | CONFIG_FIRMWARE_EDID=y | ||
| 161 | CONFIG_FB_MODE_HELPERS=y | ||
| 162 | CONFIG_FB_OF=y | ||
| 163 | CONFIG_FB_MATROX=y | ||
| 164 | CONFIG_FB_MATROX_MILLENIUM=y | ||
| 165 | CONFIG_FB_MATROX_MYSTIQUE=y | ||
| 166 | CONFIG_FB_MATROX_G=y | ||
| 167 | # CONFIG_LCD_CLASS_DEVICE is not set | ||
| 168 | # CONFIG_BACKLIGHT_GENERIC is not set | ||
| 169 | # CONFIG_VGA_CONSOLE is not set | ||
| 170 | CONFIG_LOGO=y | ||
| 171 | # CONFIG_LOGO_LINUX_MONO is not set | ||
| 172 | # CONFIG_LOGO_LINUX_VGA16 is not set | ||
| 173 | CONFIG_USB_HIDDEV=y | ||
| 174 | CONFIG_USB=y | ||
| 175 | CONFIG_USB_MON=y | ||
| 176 | CONFIG_USB_XHCI_HCD=y | ||
| 177 | CONFIG_USB_EHCI_HCD=y | ||
| 178 | # CONFIG_USB_EHCI_HCD_PPC_OF is not set | ||
| 179 | CONFIG_USB_OHCI_HCD=y | ||
| 180 | CONFIG_USB_STORAGE=y | ||
| 181 | CONFIG_RTC_CLASS=y | ||
| 182 | CONFIG_RTC_DRV_GENERIC=m | ||
| 183 | CONFIG_VIRT_DRIVERS=y | ||
| 184 | CONFIG_VIRTIO_PCI=y | ||
| 185 | # CONFIG_IOMMU_SUPPORT is not set | ||
| 186 | CONFIG_EXT4_FS=m | ||
| 187 | CONFIG_EXT4_FS_POSIX_ACL=y | ||
| 188 | CONFIG_EXT4_FS_SECURITY=y | ||
| 189 | CONFIG_XFS_FS=m | ||
| 190 | CONFIG_XFS_POSIX_ACL=y | ||
| 191 | CONFIG_BTRFS_FS=m | ||
| 192 | CONFIG_BTRFS_FS_POSIX_ACL=y | ||
| 193 | CONFIG_ISO9660_FS=m | ||
| 194 | CONFIG_UDF_FS=m | ||
| 195 | CONFIG_MSDOS_FS=m | ||
| 196 | CONFIG_VFAT_FS=m | ||
| 197 | CONFIG_PROC_KCORE=y | ||
| 198 | CONFIG_TMPFS=y | ||
| 199 | CONFIG_TMPFS_POSIX_ACL=y | ||
| 200 | # CONFIG_MISC_FILESYSTEMS is not set | ||
| 201 | # CONFIG_NETWORK_FILESYSTEMS is not set | ||
| 202 | CONFIG_NLS_DEFAULT="utf8" | ||
| 203 | CONFIG_NLS_CODEPAGE_437=y | ||
| 204 | CONFIG_NLS_ASCII=y | ||
| 205 | CONFIG_NLS_ISO8859_1=y | ||
| 206 | CONFIG_NLS_UTF8=y | ||
| 207 | CONFIG_CRC16=y | ||
| 208 | CONFIG_CRC_ITU_T=y | ||
| 209 | CONFIG_LIBCRC32C=y | ||
| 210 | CONFIG_PRINTK_TIME=y | ||
| 211 | CONFIG_MAGIC_SYSRQ=y | ||
| 212 | CONFIG_DEBUG_KERNEL=y | ||
| 213 | CONFIG_DEBUG_STACKOVERFLOW=y | ||
| 214 | CONFIG_SOFTLOCKUP_DETECTOR=y | ||
| 215 | CONFIG_HARDLOCKUP_DETECTOR=y | ||
| 216 | CONFIG_BOOTPARAM_HARDLOCKUP_PANIC=y | ||
| 217 | CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y | ||
| 218 | CONFIG_WQ_WATCHDOG=y | ||
| 219 | CONFIG_SCHEDSTATS=y | ||
| 220 | # CONFIG_FTRACE is not set | ||
| 221 | CONFIG_XMON=y | ||
| 222 | CONFIG_XMON_DEFAULT=y | ||
| 223 | CONFIG_SECURITY=y | ||
| 224 | CONFIG_IMA=y | ||
| 225 | CONFIG_EVM=y | ||
| 226 | # CONFIG_CRYPTO_ECHAINIV is not set | ||
| 227 | CONFIG_CRYPTO_ECB=y | ||
| 228 | CONFIG_CRYPTO_CMAC=y | ||
| 229 | CONFIG_CRYPTO_MD4=y | ||
| 230 | CONFIG_CRYPTO_ARC4=y | ||
| 231 | CONFIG_CRYPTO_DES=y | ||
| 232 | # CONFIG_CRYPTO_HW is not set | ||
diff --git a/arch/powerpc/include/asm/book3s/64/mmu-hash.h b/arch/powerpc/include/asm/book3s/64/mmu-hash.h index 508275bb05d5..e91e115a816f 100644 --- a/arch/powerpc/include/asm/book3s/64/mmu-hash.h +++ b/arch/powerpc/include/asm/book3s/64/mmu-hash.h | |||
| @@ -606,7 +606,7 @@ extern void slb_set_size(u16 size); | |||
| 606 | 606 | ||
| 607 | /* 4 bits per slice and we have one slice per 1TB */ | 607 | /* 4 bits per slice and we have one slice per 1TB */ |
| 608 | #define SLICE_ARRAY_SIZE (H_PGTABLE_RANGE >> 41) | 608 | #define SLICE_ARRAY_SIZE (H_PGTABLE_RANGE >> 41) |
| 609 | #define TASK_SLICE_ARRAY_SZ(x) ((x)->context.addr_limit >> 41) | 609 | #define TASK_SLICE_ARRAY_SZ(x) ((x)->context.slb_addr_limit >> 41) |
| 610 | 610 | ||
| 611 | #ifndef __ASSEMBLY__ | 611 | #ifndef __ASSEMBLY__ |
| 612 | 612 | ||
diff --git a/arch/powerpc/include/asm/book3s/64/mmu.h b/arch/powerpc/include/asm/book3s/64/mmu.h index 37fdede5a24c..c9448e19847a 100644 --- a/arch/powerpc/include/asm/book3s/64/mmu.h +++ b/arch/powerpc/include/asm/book3s/64/mmu.h | |||
| @@ -93,7 +93,7 @@ typedef struct { | |||
| 93 | #ifdef CONFIG_PPC_MM_SLICES | 93 | #ifdef CONFIG_PPC_MM_SLICES |
| 94 | u64 low_slices_psize; /* SLB page size encodings */ | 94 | u64 low_slices_psize; /* SLB page size encodings */ |
| 95 | unsigned char high_slices_psize[SLICE_ARRAY_SIZE]; | 95 | unsigned char high_slices_psize[SLICE_ARRAY_SIZE]; |
| 96 | unsigned long addr_limit; | 96 | unsigned long slb_addr_limit; |
| 97 | #else | 97 | #else |
| 98 | u16 sllp; /* SLB page size encoding */ | 98 | u16 sllp; /* SLB page size encoding */ |
| 99 | #endif | 99 | #endif |
diff --git a/arch/powerpc/include/asm/book3s/64/tlbflush-hash.h b/arch/powerpc/include/asm/book3s/64/tlbflush-hash.h index 42178897a050..849ecaae9e79 100644 --- a/arch/powerpc/include/asm/book3s/64/tlbflush-hash.h +++ b/arch/powerpc/include/asm/book3s/64/tlbflush-hash.h | |||
| @@ -66,6 +66,28 @@ static inline void hash__flush_tlb_mm(struct mm_struct *mm) | |||
| 66 | { | 66 | { |
| 67 | } | 67 | } |
| 68 | 68 | ||
| 69 | static inline void hash__local_flush_all_mm(struct mm_struct *mm) | ||
| 70 | { | ||
| 71 | /* | ||
| 72 | * There's no Page Walk Cache for hash, so what is needed is | ||
| 73 | * the same as flush_tlb_mm(), which doesn't really make sense | ||
| 74 | * with hash. So the only thing we could do is flush the | ||
| 75 | * entire LPID! Punt for now, as it's not being used. | ||
| 76 | */ | ||
| 77 | WARN_ON_ONCE(1); | ||
| 78 | } | ||
| 79 | |||
| 80 | static inline void hash__flush_all_mm(struct mm_struct *mm) | ||
| 81 | { | ||
| 82 | /* | ||
| 83 | * There's no Page Walk Cache for hash, so what is needed is | ||
| 84 | * the same as flush_tlb_mm(), which doesn't really make sense | ||
| 85 | * with hash. So the only thing we could do is flush the | ||
| 86 | * entire LPID! Punt for now, as it's not being used. | ||
| 87 | */ | ||
| 88 | WARN_ON_ONCE(1); | ||
| 89 | } | ||
| 90 | |||
| 69 | static inline void hash__local_flush_tlb_page(struct vm_area_struct *vma, | 91 | static inline void hash__local_flush_tlb_page(struct vm_area_struct *vma, |
| 70 | unsigned long vmaddr) | 92 | unsigned long vmaddr) |
| 71 | { | 93 | { |
diff --git a/arch/powerpc/include/asm/book3s/64/tlbflush-radix.h b/arch/powerpc/include/asm/book3s/64/tlbflush-radix.h index c2115dfcef0c..6a9e68003387 100644 --- a/arch/powerpc/include/asm/book3s/64/tlbflush-radix.h +++ b/arch/powerpc/include/asm/book3s/64/tlbflush-radix.h | |||
| @@ -22,17 +22,20 @@ extern void radix__flush_tlb_range(struct vm_area_struct *vma, unsigned long sta | |||
| 22 | extern void radix__flush_tlb_kernel_range(unsigned long start, unsigned long end); | 22 | extern void radix__flush_tlb_kernel_range(unsigned long start, unsigned long end); |
| 23 | 23 | ||
| 24 | extern void radix__local_flush_tlb_mm(struct mm_struct *mm); | 24 | extern void radix__local_flush_tlb_mm(struct mm_struct *mm); |
| 25 | extern void radix__local_flush_all_mm(struct mm_struct *mm); | ||
| 25 | extern void radix__local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr); | 26 | extern void radix__local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr); |
| 26 | extern void radix__local_flush_tlb_page_psize(struct mm_struct *mm, unsigned long vmaddr, | 27 | extern void radix__local_flush_tlb_page_psize(struct mm_struct *mm, unsigned long vmaddr, |
| 27 | int psize); | 28 | int psize); |
| 28 | extern void radix__tlb_flush(struct mmu_gather *tlb); | 29 | extern void radix__tlb_flush(struct mmu_gather *tlb); |
| 29 | #ifdef CONFIG_SMP | 30 | #ifdef CONFIG_SMP |
| 30 | extern void radix__flush_tlb_mm(struct mm_struct *mm); | 31 | extern void radix__flush_tlb_mm(struct mm_struct *mm); |
| 32 | extern void radix__flush_all_mm(struct mm_struct *mm); | ||
| 31 | extern void radix__flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr); | 33 | extern void radix__flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr); |
| 32 | extern void radix__flush_tlb_page_psize(struct mm_struct *mm, unsigned long vmaddr, | 34 | extern void radix__flush_tlb_page_psize(struct mm_struct *mm, unsigned long vmaddr, |
| 33 | int psize); | 35 | int psize); |
| 34 | #else | 36 | #else |
| 35 | #define radix__flush_tlb_mm(mm) radix__local_flush_tlb_mm(mm) | 37 | #define radix__flush_tlb_mm(mm) radix__local_flush_tlb_mm(mm) |
| 38 | #define radix__flush_all_mm(mm) radix__local_flush_all_mm(mm) | ||
| 36 | #define radix__flush_tlb_page(vma,addr) radix__local_flush_tlb_page(vma,addr) | 39 | #define radix__flush_tlb_page(vma,addr) radix__local_flush_tlb_page(vma,addr) |
| 37 | #define radix__flush_tlb_page_psize(mm,addr,p) radix__local_flush_tlb_page_psize(mm,addr,p) | 40 | #define radix__flush_tlb_page_psize(mm,addr,p) radix__local_flush_tlb_page_psize(mm,addr,p) |
| 38 | #endif | 41 | #endif |
diff --git a/arch/powerpc/include/asm/book3s/64/tlbflush.h b/arch/powerpc/include/asm/book3s/64/tlbflush.h index fcffddbb3102..58b576f654b3 100644 --- a/arch/powerpc/include/asm/book3s/64/tlbflush.h +++ b/arch/powerpc/include/asm/book3s/64/tlbflush.h | |||
| @@ -58,6 +58,13 @@ static inline void local_flush_tlb_page(struct vm_area_struct *vma, | |||
| 58 | return hash__local_flush_tlb_page(vma, vmaddr); | 58 | return hash__local_flush_tlb_page(vma, vmaddr); |
| 59 | } | 59 | } |
| 60 | 60 | ||
| 61 | static inline void local_flush_all_mm(struct mm_struct *mm) | ||
| 62 | { | ||
| 63 | if (radix_enabled()) | ||
| 64 | return radix__local_flush_all_mm(mm); | ||
| 65 | return hash__local_flush_all_mm(mm); | ||
| 66 | } | ||
| 67 | |||
| 61 | static inline void tlb_flush(struct mmu_gather *tlb) | 68 | static inline void tlb_flush(struct mmu_gather *tlb) |
| 62 | { | 69 | { |
| 63 | if (radix_enabled()) | 70 | if (radix_enabled()) |
| @@ -80,9 +87,17 @@ static inline void flush_tlb_page(struct vm_area_struct *vma, | |||
| 80 | return radix__flush_tlb_page(vma, vmaddr); | 87 | return radix__flush_tlb_page(vma, vmaddr); |
| 81 | return hash__flush_tlb_page(vma, vmaddr); | 88 | return hash__flush_tlb_page(vma, vmaddr); |
| 82 | } | 89 | } |
| 90 | |||
| 91 | static inline void flush_all_mm(struct mm_struct *mm) | ||
| 92 | { | ||
| 93 | if (radix_enabled()) | ||
| 94 | return radix__flush_all_mm(mm); | ||
| 95 | return hash__flush_all_mm(mm); | ||
| 96 | } | ||
| 83 | #else | 97 | #else |
| 84 | #define flush_tlb_mm(mm) local_flush_tlb_mm(mm) | 98 | #define flush_tlb_mm(mm) local_flush_tlb_mm(mm) |
| 85 | #define flush_tlb_page(vma, addr) local_flush_tlb_page(vma, addr) | 99 | #define flush_tlb_page(vma, addr) local_flush_tlb_page(vma, addr) |
| 100 | #define flush_all_mm(mm) local_flush_all_mm(mm) | ||
| 86 | #endif /* CONFIG_SMP */ | 101 | #endif /* CONFIG_SMP */ |
| 87 | /* | 102 | /* |
| 88 | * flush the page walk cache for the address | 103 | * flush the page walk cache for the address |
diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h index 53b31c2bcdf4..0546663a98db 100644 --- a/arch/powerpc/include/asm/cputable.h +++ b/arch/powerpc/include/asm/cputable.h | |||
| @@ -207,7 +207,7 @@ enum { | |||
| 207 | #define CPU_FTR_STCX_CHECKS_ADDRESS LONG_ASM_CONST(0x0004000000000000) | 207 | #define CPU_FTR_STCX_CHECKS_ADDRESS LONG_ASM_CONST(0x0004000000000000) |
| 208 | #define CPU_FTR_POPCNTB LONG_ASM_CONST(0x0008000000000000) | 208 | #define CPU_FTR_POPCNTB LONG_ASM_CONST(0x0008000000000000) |
| 209 | #define CPU_FTR_POPCNTD LONG_ASM_CONST(0x0010000000000000) | 209 | #define CPU_FTR_POPCNTD LONG_ASM_CONST(0x0010000000000000) |
| 210 | #define CPU_FTR_ICSWX LONG_ASM_CONST(0x0020000000000000) | 210 | /* Free LONG_ASM_CONST(0x0020000000000000) */ |
| 211 | #define CPU_FTR_VMX_COPY LONG_ASM_CONST(0x0040000000000000) | 211 | #define CPU_FTR_VMX_COPY LONG_ASM_CONST(0x0040000000000000) |
| 212 | #define CPU_FTR_TM LONG_ASM_CONST(0x0080000000000000) | 212 | #define CPU_FTR_TM LONG_ASM_CONST(0x0080000000000000) |
| 213 | #define CPU_FTR_CFAR LONG_ASM_CONST(0x0100000000000000) | 213 | #define CPU_FTR_CFAR LONG_ASM_CONST(0x0100000000000000) |
| @@ -216,6 +216,7 @@ enum { | |||
| 216 | #define CPU_FTR_DABRX LONG_ASM_CONST(0x0800000000000000) | 216 | #define CPU_FTR_DABRX LONG_ASM_CONST(0x0800000000000000) |
| 217 | #define CPU_FTR_PMAO_BUG LONG_ASM_CONST(0x1000000000000000) | 217 | #define CPU_FTR_PMAO_BUG LONG_ASM_CONST(0x1000000000000000) |
| 218 | #define CPU_FTR_POWER9_DD1 LONG_ASM_CONST(0x4000000000000000) | 218 | #define CPU_FTR_POWER9_DD1 LONG_ASM_CONST(0x4000000000000000) |
| 219 | #define CPU_FTR_POWER9_DD2_1 LONG_ASM_CONST(0x8000000000000000) | ||
| 219 | 220 | ||
| 220 | #ifndef __ASSEMBLY__ | 221 | #ifndef __ASSEMBLY__ |
| 221 | 222 | ||
| @@ -452,7 +453,7 @@ enum { | |||
| 452 | CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \ | 453 | CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \ |
| 453 | CPU_FTR_DSCR | CPU_FTR_SAO | CPU_FTR_ASYM_SMT | \ | 454 | CPU_FTR_DSCR | CPU_FTR_SAO | CPU_FTR_ASYM_SMT | \ |
| 454 | CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \ | 455 | CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \ |
| 455 | CPU_FTR_ICSWX | CPU_FTR_CFAR | CPU_FTR_HVMODE | \ | 456 | CPU_FTR_CFAR | CPU_FTR_HVMODE | \ |
| 456 | CPU_FTR_VMX_COPY | CPU_FTR_HAS_PPR | CPU_FTR_DABRX) | 457 | CPU_FTR_VMX_COPY | CPU_FTR_HAS_PPR | CPU_FTR_DABRX) |
| 457 | #define CPU_FTRS_POWER8 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \ | 458 | #define CPU_FTRS_POWER8 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \ |
| 458 | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | CPU_FTR_ARCH_206 |\ | 459 | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | CPU_FTR_ARCH_206 |\ |
| @@ -461,7 +462,7 @@ enum { | |||
| 461 | CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \ | 462 | CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \ |
| 462 | CPU_FTR_DSCR | CPU_FTR_SAO | \ | 463 | CPU_FTR_DSCR | CPU_FTR_SAO | \ |
| 463 | CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \ | 464 | CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \ |
| 464 | CPU_FTR_ICSWX | CPU_FTR_CFAR | CPU_FTR_HVMODE | CPU_FTR_VMX_COPY | \ | 465 | CPU_FTR_CFAR | CPU_FTR_HVMODE | CPU_FTR_VMX_COPY | \ |
| 465 | CPU_FTR_DBELL | CPU_FTR_HAS_PPR | CPU_FTR_DAWR | \ | 466 | CPU_FTR_DBELL | CPU_FTR_HAS_PPR | CPU_FTR_DAWR | \ |
| 466 | CPU_FTR_ARCH_207S | CPU_FTR_TM_COMP) | 467 | CPU_FTR_ARCH_207S | CPU_FTR_TM_COMP) |
| 467 | #define CPU_FTRS_POWER8E (CPU_FTRS_POWER8 | CPU_FTR_PMAO_BUG) | 468 | #define CPU_FTRS_POWER8E (CPU_FTRS_POWER8 | CPU_FTR_PMAO_BUG) |
| @@ -478,6 +479,8 @@ enum { | |||
| 478 | CPU_FTR_ARCH_207S | CPU_FTR_TM_COMP | CPU_FTR_ARCH_300) | 479 | CPU_FTR_ARCH_207S | CPU_FTR_TM_COMP | CPU_FTR_ARCH_300) |
| 479 | #define CPU_FTRS_POWER9_DD1 ((CPU_FTRS_POWER9 | CPU_FTR_POWER9_DD1) & \ | 480 | #define CPU_FTRS_POWER9_DD1 ((CPU_FTRS_POWER9 | CPU_FTR_POWER9_DD1) & \ |
| 480 | (~CPU_FTR_SAO)) | 481 | (~CPU_FTR_SAO)) |
| 482 | #define CPU_FTRS_POWER9_DD2_0 CPU_FTRS_POWER9 | ||
| 483 | #define CPU_FTRS_POWER9_DD2_1 (CPU_FTRS_POWER9 | CPU_FTR_POWER9_DD2_1) | ||
| 481 | #define CPU_FTRS_CELL (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \ | 484 | #define CPU_FTRS_CELL (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \ |
| 482 | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ | 485 | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ |
| 483 | CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \ | 486 | CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \ |
| @@ -496,7 +499,8 @@ enum { | |||
| 496 | (CPU_FTRS_POWER4 | CPU_FTRS_PPC970 | CPU_FTRS_POWER5 | \ | 499 | (CPU_FTRS_POWER4 | CPU_FTRS_PPC970 | CPU_FTRS_POWER5 | \ |
| 497 | CPU_FTRS_POWER6 | CPU_FTRS_POWER7 | CPU_FTRS_POWER8E | \ | 500 | CPU_FTRS_POWER6 | CPU_FTRS_POWER7 | CPU_FTRS_POWER8E | \ |
| 498 | CPU_FTRS_POWER8 | CPU_FTRS_POWER8_DD1 | CPU_FTRS_CELL | \ | 501 | CPU_FTRS_POWER8 | CPU_FTRS_POWER8_DD1 | CPU_FTRS_CELL | \ |
| 499 | CPU_FTRS_PA6T | CPU_FTR_VSX | CPU_FTRS_POWER9 | CPU_FTRS_POWER9_DD1) | 502 | CPU_FTRS_PA6T | CPU_FTR_VSX | CPU_FTRS_POWER9 | \ |
| 503 | CPU_FTRS_POWER9_DD1 | CPU_FTRS_POWER9_DD2_1) | ||
| 500 | #endif | 504 | #endif |
| 501 | #else | 505 | #else |
| 502 | enum { | 506 | enum { |
diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h index 9847ae3a12d1..5161c37dd039 100644 --- a/arch/powerpc/include/asm/eeh.h +++ b/arch/powerpc/include/asm/eeh.h | |||
| @@ -93,7 +93,7 @@ struct eeh_pe { | |||
| 93 | struct pci_bus *bus; /* Top PCI bus for bus PE */ | 93 | struct pci_bus *bus; /* Top PCI bus for bus PE */ |
| 94 | int check_count; /* Times of ignored error */ | 94 | int check_count; /* Times of ignored error */ |
| 95 | int freeze_count; /* Times of froze up */ | 95 | int freeze_count; /* Times of froze up */ |
| 96 | struct timeval tstamp; /* Time on first-time freeze */ | 96 | time64_t tstamp; /* Time on first-time freeze */ |
| 97 | int false_positives; /* Times of reported #ff's */ | 97 | int false_positives; /* Times of reported #ff's */ |
| 98 | atomic_t pass_dev_cnt; /* Count of passed through devs */ | 98 | atomic_t pass_dev_cnt; /* Count of passed through devs */ |
| 99 | struct eeh_pe *parent; /* Parent PE */ | 99 | struct eeh_pe *parent; /* Parent PE */ |
| @@ -200,7 +200,6 @@ enum { | |||
| 200 | struct eeh_ops { | 200 | struct eeh_ops { |
| 201 | char *name; | 201 | char *name; |
| 202 | int (*init)(void); | 202 | int (*init)(void); |
| 203 | int (*post_init)(void); | ||
| 204 | void* (*probe)(struct pci_dn *pdn, void *data); | 203 | void* (*probe)(struct pci_dn *pdn, void *data); |
| 205 | int (*set_option)(struct eeh_pe *pe, int option); | 204 | int (*set_option)(struct eeh_pe *pe, int option); |
| 206 | int (*get_pe_addr)(struct eeh_pe *pe); | 205 | int (*get_pe_addr)(struct eeh_pe *pe); |
| @@ -275,7 +274,7 @@ struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe); | |||
| 275 | 274 | ||
| 276 | struct eeh_dev *eeh_dev_init(struct pci_dn *pdn); | 275 | struct eeh_dev *eeh_dev_init(struct pci_dn *pdn); |
| 277 | void eeh_dev_phb_init_dynamic(struct pci_controller *phb); | 276 | void eeh_dev_phb_init_dynamic(struct pci_controller *phb); |
| 278 | int eeh_init(void); | 277 | void eeh_probe_devices(void); |
| 279 | int __init eeh_ops_register(struct eeh_ops *ops); | 278 | int __init eeh_ops_register(struct eeh_ops *ops); |
| 280 | int __exit eeh_ops_unregister(const char *name); | 279 | int __exit eeh_ops_unregister(const char *name); |
| 281 | int eeh_check_failure(const volatile void __iomem *token); | 280 | int eeh_check_failure(const volatile void __iomem *token); |
| @@ -321,10 +320,7 @@ static inline bool eeh_enabled(void) | |||
| 321 | return false; | 320 | return false; |
| 322 | } | 321 | } |
| 323 | 322 | ||
| 324 | static inline int eeh_init(void) | 323 | static inline void eeh_probe_devices(void) { } |
| 325 | { | ||
| 326 | return 0; | ||
| 327 | } | ||
| 328 | 324 | ||
| 329 | static inline void *eeh_dev_init(struct pci_dn *pdn, void *data) | 325 | static inline void *eeh_dev_init(struct pci_dn *pdn, void *data) |
| 330 | { | 326 | { |
diff --git a/arch/powerpc/include/asm/emulated_ops.h b/arch/powerpc/include/asm/emulated_ops.h index f00e10e2a335..651e1354498e 100644 --- a/arch/powerpc/include/asm/emulated_ops.h +++ b/arch/powerpc/include/asm/emulated_ops.h | |||
| @@ -55,6 +55,10 @@ extern struct ppc_emulated { | |||
| 55 | struct ppc_emulated_entry mfdscr; | 55 | struct ppc_emulated_entry mfdscr; |
| 56 | struct ppc_emulated_entry mtdscr; | 56 | struct ppc_emulated_entry mtdscr; |
| 57 | struct ppc_emulated_entry lq_stq; | 57 | struct ppc_emulated_entry lq_stq; |
| 58 | struct ppc_emulated_entry lxvw4x; | ||
| 59 | struct ppc_emulated_entry lxvh8x; | ||
| 60 | struct ppc_emulated_entry lxvd2x; | ||
| 61 | struct ppc_emulated_entry lxvb16x; | ||
| 58 | #endif | 62 | #endif |
| 59 | } ppc_emulated; | 63 | } ppc_emulated; |
| 60 | 64 | ||
diff --git a/arch/powerpc/include/asm/epapr_hcalls.h b/arch/powerpc/include/asm/epapr_hcalls.h index 334459ad145b..90863245df53 100644 --- a/arch/powerpc/include/asm/epapr_hcalls.h +++ b/arch/powerpc/include/asm/epapr_hcalls.h | |||
| @@ -508,7 +508,7 @@ static unsigned long epapr_hypercall(unsigned long *in, | |||
| 508 | 508 | ||
| 509 | static inline long epapr_hypercall0_1(unsigned int nr, unsigned long *r2) | 509 | static inline long epapr_hypercall0_1(unsigned int nr, unsigned long *r2) |
| 510 | { | 510 | { |
| 511 | unsigned long in[8]; | 511 | unsigned long in[8] = {0}; |
| 512 | unsigned long out[8]; | 512 | unsigned long out[8]; |
| 513 | unsigned long r; | 513 | unsigned long r; |
| 514 | 514 | ||
| @@ -520,7 +520,7 @@ static inline long epapr_hypercall0_1(unsigned int nr, unsigned long *r2) | |||
| 520 | 520 | ||
| 521 | static inline long epapr_hypercall0(unsigned int nr) | 521 | static inline long epapr_hypercall0(unsigned int nr) |
| 522 | { | 522 | { |
| 523 | unsigned long in[8]; | 523 | unsigned long in[8] = {0}; |
| 524 | unsigned long out[8]; | 524 | unsigned long out[8]; |
| 525 | 525 | ||
| 526 | return epapr_hypercall(in, out, nr); | 526 | return epapr_hypercall(in, out, nr); |
| @@ -528,7 +528,7 @@ static inline long epapr_hypercall0(unsigned int nr) | |||
| 528 | 528 | ||
| 529 | static inline long epapr_hypercall1(unsigned int nr, unsigned long p1) | 529 | static inline long epapr_hypercall1(unsigned int nr, unsigned long p1) |
| 530 | { | 530 | { |
| 531 | unsigned long in[8]; | 531 | unsigned long in[8] = {0}; |
| 532 | unsigned long out[8]; | 532 | unsigned long out[8]; |
| 533 | 533 | ||
| 534 | in[0] = p1; | 534 | in[0] = p1; |
| @@ -538,7 +538,7 @@ static inline long epapr_hypercall1(unsigned int nr, unsigned long p1) | |||
| 538 | static inline long epapr_hypercall2(unsigned int nr, unsigned long p1, | 538 | static inline long epapr_hypercall2(unsigned int nr, unsigned long p1, |
| 539 | unsigned long p2) | 539 | unsigned long p2) |
| 540 | { | 540 | { |
| 541 | unsigned long in[8]; | 541 | unsigned long in[8] = {0}; |
| 542 | unsigned long out[8]; | 542 | unsigned long out[8]; |
| 543 | 543 | ||
| 544 | in[0] = p1; | 544 | in[0] = p1; |
| @@ -549,7 +549,7 @@ static inline long epapr_hypercall2(unsigned int nr, unsigned long p1, | |||
| 549 | static inline long epapr_hypercall3(unsigned int nr, unsigned long p1, | 549 | static inline long epapr_hypercall3(unsigned int nr, unsigned long p1, |
| 550 | unsigned long p2, unsigned long p3) | 550 | unsigned long p2, unsigned long p3) |
| 551 | { | 551 | { |
| 552 | unsigned long in[8]; | 552 | unsigned long in[8] = {0}; |
| 553 | unsigned long out[8]; | 553 | unsigned long out[8]; |
| 554 | 554 | ||
| 555 | in[0] = p1; | 555 | in[0] = p1; |
| @@ -562,7 +562,7 @@ static inline long epapr_hypercall4(unsigned int nr, unsigned long p1, | |||
| 562 | unsigned long p2, unsigned long p3, | 562 | unsigned long p2, unsigned long p3, |
| 563 | unsigned long p4) | 563 | unsigned long p4) |
| 564 | { | 564 | { |
| 565 | unsigned long in[8]; | 565 | unsigned long in[8] = {0}; |
| 566 | unsigned long out[8]; | 566 | unsigned long out[8]; |
| 567 | 567 | ||
| 568 | in[0] = p1; | 568 | in[0] = p1; |
diff --git a/arch/powerpc/include/asm/exception-64s.h b/arch/powerpc/include/asm/exception-64s.h index 9a318973af05..b27205297e1d 100644 --- a/arch/powerpc/include/asm/exception-64s.h +++ b/arch/powerpc/include/asm/exception-64s.h | |||
| @@ -55,6 +55,11 @@ | |||
| 55 | #endif | 55 | #endif |
| 56 | 56 | ||
| 57 | /* | 57 | /* |
| 58 | * maximum recursive depth of MCE exceptions | ||
| 59 | */ | ||
| 60 | #define MAX_MCE_DEPTH 4 | ||
| 61 | |||
| 62 | /* | ||
| 58 | * EX_LR is only used in EXSLB and where it does not overlap with EX_DAR | 63 | * EX_LR is only used in EXSLB and where it does not overlap with EX_DAR |
| 59 | * EX_CCR similarly with DSISR, but being 4 byte registers there is a hole | 64 | * EX_CCR similarly with DSISR, but being 4 byte registers there is a hole |
| 60 | * in the save area so it's not necessary to overlap them. Could be used | 65 | * in the save area so it's not necessary to overlap them. Could be used |
diff --git a/arch/powerpc/include/asm/hugetlb.h b/arch/powerpc/include/asm/hugetlb.h index 93f98239159f..14c9d44f355b 100644 --- a/arch/powerpc/include/asm/hugetlb.h +++ b/arch/powerpc/include/asm/hugetlb.h | |||
| @@ -41,12 +41,6 @@ static inline void flush_hugetlb_page(struct vm_area_struct *vma, | |||
| 41 | return radix__flush_hugetlb_page(vma, vmaddr); | 41 | return radix__flush_hugetlb_page(vma, vmaddr); |
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | static inline void __local_flush_hugetlb_page(struct vm_area_struct *vma, | ||
| 45 | unsigned long vmaddr) | ||
| 46 | { | ||
| 47 | if (radix_enabled()) | ||
| 48 | return radix__local_flush_hugetlb_page(vma, vmaddr); | ||
| 49 | } | ||
| 50 | #else | 44 | #else |
| 51 | 45 | ||
| 52 | static inline pte_t *hugepd_page(hugepd_t hpd) | 46 | static inline pte_t *hugepd_page(hugepd_t hpd) |
diff --git a/arch/powerpc/include/asm/hw_irq.h b/arch/powerpc/include/asm/hw_irq.h index abd04c36c251..3818fa0164f0 100644 --- a/arch/powerpc/include/asm/hw_irq.h +++ b/arch/powerpc/include/asm/hw_irq.h | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | 32 | ||
| 33 | #ifndef __ASSEMBLY__ | 33 | #ifndef __ASSEMBLY__ |
| 34 | 34 | ||
| 35 | extern void replay_system_reset(void); | ||
| 35 | extern void __replay_interrupt(unsigned int vector); | 36 | extern void __replay_interrupt(unsigned int vector); |
| 36 | 37 | ||
| 37 | extern void timer_interrupt(struct pt_regs *); | 38 | extern void timer_interrupt(struct pt_regs *); |
diff --git a/arch/powerpc/include/asm/kprobes.h b/arch/powerpc/include/asm/kprobes.h index 8814a7249ceb..9f3be5c8a4a3 100644 --- a/arch/powerpc/include/asm/kprobes.h +++ b/arch/powerpc/include/asm/kprobes.h | |||
| @@ -103,8 +103,8 @@ extern int kprobe_exceptions_notify(struct notifier_block *self, | |||
| 103 | extern int kprobe_fault_handler(struct pt_regs *regs, int trapnr); | 103 | extern int kprobe_fault_handler(struct pt_regs *regs, int trapnr); |
| 104 | extern int kprobe_handler(struct pt_regs *regs); | 104 | extern int kprobe_handler(struct pt_regs *regs); |
| 105 | extern int kprobe_post_handler(struct pt_regs *regs); | 105 | extern int kprobe_post_handler(struct pt_regs *regs); |
| 106 | extern int is_current_kprobe_addr(unsigned long addr); | ||
| 107 | #ifdef CONFIG_KPROBES_ON_FTRACE | 106 | #ifdef CONFIG_KPROBES_ON_FTRACE |
| 107 | extern int __is_active_jprobe(unsigned long addr); | ||
| 108 | extern int skip_singlestep(struct kprobe *p, struct pt_regs *regs, | 108 | extern int skip_singlestep(struct kprobe *p, struct pt_regs *regs, |
| 109 | struct kprobe_ctlblk *kcb); | 109 | struct kprobe_ctlblk *kcb); |
| 110 | #else | 110 | #else |
diff --git a/arch/powerpc/include/asm/kvm_book3s_asm.h b/arch/powerpc/include/asm/kvm_book3s_asm.h index 83596f32f50b..7cea76f11c26 100644 --- a/arch/powerpc/include/asm/kvm_book3s_asm.h +++ b/arch/powerpc/include/asm/kvm_book3s_asm.h | |||
| @@ -104,10 +104,6 @@ struct kvmppc_host_state { | |||
| 104 | u8 napping; | 104 | u8 napping; |
| 105 | 105 | ||
| 106 | #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE | 106 | #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE |
| 107 | /* | ||
| 108 | * hwthread_req/hwthread_state pair is used to pull sibling threads | ||
| 109 | * out of guest on pre-ISAv3.0B CPUs where threads share MMU. | ||
| 110 | */ | ||
| 111 | u8 hwthread_req; | 107 | u8 hwthread_req; |
| 112 | u8 hwthread_state; | 108 | u8 hwthread_state; |
| 113 | u8 host_ipi; | 109 | u8 host_ipi; |
diff --git a/arch/powerpc/include/asm/mce.h b/arch/powerpc/include/asm/mce.h index 190d69a7f701..3a1226e9b465 100644 --- a/arch/powerpc/include/asm/mce.h +++ b/arch/powerpc/include/asm/mce.h | |||
| @@ -204,12 +204,10 @@ struct mce_error_info { | |||
| 204 | 204 | ||
| 205 | extern void save_mce_event(struct pt_regs *regs, long handled, | 205 | extern void save_mce_event(struct pt_regs *regs, long handled, |
| 206 | struct mce_error_info *mce_err, uint64_t nip, | 206 | struct mce_error_info *mce_err, uint64_t nip, |
| 207 | uint64_t addr); | 207 | uint64_t addr, uint64_t phys_addr); |
| 208 | extern int get_mce_event(struct machine_check_event *mce, bool release); | 208 | extern int get_mce_event(struct machine_check_event *mce, bool release); |
| 209 | extern void release_mce_event(void); | 209 | extern void release_mce_event(void); |
| 210 | extern void machine_check_queue_event(void); | 210 | extern void machine_check_queue_event(void); |
| 211 | extern void machine_check_print_event_info(struct machine_check_event *evt, | 211 | extern void machine_check_print_event_info(struct machine_check_event *evt, |
| 212 | bool user_mode); | 212 | bool user_mode); |
| 213 | extern uint64_t get_mce_fault_addr(struct machine_check_event *evt); | ||
| 214 | |||
| 215 | #endif /* __ASM_PPC64_MCE_H__ */ | 213 | #endif /* __ASM_PPC64_MCE_H__ */ |
diff --git a/arch/powerpc/include/asm/mmu_context.h b/arch/powerpc/include/asm/mmu_context.h index 492d8140a395..6177d43f0ce8 100644 --- a/arch/powerpc/include/asm/mmu_context.h +++ b/arch/powerpc/include/asm/mmu_context.h | |||
| @@ -78,6 +78,52 @@ extern void switch_cop(struct mm_struct *next); | |||
| 78 | extern int use_cop(unsigned long acop, struct mm_struct *mm); | 78 | extern int use_cop(unsigned long acop, struct mm_struct *mm); |
| 79 | extern void drop_cop(unsigned long acop, struct mm_struct *mm); | 79 | extern void drop_cop(unsigned long acop, struct mm_struct *mm); |
| 80 | 80 | ||
| 81 | #ifdef CONFIG_PPC_BOOK3S_64 | ||
| 82 | static inline void inc_mm_active_cpus(struct mm_struct *mm) | ||
| 83 | { | ||
| 84 | atomic_inc(&mm->context.active_cpus); | ||
| 85 | } | ||
| 86 | |||
| 87 | static inline void dec_mm_active_cpus(struct mm_struct *mm) | ||
| 88 | { | ||
| 89 | atomic_dec(&mm->context.active_cpus); | ||
| 90 | } | ||
| 91 | |||
| 92 | static inline void mm_context_add_copro(struct mm_struct *mm) | ||
| 93 | { | ||
| 94 | /* | ||
| 95 | * On hash, should only be called once over the lifetime of | ||
| 96 | * the context, as we can't decrement the active cpus count | ||
| 97 | * and flush properly for the time being. | ||
| 98 | */ | ||
| 99 | inc_mm_active_cpus(mm); | ||
| 100 | } | ||
| 101 | |||
| 102 | static inline void mm_context_remove_copro(struct mm_struct *mm) | ||
| 103 | { | ||
| 104 | /* | ||
| 105 | * Need to broadcast a global flush of the full mm before | ||
| 106 | * decrementing active_cpus count, as the next TLBI may be | ||
| 107 | * local and the nMMU and/or PSL need to be cleaned up. | ||
| 108 | * Should be rare enough so that it's acceptable. | ||
| 109 | * | ||
| 110 | * Skip on hash, as we don't know how to do the proper flush | ||
| 111 | * for the time being. Invalidations will remain global if | ||
| 112 | * used on hash. | ||
| 113 | */ | ||
| 114 | if (radix_enabled()) { | ||
| 115 | flush_all_mm(mm); | ||
| 116 | dec_mm_active_cpus(mm); | ||
| 117 | } | ||
| 118 | } | ||
| 119 | #else | ||
| 120 | static inline void inc_mm_active_cpus(struct mm_struct *mm) { } | ||
| 121 | static inline void dec_mm_active_cpus(struct mm_struct *mm) { } | ||
| 122 | static inline void mm_context_add_copro(struct mm_struct *mm) { } | ||
| 123 | static inline void mm_context_remove_copro(struct mm_struct *mm) { } | ||
| 124 | #endif | ||
| 125 | |||
| 126 | |||
| 81 | extern void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next, | 127 | extern void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next, |
| 82 | struct task_struct *tsk); | 128 | struct task_struct *tsk); |
| 83 | 129 | ||
| @@ -119,9 +165,13 @@ static inline void arch_dup_mmap(struct mm_struct *oldmm, | |||
| 119 | { | 165 | { |
| 120 | } | 166 | } |
| 121 | 167 | ||
| 168 | #ifndef CONFIG_PPC_BOOK3S_64 | ||
| 122 | static inline void arch_exit_mmap(struct mm_struct *mm) | 169 | static inline void arch_exit_mmap(struct mm_struct *mm) |
| 123 | { | 170 | { |
| 124 | } | 171 | } |
| 172 | #else | ||
| 173 | extern void arch_exit_mmap(struct mm_struct *mm); | ||
| 174 | #endif | ||
| 125 | 175 | ||
| 126 | static inline void arch_unmap(struct mm_struct *mm, | 176 | static inline void arch_unmap(struct mm_struct *mm, |
| 127 | struct vm_area_struct *vma, | 177 | struct vm_area_struct *vma, |
diff --git a/arch/powerpc/include/asm/nohash/64/pgtable.h b/arch/powerpc/include/asm/nohash/64/pgtable.h index 265bbd7cba73..abddf5830ad5 100644 --- a/arch/powerpc/include/asm/nohash/64/pgtable.h +++ b/arch/powerpc/include/asm/nohash/64/pgtable.h | |||
| @@ -204,7 +204,7 @@ static inline unsigned long pte_update(struct mm_struct *mm, | |||
| 204 | if (!huge) | 204 | if (!huge) |
| 205 | assert_pte_locked(mm, addr); | 205 | assert_pte_locked(mm, addr); |
| 206 | 206 | ||
| 207 | #ifdef CONFIG_PPC_STD_MMU_64 | 207 | #ifdef CONFIG_PPC_BOOK3S_64 |
| 208 | if (old & _PAGE_HASHPTE) | 208 | if (old & _PAGE_HASHPTE) |
| 209 | hpte_need_flush(mm, addr, ptep, old, huge); | 209 | hpte_need_flush(mm, addr, ptep, old, huge); |
| 210 | #endif | 210 | #endif |
diff --git a/arch/powerpc/include/asm/opal-api.h b/arch/powerpc/include/asm/opal-api.h index 450a60b81d2a..233c7504b1f2 100644 --- a/arch/powerpc/include/asm/opal-api.h +++ b/arch/powerpc/include/asm/opal-api.h | |||
| @@ -188,6 +188,7 @@ | |||
| 188 | #define OPAL_XIVE_DUMP 142 | 188 | #define OPAL_XIVE_DUMP 142 |
| 189 | #define OPAL_XIVE_RESERVED3 143 | 189 | #define OPAL_XIVE_RESERVED3 143 |
| 190 | #define OPAL_XIVE_RESERVED4 144 | 190 | #define OPAL_XIVE_RESERVED4 144 |
| 191 | #define OPAL_SIGNAL_SYSTEM_RESET 145 | ||
| 191 | #define OPAL_NPU_INIT_CONTEXT 146 | 192 | #define OPAL_NPU_INIT_CONTEXT 146 |
| 192 | #define OPAL_NPU_DESTROY_CONTEXT 147 | 193 | #define OPAL_NPU_DESTROY_CONTEXT 147 |
| 193 | #define OPAL_NPU_MAP_LPAR 148 | 194 | #define OPAL_NPU_MAP_LPAR 148 |
| @@ -895,6 +896,8 @@ enum { | |||
| 895 | */ | 896 | */ |
| 896 | OPAL_REINIT_CPUS_MMU_HASH = (1 << 2), | 897 | OPAL_REINIT_CPUS_MMU_HASH = (1 << 2), |
| 897 | OPAL_REINIT_CPUS_MMU_RADIX = (1 << 3), | 898 | OPAL_REINIT_CPUS_MMU_RADIX = (1 << 3), |
| 899 | |||
| 900 | OPAL_REINIT_CPUS_TM_SUSPEND_DISABLED = (1 << 4), | ||
| 898 | }; | 901 | }; |
| 899 | 902 | ||
| 900 | typedef struct oppanel_line { | 903 | typedef struct oppanel_line { |
diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h index 726c23304a57..0c545f7fc77b 100644 --- a/arch/powerpc/include/asm/opal.h +++ b/arch/powerpc/include/asm/opal.h | |||
| @@ -281,6 +281,8 @@ int opal_get_power_shift_ratio(u32 handle, int token, u32 *psr); | |||
| 281 | int opal_set_power_shift_ratio(u32 handle, int token, u32 psr); | 281 | int opal_set_power_shift_ratio(u32 handle, int token, u32 psr); |
| 282 | int opal_sensor_group_clear(u32 group_hndl, int token); | 282 | int opal_sensor_group_clear(u32 group_hndl, int token); |
| 283 | 283 | ||
| 284 | s64 opal_signal_system_reset(s32 cpu); | ||
| 285 | |||
| 284 | /* Internal functions */ | 286 | /* Internal functions */ |
| 285 | extern int early_init_dt_scan_opal(unsigned long node, const char *uname, | 287 | extern int early_init_dt_scan_opal(unsigned long node, const char *uname, |
| 286 | int depth, void *data); | 288 | int depth, void *data); |
| @@ -304,11 +306,11 @@ extern void opal_notifier_enable(void); | |||
| 304 | extern void opal_notifier_disable(void); | 306 | extern void opal_notifier_disable(void); |
| 305 | extern void opal_notifier_update_evt(uint64_t evt_mask, uint64_t evt_val); | 307 | extern void opal_notifier_update_evt(uint64_t evt_mask, uint64_t evt_val); |
| 306 | 308 | ||
| 307 | extern int __opal_async_get_token(void); | ||
| 308 | extern int opal_async_get_token_interruptible(void); | 309 | extern int opal_async_get_token_interruptible(void); |
| 309 | extern int __opal_async_release_token(int token); | ||
| 310 | extern int opal_async_release_token(int token); | 310 | extern int opal_async_release_token(int token); |
| 311 | extern int opal_async_wait_response(uint64_t token, struct opal_msg *msg); | 311 | extern int opal_async_wait_response(uint64_t token, struct opal_msg *msg); |
| 312 | extern int opal_async_wait_response_interruptible(uint64_t token, | ||
| 313 | struct opal_msg *msg); | ||
| 312 | extern int opal_get_sensor_data(u32 sensor_hndl, u32 *sensor_data); | 314 | extern int opal_get_sensor_data(u32 sensor_hndl, u32 *sensor_data); |
| 313 | 315 | ||
| 314 | struct rtc_time; | 316 | struct rtc_time; |
diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h index 04b60af027ae..3892db93b837 100644 --- a/arch/powerpc/include/asm/paca.h +++ b/arch/powerpc/include/asm/paca.h | |||
| @@ -91,14 +91,14 @@ struct paca_struct { | |||
| 91 | u8 cpu_start; /* At startup, processor spins until */ | 91 | u8 cpu_start; /* At startup, processor spins until */ |
| 92 | /* this becomes non-zero. */ | 92 | /* this becomes non-zero. */ |
| 93 | u8 kexec_state; /* set when kexec down has irqs off */ | 93 | u8 kexec_state; /* set when kexec down has irqs off */ |
| 94 | #ifdef CONFIG_PPC_STD_MMU_64 | 94 | #ifdef CONFIG_PPC_BOOK3S_64 |
| 95 | struct slb_shadow *slb_shadow_ptr; | 95 | struct slb_shadow *slb_shadow_ptr; |
| 96 | struct dtl_entry *dispatch_log; | 96 | struct dtl_entry *dispatch_log; |
| 97 | struct dtl_entry *dispatch_log_end; | 97 | struct dtl_entry *dispatch_log_end; |
| 98 | #endif /* CONFIG_PPC_STD_MMU_64 */ | 98 | #endif |
| 99 | u64 dscr_default; /* per-CPU default DSCR */ | 99 | u64 dscr_default; /* per-CPU default DSCR */ |
| 100 | 100 | ||
| 101 | #ifdef CONFIG_PPC_STD_MMU_64 | 101 | #ifdef CONFIG_PPC_BOOK3S_64 |
| 102 | /* | 102 | /* |
| 103 | * Now, starting in cacheline 2, the exception save areas | 103 | * Now, starting in cacheline 2, the exception save areas |
| 104 | */ | 104 | */ |
| @@ -110,7 +110,7 @@ struct paca_struct { | |||
| 110 | u16 vmalloc_sllp; | 110 | u16 vmalloc_sllp; |
| 111 | u16 slb_cache_ptr; | 111 | u16 slb_cache_ptr; |
| 112 | u32 slb_cache[SLB_CACHE_ENTRIES]; | 112 | u32 slb_cache[SLB_CACHE_ENTRIES]; |
| 113 | #endif /* CONFIG_PPC_STD_MMU_64 */ | 113 | #endif /* CONFIG_PPC_BOOK3S_64 */ |
| 114 | 114 | ||
| 115 | #ifdef CONFIG_PPC_BOOK3E | 115 | #ifdef CONFIG_PPC_BOOK3E |
| 116 | u64 exgen[8] __aligned(0x40); | 116 | u64 exgen[8] __aligned(0x40); |
| @@ -143,7 +143,7 @@ struct paca_struct { | |||
| 143 | #ifdef CONFIG_PPC_MM_SLICES | 143 | #ifdef CONFIG_PPC_MM_SLICES |
| 144 | u64 mm_ctx_low_slices_psize; | 144 | u64 mm_ctx_low_slices_psize; |
| 145 | unsigned char mm_ctx_high_slices_psize[SLICE_ARRAY_SIZE]; | 145 | unsigned char mm_ctx_high_slices_psize[SLICE_ARRAY_SIZE]; |
| 146 | unsigned long addr_limit; | 146 | unsigned long mm_ctx_slb_addr_limit; |
| 147 | #else | 147 | #else |
| 148 | u16 mm_ctx_user_psize; | 148 | u16 mm_ctx_user_psize; |
| 149 | u16 mm_ctx_sllp; | 149 | u16 mm_ctx_sllp; |
| @@ -192,7 +192,7 @@ struct paca_struct { | |||
| 192 | struct stop_sprs stop_sprs; | 192 | struct stop_sprs stop_sprs; |
| 193 | #endif | 193 | #endif |
| 194 | 194 | ||
| 195 | #ifdef CONFIG_PPC_STD_MMU_64 | 195 | #ifdef CONFIG_PPC_BOOK3S_64 |
| 196 | /* Non-maskable exceptions that are not performance critical */ | 196 | /* Non-maskable exceptions that are not performance critical */ |
| 197 | u64 exnmi[EX_SIZE]; /* used for system reset (nmi) */ | 197 | u64 exnmi[EX_SIZE]; /* used for system reset (nmi) */ |
| 198 | u64 exmc[EX_SIZE]; /* used for machine checks */ | 198 | u64 exmc[EX_SIZE]; /* used for machine checks */ |
| @@ -210,6 +210,7 @@ struct paca_struct { | |||
| 210 | */ | 210 | */ |
| 211 | u16 in_mce; | 211 | u16 in_mce; |
| 212 | u8 hmi_event_available; /* HMI event is available */ | 212 | u8 hmi_event_available; /* HMI event is available */ |
| 213 | u8 hmi_p9_special_emu; /* HMI P9 special emulation */ | ||
| 213 | #endif | 214 | #endif |
| 214 | 215 | ||
| 215 | /* Stuff for accurate time accounting */ | 216 | /* Stuff for accurate time accounting */ |
diff --git a/arch/powerpc/include/asm/page_64.h b/arch/powerpc/include/asm/page_64.h index c4d9654bd637..56234c6fcd61 100644 --- a/arch/powerpc/include/asm/page_64.h +++ b/arch/powerpc/include/asm/page_64.h | |||
| @@ -117,21 +117,21 @@ extern void slice_set_range_psize(struct mm_struct *mm, unsigned long start, | |||
| 117 | #endif /* __ASSEMBLY__ */ | 117 | #endif /* __ASSEMBLY__ */ |
| 118 | #else | 118 | #else |
| 119 | #define slice_init() | 119 | #define slice_init() |
| 120 | #ifdef CONFIG_PPC_STD_MMU_64 | 120 | #ifdef CONFIG_PPC_BOOK3S_64 |
| 121 | #define get_slice_psize(mm, addr) ((mm)->context.user_psize) | 121 | #define get_slice_psize(mm, addr) ((mm)->context.user_psize) |
| 122 | #define slice_set_user_psize(mm, psize) \ | 122 | #define slice_set_user_psize(mm, psize) \ |
| 123 | do { \ | 123 | do { \ |
| 124 | (mm)->context.user_psize = (psize); \ | 124 | (mm)->context.user_psize = (psize); \ |
| 125 | (mm)->context.sllp = SLB_VSID_USER | mmu_psize_defs[(psize)].sllp; \ | 125 | (mm)->context.sllp = SLB_VSID_USER | mmu_psize_defs[(psize)].sllp; \ |
| 126 | } while (0) | 126 | } while (0) |
| 127 | #else /* CONFIG_PPC_STD_MMU_64 */ | 127 | #else /* !CONFIG_PPC_BOOK3S_64 */ |
| 128 | #ifdef CONFIG_PPC_64K_PAGES | 128 | #ifdef CONFIG_PPC_64K_PAGES |
| 129 | #define get_slice_psize(mm, addr) MMU_PAGE_64K | 129 | #define get_slice_psize(mm, addr) MMU_PAGE_64K |
| 130 | #else /* CONFIG_PPC_64K_PAGES */ | 130 | #else /* CONFIG_PPC_64K_PAGES */ |
| 131 | #define get_slice_psize(mm, addr) MMU_PAGE_4K | 131 | #define get_slice_psize(mm, addr) MMU_PAGE_4K |
| 132 | #endif /* !CONFIG_PPC_64K_PAGES */ | 132 | #endif /* !CONFIG_PPC_64K_PAGES */ |
| 133 | #define slice_set_user_psize(mm, psize) do { BUG(); } while(0) | 133 | #define slice_set_user_psize(mm, psize) do { BUG(); } while(0) |
| 134 | #endif /* !CONFIG_PPC_STD_MMU_64 */ | 134 | #endif /* CONFIG_PPC_BOOK3S_64 */ |
| 135 | 135 | ||
| 136 | #define slice_set_range_psize(mm, start, len, psize) \ | 136 | #define slice_set_range_psize(mm, start, len, psize) \ |
| 137 | slice_set_user_psize((mm), (psize)) | 137 | slice_set_user_psize((mm), (psize)) |
diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h index 0b8aa1fe2d5f..62ed83db04ae 100644 --- a/arch/powerpc/include/asm/pci-bridge.h +++ b/arch/powerpc/include/asm/pci-bridge.h | |||
| @@ -218,6 +218,7 @@ struct pci_dn { | |||
| 218 | #endif | 218 | #endif |
| 219 | struct list_head child_list; | 219 | struct list_head child_list; |
| 220 | struct list_head list; | 220 | struct list_head list; |
| 221 | struct resource holes[PCI_SRIOV_NUM_BARS]; | ||
| 221 | }; | 222 | }; |
| 222 | 223 | ||
| 223 | /* Get the pointer to a device_node's pci_dn */ | 224 | /* Get the pointer to a device_node's pci_dn */ |
diff --git a/arch/powerpc/include/asm/pgtable-be-types.h b/arch/powerpc/include/asm/pgtable-be-types.h index beb6e3e79788..a89c67b62680 100644 --- a/arch/powerpc/include/asm/pgtable-be-types.h +++ b/arch/powerpc/include/asm/pgtable-be-types.h | |||
| @@ -77,7 +77,7 @@ typedef struct { unsigned long pgprot; } pgprot_t; | |||
| 77 | * With hash config 64k pages additionally define a bigger "real PTE" type that | 77 | * With hash config 64k pages additionally define a bigger "real PTE" type that |
| 78 | * gathers the "second half" part of the PTE for pseudo 64k pages | 78 | * gathers the "second half" part of the PTE for pseudo 64k pages |
| 79 | */ | 79 | */ |
| 80 | #if defined(CONFIG_PPC_64K_PAGES) && defined(CONFIG_PPC_STD_MMU_64) | 80 | #if defined(CONFIG_PPC_64K_PAGES) && defined(CONFIG_PPC_BOOK3S_64) |
| 81 | typedef struct { pte_t pte; unsigned long hidx; } real_pte_t; | 81 | typedef struct { pte_t pte; unsigned long hidx; } real_pte_t; |
| 82 | #else | 82 | #else |
| 83 | typedef struct { pte_t pte; } real_pte_t; | 83 | typedef struct { pte_t pte; } real_pte_t; |
diff --git a/arch/powerpc/include/asm/pgtable-types.h b/arch/powerpc/include/asm/pgtable-types.h index cfe89a6fc308..eccb30b38b47 100644 --- a/arch/powerpc/include/asm/pgtable-types.h +++ b/arch/powerpc/include/asm/pgtable-types.h | |||
| @@ -50,13 +50,13 @@ typedef struct { unsigned long pgprot; } pgprot_t; | |||
| 50 | * With hash config 64k pages additionally define a bigger "real PTE" type that | 50 | * With hash config 64k pages additionally define a bigger "real PTE" type that |
| 51 | * gathers the "second half" part of the PTE for pseudo 64k pages | 51 | * gathers the "second half" part of the PTE for pseudo 64k pages |
| 52 | */ | 52 | */ |
| 53 | #if defined(CONFIG_PPC_64K_PAGES) && defined(CONFIG_PPC_STD_MMU_64) | 53 | #if defined(CONFIG_PPC_64K_PAGES) && defined(CONFIG_PPC_BOOK3S_64) |
| 54 | typedef struct { pte_t pte; unsigned long hidx; } real_pte_t; | 54 | typedef struct { pte_t pte; unsigned long hidx; } real_pte_t; |
| 55 | #else | 55 | #else |
| 56 | typedef struct { pte_t pte; } real_pte_t; | 56 | typedef struct { pte_t pte; } real_pte_t; |
| 57 | #endif | 57 | #endif |
| 58 | 58 | ||
| 59 | #ifdef CONFIG_PPC_STD_MMU_64 | 59 | #ifdef CONFIG_PPC_BOOK3S_64 |
| 60 | #include <asm/cmpxchg.h> | 60 | #include <asm/cmpxchg.h> |
| 61 | 61 | ||
| 62 | static inline bool pte_xchg(pte_t *ptep, pte_t old, pte_t new) | 62 | static inline bool pte_xchg(pte_t *ptep, pte_t old, pte_t new) |
diff --git a/arch/powerpc/include/asm/powernv.h b/arch/powerpc/include/asm/powernv.h index f62797702300..dc5f6a5d4575 100644 --- a/arch/powerpc/include/asm/powernv.h +++ b/arch/powerpc/include/asm/powernv.h | |||
| @@ -22,6 +22,8 @@ extern void pnv_npu2_destroy_context(struct npu_context *context, | |||
| 22 | extern int pnv_npu2_handle_fault(struct npu_context *context, uintptr_t *ea, | 22 | extern int pnv_npu2_handle_fault(struct npu_context *context, uintptr_t *ea, |
| 23 | unsigned long *flags, unsigned long *status, | 23 | unsigned long *flags, unsigned long *status, |
| 24 | int count); | 24 | int count); |
| 25 | |||
| 26 | void pnv_tm_init(void); | ||
| 25 | #else | 27 | #else |
| 26 | static inline void powernv_set_nmmu_ptcr(unsigned long ptcr) { } | 28 | static inline void powernv_set_nmmu_ptcr(unsigned long ptcr) { } |
| 27 | static inline struct npu_context *pnv_npu2_init_context(struct pci_dev *gpdev, | 29 | static inline struct npu_context *pnv_npu2_init_context(struct pci_dev *gpdev, |
| @@ -36,6 +38,8 @@ static inline int pnv_npu2_handle_fault(struct npu_context *context, | |||
| 36 | unsigned long *status, int count) { | 38 | unsigned long *status, int count) { |
| 37 | return -ENODEV; | 39 | return -ENODEV; |
| 38 | } | 40 | } |
| 41 | |||
| 42 | static inline void pnv_tm_init(void) { } | ||
| 39 | #endif | 43 | #endif |
| 40 | 44 | ||
| 41 | #endif /* _ASM_POWERNV_H */ | 45 | #endif /* _ASM_POWERNV_H */ |
diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h index 36f3e41c9fbe..ae94b3626b6c 100644 --- a/arch/powerpc/include/asm/ppc_asm.h +++ b/arch/powerpc/include/asm/ppc_asm.h | |||
| @@ -774,9 +774,13 @@ END_FTR_SECTION_IFCLR(CPU_FTR_601) | |||
| 774 | #ifdef CONFIG_PPC_BOOK3E | 774 | #ifdef CONFIG_PPC_BOOK3E |
| 775 | #define FIXUP_ENDIAN | 775 | #define FIXUP_ENDIAN |
| 776 | #else | 776 | #else |
| 777 | /* | ||
| 778 | * This version may be used in in HV or non-HV context. | ||
| 779 | * MSR[EE] must be disabled. | ||
| 780 | */ | ||
| 777 | #define FIXUP_ENDIAN \ | 781 | #define FIXUP_ENDIAN \ |
| 778 | tdi 0,0,0x48; /* Reverse endian of b . + 8 */ \ | 782 | tdi 0,0,0x48; /* Reverse endian of b . + 8 */ \ |
| 779 | b $+44; /* Skip trampoline if endian is good */ \ | 783 | b 191f; /* Skip trampoline if endian is good */ \ |
| 780 | .long 0xa600607d; /* mfmsr r11 */ \ | 784 | .long 0xa600607d; /* mfmsr r11 */ \ |
| 781 | .long 0x01006b69; /* xori r11,r11,1 */ \ | 785 | .long 0x01006b69; /* xori r11,r11,1 */ \ |
| 782 | .long 0x00004039; /* li r10,0 */ \ | 786 | .long 0x00004039; /* li r10,0 */ \ |
| @@ -786,7 +790,26 @@ END_FTR_SECTION_IFCLR(CPU_FTR_601) | |||
| 786 | .long 0x14004a39; /* addi r10,r10,20 */ \ | 790 | .long 0x14004a39; /* addi r10,r10,20 */ \ |
| 787 | .long 0xa6035a7d; /* mtsrr0 r10 */ \ | 791 | .long 0xa6035a7d; /* mtsrr0 r10 */ \ |
| 788 | .long 0xa6037b7d; /* mtsrr1 r11 */ \ | 792 | .long 0xa6037b7d; /* mtsrr1 r11 */ \ |
| 789 | .long 0x2400004c /* rfid */ | 793 | .long 0x2400004c; /* rfid */ \ |
| 794 | 191: | ||
| 795 | |||
| 796 | /* | ||
| 797 | * This version that may only be used with MSR[HV]=1 | ||
| 798 | * - Does not clear MSR[RI], so more robust. | ||
| 799 | * - Slightly smaller and faster. | ||
| 800 | */ | ||
| 801 | #define FIXUP_ENDIAN_HV \ | ||
| 802 | tdi 0,0,0x48; /* Reverse endian of b . + 8 */ \ | ||
| 803 | b 191f; /* Skip trampoline if endian is good */ \ | ||
| 804 | .long 0xa600607d; /* mfmsr r11 */ \ | ||
| 805 | .long 0x01006b69; /* xori r11,r11,1 */ \ | ||
| 806 | .long 0x05009f42; /* bcl 20,31,$+4 */ \ | ||
| 807 | .long 0xa602487d; /* mflr r10 */ \ | ||
| 808 | .long 0x14004a39; /* addi r10,r10,20 */ \ | ||
| 809 | .long 0xa64b5a7d; /* mthsrr0 r10 */ \ | ||
| 810 | .long 0xa64b7b7d; /* mthsrr1 r11 */ \ | ||
| 811 | .long 0x2402004c; /* hrfid */ \ | ||
| 812 | 191: | ||
| 790 | 813 | ||
| 791 | #endif /* !CONFIG_PPC_BOOK3E */ | 814 | #endif /* !CONFIG_PPC_BOOK3E */ |
| 792 | 815 | ||
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h index fab7ff877304..bdab3b74eb98 100644 --- a/arch/powerpc/include/asm/processor.h +++ b/arch/powerpc/include/asm/processor.h | |||
| @@ -329,6 +329,7 @@ struct thread_struct { | |||
| 329 | */ | 329 | */ |
| 330 | int dscr_inherit; | 330 | int dscr_inherit; |
| 331 | unsigned long ppr; /* used to save/restore SMT priority */ | 331 | unsigned long ppr; /* used to save/restore SMT priority */ |
| 332 | unsigned long tidr; | ||
| 332 | #endif | 333 | #endif |
| 333 | #ifdef CONFIG_PPC_BOOK3S_64 | 334 | #ifdef CONFIG_PPC_BOOK3S_64 |
| 334 | unsigned long tar; | 335 | unsigned long tar; |
| @@ -340,7 +341,9 @@ struct thread_struct { | |||
| 340 | unsigned long sier; | 341 | unsigned long sier; |
| 341 | unsigned long mmcr2; | 342 | unsigned long mmcr2; |
| 342 | unsigned mmcr0; | 343 | unsigned mmcr0; |
| 344 | |||
| 343 | unsigned used_ebb; | 345 | unsigned used_ebb; |
| 346 | unsigned int used_vas; | ||
| 344 | #endif | 347 | #endif |
| 345 | }; | 348 | }; |
| 346 | 349 | ||
diff --git a/arch/powerpc/include/asm/string.h b/arch/powerpc/include/asm/string.h index d98ac188cedb..9b8cedf618f4 100644 --- a/arch/powerpc/include/asm/string.h +++ b/arch/powerpc/include/asm/string.h | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | #define __HAVE_ARCH_MEMCMP | 12 | #define __HAVE_ARCH_MEMCMP |
| 13 | #define __HAVE_ARCH_MEMCHR | 13 | #define __HAVE_ARCH_MEMCHR |
| 14 | #define __HAVE_ARCH_MEMSET16 | 14 | #define __HAVE_ARCH_MEMSET16 |
| 15 | #define __HAVE_ARCH_MEMCPY_FLUSHCACHE | ||
| 15 | 16 | ||
| 16 | extern char * strcpy(char *,const char *); | 17 | extern char * strcpy(char *,const char *); |
| 17 | extern char * strncpy(char *,const char *, __kernel_size_t); | 18 | extern char * strncpy(char *,const char *, __kernel_size_t); |
| @@ -24,6 +25,7 @@ extern void * memcpy(void *,const void *,__kernel_size_t); | |||
| 24 | extern void * memmove(void *,const void *,__kernel_size_t); | 25 | extern void * memmove(void *,const void *,__kernel_size_t); |
| 25 | extern int memcmp(const void *,const void *,__kernel_size_t); | 26 | extern int memcmp(const void *,const void *,__kernel_size_t); |
| 26 | extern void * memchr(const void *,int,__kernel_size_t); | 27 | extern void * memchr(const void *,int,__kernel_size_t); |
| 28 | extern void * memcpy_flushcache(void *,const void *,__kernel_size_t); | ||
| 27 | 29 | ||
| 28 | #ifdef CONFIG_PPC64 | 30 | #ifdef CONFIG_PPC64 |
| 29 | #define __HAVE_ARCH_MEMSET32 | 31 | #define __HAVE_ARCH_MEMSET32 |
diff --git a/arch/powerpc/include/asm/switch_to.h b/arch/powerpc/include/asm/switch_to.h index bf820f53e27e..c3ca42cdc9f5 100644 --- a/arch/powerpc/include/asm/switch_to.h +++ b/arch/powerpc/include/asm/switch_to.h | |||
| @@ -92,4 +92,9 @@ static inline void clear_task_ebb(struct task_struct *t) | |||
| 92 | #endif | 92 | #endif |
| 93 | } | 93 | } |
| 94 | 94 | ||
| 95 | extern int set_thread_uses_vas(void); | ||
| 96 | |||
| 97 | extern int set_thread_tidr(struct task_struct *t); | ||
| 98 | extern void clear_thread_tidr(struct task_struct *t); | ||
| 99 | |||
| 95 | #endif /* _ASM_POWERPC_SWITCH_TO_H */ | 100 | #endif /* _ASM_POWERPC_SWITCH_TO_H */ |
diff --git a/arch/powerpc/include/asm/tlbflush.h b/arch/powerpc/include/asm/tlbflush.h index 13dbcd41885e..7d5a157c7832 100644 --- a/arch/powerpc/include/asm/tlbflush.h +++ b/arch/powerpc/include/asm/tlbflush.h | |||
| @@ -77,7 +77,7 @@ static inline void local_flush_tlb_mm(struct mm_struct *mm) | |||
| 77 | flush_tlb_mm(mm); | 77 | flush_tlb_mm(mm); |
| 78 | } | 78 | } |
| 79 | 79 | ||
| 80 | #elif defined(CONFIG_PPC_STD_MMU_64) | 80 | #elif defined(CONFIG_PPC_BOOK3S_64) |
| 81 | #include <asm/book3s/64/tlbflush.h> | 81 | #include <asm/book3s/64/tlbflush.h> |
| 82 | #else | 82 | #else |
| 83 | #error Unsupported MMU type | 83 | #error Unsupported MMU type |
diff --git a/arch/powerpc/include/asm/tm.h b/arch/powerpc/include/asm/tm.h index a8bc72a7f4be..b1658c97047c 100644 --- a/arch/powerpc/include/asm/tm.h +++ b/arch/powerpc/include/asm/tm.h | |||
| @@ -12,12 +12,13 @@ | |||
| 12 | 12 | ||
| 13 | extern void tm_enable(void); | 13 | extern void tm_enable(void); |
| 14 | extern void tm_reclaim(struct thread_struct *thread, | 14 | extern void tm_reclaim(struct thread_struct *thread, |
| 15 | unsigned long orig_msr, uint8_t cause); | 15 | uint8_t cause); |
| 16 | extern void tm_reclaim_current(uint8_t cause); | 16 | extern void tm_reclaim_current(uint8_t cause); |
| 17 | extern void tm_recheckpoint(struct thread_struct *thread, | 17 | extern void tm_recheckpoint(struct thread_struct *thread); |
| 18 | unsigned long orig_msr); | ||
| 19 | extern void tm_abort(uint8_t cause); | 18 | extern void tm_abort(uint8_t cause); |
| 20 | extern void tm_save_sprs(struct thread_struct *thread); | 19 | extern void tm_save_sprs(struct thread_struct *thread); |
| 21 | extern void tm_restore_sprs(struct thread_struct *thread); | 20 | extern void tm_restore_sprs(struct thread_struct *thread); |
| 22 | 21 | ||
| 22 | extern bool tm_suspend_disabled; | ||
| 23 | |||
| 23 | #endif /* __ASSEMBLY__ */ | 24 | #endif /* __ASSEMBLY__ */ |
diff --git a/arch/powerpc/include/asm/topology.h b/arch/powerpc/include/asm/topology.h index 023ff9f17501..88187c285c70 100644 --- a/arch/powerpc/include/asm/topology.h +++ b/arch/powerpc/include/asm/topology.h | |||
| @@ -97,6 +97,14 @@ static inline int prrn_is_enabled(void) | |||
| 97 | } | 97 | } |
| 98 | #endif /* CONFIG_NUMA && CONFIG_PPC_SPLPAR */ | 98 | #endif /* CONFIG_NUMA && CONFIG_PPC_SPLPAR */ |
| 99 | 99 | ||
| 100 | #if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_NEED_MULTIPLE_NODES) | ||
| 101 | #if defined(CONFIG_PPC_SPLPAR) | ||
| 102 | extern int timed_topology_update(int nsecs); | ||
| 103 | #else | ||
| 104 | #define timed_topology_update(nsecs) | ||
| 105 | #endif /* CONFIG_PPC_SPLPAR */ | ||
| 106 | #endif /* CONFIG_HOTPLUG_CPU || CONFIG_NEED_MULTIPLE_NODES */ | ||
| 107 | |||
| 100 | #include <asm-generic/topology.h> | 108 | #include <asm-generic/topology.h> |
| 101 | 109 | ||
| 102 | #ifdef CONFIG_SMP | 110 | #ifdef CONFIG_SMP |
diff --git a/arch/powerpc/include/asm/uaccess.h b/arch/powerpc/include/asm/uaccess.h index 11f4bd07cce0..51bfeb8777f0 100644 --- a/arch/powerpc/include/asm/uaccess.h +++ b/arch/powerpc/include/asm/uaccess.h | |||
| @@ -174,6 +174,23 @@ do { \ | |||
| 174 | 174 | ||
| 175 | extern long __get_user_bad(void); | 175 | extern long __get_user_bad(void); |
| 176 | 176 | ||
| 177 | /* | ||
| 178 | * This does an atomic 128 byte aligned load from userspace. | ||
| 179 | * Upto caller to do enable_kernel_vmx() before calling! | ||
| 180 | */ | ||
| 181 | #define __get_user_atomic_128_aligned(kaddr, uaddr, err) \ | ||
| 182 | __asm__ __volatile__( \ | ||
| 183 | "1: lvx 0,0,%1 # get user\n" \ | ||
| 184 | " stvx 0,0,%2 # put kernel\n" \ | ||
| 185 | "2:\n" \ | ||
| 186 | ".section .fixup,\"ax\"\n" \ | ||
| 187 | "3: li %0,%3\n" \ | ||
| 188 | " b 2b\n" \ | ||
| 189 | ".previous\n" \ | ||
| 190 | EX_TABLE(1b, 3b) \ | ||
| 191 | : "=r" (err) \ | ||
| 192 | : "b" (uaddr), "b" (kaddr), "i" (-EFAULT), "0" (err)) | ||
| 193 | |||
| 177 | #define __get_user_asm(x, addr, err, op) \ | 194 | #define __get_user_asm(x, addr, err, op) \ |
| 178 | __asm__ __volatile__( \ | 195 | __asm__ __volatile__( \ |
| 179 | "1: "op" %1,0(%2) # get_user\n" \ | 196 | "1: "op" %1,0(%2) # get_user\n" \ |
| @@ -340,4 +357,9 @@ static inline unsigned long clear_user(void __user *addr, unsigned long size) | |||
| 340 | extern long strncpy_from_user(char *dst, const char __user *src, long count); | 357 | extern long strncpy_from_user(char *dst, const char __user *src, long count); |
| 341 | extern __must_check long strnlen_user(const char __user *str, long n); | 358 | extern __must_check long strnlen_user(const char __user *str, long n); |
| 342 | 359 | ||
| 360 | extern long __copy_from_user_flushcache(void *dst, const void __user *src, | ||
| 361 | unsigned size); | ||
| 362 | extern void memcpy_page_flushcache(char *to, struct page *page, size_t offset, | ||
| 363 | size_t len); | ||
| 364 | |||
| 343 | #endif /* _ARCH_POWERPC_UACCESS_H */ | 365 | #endif /* _ARCH_POWERPC_UACCESS_H */ |
diff --git a/arch/powerpc/include/asm/vas.h b/arch/powerpc/include/asm/vas.h index fd5963acd658..771456227496 100644 --- a/arch/powerpc/include/asm/vas.h +++ b/arch/powerpc/include/asm/vas.h | |||
| @@ -10,6 +10,8 @@ | |||
| 10 | #ifndef _ASM_POWERPC_VAS_H | 10 | #ifndef _ASM_POWERPC_VAS_H |
| 11 | #define _ASM_POWERPC_VAS_H | 11 | #define _ASM_POWERPC_VAS_H |
| 12 | 12 | ||
| 13 | struct vas_window; | ||
| 14 | |||
| 13 | /* | 15 | /* |
| 14 | * Min and max FIFO sizes are based on Version 1.05 Section 3.1.4.25 | 16 | * Min and max FIFO sizes are based on Version 1.05 Section 3.1.4.25 |
| 15 | * (Local FIFO Size Register) of the VAS workbook. | 17 | * (Local FIFO Size Register) of the VAS workbook. |
| @@ -104,6 +106,15 @@ struct vas_tx_win_attr { | |||
| 104 | }; | 106 | }; |
| 105 | 107 | ||
| 106 | /* | 108 | /* |
| 109 | * Helper to map a chip id to VAS id. | ||
| 110 | * For POWER9, this is a 1:1 mapping. In the future this maybe a 1:N | ||
| 111 | * mapping in which case, we will need to update this helper. | ||
| 112 | * | ||
| 113 | * Return the VAS id or -1 if no matching vasid is found. | ||
| 114 | */ | ||
| 115 | int chip_to_vas_id(int chipid); | ||
| 116 | |||
| 117 | /* | ||
| 107 | * Helper to initialize receive window attributes to defaults for an | 118 | * Helper to initialize receive window attributes to defaults for an |
| 108 | * NX window. | 119 | * NX window. |
| 109 | */ | 120 | */ |
| @@ -156,4 +167,14 @@ int vas_copy_crb(void *crb, int offset); | |||
| 156 | */ | 167 | */ |
| 157 | int vas_paste_crb(struct vas_window *win, int offset, bool re); | 168 | int vas_paste_crb(struct vas_window *win, int offset, bool re); |
| 158 | 169 | ||
| 170 | /* | ||
| 171 | * Return a system-wide unique id for the VAS window @win. | ||
| 172 | */ | ||
| 173 | extern u32 vas_win_id(struct vas_window *win); | ||
| 174 | |||
| 175 | /* | ||
| 176 | * Return the power bus paste address associated with @win so the caller | ||
| 177 | * can map that address into their address space. | ||
| 178 | */ | ||
| 179 | extern u64 vas_win_paste_addr(struct vas_window *win); | ||
| 159 | #endif /* __ASM_POWERPC_VAS_H */ | 180 | #endif /* __ASM_POWERPC_VAS_H */ |
diff --git a/arch/powerpc/include/uapi/asm/cputable.h b/arch/powerpc/include/uapi/asm/cputable.h index 50bcb4295de4..540592034740 100644 --- a/arch/powerpc/include/uapi/asm/cputable.h +++ b/arch/powerpc/include/uapi/asm/cputable.h | |||
| @@ -49,6 +49,7 @@ | |||
| 49 | #define PPC_FEATURE2_HAS_IEEE128 0x00400000 /* VSX IEEE Binary Float 128-bit */ | 49 | #define PPC_FEATURE2_HAS_IEEE128 0x00400000 /* VSX IEEE Binary Float 128-bit */ |
| 50 | #define PPC_FEATURE2_DARN 0x00200000 /* darn random number insn */ | 50 | #define PPC_FEATURE2_DARN 0x00200000 /* darn random number insn */ |
| 51 | #define PPC_FEATURE2_SCV 0x00100000 /* scv syscall */ | 51 | #define PPC_FEATURE2_SCV 0x00100000 /* scv syscall */ |
| 52 | #define PPC_FEATURE2_HTM_NO_SUSPEND 0x00080000 /* TM w/out suspended state */ | ||
| 52 | 53 | ||
| 53 | /* | 54 | /* |
| 54 | * IMPORTANT! | 55 | * IMPORTANT! |
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 6c6cce937dd8..1b6bc7fba996 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile | |||
| @@ -129,7 +129,7 @@ obj64-$(CONFIG_PPC_TRANSACTIONAL_MEM) += tm.o | |||
| 129 | obj-$(CONFIG_PPC64) += $(obj64-y) | 129 | obj-$(CONFIG_PPC64) += $(obj64-y) |
| 130 | obj-$(CONFIG_PPC32) += $(obj32-y) | 130 | obj-$(CONFIG_PPC32) += $(obj32-y) |
| 131 | 131 | ||
| 132 | ifneq ($(CONFIG_XMON)$(CONFIG_KEXEC_CORE),) | 132 | ifneq ($(CONFIG_XMON)$(CONFIG_KEXEC_CORE)(CONFIG_PPC_BOOK3S),) |
| 133 | obj-y += ppc_save_regs.o | 133 | obj-y += ppc_save_regs.o |
| 134 | endif | 134 | endif |
| 135 | 135 | ||
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 8cfb20e38cfe..9aace433491a 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c | |||
| @@ -185,7 +185,7 @@ int main(void) | |||
| 185 | #ifdef CONFIG_PPC_MM_SLICES | 185 | #ifdef CONFIG_PPC_MM_SLICES |
| 186 | OFFSET(PACALOWSLICESPSIZE, paca_struct, mm_ctx_low_slices_psize); | 186 | OFFSET(PACALOWSLICESPSIZE, paca_struct, mm_ctx_low_slices_psize); |
| 187 | OFFSET(PACAHIGHSLICEPSIZE, paca_struct, mm_ctx_high_slices_psize); | 187 | OFFSET(PACAHIGHSLICEPSIZE, paca_struct, mm_ctx_high_slices_psize); |
| 188 | DEFINE(PACA_ADDR_LIMIT, offsetof(struct paca_struct, addr_limit)); | 188 | OFFSET(PACA_SLB_ADDR_LIMIT, paca_struct, mm_ctx_slb_addr_limit); |
| 189 | DEFINE(MMUPSIZEDEFSIZE, sizeof(struct mmu_psize_def)); | 189 | DEFINE(MMUPSIZEDEFSIZE, sizeof(struct mmu_psize_def)); |
| 190 | #endif /* CONFIG_PPC_MM_SLICES */ | 190 | #endif /* CONFIG_PPC_MM_SLICES */ |
| 191 | #endif | 191 | #endif |
| @@ -208,7 +208,7 @@ int main(void) | |||
| 208 | OFFSET(TCD_ESEL_FIRST, tlb_core_data, esel_first); | 208 | OFFSET(TCD_ESEL_FIRST, tlb_core_data, esel_first); |
| 209 | #endif /* CONFIG_PPC_BOOK3E */ | 209 | #endif /* CONFIG_PPC_BOOK3E */ |
| 210 | 210 | ||
| 211 | #ifdef CONFIG_PPC_STD_MMU_64 | 211 | #ifdef CONFIG_PPC_BOOK3S_64 |
| 212 | OFFSET(PACASLBCACHE, paca_struct, slb_cache); | 212 | OFFSET(PACASLBCACHE, paca_struct, slb_cache); |
| 213 | OFFSET(PACASLBCACHEPTR, paca_struct, slb_cache_ptr); | 213 | OFFSET(PACASLBCACHEPTR, paca_struct, slb_cache_ptr); |
| 214 | OFFSET(PACAVMALLOCSLLP, paca_struct, vmalloc_sllp); | 214 | OFFSET(PACAVMALLOCSLLP, paca_struct, vmalloc_sllp); |
| @@ -230,7 +230,7 @@ int main(void) | |||
| 230 | OFFSET(LPPACA_DTLIDX, lppaca, dtl_idx); | 230 | OFFSET(LPPACA_DTLIDX, lppaca, dtl_idx); |
| 231 | OFFSET(LPPACA_YIELDCOUNT, lppaca, yield_count); | 231 | OFFSET(LPPACA_YIELDCOUNT, lppaca, yield_count); |
| 232 | OFFSET(PACA_DTL_RIDX, paca_struct, dtl_ridx); | 232 | OFFSET(PACA_DTL_RIDX, paca_struct, dtl_ridx); |
| 233 | #endif /* CONFIG_PPC_STD_MMU_64 */ | 233 | #endif /* CONFIG_PPC_BOOK3S_64 */ |
| 234 | OFFSET(PACAEMERGSP, paca_struct, emergency_sp); | 234 | OFFSET(PACAEMERGSP, paca_struct, emergency_sp); |
| 235 | #ifdef CONFIG_PPC_BOOK3S_64 | 235 | #ifdef CONFIG_PPC_BOOK3S_64 |
| 236 | OFFSET(PACAMCEMERGSP, paca_struct, mc_emergency_sp); | 236 | OFFSET(PACAMCEMERGSP, paca_struct, mc_emergency_sp); |
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 760872916013..1350f49d81a8 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c | |||
| @@ -547,11 +547,31 @@ static struct cpu_spec __initdata cpu_specs[] = { | |||
| 547 | .machine_check_early = __machine_check_early_realmode_p9, | 547 | .machine_check_early = __machine_check_early_realmode_p9, |
| 548 | .platform = "power9", | 548 | .platform = "power9", |
| 549 | }, | 549 | }, |
| 550 | { /* Power9 */ | 550 | { /* Power9 DD2.0 */ |
| 551 | .pvr_mask = 0xffffefff, | ||
| 552 | .pvr_value = 0x004e0200, | ||
| 553 | .cpu_name = "POWER9 (raw)", | ||
| 554 | .cpu_features = CPU_FTRS_POWER9_DD2_0, | ||
| 555 | .cpu_user_features = COMMON_USER_POWER9, | ||
| 556 | .cpu_user_features2 = COMMON_USER2_POWER9, | ||
| 557 | .mmu_features = MMU_FTRS_POWER9, | ||
| 558 | .icache_bsize = 128, | ||
| 559 | .dcache_bsize = 128, | ||
| 560 | .num_pmcs = 6, | ||
| 561 | .pmc_type = PPC_PMC_IBM, | ||
| 562 | .oprofile_cpu_type = "ppc64/power9", | ||
| 563 | .oprofile_type = PPC_OPROFILE_INVALID, | ||
| 564 | .cpu_setup = __setup_cpu_power9, | ||
| 565 | .cpu_restore = __restore_cpu_power9, | ||
| 566 | .flush_tlb = __flush_tlb_power9, | ||
| 567 | .machine_check_early = __machine_check_early_realmode_p9, | ||
| 568 | .platform = "power9", | ||
| 569 | }, | ||
| 570 | { /* Power9 DD 2.1 or later (see DD2.0 above) */ | ||
| 551 | .pvr_mask = 0xffff0000, | 571 | .pvr_mask = 0xffff0000, |
| 552 | .pvr_value = 0x004e0000, | 572 | .pvr_value = 0x004e0000, |
| 553 | .cpu_name = "POWER9 (raw)", | 573 | .cpu_name = "POWER9 (raw)", |
| 554 | .cpu_features = CPU_FTRS_POWER9, | 574 | .cpu_features = CPU_FTRS_POWER9_DD2_1, |
| 555 | .cpu_user_features = COMMON_USER_POWER9, | 575 | .cpu_user_features = COMMON_USER_POWER9, |
| 556 | .cpu_user_features2 = COMMON_USER2_POWER9, | 576 | .cpu_user_features2 = COMMON_USER2_POWER9, |
| 557 | .mmu_features = MMU_FTRS_POWER9, | 577 | .mmu_features = MMU_FTRS_POWER9, |
diff --git a/arch/powerpc/kernel/dt_cpu_ftrs.c b/arch/powerpc/kernel/dt_cpu_ftrs.c index 7275fed271af..602e0fde19b4 100644 --- a/arch/powerpc/kernel/dt_cpu_ftrs.c +++ b/arch/powerpc/kernel/dt_cpu_ftrs.c | |||
| @@ -634,7 +634,7 @@ static struct dt_cpu_feature_match __initdata | |||
| 634 | {"no-execute", feat_enable, 0}, | 634 | {"no-execute", feat_enable, 0}, |
| 635 | {"strong-access-ordering", feat_enable, CPU_FTR_SAO}, | 635 | {"strong-access-ordering", feat_enable, CPU_FTR_SAO}, |
| 636 | {"cache-inhibited-large-page", feat_enable_large_ci, 0}, | 636 | {"cache-inhibited-large-page", feat_enable_large_ci, 0}, |
| 637 | {"coprocessor-icswx", feat_enable, CPU_FTR_ICSWX}, | 637 | {"coprocessor-icswx", feat_enable, 0}, |
| 638 | {"hypervisor-virtualization-interrupt", feat_enable_hvi, 0}, | 638 | {"hypervisor-virtualization-interrupt", feat_enable_hvi, 0}, |
| 639 | {"program-priority-register", feat_enable, CPU_FTR_HAS_PPR}, | 639 | {"program-priority-register", feat_enable, CPU_FTR_HAS_PPR}, |
| 640 | {"wait", feat_enable, 0}, | 640 | {"wait", feat_enable, 0}, |
| @@ -735,6 +735,8 @@ static __init void cpufeatures_cpu_quirks(void) | |||
| 735 | */ | 735 | */ |
| 736 | if ((version & 0xffffff00) == 0x004e0100) | 736 | if ((version & 0xffffff00) == 0x004e0100) |
| 737 | cur_cpu_spec->cpu_features |= CPU_FTR_POWER9_DD1; | 737 | cur_cpu_spec->cpu_features |= CPU_FTR_POWER9_DD1; |
| 738 | else if ((version & 0xffffefff) == 0x004e0200) | ||
| 739 | cur_cpu_spec->cpu_features &= ~CPU_FTR_POWER9_DD2_1; | ||
| 738 | } | 740 | } |
| 739 | 741 | ||
| 740 | static void __init cpufeatures_setup_finished(void) | 742 | static void __init cpufeatures_setup_finished(void) |
diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c index 116000b45531..cbca0a667682 100644 --- a/arch/powerpc/kernel/eeh.c +++ b/arch/powerpc/kernel/eeh.c | |||
| @@ -972,6 +972,18 @@ static struct notifier_block eeh_reboot_nb = { | |||
| 972 | .notifier_call = eeh_reboot_notifier, | 972 | .notifier_call = eeh_reboot_notifier, |
| 973 | }; | 973 | }; |
| 974 | 974 | ||
| 975 | void eeh_probe_devices(void) | ||
| 976 | { | ||
| 977 | struct pci_controller *hose, *tmp; | ||
| 978 | struct pci_dn *pdn; | ||
| 979 | |||
| 980 | /* Enable EEH for all adapters */ | ||
| 981 | list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { | ||
| 982 | pdn = hose->pci_data; | ||
| 983 | traverse_pci_dn(pdn, eeh_ops->probe, NULL); | ||
| 984 | } | ||
| 985 | } | ||
| 986 | |||
| 975 | /** | 987 | /** |
| 976 | * eeh_init - EEH initialization | 988 | * eeh_init - EEH initialization |
| 977 | * | 989 | * |
| @@ -987,22 +999,11 @@ static struct notifier_block eeh_reboot_nb = { | |||
| 987 | * Even if force-off is set, the EEH hardware is still enabled, so that | 999 | * Even if force-off is set, the EEH hardware is still enabled, so that |
| 988 | * newer systems can boot. | 1000 | * newer systems can boot. |
| 989 | */ | 1001 | */ |
| 990 | int eeh_init(void) | 1002 | static int eeh_init(void) |
| 991 | { | 1003 | { |
| 992 | struct pci_controller *hose, *tmp; | 1004 | struct pci_controller *hose, *tmp; |
| 993 | struct pci_dn *pdn; | ||
| 994 | static int cnt = 0; | ||
| 995 | int ret = 0; | 1005 | int ret = 0; |
| 996 | 1006 | ||
| 997 | /* | ||
| 998 | * We have to delay the initialization on PowerNV after | ||
| 999 | * the PCI hierarchy tree has been built because the PEs | ||
| 1000 | * are figured out based on PCI devices instead of device | ||
| 1001 | * tree nodes | ||
| 1002 | */ | ||
| 1003 | if (machine_is(powernv) && cnt++ <= 0) | ||
| 1004 | return ret; | ||
| 1005 | |||
| 1006 | /* Register reboot notifier */ | 1007 | /* Register reboot notifier */ |
| 1007 | ret = register_reboot_notifier(&eeh_reboot_nb); | 1008 | ret = register_reboot_notifier(&eeh_reboot_nb); |
| 1008 | if (ret) { | 1009 | if (ret) { |
| @@ -1028,22 +1029,7 @@ int eeh_init(void) | |||
| 1028 | if (ret) | 1029 | if (ret) |
| 1029 | return ret; | 1030 | return ret; |
| 1030 | 1031 | ||
| 1031 | /* Enable EEH for all adapters */ | 1032 | eeh_probe_devices(); |
| 1032 | list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { | ||
| 1033 | pdn = hose->pci_data; | ||
| 1034 | traverse_pci_dn(pdn, eeh_ops->probe, NULL); | ||
| 1035 | } | ||
| 1036 | |||
| 1037 | /* | ||
| 1038 | * Call platform post-initialization. Actually, It's good chance | ||
| 1039 | * to inform platform that EEH is ready to supply service if the | ||
| 1040 | * I/O cache stuff has been built up. | ||
| 1041 | */ | ||
| 1042 | if (eeh_ops->post_init) { | ||
| 1043 | ret = eeh_ops->post_init(); | ||
| 1044 | if (ret) | ||
| 1045 | return ret; | ||
| 1046 | } | ||
| 1047 | 1033 | ||
| 1048 | if (eeh_enabled()) | 1034 | if (eeh_enabled()) |
| 1049 | pr_info("EEH: PCI Enhanced I/O Error Handling Enabled\n"); | 1035 | pr_info("EEH: PCI Enhanced I/O Error Handling Enabled\n"); |
| @@ -1757,10 +1743,6 @@ static int eeh_enable_dbgfs_set(void *data, u64 val) | |||
| 1757 | else | 1743 | else |
| 1758 | eeh_add_flag(EEH_FORCE_DISABLED); | 1744 | eeh_add_flag(EEH_FORCE_DISABLED); |
| 1759 | 1745 | ||
| 1760 | /* Notify the backend */ | ||
| 1761 | if (eeh_ops->post_init) | ||
| 1762 | eeh_ops->post_init(); | ||
| 1763 | |||
| 1764 | return 0; | 1746 | return 0; |
| 1765 | } | 1747 | } |
| 1766 | 1748 | ||
diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c index 4e1b433f6cb5..4f71e4c9beb7 100644 --- a/arch/powerpc/kernel/eeh_driver.c +++ b/arch/powerpc/kernel/eeh_driver.c | |||
| @@ -623,7 +623,7 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus, | |||
| 623 | struct eeh_rmv_data *rmv_data) | 623 | struct eeh_rmv_data *rmv_data) |
| 624 | { | 624 | { |
| 625 | struct pci_bus *frozen_bus = eeh_pe_bus_get(pe); | 625 | struct pci_bus *frozen_bus = eeh_pe_bus_get(pe); |
| 626 | struct timeval tstamp; | 626 | time64_t tstamp; |
| 627 | int cnt, rc; | 627 | int cnt, rc; |
| 628 | struct eeh_dev *edev; | 628 | struct eeh_dev *edev; |
| 629 | 629 | ||
diff --git a/arch/powerpc/kernel/eeh_pe.c b/arch/powerpc/kernel/eeh_pe.c index 2e8d1b2b5af4..2d4956e97aa9 100644 --- a/arch/powerpc/kernel/eeh_pe.c +++ b/arch/powerpc/kernel/eeh_pe.c | |||
| @@ -526,16 +526,16 @@ int eeh_rmv_from_parent_pe(struct eeh_dev *edev) | |||
| 526 | */ | 526 | */ |
| 527 | void eeh_pe_update_time_stamp(struct eeh_pe *pe) | 527 | void eeh_pe_update_time_stamp(struct eeh_pe *pe) |
| 528 | { | 528 | { |
| 529 | struct timeval tstamp; | 529 | time64_t tstamp; |
| 530 | 530 | ||
| 531 | if (!pe) return; | 531 | if (!pe) return; |
| 532 | 532 | ||
| 533 | if (pe->freeze_count <= 0) { | 533 | if (pe->freeze_count <= 0) { |
| 534 | pe->freeze_count = 0; | 534 | pe->freeze_count = 0; |
| 535 | do_gettimeofday(&pe->tstamp); | 535 | pe->tstamp = ktime_get_seconds(); |
| 536 | } else { | 536 | } else { |
| 537 | do_gettimeofday(&tstamp); | 537 | tstamp = ktime_get_seconds(); |
| 538 | if (tstamp.tv_sec - pe->tstamp.tv_sec > 3600) { | 538 | if (tstamp - pe->tstamp > 3600) { |
| 539 | pe->tstamp = tstamp; | 539 | pe->tstamp = tstamp; |
| 540 | pe->freeze_count = 0; | 540 | pe->freeze_count = 0; |
| 541 | } | 541 | } |
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 4a0fd4f40245..3320bcac7192 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S | |||
| @@ -539,7 +539,7 @@ _GLOBAL(_switch) | |||
| 539 | std r6,PACACURRENT(r13) /* Set new 'current' */ | 539 | std r6,PACACURRENT(r13) /* Set new 'current' */ |
| 540 | 540 | ||
| 541 | ld r8,KSP(r4) /* new stack pointer */ | 541 | ld r8,KSP(r4) /* new stack pointer */ |
| 542 | #ifdef CONFIG_PPC_STD_MMU_64 | 542 | #ifdef CONFIG_PPC_BOOK3S_64 |
| 543 | BEGIN_MMU_FTR_SECTION | 543 | BEGIN_MMU_FTR_SECTION |
| 544 | b 2f | 544 | b 2f |
| 545 | END_MMU_FTR_SECTION_IFSET(MMU_FTR_TYPE_RADIX) | 545 | END_MMU_FTR_SECTION_IFSET(MMU_FTR_TYPE_RADIX) |
| @@ -588,7 +588,7 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT) | |||
| 588 | slbmte r7,r0 | 588 | slbmte r7,r0 |
| 589 | isync | 589 | isync |
| 590 | 2: | 590 | 2: |
| 591 | #endif /* CONFIG_PPC_STD_MMU_64 */ | 591 | #endif /* CONFIG_PPC_BOOK3S_64 */ |
| 592 | 592 | ||
| 593 | CURRENT_THREAD_INFO(r7, r8) /* base of new stack */ | 593 | CURRENT_THREAD_INFO(r7, r8) /* base of new stack */ |
| 594 | /* Note: this uses SWITCH_FRAME_SIZE rather than INT_FRAME_SIZE | 594 | /* Note: this uses SWITCH_FRAME_SIZE rather than INT_FRAME_SIZE |
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S index 1c80bd292e48..e441b469dc8f 100644 --- a/arch/powerpc/kernel/exceptions-64s.S +++ b/arch/powerpc/kernel/exceptions-64s.S | |||
| @@ -114,6 +114,7 @@ EXC_VIRT_NONE(0x4000, 0x100) | |||
| 114 | cmpwi cr3,r10,2 ; \ | 114 | cmpwi cr3,r10,2 ; \ |
| 115 | BRANCH_TO_C000(r10, system_reset_idle_common) ; \ | 115 | BRANCH_TO_C000(r10, system_reset_idle_common) ; \ |
| 116 | 1: \ | 116 | 1: \ |
| 117 | KVMTEST_PR(n) ; \ | ||
| 117 | END_FTR_SECTION_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206) | 118 | END_FTR_SECTION_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206) |
| 118 | #else | 119 | #else |
| 119 | #define IDLETEST NOTEST | 120 | #define IDLETEST NOTEST |
| @@ -130,6 +131,7 @@ EXC_REAL_BEGIN(system_reset, 0x100, 0x100) | |||
| 130 | 131 | ||
| 131 | EXC_REAL_END(system_reset, 0x100, 0x100) | 132 | EXC_REAL_END(system_reset, 0x100, 0x100) |
| 132 | EXC_VIRT_NONE(0x4100, 0x100) | 133 | EXC_VIRT_NONE(0x4100, 0x100) |
| 134 | TRAMP_KVM(PACA_EXNMI, 0x100) | ||
| 133 | 135 | ||
| 134 | #ifdef CONFIG_PPC_P7_NAP | 136 | #ifdef CONFIG_PPC_P7_NAP |
| 135 | EXC_COMMON_BEGIN(system_reset_idle_common) | 137 | EXC_COMMON_BEGIN(system_reset_idle_common) |
| @@ -233,7 +235,7 @@ BEGIN_FTR_SECTION | |||
| 233 | addi r10,r10,1 /* increment paca->in_mce */ | 235 | addi r10,r10,1 /* increment paca->in_mce */ |
| 234 | sth r10,PACA_IN_MCE(r13) | 236 | sth r10,PACA_IN_MCE(r13) |
| 235 | /* Limit nested MCE to level 4 to avoid stack overflow */ | 237 | /* Limit nested MCE to level 4 to avoid stack overflow */ |
| 236 | cmpwi r10,4 | 238 | cmpwi r10,MAX_MCE_DEPTH |
| 237 | bgt 2f /* Check if we hit limit of 4 */ | 239 | bgt 2f /* Check if we hit limit of 4 */ |
| 238 | std r11,GPR1(r1) /* Save r1 on the stack. */ | 240 | std r11,GPR1(r1) /* Save r1 on the stack. */ |
| 239 | std r11,0(r1) /* make stack chain pointer */ | 241 | std r11,0(r1) /* make stack chain pointer */ |
| @@ -542,7 +544,7 @@ EXC_COMMON_BEGIN(instruction_access_common) | |||
| 542 | RECONCILE_IRQ_STATE(r10, r11) | 544 | RECONCILE_IRQ_STATE(r10, r11) |
| 543 | ld r12,_MSR(r1) | 545 | ld r12,_MSR(r1) |
| 544 | ld r3,_NIP(r1) | 546 | ld r3,_NIP(r1) |
| 545 | andis. r4,r12,DSISR_BAD_FAULT_64S@h | 547 | andis. r4,r12,DSISR_SRR1_MATCH_64S@h |
| 546 | li r5,0x400 | 548 | li r5,0x400 |
| 547 | std r3,_DAR(r1) | 549 | std r3,_DAR(r1) |
| 548 | std r4,_DSISR(r1) | 550 | std r4,_DSISR(r1) |
| @@ -606,7 +608,7 @@ EXC_COMMON_BEGIN(slb_miss_common) | |||
| 606 | cmpdi cr5,r11,MSR_RI | 608 | cmpdi cr5,r11,MSR_RI |
| 607 | 609 | ||
| 608 | crset 4*cr0+eq | 610 | crset 4*cr0+eq |
| 609 | #ifdef CONFIG_PPC_STD_MMU_64 | 611 | #ifdef CONFIG_PPC_BOOK3S_64 |
| 610 | BEGIN_MMU_FTR_SECTION | 612 | BEGIN_MMU_FTR_SECTION |
| 611 | bl slb_allocate | 613 | bl slb_allocate |
| 612 | END_MMU_FTR_SECTION_IFCLR(MMU_FTR_TYPE_RADIX) | 614 | END_MMU_FTR_SECTION_IFCLR(MMU_FTR_TYPE_RADIX) |
| @@ -888,12 +890,6 @@ EXC_COMMON(trap_0b_common, 0xb00, unknown_exception) | |||
| 888 | #define LOAD_SYSCALL_HANDLER(reg) \ | 890 | #define LOAD_SYSCALL_HANDLER(reg) \ |
| 889 | __LOAD_HANDLER(reg, system_call_common) | 891 | __LOAD_HANDLER(reg, system_call_common) |
| 890 | 892 | ||
| 891 | #define SYSCALL_FASTENDIAN_TEST \ | ||
| 892 | BEGIN_FTR_SECTION \ | ||
| 893 | cmpdi r0,0x1ebe ; \ | ||
| 894 | beq- 1f ; \ | ||
| 895 | END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE) \ | ||
| 896 | |||
| 897 | /* | 893 | /* |
| 898 | * After SYSCALL_KVMTEST, we reach here with PACA in r13, r13 in r9, | 894 | * After SYSCALL_KVMTEST, we reach here with PACA in r13, r13 in r9, |
| 899 | * and HMT_MEDIUM. | 895 | * and HMT_MEDIUM. |
| @@ -908,6 +904,13 @@ END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE) \ | |||
| 908 | rfid ; \ | 904 | rfid ; \ |
| 909 | b . ; /* prevent speculative execution */ | 905 | b . ; /* prevent speculative execution */ |
| 910 | 906 | ||
| 907 | #ifdef CONFIG_PPC_FAST_ENDIAN_SWITCH | ||
| 908 | #define SYSCALL_FASTENDIAN_TEST \ | ||
| 909 | BEGIN_FTR_SECTION \ | ||
| 910 | cmpdi r0,0x1ebe ; \ | ||
| 911 | beq- 1f ; \ | ||
| 912 | END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE) \ | ||
| 913 | |||
| 911 | #define SYSCALL_FASTENDIAN \ | 914 | #define SYSCALL_FASTENDIAN \ |
| 912 | /* Fast LE/BE switch system call */ \ | 915 | /* Fast LE/BE switch system call */ \ |
| 913 | 1: mfspr r12,SPRN_SRR1 ; \ | 916 | 1: mfspr r12,SPRN_SRR1 ; \ |
| @@ -916,6 +919,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE) \ | |||
| 916 | mr r13,r9 ; \ | 919 | mr r13,r9 ; \ |
| 917 | rfid ; /* return to userspace */ \ | 920 | rfid ; /* return to userspace */ \ |
| 918 | b . ; /* prevent speculative execution */ | 921 | b . ; /* prevent speculative execution */ |
| 922 | #else | ||
| 923 | #define SYSCALL_FASTENDIAN_TEST | ||
| 924 | #define SYSCALL_FASTENDIAN | ||
| 925 | #endif /* CONFIG_PPC_FAST_ENDIAN_SWITCH */ | ||
| 919 | 926 | ||
| 920 | #if defined(CONFIG_RELOCATABLE) | 927 | #if defined(CONFIG_RELOCATABLE) |
| 921 | /* | 928 | /* |
| @@ -1033,6 +1040,8 @@ TRAMP_REAL_BEGIN(hmi_exception_early) | |||
| 1033 | EXCEPTION_PROLOG_COMMON_3(0xe60) | 1040 | EXCEPTION_PROLOG_COMMON_3(0xe60) |
| 1034 | addi r3,r1,STACK_FRAME_OVERHEAD | 1041 | addi r3,r1,STACK_FRAME_OVERHEAD |
| 1035 | BRANCH_LINK_TO_FAR(hmi_exception_realmode) /* Function call ABI */ | 1042 | BRANCH_LINK_TO_FAR(hmi_exception_realmode) /* Function call ABI */ |
| 1043 | cmpdi cr0,r3,0 | ||
| 1044 | |||
| 1036 | /* Windup the stack. */ | 1045 | /* Windup the stack. */ |
| 1037 | /* Move original HSRR0 and HSRR1 into the respective regs */ | 1046 | /* Move original HSRR0 and HSRR1 into the respective regs */ |
| 1038 | ld r9,_MSR(r1) | 1047 | ld r9,_MSR(r1) |
| @@ -1049,10 +1058,15 @@ TRAMP_REAL_BEGIN(hmi_exception_early) | |||
| 1049 | REST_8GPRS(2, r1) | 1058 | REST_8GPRS(2, r1) |
| 1050 | REST_GPR(10, r1) | 1059 | REST_GPR(10, r1) |
| 1051 | ld r11,_CCR(r1) | 1060 | ld r11,_CCR(r1) |
| 1061 | REST_2GPRS(12, r1) | ||
| 1062 | bne 1f | ||
| 1052 | mtcr r11 | 1063 | mtcr r11 |
| 1053 | REST_GPR(11, r1) | 1064 | REST_GPR(11, r1) |
| 1054 | REST_2GPRS(12, r1) | 1065 | ld r1,GPR1(r1) |
| 1055 | /* restore original r1. */ | 1066 | hrfid |
| 1067 | |||
| 1068 | 1: mtcr r11 | ||
| 1069 | REST_GPR(11, r1) | ||
| 1056 | ld r1,GPR1(r1) | 1070 | ld r1,GPR1(r1) |
| 1057 | 1071 | ||
| 1058 | /* | 1072 | /* |
| @@ -1065,8 +1079,9 @@ hmi_exception_after_realmode: | |||
| 1065 | EXCEPTION_PROLOG_0(PACA_EXGEN) | 1079 | EXCEPTION_PROLOG_0(PACA_EXGEN) |
| 1066 | b tramp_real_hmi_exception | 1080 | b tramp_real_hmi_exception |
| 1067 | 1081 | ||
| 1068 | EXC_COMMON_ASYNC(hmi_exception_common, 0xe60, handle_hmi_exception) | 1082 | EXC_COMMON_BEGIN(hmi_exception_common) |
| 1069 | 1083 | EXCEPTION_COMMON(PACA_EXGEN, 0xe60, hmi_exception_common, handle_hmi_exception, | |
| 1084 | ret_from_except, FINISH_NAP;ADD_NVGPRS;ADD_RECONCILE;RUNLATCH_ON) | ||
| 1070 | 1085 | ||
| 1071 | EXC_REAL_OOL_MASKABLE_HV(h_doorbell, 0xe80, 0x20) | 1086 | EXC_REAL_OOL_MASKABLE_HV(h_doorbell, 0xe80, 0x20) |
| 1072 | EXC_VIRT_OOL_MASKABLE_HV(h_doorbell, 0x4e80, 0x20, 0xe80) | 1087 | EXC_VIRT_OOL_MASKABLE_HV(h_doorbell, 0x4e80, 0x20, 0xe80) |
| @@ -1505,8 +1520,8 @@ USE_TEXT_SECTION() | |||
| 1505 | */ | 1520 | */ |
| 1506 | .balign IFETCH_ALIGN_BYTES | 1521 | .balign IFETCH_ALIGN_BYTES |
| 1507 | do_hash_page: | 1522 | do_hash_page: |
| 1508 | #ifdef CONFIG_PPC_STD_MMU_64 | 1523 | #ifdef CONFIG_PPC_BOOK3S_64 |
| 1509 | lis r0,DSISR_BAD_FAULT_64S@h | 1524 | lis r0,(DSISR_BAD_FAULT_64S|DSISR_DABRMATCH)@h |
| 1510 | ori r0,r0,DSISR_BAD_FAULT_64S@l | 1525 | ori r0,r0,DSISR_BAD_FAULT_64S@l |
| 1511 | and. r0,r4,r0 /* weird error? */ | 1526 | and. r0,r4,r0 /* weird error? */ |
| 1512 | bne- handle_page_fault /* if not, try to insert a HPTE */ | 1527 | bne- handle_page_fault /* if not, try to insert a HPTE */ |
| @@ -1536,7 +1551,7 @@ do_hash_page: | |||
| 1536 | 1551 | ||
| 1537 | /* Reload DSISR into r4 for the DABR check below */ | 1552 | /* Reload DSISR into r4 for the DABR check below */ |
| 1538 | ld r4,_DSISR(r1) | 1553 | ld r4,_DSISR(r1) |
| 1539 | #endif /* CONFIG_PPC_STD_MMU_64 */ | 1554 | #endif /* CONFIG_PPC_BOOK3S_64 */ |
| 1540 | 1555 | ||
| 1541 | /* Here we have a page fault that hash_page can't handle. */ | 1556 | /* Here we have a page fault that hash_page can't handle. */ |
| 1542 | handle_page_fault: | 1557 | handle_page_fault: |
| @@ -1565,7 +1580,7 @@ handle_dabr_fault: | |||
| 1565 | 12: b ret_from_except_lite | 1580 | 12: b ret_from_except_lite |
| 1566 | 1581 | ||
| 1567 | 1582 | ||
| 1568 | #ifdef CONFIG_PPC_STD_MMU_64 | 1583 | #ifdef CONFIG_PPC_BOOK3S_64 |
| 1569 | /* We have a page fault that hash_page could handle but HV refused | 1584 | /* We have a page fault that hash_page could handle but HV refused |
| 1570 | * the PTE insertion | 1585 | * the PTE insertion |
| 1571 | */ | 1586 | */ |
diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c index e1431800bfb9..04ea5c04fd24 100644 --- a/arch/powerpc/kernel/fadump.c +++ b/arch/powerpc/kernel/fadump.c | |||
| @@ -1270,10 +1270,15 @@ static ssize_t fadump_release_memory_store(struct kobject *kobj, | |||
| 1270 | struct kobj_attribute *attr, | 1270 | struct kobj_attribute *attr, |
| 1271 | const char *buf, size_t count) | 1271 | const char *buf, size_t count) |
| 1272 | { | 1272 | { |
| 1273 | int input = -1; | ||
| 1274 | |||
| 1273 | if (!fw_dump.dump_active) | 1275 | if (!fw_dump.dump_active) |
| 1274 | return -EPERM; | 1276 | return -EPERM; |
| 1275 | 1277 | ||
| 1276 | if (buf[0] == '1') { | 1278 | if (kstrtoint(buf, 0, &input)) |
| 1279 | return -EINVAL; | ||
| 1280 | |||
| 1281 | if (input == 1) { | ||
| 1277 | /* | 1282 | /* |
| 1278 | * Take away the '/proc/vmcore'. We are releasing the dump | 1283 | * Take away the '/proc/vmcore'. We are releasing the dump |
| 1279 | * memory, hence it will not be valid anymore. | 1284 | * memory, hence it will not be valid anymore. |
| @@ -1307,21 +1312,25 @@ static ssize_t fadump_register_store(struct kobject *kobj, | |||
| 1307 | const char *buf, size_t count) | 1312 | const char *buf, size_t count) |
| 1308 | { | 1313 | { |
| 1309 | int ret = 0; | 1314 | int ret = 0; |
| 1315 | int input = -1; | ||
| 1310 | 1316 | ||
| 1311 | if (!fw_dump.fadump_enabled || fdm_active) | 1317 | if (!fw_dump.fadump_enabled || fdm_active) |
| 1312 | return -EPERM; | 1318 | return -EPERM; |
| 1313 | 1319 | ||
| 1320 | if (kstrtoint(buf, 0, &input)) | ||
| 1321 | return -EINVAL; | ||
| 1322 | |||
| 1314 | mutex_lock(&fadump_mutex); | 1323 | mutex_lock(&fadump_mutex); |
| 1315 | 1324 | ||
| 1316 | switch (buf[0]) { | 1325 | switch (input) { |
| 1317 | case '0': | 1326 | case 0: |
| 1318 | if (fw_dump.dump_registered == 0) { | 1327 | if (fw_dump.dump_registered == 0) { |
| 1319 | goto unlock_out; | 1328 | goto unlock_out; |
| 1320 | } | 1329 | } |
| 1321 | /* Un-register Firmware-assisted dump */ | 1330 | /* Un-register Firmware-assisted dump */ |
| 1322 | fadump_unregister_dump(&fdm); | 1331 | fadump_unregister_dump(&fdm); |
| 1323 | break; | 1332 | break; |
| 1324 | case '1': | 1333 | case 1: |
| 1325 | if (fw_dump.dump_registered == 1) { | 1334 | if (fw_dump.dump_registered == 1) { |
| 1326 | ret = -EEXIST; | 1335 | ret = -EEXIST; |
| 1327 | goto unlock_out; | 1336 | goto unlock_out; |
diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S index 8c54166491e7..29b2fed93289 100644 --- a/arch/powerpc/kernel/head_32.S +++ b/arch/powerpc/kernel/head_32.S | |||
| @@ -388,7 +388,7 @@ DataAccess: | |||
| 388 | EXCEPTION_PROLOG | 388 | EXCEPTION_PROLOG |
| 389 | mfspr r10,SPRN_DSISR | 389 | mfspr r10,SPRN_DSISR |
| 390 | stw r10,_DSISR(r11) | 390 | stw r10,_DSISR(r11) |
| 391 | andis. r0,r10,DSISR_BAD_FAULT_32S@h | 391 | andis. r0,r10,(DSISR_BAD_FAULT_32S|DSISR_DABRMATCH)@h |
| 392 | bne 1f /* if not, try to put a PTE */ | 392 | bne 1f /* if not, try to put a PTE */ |
| 393 | mfspr r4,SPRN_DAR /* into the hash table */ | 393 | mfspr r4,SPRN_DAR /* into the hash table */ |
| 394 | rlwinm r3,r10,32-15,21,21 /* DSISR_STORE -> _PAGE_RW */ | 394 | rlwinm r3,r10,32-15,21,21 /* DSISR_STORE -> _PAGE_RW */ |
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index ff8511d6d8ea..aa71a90f5222 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S | |||
| @@ -55,12 +55,18 @@ | |||
| 55 | * | 55 | * |
| 56 | * For pSeries or server processors: | 56 | * For pSeries or server processors: |
| 57 | * 1. The MMU is off & open firmware is running in real mode. | 57 | * 1. The MMU is off & open firmware is running in real mode. |
| 58 | * 2. The kernel is entered at __start | 58 | * 2. The primary CPU enters at __start. |
| 59 | * 3. If the RTAS supports "query-cpu-stopped-state", then secondary | ||
| 60 | * CPUs will enter as directed by "start-cpu" RTAS call, which is | ||
| 61 | * generic_secondary_smp_init, with PIR in r3. | ||
| 62 | * 4. Else the secondary CPUs will enter at secondary_hold (0x60) as | ||
| 63 | * directed by the "start-cpu" RTS call, with PIR in r3. | ||
| 59 | * -or- For OPAL entry: | 64 | * -or- For OPAL entry: |
| 60 | * 1. The MMU is off, processor in HV mode, primary CPU enters at 0 | 65 | * 1. The MMU is off, processor in HV mode. |
| 61 | * with device-tree in gpr3. We also get OPAL base in r8 and | 66 | * 2. The primary CPU enters at 0 with device-tree in r3, OPAL base |
| 62 | * entry in r9 for debugging purposes | 67 | * in r8, and entry in r9 for debugging purposes. |
| 63 | * 2. Secondary processors enter at 0x60 with PIR in gpr3 | 68 | * 3. Secondary CPUs enter as directed by OPAL_START_CPU call, which |
| 69 | * is at generic_secondary_smp_init, with PIR in r3. | ||
| 64 | * | 70 | * |
| 65 | * For Book3E processors: | 71 | * For Book3E processors: |
| 66 | * 1. The MMU is on running in AS0 in a state defined in ePAPR | 72 | * 1. The MMU is on running in AS0 in a state defined in ePAPR |
diff --git a/arch/powerpc/kernel/idle_book3s.S b/arch/powerpc/kernel/idle_book3s.S index 1125c9be9e06..01e1c1997893 100644 --- a/arch/powerpc/kernel/idle_book3s.S +++ b/arch/powerpc/kernel/idle_book3s.S | |||
| @@ -112,12 +112,14 @@ power9_save_additional_sprs: | |||
| 112 | std r4, STOP_HFSCR(r13) | 112 | std r4, STOP_HFSCR(r13) |
| 113 | 113 | ||
| 114 | mfspr r3, SPRN_MMCRA | 114 | mfspr r3, SPRN_MMCRA |
| 115 | mfspr r4, SPRN_MMCR1 | 115 | mfspr r4, SPRN_MMCR0 |
| 116 | std r3, STOP_MMCRA(r13) | 116 | std r3, STOP_MMCRA(r13) |
| 117 | std r4, STOP_MMCR1(r13) | 117 | std r4, _MMCR0(r1) |
| 118 | 118 | ||
| 119 | mfspr r3, SPRN_MMCR2 | 119 | mfspr r3, SPRN_MMCR1 |
| 120 | std r3, STOP_MMCR2(r13) | 120 | mfspr r4, SPRN_MMCR2 |
| 121 | std r3, STOP_MMCR1(r13) | ||
| 122 | std r4, STOP_MMCR2(r13) | ||
| 121 | blr | 123 | blr |
| 122 | 124 | ||
| 123 | power9_restore_additional_sprs: | 125 | power9_restore_additional_sprs: |
| @@ -135,11 +137,14 @@ power9_restore_additional_sprs: | |||
| 135 | ld r4, STOP_MMCRA(r13) | 137 | ld r4, STOP_MMCRA(r13) |
| 136 | mtspr SPRN_HFSCR, r3 | 138 | mtspr SPRN_HFSCR, r3 |
| 137 | mtspr SPRN_MMCRA, r4 | 139 | mtspr SPRN_MMCRA, r4 |
| 138 | /* We have already restored PACA_MMCR0 */ | 140 | |
| 139 | ld r3, STOP_MMCR1(r13) | 141 | ld r3, _MMCR0(r1) |
| 140 | ld r4, STOP_MMCR2(r13) | 142 | ld r4, STOP_MMCR1(r13) |
| 141 | mtspr SPRN_MMCR1, r3 | 143 | mtspr SPRN_MMCR0, r3 |
| 142 | mtspr SPRN_MMCR2, r4 | 144 | mtspr SPRN_MMCR1, r4 |
| 145 | |||
| 146 | ld r3, STOP_MMCR2(r13) | ||
| 147 | mtspr SPRN_MMCR2, r3 | ||
| 143 | blr | 148 | blr |
| 144 | 149 | ||
| 145 | /* | 150 | /* |
| @@ -319,20 +324,13 @@ enter_winkle: | |||
| 319 | /* | 324 | /* |
| 320 | * r3 - PSSCR value corresponding to the requested stop state. | 325 | * r3 - PSSCR value corresponding to the requested stop state. |
| 321 | */ | 326 | */ |
| 327 | power_enter_stop: | ||
| 322 | #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE | 328 | #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE |
| 323 | power_enter_stop_kvm_rm: | 329 | /* Tell KVM we're entering idle */ |
| 324 | /* | ||
| 325 | * This is currently unused because POWER9 KVM does not have to | ||
| 326 | * gather secondary threads into sibling mode, but the code is | ||
| 327 | * here in case that function is required. | ||
| 328 | * | ||
| 329 | * Tell KVM we're entering idle. | ||
| 330 | */ | ||
| 331 | li r4,KVM_HWTHREAD_IN_IDLE | 330 | li r4,KVM_HWTHREAD_IN_IDLE |
| 332 | /* DO THIS IN REAL MODE! See comment above. */ | 331 | /* DO THIS IN REAL MODE! See comment above. */ |
| 333 | stb r4,HSTATE_HWTHREAD_STATE(r13) | 332 | stb r4,HSTATE_HWTHREAD_STATE(r13) |
| 334 | #endif | 333 | #endif |
| 335 | power_enter_stop: | ||
| 336 | /* | 334 | /* |
| 337 | * Check if we are executing the lite variant with ESL=EC=0 | 335 | * Check if we are executing the lite variant with ESL=EC=0 |
| 338 | */ | 336 | */ |
| @@ -357,13 +355,15 @@ power_enter_stop: | |||
| 357 | b pnv_wakeup_noloss | 355 | b pnv_wakeup_noloss |
| 358 | 356 | ||
| 359 | .Lhandle_esl_ec_set: | 357 | .Lhandle_esl_ec_set: |
| 358 | BEGIN_FTR_SECTION | ||
| 360 | /* | 359 | /* |
| 361 | * POWER9 DD2 can incorrectly set PMAO when waking up after a | 360 | * POWER9 DD2.0 or earlier can incorrectly set PMAO when waking up after |
| 362 | * state-loss idle. Saving and restoring MMCR0 over idle is a | 361 | * a state-loss idle. Saving and restoring MMCR0 over idle is a |
| 363 | * workaround. | 362 | * workaround. |
| 364 | */ | 363 | */ |
| 365 | mfspr r4,SPRN_MMCR0 | 364 | mfspr r4,SPRN_MMCR0 |
| 366 | std r4,_MMCR0(r1) | 365 | std r4,_MMCR0(r1) |
| 366 | END_FTR_SECTION_IFCLR(CPU_FTR_POWER9_DD2_1) | ||
| 367 | 367 | ||
| 368 | /* | 368 | /* |
| 369 | * Check if the requested state is a deep idle state. | 369 | * Check if the requested state is a deep idle state. |
| @@ -496,18 +496,6 @@ pnv_powersave_wakeup_mce: | |||
| 496 | 496 | ||
| 497 | b pnv_powersave_wakeup | 497 | b pnv_powersave_wakeup |
| 498 | 498 | ||
| 499 | #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE | ||
| 500 | kvm_start_guest_check: | ||
| 501 | li r0,KVM_HWTHREAD_IN_KERNEL | ||
| 502 | stb r0,HSTATE_HWTHREAD_STATE(r13) | ||
| 503 | /* Order setting hwthread_state vs. testing hwthread_req */ | ||
| 504 | sync | ||
| 505 | lbz r0,HSTATE_HWTHREAD_REQ(r13) | ||
| 506 | cmpwi r0,0 | ||
| 507 | beqlr | ||
| 508 | b kvm_start_guest | ||
| 509 | #endif | ||
| 510 | |||
| 511 | /* | 499 | /* |
| 512 | * Called from reset vector for powersave wakeups. | 500 | * Called from reset vector for powersave wakeups. |
| 513 | * cr3 - set to gt if waking up with partial/complete hypervisor state loss | 501 | * cr3 - set to gt if waking up with partial/complete hypervisor state loss |
| @@ -532,9 +520,15 @@ ALT_FTR_SECTION_END_IFSET(CPU_FTR_ARCH_300) | |||
| 532 | mr r3,r12 | 520 | mr r3,r12 |
| 533 | 521 | ||
| 534 | #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE | 522 | #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE |
| 535 | BEGIN_FTR_SECTION | 523 | li r0,KVM_HWTHREAD_IN_KERNEL |
| 536 | bl kvm_start_guest_check | 524 | stb r0,HSTATE_HWTHREAD_STATE(r13) |
| 537 | END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_300) | 525 | /* Order setting hwthread_state vs. testing hwthread_req */ |
| 526 | sync | ||
| 527 | lbz r0,HSTATE_HWTHREAD_REQ(r13) | ||
| 528 | cmpwi r0,0 | ||
| 529 | beq 1f | ||
| 530 | b kvm_start_guest | ||
| 531 | 1: | ||
| 538 | #endif | 532 | #endif |
| 539 | 533 | ||
| 540 | /* Return SRR1 from power7_nap() */ | 534 | /* Return SRR1 from power7_nap() */ |
| @@ -555,15 +549,17 @@ pnv_restore_hyp_resource_arch300: | |||
| 555 | * then clear bit 60 in MMCRA to ensure the PMU starts running. | 549 | * then clear bit 60 in MMCRA to ensure the PMU starts running. |
| 556 | */ | 550 | */ |
| 557 | blt cr3,1f | 551 | blt cr3,1f |
| 552 | BEGIN_FTR_SECTION | ||
| 558 | PPC_INVALIDATE_ERAT | 553 | PPC_INVALIDATE_ERAT |
| 559 | ld r1,PACAR1(r13) | 554 | ld r1,PACAR1(r13) |
| 555 | ld r4,_MMCR0(r1) | ||
| 556 | mtspr SPRN_MMCR0,r4 | ||
| 557 | END_FTR_SECTION_IFCLR(CPU_FTR_POWER9_DD2_1) | ||
| 560 | mfspr r4,SPRN_MMCRA | 558 | mfspr r4,SPRN_MMCRA |
| 561 | ori r4,r4,(1 << (63-60)) | 559 | ori r4,r4,(1 << (63-60)) |
| 562 | mtspr SPRN_MMCRA,r4 | 560 | mtspr SPRN_MMCRA,r4 |
| 563 | xori r4,r4,(1 << (63-60)) | 561 | xori r4,r4,(1 << (63-60)) |
| 564 | mtspr SPRN_MMCRA,r4 | 562 | mtspr SPRN_MMCRA,r4 |
| 565 | ld r4,_MMCR0(r1) | ||
| 566 | mtspr SPRN_MMCR0,r4 | ||
| 567 | 1: | 563 | 1: |
| 568 | /* | 564 | /* |
| 569 | * POWER ISA 3. Use PSSCR to determine if we | 565 | * POWER ISA 3. Use PSSCR to determine if we |
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 4e65bf82f5e0..b7a84522e652 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c | |||
| @@ -143,6 +143,13 @@ notrace unsigned int __check_irq_replay(void) | |||
| 143 | */ | 143 | */ |
| 144 | unsigned char happened = local_paca->irq_happened; | 144 | unsigned char happened = local_paca->irq_happened; |
| 145 | 145 | ||
| 146 | /* | ||
| 147 | * We are responding to the next interrupt, so interrupt-off | ||
| 148 | * latencies should be reset here. | ||
| 149 | */ | ||
| 150 | trace_hardirqs_on(); | ||
| 151 | trace_hardirqs_off(); | ||
| 152 | |||
| 146 | if (happened & PACA_IRQ_HARD_DIS) { | 153 | if (happened & PACA_IRQ_HARD_DIS) { |
| 147 | /* Clear bit 0 which we wouldn't clear otherwise */ | 154 | /* Clear bit 0 which we wouldn't clear otherwise */ |
| 148 | local_paca->irq_happened &= ~PACA_IRQ_HARD_DIS; | 155 | local_paca->irq_happened &= ~PACA_IRQ_HARD_DIS; |
| @@ -270,6 +277,7 @@ notrace void arch_local_irq_restore(unsigned long en) | |||
| 270 | #endif /* CONFIG_TRACE_IRQFLAGS */ | 277 | #endif /* CONFIG_TRACE_IRQFLAGS */ |
| 271 | 278 | ||
| 272 | set_soft_enabled(0); | 279 | set_soft_enabled(0); |
| 280 | trace_hardirqs_off(); | ||
| 273 | 281 | ||
| 274 | /* | 282 | /* |
| 275 | * Check if anything needs to be re-emitted. We haven't | 283 | * Check if anything needs to be re-emitted. We haven't |
| @@ -279,6 +287,7 @@ notrace void arch_local_irq_restore(unsigned long en) | |||
| 279 | replay = __check_irq_replay(); | 287 | replay = __check_irq_replay(); |
| 280 | 288 | ||
| 281 | /* We can soft-enable now */ | 289 | /* We can soft-enable now */ |
| 290 | trace_hardirqs_on(); | ||
| 282 | set_soft_enabled(1); | 291 | set_soft_enabled(1); |
| 283 | 292 | ||
| 284 | /* | 293 | /* |
| @@ -394,11 +403,19 @@ bool prep_irq_for_idle_irqsoff(void) | |||
| 394 | /* | 403 | /* |
| 395 | * Take the SRR1 wakeup reason, index into this table to find the | 404 | * Take the SRR1 wakeup reason, index into this table to find the |
| 396 | * appropriate irq_happened bit. | 405 | * appropriate irq_happened bit. |
| 406 | * | ||
| 407 | * Sytem reset exceptions taken in idle state also come through here, | ||
| 408 | * but they are NMI interrupts so do not need to wait for IRQs to be | ||
| 409 | * restored, and should be taken as early as practical. These are marked | ||
| 410 | * with 0xff in the table. The Power ISA specifies 0100b as the system | ||
| 411 | * reset interrupt reason. | ||
| 397 | */ | 412 | */ |
| 413 | #define IRQ_SYSTEM_RESET 0xff | ||
| 414 | |||
| 398 | static const u8 srr1_to_lazyirq[0x10] = { | 415 | static const u8 srr1_to_lazyirq[0x10] = { |
| 399 | 0, 0, 0, | 416 | 0, 0, 0, |
| 400 | PACA_IRQ_DBELL, | 417 | PACA_IRQ_DBELL, |
| 401 | 0, | 418 | IRQ_SYSTEM_RESET, |
| 402 | PACA_IRQ_DBELL, | 419 | PACA_IRQ_DBELL, |
| 403 | PACA_IRQ_DEC, | 420 | PACA_IRQ_DEC, |
| 404 | 0, | 421 | 0, |
| @@ -407,15 +424,43 @@ static const u8 srr1_to_lazyirq[0x10] = { | |||
| 407 | PACA_IRQ_HMI, | 424 | PACA_IRQ_HMI, |
| 408 | 0, 0, 0, 0, 0 }; | 425 | 0, 0, 0, 0, 0 }; |
| 409 | 426 | ||
| 427 | void replay_system_reset(void) | ||
| 428 | { | ||
| 429 | struct pt_regs regs; | ||
| 430 | |||
| 431 | ppc_save_regs(®s); | ||
| 432 | regs.trap = 0x100; | ||
| 433 | get_paca()->in_nmi = 1; | ||
| 434 | system_reset_exception(®s); | ||
| 435 | get_paca()->in_nmi = 0; | ||
| 436 | } | ||
| 437 | EXPORT_SYMBOL_GPL(replay_system_reset); | ||
| 438 | |||
| 410 | void irq_set_pending_from_srr1(unsigned long srr1) | 439 | void irq_set_pending_from_srr1(unsigned long srr1) |
| 411 | { | 440 | { |
| 412 | unsigned int idx = (srr1 & SRR1_WAKEMASK_P8) >> 18; | 441 | unsigned int idx = (srr1 & SRR1_WAKEMASK_P8) >> 18; |
| 442 | u8 reason = srr1_to_lazyirq[idx]; | ||
| 443 | |||
| 444 | /* | ||
| 445 | * Take the system reset now, which is immediately after registers | ||
| 446 | * are restored from idle. It's an NMI, so interrupts need not be | ||
| 447 | * re-enabled before it is taken. | ||
| 448 | */ | ||
| 449 | if (unlikely(reason == IRQ_SYSTEM_RESET)) { | ||
| 450 | replay_system_reset(); | ||
| 451 | return; | ||
| 452 | } | ||
| 413 | 453 | ||
| 414 | /* | 454 | /* |
| 415 | * The 0 index (SRR1[42:45]=b0000) must always evaluate to 0, | 455 | * The 0 index (SRR1[42:45]=b0000) must always evaluate to 0, |
| 416 | * so this can be called unconditionally with srr1 wake reason. | 456 | * so this can be called unconditionally with the SRR1 wake |
| 457 | * reason as returned by the idle code, which uses 0 to mean no | ||
| 458 | * interrupt. | ||
| 459 | * | ||
| 460 | * If a future CPU was to designate this as an interrupt reason, | ||
| 461 | * then a new index for no interrupt must be assigned. | ||
| 417 | */ | 462 | */ |
| 418 | local_paca->irq_happened |= srr1_to_lazyirq[idx]; | 463 | local_paca->irq_happened |= reason; |
| 419 | } | 464 | } |
| 420 | #endif /* CONFIG_PPC_BOOK3S */ | 465 | #endif /* CONFIG_PPC_BOOK3S */ |
| 421 | 466 | ||
diff --git a/arch/powerpc/kernel/kprobes-ftrace.c b/arch/powerpc/kernel/kprobes-ftrace.c index 6c089d9757c9..7a1f99f1b47f 100644 --- a/arch/powerpc/kernel/kprobes-ftrace.c +++ b/arch/powerpc/kernel/kprobes-ftrace.c | |||
| @@ -25,6 +25,21 @@ | |||
| 25 | #include <linux/preempt.h> | 25 | #include <linux/preempt.h> |
| 26 | #include <linux/ftrace.h> | 26 | #include <linux/ftrace.h> |
| 27 | 27 | ||
| 28 | /* | ||
| 29 | * This is called from ftrace code after invoking registered handlers to | ||
| 30 | * disambiguate regs->nip changes done by jprobes and livepatch. We check if | ||
| 31 | * there is an active jprobe at the provided address (mcount location). | ||
| 32 | */ | ||
| 33 | int __is_active_jprobe(unsigned long addr) | ||
| 34 | { | ||
| 35 | if (!preemptible()) { | ||
| 36 | struct kprobe *p = raw_cpu_read(current_kprobe); | ||
| 37 | return (p && (unsigned long)p->addr == addr) ? 1 : 0; | ||
| 38 | } | ||
| 39 | |||
| 40 | return 0; | ||
| 41 | } | ||
| 42 | |||
| 28 | static nokprobe_inline | 43 | static nokprobe_inline |
| 29 | int __skip_singlestep(struct kprobe *p, struct pt_regs *regs, | 44 | int __skip_singlestep(struct kprobe *p, struct pt_regs *regs, |
| 30 | struct kprobe_ctlblk *kcb, unsigned long orig_nip) | 45 | struct kprobe_ctlblk *kcb, unsigned long orig_nip) |
| @@ -60,11 +75,8 @@ void kprobe_ftrace_handler(unsigned long nip, unsigned long parent_nip, | |||
| 60 | { | 75 | { |
| 61 | struct kprobe *p; | 76 | struct kprobe *p; |
| 62 | struct kprobe_ctlblk *kcb; | 77 | struct kprobe_ctlblk *kcb; |
| 63 | unsigned long flags; | ||
| 64 | 78 | ||
| 65 | /* Disable irq for emulating a breakpoint and avoiding preempt */ | 79 | preempt_disable(); |
| 66 | local_irq_save(flags); | ||
| 67 | hard_irq_disable(); | ||
| 68 | 80 | ||
| 69 | p = get_kprobe((kprobe_opcode_t *)nip); | 81 | p = get_kprobe((kprobe_opcode_t *)nip); |
| 70 | if (unlikely(!p) || kprobe_disabled(p)) | 82 | if (unlikely(!p) || kprobe_disabled(p)) |
| @@ -86,13 +98,17 @@ void kprobe_ftrace_handler(unsigned long nip, unsigned long parent_nip, | |||
| 86 | kcb->kprobe_status = KPROBE_HIT_ACTIVE; | 98 | kcb->kprobe_status = KPROBE_HIT_ACTIVE; |
| 87 | if (!p->pre_handler || !p->pre_handler(p, regs)) | 99 | if (!p->pre_handler || !p->pre_handler(p, regs)) |
| 88 | __skip_singlestep(p, regs, kcb, orig_nip); | 100 | __skip_singlestep(p, regs, kcb, orig_nip); |
| 89 | /* | 101 | else { |
| 90 | * If pre_handler returns !0, it sets regs->nip and | 102 | /* |
| 91 | * resets current kprobe. | 103 | * If pre_handler returns !0, it sets regs->nip and |
| 92 | */ | 104 | * resets current kprobe. In this case, we should not |
| 105 | * re-enable preemption. | ||
| 106 | */ | ||
| 107 | return; | ||
| 108 | } | ||
| 93 | } | 109 | } |
| 94 | end: | 110 | end: |
| 95 | local_irq_restore(flags); | 111 | preempt_enable_no_resched(); |
| 96 | } | 112 | } |
| 97 | NOKPROBE_SYMBOL(kprobe_ftrace_handler); | 113 | NOKPROBE_SYMBOL(kprobe_ftrace_handler); |
| 98 | 114 | ||
diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c index bebc3007a793..ca5d5a081e75 100644 --- a/arch/powerpc/kernel/kprobes.c +++ b/arch/powerpc/kernel/kprobes.c | |||
| @@ -43,12 +43,6 @@ DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); | |||
| 43 | 43 | ||
| 44 | struct kretprobe_blackpoint kretprobe_blacklist[] = {{NULL, NULL}}; | 44 | struct kretprobe_blackpoint kretprobe_blacklist[] = {{NULL, NULL}}; |
| 45 | 45 | ||
| 46 | int is_current_kprobe_addr(unsigned long addr) | ||
| 47 | { | ||
| 48 | struct kprobe *p = kprobe_running(); | ||
| 49 | return (p && (unsigned long)p->addr == addr) ? 1 : 0; | ||
| 50 | } | ||
| 51 | |||
| 52 | bool arch_within_kprobe_blacklist(unsigned long addr) | 46 | bool arch_within_kprobe_blacklist(unsigned long addr) |
| 53 | { | 47 | { |
| 54 | return (addr >= (unsigned long)__kprobes_text_start && | 48 | return (addr >= (unsigned long)__kprobes_text_start && |
| @@ -59,7 +53,7 @@ bool arch_within_kprobe_blacklist(unsigned long addr) | |||
| 59 | 53 | ||
| 60 | kprobe_opcode_t *kprobe_lookup_name(const char *name, unsigned int offset) | 54 | kprobe_opcode_t *kprobe_lookup_name(const char *name, unsigned int offset) |
| 61 | { | 55 | { |
| 62 | kprobe_opcode_t *addr; | 56 | kprobe_opcode_t *addr = NULL; |
| 63 | 57 | ||
| 64 | #ifdef PPC64_ELF_ABI_v2 | 58 | #ifdef PPC64_ELF_ABI_v2 |
| 65 | /* PPC64 ABIv2 needs local entry point */ | 59 | /* PPC64 ABIv2 needs local entry point */ |
| @@ -91,36 +85,29 @@ kprobe_opcode_t *kprobe_lookup_name(const char *name, unsigned int offset) | |||
| 91 | * Also handle <module:symbol> format. | 85 | * Also handle <module:symbol> format. |
| 92 | */ | 86 | */ |
| 93 | char dot_name[MODULE_NAME_LEN + 1 + KSYM_NAME_LEN]; | 87 | char dot_name[MODULE_NAME_LEN + 1 + KSYM_NAME_LEN]; |
| 94 | const char *modsym; | ||
| 95 | bool dot_appended = false; | 88 | bool dot_appended = false; |
| 96 | if ((modsym = strchr(name, ':')) != NULL) { | 89 | const char *c; |
| 97 | modsym++; | 90 | ssize_t ret = 0; |
| 98 | if (*modsym != '\0' && *modsym != '.') { | 91 | int len = 0; |
| 99 | /* Convert to <module:.symbol> */ | 92 | |
| 100 | strncpy(dot_name, name, modsym - name); | 93 | if ((c = strnchr(name, MODULE_NAME_LEN, ':')) != NULL) { |
| 101 | dot_name[modsym - name] = '.'; | 94 | c++; |
| 102 | dot_name[modsym - name + 1] = '\0'; | 95 | len = c - name; |
| 103 | strncat(dot_name, modsym, | 96 | memcpy(dot_name, name, len); |
| 104 | sizeof(dot_name) - (modsym - name) - 2); | 97 | } else |
| 105 | dot_appended = true; | 98 | c = name; |
| 106 | } else { | 99 | |
| 107 | dot_name[0] = '\0'; | 100 | if (*c != '\0' && *c != '.') { |
| 108 | strncat(dot_name, name, sizeof(dot_name) - 1); | 101 | dot_name[len++] = '.'; |
| 109 | } | ||
| 110 | } else if (name[0] != '.') { | ||
| 111 | dot_name[0] = '.'; | ||
| 112 | dot_name[1] = '\0'; | ||
| 113 | strncat(dot_name, name, KSYM_NAME_LEN - 2); | ||
| 114 | dot_appended = true; | 102 | dot_appended = true; |
| 115 | } else { | ||
| 116 | dot_name[0] = '\0'; | ||
| 117 | strncat(dot_name, name, KSYM_NAME_LEN - 1); | ||
| 118 | } | 103 | } |
| 119 | addr = (kprobe_opcode_t *)kallsyms_lookup_name(dot_name); | 104 | ret = strscpy(dot_name + len, c, KSYM_NAME_LEN); |
| 120 | if (!addr && dot_appended) { | 105 | if (ret > 0) |
| 121 | /* Let's try the original non-dot symbol lookup */ | 106 | addr = (kprobe_opcode_t *)kallsyms_lookup_name(dot_name); |
| 107 | |||
| 108 | /* Fallback to the original non-dot symbol lookup */ | ||
| 109 | if (!addr && dot_appended) | ||
| 122 | addr = (kprobe_opcode_t *)kallsyms_lookup_name(name); | 110 | addr = (kprobe_opcode_t *)kallsyms_lookup_name(name); |
| 123 | } | ||
| 124 | #else | 111 | #else |
| 125 | addr = (kprobe_opcode_t *)kallsyms_lookup_name(name); | 112 | addr = (kprobe_opcode_t *)kallsyms_lookup_name(name); |
| 126 | #endif | 113 | #endif |
| @@ -239,7 +226,7 @@ void arch_prepare_kretprobe(struct kretprobe_instance *ri, struct pt_regs *regs) | |||
| 239 | } | 226 | } |
| 240 | NOKPROBE_SYMBOL(arch_prepare_kretprobe); | 227 | NOKPROBE_SYMBOL(arch_prepare_kretprobe); |
| 241 | 228 | ||
| 242 | int try_to_emulate(struct kprobe *p, struct pt_regs *regs) | 229 | static int try_to_emulate(struct kprobe *p, struct pt_regs *regs) |
| 243 | { | 230 | { |
| 244 | int ret; | 231 | int ret; |
| 245 | unsigned int insn = *p->ainsn.insn; | 232 | unsigned int insn = *p->ainsn.insn; |
| @@ -261,9 +248,20 @@ int try_to_emulate(struct kprobe *p, struct pt_regs *regs) | |||
| 261 | */ | 248 | */ |
| 262 | printk("Can't step on instruction %x\n", insn); | 249 | printk("Can't step on instruction %x\n", insn); |
| 263 | BUG(); | 250 | BUG(); |
| 264 | } else if (ret == 0) | 251 | } else { |
| 265 | /* This instruction can't be boosted */ | 252 | /* |
| 266 | p->ainsn.boostable = -1; | 253 | * If we haven't previously emulated this instruction, then it |
| 254 | * can't be boosted. Note it down so we don't try to do so again. | ||
| 255 | * | ||
| 256 | * If, however, we had emulated this instruction in the past, | ||
| 257 | * then this is just an error with the current run (for | ||
| 258 | * instance, exceptions due to a load/store). We return 0 so | ||
| 259 | * that this is now single-stepped, but continue to try | ||
| 260 | * emulating it in subsequent probe hits. | ||
| 261 | */ | ||
| 262 | if (unlikely(p->ainsn.boostable != 1)) | ||
| 263 | p->ainsn.boostable = -1; | ||
| 264 | } | ||
| 267 | 265 | ||
| 268 | return ret; | 266 | return ret; |
| 269 | } | 267 | } |
| @@ -639,24 +637,22 @@ NOKPROBE_SYMBOL(setjmp_pre_handler); | |||
| 639 | 637 | ||
| 640 | void __used jprobe_return(void) | 638 | void __used jprobe_return(void) |
| 641 | { | 639 | { |
| 642 | asm volatile("trap" ::: "memory"); | 640 | asm volatile("jprobe_return_trap:\n" |
| 641 | "trap\n" | ||
| 642 | ::: "memory"); | ||
| 643 | } | 643 | } |
| 644 | NOKPROBE_SYMBOL(jprobe_return); | 644 | NOKPROBE_SYMBOL(jprobe_return); |
| 645 | 645 | ||
| 646 | static void __used jprobe_return_end(void) | ||
| 647 | { | ||
| 648 | } | ||
| 649 | NOKPROBE_SYMBOL(jprobe_return_end); | ||
| 650 | |||
| 651 | int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) | 646 | int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) |
| 652 | { | 647 | { |
| 653 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); | 648 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); |
| 654 | 649 | ||
| 655 | /* | 650 | if (regs->nip != ppc_kallsyms_lookup_name("jprobe_return_trap")) { |
| 656 | * FIXME - we should ideally be validating that we got here 'cos | 651 | pr_debug("longjmp_break_handler NIP (0x%lx) does not match jprobe_return_trap (0x%lx)\n", |
| 657 | * of the "trap" in jprobe_return() above, before restoring the | 652 | regs->nip, ppc_kallsyms_lookup_name("jprobe_return_trap")); |
| 658 | * saved regs... | 653 | return 0; |
| 659 | */ | 654 | } |
| 655 | |||
| 660 | memcpy(regs, &kcb->jprobe_saved_regs, sizeof(struct pt_regs)); | 656 | memcpy(regs, &kcb->jprobe_saved_regs, sizeof(struct pt_regs)); |
| 661 | /* It's OK to start function graph tracing again */ | 657 | /* It's OK to start function graph tracing again */ |
| 662 | unpause_graph_tracing(); | 658 | unpause_graph_tracing(); |
diff --git a/arch/powerpc/kernel/machine_kexec_64.c b/arch/powerpc/kernel/machine_kexec_64.c index 5c12e21d0d1a..49d34d7271e7 100644 --- a/arch/powerpc/kernel/machine_kexec_64.c +++ b/arch/powerpc/kernel/machine_kexec_64.c | |||
| @@ -360,7 +360,7 @@ void default_machine_kexec(struct kimage *image) | |||
| 360 | /* NOTREACHED */ | 360 | /* NOTREACHED */ |
| 361 | } | 361 | } |
| 362 | 362 | ||
| 363 | #ifdef CONFIG_PPC_STD_MMU_64 | 363 | #ifdef CONFIG_PPC_BOOK3S_64 |
| 364 | /* Values we need to export to the second kernel via the device tree. */ | 364 | /* Values we need to export to the second kernel via the device tree. */ |
| 365 | static unsigned long htab_base; | 365 | static unsigned long htab_base; |
| 366 | static unsigned long htab_size; | 366 | static unsigned long htab_size; |
| @@ -402,4 +402,4 @@ static int __init export_htab_values(void) | |||
| 402 | return 0; | 402 | return 0; |
| 403 | } | 403 | } |
| 404 | late_initcall(export_htab_values); | 404 | late_initcall(export_htab_values); |
| 405 | #endif /* CONFIG_PPC_STD_MMU_64 */ | 405 | #endif /* CONFIG_PPC_BOOK3S_64 */ |
diff --git a/arch/powerpc/kernel/mce.c b/arch/powerpc/kernel/mce.c index 9b2ea7e71c06..742e4658c5dc 100644 --- a/arch/powerpc/kernel/mce.c +++ b/arch/powerpc/kernel/mce.c | |||
| @@ -39,11 +39,21 @@ static DEFINE_PER_CPU(struct machine_check_event[MAX_MC_EVT], mce_event); | |||
| 39 | static DEFINE_PER_CPU(int, mce_queue_count); | 39 | static DEFINE_PER_CPU(int, mce_queue_count); |
| 40 | static DEFINE_PER_CPU(struct machine_check_event[MAX_MC_EVT], mce_event_queue); | 40 | static DEFINE_PER_CPU(struct machine_check_event[MAX_MC_EVT], mce_event_queue); |
| 41 | 41 | ||
| 42 | /* Queue for delayed MCE UE events. */ | ||
| 43 | static DEFINE_PER_CPU(int, mce_ue_count); | ||
| 44 | static DEFINE_PER_CPU(struct machine_check_event[MAX_MC_EVT], | ||
| 45 | mce_ue_event_queue); | ||
| 46 | |||
| 42 | static void machine_check_process_queued_event(struct irq_work *work); | 47 | static void machine_check_process_queued_event(struct irq_work *work); |
| 48 | void machine_check_ue_event(struct machine_check_event *evt); | ||
| 49 | static void machine_process_ue_event(struct work_struct *work); | ||
| 50 | |||
| 43 | static struct irq_work mce_event_process_work = { | 51 | static struct irq_work mce_event_process_work = { |
| 44 | .func = machine_check_process_queued_event, | 52 | .func = machine_check_process_queued_event, |
| 45 | }; | 53 | }; |
| 46 | 54 | ||
| 55 | DECLARE_WORK(mce_ue_event_work, machine_process_ue_event); | ||
| 56 | |||
| 47 | static void mce_set_error_info(struct machine_check_event *mce, | 57 | static void mce_set_error_info(struct machine_check_event *mce, |
| 48 | struct mce_error_info *mce_err) | 58 | struct mce_error_info *mce_err) |
| 49 | { | 59 | { |
| @@ -82,7 +92,7 @@ static void mce_set_error_info(struct machine_check_event *mce, | |||
| 82 | */ | 92 | */ |
| 83 | void save_mce_event(struct pt_regs *regs, long handled, | 93 | void save_mce_event(struct pt_regs *regs, long handled, |
| 84 | struct mce_error_info *mce_err, | 94 | struct mce_error_info *mce_err, |
| 85 | uint64_t nip, uint64_t addr) | 95 | uint64_t nip, uint64_t addr, uint64_t phys_addr) |
| 86 | { | 96 | { |
| 87 | int index = __this_cpu_inc_return(mce_nest_count) - 1; | 97 | int index = __this_cpu_inc_return(mce_nest_count) - 1; |
| 88 | struct machine_check_event *mce = this_cpu_ptr(&mce_event[index]); | 98 | struct machine_check_event *mce = this_cpu_ptr(&mce_event[index]); |
| @@ -140,6 +150,11 @@ void save_mce_event(struct pt_regs *regs, long handled, | |||
| 140 | } else if (mce->error_type == MCE_ERROR_TYPE_UE) { | 150 | } else if (mce->error_type == MCE_ERROR_TYPE_UE) { |
| 141 | mce->u.ue_error.effective_address_provided = true; | 151 | mce->u.ue_error.effective_address_provided = true; |
| 142 | mce->u.ue_error.effective_address = addr; | 152 | mce->u.ue_error.effective_address = addr; |
| 153 | if (phys_addr != ULONG_MAX) { | ||
| 154 | mce->u.ue_error.physical_address_provided = true; | ||
| 155 | mce->u.ue_error.physical_address = phys_addr; | ||
| 156 | machine_check_ue_event(mce); | ||
| 157 | } | ||
| 143 | } | 158 | } |
| 144 | return; | 159 | return; |
| 145 | } | 160 | } |
| @@ -193,6 +208,26 @@ void release_mce_event(void) | |||
| 193 | get_mce_event(NULL, true); | 208 | get_mce_event(NULL, true); |
| 194 | } | 209 | } |
| 195 | 210 | ||
| 211 | |||
| 212 | /* | ||
| 213 | * Queue up the MCE event which then can be handled later. | ||
| 214 | */ | ||
| 215 | void machine_check_ue_event(struct machine_check_event *evt) | ||
| 216 | { | ||
| 217 | int index; | ||
| 218 | |||
| 219 | index = __this_cpu_inc_return(mce_ue_count) - 1; | ||
| 220 | /* If queue is full, just return for now. */ | ||
| 221 | if (index >= MAX_MC_EVT) { | ||
| 222 | __this_cpu_dec(mce_ue_count); | ||
| 223 | return; | ||
| 224 | } | ||
| 225 | memcpy(this_cpu_ptr(&mce_ue_event_queue[index]), evt, sizeof(*evt)); | ||
| 226 | |||
| 227 | /* Queue work to process this event later. */ | ||
| 228 | schedule_work(&mce_ue_event_work); | ||
| 229 | } | ||
| 230 | |||
| 196 | /* | 231 | /* |
| 197 | * Queue up the MCE event which then can be handled later. | 232 | * Queue up the MCE event which then can be handled later. |
| 198 | */ | 233 | */ |
| @@ -215,7 +250,39 @@ void machine_check_queue_event(void) | |||
| 215 | /* Queue irq work to process this event later. */ | 250 | /* Queue irq work to process this event later. */ |
| 216 | irq_work_queue(&mce_event_process_work); | 251 | irq_work_queue(&mce_event_process_work); |
| 217 | } | 252 | } |
| 218 | 253 | /* | |
| 254 | * process pending MCE event from the mce event queue. This function will be | ||
| 255 | * called during syscall exit. | ||
| 256 | */ | ||
| 257 | static void machine_process_ue_event(struct work_struct *work) | ||
| 258 | { | ||
| 259 | int index; | ||
| 260 | struct machine_check_event *evt; | ||
| 261 | |||
| 262 | while (__this_cpu_read(mce_ue_count) > 0) { | ||
| 263 | index = __this_cpu_read(mce_ue_count) - 1; | ||
| 264 | evt = this_cpu_ptr(&mce_ue_event_queue[index]); | ||
| 265 | #ifdef CONFIG_MEMORY_FAILURE | ||
| 266 | /* | ||
| 267 | * This should probably queued elsewhere, but | ||
| 268 | * oh! well | ||
| 269 | */ | ||
| 270 | if (evt->error_type == MCE_ERROR_TYPE_UE) { | ||
| 271 | if (evt->u.ue_error.physical_address_provided) { | ||
| 272 | unsigned long pfn; | ||
| 273 | |||
| 274 | pfn = evt->u.ue_error.physical_address >> | ||
| 275 | PAGE_SHIFT; | ||
| 276 | memory_failure(pfn, SIGBUS, 0); | ||
| 277 | } else | ||
| 278 | pr_warn("Failed to identify bad address from " | ||
| 279 | "where the uncorrectable error (UE) " | ||
| 280 | "was generated\n"); | ||
| 281 | } | ||
| 282 | #endif | ||
| 283 | __this_cpu_dec(mce_ue_count); | ||
| 284 | } | ||
| 285 | } | ||
| 219 | /* | 286 | /* |
| 220 | * process pending MCE event from the mce event queue. This function will be | 287 | * process pending MCE event from the mce event queue. This function will be |
| 221 | * called during syscall exit. | 288 | * called during syscall exit. |
| @@ -223,6 +290,7 @@ void machine_check_queue_event(void) | |||
| 223 | static void machine_check_process_queued_event(struct irq_work *work) | 290 | static void machine_check_process_queued_event(struct irq_work *work) |
| 224 | { | 291 | { |
| 225 | int index; | 292 | int index; |
| 293 | struct machine_check_event *evt; | ||
| 226 | 294 | ||
| 227 | add_taint(TAINT_MACHINE_CHECK, LOCKDEP_NOW_UNRELIABLE); | 295 | add_taint(TAINT_MACHINE_CHECK, LOCKDEP_NOW_UNRELIABLE); |
| 228 | 296 | ||
| @@ -232,8 +300,8 @@ static void machine_check_process_queued_event(struct irq_work *work) | |||
| 232 | */ | 300 | */ |
| 233 | while (__this_cpu_read(mce_queue_count) > 0) { | 301 | while (__this_cpu_read(mce_queue_count) > 0) { |
| 234 | index = __this_cpu_read(mce_queue_count) - 1; | 302 | index = __this_cpu_read(mce_queue_count) - 1; |
| 235 | machine_check_print_event_info( | 303 | evt = this_cpu_ptr(&mce_event_queue[index]); |
| 236 | this_cpu_ptr(&mce_event_queue[index]), false); | 304 | machine_check_print_event_info(evt, false); |
| 237 | __this_cpu_dec(mce_queue_count); | 305 | __this_cpu_dec(mce_queue_count); |
| 238 | } | 306 | } |
| 239 | } | 307 | } |
| @@ -340,7 +408,7 @@ void machine_check_print_event_info(struct machine_check_event *evt, | |||
| 340 | printk("%s Effective address: %016llx\n", | 408 | printk("%s Effective address: %016llx\n", |
| 341 | level, evt->u.ue_error.effective_address); | 409 | level, evt->u.ue_error.effective_address); |
| 342 | if (evt->u.ue_error.physical_address_provided) | 410 | if (evt->u.ue_error.physical_address_provided) |
| 343 | printk("%s Physical address: %016llx\n", | 411 | printk("%s Physical address: %016llx\n", |
| 344 | level, evt->u.ue_error.physical_address); | 412 | level, evt->u.ue_error.physical_address); |
| 345 | break; | 413 | break; |
| 346 | case MCE_ERROR_TYPE_SLB: | 414 | case MCE_ERROR_TYPE_SLB: |
| @@ -411,45 +479,6 @@ void machine_check_print_event_info(struct machine_check_event *evt, | |||
| 411 | } | 479 | } |
| 412 | EXPORT_SYMBOL_GPL(machine_check_print_event_info); | 480 | EXPORT_SYMBOL_GPL(machine_check_print_event_info); |
| 413 | 481 | ||
| 414 | uint64_t get_mce_fault_addr(struct machine_check_event *evt) | ||
| 415 | { | ||
| 416 | switch (evt->error_type) { | ||
| 417 | case MCE_ERROR_TYPE_UE: | ||
| 418 | if (evt->u.ue_error.effective_address_provided) | ||
| 419 | return evt->u.ue_error.effective_address; | ||
| 420 | break; | ||
| 421 | case MCE_ERROR_TYPE_SLB: | ||
| 422 | if (evt->u.slb_error.effective_address_provided) | ||
| 423 | return evt->u.slb_error.effective_address; | ||
| 424 | break; | ||
| 425 | case MCE_ERROR_TYPE_ERAT: | ||
| 426 | if (evt->u.erat_error.effective_address_provided) | ||
| 427 | return evt->u.erat_error.effective_address; | ||
| 428 | break; | ||
| 429 | case MCE_ERROR_TYPE_TLB: | ||
| 430 | if (evt->u.tlb_error.effective_address_provided) | ||
| 431 | return evt->u.tlb_error.effective_address; | ||
| 432 | break; | ||
| 433 | case MCE_ERROR_TYPE_USER: | ||
| 434 | if (evt->u.user_error.effective_address_provided) | ||
| 435 | return evt->u.user_error.effective_address; | ||
| 436 | break; | ||
| 437 | case MCE_ERROR_TYPE_RA: | ||
| 438 | if (evt->u.ra_error.effective_address_provided) | ||
| 439 | return evt->u.ra_error.effective_address; | ||
| 440 | break; | ||
| 441 | case MCE_ERROR_TYPE_LINK: | ||
| 442 | if (evt->u.link_error.effective_address_provided) | ||
| 443 | return evt->u.link_error.effective_address; | ||
| 444 | break; | ||
| 445 | default: | ||
| 446 | case MCE_ERROR_TYPE_UNKNOWN: | ||
| 447 | break; | ||
| 448 | } | ||
| 449 | return 0; | ||
| 450 | } | ||
| 451 | EXPORT_SYMBOL(get_mce_fault_addr); | ||
| 452 | |||
| 453 | /* | 482 | /* |
| 454 | * This function is called in real mode. Strictly no printk's please. | 483 | * This function is called in real mode. Strictly no printk's please. |
| 455 | * | 484 | * |
| @@ -470,6 +499,34 @@ long hmi_exception_realmode(struct pt_regs *regs) | |||
| 470 | { | 499 | { |
| 471 | __this_cpu_inc(irq_stat.hmi_exceptions); | 500 | __this_cpu_inc(irq_stat.hmi_exceptions); |
| 472 | 501 | ||
| 502 | #ifdef CONFIG_PPC_BOOK3S_64 | ||
| 503 | /* Workaround for P9 vector CI loads (see p9_hmi_special_emu) */ | ||
| 504 | if (pvr_version_is(PVR_POWER9)) { | ||
| 505 | unsigned long hmer = mfspr(SPRN_HMER); | ||
| 506 | |||
| 507 | /* Do we have the debug bit set */ | ||
| 508 | if (hmer & PPC_BIT(17)) { | ||
| 509 | hmer &= ~PPC_BIT(17); | ||
| 510 | mtspr(SPRN_HMER, hmer); | ||
| 511 | |||
| 512 | /* | ||
| 513 | * Now to avoid problems with soft-disable we | ||
| 514 | * only do the emulation if we are coming from | ||
| 515 | * user space | ||
| 516 | */ | ||
| 517 | if (user_mode(regs)) | ||
| 518 | local_paca->hmi_p9_special_emu = 1; | ||
| 519 | |||
| 520 | /* | ||
| 521 | * Don't bother going to OPAL if that's the | ||
| 522 | * only relevant bit. | ||
| 523 | */ | ||
| 524 | if (!(hmer & mfspr(SPRN_HMEER))) | ||
| 525 | return local_paca->hmi_p9_special_emu; | ||
| 526 | } | ||
| 527 | } | ||
| 528 | #endif /* CONFIG_PPC_BOOK3S_64 */ | ||
| 529 | |||
| 473 | wait_for_subcore_guest_exit(); | 530 | wait_for_subcore_guest_exit(); |
| 474 | 531 | ||
| 475 | if (ppc_md.hmi_exception_early) | 532 | if (ppc_md.hmi_exception_early) |
| @@ -477,5 +534,5 @@ long hmi_exception_realmode(struct pt_regs *regs) | |||
| 477 | 534 | ||
| 478 | wait_for_tb_resync(); | 535 | wait_for_tb_resync(); |
| 479 | 536 | ||
| 480 | return 0; | 537 | return 1; |
| 481 | } | 538 | } |
diff --git a/arch/powerpc/kernel/mce_power.c b/arch/powerpc/kernel/mce_power.c index 72f153c6f3fa..644f7040b91c 100644 --- a/arch/powerpc/kernel/mce_power.c +++ b/arch/powerpc/kernel/mce_power.c | |||
| @@ -27,6 +27,36 @@ | |||
| 27 | #include <asm/mmu.h> | 27 | #include <asm/mmu.h> |
| 28 | #include <asm/mce.h> | 28 | #include <asm/mce.h> |
| 29 | #include <asm/machdep.h> | 29 | #include <asm/machdep.h> |
| 30 | #include <asm/pgtable.h> | ||
| 31 | #include <asm/pte-walk.h> | ||
| 32 | #include <asm/sstep.h> | ||
| 33 | #include <asm/exception-64s.h> | ||
| 34 | |||
| 35 | /* | ||
| 36 | * Convert an address related to an mm to a PFN. NOTE: we are in real | ||
| 37 | * mode, we could potentially race with page table updates. | ||
| 38 | */ | ||
| 39 | static unsigned long addr_to_pfn(struct pt_regs *regs, unsigned long addr) | ||
| 40 | { | ||
| 41 | pte_t *ptep; | ||
| 42 | unsigned long flags; | ||
| 43 | struct mm_struct *mm; | ||
| 44 | |||
| 45 | if (user_mode(regs)) | ||
| 46 | mm = current->mm; | ||
| 47 | else | ||
| 48 | mm = &init_mm; | ||
| 49 | |||
| 50 | local_irq_save(flags); | ||
| 51 | if (mm == current->mm) | ||
| 52 | ptep = find_current_mm_pte(mm->pgd, addr, NULL, NULL); | ||
| 53 | else | ||
| 54 | ptep = find_init_mm_pte(addr, NULL); | ||
| 55 | local_irq_restore(flags); | ||
| 56 | if (!ptep || pte_special(*ptep)) | ||
| 57 | return ULONG_MAX; | ||
| 58 | return pte_pfn(*ptep); | ||
| 59 | } | ||
| 30 | 60 | ||
| 31 | static void flush_tlb_206(unsigned int num_sets, unsigned int action) | 61 | static void flush_tlb_206(unsigned int num_sets, unsigned int action) |
| 32 | { | 62 | { |
| @@ -128,7 +158,7 @@ void __flush_tlb_power9(unsigned int action) | |||
| 128 | { | 158 | { |
| 129 | unsigned int num_sets; | 159 | unsigned int num_sets; |
| 130 | 160 | ||
| 131 | if (radix_enabled()) | 161 | if (early_radix_enabled()) |
| 132 | num_sets = POWER9_TLB_SETS_RADIX; | 162 | num_sets = POWER9_TLB_SETS_RADIX; |
| 133 | else | 163 | else |
| 134 | num_sets = POWER9_TLB_SETS_HASH; | 164 | num_sets = POWER9_TLB_SETS_HASH; |
| @@ -138,7 +168,7 @@ void __flush_tlb_power9(unsigned int action) | |||
| 138 | 168 | ||
| 139 | 169 | ||
| 140 | /* flush SLBs and reload */ | 170 | /* flush SLBs and reload */ |
| 141 | #ifdef CONFIG_PPC_STD_MMU_64 | 171 | #ifdef CONFIG_PPC_BOOK3S_64 |
| 142 | static void flush_and_reload_slb(void) | 172 | static void flush_and_reload_slb(void) |
| 143 | { | 173 | { |
| 144 | struct slb_shadow *slb; | 174 | struct slb_shadow *slb; |
| @@ -185,7 +215,7 @@ static void flush_erat(void) | |||
| 185 | 215 | ||
| 186 | static int mce_flush(int what) | 216 | static int mce_flush(int what) |
| 187 | { | 217 | { |
| 188 | #ifdef CONFIG_PPC_STD_MMU_64 | 218 | #ifdef CONFIG_PPC_BOOK3S_64 |
| 189 | if (what == MCE_FLUSH_SLB) { | 219 | if (what == MCE_FLUSH_SLB) { |
| 190 | flush_and_reload_slb(); | 220 | flush_and_reload_slb(); |
| 191 | return 1; | 221 | return 1; |
| @@ -421,9 +451,45 @@ static const struct mce_derror_table mce_p9_derror_table[] = { | |||
| 421 | MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, }, | 451 | MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, }, |
| 422 | { 0, false, 0, 0, 0, 0 } }; | 452 | { 0, false, 0, 0, 0, 0 } }; |
| 423 | 453 | ||
| 454 | static int mce_find_instr_ea_and_pfn(struct pt_regs *regs, uint64_t *addr, | ||
| 455 | uint64_t *phys_addr) | ||
| 456 | { | ||
| 457 | /* | ||
| 458 | * Carefully look at the NIP to determine | ||
| 459 | * the instruction to analyse. Reading the NIP | ||
| 460 | * in real-mode is tricky and can lead to recursive | ||
| 461 | * faults | ||
| 462 | */ | ||
| 463 | int instr; | ||
| 464 | unsigned long pfn, instr_addr; | ||
| 465 | struct instruction_op op; | ||
| 466 | struct pt_regs tmp = *regs; | ||
| 467 | |||
| 468 | pfn = addr_to_pfn(regs, regs->nip); | ||
| 469 | if (pfn != ULONG_MAX) { | ||
| 470 | instr_addr = (pfn << PAGE_SHIFT) + (regs->nip & ~PAGE_MASK); | ||
| 471 | instr = *(unsigned int *)(instr_addr); | ||
| 472 | if (!analyse_instr(&op, &tmp, instr)) { | ||
| 473 | pfn = addr_to_pfn(regs, op.ea); | ||
| 474 | *addr = op.ea; | ||
| 475 | *phys_addr = (pfn << PAGE_SHIFT); | ||
| 476 | return 0; | ||
| 477 | } | ||
| 478 | /* | ||
| 479 | * analyse_instr() might fail if the instruction | ||
| 480 | * is not a load/store, although this is unexpected | ||
| 481 | * for load/store errors or if we got the NIP | ||
| 482 | * wrong | ||
| 483 | */ | ||
| 484 | } | ||
| 485 | *addr = 0; | ||
| 486 | return -1; | ||
| 487 | } | ||
| 488 | |||
| 424 | static int mce_handle_ierror(struct pt_regs *regs, | 489 | static int mce_handle_ierror(struct pt_regs *regs, |
| 425 | const struct mce_ierror_table table[], | 490 | const struct mce_ierror_table table[], |
| 426 | struct mce_error_info *mce_err, uint64_t *addr) | 491 | struct mce_error_info *mce_err, uint64_t *addr, |
| 492 | uint64_t *phys_addr) | ||
| 427 | { | 493 | { |
| 428 | uint64_t srr1 = regs->msr; | 494 | uint64_t srr1 = regs->msr; |
| 429 | int handled = 0; | 495 | int handled = 0; |
| @@ -475,8 +541,22 @@ static int mce_handle_ierror(struct pt_regs *regs, | |||
| 475 | } | 541 | } |
| 476 | mce_err->severity = table[i].severity; | 542 | mce_err->severity = table[i].severity; |
| 477 | mce_err->initiator = table[i].initiator; | 543 | mce_err->initiator = table[i].initiator; |
| 478 | if (table[i].nip_valid) | 544 | if (table[i].nip_valid) { |
| 479 | *addr = regs->nip; | 545 | *addr = regs->nip; |
| 546 | if (mce_err->severity == MCE_SEV_ERROR_SYNC && | ||
| 547 | table[i].error_type == MCE_ERROR_TYPE_UE) { | ||
| 548 | unsigned long pfn; | ||
| 549 | |||
| 550 | if (get_paca()->in_mce < MAX_MCE_DEPTH) { | ||
| 551 | pfn = addr_to_pfn(regs, regs->nip); | ||
| 552 | if (pfn != ULONG_MAX) { | ||
| 553 | *phys_addr = | ||
| 554 | (pfn << PAGE_SHIFT); | ||
| 555 | handled = 1; | ||
| 556 | } | ||
| 557 | } | ||
| 558 | } | ||
| 559 | } | ||
| 480 | return handled; | 560 | return handled; |
| 481 | } | 561 | } |
| 482 | 562 | ||
| @@ -489,7 +569,8 @@ static int mce_handle_ierror(struct pt_regs *regs, | |||
| 489 | 569 | ||
| 490 | static int mce_handle_derror(struct pt_regs *regs, | 570 | static int mce_handle_derror(struct pt_regs *regs, |
| 491 | const struct mce_derror_table table[], | 571 | const struct mce_derror_table table[], |
| 492 | struct mce_error_info *mce_err, uint64_t *addr) | 572 | struct mce_error_info *mce_err, uint64_t *addr, |
| 573 | uint64_t *phys_addr) | ||
| 493 | { | 574 | { |
| 494 | uint64_t dsisr = regs->dsisr; | 575 | uint64_t dsisr = regs->dsisr; |
| 495 | int handled = 0; | 576 | int handled = 0; |
| @@ -555,7 +636,17 @@ static int mce_handle_derror(struct pt_regs *regs, | |||
| 555 | mce_err->initiator = table[i].initiator; | 636 | mce_err->initiator = table[i].initiator; |
| 556 | if (table[i].dar_valid) | 637 | if (table[i].dar_valid) |
| 557 | *addr = regs->dar; | 638 | *addr = regs->dar; |
| 558 | 639 | else if (mce_err->severity == MCE_SEV_ERROR_SYNC && | |
| 640 | table[i].error_type == MCE_ERROR_TYPE_UE) { | ||
| 641 | /* | ||
| 642 | * We do a maximum of 4 nested MCE calls, see | ||
| 643 | * kernel/exception-64s.h | ||
| 644 | */ | ||
| 645 | if (get_paca()->in_mce < MAX_MCE_DEPTH) | ||
| 646 | if (!mce_find_instr_ea_and_pfn(regs, addr, | ||
| 647 | phys_addr)) | ||
| 648 | handled = 1; | ||
| 649 | } | ||
| 559 | found = 1; | 650 | found = 1; |
| 560 | } | 651 | } |
| 561 | 652 | ||
| @@ -592,19 +683,21 @@ static long mce_handle_error(struct pt_regs *regs, | |||
| 592 | const struct mce_ierror_table itable[]) | 683 | const struct mce_ierror_table itable[]) |
| 593 | { | 684 | { |
| 594 | struct mce_error_info mce_err = { 0 }; | 685 | struct mce_error_info mce_err = { 0 }; |
| 595 | uint64_t addr; | 686 | uint64_t addr, phys_addr; |
| 596 | uint64_t srr1 = regs->msr; | 687 | uint64_t srr1 = regs->msr; |
| 597 | long handled; | 688 | long handled; |
| 598 | 689 | ||
| 599 | if (SRR1_MC_LOADSTORE(srr1)) | 690 | if (SRR1_MC_LOADSTORE(srr1)) |
| 600 | handled = mce_handle_derror(regs, dtable, &mce_err, &addr); | 691 | handled = mce_handle_derror(regs, dtable, &mce_err, &addr, |
| 692 | &phys_addr); | ||
| 601 | else | 693 | else |
| 602 | handled = mce_handle_ierror(regs, itable, &mce_err, &addr); | 694 | handled = mce_handle_ierror(regs, itable, &mce_err, &addr, |
| 695 | &phys_addr); | ||
| 603 | 696 | ||
| 604 | if (!handled && mce_err.error_type == MCE_ERROR_TYPE_UE) | 697 | if (!handled && mce_err.error_type == MCE_ERROR_TYPE_UE) |
| 605 | handled = mce_handle_ue_error(regs); | 698 | handled = mce_handle_ue_error(regs); |
| 606 | 699 | ||
| 607 | save_mce_event(regs, handled, &mce_err, regs->nip, addr); | 700 | save_mce_event(regs, handled, &mce_err, regs->nip, addr, phys_addr); |
| 608 | 701 | ||
| 609 | return handled; | 702 | return handled; |
| 610 | } | 703 | } |
diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c index 0b0f89685b67..759104b99f9f 100644 --- a/arch/powerpc/kernel/module_64.c +++ b/arch/powerpc/kernel/module_64.c | |||
| @@ -429,7 +429,8 @@ static unsigned long stub_for_addr(const Elf64_Shdr *sechdrs, | |||
| 429 | /* Find this stub, or if that fails, the next avail. entry */ | 429 | /* Find this stub, or if that fails, the next avail. entry */ |
| 430 | stubs = (void *)sechdrs[me->arch.stubs_section].sh_addr; | 430 | stubs = (void *)sechdrs[me->arch.stubs_section].sh_addr; |
| 431 | for (i = 0; stub_func_addr(stubs[i].funcdata); i++) { | 431 | for (i = 0; stub_func_addr(stubs[i].funcdata); i++) { |
| 432 | BUG_ON(i >= num_stubs); | 432 | if (WARN_ON(i >= num_stubs)) |
| 433 | return 0; | ||
| 433 | 434 | ||
| 434 | if (stub_func_addr(stubs[i].funcdata) == func_addr(addr)) | 435 | if (stub_func_addr(stubs[i].funcdata) == func_addr(addr)) |
| 435 | return (unsigned long)&stubs[i]; | 436 | return (unsigned long)&stubs[i]; |
diff --git a/arch/powerpc/kernel/optprobes.c b/arch/powerpc/kernel/optprobes.c index 91e037ab20a1..8237884ca389 100644 --- a/arch/powerpc/kernel/optprobes.c +++ b/arch/powerpc/kernel/optprobes.c | |||
| @@ -115,32 +115,23 @@ static unsigned long can_optimize(struct kprobe *p) | |||
| 115 | static void optimized_callback(struct optimized_kprobe *op, | 115 | static void optimized_callback(struct optimized_kprobe *op, |
| 116 | struct pt_regs *regs) | 116 | struct pt_regs *regs) |
| 117 | { | 117 | { |
| 118 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); | ||
| 119 | unsigned long flags; | ||
| 120 | |||
| 121 | /* This is possible if op is under delayed unoptimizing */ | 118 | /* This is possible if op is under delayed unoptimizing */ |
| 122 | if (kprobe_disabled(&op->kp)) | 119 | if (kprobe_disabled(&op->kp)) |
| 123 | return; | 120 | return; |
| 124 | 121 | ||
| 125 | local_irq_save(flags); | 122 | preempt_disable(); |
| 126 | hard_irq_disable(); | ||
| 127 | 123 | ||
| 128 | if (kprobe_running()) { | 124 | if (kprobe_running()) { |
| 129 | kprobes_inc_nmissed_count(&op->kp); | 125 | kprobes_inc_nmissed_count(&op->kp); |
| 130 | } else { | 126 | } else { |
| 131 | __this_cpu_write(current_kprobe, &op->kp); | 127 | __this_cpu_write(current_kprobe, &op->kp); |
| 132 | regs->nip = (unsigned long)op->kp.addr; | 128 | regs->nip = (unsigned long)op->kp.addr; |
| 133 | kcb->kprobe_status = KPROBE_HIT_ACTIVE; | 129 | get_kprobe_ctlblk()->kprobe_status = KPROBE_HIT_ACTIVE; |
| 134 | opt_pre_handler(&op->kp, regs); | 130 | opt_pre_handler(&op->kp, regs); |
| 135 | __this_cpu_write(current_kprobe, NULL); | 131 | __this_cpu_write(current_kprobe, NULL); |
| 136 | } | 132 | } |
| 137 | 133 | ||
| 138 | /* | 134 | preempt_enable_no_resched(); |
| 139 | * No need for an explicit __hard_irq_enable() here. | ||
| 140 | * local_irq_restore() will re-enable interrupts, | ||
| 141 | * if they were hard disabled. | ||
| 142 | */ | ||
| 143 | local_irq_restore(flags); | ||
| 144 | } | 135 | } |
| 145 | NOKPROBE_SYMBOL(optimized_callback); | 136 | NOKPROBE_SYMBOL(optimized_callback); |
| 146 | 137 | ||
diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c index 2ff2b8a19f71..d6597038931d 100644 --- a/arch/powerpc/kernel/paca.c +++ b/arch/powerpc/kernel/paca.c | |||
| @@ -90,7 +90,7 @@ static inline void free_lppacas(void) { } | |||
| 90 | 90 | ||
| 91 | #endif /* CONFIG_PPC_BOOK3S */ | 91 | #endif /* CONFIG_PPC_BOOK3S */ |
| 92 | 92 | ||
| 93 | #ifdef CONFIG_PPC_STD_MMU_64 | 93 | #ifdef CONFIG_PPC_BOOK3S_64 |
| 94 | 94 | ||
| 95 | /* | 95 | /* |
| 96 | * 3 persistent SLBs are registered here. The buffer will be zero | 96 | * 3 persistent SLBs are registered here. The buffer will be zero |
| @@ -135,11 +135,11 @@ static struct slb_shadow * __init init_slb_shadow(int cpu) | |||
| 135 | return s; | 135 | return s; |
| 136 | } | 136 | } |
| 137 | 137 | ||
| 138 | #else /* CONFIG_PPC_STD_MMU_64 */ | 138 | #else /* !CONFIG_PPC_BOOK3S_64 */ |
| 139 | 139 | ||
| 140 | static void __init allocate_slb_shadows(int nr_cpus, int limit) { } | 140 | static void __init allocate_slb_shadows(int nr_cpus, int limit) { } |
| 141 | 141 | ||
| 142 | #endif /* CONFIG_PPC_STD_MMU_64 */ | 142 | #endif /* CONFIG_PPC_BOOK3S_64 */ |
| 143 | 143 | ||
| 144 | /* The Paca is an array with one entry per processor. Each contains an | 144 | /* The Paca is an array with one entry per processor. Each contains an |
| 145 | * lppaca, which contains the information shared between the | 145 | * lppaca, which contains the information shared between the |
| @@ -170,9 +170,9 @@ void __init initialise_paca(struct paca_struct *new_paca, int cpu) | |||
| 170 | new_paca->kexec_state = KEXEC_STATE_NONE; | 170 | new_paca->kexec_state = KEXEC_STATE_NONE; |
| 171 | new_paca->__current = &init_task; | 171 | new_paca->__current = &init_task; |
| 172 | new_paca->data_offset = 0xfeeeeeeeeeeeeeeeULL; | 172 | new_paca->data_offset = 0xfeeeeeeeeeeeeeeeULL; |
| 173 | #ifdef CONFIG_PPC_STD_MMU_64 | 173 | #ifdef CONFIG_PPC_BOOK3S_64 |
| 174 | new_paca->slb_shadow_ptr = init_slb_shadow(cpu); | 174 | new_paca->slb_shadow_ptr = init_slb_shadow(cpu); |
| 175 | #endif /* CONFIG_PPC_STD_MMU_64 */ | 175 | #endif |
| 176 | 176 | ||
| 177 | #ifdef CONFIG_PPC_BOOK3E | 177 | #ifdef CONFIG_PPC_BOOK3E |
| 178 | /* For now -- if we have threads this will be adjusted later */ | 178 | /* For now -- if we have threads this will be adjusted later */ |
| @@ -262,8 +262,8 @@ void copy_mm_to_paca(struct mm_struct *mm) | |||
| 262 | 262 | ||
| 263 | get_paca()->mm_ctx_id = context->id; | 263 | get_paca()->mm_ctx_id = context->id; |
| 264 | #ifdef CONFIG_PPC_MM_SLICES | 264 | #ifdef CONFIG_PPC_MM_SLICES |
| 265 | VM_BUG_ON(!mm->context.addr_limit); | 265 | VM_BUG_ON(!mm->context.slb_addr_limit); |
| 266 | get_paca()->addr_limit = mm->context.addr_limit; | 266 | get_paca()->mm_ctx_slb_addr_limit = mm->context.slb_addr_limit; |
| 267 | get_paca()->mm_ctx_low_slices_psize = context->low_slices_psize; | 267 | get_paca()->mm_ctx_low_slices_psize = context->low_slices_psize; |
| 268 | memcpy(&get_paca()->mm_ctx_high_slices_psize, | 268 | memcpy(&get_paca()->mm_ctx_high_slices_psize, |
| 269 | &context->high_slices_psize, TASK_SLICE_ARRAY_SZ(mm)); | 269 | &context->high_slices_psize, TASK_SLICE_ARRAY_SZ(mm)); |
| @@ -271,7 +271,7 @@ void copy_mm_to_paca(struct mm_struct *mm) | |||
| 271 | get_paca()->mm_ctx_user_psize = context->user_psize; | 271 | get_paca()->mm_ctx_user_psize = context->user_psize; |
| 272 | get_paca()->mm_ctx_sllp = context->sllp; | 272 | get_paca()->mm_ctx_sllp = context->sllp; |
| 273 | #endif | 273 | #endif |
| 274 | #else /* CONFIG_PPC_BOOK3S */ | 274 | #else /* !CONFIG_PPC_BOOK3S */ |
| 275 | return; | 275 | return; |
| 276 | #endif | 276 | #endif |
| 277 | } | 277 | } |
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 932b9741aa8f..15ce0306b092 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c | |||
| @@ -90,14 +90,14 @@ int pcibios_unmap_io_space(struct pci_bus *bus) | |||
| 90 | * to do an appropriate TLB flush here too | 90 | * to do an appropriate TLB flush here too |
| 91 | */ | 91 | */ |
| 92 | if (bus->self) { | 92 | if (bus->self) { |
| 93 | #ifdef CONFIG_PPC_STD_MMU_64 | 93 | #ifdef CONFIG_PPC_BOOK3S_64 |
| 94 | struct resource *res = bus->resource[0]; | 94 | struct resource *res = bus->resource[0]; |
| 95 | #endif | 95 | #endif |
| 96 | 96 | ||
| 97 | pr_debug("IO unmapping for PCI-PCI bridge %s\n", | 97 | pr_debug("IO unmapping for PCI-PCI bridge %s\n", |
| 98 | pci_name(bus->self)); | 98 | pci_name(bus->self)); |
| 99 | 99 | ||
| 100 | #ifdef CONFIG_PPC_STD_MMU_64 | 100 | #ifdef CONFIG_PPC_BOOK3S_64 |
| 101 | __flush_hash_table_range(&init_mm, res->start + _IO_BASE, | 101 | __flush_hash_table_range(&init_mm, res->start + _IO_BASE, |
| 102 | res->end + _IO_BASE + 1); | 102 | res->end + _IO_BASE + 1); |
| 103 | #endif | 103 | #endif |
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index a0c74bbf3454..bfdd783e3916 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c | |||
| @@ -77,6 +77,13 @@ | |||
| 77 | extern unsigned long _get_SP(void); | 77 | extern unsigned long _get_SP(void); |
| 78 | 78 | ||
| 79 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | 79 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM |
| 80 | /* | ||
| 81 | * Are we running in "Suspend disabled" mode? If so we have to block any | ||
| 82 | * sigreturn that would get us into suspended state, and we also warn in some | ||
| 83 | * other paths that we should never reach with suspend disabled. | ||
| 84 | */ | ||
| 85 | bool tm_suspend_disabled __ro_after_init = false; | ||
| 86 | |||
| 80 | static void check_if_tm_restore_required(struct task_struct *tsk) | 87 | static void check_if_tm_restore_required(struct task_struct *tsk) |
| 81 | { | 88 | { |
| 82 | /* | 89 | /* |
| @@ -97,9 +104,23 @@ static inline bool msr_tm_active(unsigned long msr) | |||
| 97 | { | 104 | { |
| 98 | return MSR_TM_ACTIVE(msr); | 105 | return MSR_TM_ACTIVE(msr); |
| 99 | } | 106 | } |
| 107 | |||
| 108 | static bool tm_active_with_fp(struct task_struct *tsk) | ||
| 109 | { | ||
| 110 | return msr_tm_active(tsk->thread.regs->msr) && | ||
| 111 | (tsk->thread.ckpt_regs.msr & MSR_FP); | ||
| 112 | } | ||
| 113 | |||
| 114 | static bool tm_active_with_altivec(struct task_struct *tsk) | ||
| 115 | { | ||
| 116 | return msr_tm_active(tsk->thread.regs->msr) && | ||
| 117 | (tsk->thread.ckpt_regs.msr & MSR_VEC); | ||
| 118 | } | ||
| 100 | #else | 119 | #else |
| 101 | static inline bool msr_tm_active(unsigned long msr) { return false; } | 120 | static inline bool msr_tm_active(unsigned long msr) { return false; } |
| 102 | static inline void check_if_tm_restore_required(struct task_struct *tsk) { } | 121 | static inline void check_if_tm_restore_required(struct task_struct *tsk) { } |
| 122 | static inline bool tm_active_with_fp(struct task_struct *tsk) { return false; } | ||
| 123 | static inline bool tm_active_with_altivec(struct task_struct *tsk) { return false; } | ||
| 103 | #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */ | 124 | #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */ |
| 104 | 125 | ||
| 105 | bool strict_msr_control; | 126 | bool strict_msr_control; |
| @@ -232,7 +253,7 @@ EXPORT_SYMBOL(enable_kernel_fp); | |||
| 232 | 253 | ||
| 233 | static int restore_fp(struct task_struct *tsk) | 254 | static int restore_fp(struct task_struct *tsk) |
| 234 | { | 255 | { |
| 235 | if (tsk->thread.load_fp || msr_tm_active(tsk->thread.regs->msr)) { | 256 | if (tsk->thread.load_fp || tm_active_with_fp(tsk)) { |
| 236 | load_fp_state(¤t->thread.fp_state); | 257 | load_fp_state(¤t->thread.fp_state); |
| 237 | current->thread.load_fp++; | 258 | current->thread.load_fp++; |
| 238 | return 1; | 259 | return 1; |
| @@ -314,7 +335,7 @@ EXPORT_SYMBOL_GPL(flush_altivec_to_thread); | |||
| 314 | static int restore_altivec(struct task_struct *tsk) | 335 | static int restore_altivec(struct task_struct *tsk) |
| 315 | { | 336 | { |
| 316 | if (cpu_has_feature(CPU_FTR_ALTIVEC) && | 337 | if (cpu_has_feature(CPU_FTR_ALTIVEC) && |
| 317 | (tsk->thread.load_vec || msr_tm_active(tsk->thread.regs->msr))) { | 338 | (tsk->thread.load_vec || tm_active_with_altivec(tsk))) { |
| 318 | load_vr_state(&tsk->thread.vr_state); | 339 | load_vr_state(&tsk->thread.vr_state); |
| 319 | tsk->thread.used_vr = 1; | 340 | tsk->thread.used_vr = 1; |
| 320 | tsk->thread.load_vec++; | 341 | tsk->thread.load_vec++; |
| @@ -853,6 +874,10 @@ static void tm_reclaim_thread(struct thread_struct *thr, | |||
| 853 | if (!MSR_TM_SUSPENDED(mfmsr())) | 874 | if (!MSR_TM_SUSPENDED(mfmsr())) |
| 854 | return; | 875 | return; |
| 855 | 876 | ||
| 877 | giveup_all(container_of(thr, struct task_struct, thread)); | ||
| 878 | |||
| 879 | tm_reclaim(thr, cause); | ||
| 880 | |||
| 856 | /* | 881 | /* |
| 857 | * If we are in a transaction and FP is off then we can't have | 882 | * If we are in a transaction and FP is off then we can't have |
| 858 | * used FP inside that transaction. Hence the checkpointed | 883 | * used FP inside that transaction. Hence the checkpointed |
| @@ -871,10 +896,6 @@ static void tm_reclaim_thread(struct thread_struct *thr, | |||
| 871 | if ((thr->ckpt_regs.msr & MSR_VEC) == 0) | 896 | if ((thr->ckpt_regs.msr & MSR_VEC) == 0) |
| 872 | memcpy(&thr->ckvr_state, &thr->vr_state, | 897 | memcpy(&thr->ckvr_state, &thr->vr_state, |
| 873 | sizeof(struct thread_vr_state)); | 898 | sizeof(struct thread_vr_state)); |
| 874 | |||
| 875 | giveup_all(container_of(thr, struct task_struct, thread)); | ||
| 876 | |||
| 877 | tm_reclaim(thr, thr->ckpt_regs.msr, cause); | ||
| 878 | } | 899 | } |
| 879 | 900 | ||
| 880 | void tm_reclaim_current(uint8_t cause) | 901 | void tm_reclaim_current(uint8_t cause) |
| @@ -903,6 +924,8 @@ static inline void tm_reclaim_task(struct task_struct *tsk) | |||
| 903 | if (!MSR_TM_ACTIVE(thr->regs->msr)) | 924 | if (!MSR_TM_ACTIVE(thr->regs->msr)) |
| 904 | goto out_and_saveregs; | 925 | goto out_and_saveregs; |
| 905 | 926 | ||
| 927 | WARN_ON(tm_suspend_disabled); | ||
| 928 | |||
| 906 | TM_DEBUG("--- tm_reclaim on pid %d (NIP=%lx, " | 929 | TM_DEBUG("--- tm_reclaim on pid %d (NIP=%lx, " |
| 907 | "ccr=%lx, msr=%lx, trap=%lx)\n", | 930 | "ccr=%lx, msr=%lx, trap=%lx)\n", |
| 908 | tsk->pid, thr->regs->nip, | 931 | tsk->pid, thr->regs->nip, |
| @@ -923,11 +946,9 @@ out_and_saveregs: | |||
| 923 | tm_save_sprs(thr); | 946 | tm_save_sprs(thr); |
| 924 | } | 947 | } |
| 925 | 948 | ||
| 926 | extern void __tm_recheckpoint(struct thread_struct *thread, | 949 | extern void __tm_recheckpoint(struct thread_struct *thread); |
| 927 | unsigned long orig_msr); | ||
| 928 | 950 | ||
| 929 | void tm_recheckpoint(struct thread_struct *thread, | 951 | void tm_recheckpoint(struct thread_struct *thread) |
| 930 | unsigned long orig_msr) | ||
| 931 | { | 952 | { |
| 932 | unsigned long flags; | 953 | unsigned long flags; |
| 933 | 954 | ||
| @@ -946,15 +967,13 @@ void tm_recheckpoint(struct thread_struct *thread, | |||
| 946 | */ | 967 | */ |
| 947 | tm_restore_sprs(thread); | 968 | tm_restore_sprs(thread); |
| 948 | 969 | ||
| 949 | __tm_recheckpoint(thread, orig_msr); | 970 | __tm_recheckpoint(thread); |
| 950 | 971 | ||
| 951 | local_irq_restore(flags); | 972 | local_irq_restore(flags); |
| 952 | } | 973 | } |
| 953 | 974 | ||
| 954 | static inline void tm_recheckpoint_new_task(struct task_struct *new) | 975 | static inline void tm_recheckpoint_new_task(struct task_struct *new) |
| 955 | { | 976 | { |
| 956 | unsigned long msr; | ||
| 957 | |||
| 958 | if (!cpu_has_feature(CPU_FTR_TM)) | 977 | if (!cpu_has_feature(CPU_FTR_TM)) |
| 959 | return; | 978 | return; |
| 960 | 979 | ||
| @@ -973,13 +992,11 @@ static inline void tm_recheckpoint_new_task(struct task_struct *new) | |||
| 973 | tm_restore_sprs(&new->thread); | 992 | tm_restore_sprs(&new->thread); |
| 974 | return; | 993 | return; |
| 975 | } | 994 | } |
| 976 | msr = new->thread.ckpt_regs.msr; | ||
| 977 | /* Recheckpoint to restore original checkpointed register state. */ | 995 | /* Recheckpoint to restore original checkpointed register state. */ |
| 978 | TM_DEBUG("*** tm_recheckpoint of pid %d " | 996 | TM_DEBUG("*** tm_recheckpoint of pid %d (new->msr 0x%lx)\n", |
| 979 | "(new->msr 0x%lx, new->origmsr 0x%lx)\n", | 997 | new->pid, new->thread.regs->msr); |
| 980 | new->pid, new->thread.regs->msr, msr); | ||
| 981 | 998 | ||
| 982 | tm_recheckpoint(&new->thread, msr); | 999 | tm_recheckpoint(&new->thread); |
| 983 | 1000 | ||
| 984 | /* | 1001 | /* |
| 985 | * The checkpointed state has been restored but the live state has | 1002 | * The checkpointed state has been restored but the live state has |
| @@ -1119,6 +1136,10 @@ static inline void restore_sprs(struct thread_struct *old_thread, | |||
| 1119 | if (old_thread->tar != new_thread->tar) | 1136 | if (old_thread->tar != new_thread->tar) |
| 1120 | mtspr(SPRN_TAR, new_thread->tar); | 1137 | mtspr(SPRN_TAR, new_thread->tar); |
| 1121 | } | 1138 | } |
| 1139 | |||
| 1140 | if (cpu_has_feature(CPU_FTR_ARCH_300) && | ||
| 1141 | old_thread->tidr != new_thread->tidr) | ||
| 1142 | mtspr(SPRN_TIDR, new_thread->tidr); | ||
| 1122 | #endif | 1143 | #endif |
| 1123 | } | 1144 | } |
| 1124 | 1145 | ||
| @@ -1155,7 +1176,7 @@ struct task_struct *__switch_to(struct task_struct *prev, | |||
| 1155 | } | 1176 | } |
| 1156 | #endif /* CONFIG_PPC64 */ | 1177 | #endif /* CONFIG_PPC64 */ |
| 1157 | 1178 | ||
| 1158 | #ifdef CONFIG_PPC_STD_MMU_64 | 1179 | #ifdef CONFIG_PPC_BOOK3S_64 |
| 1159 | batch = this_cpu_ptr(&ppc64_tlb_batch); | 1180 | batch = this_cpu_ptr(&ppc64_tlb_batch); |
| 1160 | if (batch->active) { | 1181 | if (batch->active) { |
| 1161 | current_thread_info()->local_flags |= _TLF_LAZY_MMU; | 1182 | current_thread_info()->local_flags |= _TLF_LAZY_MMU; |
| @@ -1163,7 +1184,7 @@ struct task_struct *__switch_to(struct task_struct *prev, | |||
| 1163 | __flush_tlb_pending(batch); | 1184 | __flush_tlb_pending(batch); |
| 1164 | batch->active = 0; | 1185 | batch->active = 0; |
| 1165 | } | 1186 | } |
| 1166 | #endif /* CONFIG_PPC_STD_MMU_64 */ | 1187 | #endif /* CONFIG_PPC_BOOK3S_64 */ |
| 1167 | 1188 | ||
| 1168 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS | 1189 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS |
| 1169 | switch_booke_debug_regs(&new->thread.debug); | 1190 | switch_booke_debug_regs(&new->thread.debug); |
| @@ -1209,7 +1230,7 @@ struct task_struct *__switch_to(struct task_struct *prev, | |||
| 1209 | 1230 | ||
| 1210 | last = _switch(old_thread, new_thread); | 1231 | last = _switch(old_thread, new_thread); |
| 1211 | 1232 | ||
| 1212 | #ifdef CONFIG_PPC_STD_MMU_64 | 1233 | #ifdef CONFIG_PPC_BOOK3S_64 |
| 1213 | if (current_thread_info()->local_flags & _TLF_LAZY_MMU) { | 1234 | if (current_thread_info()->local_flags & _TLF_LAZY_MMU) { |
| 1214 | current_thread_info()->local_flags &= ~_TLF_LAZY_MMU; | 1235 | current_thread_info()->local_flags &= ~_TLF_LAZY_MMU; |
| 1215 | batch = this_cpu_ptr(&ppc64_tlb_batch); | 1236 | batch = this_cpu_ptr(&ppc64_tlb_batch); |
| @@ -1223,22 +1244,22 @@ struct task_struct *__switch_to(struct task_struct *prev, | |||
| 1223 | * The copy-paste buffer can only store into foreign real | 1244 | * The copy-paste buffer can only store into foreign real |
| 1224 | * addresses, so unprivileged processes can not see the | 1245 | * addresses, so unprivileged processes can not see the |
| 1225 | * data or use it in any way unless they have foreign real | 1246 | * data or use it in any way unless they have foreign real |
| 1226 | * mappings. We don't have a VAS driver that allocates those | 1247 | * mappings. If the new process has the foreign real address |
| 1227 | * yet, so no cpabort is required. | 1248 | * mappings, we must issue a cp_abort to clear any state and |
| 1249 | * prevent snooping, corruption or a covert channel. | ||
| 1250 | * | ||
| 1251 | * DD1 allows paste into normal system memory so we do an | ||
| 1252 | * unpaired copy, rather than cp_abort, to clear the buffer, | ||
| 1253 | * since cp_abort is quite expensive. | ||
| 1228 | */ | 1254 | */ |
| 1229 | if (cpu_has_feature(CPU_FTR_POWER9_DD1)) { | 1255 | if (current_thread_info()->task->thread.used_vas) { |
| 1230 | /* | 1256 | asm volatile(PPC_CP_ABORT); |
| 1231 | * DD1 allows paste into normal system memory, so we | 1257 | } else if (cpu_has_feature(CPU_FTR_POWER9_DD1)) { |
| 1232 | * do an unpaired copy here to clear the buffer and | ||
| 1233 | * prevent a covert channel being set up. | ||
| 1234 | * | ||
| 1235 | * cpabort is not used because it is quite expensive. | ||
| 1236 | */ | ||
| 1237 | asm volatile(PPC_COPY(%0, %1) | 1258 | asm volatile(PPC_COPY(%0, %1) |
| 1238 | : : "r"(dummy_copy_buffer), "r"(0)); | 1259 | : : "r"(dummy_copy_buffer), "r"(0)); |
| 1239 | } | 1260 | } |
| 1240 | } | 1261 | } |
| 1241 | #endif /* CONFIG_PPC_STD_MMU_64 */ | 1262 | #endif /* CONFIG_PPC_BOOK3S_64 */ |
| 1242 | 1263 | ||
| 1243 | return last; | 1264 | return last; |
| 1244 | } | 1265 | } |
| @@ -1434,6 +1455,137 @@ void flush_thread(void) | |||
| 1434 | #endif /* CONFIG_HAVE_HW_BREAKPOINT */ | 1455 | #endif /* CONFIG_HAVE_HW_BREAKPOINT */ |
| 1435 | } | 1456 | } |
| 1436 | 1457 | ||
| 1458 | int set_thread_uses_vas(void) | ||
| 1459 | { | ||
| 1460 | #ifdef CONFIG_PPC_BOOK3S_64 | ||
| 1461 | if (!cpu_has_feature(CPU_FTR_ARCH_300)) | ||
| 1462 | return -EINVAL; | ||
| 1463 | |||
| 1464 | current->thread.used_vas = 1; | ||
| 1465 | |||
| 1466 | /* | ||
| 1467 | * Even a process that has no foreign real address mapping can use | ||
| 1468 | * an unpaired COPY instruction (to no real effect). Issue CP_ABORT | ||
| 1469 | * to clear any pending COPY and prevent a covert channel. | ||
| 1470 | * | ||
| 1471 | * __switch_to() will issue CP_ABORT on future context switches. | ||
| 1472 | */ | ||
| 1473 | asm volatile(PPC_CP_ABORT); | ||
| 1474 | |||
| 1475 | #endif /* CONFIG_PPC_BOOK3S_64 */ | ||
| 1476 | return 0; | ||
| 1477 | } | ||
| 1478 | |||
| 1479 | #ifdef CONFIG_PPC64 | ||
| 1480 | static DEFINE_SPINLOCK(vas_thread_id_lock); | ||
| 1481 | static DEFINE_IDA(vas_thread_ida); | ||
| 1482 | |||
| 1483 | /* | ||
| 1484 | * We need to assign a unique thread id to each thread in a process. | ||
| 1485 | * | ||
| 1486 | * This thread id, referred to as TIDR, and separate from the Linux's tgid, | ||
| 1487 | * is intended to be used to direct an ASB_Notify from the hardware to the | ||
| 1488 | * thread, when a suitable event occurs in the system. | ||
| 1489 | * | ||
| 1490 | * One such event is a "paste" instruction in the context of Fast Thread | ||
| 1491 | * Wakeup (aka Core-to-core wake up in the Virtual Accelerator Switchboard | ||
| 1492 | * (VAS) in POWER9. | ||
| 1493 | * | ||
| 1494 | * To get a unique TIDR per process we could simply reuse task_pid_nr() but | ||
| 1495 | * the problem is that task_pid_nr() is not yet available copy_thread() is | ||
| 1496 | * called. Fixing that would require changing more intrusive arch-neutral | ||
| 1497 | * code in code path in copy_process()?. | ||
| 1498 | * | ||
| 1499 | * Further, to assign unique TIDRs within each process, we need an atomic | ||
| 1500 | * field (or an IDR) in task_struct, which again intrudes into the arch- | ||
| 1501 | * neutral code. So try to assign globally unique TIDRs for now. | ||
| 1502 | * | ||
| 1503 | * NOTE: TIDR 0 indicates that the thread does not need a TIDR value. | ||
| 1504 | * For now, only threads that expect to be notified by the VAS | ||
| 1505 | * hardware need a TIDR value and we assign values > 0 for those. | ||
| 1506 | */ | ||
| 1507 | #define MAX_THREAD_CONTEXT ((1 << 16) - 1) | ||
| 1508 | static int assign_thread_tidr(void) | ||
| 1509 | { | ||
| 1510 | int index; | ||
| 1511 | int err; | ||
| 1512 | |||
| 1513 | again: | ||
| 1514 | if (!ida_pre_get(&vas_thread_ida, GFP_KERNEL)) | ||
| 1515 | return -ENOMEM; | ||
| 1516 | |||
| 1517 | spin_lock(&vas_thread_id_lock); | ||
| 1518 | err = ida_get_new_above(&vas_thread_ida, 1, &index); | ||
| 1519 | spin_unlock(&vas_thread_id_lock); | ||
| 1520 | |||
| 1521 | if (err == -EAGAIN) | ||
| 1522 | goto again; | ||
| 1523 | else if (err) | ||
| 1524 | return err; | ||
| 1525 | |||
| 1526 | if (index > MAX_THREAD_CONTEXT) { | ||
| 1527 | spin_lock(&vas_thread_id_lock); | ||
| 1528 | ida_remove(&vas_thread_ida, index); | ||
| 1529 | spin_unlock(&vas_thread_id_lock); | ||
| 1530 | return -ENOMEM; | ||
| 1531 | } | ||
| 1532 | |||
| 1533 | return index; | ||
| 1534 | } | ||
| 1535 | |||
| 1536 | static void free_thread_tidr(int id) | ||
| 1537 | { | ||
| 1538 | spin_lock(&vas_thread_id_lock); | ||
| 1539 | ida_remove(&vas_thread_ida, id); | ||
| 1540 | spin_unlock(&vas_thread_id_lock); | ||
| 1541 | } | ||
| 1542 | |||
| 1543 | /* | ||
| 1544 | * Clear any TIDR value assigned to this thread. | ||
| 1545 | */ | ||
| 1546 | void clear_thread_tidr(struct task_struct *t) | ||
| 1547 | { | ||
| 1548 | if (!t->thread.tidr) | ||
| 1549 | return; | ||
| 1550 | |||
| 1551 | if (!cpu_has_feature(CPU_FTR_ARCH_300)) { | ||
| 1552 | WARN_ON_ONCE(1); | ||
| 1553 | return; | ||
| 1554 | } | ||
| 1555 | |||
| 1556 | mtspr(SPRN_TIDR, 0); | ||
| 1557 | free_thread_tidr(t->thread.tidr); | ||
| 1558 | t->thread.tidr = 0; | ||
| 1559 | } | ||
| 1560 | |||
| 1561 | void arch_release_task_struct(struct task_struct *t) | ||
| 1562 | { | ||
| 1563 | clear_thread_tidr(t); | ||
| 1564 | } | ||
| 1565 | |||
| 1566 | /* | ||
| 1567 | * Assign a unique TIDR (thread id) for task @t and set it in the thread | ||
| 1568 | * structure. For now, we only support setting TIDR for 'current' task. | ||
| 1569 | */ | ||
| 1570 | int set_thread_tidr(struct task_struct *t) | ||
| 1571 | { | ||
| 1572 | if (!cpu_has_feature(CPU_FTR_ARCH_300)) | ||
| 1573 | return -EINVAL; | ||
| 1574 | |||
| 1575 | if (t != current) | ||
| 1576 | return -EINVAL; | ||
| 1577 | |||
| 1578 | t->thread.tidr = assign_thread_tidr(); | ||
| 1579 | if (t->thread.tidr < 0) | ||
| 1580 | return t->thread.tidr; | ||
| 1581 | |||
| 1582 | mtspr(SPRN_TIDR, t->thread.tidr); | ||
| 1583 | |||
| 1584 | return 0; | ||
| 1585 | } | ||
| 1586 | |||
| 1587 | #endif /* CONFIG_PPC64 */ | ||
| 1588 | |||
| 1437 | void | 1589 | void |
| 1438 | release_thread(struct task_struct *t) | 1590 | release_thread(struct task_struct *t) |
| 1439 | { | 1591 | { |
| @@ -1467,7 +1619,7 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) | |||
| 1467 | 1619 | ||
| 1468 | static void setup_ksp_vsid(struct task_struct *p, unsigned long sp) | 1620 | static void setup_ksp_vsid(struct task_struct *p, unsigned long sp) |
| 1469 | { | 1621 | { |
| 1470 | #ifdef CONFIG_PPC_STD_MMU_64 | 1622 | #ifdef CONFIG_PPC_BOOK3S_64 |
| 1471 | unsigned long sp_vsid; | 1623 | unsigned long sp_vsid; |
| 1472 | unsigned long llp = mmu_psize_defs[mmu_linear_psize].sllp; | 1624 | unsigned long llp = mmu_psize_defs[mmu_linear_psize].sllp; |
| 1473 | 1625 | ||
| @@ -1580,6 +1732,8 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, | |||
| 1580 | } | 1732 | } |
| 1581 | if (cpu_has_feature(CPU_FTR_HAS_PPR)) | 1733 | if (cpu_has_feature(CPU_FTR_HAS_PPR)) |
| 1582 | p->thread.ppr = INIT_PPR; | 1734 | p->thread.ppr = INIT_PPR; |
| 1735 | |||
| 1736 | p->thread.tidr = 0; | ||
| 1583 | #endif | 1737 | #endif |
| 1584 | kregs->nip = ppc_function_entry(f); | 1738 | kregs->nip = ppc_function_entry(f); |
| 1585 | return 0; | 1739 | return 0; |
| @@ -1898,7 +2052,8 @@ unsigned long get_wchan(struct task_struct *p) | |||
| 1898 | 2052 | ||
| 1899 | do { | 2053 | do { |
| 1900 | sp = *(unsigned long *)sp; | 2054 | sp = *(unsigned long *)sp; |
| 1901 | if (!validate_sp(sp, p, STACK_FRAME_OVERHEAD)) | 2055 | if (!validate_sp(sp, p, STACK_FRAME_OVERHEAD) || |
| 2056 | p->state == TASK_RUNNING) | ||
| 1902 | return 0; | 2057 | return 0; |
| 1903 | if (count > 0) { | 2058 | if (count > 0) { |
| 1904 | ip = ((unsigned long *)sp)[STACK_FRAME_LR_SAVE]; | 2059 | ip = ((unsigned long *)sp)[STACK_FRAME_LR_SAVE]; |
| @@ -2046,7 +2201,7 @@ unsigned long arch_randomize_brk(struct mm_struct *mm) | |||
| 2046 | unsigned long base = mm->brk; | 2201 | unsigned long base = mm->brk; |
| 2047 | unsigned long ret; | 2202 | unsigned long ret; |
| 2048 | 2203 | ||
| 2049 | #ifdef CONFIG_PPC_STD_MMU_64 | 2204 | #ifdef CONFIG_PPC_BOOK3S_64 |
| 2050 | /* | 2205 | /* |
| 2051 | * If we are using 1TB segments and we are allowed to randomise | 2206 | * If we are using 1TB segments and we are allowed to randomise |
| 2052 | * the heap, we can put it above 1TB so it is backed by a 1TB | 2207 | * the heap, we can put it above 1TB so it is backed by a 1TB |
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index f83056297441..b15bae265c90 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c | |||
| @@ -47,6 +47,7 @@ | |||
| 47 | #include <asm/mmu.h> | 47 | #include <asm/mmu.h> |
| 48 | #include <asm/paca.h> | 48 | #include <asm/paca.h> |
| 49 | #include <asm/pgtable.h> | 49 | #include <asm/pgtable.h> |
| 50 | #include <asm/powernv.h> | ||
| 50 | #include <asm/iommu.h> | 51 | #include <asm/iommu.h> |
| 51 | #include <asm/btext.h> | 52 | #include <asm/btext.h> |
| 52 | #include <asm/sections.h> | 53 | #include <asm/sections.h> |
| @@ -228,7 +229,7 @@ static void __init check_cpu_pa_features(unsigned long node) | |||
| 228 | ibm_pa_features, ARRAY_SIZE(ibm_pa_features)); | 229 | ibm_pa_features, ARRAY_SIZE(ibm_pa_features)); |
| 229 | } | 230 | } |
| 230 | 231 | ||
| 231 | #ifdef CONFIG_PPC_STD_MMU_64 | 232 | #ifdef CONFIG_PPC_BOOK3S_64 |
| 232 | static void __init init_mmu_slb_size(unsigned long node) | 233 | static void __init init_mmu_slb_size(unsigned long node) |
| 233 | { | 234 | { |
| 234 | const __be32 *slb_size_ptr; | 235 | const __be32 *slb_size_ptr; |
| @@ -658,6 +659,38 @@ static void __init early_reserve_mem(void) | |||
| 658 | #endif | 659 | #endif |
| 659 | } | 660 | } |
| 660 | 661 | ||
| 662 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | ||
| 663 | static bool tm_disabled __initdata; | ||
| 664 | |||
| 665 | static int __init parse_ppc_tm(char *str) | ||
| 666 | { | ||
| 667 | bool res; | ||
| 668 | |||
| 669 | if (kstrtobool(str, &res)) | ||
| 670 | return -EINVAL; | ||
| 671 | |||
| 672 | tm_disabled = !res; | ||
| 673 | |||
| 674 | return 0; | ||
| 675 | } | ||
| 676 | early_param("ppc_tm", parse_ppc_tm); | ||
| 677 | |||
| 678 | static void __init tm_init(void) | ||
| 679 | { | ||
| 680 | if (tm_disabled) { | ||
| 681 | pr_info("Disabling hardware transactional memory (HTM)\n"); | ||
| 682 | cur_cpu_spec->cpu_user_features2 &= | ||
| 683 | ~(PPC_FEATURE2_HTM_NOSC | PPC_FEATURE2_HTM); | ||
| 684 | cur_cpu_spec->cpu_features &= ~CPU_FTR_TM; | ||
| 685 | return; | ||
| 686 | } | ||
| 687 | |||
| 688 | pnv_tm_init(); | ||
| 689 | } | ||
| 690 | #else | ||
| 691 | static void tm_init(void) { } | ||
| 692 | #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */ | ||
| 693 | |||
| 661 | void __init early_init_devtree(void *params) | 694 | void __init early_init_devtree(void *params) |
| 662 | { | 695 | { |
| 663 | phys_addr_t limit; | 696 | phys_addr_t limit; |
| @@ -767,6 +800,8 @@ void __init early_init_devtree(void *params) | |||
| 767 | powerpc_firmware_features |= FW_FEATURE_PS3_POSSIBLE; | 800 | powerpc_firmware_features |= FW_FEATURE_PS3_POSSIBLE; |
| 768 | #endif | 801 | #endif |
| 769 | 802 | ||
| 803 | tm_init(); | ||
| 804 | |||
| 770 | DBG(" <- early_init_devtree()\n"); | 805 | DBG(" <- early_init_devtree()\n"); |
| 771 | } | 806 | } |
| 772 | 807 | ||
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index 2e3bc16d02b2..2075322cd225 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c | |||
| @@ -773,7 +773,7 @@ void arch_setup_pdev_archdata(struct platform_device *pdev) | |||
| 773 | static __init void print_system_info(void) | 773 | static __init void print_system_info(void) |
| 774 | { | 774 | { |
| 775 | pr_info("-----------------------------------------------------\n"); | 775 | pr_info("-----------------------------------------------------\n"); |
| 776 | #ifdef CONFIG_PPC_STD_MMU_64 | 776 | #ifdef CONFIG_PPC_BOOK3S_64 |
| 777 | pr_info("ppc64_pft_size = 0x%llx\n", ppc64_pft_size); | 777 | pr_info("ppc64_pft_size = 0x%llx\n", ppc64_pft_size); |
| 778 | #endif | 778 | #endif |
| 779 | #ifdef CONFIG_PPC_STD_MMU_32 | 779 | #ifdef CONFIG_PPC_STD_MMU_32 |
| @@ -800,7 +800,7 @@ static __init void print_system_info(void) | |||
| 800 | pr_info("firmware_features = 0x%016lx\n", powerpc_firmware_features); | 800 | pr_info("firmware_features = 0x%016lx\n", powerpc_firmware_features); |
| 801 | #endif | 801 | #endif |
| 802 | 802 | ||
| 803 | #ifdef CONFIG_PPC_STD_MMU_64 | 803 | #ifdef CONFIG_PPC_BOOK3S_64 |
| 804 | if (htab_address) | 804 | if (htab_address) |
| 805 | pr_info("htab_address = 0x%p\n", htab_address); | 805 | pr_info("htab_address = 0x%p\n", htab_address); |
| 806 | if (htab_hash_mask) | 806 | if (htab_hash_mask) |
| @@ -898,7 +898,8 @@ void __init setup_arch(char **cmdline_p) | |||
| 898 | 898 | ||
| 899 | #ifdef CONFIG_PPC_MM_SLICES | 899 | #ifdef CONFIG_PPC_MM_SLICES |
| 900 | #ifdef CONFIG_PPC64 | 900 | #ifdef CONFIG_PPC64 |
| 901 | init_mm.context.addr_limit = DEFAULT_MAP_WINDOW_USER64; | 901 | if (!radix_enabled()) |
| 902 | init_mm.context.slb_addr_limit = DEFAULT_MAP_WINDOW_USER64; | ||
| 902 | #else | 903 | #else |
| 903 | #error "context.addr_limit not initialized." | 904 | #error "context.addr_limit not initialized." |
| 904 | #endif | 905 | #endif |
diff --git a/arch/powerpc/kernel/setup.h b/arch/powerpc/kernel/setup.h index cfba134b3024..21c18071d9d5 100644 --- a/arch/powerpc/kernel/setup.h +++ b/arch/powerpc/kernel/setup.h | |||
| @@ -45,6 +45,12 @@ void emergency_stack_init(void); | |||
| 45 | static inline void emergency_stack_init(void) { }; | 45 | static inline void emergency_stack_init(void) { }; |
| 46 | #endif | 46 | #endif |
| 47 | 47 | ||
| 48 | #ifdef CONFIG_PPC64 | ||
| 49 | void record_spr_defaults(void); | ||
| 50 | #else | ||
| 51 | static inline void record_spr_defaults(void) { }; | ||
| 52 | #endif | ||
| 53 | |||
| 48 | /* | 54 | /* |
| 49 | * Having this in kvm_ppc.h makes include dependencies too | 55 | * Having this in kvm_ppc.h makes include dependencies too |
| 50 | * tricky to solve for setup-common.c so have it here. | 56 | * tricky to solve for setup-common.c so have it here. |
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index b89c6aac48c9..8956a9856604 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c | |||
| @@ -69,6 +69,8 @@ | |||
| 69 | #include <asm/opal.h> | 69 | #include <asm/opal.h> |
| 70 | #include <asm/cputhreads.h> | 70 | #include <asm/cputhreads.h> |
| 71 | 71 | ||
| 72 | #include "setup.h" | ||
| 73 | |||
| 72 | #ifdef DEBUG | 74 | #ifdef DEBUG |
| 73 | #define DBG(fmt...) udbg_printf(fmt) | 75 | #define DBG(fmt...) udbg_printf(fmt) |
| 74 | #else | 76 | #else |
| @@ -317,6 +319,13 @@ void __init early_setup(unsigned long dt_ptr) | |||
| 317 | early_init_mmu(); | 319 | early_init_mmu(); |
| 318 | 320 | ||
| 319 | /* | 321 | /* |
| 322 | * After firmware and early platform setup code has set things up, | ||
| 323 | * we note the SPR values for configurable control/performance | ||
| 324 | * registers, and use those as initial defaults. | ||
| 325 | */ | ||
| 326 | record_spr_defaults(); | ||
| 327 | |||
| 328 | /* | ||
| 320 | * At this point, we can let interrupts switch to virtual mode | 329 | * At this point, we can let interrupts switch to virtual mode |
| 321 | * (the MMU has been setup), so adjust the MSR in the PACA to | 330 | * (the MMU has been setup), so adjust the MSR in the PACA to |
| 322 | * have IR and DR set and enable AIL if it exists | 331 | * have IR and DR set and enable AIL if it exists |
| @@ -360,8 +369,16 @@ void early_setup_secondary(void) | |||
| 360 | #if defined(CONFIG_SMP) || defined(CONFIG_KEXEC_CORE) | 369 | #if defined(CONFIG_SMP) || defined(CONFIG_KEXEC_CORE) |
| 361 | static bool use_spinloop(void) | 370 | static bool use_spinloop(void) |
| 362 | { | 371 | { |
| 363 | if (!IS_ENABLED(CONFIG_PPC_BOOK3E)) | 372 | if (IS_ENABLED(CONFIG_PPC_BOOK3S)) { |
| 373 | /* | ||
| 374 | * See comments in head_64.S -- not all platforms insert | ||
| 375 | * secondaries at __secondary_hold and wait at the spin | ||
| 376 | * loop. | ||
| 377 | */ | ||
| 378 | if (firmware_has_feature(FW_FEATURE_OPAL)) | ||
| 379 | return false; | ||
| 364 | return true; | 380 | return true; |
| 381 | } | ||
| 365 | 382 | ||
| 366 | /* | 383 | /* |
| 367 | * When book3e boots from kexec, the ePAPR spin table does | 384 | * When book3e boots from kexec, the ePAPR spin table does |
diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c index e9436c5e1e09..3d7539b90010 100644 --- a/arch/powerpc/kernel/signal.c +++ b/arch/powerpc/kernel/signal.c | |||
| @@ -103,7 +103,7 @@ static void check_syscall_restart(struct pt_regs *regs, struct k_sigaction *ka, | |||
| 103 | static void do_signal(struct task_struct *tsk) | 103 | static void do_signal(struct task_struct *tsk) |
| 104 | { | 104 | { |
| 105 | sigset_t *oldset = sigmask_to_save(); | 105 | sigset_t *oldset = sigmask_to_save(); |
| 106 | struct ksignal ksig; | 106 | struct ksignal ksig = { .sig = 0 }; |
| 107 | int ret; | 107 | int ret; |
| 108 | int is32 = is_32bit_task(); | 108 | int is32 = is_32bit_task(); |
| 109 | 109 | ||
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index 92fb1c8dbbd8..16d16583cf11 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c | |||
| @@ -519,6 +519,8 @@ static int save_tm_user_regs(struct pt_regs *regs, | |||
| 519 | { | 519 | { |
| 520 | unsigned long msr = regs->msr; | 520 | unsigned long msr = regs->msr; |
| 521 | 521 | ||
| 522 | WARN_ON(tm_suspend_disabled); | ||
| 523 | |||
| 522 | /* Remove TM bits from thread's MSR. The MSR in the sigcontext | 524 | /* Remove TM bits from thread's MSR. The MSR in the sigcontext |
| 523 | * just indicates to userland that we were doing a transaction, but we | 525 | * just indicates to userland that we were doing a transaction, but we |
| 524 | * don't want to return in transactional state. This also ensures | 526 | * don't want to return in transactional state. This also ensures |
| @@ -769,6 +771,8 @@ static long restore_tm_user_regs(struct pt_regs *regs, | |||
| 769 | int i; | 771 | int i; |
| 770 | #endif | 772 | #endif |
| 771 | 773 | ||
| 774 | if (tm_suspend_disabled) | ||
| 775 | return 1; | ||
| 772 | /* | 776 | /* |
| 773 | * restore general registers but not including MSR or SOFTE. Also | 777 | * restore general registers but not including MSR or SOFTE. Also |
| 774 | * take care of keeping r2 (TLS) intact if not a signal. | 778 | * take care of keeping r2 (TLS) intact if not a signal. |
| @@ -876,7 +880,7 @@ static long restore_tm_user_regs(struct pt_regs *regs, | |||
| 876 | /* Make sure the transaction is marked as failed */ | 880 | /* Make sure the transaction is marked as failed */ |
| 877 | current->thread.tm_texasr |= TEXASR_FS; | 881 | current->thread.tm_texasr |= TEXASR_FS; |
| 878 | /* This loads the checkpointed FP/VEC state, if used */ | 882 | /* This loads the checkpointed FP/VEC state, if used */ |
| 879 | tm_recheckpoint(¤t->thread, msr); | 883 | tm_recheckpoint(¤t->thread); |
| 880 | 884 | ||
| 881 | /* This loads the speculative FP/VEC state, if used */ | 885 | /* This loads the speculative FP/VEC state, if used */ |
| 882 | msr_check_and_set(msr & (MSR_FP | MSR_VEC)); | 886 | msr_check_and_set(msr & (MSR_FP | MSR_VEC)); |
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c index b2c002993d78..4b9ca3570344 100644 --- a/arch/powerpc/kernel/signal_64.c +++ b/arch/powerpc/kernel/signal_64.c | |||
| @@ -214,6 +214,8 @@ static long setup_tm_sigcontexts(struct sigcontext __user *sc, | |||
| 214 | 214 | ||
| 215 | BUG_ON(!MSR_TM_ACTIVE(regs->msr)); | 215 | BUG_ON(!MSR_TM_ACTIVE(regs->msr)); |
| 216 | 216 | ||
| 217 | WARN_ON(tm_suspend_disabled); | ||
| 218 | |||
| 217 | /* Remove TM bits from thread's MSR. The MSR in the sigcontext | 219 | /* Remove TM bits from thread's MSR. The MSR in the sigcontext |
| 218 | * just indicates to userland that we were doing a transaction, but we | 220 | * just indicates to userland that we were doing a transaction, but we |
| 219 | * don't want to return in transactional state. This also ensures | 221 | * don't want to return in transactional state. This also ensures |
| @@ -430,6 +432,9 @@ static long restore_tm_sigcontexts(struct task_struct *tsk, | |||
| 430 | 432 | ||
| 431 | BUG_ON(tsk != current); | 433 | BUG_ON(tsk != current); |
| 432 | 434 | ||
| 435 | if (tm_suspend_disabled) | ||
| 436 | return -EINVAL; | ||
| 437 | |||
| 433 | /* copy the GPRs */ | 438 | /* copy the GPRs */ |
| 434 | err |= __copy_from_user(regs->gpr, tm_sc->gp_regs, sizeof(regs->gpr)); | 439 | err |= __copy_from_user(regs->gpr, tm_sc->gp_regs, sizeof(regs->gpr)); |
| 435 | err |= __copy_from_user(&tsk->thread.ckpt_regs, sc->gp_regs, | 440 | err |= __copy_from_user(&tsk->thread.ckpt_regs, sc->gp_regs, |
| @@ -558,7 +563,7 @@ static long restore_tm_sigcontexts(struct task_struct *tsk, | |||
| 558 | /* Make sure the transaction is marked as failed */ | 563 | /* Make sure the transaction is marked as failed */ |
| 559 | tsk->thread.tm_texasr |= TEXASR_FS; | 564 | tsk->thread.tm_texasr |= TEXASR_FS; |
| 560 | /* This loads the checkpointed FP/VEC state, if used */ | 565 | /* This loads the checkpointed FP/VEC state, if used */ |
| 561 | tm_recheckpoint(&tsk->thread, msr); | 566 | tm_recheckpoint(&tsk->thread); |
| 562 | 567 | ||
| 563 | msr_check_and_set(msr & (MSR_FP | MSR_VEC)); | 568 | msr_check_and_set(msr & (MSR_FP | MSR_VEC)); |
| 564 | if (msr & MSR_FP) { | 569 | if (msr & MSR_FP) { |
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c index 4437c70c7c2b..b8d4a1dac39f 100644 --- a/arch/powerpc/kernel/sysfs.c +++ b/arch/powerpc/kernel/sysfs.c | |||
| @@ -590,6 +590,17 @@ static void sysfs_create_dscr_default(void) | |||
| 590 | if (cpu_has_feature(CPU_FTR_DSCR)) | 590 | if (cpu_has_feature(CPU_FTR_DSCR)) |
| 591 | err = device_create_file(cpu_subsys.dev_root, &dev_attr_dscr_default); | 591 | err = device_create_file(cpu_subsys.dev_root, &dev_attr_dscr_default); |
| 592 | } | 592 | } |
| 593 | |||
| 594 | void __init record_spr_defaults(void) | ||
| 595 | { | ||
| 596 | int cpu; | ||
| 597 | |||
| 598 | if (cpu_has_feature(CPU_FTR_DSCR)) { | ||
| 599 | dscr_default = mfspr(SPRN_DSCR); | ||
| 600 | for (cpu = 0; cpu < nr_cpu_ids; cpu++) | ||
| 601 | paca[cpu].dscr_default = dscr_default; | ||
| 602 | } | ||
| 603 | } | ||
| 593 | #endif /* CONFIG_PPC64 */ | 604 | #endif /* CONFIG_PPC64 */ |
| 594 | 605 | ||
| 595 | #ifdef HAS_PPC_PMC_PA6T | 606 | #ifdef HAS_PPC_PMC_PA6T |
diff --git a/arch/powerpc/kernel/tau_6xx.c b/arch/powerpc/kernel/tau_6xx.c index a3374e8a258c..e3c5f75d137c 100644 --- a/arch/powerpc/kernel/tau_6xx.c +++ b/arch/powerpc/kernel/tau_6xx.c | |||
| @@ -230,8 +230,7 @@ int __init TAU_init(void) | |||
| 230 | 230 | ||
| 231 | 231 | ||
| 232 | /* first, set up the window shrinking timer */ | 232 | /* first, set up the window shrinking timer */ |
| 233 | init_timer(&tau_timer); | 233 | setup_timer(&tau_timer, tau_timeout_smp, 0UL); |
| 234 | tau_timer.function = tau_timeout_smp; | ||
| 235 | tau_timer.expires = jiffies + shrink_timer; | 234 | tau_timer.expires = jiffies + shrink_timer; |
| 236 | add_timer(&tau_timer); | 235 | add_timer(&tau_timer); |
| 237 | 236 | ||
diff --git a/arch/powerpc/kernel/tm.S b/arch/powerpc/kernel/tm.S index 1da12f521cb7..b92ac8e711db 100644 --- a/arch/powerpc/kernel/tm.S +++ b/arch/powerpc/kernel/tm.S | |||
| @@ -80,15 +80,12 @@ _GLOBAL(tm_abort) | |||
| 80 | blr | 80 | blr |
| 81 | 81 | ||
| 82 | /* void tm_reclaim(struct thread_struct *thread, | 82 | /* void tm_reclaim(struct thread_struct *thread, |
| 83 | * unsigned long orig_msr, | ||
| 84 | * uint8_t cause) | 83 | * uint8_t cause) |
| 85 | * | 84 | * |
| 86 | * - Performs a full reclaim. This destroys outstanding | 85 | * - Performs a full reclaim. This destroys outstanding |
| 87 | * transactions and updates thread->regs.tm_ckpt_* with the | 86 | * transactions and updates thread->regs.tm_ckpt_* with the |
| 88 | * original checkpointed state. Note that thread->regs is | 87 | * original checkpointed state. Note that thread->regs is |
| 89 | * unchanged. | 88 | * unchanged. |
| 90 | * - FP regs are written back to thread->transact_fpr before | ||
| 91 | * reclaiming. These are the transactional (current) versions. | ||
| 92 | * | 89 | * |
| 93 | * Purpose is to both abort transactions of, and preserve the state of, | 90 | * Purpose is to both abort transactions of, and preserve the state of, |
| 94 | * a transactions at a context switch. We preserve/restore both sets of process | 91 | * a transactions at a context switch. We preserve/restore both sets of process |
| @@ -99,9 +96,9 @@ _GLOBAL(tm_abort) | |||
| 99 | * Call with IRQs off, stacks get all out of sync for some periods in here! | 96 | * Call with IRQs off, stacks get all out of sync for some periods in here! |
| 100 | */ | 97 | */ |
| 101 | _GLOBAL(tm_reclaim) | 98 | _GLOBAL(tm_reclaim) |
| 102 | mfcr r6 | 99 | mfcr r5 |
| 103 | mflr r0 | 100 | mflr r0 |
| 104 | stw r6, 8(r1) | 101 | stw r5, 8(r1) |
| 105 | std r0, 16(r1) | 102 | std r0, 16(r1) |
| 106 | std r2, STK_GOT(r1) | 103 | std r2, STK_GOT(r1) |
| 107 | stdu r1, -TM_FRAME_SIZE(r1) | 104 | stdu r1, -TM_FRAME_SIZE(r1) |
| @@ -109,7 +106,6 @@ _GLOBAL(tm_reclaim) | |||
| 109 | /* We've a struct pt_regs at [r1+STACK_FRAME_OVERHEAD]. */ | 106 | /* We've a struct pt_regs at [r1+STACK_FRAME_OVERHEAD]. */ |
| 110 | 107 | ||
| 111 | std r3, STK_PARAM(R3)(r1) | 108 | std r3, STK_PARAM(R3)(r1) |
| 112 | std r4, STK_PARAM(R4)(r1) | ||
| 113 | SAVE_NVGPRS(r1) | 109 | SAVE_NVGPRS(r1) |
| 114 | 110 | ||
| 115 | /* We need to setup MSR for VSX register save instructions. */ | 111 | /* We need to setup MSR for VSX register save instructions. */ |
| @@ -139,8 +135,8 @@ _GLOBAL(tm_reclaim) | |||
| 139 | std r1, PACAR1(r13) | 135 | std r1, PACAR1(r13) |
| 140 | 136 | ||
| 141 | /* Clear MSR RI since we are about to change r1, EE is already off. */ | 137 | /* Clear MSR RI since we are about to change r1, EE is already off. */ |
| 142 | li r4, 0 | 138 | li r5, 0 |
| 143 | mtmsrd r4, 1 | 139 | mtmsrd r5, 1 |
| 144 | 140 | ||
| 145 | /* | 141 | /* |
| 146 | * BE CAREFUL HERE: | 142 | * BE CAREFUL HERE: |
| @@ -152,7 +148,7 @@ _GLOBAL(tm_reclaim) | |||
| 152 | * to user register state. (FPRs, CCR etc. also!) | 148 | * to user register state. (FPRs, CCR etc. also!) |
| 153 | * Use an sprg and a tm_scratch in the PACA to shuffle. | 149 | * Use an sprg and a tm_scratch in the PACA to shuffle. |
| 154 | */ | 150 | */ |
| 155 | TRECLAIM(R5) /* Cause in r5 */ | 151 | TRECLAIM(R4) /* Cause in r4 */ |
| 156 | 152 | ||
| 157 | /* ******************** GPRs ******************** */ | 153 | /* ******************** GPRs ******************** */ |
| 158 | /* Stash the checkpointed r13 away in the scratch SPR and get the real | 154 | /* Stash the checkpointed r13 away in the scratch SPR and get the real |
| @@ -243,40 +239,30 @@ _GLOBAL(tm_reclaim) | |||
| 243 | 239 | ||
| 244 | 240 | ||
| 245 | /* ******************** FPR/VR/VSRs ************ | 241 | /* ******************** FPR/VR/VSRs ************ |
| 246 | * After reclaiming, capture the checkpointed FPRs/VRs /if used/. | 242 | * After reclaiming, capture the checkpointed FPRs/VRs. |
| 247 | * | ||
| 248 | * (If VSX used, FP and VMX are implied. Or, we don't need to look | ||
| 249 | * at MSR.VSX as copying FP regs if .FP, vector regs if .VMX covers it.) | ||
| 250 | * | ||
| 251 | * We're passed the thread's MSR as the second parameter | ||
| 252 | * | 243 | * |
| 253 | * We enabled VEC/FP/VSX in the msr above, so we can execute these | 244 | * We enabled VEC/FP/VSX in the msr above, so we can execute these |
| 254 | * instructions! | 245 | * instructions! |
| 255 | */ | 246 | */ |
| 256 | ld r4, STK_PARAM(R4)(r1) /* Second parameter, MSR * */ | ||
| 257 | mr r3, r12 | 247 | mr r3, r12 |
| 258 | andis. r0, r4, MSR_VEC@h | ||
| 259 | beq dont_backup_vec | ||
| 260 | 248 | ||
| 249 | /* Altivec (VEC/VMX/VR)*/ | ||
| 261 | addi r7, r3, THREAD_CKVRSTATE | 250 | addi r7, r3, THREAD_CKVRSTATE |
| 262 | SAVE_32VRS(0, r6, r7) /* r6 scratch, r7 transact vr state */ | 251 | SAVE_32VRS(0, r6, r7) /* r6 scratch, r7 transact vr state */ |
| 263 | mfvscr v0 | 252 | mfvscr v0 |
| 264 | li r6, VRSTATE_VSCR | 253 | li r6, VRSTATE_VSCR |
| 265 | stvx v0, r7, r6 | 254 | stvx v0, r7, r6 |
| 266 | dont_backup_vec: | 255 | |
| 256 | /* VRSAVE */ | ||
| 267 | mfspr r0, SPRN_VRSAVE | 257 | mfspr r0, SPRN_VRSAVE |
| 268 | std r0, THREAD_CKVRSAVE(r3) | 258 | std r0, THREAD_CKVRSAVE(r3) |
| 269 | 259 | ||
| 270 | andi. r0, r4, MSR_FP | 260 | /* Floating Point (FP) */ |
| 271 | beq dont_backup_fp | ||
| 272 | |||
| 273 | addi r7, r3, THREAD_CKFPSTATE | 261 | addi r7, r3, THREAD_CKFPSTATE |
| 274 | SAVE_32FPRS_VSRS(0, R6, R7) /* r6 scratch, r7 transact fp state */ | 262 | SAVE_32FPRS_VSRS(0, R6, R7) /* r6 scratch, r7 transact fp state */ |
| 275 | |||
| 276 | mffs fr0 | 263 | mffs fr0 |
| 277 | stfd fr0,FPSTATE_FPSCR(r7) | 264 | stfd fr0,FPSTATE_FPSCR(r7) |
| 278 | 265 | ||
| 279 | dont_backup_fp: | ||
| 280 | 266 | ||
| 281 | /* TM regs, incl TEXASR -- these live in thread_struct. Note they've | 267 | /* TM regs, incl TEXASR -- these live in thread_struct. Note they've |
| 282 | * been updated by the treclaim, to explain to userland the failure | 268 | * been updated by the treclaim, to explain to userland the failure |
| @@ -344,22 +330,19 @@ _GLOBAL(__tm_recheckpoint) | |||
| 344 | */ | 330 | */ |
| 345 | subi r7, r7, STACK_FRAME_OVERHEAD | 331 | subi r7, r7, STACK_FRAME_OVERHEAD |
| 346 | 332 | ||
| 333 | /* We need to setup MSR for FP/VMX/VSX register save instructions. */ | ||
| 347 | mfmsr r6 | 334 | mfmsr r6 |
| 348 | /* R4 = original MSR to indicate whether thread used FP/Vector etc. */ | 335 | mr r5, r6 |
| 349 | |||
| 350 | /* Enable FP/vec in MSR if necessary! */ | ||
| 351 | lis r5, MSR_VEC@h | ||
| 352 | ori r5, r5, MSR_FP | 336 | ori r5, r5, MSR_FP |
| 353 | and. r5, r4, r5 | 337 | #ifdef CONFIG_ALTIVEC |
| 354 | beq restore_gprs /* if neither, skip both */ | 338 | oris r5, r5, MSR_VEC@h |
| 355 | 339 | #endif | |
| 356 | #ifdef CONFIG_VSX | 340 | #ifdef CONFIG_VSX |
| 357 | BEGIN_FTR_SECTION | 341 | BEGIN_FTR_SECTION |
| 358 | oris r5, r5, MSR_VSX@h | 342 | oris r5,r5, MSR_VSX@h |
| 359 | END_FTR_SECTION_IFSET(CPU_FTR_VSX) | 343 | END_FTR_SECTION_IFSET(CPU_FTR_VSX) |
| 360 | #endif | 344 | #endif |
| 361 | or r5, r6, r5 /* Set MSR.FP+.VSX/.VEC */ | 345 | mtmsrd r5 |
| 362 | mtmsr r5 | ||
| 363 | 346 | ||
| 364 | #ifdef CONFIG_ALTIVEC | 347 | #ifdef CONFIG_ALTIVEC |
| 365 | /* | 348 | /* |
| @@ -368,28 +351,20 @@ _GLOBAL(__tm_recheckpoint) | |||
| 368 | * thread.fp_state[] version holds the 'live' (transactional) | 351 | * thread.fp_state[] version holds the 'live' (transactional) |
| 369 | * and will be loaded subsequently by any FPUnavailable trap. | 352 | * and will be loaded subsequently by any FPUnavailable trap. |
| 370 | */ | 353 | */ |
| 371 | andis. r0, r4, MSR_VEC@h | ||
| 372 | beq dont_restore_vec | ||
| 373 | |||
| 374 | addi r8, r3, THREAD_CKVRSTATE | 354 | addi r8, r3, THREAD_CKVRSTATE |
| 375 | li r5, VRSTATE_VSCR | 355 | li r5, VRSTATE_VSCR |
| 376 | lvx v0, r8, r5 | 356 | lvx v0, r8, r5 |
| 377 | mtvscr v0 | 357 | mtvscr v0 |
| 378 | REST_32VRS(0, r5, r8) /* r5 scratch, r8 ptr */ | 358 | REST_32VRS(0, r5, r8) /* r5 scratch, r8 ptr */ |
| 379 | dont_restore_vec: | ||
| 380 | ld r5, THREAD_CKVRSAVE(r3) | 359 | ld r5, THREAD_CKVRSAVE(r3) |
| 381 | mtspr SPRN_VRSAVE, r5 | 360 | mtspr SPRN_VRSAVE, r5 |
| 382 | #endif | 361 | #endif |
| 383 | 362 | ||
| 384 | andi. r0, r4, MSR_FP | ||
| 385 | beq dont_restore_fp | ||
| 386 | |||
| 387 | addi r8, r3, THREAD_CKFPSTATE | 363 | addi r8, r3, THREAD_CKFPSTATE |
| 388 | lfd fr0, FPSTATE_FPSCR(r8) | 364 | lfd fr0, FPSTATE_FPSCR(r8) |
| 389 | MTFSF_L(fr0) | 365 | MTFSF_L(fr0) |
| 390 | REST_32FPRS_VSRS(0, R4, R8) | 366 | REST_32FPRS_VSRS(0, R4, R8) |
| 391 | 367 | ||
| 392 | dont_restore_fp: | ||
| 393 | mtmsr r6 /* FP/Vec off again! */ | 368 | mtmsr r6 /* FP/Vec off again! */ |
| 394 | 369 | ||
| 395 | restore_gprs: | 370 | restore_gprs: |
diff --git a/arch/powerpc/kernel/trace/ftrace_64_mprofile.S b/arch/powerpc/kernel/trace/ftrace_64_mprofile.S index b4e2b7165f79..3f3e81852422 100644 --- a/arch/powerpc/kernel/trace/ftrace_64_mprofile.S +++ b/arch/powerpc/kernel/trace/ftrace_64_mprofile.S | |||
| @@ -110,9 +110,9 @@ ftrace_call: | |||
| 110 | /* NIP has not been altered, skip over further checks */ | 110 | /* NIP has not been altered, skip over further checks */ |
| 111 | beq 1f | 111 | beq 1f |
| 112 | 112 | ||
| 113 | /* Check if there is an active kprobe on us */ | 113 | /* Check if there is an active jprobe on us */ |
| 114 | subi r3, r14, 4 | 114 | subi r3, r14, 4 |
| 115 | bl is_current_kprobe_addr | 115 | bl __is_active_jprobe |
| 116 | nop | 116 | nop |
| 117 | 117 | ||
| 118 | /* | 118 | /* |
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 13c9dcdcba69..f3eb61be0d30 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c | |||
| @@ -37,6 +37,7 @@ | |||
| 37 | #include <linux/kdebug.h> | 37 | #include <linux/kdebug.h> |
| 38 | #include <linux/ratelimit.h> | 38 | #include <linux/ratelimit.h> |
| 39 | #include <linux/context_tracking.h> | 39 | #include <linux/context_tracking.h> |
| 40 | #include <linux/smp.h> | ||
| 40 | 41 | ||
| 41 | #include <asm/emulated_ops.h> | 42 | #include <asm/emulated_ops.h> |
| 42 | #include <asm/pgtable.h> | 43 | #include <asm/pgtable.h> |
| @@ -699,6 +700,187 @@ void SMIException(struct pt_regs *regs) | |||
| 699 | die("System Management Interrupt", regs, SIGABRT); | 700 | die("System Management Interrupt", regs, SIGABRT); |
| 700 | } | 701 | } |
| 701 | 702 | ||
| 703 | #ifdef CONFIG_VSX | ||
| 704 | static void p9_hmi_special_emu(struct pt_regs *regs) | ||
| 705 | { | ||
| 706 | unsigned int ra, rb, t, i, sel, instr, rc; | ||
| 707 | const void __user *addr; | ||
| 708 | u8 vbuf[16], *vdst; | ||
| 709 | unsigned long ea, msr, msr_mask; | ||
| 710 | bool swap; | ||
| 711 | |||
| 712 | if (__get_user_inatomic(instr, (unsigned int __user *)regs->nip)) | ||
| 713 | return; | ||
| 714 | |||
| 715 | /* | ||
| 716 | * lxvb16x opcode: 0x7c0006d8 | ||
| 717 | * lxvd2x opcode: 0x7c000698 | ||
| 718 | * lxvh8x opcode: 0x7c000658 | ||
| 719 | * lxvw4x opcode: 0x7c000618 | ||
| 720 | */ | ||
| 721 | if ((instr & 0xfc00073e) != 0x7c000618) { | ||
| 722 | pr_devel("HMI vec emu: not vector CI %i:%s[%d] nip=%016lx" | ||
| 723 | " instr=%08x\n", | ||
| 724 | smp_processor_id(), current->comm, current->pid, | ||
| 725 | regs->nip, instr); | ||
| 726 | return; | ||
| 727 | } | ||
| 728 | |||
| 729 | /* Grab vector registers into the task struct */ | ||
| 730 | msr = regs->msr; /* Grab msr before we flush the bits */ | ||
| 731 | flush_vsx_to_thread(current); | ||
| 732 | enable_kernel_altivec(); | ||
| 733 | |||
| 734 | /* | ||
| 735 | * Is userspace running with a different endian (this is rare but | ||
| 736 | * not impossible) | ||
| 737 | */ | ||
| 738 | swap = (msr & MSR_LE) != (MSR_KERNEL & MSR_LE); | ||
| 739 | |||
| 740 | /* Decode the instruction */ | ||
| 741 | ra = (instr >> 16) & 0x1f; | ||
| 742 | rb = (instr >> 11) & 0x1f; | ||
| 743 | t = (instr >> 21) & 0x1f; | ||
| 744 | if (instr & 1) | ||
| 745 | vdst = (u8 *)¤t->thread.vr_state.vr[t]; | ||
| 746 | else | ||
| 747 | vdst = (u8 *)¤t->thread.fp_state.fpr[t][0]; | ||
| 748 | |||
| 749 | /* Grab the vector address */ | ||
| 750 | ea = regs->gpr[rb] + (ra ? regs->gpr[ra] : 0); | ||
| 751 | if (is_32bit_task()) | ||
| 752 | ea &= 0xfffffffful; | ||
| 753 | addr = (__force const void __user *)ea; | ||
| 754 | |||
| 755 | /* Check it */ | ||
| 756 | if (!access_ok(VERIFY_READ, addr, 16)) { | ||
| 757 | pr_devel("HMI vec emu: bad access %i:%s[%d] nip=%016lx" | ||
| 758 | " instr=%08x addr=%016lx\n", | ||
| 759 | smp_processor_id(), current->comm, current->pid, | ||
| 760 | regs->nip, instr, (unsigned long)addr); | ||
| 761 | return; | ||
| 762 | } | ||
| 763 | |||
| 764 | /* Read the vector */ | ||
| 765 | rc = 0; | ||
| 766 | if ((unsigned long)addr & 0xfUL) | ||
| 767 | /* unaligned case */ | ||
| 768 | rc = __copy_from_user_inatomic(vbuf, addr, 16); | ||
| 769 | else | ||
| 770 | __get_user_atomic_128_aligned(vbuf, addr, rc); | ||
| 771 | if (rc) { | ||
| 772 | pr_devel("HMI vec emu: page fault %i:%s[%d] nip=%016lx" | ||
| 773 | " instr=%08x addr=%016lx\n", | ||
| 774 | smp_processor_id(), current->comm, current->pid, | ||
| 775 | regs->nip, instr, (unsigned long)addr); | ||
| 776 | return; | ||
| 777 | } | ||
| 778 | |||
| 779 | pr_devel("HMI vec emu: emulated vector CI %i:%s[%d] nip=%016lx" | ||
| 780 | " instr=%08x addr=%016lx\n", | ||
| 781 | smp_processor_id(), current->comm, current->pid, regs->nip, | ||
| 782 | instr, (unsigned long) addr); | ||
| 783 | |||
| 784 | /* Grab instruction "selector" */ | ||
| 785 | sel = (instr >> 6) & 3; | ||
| 786 | |||
| 787 | /* | ||
| 788 | * Check to make sure the facility is actually enabled. This | ||
| 789 | * could happen if we get a false positive hit. | ||
| 790 | * | ||
| 791 | * lxvd2x/lxvw4x always check MSR VSX sel = 0,2 | ||
| 792 | * lxvh8x/lxvb16x check MSR VSX or VEC depending on VSR used sel = 1,3 | ||
| 793 | */ | ||
| 794 | msr_mask = MSR_VSX; | ||
| 795 | if ((sel & 1) && (instr & 1)) /* lxvh8x & lxvb16x + VSR >= 32 */ | ||
| 796 | msr_mask = MSR_VEC; | ||
| 797 | if (!(msr & msr_mask)) { | ||
| 798 | pr_devel("HMI vec emu: MSR fac clear %i:%s[%d] nip=%016lx" | ||
| 799 | " instr=%08x msr:%016lx\n", | ||
| 800 | smp_processor_id(), current->comm, current->pid, | ||
| 801 | regs->nip, instr, msr); | ||
| 802 | return; | ||
| 803 | } | ||
| 804 | |||
| 805 | /* Do logging here before we modify sel based on endian */ | ||
| 806 | switch (sel) { | ||
| 807 | case 0: /* lxvw4x */ | ||
| 808 | PPC_WARN_EMULATED(lxvw4x, regs); | ||
| 809 | break; | ||
| 810 | case 1: /* lxvh8x */ | ||
| 811 | PPC_WARN_EMULATED(lxvh8x, regs); | ||
| 812 | break; | ||
| 813 | case 2: /* lxvd2x */ | ||
| 814 | PPC_WARN_EMULATED(lxvd2x, regs); | ||
| 815 | break; | ||
| 816 | case 3: /* lxvb16x */ | ||
| 817 | PPC_WARN_EMULATED(lxvb16x, regs); | ||
| 818 | break; | ||
| 819 | } | ||
| 820 | |||
| 821 | #ifdef __LITTLE_ENDIAN__ | ||
| 822 | /* | ||
| 823 | * An LE kernel stores the vector in the task struct as an LE | ||
| 824 | * byte array (effectively swapping both the components and | ||
| 825 | * the content of the components). Those instructions expect | ||
| 826 | * the components to remain in ascending address order, so we | ||
| 827 | * swap them back. | ||
| 828 | * | ||
| 829 | * If we are running a BE user space, the expectation is that | ||
| 830 | * of a simple memcpy, so forcing the emulation to look like | ||
| 831 | * a lxvb16x should do the trick. | ||
| 832 | */ | ||
| 833 | if (swap) | ||
| 834 | sel = 3; | ||
| 835 | |||
| 836 | switch (sel) { | ||
| 837 | case 0: /* lxvw4x */ | ||
| 838 | for (i = 0; i < 4; i++) | ||
| 839 | ((u32 *)vdst)[i] = ((u32 *)vbuf)[3-i]; | ||
| 840 | break; | ||
| 841 | case 1: /* lxvh8x */ | ||
| 842 | for (i = 0; i < 8; i++) | ||
| 843 | ((u16 *)vdst)[i] = ((u16 *)vbuf)[7-i]; | ||
| 844 | break; | ||
| 845 | case 2: /* lxvd2x */ | ||
| 846 | for (i = 0; i < 2; i++) | ||
| 847 | ((u64 *)vdst)[i] = ((u64 *)vbuf)[1-i]; | ||
| 848 | break; | ||
| 849 | case 3: /* lxvb16x */ | ||
| 850 | for (i = 0; i < 16; i++) | ||
| 851 | vdst[i] = vbuf[15-i]; | ||
| 852 | break; | ||
| 853 | } | ||
| 854 | #else /* __LITTLE_ENDIAN__ */ | ||
| 855 | /* On a big endian kernel, a BE userspace only needs a memcpy */ | ||
| 856 | if (!swap) | ||
| 857 | sel = 3; | ||
| 858 | |||
| 859 | /* Otherwise, we need to swap the content of the components */ | ||
| 860 | switch (sel) { | ||
| 861 | case 0: /* lxvw4x */ | ||
| 862 | for (i = 0; i < 4; i++) | ||
| 863 | ((u32 *)vdst)[i] = cpu_to_le32(((u32 *)vbuf)[i]); | ||
| 864 | break; | ||
| 865 | case 1: /* lxvh8x */ | ||
| 866 | for (i = 0; i < 8; i++) | ||
| 867 | ((u16 *)vdst)[i] = cpu_to_le16(((u16 *)vbuf)[i]); | ||
| 868 | break; | ||
| 869 | case 2: /* lxvd2x */ | ||
| 870 | for (i = 0; i < 2; i++) | ||
| 871 | ((u64 *)vdst)[i] = cpu_to_le64(((u64 *)vbuf)[i]); | ||
| 872 | break; | ||
| 873 | case 3: /* lxvb16x */ | ||
| 874 | memcpy(vdst, vbuf, 16); | ||
| 875 | break; | ||
| 876 | } | ||
| 877 | #endif /* !__LITTLE_ENDIAN__ */ | ||
| 878 | |||
| 879 | /* Go to next instruction */ | ||
| 880 | regs->nip += 4; | ||
| 881 | } | ||
| 882 | #endif /* CONFIG_VSX */ | ||
| 883 | |||
| 702 | void handle_hmi_exception(struct pt_regs *regs) | 884 | void handle_hmi_exception(struct pt_regs *regs) |
| 703 | { | 885 | { |
| 704 | struct pt_regs *old_regs; | 886 | struct pt_regs *old_regs; |
| @@ -706,6 +888,21 @@ void handle_hmi_exception(struct pt_regs *regs) | |||
| 706 | old_regs = set_irq_regs(regs); | 888 | old_regs = set_irq_regs(regs); |
| 707 | irq_enter(); | 889 | irq_enter(); |
| 708 | 890 | ||
| 891 | #ifdef CONFIG_VSX | ||
| 892 | /* Real mode flagged P9 special emu is needed */ | ||
| 893 | if (local_paca->hmi_p9_special_emu) { | ||
| 894 | local_paca->hmi_p9_special_emu = 0; | ||
| 895 | |||
| 896 | /* | ||
| 897 | * We don't want to take page faults while doing the | ||
| 898 | * emulation, we just replay the instruction if necessary. | ||
| 899 | */ | ||
| 900 | pagefault_disable(); | ||
| 901 | p9_hmi_special_emu(regs); | ||
| 902 | pagefault_enable(); | ||
| 903 | } | ||
| 904 | #endif /* CONFIG_VSX */ | ||
| 905 | |||
| 709 | if (ppc_md.handle_hmi_exception) | 906 | if (ppc_md.handle_hmi_exception) |
| 710 | ppc_md.handle_hmi_exception(regs); | 907 | ppc_md.handle_hmi_exception(regs); |
| 711 | 908 | ||
| @@ -1140,13 +1337,8 @@ void program_check_exception(struct pt_regs *regs) | |||
| 1140 | * - A treclaim is attempted when non transactional. | 1337 | * - A treclaim is attempted when non transactional. |
| 1141 | * - A tend is illegally attempted. | 1338 | * - A tend is illegally attempted. |
| 1142 | * - writing a TM SPR when transactional. | 1339 | * - writing a TM SPR when transactional. |
| 1143 | */ | 1340 | * |
| 1144 | if (!user_mode(regs) && | 1341 | * If usermode caused this, it's done something illegal and |
| 1145 | report_bug(regs->nip, regs) == BUG_TRAP_TYPE_WARN) { | ||
| 1146 | regs->nip += 4; | ||
| 1147 | goto bail; | ||
| 1148 | } | ||
| 1149 | /* If usermode caused this, it's done something illegal and | ||
| 1150 | * gets a SIGILL slap on the wrist. We call it an illegal | 1342 | * gets a SIGILL slap on the wrist. We call it an illegal |
| 1151 | * operand to distinguish from the instruction just being bad | 1343 | * operand to distinguish from the instruction just being bad |
| 1152 | * (e.g. executing a 'tend' on a CPU without TM!); it's an | 1344 | * (e.g. executing a 'tend' on a CPU without TM!); it's an |
| @@ -1487,7 +1679,7 @@ void fp_unavailable_tm(struct pt_regs *regs) | |||
| 1487 | /* Reclaim didn't save out any FPRs to transact_fprs. */ | 1679 | /* Reclaim didn't save out any FPRs to transact_fprs. */ |
| 1488 | 1680 | ||
| 1489 | /* Enable FP for the task: */ | 1681 | /* Enable FP for the task: */ |
| 1490 | regs->msr |= (MSR_FP | current->thread.fpexc_mode); | 1682 | current->thread.load_fp = 1; |
| 1491 | 1683 | ||
| 1492 | /* This loads and recheckpoints the FP registers from | 1684 | /* This loads and recheckpoints the FP registers from |
| 1493 | * thread.fpr[]. They will remain in registers after the | 1685 | * thread.fpr[]. They will remain in registers after the |
| @@ -1495,15 +1687,7 @@ void fp_unavailable_tm(struct pt_regs *regs) | |||
| 1495 | * If VMX is in use, the VRs now hold checkpointed values, | 1687 | * If VMX is in use, the VRs now hold checkpointed values, |
| 1496 | * so we don't want to load the VRs from the thread_struct. | 1688 | * so we don't want to load the VRs from the thread_struct. |
| 1497 | */ | 1689 | */ |
| 1498 | tm_recheckpoint(¤t->thread, MSR_FP); | 1690 | tm_recheckpoint(¤t->thread); |
| 1499 | |||
| 1500 | /* If VMX is in use, get the transactional values back */ | ||
| 1501 | if (regs->msr & MSR_VEC) { | ||
| 1502 | msr_check_and_set(MSR_VEC); | ||
| 1503 | load_vr_state(¤t->thread.vr_state); | ||
| 1504 | /* At this point all the VSX state is loaded, so enable it */ | ||
| 1505 | regs->msr |= MSR_VSX; | ||
| 1506 | } | ||
| 1507 | } | 1691 | } |
| 1508 | 1692 | ||
| 1509 | void altivec_unavailable_tm(struct pt_regs *regs) | 1693 | void altivec_unavailable_tm(struct pt_regs *regs) |
| @@ -1516,21 +1700,13 @@ void altivec_unavailable_tm(struct pt_regs *regs) | |||
| 1516 | "MSR=%lx\n", | 1700 | "MSR=%lx\n", |
| 1517 | regs->nip, regs->msr); | 1701 | regs->nip, regs->msr); |
| 1518 | tm_reclaim_current(TM_CAUSE_FAC_UNAV); | 1702 | tm_reclaim_current(TM_CAUSE_FAC_UNAV); |
| 1519 | regs->msr |= MSR_VEC; | 1703 | current->thread.load_vec = 1; |
| 1520 | tm_recheckpoint(¤t->thread, MSR_VEC); | 1704 | tm_recheckpoint(¤t->thread); |
| 1521 | current->thread.used_vr = 1; | 1705 | current->thread.used_vr = 1; |
| 1522 | |||
| 1523 | if (regs->msr & MSR_FP) { | ||
| 1524 | msr_check_and_set(MSR_FP); | ||
| 1525 | load_fp_state(¤t->thread.fp_state); | ||
| 1526 | regs->msr |= MSR_VSX; | ||
| 1527 | } | ||
| 1528 | } | 1706 | } |
| 1529 | 1707 | ||
| 1530 | void vsx_unavailable_tm(struct pt_regs *regs) | 1708 | void vsx_unavailable_tm(struct pt_regs *regs) |
| 1531 | { | 1709 | { |
| 1532 | unsigned long orig_msr = regs->msr; | ||
| 1533 | |||
| 1534 | /* See the comments in fp_unavailable_tm(). This works similarly, | 1710 | /* See the comments in fp_unavailable_tm(). This works similarly, |
| 1535 | * though we're loading both FP and VEC registers in here. | 1711 | * though we're loading both FP and VEC registers in here. |
| 1536 | * | 1712 | * |
| @@ -1544,29 +1720,13 @@ void vsx_unavailable_tm(struct pt_regs *regs) | |||
| 1544 | 1720 | ||
| 1545 | current->thread.used_vsr = 1; | 1721 | current->thread.used_vsr = 1; |
| 1546 | 1722 | ||
| 1547 | /* If FP and VMX are already loaded, we have all the state we need */ | ||
| 1548 | if ((orig_msr & (MSR_FP | MSR_VEC)) == (MSR_FP | MSR_VEC)) { | ||
| 1549 | regs->msr |= MSR_VSX; | ||
| 1550 | return; | ||
| 1551 | } | ||
| 1552 | |||
| 1553 | /* This reclaims FP and/or VR regs if they're already enabled */ | 1723 | /* This reclaims FP and/or VR regs if they're already enabled */ |
| 1554 | tm_reclaim_current(TM_CAUSE_FAC_UNAV); | 1724 | tm_reclaim_current(TM_CAUSE_FAC_UNAV); |
| 1555 | 1725 | ||
| 1556 | regs->msr |= MSR_VEC | MSR_FP | current->thread.fpexc_mode | | 1726 | current->thread.load_vec = 1; |
| 1557 | MSR_VSX; | 1727 | current->thread.load_fp = 1; |
| 1558 | |||
| 1559 | /* This loads & recheckpoints FP and VRs; but we have | ||
| 1560 | * to be sure not to overwrite previously-valid state. | ||
| 1561 | */ | ||
| 1562 | tm_recheckpoint(¤t->thread, regs->msr & ~orig_msr); | ||
| 1563 | |||
| 1564 | msr_check_and_set(orig_msr & (MSR_FP | MSR_VEC)); | ||
| 1565 | 1728 | ||
| 1566 | if (orig_msr & MSR_FP) | 1729 | tm_recheckpoint(¤t->thread); |
| 1567 | load_fp_state(¤t->thread.fp_state); | ||
| 1568 | if (orig_msr & MSR_VEC) | ||
| 1569 | load_vr_state(¤t->thread.vr_state); | ||
| 1570 | } | 1730 | } |
| 1571 | #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */ | 1731 | #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */ |
| 1572 | 1732 | ||
| @@ -1924,6 +2084,10 @@ struct ppc_emulated ppc_emulated = { | |||
| 1924 | WARN_EMULATED_SETUP(mfdscr), | 2084 | WARN_EMULATED_SETUP(mfdscr), |
| 1925 | WARN_EMULATED_SETUP(mtdscr), | 2085 | WARN_EMULATED_SETUP(mtdscr), |
| 1926 | WARN_EMULATED_SETUP(lq_stq), | 2086 | WARN_EMULATED_SETUP(lq_stq), |
| 2087 | WARN_EMULATED_SETUP(lxvw4x), | ||
| 2088 | WARN_EMULATED_SETUP(lxvh8x), | ||
| 2089 | WARN_EMULATED_SETUP(lxvd2x), | ||
| 2090 | WARN_EMULATED_SETUP(lxvb16x), | ||
| 1927 | #endif | 2091 | #endif |
| 1928 | }; | 2092 | }; |
| 1929 | 2093 | ||
diff --git a/arch/powerpc/kernel/watchdog.c b/arch/powerpc/kernel/watchdog.c index 1d89163d67f2..87da80ccced1 100644 --- a/arch/powerpc/kernel/watchdog.c +++ b/arch/powerpc/kernel/watchdog.c | |||
| @@ -98,8 +98,7 @@ static void wd_lockup_ipi(struct pt_regs *regs) | |||
| 98 | else | 98 | else |
| 99 | dump_stack(); | 99 | dump_stack(); |
| 100 | 100 | ||
| 101 | if (hardlockup_panic) | 101 | /* Do not panic from here because that can recurse into NMI IPI layer */ |
| 102 | nmi_panic(regs, "Hard LOCKUP"); | ||
| 103 | } | 102 | } |
| 104 | 103 | ||
| 105 | static void set_cpumask_stuck(const struct cpumask *cpumask, u64 tb) | 104 | static void set_cpumask_stuck(const struct cpumask *cpumask, u64 tb) |
| @@ -135,15 +134,18 @@ static void watchdog_smp_panic(int cpu, u64 tb) | |||
| 135 | pr_emerg("Watchdog CPU:%d detected Hard LOCKUP other CPUS:%*pbl\n", | 134 | pr_emerg("Watchdog CPU:%d detected Hard LOCKUP other CPUS:%*pbl\n", |
| 136 | cpu, cpumask_pr_args(&wd_smp_cpus_pending)); | 135 | cpu, cpumask_pr_args(&wd_smp_cpus_pending)); |
| 137 | 136 | ||
| 138 | /* | 137 | if (!sysctl_hardlockup_all_cpu_backtrace) { |
| 139 | * Try to trigger the stuck CPUs. | 138 | /* |
| 140 | */ | 139 | * Try to trigger the stuck CPUs, unless we are going to |
| 141 | for_each_cpu(c, &wd_smp_cpus_pending) { | 140 | * get a backtrace on all of them anyway. |
| 142 | if (c == cpu) | 141 | */ |
| 143 | continue; | 142 | for_each_cpu(c, &wd_smp_cpus_pending) { |
| 144 | smp_send_nmi_ipi(c, wd_lockup_ipi, 1000000); | 143 | if (c == cpu) |
| 144 | continue; | ||
| 145 | smp_send_nmi_ipi(c, wd_lockup_ipi, 1000000); | ||
| 146 | } | ||
| 147 | smp_flush_nmi_ipi(1000000); | ||
| 145 | } | 148 | } |
| 146 | smp_flush_nmi_ipi(1000000); | ||
| 147 | 149 | ||
| 148 | /* Take the stuck CPUs out of the watch group */ | 150 | /* Take the stuck CPUs out of the watch group */ |
| 149 | set_cpumask_stuck(&wd_smp_cpus_pending, tb); | 151 | set_cpumask_stuck(&wd_smp_cpus_pending, tb); |
| @@ -275,9 +277,12 @@ void arch_touch_nmi_watchdog(void) | |||
| 275 | { | 277 | { |
| 276 | unsigned long ticks = tb_ticks_per_usec * wd_timer_period_ms * 1000; | 278 | unsigned long ticks = tb_ticks_per_usec * wd_timer_period_ms * 1000; |
| 277 | int cpu = smp_processor_id(); | 279 | int cpu = smp_processor_id(); |
| 280 | u64 tb = get_tb(); | ||
| 278 | 281 | ||
| 279 | if (get_tb() - per_cpu(wd_timer_tb, cpu) >= ticks) | 282 | if (tb - per_cpu(wd_timer_tb, cpu) >= ticks) { |
| 280 | watchdog_timer_interrupt(cpu); | 283 | per_cpu(wd_timer_tb, cpu) = tb; |
| 284 | wd_smp_clear_cpu_pending(cpu, tb); | ||
| 285 | } | ||
| 281 | } | 286 | } |
| 282 | EXPORT_SYMBOL(arch_touch_nmi_watchdog); | 287 | EXPORT_SYMBOL(arch_touch_nmi_watchdog); |
| 283 | 288 | ||
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c index 8d43cf205d34..40e5857c4b1c 100644 --- a/arch/powerpc/kvm/book3s_hv.c +++ b/arch/powerpc/kvm/book3s_hv.c | |||
| @@ -47,6 +47,7 @@ | |||
| 47 | 47 | ||
| 48 | #include <asm/reg.h> | 48 | #include <asm/reg.h> |
| 49 | #include <asm/ppc-opcode.h> | 49 | #include <asm/ppc-opcode.h> |
| 50 | #include <asm/asm-prototypes.h> | ||
| 50 | #include <asm/disassemble.h> | 51 | #include <asm/disassemble.h> |
| 51 | #include <asm/cputable.h> | 52 | #include <asm/cputable.h> |
| 52 | #include <asm/cacheflush.h> | 53 | #include <asm/cacheflush.h> |
| @@ -1089,9 +1090,10 @@ static int kvmppc_handle_exit_hv(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
| 1089 | vcpu->stat.ext_intr_exits++; | 1090 | vcpu->stat.ext_intr_exits++; |
| 1090 | r = RESUME_GUEST; | 1091 | r = RESUME_GUEST; |
| 1091 | break; | 1092 | break; |
| 1092 | /* HMI is hypervisor interrupt and host has handled it. Resume guest.*/ | 1093 | /* SR/HMI/PMI are HV interrupts that host has handled. Resume guest.*/ |
| 1093 | case BOOK3S_INTERRUPT_HMI: | 1094 | case BOOK3S_INTERRUPT_HMI: |
| 1094 | case BOOK3S_INTERRUPT_PERFMON: | 1095 | case BOOK3S_INTERRUPT_PERFMON: |
| 1096 | case BOOK3S_INTERRUPT_SYSTEM_RESET: | ||
| 1095 | r = RESUME_GUEST; | 1097 | r = RESUME_GUEST; |
| 1096 | break; | 1098 | break; |
| 1097 | case BOOK3S_INTERRUPT_MACHINE_CHECK: | 1099 | case BOOK3S_INTERRUPT_MACHINE_CHECK: |
| @@ -2117,15 +2119,6 @@ static int kvmppc_grab_hwthread(int cpu) | |||
| 2117 | struct paca_struct *tpaca; | 2119 | struct paca_struct *tpaca; |
| 2118 | long timeout = 10000; | 2120 | long timeout = 10000; |
| 2119 | 2121 | ||
| 2120 | /* | ||
| 2121 | * ISA v3.0 idle routines do not set hwthread_state or test | ||
| 2122 | * hwthread_req, so they can not grab idle threads. | ||
| 2123 | */ | ||
| 2124 | if (cpu_has_feature(CPU_FTR_ARCH_300)) { | ||
| 2125 | WARN(1, "KVM: can not control sibling threads\n"); | ||
| 2126 | return -EBUSY; | ||
| 2127 | } | ||
| 2128 | |||
| 2129 | tpaca = &paca[cpu]; | 2122 | tpaca = &paca[cpu]; |
| 2130 | 2123 | ||
| 2131 | /* Ensure the thread won't go into the kernel if it wakes */ | 2124 | /* Ensure the thread won't go into the kernel if it wakes */ |
| @@ -2160,12 +2153,10 @@ static void kvmppc_release_hwthread(int cpu) | |||
| 2160 | struct paca_struct *tpaca; | 2153 | struct paca_struct *tpaca; |
| 2161 | 2154 | ||
| 2162 | tpaca = &paca[cpu]; | 2155 | tpaca = &paca[cpu]; |
| 2156 | tpaca->kvm_hstate.hwthread_req = 0; | ||
| 2163 | tpaca->kvm_hstate.kvm_vcpu = NULL; | 2157 | tpaca->kvm_hstate.kvm_vcpu = NULL; |
| 2164 | tpaca->kvm_hstate.kvm_vcore = NULL; | 2158 | tpaca->kvm_hstate.kvm_vcore = NULL; |
| 2165 | tpaca->kvm_hstate.kvm_split_mode = NULL; | 2159 | tpaca->kvm_hstate.kvm_split_mode = NULL; |
| 2166 | if (!cpu_has_feature(CPU_FTR_ARCH_300)) | ||
| 2167 | tpaca->kvm_hstate.hwthread_req = 0; | ||
| 2168 | |||
| 2169 | } | 2160 | } |
| 2170 | 2161 | ||
| 2171 | static void radix_flush_cpu(struct kvm *kvm, int cpu, struct kvm_vcpu *vcpu) | 2162 | static void radix_flush_cpu(struct kvm *kvm, int cpu, struct kvm_vcpu *vcpu) |
| @@ -2615,6 +2606,9 @@ static void set_irq_happened(int trap) | |||
| 2615 | case BOOK3S_INTERRUPT_HMI: | 2606 | case BOOK3S_INTERRUPT_HMI: |
| 2616 | local_paca->irq_happened |= PACA_IRQ_HMI; | 2607 | local_paca->irq_happened |= PACA_IRQ_HMI; |
| 2617 | break; | 2608 | break; |
| 2609 | case BOOK3S_INTERRUPT_SYSTEM_RESET: | ||
| 2610 | replay_system_reset(); | ||
| 2611 | break; | ||
| 2618 | } | 2612 | } |
| 2619 | } | 2613 | } |
| 2620 | 2614 | ||
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S index 42639fba89e8..68bf0f14a962 100644 --- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S +++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S | |||
| @@ -149,11 +149,9 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) | |||
| 149 | subf r4, r4, r3 | 149 | subf r4, r4, r3 |
| 150 | mtspr SPRN_DEC, r4 | 150 | mtspr SPRN_DEC, r4 |
| 151 | 151 | ||
| 152 | BEGIN_FTR_SECTION | ||
| 153 | /* hwthread_req may have got set by cede or no vcpu, so clear it */ | 152 | /* hwthread_req may have got set by cede or no vcpu, so clear it */ |
| 154 | li r0, 0 | 153 | li r0, 0 |
| 155 | stb r0, HSTATE_HWTHREAD_REQ(r13) | 154 | stb r0, HSTATE_HWTHREAD_REQ(r13) |
| 156 | END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_300) | ||
| 157 | 155 | ||
| 158 | /* | 156 | /* |
| 159 | * For external interrupts we need to call the Linux | 157 | * For external interrupts we need to call the Linux |
| @@ -316,7 +314,6 @@ kvm_novcpu_exit: | |||
| 316 | * Relocation is off and most register values are lost. | 314 | * Relocation is off and most register values are lost. |
| 317 | * r13 points to the PACA. | 315 | * r13 points to the PACA. |
| 318 | * r3 contains the SRR1 wakeup value, SRR1 is trashed. | 316 | * r3 contains the SRR1 wakeup value, SRR1 is trashed. |
| 319 | * This is not used by ISAv3.0B processors. | ||
| 320 | */ | 317 | */ |
| 321 | .globl kvm_start_guest | 318 | .globl kvm_start_guest |
| 322 | kvm_start_guest: | 319 | kvm_start_guest: |
| @@ -435,9 +432,6 @@ kvm_secondary_got_guest: | |||
| 435 | * While waiting we also need to check if we get given a vcpu to run. | 432 | * While waiting we also need to check if we get given a vcpu to run. |
| 436 | */ | 433 | */ |
| 437 | kvm_no_guest: | 434 | kvm_no_guest: |
| 438 | BEGIN_FTR_SECTION | ||
| 439 | twi 31,0,0 | ||
| 440 | END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300) | ||
| 441 | lbz r3, HSTATE_HWTHREAD_REQ(r13) | 435 | lbz r3, HSTATE_HWTHREAD_REQ(r13) |
| 442 | cmpwi r3, 0 | 436 | cmpwi r3, 0 |
| 443 | bne 53f | 437 | bne 53f |
| @@ -2546,10 +2540,8 @@ kvm_do_nap: | |||
| 2546 | clrrdi r0, r0, 1 | 2540 | clrrdi r0, r0, 1 |
| 2547 | mtspr SPRN_CTRLT, r0 | 2541 | mtspr SPRN_CTRLT, r0 |
| 2548 | 2542 | ||
| 2549 | BEGIN_FTR_SECTION | ||
| 2550 | li r0,1 | 2543 | li r0,1 |
| 2551 | stb r0,HSTATE_HWTHREAD_REQ(r13) | 2544 | stb r0,HSTATE_HWTHREAD_REQ(r13) |
| 2552 | END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_300) | ||
| 2553 | mfspr r5,SPRN_LPCR | 2545 | mfspr r5,SPRN_LPCR |
| 2554 | ori r5,r5,LPCR_PECE0 | LPCR_PECE1 | 2546 | ori r5,r5,LPCR_PECE0 | LPCR_PECE1 |
| 2555 | BEGIN_FTR_SECTION | 2547 | BEGIN_FTR_SECTION |
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c index ee279c7f4802..1abe6eb51335 100644 --- a/arch/powerpc/kvm/powerpc.c +++ b/arch/powerpc/kvm/powerpc.c | |||
| @@ -644,7 +644,8 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) | |||
| 644 | break; | 644 | break; |
| 645 | #endif | 645 | #endif |
| 646 | case KVM_CAP_PPC_HTM: | 646 | case KVM_CAP_PPC_HTM: |
| 647 | r = cpu_has_feature(CPU_FTR_TM_COMP) && hv_enabled; | 647 | r = hv_enabled && |
| 648 | (cur_cpu_spec->cpu_user_features2 & PPC_FEATURE2_HTM_COMP); | ||
| 648 | break; | 649 | break; |
| 649 | default: | 650 | default: |
| 650 | r = 0; | 651 | r = 0; |
diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile index c66c3626a216..3c29c9009bbf 100644 --- a/arch/powerpc/lib/Makefile +++ b/arch/powerpc/lib/Makefile | |||
| @@ -24,7 +24,7 @@ endif | |||
| 24 | 24 | ||
| 25 | obj64-y += copypage_64.o copyuser_64.o mem_64.o hweight_64.o \ | 25 | obj64-y += copypage_64.o copyuser_64.o mem_64.o hweight_64.o \ |
| 26 | copyuser_power7.o string_64.o copypage_power7.o memcpy_power7.o \ | 26 | copyuser_power7.o string_64.o copypage_power7.o memcpy_power7.o \ |
| 27 | memcpy_64.o memcmp_64.o | 27 | memcpy_64.o memcmp_64.o pmem.o |
| 28 | 28 | ||
| 29 | obj64-$(CONFIG_SMP) += locks.o | 29 | obj64-$(CONFIG_SMP) += locks.o |
| 30 | obj64-$(CONFIG_ALTIVEC) += vmx-helper.o | 30 | obj64-$(CONFIG_ALTIVEC) += vmx-helper.o |
diff --git a/arch/powerpc/lib/pmem.c b/arch/powerpc/lib/pmem.c new file mode 100644 index 000000000000..53c018762e1c --- /dev/null +++ b/arch/powerpc/lib/pmem.c | |||
| @@ -0,0 +1,67 @@ | |||
| 1 | /* | ||
| 2 | * Copyright(c) 2017 IBM Corporation. All rights reserved. | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify | ||
| 5 | * it under the terms of version 2 of the GNU General Public License as | ||
| 6 | * published by the Free Software Foundation. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, but | ||
| 9 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 11 | * General Public License for more details. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/string.h> | ||
| 15 | #include <linux/export.h> | ||
| 16 | #include <linux/uaccess.h> | ||
| 17 | |||
| 18 | #include <asm/cacheflush.h> | ||
| 19 | |||
| 20 | /* | ||
| 21 | * CONFIG_ARCH_HAS_PMEM_API symbols | ||
| 22 | */ | ||
| 23 | void arch_wb_cache_pmem(void *addr, size_t size) | ||
| 24 | { | ||
| 25 | unsigned long start = (unsigned long) addr; | ||
| 26 | flush_inval_dcache_range(start, start + size); | ||
| 27 | } | ||
| 28 | EXPORT_SYMBOL(arch_wb_cache_pmem); | ||
| 29 | |||
| 30 | void arch_invalidate_pmem(void *addr, size_t size) | ||
| 31 | { | ||
| 32 | unsigned long start = (unsigned long) addr; | ||
| 33 | flush_inval_dcache_range(start, start + size); | ||
| 34 | } | ||
| 35 | EXPORT_SYMBOL(arch_invalidate_pmem); | ||
| 36 | |||
| 37 | /* | ||
| 38 | * CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE symbols | ||
| 39 | */ | ||
| 40 | long __copy_from_user_flushcache(void *dest, const void __user *src, | ||
| 41 | unsigned size) | ||
| 42 | { | ||
| 43 | unsigned long copied, start = (unsigned long) dest; | ||
| 44 | |||
| 45 | copied = __copy_from_user(dest, src, size); | ||
| 46 | flush_inval_dcache_range(start, start + size); | ||
| 47 | |||
| 48 | return copied; | ||
| 49 | } | ||
| 50 | |||
| 51 | void *memcpy_flushcache(void *dest, const void *src, size_t size) | ||
| 52 | { | ||
| 53 | unsigned long start = (unsigned long) dest; | ||
| 54 | |||
| 55 | memcpy(dest, src, size); | ||
| 56 | flush_inval_dcache_range(start, start + size); | ||
| 57 | |||
| 58 | return dest; | ||
| 59 | } | ||
| 60 | EXPORT_SYMBOL(memcpy_flushcache); | ||
| 61 | |||
| 62 | void memcpy_page_flushcache(char *to, struct page *page, size_t offset, | ||
| 63 | size_t len) | ||
| 64 | { | ||
| 65 | memcpy_flushcache(to, page_to_virt(page) + offset, len); | ||
| 66 | } | ||
| 67 | EXPORT_SYMBOL(memcpy_page_flushcache); | ||
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c index f208f560aecd..70274b7b4773 100644 --- a/arch/powerpc/lib/sstep.c +++ b/arch/powerpc/lib/sstep.c | |||
| @@ -31,6 +31,8 @@ extern char system_call_common[]; | |||
| 31 | #define XER_SO 0x80000000U | 31 | #define XER_SO 0x80000000U |
| 32 | #define XER_OV 0x40000000U | 32 | #define XER_OV 0x40000000U |
| 33 | #define XER_CA 0x20000000U | 33 | #define XER_CA 0x20000000U |
| 34 | #define XER_OV32 0x00080000U | ||
| 35 | #define XER_CA32 0x00040000U | ||
| 34 | 36 | ||
| 35 | #ifdef CONFIG_PPC_FPU | 37 | #ifdef CONFIG_PPC_FPU |
| 36 | /* | 38 | /* |
| @@ -962,6 +964,16 @@ static nokprobe_inline void set_cr0(const struct pt_regs *regs, | |||
| 962 | op->ccval |= 0x20000000; | 964 | op->ccval |= 0x20000000; |
| 963 | } | 965 | } |
| 964 | 966 | ||
| 967 | static nokprobe_inline void set_ca32(struct instruction_op *op, bool val) | ||
| 968 | { | ||
| 969 | if (cpu_has_feature(CPU_FTR_ARCH_300)) { | ||
| 970 | if (val) | ||
| 971 | op->xerval |= XER_CA32; | ||
| 972 | else | ||
| 973 | op->xerval &= ~XER_CA32; | ||
| 974 | } | ||
| 975 | } | ||
| 976 | |||
| 965 | static nokprobe_inline void add_with_carry(const struct pt_regs *regs, | 977 | static nokprobe_inline void add_with_carry(const struct pt_regs *regs, |
| 966 | struct instruction_op *op, int rd, | 978 | struct instruction_op *op, int rd, |
| 967 | unsigned long val1, unsigned long val2, | 979 | unsigned long val1, unsigned long val2, |
| @@ -985,6 +997,9 @@ static nokprobe_inline void add_with_carry(const struct pt_regs *regs, | |||
| 985 | op->xerval |= XER_CA; | 997 | op->xerval |= XER_CA; |
| 986 | else | 998 | else |
| 987 | op->xerval &= ~XER_CA; | 999 | op->xerval &= ~XER_CA; |
| 1000 | |||
| 1001 | set_ca32(op, (unsigned int)val < (unsigned int)val1 || | ||
| 1002 | (carry_in && (unsigned int)val == (unsigned int)val1)); | ||
| 988 | } | 1003 | } |
| 989 | 1004 | ||
| 990 | static nokprobe_inline void do_cmp_signed(const struct pt_regs *regs, | 1005 | static nokprobe_inline void do_cmp_signed(const struct pt_regs *regs, |
| @@ -1791,6 +1806,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, | |||
| 1791 | op->xerval |= XER_CA; | 1806 | op->xerval |= XER_CA; |
| 1792 | else | 1807 | else |
| 1793 | op->xerval &= ~XER_CA; | 1808 | op->xerval &= ~XER_CA; |
| 1809 | set_ca32(op, op->xerval & XER_CA); | ||
| 1794 | goto logical_done; | 1810 | goto logical_done; |
| 1795 | 1811 | ||
| 1796 | case 824: /* srawi */ | 1812 | case 824: /* srawi */ |
| @@ -1803,6 +1819,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, | |||
| 1803 | op->xerval |= XER_CA; | 1819 | op->xerval |= XER_CA; |
| 1804 | else | 1820 | else |
| 1805 | op->xerval &= ~XER_CA; | 1821 | op->xerval &= ~XER_CA; |
| 1822 | set_ca32(op, op->xerval & XER_CA); | ||
| 1806 | goto logical_done; | 1823 | goto logical_done; |
| 1807 | 1824 | ||
| 1808 | #ifdef __powerpc64__ | 1825 | #ifdef __powerpc64__ |
| @@ -1832,6 +1849,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, | |||
| 1832 | op->xerval |= XER_CA; | 1849 | op->xerval |= XER_CA; |
| 1833 | else | 1850 | else |
| 1834 | op->xerval &= ~XER_CA; | 1851 | op->xerval &= ~XER_CA; |
| 1852 | set_ca32(op, op->xerval & XER_CA); | ||
| 1835 | goto logical_done; | 1853 | goto logical_done; |
| 1836 | 1854 | ||
| 1837 | case 826: /* sradi with sh_5 = 0 */ | 1855 | case 826: /* sradi with sh_5 = 0 */ |
| @@ -1845,6 +1863,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, | |||
| 1845 | op->xerval |= XER_CA; | 1863 | op->xerval |= XER_CA; |
| 1846 | else | 1864 | else |
| 1847 | op->xerval &= ~XER_CA; | 1865 | op->xerval &= ~XER_CA; |
| 1866 | set_ca32(op, op->xerval & XER_CA); | ||
| 1848 | goto logical_done; | 1867 | goto logical_done; |
| 1849 | #endif /* __powerpc64__ */ | 1868 | #endif /* __powerpc64__ */ |
| 1850 | 1869 | ||
| @@ -2698,6 +2717,7 @@ void emulate_update_regs(struct pt_regs *regs, struct instruction_op *op) | |||
| 2698 | } | 2717 | } |
| 2699 | regs->nip = next_pc; | 2718 | regs->nip = next_pc; |
| 2700 | } | 2719 | } |
| 2720 | NOKPROBE_SYMBOL(emulate_update_regs); | ||
| 2701 | 2721 | ||
| 2702 | /* | 2722 | /* |
| 2703 | * Emulate a previously-analysed load or store instruction. | 2723 | * Emulate a previously-analysed load or store instruction. |
diff --git a/arch/powerpc/mm/Makefile b/arch/powerpc/mm/Makefile index a0c327d544d1..76a6b057d454 100644 --- a/arch/powerpc/mm/Makefile +++ b/arch/powerpc/mm/Makefile | |||
| @@ -15,11 +15,11 @@ obj-$(CONFIG_PPC_MMU_NOHASH) += mmu_context_nohash.o tlb_nohash.o \ | |||
| 15 | obj-$(CONFIG_PPC_BOOK3E) += tlb_low_$(BITS)e.o | 15 | obj-$(CONFIG_PPC_BOOK3E) += tlb_low_$(BITS)e.o |
| 16 | hash64-$(CONFIG_PPC_NATIVE) := hash_native_64.o | 16 | hash64-$(CONFIG_PPC_NATIVE) := hash_native_64.o |
| 17 | obj-$(CONFIG_PPC_BOOK3E_64) += pgtable-book3e.o | 17 | obj-$(CONFIG_PPC_BOOK3E_64) += pgtable-book3e.o |
| 18 | obj-$(CONFIG_PPC_STD_MMU_64) += pgtable-hash64.o hash_utils_64.o slb_low.o slb.o $(hash64-y) mmu_context_book3s64.o pgtable-book3s64.o | 18 | obj-$(CONFIG_PPC_BOOK3S_64) += pgtable-hash64.o hash_utils_64.o slb_low.o slb.o $(hash64-y) mmu_context_book3s64.o pgtable-book3s64.o |
| 19 | obj-$(CONFIG_PPC_RADIX_MMU) += pgtable-radix.o tlb-radix.o | 19 | obj-$(CONFIG_PPC_RADIX_MMU) += pgtable-radix.o tlb-radix.o |
| 20 | obj-$(CONFIG_PPC_STD_MMU_32) += ppc_mmu_32.o hash_low_32.o mmu_context_hash32.o | 20 | obj-$(CONFIG_PPC_STD_MMU_32) += ppc_mmu_32.o hash_low_32.o mmu_context_hash32.o |
| 21 | obj-$(CONFIG_PPC_STD_MMU) += tlb_hash$(BITS).o | 21 | obj-$(CONFIG_PPC_STD_MMU) += tlb_hash$(BITS).o |
| 22 | ifeq ($(CONFIG_PPC_STD_MMU_64),y) | 22 | ifeq ($(CONFIG_PPC_BOOK3S_64),y) |
| 23 | obj-$(CONFIG_PPC_4K_PAGES) += hash64_4k.o | 23 | obj-$(CONFIG_PPC_4K_PAGES) += hash64_4k.o |
| 24 | obj-$(CONFIG_PPC_64K_PAGES) += hash64_64k.o | 24 | obj-$(CONFIG_PPC_64K_PAGES) += hash64_64k.o |
| 25 | endif | 25 | endif |
| @@ -32,7 +32,7 @@ obj-$(CONFIG_PPC_SPLPAR) += vphn.o | |||
| 32 | obj-$(CONFIG_PPC_MM_SLICES) += slice.o | 32 | obj-$(CONFIG_PPC_MM_SLICES) += slice.o |
| 33 | obj-y += hugetlbpage.o | 33 | obj-y += hugetlbpage.o |
| 34 | ifeq ($(CONFIG_HUGETLB_PAGE),y) | 34 | ifeq ($(CONFIG_HUGETLB_PAGE),y) |
| 35 | obj-$(CONFIG_PPC_STD_MMU_64) += hugetlbpage-hash64.o | 35 | obj-$(CONFIG_PPC_BOOK3S_64) += hugetlbpage-hash64.o |
| 36 | obj-$(CONFIG_PPC_RADIX_MMU) += hugetlbpage-radix.o | 36 | obj-$(CONFIG_PPC_RADIX_MMU) += hugetlbpage-radix.o |
| 37 | obj-$(CONFIG_PPC_BOOK3E_MMU) += hugetlbpage-book3e.o | 37 | obj-$(CONFIG_PPC_BOOK3E_MMU) += hugetlbpage-book3e.o |
| 38 | endif | 38 | endif |
diff --git a/arch/powerpc/mm/dump_hashpagetable.c b/arch/powerpc/mm/dump_hashpagetable.c index 5c4c93dcff19..14cfb11b09d0 100644 --- a/arch/powerpc/mm/dump_hashpagetable.c +++ b/arch/powerpc/mm/dump_hashpagetable.c | |||
| @@ -500,7 +500,7 @@ static void populate_markers(void) | |||
| 500 | address_markers[6].start_address = PHB_IO_END; | 500 | address_markers[6].start_address = PHB_IO_END; |
| 501 | address_markers[7].start_address = IOREMAP_BASE; | 501 | address_markers[7].start_address = IOREMAP_BASE; |
| 502 | address_markers[8].start_address = IOREMAP_END; | 502 | address_markers[8].start_address = IOREMAP_END; |
| 503 | #ifdef CONFIG_PPC_STD_MMU_64 | 503 | #ifdef CONFIG_PPC_BOOK3S_64 |
| 504 | address_markers[9].start_address = H_VMEMMAP_BASE; | 504 | address_markers[9].start_address = H_VMEMMAP_BASE; |
| 505 | #else | 505 | #else |
| 506 | address_markers[9].start_address = VMEMMAP_BASE; | 506 | address_markers[9].start_address = VMEMMAP_BASE; |
diff --git a/arch/powerpc/mm/dump_linuxpagetables.c b/arch/powerpc/mm/dump_linuxpagetables.c index c9282d27b203..c2e7dea59490 100644 --- a/arch/powerpc/mm/dump_linuxpagetables.c +++ b/arch/powerpc/mm/dump_linuxpagetables.c | |||
| @@ -112,7 +112,7 @@ struct flag_info { | |||
| 112 | 112 | ||
| 113 | static const struct flag_info flag_array[] = { | 113 | static const struct flag_info flag_array[] = { |
| 114 | { | 114 | { |
| 115 | #ifdef CONFIG_PPC_STD_MMU_64 | 115 | #ifdef CONFIG_PPC_BOOK3S_64 |
| 116 | .mask = _PAGE_PRIVILEGED, | 116 | .mask = _PAGE_PRIVILEGED, |
| 117 | .val = 0, | 117 | .val = 0, |
| 118 | #else | 118 | #else |
| @@ -147,7 +147,7 @@ static const struct flag_info flag_array[] = { | |||
| 147 | .set = "present", | 147 | .set = "present", |
| 148 | .clear = " ", | 148 | .clear = " ", |
| 149 | }, { | 149 | }, { |
| 150 | #ifdef CONFIG_PPC_STD_MMU_64 | 150 | #ifdef CONFIG_PPC_BOOK3S_64 |
| 151 | .mask = H_PAGE_HASHPTE, | 151 | .mask = H_PAGE_HASHPTE, |
| 152 | .val = H_PAGE_HASHPTE, | 152 | .val = H_PAGE_HASHPTE, |
| 153 | #else | 153 | #else |
| @@ -157,7 +157,7 @@ static const struct flag_info flag_array[] = { | |||
| 157 | .set = "hpte", | 157 | .set = "hpte", |
| 158 | .clear = " ", | 158 | .clear = " ", |
| 159 | }, { | 159 | }, { |
| 160 | #ifndef CONFIG_PPC_STD_MMU_64 | 160 | #ifndef CONFIG_PPC_BOOK3S_64 |
| 161 | .mask = _PAGE_GUARDED, | 161 | .mask = _PAGE_GUARDED, |
| 162 | .val = _PAGE_GUARDED, | 162 | .val = _PAGE_GUARDED, |
| 163 | .set = "guarded", | 163 | .set = "guarded", |
| @@ -174,7 +174,7 @@ static const struct flag_info flag_array[] = { | |||
| 174 | .set = "accessed", | 174 | .set = "accessed", |
| 175 | .clear = " ", | 175 | .clear = " ", |
| 176 | }, { | 176 | }, { |
| 177 | #ifndef CONFIG_PPC_STD_MMU_64 | 177 | #ifndef CONFIG_PPC_BOOK3S_64 |
| 178 | .mask = _PAGE_WRITETHRU, | 178 | .mask = _PAGE_WRITETHRU, |
| 179 | .val = _PAGE_WRITETHRU, | 179 | .val = _PAGE_WRITETHRU, |
| 180 | .set = "write through", | 180 | .set = "write through", |
| @@ -450,7 +450,7 @@ static void populate_markers(void) | |||
| 450 | address_markers[i++].start_address = PHB_IO_END; | 450 | address_markers[i++].start_address = PHB_IO_END; |
| 451 | address_markers[i++].start_address = IOREMAP_BASE; | 451 | address_markers[i++].start_address = IOREMAP_BASE; |
| 452 | address_markers[i++].start_address = IOREMAP_END; | 452 | address_markers[i++].start_address = IOREMAP_END; |
| 453 | #ifdef CONFIG_PPC_STD_MMU_64 | 453 | #ifdef CONFIG_PPC_BOOK3S_64 |
| 454 | address_markers[i++].start_address = H_VMEMMAP_BASE; | 454 | address_markers[i++].start_address = H_VMEMMAP_BASE; |
| 455 | #else | 455 | #else |
| 456 | address_markers[i++].start_address = VMEMMAP_BASE; | 456 | address_markers[i++].start_address = VMEMMAP_BASE; |
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 67ec2e927253..655a5a9a183d 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #undef DEBUG | 21 | #undef DEBUG |
| 22 | #undef DEBUG_LOW | 22 | #undef DEBUG_LOW |
| 23 | 23 | ||
| 24 | #define pr_fmt(fmt) "hash-mmu: " fmt | ||
| 24 | #include <linux/spinlock.h> | 25 | #include <linux/spinlock.h> |
| 25 | #include <linux/errno.h> | 26 | #include <linux/errno.h> |
| 26 | #include <linux/sched/mm.h> | 27 | #include <linux/sched/mm.h> |
diff --git a/arch/powerpc/mm/hugetlbpage-radix.c b/arch/powerpc/mm/hugetlbpage-radix.c index 558e9d3891bf..2486bee0f93e 100644 --- a/arch/powerpc/mm/hugetlbpage-radix.c +++ b/arch/powerpc/mm/hugetlbpage-radix.c | |||
| @@ -49,17 +49,22 @@ radix__hugetlb_get_unmapped_area(struct file *file, unsigned long addr, | |||
| 49 | struct mm_struct *mm = current->mm; | 49 | struct mm_struct *mm = current->mm; |
| 50 | struct vm_area_struct *vma; | 50 | struct vm_area_struct *vma; |
| 51 | struct hstate *h = hstate_file(file); | 51 | struct hstate *h = hstate_file(file); |
| 52 | int fixed = (flags & MAP_FIXED); | ||
| 53 | unsigned long high_limit; | ||
| 52 | struct vm_unmapped_area_info info; | 54 | struct vm_unmapped_area_info info; |
| 53 | 55 | ||
| 54 | if (unlikely(addr > mm->context.addr_limit && addr < TASK_SIZE)) | 56 | high_limit = DEFAULT_MAP_WINDOW; |
| 55 | mm->context.addr_limit = TASK_SIZE; | 57 | if (addr >= high_limit || (fixed && (addr + len > high_limit))) |
| 58 | high_limit = TASK_SIZE; | ||
| 56 | 59 | ||
| 57 | if (len & ~huge_page_mask(h)) | 60 | if (len & ~huge_page_mask(h)) |
| 58 | return -EINVAL; | 61 | return -EINVAL; |
| 59 | if (len > mm->task_size) | 62 | if (len > high_limit) |
| 60 | return -ENOMEM; | 63 | return -ENOMEM; |
| 61 | 64 | ||
| 62 | if (flags & MAP_FIXED) { | 65 | if (fixed) { |
| 66 | if (addr > high_limit - len) | ||
| 67 | return -ENOMEM; | ||
| 63 | if (prepare_hugepage_range(file, addr, len)) | 68 | if (prepare_hugepage_range(file, addr, len)) |
| 64 | return -EINVAL; | 69 | return -EINVAL; |
| 65 | return addr; | 70 | return addr; |
| @@ -68,7 +73,7 @@ radix__hugetlb_get_unmapped_area(struct file *file, unsigned long addr, | |||
| 68 | if (addr) { | 73 | if (addr) { |
| 69 | addr = ALIGN(addr, huge_page_size(h)); | 74 | addr = ALIGN(addr, huge_page_size(h)); |
| 70 | vma = find_vma(mm, addr); | 75 | vma = find_vma(mm, addr); |
| 71 | if (mm->task_size - len >= addr && | 76 | if (high_limit - len >= addr && |
| 72 | (!vma || addr + len <= vm_start_gap(vma))) | 77 | (!vma || addr + len <= vm_start_gap(vma))) |
| 73 | return addr; | 78 | return addr; |
| 74 | } | 79 | } |
| @@ -79,12 +84,9 @@ radix__hugetlb_get_unmapped_area(struct file *file, unsigned long addr, | |||
| 79 | info.flags = VM_UNMAPPED_AREA_TOPDOWN; | 84 | info.flags = VM_UNMAPPED_AREA_TOPDOWN; |
| 80 | info.length = len; | 85 | info.length = len; |
| 81 | info.low_limit = PAGE_SIZE; | 86 | info.low_limit = PAGE_SIZE; |
| 82 | info.high_limit = current->mm->mmap_base; | 87 | info.high_limit = mm->mmap_base + (high_limit - DEFAULT_MAP_WINDOW); |
| 83 | info.align_mask = PAGE_MASK & ~huge_page_mask(h); | 88 | info.align_mask = PAGE_MASK & ~huge_page_mask(h); |
| 84 | info.align_offset = 0; | 89 | info.align_offset = 0; |
| 85 | 90 | ||
| 86 | if (addr > DEFAULT_MAP_WINDOW) | ||
| 87 | info.high_limit += mm->context.addr_limit - DEFAULT_MAP_WINDOW; | ||
| 88 | |||
| 89 | return vm_unmapped_area(&info); | 91 | return vm_unmapped_area(&info); |
| 90 | } | 92 | } |
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c index 588a521966ec..a07722531b32 100644 --- a/arch/powerpc/mm/init_64.c +++ b/arch/powerpc/mm/init_64.c | |||
| @@ -68,11 +68,11 @@ | |||
| 68 | 68 | ||
| 69 | #include "mmu_decl.h" | 69 | #include "mmu_decl.h" |
| 70 | 70 | ||
| 71 | #ifdef CONFIG_PPC_STD_MMU_64 | 71 | #ifdef CONFIG_PPC_BOOK3S_64 |
| 72 | #if H_PGTABLE_RANGE > USER_VSID_RANGE | 72 | #if H_PGTABLE_RANGE > USER_VSID_RANGE |
| 73 | #warning Limited user VSID range means pagetable space is wasted | 73 | #warning Limited user VSID range means pagetable space is wasted |
| 74 | #endif | 74 | #endif |
| 75 | #endif /* CONFIG_PPC_STD_MMU_64 */ | 75 | #endif /* CONFIG_PPC_BOOK3S_64 */ |
| 76 | 76 | ||
| 77 | phys_addr_t memstart_addr = ~0; | 77 | phys_addr_t memstart_addr = ~0; |
| 78 | EXPORT_SYMBOL_GPL(memstart_addr); | 78 | EXPORT_SYMBOL_GPL(memstart_addr); |
| @@ -367,11 +367,20 @@ EXPORT_SYMBOL_GPL(realmode_pfn_to_page); | |||
| 367 | 367 | ||
| 368 | #endif /* CONFIG_SPARSEMEM_VMEMMAP */ | 368 | #endif /* CONFIG_SPARSEMEM_VMEMMAP */ |
| 369 | 369 | ||
| 370 | #ifdef CONFIG_PPC_STD_MMU_64 | 370 | #ifdef CONFIG_PPC_BOOK3S_64 |
| 371 | static bool disable_radix; | 371 | static bool disable_radix = !IS_ENABLED(CONFIG_PPC_RADIX_MMU_DEFAULT); |
| 372 | |||
| 372 | static int __init parse_disable_radix(char *p) | 373 | static int __init parse_disable_radix(char *p) |
| 373 | { | 374 | { |
| 374 | disable_radix = true; | 375 | bool val; |
| 376 | |||
| 377 | if (strlen(p) == 0) | ||
| 378 | val = true; | ||
| 379 | else if (kstrtobool(p, &val)) | ||
| 380 | return -EINVAL; | ||
| 381 | |||
| 382 | disable_radix = val; | ||
| 383 | |||
| 375 | return 0; | 384 | return 0; |
| 376 | } | 385 | } |
| 377 | early_param("disable_radix", parse_disable_radix); | 386 | early_param("disable_radix", parse_disable_radix); |
| @@ -444,4 +453,4 @@ void __init mmu_early_init_devtree(void) | |||
| 444 | else | 453 | else |
| 445 | hash__early_init_devtree(); | 454 | hash__early_init_devtree(); |
| 446 | } | 455 | } |
| 447 | #endif /* CONFIG_PPC_STD_MMU_64 */ | 456 | #endif /* CONFIG_PPC_BOOK3S_64 */ |
diff --git a/arch/powerpc/mm/mmap.c b/arch/powerpc/mm/mmap.c index 5d78b193fec4..d503f344e476 100644 --- a/arch/powerpc/mm/mmap.c +++ b/arch/powerpc/mm/mmap.c | |||
| @@ -106,22 +106,27 @@ radix__arch_get_unmapped_area(struct file *filp, unsigned long addr, | |||
| 106 | { | 106 | { |
| 107 | struct mm_struct *mm = current->mm; | 107 | struct mm_struct *mm = current->mm; |
| 108 | struct vm_area_struct *vma; | 108 | struct vm_area_struct *vma; |
| 109 | int fixed = (flags & MAP_FIXED); | ||
| 110 | unsigned long high_limit; | ||
| 109 | struct vm_unmapped_area_info info; | 111 | struct vm_unmapped_area_info info; |
| 110 | 112 | ||
| 111 | if (unlikely(addr > mm->context.addr_limit && | 113 | high_limit = DEFAULT_MAP_WINDOW; |
| 112 | mm->context.addr_limit != TASK_SIZE)) | 114 | if (addr >= high_limit || (fixed && (addr + len > high_limit))) |
| 113 | mm->context.addr_limit = TASK_SIZE; | 115 | high_limit = TASK_SIZE; |
| 114 | 116 | ||
| 115 | if (len > mm->task_size - mmap_min_addr) | 117 | if (len > high_limit) |
| 116 | return -ENOMEM; | 118 | return -ENOMEM; |
| 117 | 119 | ||
| 118 | if (flags & MAP_FIXED) | 120 | if (fixed) { |
| 121 | if (addr > high_limit - len) | ||
| 122 | return -ENOMEM; | ||
| 119 | return addr; | 123 | return addr; |
| 124 | } | ||
| 120 | 125 | ||
| 121 | if (addr) { | 126 | if (addr) { |
| 122 | addr = PAGE_ALIGN(addr); | 127 | addr = PAGE_ALIGN(addr); |
| 123 | vma = find_vma(mm, addr); | 128 | vma = find_vma(mm, addr); |
| 124 | if (mm->task_size - len >= addr && addr >= mmap_min_addr && | 129 | if (high_limit - len >= addr && addr >= mmap_min_addr && |
| 125 | (!vma || addr + len <= vm_start_gap(vma))) | 130 | (!vma || addr + len <= vm_start_gap(vma))) |
| 126 | return addr; | 131 | return addr; |
| 127 | } | 132 | } |
| @@ -129,13 +134,9 @@ radix__arch_get_unmapped_area(struct file *filp, unsigned long addr, | |||
| 129 | info.flags = 0; | 134 | info.flags = 0; |
| 130 | info.length = len; | 135 | info.length = len; |
| 131 | info.low_limit = mm->mmap_base; | 136 | info.low_limit = mm->mmap_base; |
| 137 | info.high_limit = high_limit; | ||
| 132 | info.align_mask = 0; | 138 | info.align_mask = 0; |
| 133 | 139 | ||
| 134 | if (unlikely(addr > DEFAULT_MAP_WINDOW)) | ||
| 135 | info.high_limit = mm->context.addr_limit; | ||
| 136 | else | ||
| 137 | info.high_limit = DEFAULT_MAP_WINDOW; | ||
| 138 | |||
| 139 | return vm_unmapped_area(&info); | 140 | return vm_unmapped_area(&info); |
| 140 | } | 141 | } |
| 141 | 142 | ||
| @@ -149,37 +150,37 @@ radix__arch_get_unmapped_area_topdown(struct file *filp, | |||
| 149 | struct vm_area_struct *vma; | 150 | struct vm_area_struct *vma; |
| 150 | struct mm_struct *mm = current->mm; | 151 | struct mm_struct *mm = current->mm; |
| 151 | unsigned long addr = addr0; | 152 | unsigned long addr = addr0; |
| 153 | int fixed = (flags & MAP_FIXED); | ||
| 154 | unsigned long high_limit; | ||
| 152 | struct vm_unmapped_area_info info; | 155 | struct vm_unmapped_area_info info; |
| 153 | 156 | ||
| 154 | if (unlikely(addr > mm->context.addr_limit && | 157 | high_limit = DEFAULT_MAP_WINDOW; |
| 155 | mm->context.addr_limit != TASK_SIZE)) | 158 | if (addr >= high_limit || (fixed && (addr + len > high_limit))) |
| 156 | mm->context.addr_limit = TASK_SIZE; | 159 | high_limit = TASK_SIZE; |
| 157 | 160 | ||
| 158 | /* requested length too big for entire address space */ | 161 | if (len > high_limit) |
| 159 | if (len > mm->task_size - mmap_min_addr) | ||
| 160 | return -ENOMEM; | 162 | return -ENOMEM; |
| 161 | 163 | ||
| 162 | if (flags & MAP_FIXED) | 164 | if (fixed) { |
| 165 | if (addr > high_limit - len) | ||
| 166 | return -ENOMEM; | ||
| 163 | return addr; | 167 | return addr; |
| 168 | } | ||
| 164 | 169 | ||
| 165 | /* requesting a specific address */ | ||
| 166 | if (addr) { | 170 | if (addr) { |
| 167 | addr = PAGE_ALIGN(addr); | 171 | addr = PAGE_ALIGN(addr); |
| 168 | vma = find_vma(mm, addr); | 172 | vma = find_vma(mm, addr); |
| 169 | if (mm->task_size - len >= addr && addr >= mmap_min_addr && | 173 | if (high_limit - len >= addr && addr >= mmap_min_addr && |
| 170 | (!vma || addr + len <= vm_start_gap(vma))) | 174 | (!vma || addr + len <= vm_start_gap(vma))) |
| 171 | return addr; | 175 | return addr; |
| 172 | } | 176 | } |
| 173 | 177 | ||
| 174 | info.flags = VM_UNMAPPED_AREA_TOPDOWN; | 178 | info.flags = VM_UNMAPPED_AREA_TOPDOWN; |
| 175 | info.length = len; | 179 | info.length = len; |
| 176 | info.low_limit = max(PAGE_SIZE, mmap_min_addr); | 180 | info.low_limit = max(PAGE_SIZE, mmap_min_addr); |
| 177 | info.high_limit = mm->mmap_base; | 181 | info.high_limit = mm->mmap_base + (high_limit - DEFAULT_MAP_WINDOW); |
| 178 | info.align_mask = 0; | 182 | info.align_mask = 0; |
| 179 | 183 | ||
| 180 | if (addr > DEFAULT_MAP_WINDOW) | ||
| 181 | info.high_limit += mm->context.addr_limit - DEFAULT_MAP_WINDOW; | ||
| 182 | |||
| 183 | addr = vm_unmapped_area(&info); | 184 | addr = vm_unmapped_area(&info); |
| 184 | if (!(addr & ~PAGE_MASK)) | 185 | if (!(addr & ~PAGE_MASK)) |
| 185 | return addr; | 186 | return addr; |
diff --git a/arch/powerpc/mm/mmu_context.c b/arch/powerpc/mm/mmu_context.c index 0f613bc63c50..d60a62bf4fc7 100644 --- a/arch/powerpc/mm/mmu_context.c +++ b/arch/powerpc/mm/mmu_context.c | |||
| @@ -34,15 +34,6 @@ static inline void switch_mm_pgdir(struct task_struct *tsk, | |||
| 34 | struct mm_struct *mm) { } | 34 | struct mm_struct *mm) { } |
| 35 | #endif | 35 | #endif |
| 36 | 36 | ||
| 37 | #ifdef CONFIG_PPC_BOOK3S_64 | ||
| 38 | static inline void inc_mm_active_cpus(struct mm_struct *mm) | ||
| 39 | { | ||
| 40 | atomic_inc(&mm->context.active_cpus); | ||
| 41 | } | ||
| 42 | #else | ||
| 43 | static inline void inc_mm_active_cpus(struct mm_struct *mm) { } | ||
| 44 | #endif | ||
| 45 | |||
| 46 | void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next, | 37 | void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next, |
| 47 | struct task_struct *tsk) | 38 | struct task_struct *tsk) |
| 48 | { | 39 | { |
diff --git a/arch/powerpc/mm/mmu_context_book3s64.c b/arch/powerpc/mm/mmu_context_book3s64.c index a7e998158f37..59c0766ae4e0 100644 --- a/arch/powerpc/mm/mmu_context_book3s64.c +++ b/arch/powerpc/mm/mmu_context_book3s64.c | |||
| @@ -93,11 +93,11 @@ static int hash__init_new_context(struct mm_struct *mm) | |||
| 93 | return index; | 93 | return index; |
| 94 | 94 | ||
| 95 | /* | 95 | /* |
| 96 | * We do switch_slb() early in fork, even before we setup the | 96 | * In the case of exec, use the default limit, |
| 97 | * mm->context.addr_limit. Default to max task size so that we copy the | 97 | * otherwise inherit it from the mm we are duplicating. |
| 98 | * default values to paca which will help us to handle slb miss early. | ||
| 99 | */ | 98 | */ |
| 100 | mm->context.addr_limit = DEFAULT_MAP_WINDOW_USER64; | 99 | if (!mm->context.slb_addr_limit) |
| 100 | mm->context.slb_addr_limit = DEFAULT_MAP_WINDOW_USER64; | ||
| 101 | 101 | ||
| 102 | /* | 102 | /* |
| 103 | * The old code would re-promote on fork, we don't do that when using | 103 | * The old code would re-promote on fork, we don't do that when using |
| @@ -216,19 +216,34 @@ void destroy_context(struct mm_struct *mm) | |||
| 216 | #ifdef CONFIG_SPAPR_TCE_IOMMU | 216 | #ifdef CONFIG_SPAPR_TCE_IOMMU |
| 217 | WARN_ON_ONCE(!list_empty(&mm->context.iommu_group_mem_list)); | 217 | WARN_ON_ONCE(!list_empty(&mm->context.iommu_group_mem_list)); |
| 218 | #endif | 218 | #endif |
| 219 | if (radix_enabled()) | ||
| 220 | WARN_ON(process_tb[mm->context.id].prtb0 != 0); | ||
| 221 | else | ||
| 222 | subpage_prot_free(mm); | ||
| 223 | destroy_pagetable_page(mm); | ||
| 224 | __destroy_context(mm->context.id); | ||
| 225 | mm->context.id = MMU_NO_CONTEXT; | ||
| 226 | } | ||
| 227 | |||
| 228 | void arch_exit_mmap(struct mm_struct *mm) | ||
| 229 | { | ||
| 219 | if (radix_enabled()) { | 230 | if (radix_enabled()) { |
| 220 | /* | 231 | /* |
| 221 | * Radix doesn't have a valid bit in the process table | 232 | * Radix doesn't have a valid bit in the process table |
| 222 | * entries. However we know that at least P9 implementation | 233 | * entries. However we know that at least P9 implementation |
| 223 | * will avoid caching an entry with an invalid RTS field, | 234 | * will avoid caching an entry with an invalid RTS field, |
| 224 | * and 0 is invalid. So this will do. | 235 | * and 0 is invalid. So this will do. |
| 236 | * | ||
| 237 | * This runs before the "fullmm" tlb flush in exit_mmap, | ||
| 238 | * which does a RIC=2 tlbie to clear the process table | ||
| 239 | * entry. See the "fullmm" comments in tlb-radix.c. | ||
| 240 | * | ||
| 241 | * No barrier required here after the store because | ||
| 242 | * this process will do the invalidate, which starts with | ||
| 243 | * ptesync. | ||
| 225 | */ | 244 | */ |
| 226 | process_tb[mm->context.id].prtb0 = 0; | 245 | process_tb[mm->context.id].prtb0 = 0; |
| 227 | } else | 246 | } |
| 228 | subpage_prot_free(mm); | ||
| 229 | destroy_pagetable_page(mm); | ||
| 230 | __destroy_context(mm->context.id); | ||
| 231 | mm->context.id = MMU_NO_CONTEXT; | ||
| 232 | } | 247 | } |
| 233 | 248 | ||
| 234 | #ifdef CONFIG_PPC_RADIX_MMU | 249 | #ifdef CONFIG_PPC_RADIX_MMU |
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index 73016451f330..adb6364f4091 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c | |||
| @@ -1148,11 +1148,33 @@ struct topology_update_data { | |||
| 1148 | int new_nid; | 1148 | int new_nid; |
| 1149 | }; | 1149 | }; |
| 1150 | 1150 | ||
| 1151 | #define TOPOLOGY_DEF_TIMER_SECS 60 | ||
| 1152 | |||
| 1151 | static u8 vphn_cpu_change_counts[NR_CPUS][MAX_DISTANCE_REF_POINTS]; | 1153 | static u8 vphn_cpu_change_counts[NR_CPUS][MAX_DISTANCE_REF_POINTS]; |
| 1152 | static cpumask_t cpu_associativity_changes_mask; | 1154 | static cpumask_t cpu_associativity_changes_mask; |
| 1153 | static int vphn_enabled; | 1155 | static int vphn_enabled; |
| 1154 | static int prrn_enabled; | 1156 | static int prrn_enabled; |
| 1155 | static void reset_topology_timer(void); | 1157 | static void reset_topology_timer(void); |
| 1158 | static int topology_timer_secs = 1; | ||
| 1159 | static int topology_inited; | ||
| 1160 | static int topology_update_needed; | ||
| 1161 | |||
| 1162 | /* | ||
| 1163 | * Change polling interval for associativity changes. | ||
| 1164 | */ | ||
| 1165 | int timed_topology_update(int nsecs) | ||
| 1166 | { | ||
| 1167 | if (vphn_enabled) { | ||
| 1168 | if (nsecs > 0) | ||
| 1169 | topology_timer_secs = nsecs; | ||
| 1170 | else | ||
| 1171 | topology_timer_secs = TOPOLOGY_DEF_TIMER_SECS; | ||
| 1172 | |||
| 1173 | reset_topology_timer(); | ||
| 1174 | } | ||
| 1175 | |||
| 1176 | return 0; | ||
| 1177 | } | ||
| 1156 | 1178 | ||
| 1157 | /* | 1179 | /* |
| 1158 | * Store the current values of the associativity change counters in the | 1180 | * Store the current values of the associativity change counters in the |
| @@ -1246,6 +1268,11 @@ static long vphn_get_associativity(unsigned long cpu, | |||
| 1246 | "hcall_vphn() experienced a hardware fault " | 1268 | "hcall_vphn() experienced a hardware fault " |
| 1247 | "preventing VPHN. Disabling polling...\n"); | 1269 | "preventing VPHN. Disabling polling...\n"); |
| 1248 | stop_topology_update(); | 1270 | stop_topology_update(); |
| 1271 | break; | ||
| 1272 | case H_SUCCESS: | ||
| 1273 | dbg("VPHN hcall succeeded. Reset polling...\n"); | ||
| 1274 | timed_topology_update(0); | ||
| 1275 | break; | ||
| 1249 | } | 1276 | } |
| 1250 | 1277 | ||
| 1251 | return rc; | 1278 | return rc; |
| @@ -1323,8 +1350,11 @@ int numa_update_cpu_topology(bool cpus_locked) | |||
| 1323 | struct device *dev; | 1350 | struct device *dev; |
| 1324 | int weight, new_nid, i = 0; | 1351 | int weight, new_nid, i = 0; |
| 1325 | 1352 | ||
| 1326 | if (!prrn_enabled && !vphn_enabled) | 1353 | if (!prrn_enabled && !vphn_enabled) { |
| 1354 | if (!topology_inited) | ||
| 1355 | topology_update_needed = 1; | ||
| 1327 | return 0; | 1356 | return 0; |
| 1357 | } | ||
| 1328 | 1358 | ||
| 1329 | weight = cpumask_weight(&cpu_associativity_changes_mask); | 1359 | weight = cpumask_weight(&cpu_associativity_changes_mask); |
| 1330 | if (!weight) | 1360 | if (!weight) |
| @@ -1363,22 +1393,30 @@ int numa_update_cpu_topology(bool cpus_locked) | |||
| 1363 | cpumask_andnot(&cpu_associativity_changes_mask, | 1393 | cpumask_andnot(&cpu_associativity_changes_mask, |
| 1364 | &cpu_associativity_changes_mask, | 1394 | &cpu_associativity_changes_mask, |
| 1365 | cpu_sibling_mask(cpu)); | 1395 | cpu_sibling_mask(cpu)); |
| 1396 | dbg("Assoc chg gives same node %d for cpu%d\n", | ||
| 1397 | new_nid, cpu); | ||
| 1366 | cpu = cpu_last_thread_sibling(cpu); | 1398 | cpu = cpu_last_thread_sibling(cpu); |
| 1367 | continue; | 1399 | continue; |
| 1368 | } | 1400 | } |
| 1369 | 1401 | ||
| 1370 | for_each_cpu(sibling, cpu_sibling_mask(cpu)) { | 1402 | for_each_cpu(sibling, cpu_sibling_mask(cpu)) { |
| 1371 | ud = &updates[i++]; | 1403 | ud = &updates[i++]; |
| 1404 | ud->next = &updates[i]; | ||
| 1372 | ud->cpu = sibling; | 1405 | ud->cpu = sibling; |
| 1373 | ud->new_nid = new_nid; | 1406 | ud->new_nid = new_nid; |
| 1374 | ud->old_nid = numa_cpu_lookup_table[sibling]; | 1407 | ud->old_nid = numa_cpu_lookup_table[sibling]; |
| 1375 | cpumask_set_cpu(sibling, &updated_cpus); | 1408 | cpumask_set_cpu(sibling, &updated_cpus); |
| 1376 | if (i < weight) | ||
| 1377 | ud->next = &updates[i]; | ||
| 1378 | } | 1409 | } |
| 1379 | cpu = cpu_last_thread_sibling(cpu); | 1410 | cpu = cpu_last_thread_sibling(cpu); |
| 1380 | } | 1411 | } |
| 1381 | 1412 | ||
| 1413 | /* | ||
| 1414 | * Prevent processing of 'updates' from overflowing array | ||
| 1415 | * where last entry filled in a 'next' pointer. | ||
| 1416 | */ | ||
| 1417 | if (i) | ||
| 1418 | updates[i-1].next = NULL; | ||
| 1419 | |||
| 1382 | pr_debug("Topology update for the following CPUs:\n"); | 1420 | pr_debug("Topology update for the following CPUs:\n"); |
| 1383 | if (cpumask_weight(&updated_cpus)) { | 1421 | if (cpumask_weight(&updated_cpus)) { |
| 1384 | for (ud = &updates[0]; ud; ud = ud->next) { | 1422 | for (ud = &updates[0]; ud; ud = ud->next) { |
| @@ -1433,6 +1471,7 @@ int numa_update_cpu_topology(bool cpus_locked) | |||
| 1433 | 1471 | ||
| 1434 | out: | 1472 | out: |
| 1435 | kfree(updates); | 1473 | kfree(updates); |
| 1474 | topology_update_needed = 0; | ||
| 1436 | return changed; | 1475 | return changed; |
| 1437 | } | 1476 | } |
| 1438 | 1477 | ||
| @@ -1466,7 +1505,7 @@ static struct timer_list topology_timer; | |||
| 1466 | 1505 | ||
| 1467 | static void reset_topology_timer(void) | 1506 | static void reset_topology_timer(void) |
| 1468 | { | 1507 | { |
| 1469 | mod_timer(&topology_timer, jiffies + 60 * HZ); | 1508 | mod_timer(&topology_timer, jiffies + topology_timer_secs * HZ); |
| 1470 | } | 1509 | } |
| 1471 | 1510 | ||
| 1472 | #ifdef CONFIG_SMP | 1511 | #ifdef CONFIG_SMP |
| @@ -1515,15 +1554,14 @@ int start_topology_update(void) | |||
| 1515 | if (firmware_has_feature(FW_FEATURE_PRRN)) { | 1554 | if (firmware_has_feature(FW_FEATURE_PRRN)) { |
| 1516 | if (!prrn_enabled) { | 1555 | if (!prrn_enabled) { |
| 1517 | prrn_enabled = 1; | 1556 | prrn_enabled = 1; |
| 1518 | vphn_enabled = 0; | ||
| 1519 | #ifdef CONFIG_SMP | 1557 | #ifdef CONFIG_SMP |
| 1520 | rc = of_reconfig_notifier_register(&dt_update_nb); | 1558 | rc = of_reconfig_notifier_register(&dt_update_nb); |
| 1521 | #endif | 1559 | #endif |
| 1522 | } | 1560 | } |
| 1523 | } else if (firmware_has_feature(FW_FEATURE_VPHN) && | 1561 | } |
| 1562 | if (firmware_has_feature(FW_FEATURE_VPHN) && | ||
| 1524 | lppaca_shared_proc(get_lppaca())) { | 1563 | lppaca_shared_proc(get_lppaca())) { |
| 1525 | if (!vphn_enabled) { | 1564 | if (!vphn_enabled) { |
| 1526 | prrn_enabled = 0; | ||
| 1527 | vphn_enabled = 1; | 1565 | vphn_enabled = 1; |
| 1528 | setup_cpu_associativity_change_counters(); | 1566 | setup_cpu_associativity_change_counters(); |
| 1529 | timer_setup(&topology_timer, topology_timer_fn, | 1567 | timer_setup(&topology_timer, topology_timer_fn, |
| @@ -1547,7 +1585,8 @@ int stop_topology_update(void) | |||
| 1547 | #ifdef CONFIG_SMP | 1585 | #ifdef CONFIG_SMP |
| 1548 | rc = of_reconfig_notifier_unregister(&dt_update_nb); | 1586 | rc = of_reconfig_notifier_unregister(&dt_update_nb); |
| 1549 | #endif | 1587 | #endif |
| 1550 | } else if (vphn_enabled) { | 1588 | } |
| 1589 | if (vphn_enabled) { | ||
| 1551 | vphn_enabled = 0; | 1590 | vphn_enabled = 0; |
| 1552 | rc = del_timer_sync(&topology_timer); | 1591 | rc = del_timer_sync(&topology_timer); |
| 1553 | } | 1592 | } |
| @@ -1610,9 +1649,17 @@ static int topology_update_init(void) | |||
| 1610 | if (topology_updates_enabled) | 1649 | if (topology_updates_enabled) |
| 1611 | start_topology_update(); | 1650 | start_topology_update(); |
| 1612 | 1651 | ||
| 1652 | if (vphn_enabled) | ||
| 1653 | topology_schedule_update(); | ||
| 1654 | |||
| 1613 | if (!proc_create("powerpc/topology_updates", 0644, NULL, &topology_ops)) | 1655 | if (!proc_create("powerpc/topology_updates", 0644, NULL, &topology_ops)) |
| 1614 | return -ENOMEM; | 1656 | return -ENOMEM; |
| 1615 | 1657 | ||
| 1658 | topology_inited = 1; | ||
| 1659 | if (topology_update_needed) | ||
| 1660 | bitmap_fill(cpumask_bits(&cpu_associativity_changes_mask), | ||
| 1661 | nr_cpumask_bits); | ||
| 1662 | |||
| 1616 | return 0; | 1663 | return 0; |
| 1617 | } | 1664 | } |
| 1618 | device_initcall(topology_update_init); | 1665 | device_initcall(topology_update_init); |
diff --git a/arch/powerpc/mm/pgtable-radix.c b/arch/powerpc/mm/pgtable-radix.c index 39c252b54d16..cfbbee941a76 100644 --- a/arch/powerpc/mm/pgtable-radix.c +++ b/arch/powerpc/mm/pgtable-radix.c | |||
| @@ -169,6 +169,16 @@ void radix__mark_rodata_ro(void) | |||
| 169 | { | 169 | { |
| 170 | unsigned long start, end; | 170 | unsigned long start, end; |
| 171 | 171 | ||
| 172 | /* | ||
| 173 | * mark_rodata_ro() will mark itself as !writable at some point. | ||
| 174 | * Due to DD1 workaround in radix__pte_update(), we'll end up with | ||
| 175 | * an invalid pte and the system will crash quite severly. | ||
| 176 | */ | ||
| 177 | if (cpu_has_feature(CPU_FTR_POWER9_DD1)) { | ||
| 178 | pr_warn("Warning: Unable to mark rodata read only on P9 DD1\n"); | ||
| 179 | return; | ||
| 180 | } | ||
| 181 | |||
| 172 | start = (unsigned long)_stext; | 182 | start = (unsigned long)_stext; |
| 173 | end = (unsigned long)__init_begin; | 183 | end = (unsigned long)__init_begin; |
| 174 | 184 | ||
diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c index 1ec3aee43624..813ea22c3e00 100644 --- a/arch/powerpc/mm/pgtable_64.c +++ b/arch/powerpc/mm/pgtable_64.c | |||
| @@ -57,7 +57,7 @@ | |||
| 57 | 57 | ||
| 58 | #include "mmu_decl.h" | 58 | #include "mmu_decl.h" |
| 59 | 59 | ||
| 60 | #ifdef CONFIG_PPC_STD_MMU_64 | 60 | #ifdef CONFIG_PPC_BOOK3S_64 |
| 61 | #if TASK_SIZE_USER64 > (1UL << (ESID_BITS + SID_SHIFT)) | 61 | #if TASK_SIZE_USER64 > (1UL << (ESID_BITS + SID_SHIFT)) |
| 62 | #error TASK_SIZE_USER64 exceeds user VSID range | 62 | #error TASK_SIZE_USER64 exceeds user VSID range |
| 63 | #endif | 63 | #endif |
diff --git a/arch/powerpc/mm/slb_low.S b/arch/powerpc/mm/slb_low.S index 906a86fe457b..2cf5ef3fc50d 100644 --- a/arch/powerpc/mm/slb_low.S +++ b/arch/powerpc/mm/slb_low.S | |||
| @@ -167,7 +167,7 @@ END_MMU_FTR_SECTION_IFCLR(MMU_FTR_1T_SEGMENT) | |||
| 167 | /* | 167 | /* |
| 168 | * user space make sure we are within the allowed limit | 168 | * user space make sure we are within the allowed limit |
| 169 | */ | 169 | */ |
| 170 | ld r11,PACA_ADDR_LIMIT(r13) | 170 | ld r11,PACA_SLB_ADDR_LIMIT(r13) |
| 171 | cmpld r3,r11 | 171 | cmpld r3,r11 |
| 172 | bge- 8f | 172 | bge- 8f |
| 173 | 173 | ||
| @@ -309,10 +309,6 @@ slb_compare_rr_to_size: | |||
| 309 | srdi r10,r10,(SID_SHIFT_1T - SID_SHIFT) /* get 1T ESID */ | 309 | srdi r10,r10,(SID_SHIFT_1T - SID_SHIFT) /* get 1T ESID */ |
| 310 | rldimi r10,r9,ESID_BITS_1T,0 | 310 | rldimi r10,r9,ESID_BITS_1T,0 |
| 311 | ASM_VSID_SCRAMBLE(r10,r9,r11,1T) | 311 | ASM_VSID_SCRAMBLE(r10,r9,r11,1T) |
| 312 | /* | ||
| 313 | * bits above VSID_BITS_1T need to be ignored from r10 | ||
| 314 | * also combine VSID and flags | ||
| 315 | */ | ||
| 316 | 312 | ||
| 317 | li r10,MMU_SEGSIZE_1T | 313 | li r10,MMU_SEGSIZE_1T |
| 318 | rldimi r11,r10,SLB_VSID_SSIZE_SHIFT,0 /* insert segment size */ | 314 | rldimi r11,r10,SLB_VSID_SSIZE_SHIFT,0 /* insert segment size */ |
diff --git a/arch/powerpc/mm/slice.c b/arch/powerpc/mm/slice.c index 45f6740dd407..564fff06f5c1 100644 --- a/arch/powerpc/mm/slice.c +++ b/arch/powerpc/mm/slice.c | |||
| @@ -96,7 +96,7 @@ static int slice_area_is_free(struct mm_struct *mm, unsigned long addr, | |||
| 96 | { | 96 | { |
| 97 | struct vm_area_struct *vma; | 97 | struct vm_area_struct *vma; |
| 98 | 98 | ||
| 99 | if ((mm->task_size - len) < addr) | 99 | if ((mm->context.slb_addr_limit - len) < addr) |
| 100 | return 0; | 100 | return 0; |
| 101 | vma = find_vma(mm, addr); | 101 | vma = find_vma(mm, addr); |
| 102 | return (!vma || (addr + len) <= vm_start_gap(vma)); | 102 | return (!vma || (addr + len) <= vm_start_gap(vma)); |
| @@ -133,10 +133,10 @@ static void slice_mask_for_free(struct mm_struct *mm, struct slice_mask *ret) | |||
| 133 | if (!slice_low_has_vma(mm, i)) | 133 | if (!slice_low_has_vma(mm, i)) |
| 134 | ret->low_slices |= 1u << i; | 134 | ret->low_slices |= 1u << i; |
| 135 | 135 | ||
| 136 | if (mm->task_size <= SLICE_LOW_TOP) | 136 | if (mm->context.slb_addr_limit <= SLICE_LOW_TOP) |
| 137 | return; | 137 | return; |
| 138 | 138 | ||
| 139 | for (i = 0; i < GET_HIGH_SLICE_INDEX(mm->context.addr_limit); i++) | 139 | for (i = 0; i < GET_HIGH_SLICE_INDEX(mm->context.slb_addr_limit); i++) |
| 140 | if (!slice_high_has_vma(mm, i)) | 140 | if (!slice_high_has_vma(mm, i)) |
| 141 | __set_bit(i, ret->high_slices); | 141 | __set_bit(i, ret->high_slices); |
| 142 | } | 142 | } |
| @@ -157,7 +157,7 @@ static void slice_mask_for_size(struct mm_struct *mm, int psize, struct slice_ma | |||
| 157 | ret->low_slices |= 1u << i; | 157 | ret->low_slices |= 1u << i; |
| 158 | 158 | ||
| 159 | hpsizes = mm->context.high_slices_psize; | 159 | hpsizes = mm->context.high_slices_psize; |
| 160 | for (i = 0; i < GET_HIGH_SLICE_INDEX(mm->context.addr_limit); i++) { | 160 | for (i = 0; i < GET_HIGH_SLICE_INDEX(mm->context.slb_addr_limit); i++) { |
| 161 | mask_index = i & 0x1; | 161 | mask_index = i & 0x1; |
| 162 | index = i >> 1; | 162 | index = i >> 1; |
| 163 | if (((hpsizes[index] >> (mask_index * 4)) & 0xf) == psize) | 163 | if (((hpsizes[index] >> (mask_index * 4)) & 0xf) == psize) |
| @@ -169,7 +169,7 @@ static int slice_check_fit(struct mm_struct *mm, | |||
| 169 | struct slice_mask mask, struct slice_mask available) | 169 | struct slice_mask mask, struct slice_mask available) |
| 170 | { | 170 | { |
| 171 | DECLARE_BITMAP(result, SLICE_NUM_HIGH); | 171 | DECLARE_BITMAP(result, SLICE_NUM_HIGH); |
| 172 | unsigned long slice_count = GET_HIGH_SLICE_INDEX(mm->context.addr_limit); | 172 | unsigned long slice_count = GET_HIGH_SLICE_INDEX(mm->context.slb_addr_limit); |
| 173 | 173 | ||
| 174 | bitmap_and(result, mask.high_slices, | 174 | bitmap_and(result, mask.high_slices, |
| 175 | available.high_slices, slice_count); | 175 | available.high_slices, slice_count); |
| @@ -219,7 +219,7 @@ static void slice_convert(struct mm_struct *mm, struct slice_mask mask, int psiz | |||
| 219 | mm->context.low_slices_psize = lpsizes; | 219 | mm->context.low_slices_psize = lpsizes; |
| 220 | 220 | ||
| 221 | hpsizes = mm->context.high_slices_psize; | 221 | hpsizes = mm->context.high_slices_psize; |
| 222 | for (i = 0; i < GET_HIGH_SLICE_INDEX(mm->context.addr_limit); i++) { | 222 | for (i = 0; i < GET_HIGH_SLICE_INDEX(mm->context.slb_addr_limit); i++) { |
| 223 | mask_index = i & 0x1; | 223 | mask_index = i & 0x1; |
| 224 | index = i >> 1; | 224 | index = i >> 1; |
| 225 | if (test_bit(i, mask.high_slices)) | 225 | if (test_bit(i, mask.high_slices)) |
| @@ -329,8 +329,8 @@ static unsigned long slice_find_area_topdown(struct mm_struct *mm, | |||
| 329 | * Only for that request for which high_limit is above | 329 | * Only for that request for which high_limit is above |
| 330 | * DEFAULT_MAP_WINDOW we should apply this. | 330 | * DEFAULT_MAP_WINDOW we should apply this. |
| 331 | */ | 331 | */ |
| 332 | if (high_limit > DEFAULT_MAP_WINDOW) | 332 | if (high_limit > DEFAULT_MAP_WINDOW) |
| 333 | addr += mm->context.addr_limit - DEFAULT_MAP_WINDOW; | 333 | addr += mm->context.slb_addr_limit - DEFAULT_MAP_WINDOW; |
| 334 | 334 | ||
| 335 | while (addr > PAGE_SIZE) { | 335 | while (addr > PAGE_SIZE) { |
| 336 | info.high_limit = addr; | 336 | info.high_limit = addr; |
| @@ -412,25 +412,31 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len, | |||
| 412 | struct slice_mask compat_mask; | 412 | struct slice_mask compat_mask; |
| 413 | int fixed = (flags & MAP_FIXED); | 413 | int fixed = (flags & MAP_FIXED); |
| 414 | int pshift = max_t(int, mmu_psize_defs[psize].shift, PAGE_SHIFT); | 414 | int pshift = max_t(int, mmu_psize_defs[psize].shift, PAGE_SHIFT); |
| 415 | unsigned long page_size = 1UL << pshift; | ||
| 415 | struct mm_struct *mm = current->mm; | 416 | struct mm_struct *mm = current->mm; |
| 416 | unsigned long newaddr; | 417 | unsigned long newaddr; |
| 417 | unsigned long high_limit; | 418 | unsigned long high_limit; |
| 418 | 419 | ||
| 419 | /* | 420 | high_limit = DEFAULT_MAP_WINDOW; |
| 420 | * Check if we need to expland slice area. | 421 | if (addr >= high_limit || (fixed && (addr + len > high_limit))) |
| 421 | */ | 422 | high_limit = TASK_SIZE; |
| 422 | if (unlikely(addr > mm->context.addr_limit && | 423 | |
| 423 | mm->context.addr_limit != TASK_SIZE)) { | 424 | if (len > high_limit) |
| 424 | mm->context.addr_limit = TASK_SIZE; | 425 | return -ENOMEM; |
| 426 | if (len & (page_size - 1)) | ||
| 427 | return -EINVAL; | ||
| 428 | if (fixed) { | ||
| 429 | if (addr & (page_size - 1)) | ||
| 430 | return -EINVAL; | ||
| 431 | if (addr > high_limit - len) | ||
| 432 | return -ENOMEM; | ||
| 433 | } | ||
| 434 | |||
| 435 | if (high_limit > mm->context.slb_addr_limit) { | ||
| 436 | mm->context.slb_addr_limit = high_limit; | ||
| 425 | on_each_cpu(slice_flush_segments, mm, 1); | 437 | on_each_cpu(slice_flush_segments, mm, 1); |
| 426 | } | 438 | } |
| 427 | /* | 439 | |
| 428 | * This mmap request can allocate upt to 512TB | ||
| 429 | */ | ||
| 430 | if (addr > DEFAULT_MAP_WINDOW) | ||
| 431 | high_limit = mm->context.addr_limit; | ||
| 432 | else | ||
| 433 | high_limit = DEFAULT_MAP_WINDOW; | ||
| 434 | /* | 440 | /* |
| 435 | * init different masks | 441 | * init different masks |
| 436 | */ | 442 | */ |
| @@ -446,27 +452,19 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len, | |||
| 446 | 452 | ||
| 447 | /* Sanity checks */ | 453 | /* Sanity checks */ |
| 448 | BUG_ON(mm->task_size == 0); | 454 | BUG_ON(mm->task_size == 0); |
| 455 | BUG_ON(mm->context.slb_addr_limit == 0); | ||
| 449 | VM_BUG_ON(radix_enabled()); | 456 | VM_BUG_ON(radix_enabled()); |
| 450 | 457 | ||
| 451 | slice_dbg("slice_get_unmapped_area(mm=%p, psize=%d...\n", mm, psize); | 458 | slice_dbg("slice_get_unmapped_area(mm=%p, psize=%d...\n", mm, psize); |
| 452 | slice_dbg(" addr=%lx, len=%lx, flags=%lx, topdown=%d\n", | 459 | slice_dbg(" addr=%lx, len=%lx, flags=%lx, topdown=%d\n", |
| 453 | addr, len, flags, topdown); | 460 | addr, len, flags, topdown); |
| 454 | 461 | ||
| 455 | if (len > mm->task_size) | ||
| 456 | return -ENOMEM; | ||
| 457 | if (len & ((1ul << pshift) - 1)) | ||
| 458 | return -EINVAL; | ||
| 459 | if (fixed && (addr & ((1ul << pshift) - 1))) | ||
| 460 | return -EINVAL; | ||
| 461 | if (fixed && addr > (mm->task_size - len)) | ||
| 462 | return -ENOMEM; | ||
| 463 | |||
| 464 | /* If hint, make sure it matches our alignment restrictions */ | 462 | /* If hint, make sure it matches our alignment restrictions */ |
| 465 | if (!fixed && addr) { | 463 | if (!fixed && addr) { |
| 466 | addr = _ALIGN_UP(addr, 1ul << pshift); | 464 | addr = _ALIGN_UP(addr, page_size); |
| 467 | slice_dbg(" aligned addr=%lx\n", addr); | 465 | slice_dbg(" aligned addr=%lx\n", addr); |
| 468 | /* Ignore hint if it's too large or overlaps a VMA */ | 466 | /* Ignore hint if it's too large or overlaps a VMA */ |
| 469 | if (addr > mm->task_size - len || | 467 | if (addr > high_limit - len || |
| 470 | !slice_area_is_free(mm, addr, len)) | 468 | !slice_area_is_free(mm, addr, len)) |
| 471 | addr = 0; | 469 | addr = 0; |
| 472 | } | 470 | } |
diff --git a/arch/powerpc/mm/tlb-radix.c b/arch/powerpc/mm/tlb-radix.c index d304028641a2..884f4b705b57 100644 --- a/arch/powerpc/mm/tlb-radix.c +++ b/arch/powerpc/mm/tlb-radix.c | |||
| @@ -39,6 +39,20 @@ static inline void __tlbiel_pid(unsigned long pid, int set, | |||
| 39 | trace_tlbie(0, 1, rb, rs, ric, prs, r); | 39 | trace_tlbie(0, 1, rb, rs, ric, prs, r); |
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | static inline void __tlbie_pid(unsigned long pid, unsigned long ric) | ||
| 43 | { | ||
| 44 | unsigned long rb,rs,prs,r; | ||
| 45 | |||
| 46 | rb = PPC_BIT(53); /* IS = 1 */ | ||
| 47 | rs = pid << PPC_BITLSHIFT(31); | ||
| 48 | prs = 1; /* process scoped */ | ||
| 49 | r = 1; /* raidx format */ | ||
| 50 | |||
| 51 | asm volatile(PPC_TLBIE_5(%0, %4, %3, %2, %1) | ||
| 52 | : : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : "memory"); | ||
| 53 | trace_tlbie(0, 0, rb, rs, ric, prs, r); | ||
| 54 | } | ||
| 55 | |||
| 42 | /* | 56 | /* |
| 43 | * We use 128 set in radix mode and 256 set in hpt mode. | 57 | * We use 128 set in radix mode and 256 set in hpt mode. |
| 44 | */ | 58 | */ |
| @@ -70,22 +84,13 @@ static inline void _tlbiel_pid(unsigned long pid, unsigned long ric) | |||
| 70 | 84 | ||
| 71 | static inline void _tlbie_pid(unsigned long pid, unsigned long ric) | 85 | static inline void _tlbie_pid(unsigned long pid, unsigned long ric) |
| 72 | { | 86 | { |
| 73 | unsigned long rb,rs,prs,r; | ||
| 74 | |||
| 75 | rb = PPC_BIT(53); /* IS = 1 */ | ||
| 76 | rs = pid << PPC_BITLSHIFT(31); | ||
| 77 | prs = 1; /* process scoped */ | ||
| 78 | r = 1; /* raidx format */ | ||
| 79 | |||
| 80 | asm volatile("ptesync": : :"memory"); | 87 | asm volatile("ptesync": : :"memory"); |
| 81 | asm volatile(PPC_TLBIE_5(%0, %4, %3, %2, %1) | 88 | __tlbie_pid(pid, ric); |
| 82 | : : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : "memory"); | ||
| 83 | asm volatile("eieio; tlbsync; ptesync": : :"memory"); | 89 | asm volatile("eieio; tlbsync; ptesync": : :"memory"); |
| 84 | trace_tlbie(0, 0, rb, rs, ric, prs, r); | ||
| 85 | } | 90 | } |
| 86 | 91 | ||
| 87 | static inline void _tlbiel_va(unsigned long va, unsigned long pid, | 92 | static inline void __tlbiel_va(unsigned long va, unsigned long pid, |
| 88 | unsigned long ap, unsigned long ric) | 93 | unsigned long ap, unsigned long ric) |
| 89 | { | 94 | { |
| 90 | unsigned long rb,rs,prs,r; | 95 | unsigned long rb,rs,prs,r; |
| 91 | 96 | ||
| @@ -95,14 +100,44 @@ static inline void _tlbiel_va(unsigned long va, unsigned long pid, | |||
| 95 | prs = 1; /* process scoped */ | 100 | prs = 1; /* process scoped */ |
| 96 | r = 1; /* raidx format */ | 101 | r = 1; /* raidx format */ |
| 97 | 102 | ||
| 98 | asm volatile("ptesync": : :"memory"); | ||
| 99 | asm volatile(PPC_TLBIEL(%0, %4, %3, %2, %1) | 103 | asm volatile(PPC_TLBIEL(%0, %4, %3, %2, %1) |
| 100 | : : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : "memory"); | 104 | : : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : "memory"); |
| 101 | asm volatile("ptesync": : :"memory"); | ||
| 102 | trace_tlbie(0, 1, rb, rs, ric, prs, r); | 105 | trace_tlbie(0, 1, rb, rs, ric, prs, r); |
| 103 | } | 106 | } |
| 104 | 107 | ||
| 105 | static inline void _tlbie_va(unsigned long va, unsigned long pid, | 108 | static inline void __tlbiel_va_range(unsigned long start, unsigned long end, |
| 109 | unsigned long pid, unsigned long page_size, | ||
| 110 | unsigned long psize) | ||
| 111 | { | ||
| 112 | unsigned long addr; | ||
| 113 | unsigned long ap = mmu_get_ap(psize); | ||
| 114 | |||
| 115 | for (addr = start; addr < end; addr += page_size) | ||
| 116 | __tlbiel_va(addr, pid, ap, RIC_FLUSH_TLB); | ||
| 117 | } | ||
| 118 | |||
| 119 | static inline void _tlbiel_va(unsigned long va, unsigned long pid, | ||
| 120 | unsigned long psize, unsigned long ric) | ||
| 121 | { | ||
| 122 | unsigned long ap = mmu_get_ap(psize); | ||
| 123 | |||
| 124 | asm volatile("ptesync": : :"memory"); | ||
| 125 | __tlbiel_va(va, pid, ap, ric); | ||
| 126 | asm volatile("ptesync": : :"memory"); | ||
| 127 | } | ||
| 128 | |||
| 129 | static inline void _tlbiel_va_range(unsigned long start, unsigned long end, | ||
| 130 | unsigned long pid, unsigned long page_size, | ||
| 131 | unsigned long psize, bool also_pwc) | ||
| 132 | { | ||
| 133 | asm volatile("ptesync": : :"memory"); | ||
| 134 | if (also_pwc) | ||
| 135 | __tlbiel_pid(pid, 0, RIC_FLUSH_PWC); | ||
| 136 | __tlbiel_va_range(start, end, pid, page_size, psize); | ||
| 137 | asm volatile("ptesync": : :"memory"); | ||
| 138 | } | ||
| 139 | |||
| 140 | static inline void __tlbie_va(unsigned long va, unsigned long pid, | ||
| 106 | unsigned long ap, unsigned long ric) | 141 | unsigned long ap, unsigned long ric) |
| 107 | { | 142 | { |
| 108 | unsigned long rb,rs,prs,r; | 143 | unsigned long rb,rs,prs,r; |
| @@ -113,13 +148,43 @@ static inline void _tlbie_va(unsigned long va, unsigned long pid, | |||
| 113 | prs = 1; /* process scoped */ | 148 | prs = 1; /* process scoped */ |
| 114 | r = 1; /* raidx format */ | 149 | r = 1; /* raidx format */ |
| 115 | 150 | ||
| 116 | asm volatile("ptesync": : :"memory"); | ||
| 117 | asm volatile(PPC_TLBIE_5(%0, %4, %3, %2, %1) | 151 | asm volatile(PPC_TLBIE_5(%0, %4, %3, %2, %1) |
| 118 | : : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : "memory"); | 152 | : : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : "memory"); |
| 119 | asm volatile("eieio; tlbsync; ptesync": : :"memory"); | ||
| 120 | trace_tlbie(0, 0, rb, rs, ric, prs, r); | 153 | trace_tlbie(0, 0, rb, rs, ric, prs, r); |
| 121 | } | 154 | } |
| 122 | 155 | ||
| 156 | static inline void __tlbie_va_range(unsigned long start, unsigned long end, | ||
| 157 | unsigned long pid, unsigned long page_size, | ||
| 158 | unsigned long psize) | ||
| 159 | { | ||
| 160 | unsigned long addr; | ||
| 161 | unsigned long ap = mmu_get_ap(psize); | ||
| 162 | |||
| 163 | for (addr = start; addr < end; addr += page_size) | ||
| 164 | __tlbie_va(addr, pid, ap, RIC_FLUSH_TLB); | ||
| 165 | } | ||
| 166 | |||
| 167 | static inline void _tlbie_va(unsigned long va, unsigned long pid, | ||
| 168 | unsigned long psize, unsigned long ric) | ||
| 169 | { | ||
| 170 | unsigned long ap = mmu_get_ap(psize); | ||
| 171 | |||
| 172 | asm volatile("ptesync": : :"memory"); | ||
| 173 | __tlbie_va(va, pid, ap, ric); | ||
| 174 | asm volatile("eieio; tlbsync; ptesync": : :"memory"); | ||
| 175 | } | ||
| 176 | |||
| 177 | static inline void _tlbie_va_range(unsigned long start, unsigned long end, | ||
| 178 | unsigned long pid, unsigned long page_size, | ||
| 179 | unsigned long psize, bool also_pwc) | ||
| 180 | { | ||
| 181 | asm volatile("ptesync": : :"memory"); | ||
| 182 | if (also_pwc) | ||
| 183 | __tlbie_pid(pid, RIC_FLUSH_PWC); | ||
| 184 | __tlbie_va_range(start, end, pid, page_size, psize); | ||
| 185 | asm volatile("eieio; tlbsync; ptesync": : :"memory"); | ||
| 186 | } | ||
| 187 | |||
| 123 | /* | 188 | /* |
| 124 | * Base TLB flushing operations: | 189 | * Base TLB flushing operations: |
| 125 | * | 190 | * |
| @@ -144,7 +209,7 @@ void radix__local_flush_tlb_mm(struct mm_struct *mm) | |||
| 144 | EXPORT_SYMBOL(radix__local_flush_tlb_mm); | 209 | EXPORT_SYMBOL(radix__local_flush_tlb_mm); |
| 145 | 210 | ||
| 146 | #ifndef CONFIG_SMP | 211 | #ifndef CONFIG_SMP |
| 147 | static void radix__local_flush_all_mm(struct mm_struct *mm) | 212 | void radix__local_flush_all_mm(struct mm_struct *mm) |
| 148 | { | 213 | { |
| 149 | unsigned long pid; | 214 | unsigned long pid; |
| 150 | 215 | ||
| @@ -154,18 +219,18 @@ static void radix__local_flush_all_mm(struct mm_struct *mm) | |||
| 154 | _tlbiel_pid(pid, RIC_FLUSH_ALL); | 219 | _tlbiel_pid(pid, RIC_FLUSH_ALL); |
| 155 | preempt_enable(); | 220 | preempt_enable(); |
| 156 | } | 221 | } |
| 222 | EXPORT_SYMBOL(radix__local_flush_all_mm); | ||
| 157 | #endif /* CONFIG_SMP */ | 223 | #endif /* CONFIG_SMP */ |
| 158 | 224 | ||
| 159 | void radix__local_flush_tlb_page_psize(struct mm_struct *mm, unsigned long vmaddr, | 225 | void radix__local_flush_tlb_page_psize(struct mm_struct *mm, unsigned long vmaddr, |
| 160 | int psize) | 226 | int psize) |
| 161 | { | 227 | { |
| 162 | unsigned long pid; | 228 | unsigned long pid; |
| 163 | unsigned long ap = mmu_get_ap(psize); | ||
| 164 | 229 | ||
| 165 | preempt_disable(); | 230 | preempt_disable(); |
| 166 | pid = mm ? mm->context.id : 0; | 231 | pid = mm->context.id; |
| 167 | if (pid != MMU_NO_CONTEXT) | 232 | if (pid != MMU_NO_CONTEXT) |
| 168 | _tlbiel_va(vmaddr, pid, ap, RIC_FLUSH_TLB); | 233 | _tlbiel_va(vmaddr, pid, psize, RIC_FLUSH_TLB); |
| 169 | preempt_enable(); | 234 | preempt_enable(); |
| 170 | } | 235 | } |
| 171 | 236 | ||
| @@ -173,11 +238,10 @@ void radix__local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmadd | |||
| 173 | { | 238 | { |
| 174 | #ifdef CONFIG_HUGETLB_PAGE | 239 | #ifdef CONFIG_HUGETLB_PAGE |
| 175 | /* need the return fix for nohash.c */ | 240 | /* need the return fix for nohash.c */ |
| 176 | if (vma && is_vm_hugetlb_page(vma)) | 241 | if (is_vm_hugetlb_page(vma)) |
| 177 | return __local_flush_hugetlb_page(vma, vmaddr); | 242 | return radix__local_flush_hugetlb_page(vma, vmaddr); |
| 178 | #endif | 243 | #endif |
| 179 | radix__local_flush_tlb_page_psize(vma ? vma->vm_mm : NULL, vmaddr, | 244 | radix__local_flush_tlb_page_psize(vma->vm_mm, vmaddr, mmu_virtual_psize); |
| 180 | mmu_virtual_psize); | ||
| 181 | } | 245 | } |
| 182 | EXPORT_SYMBOL(radix__local_flush_tlb_page); | 246 | EXPORT_SYMBOL(radix__local_flush_tlb_page); |
| 183 | 247 | ||
| @@ -186,36 +250,35 @@ void radix__flush_tlb_mm(struct mm_struct *mm) | |||
| 186 | { | 250 | { |
| 187 | unsigned long pid; | 251 | unsigned long pid; |
| 188 | 252 | ||
| 189 | preempt_disable(); | ||
| 190 | pid = mm->context.id; | 253 | pid = mm->context.id; |
| 191 | if (unlikely(pid == MMU_NO_CONTEXT)) | 254 | if (unlikely(pid == MMU_NO_CONTEXT)) |
| 192 | goto no_context; | 255 | return; |
| 193 | 256 | ||
| 257 | preempt_disable(); | ||
| 194 | if (!mm_is_thread_local(mm)) | 258 | if (!mm_is_thread_local(mm)) |
| 195 | _tlbie_pid(pid, RIC_FLUSH_TLB); | 259 | _tlbie_pid(pid, RIC_FLUSH_TLB); |
| 196 | else | 260 | else |
| 197 | _tlbiel_pid(pid, RIC_FLUSH_TLB); | 261 | _tlbiel_pid(pid, RIC_FLUSH_TLB); |
| 198 | no_context: | ||
| 199 | preempt_enable(); | 262 | preempt_enable(); |
| 200 | } | 263 | } |
| 201 | EXPORT_SYMBOL(radix__flush_tlb_mm); | 264 | EXPORT_SYMBOL(radix__flush_tlb_mm); |
| 202 | 265 | ||
| 203 | static void radix__flush_all_mm(struct mm_struct *mm) | 266 | void radix__flush_all_mm(struct mm_struct *mm) |
| 204 | { | 267 | { |
| 205 | unsigned long pid; | 268 | unsigned long pid; |
| 206 | 269 | ||
| 207 | preempt_disable(); | ||
| 208 | pid = mm->context.id; | 270 | pid = mm->context.id; |
| 209 | if (unlikely(pid == MMU_NO_CONTEXT)) | 271 | if (unlikely(pid == MMU_NO_CONTEXT)) |
| 210 | goto no_context; | 272 | return; |
| 211 | 273 | ||
| 274 | preempt_disable(); | ||
| 212 | if (!mm_is_thread_local(mm)) | 275 | if (!mm_is_thread_local(mm)) |
| 213 | _tlbie_pid(pid, RIC_FLUSH_ALL); | 276 | _tlbie_pid(pid, RIC_FLUSH_ALL); |
| 214 | else | 277 | else |
| 215 | _tlbiel_pid(pid, RIC_FLUSH_ALL); | 278 | _tlbiel_pid(pid, RIC_FLUSH_ALL); |
| 216 | no_context: | ||
| 217 | preempt_enable(); | 279 | preempt_enable(); |
| 218 | } | 280 | } |
| 281 | EXPORT_SYMBOL(radix__flush_all_mm); | ||
| 219 | 282 | ||
| 220 | void radix__flush_tlb_pwc(struct mmu_gather *tlb, unsigned long addr) | 283 | void radix__flush_tlb_pwc(struct mmu_gather *tlb, unsigned long addr) |
| 221 | { | 284 | { |
| @@ -227,28 +290,26 @@ void radix__flush_tlb_page_psize(struct mm_struct *mm, unsigned long vmaddr, | |||
| 227 | int psize) | 290 | int psize) |
| 228 | { | 291 | { |
| 229 | unsigned long pid; | 292 | unsigned long pid; |
| 230 | unsigned long ap = mmu_get_ap(psize); | ||
| 231 | 293 | ||
| 232 | preempt_disable(); | 294 | pid = mm->context.id; |
| 233 | pid = mm ? mm->context.id : 0; | ||
| 234 | if (unlikely(pid == MMU_NO_CONTEXT)) | 295 | if (unlikely(pid == MMU_NO_CONTEXT)) |
| 235 | goto bail; | 296 | return; |
| 297 | |||
| 298 | preempt_disable(); | ||
| 236 | if (!mm_is_thread_local(mm)) | 299 | if (!mm_is_thread_local(mm)) |
| 237 | _tlbie_va(vmaddr, pid, ap, RIC_FLUSH_TLB); | 300 | _tlbie_va(vmaddr, pid, psize, RIC_FLUSH_TLB); |
| 238 | else | 301 | else |
| 239 | _tlbiel_va(vmaddr, pid, ap, RIC_FLUSH_TLB); | 302 | _tlbiel_va(vmaddr, pid, psize, RIC_FLUSH_TLB); |
| 240 | bail: | ||
| 241 | preempt_enable(); | 303 | preempt_enable(); |
| 242 | } | 304 | } |
| 243 | 305 | ||
| 244 | void radix__flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr) | 306 | void radix__flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr) |
| 245 | { | 307 | { |
| 246 | #ifdef CONFIG_HUGETLB_PAGE | 308 | #ifdef CONFIG_HUGETLB_PAGE |
| 247 | if (vma && is_vm_hugetlb_page(vma)) | 309 | if (is_vm_hugetlb_page(vma)) |
| 248 | return flush_hugetlb_page(vma, vmaddr); | 310 | return radix__flush_hugetlb_page(vma, vmaddr); |
| 249 | #endif | 311 | #endif |
| 250 | radix__flush_tlb_page_psize(vma ? vma->vm_mm : NULL, vmaddr, | 312 | radix__flush_tlb_page_psize(vma->vm_mm, vmaddr, mmu_virtual_psize); |
| 251 | mmu_virtual_psize); | ||
| 252 | } | 313 | } |
| 253 | EXPORT_SYMBOL(radix__flush_tlb_page); | 314 | EXPORT_SYMBOL(radix__flush_tlb_page); |
| 254 | 315 | ||
| @@ -262,17 +323,86 @@ void radix__flush_tlb_kernel_range(unsigned long start, unsigned long end) | |||
| 262 | } | 323 | } |
| 263 | EXPORT_SYMBOL(radix__flush_tlb_kernel_range); | 324 | EXPORT_SYMBOL(radix__flush_tlb_kernel_range); |
| 264 | 325 | ||
| 326 | #define TLB_FLUSH_ALL -1UL | ||
| 327 | |||
| 265 | /* | 328 | /* |
| 266 | * Currently, for range flushing, we just do a full mm flush. Because | 329 | * Number of pages above which we invalidate the entire PID rather than |
| 267 | * we use this in code path where we don' track the page size. | 330 | * flush individual pages, for local and global flushes respectively. |
| 331 | * | ||
| 332 | * tlbie goes out to the interconnect and individual ops are more costly. | ||
| 333 | * It also does not iterate over sets like the local tlbiel variant when | ||
| 334 | * invalidating a full PID, so it has a far lower threshold to change from | ||
| 335 | * individual page flushes to full-pid flushes. | ||
| 268 | */ | 336 | */ |
| 337 | static unsigned long tlb_single_page_flush_ceiling __read_mostly = 33; | ||
| 338 | static unsigned long tlb_local_single_page_flush_ceiling __read_mostly = POWER9_TLB_SETS_RADIX * 2; | ||
| 339 | |||
| 269 | void radix__flush_tlb_range(struct vm_area_struct *vma, unsigned long start, | 340 | void radix__flush_tlb_range(struct vm_area_struct *vma, unsigned long start, |
| 270 | unsigned long end) | 341 | unsigned long end) |
| 271 | 342 | ||
| 272 | { | 343 | { |
| 273 | struct mm_struct *mm = vma->vm_mm; | 344 | struct mm_struct *mm = vma->vm_mm; |
| 345 | unsigned long pid; | ||
| 346 | unsigned int page_shift = mmu_psize_defs[mmu_virtual_psize].shift; | ||
| 347 | unsigned long page_size = 1UL << page_shift; | ||
| 348 | unsigned long nr_pages = (end - start) >> page_shift; | ||
| 349 | bool local, full; | ||
| 350 | |||
| 351 | #ifdef CONFIG_HUGETLB_PAGE | ||
| 352 | if (is_vm_hugetlb_page(vma)) | ||
| 353 | return radix__flush_hugetlb_tlb_range(vma, start, end); | ||
| 354 | #endif | ||
| 355 | |||
| 356 | pid = mm->context.id; | ||
| 357 | if (unlikely(pid == MMU_NO_CONTEXT)) | ||
| 358 | return; | ||
| 274 | 359 | ||
| 275 | radix__flush_tlb_mm(mm); | 360 | preempt_disable(); |
| 361 | if (mm_is_thread_local(mm)) { | ||
| 362 | local = true; | ||
| 363 | full = (end == TLB_FLUSH_ALL || | ||
| 364 | nr_pages > tlb_local_single_page_flush_ceiling); | ||
| 365 | } else { | ||
| 366 | local = false; | ||
| 367 | full = (end == TLB_FLUSH_ALL || | ||
| 368 | nr_pages > tlb_single_page_flush_ceiling); | ||
| 369 | } | ||
| 370 | |||
| 371 | if (full) { | ||
| 372 | if (local) | ||
| 373 | _tlbiel_pid(pid, RIC_FLUSH_TLB); | ||
| 374 | else | ||
| 375 | _tlbie_pid(pid, RIC_FLUSH_TLB); | ||
| 376 | } else { | ||
| 377 | bool hflush = false; | ||
| 378 | unsigned long hstart, hend; | ||
| 379 | |||
| 380 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE | ||
| 381 | hstart = (start + HPAGE_PMD_SIZE - 1) >> HPAGE_PMD_SHIFT; | ||
| 382 | hend = end >> HPAGE_PMD_SHIFT; | ||
| 383 | if (hstart < hend) { | ||
| 384 | hstart <<= HPAGE_PMD_SHIFT; | ||
| 385 | hend <<= HPAGE_PMD_SHIFT; | ||
| 386 | hflush = true; | ||
| 387 | } | ||
| 388 | #endif | ||
| 389 | |||
| 390 | asm volatile("ptesync": : :"memory"); | ||
| 391 | if (local) { | ||
| 392 | __tlbiel_va_range(start, end, pid, page_size, mmu_virtual_psize); | ||
| 393 | if (hflush) | ||
| 394 | __tlbiel_va_range(hstart, hend, pid, | ||
| 395 | HPAGE_PMD_SIZE, MMU_PAGE_2M); | ||
| 396 | asm volatile("ptesync": : :"memory"); | ||
| 397 | } else { | ||
| 398 | __tlbie_va_range(start, end, pid, page_size, mmu_virtual_psize); | ||
| 399 | if (hflush) | ||
| 400 | __tlbie_va_range(hstart, hend, pid, | ||
| 401 | HPAGE_PMD_SIZE, MMU_PAGE_2M); | ||
| 402 | asm volatile("eieio; tlbsync; ptesync": : :"memory"); | ||
| 403 | } | ||
| 404 | } | ||
| 405 | preempt_enable(); | ||
| 276 | } | 406 | } |
| 277 | EXPORT_SYMBOL(radix__flush_tlb_range); | 407 | EXPORT_SYMBOL(radix__flush_tlb_range); |
| 278 | 408 | ||
| @@ -291,101 +421,118 @@ static int radix_get_mmu_psize(int page_size) | |||
| 291 | return psize; | 421 | return psize; |
| 292 | } | 422 | } |
| 293 | 423 | ||
| 424 | static void radix__flush_tlb_pwc_range_psize(struct mm_struct *mm, unsigned long start, | ||
| 425 | unsigned long end, int psize); | ||
| 426 | |||
| 294 | void radix__tlb_flush(struct mmu_gather *tlb) | 427 | void radix__tlb_flush(struct mmu_gather *tlb) |
| 295 | { | 428 | { |
| 296 | int psize = 0; | 429 | int psize = 0; |
| 297 | struct mm_struct *mm = tlb->mm; | 430 | struct mm_struct *mm = tlb->mm; |
| 298 | int page_size = tlb->page_size; | 431 | int page_size = tlb->page_size; |
| 299 | 432 | ||
| 300 | psize = radix_get_mmu_psize(page_size); | ||
| 301 | /* | 433 | /* |
| 302 | * if page size is not something we understand, do a full mm flush | 434 | * if page size is not something we understand, do a full mm flush |
| 435 | * | ||
| 436 | * A "fullmm" flush must always do a flush_all_mm (RIC=2) flush | ||
| 437 | * that flushes the process table entry cache upon process teardown. | ||
| 438 | * See the comment for radix in arch_exit_mmap(). | ||
| 303 | */ | 439 | */ |
| 304 | if (psize != -1 && !tlb->fullmm && !tlb->need_flush_all) | 440 | if (tlb->fullmm) { |
| 305 | radix__flush_tlb_range_psize(mm, tlb->start, tlb->end, psize); | ||
| 306 | else if (tlb->need_flush_all) { | ||
| 307 | tlb->need_flush_all = 0; | ||
| 308 | radix__flush_all_mm(mm); | 441 | radix__flush_all_mm(mm); |
| 309 | } else | 442 | } else if ( (psize = radix_get_mmu_psize(page_size)) == -1) { |
| 310 | radix__flush_tlb_mm(mm); | 443 | if (!tlb->need_flush_all) |
| 311 | } | 444 | radix__flush_tlb_mm(mm); |
| 445 | else | ||
| 446 | radix__flush_all_mm(mm); | ||
| 447 | } else { | ||
| 448 | unsigned long start = tlb->start; | ||
| 449 | unsigned long end = tlb->end; | ||
| 312 | 450 | ||
| 313 | #define TLB_FLUSH_ALL -1UL | 451 | if (!tlb->need_flush_all) |
| 314 | /* | 452 | radix__flush_tlb_range_psize(mm, start, end, psize); |
| 315 | * Number of pages above which we will do a bcast tlbie. Just a | 453 | else |
| 316 | * number at this point copied from x86 | 454 | radix__flush_tlb_pwc_range_psize(mm, start, end, psize); |
| 317 | */ | 455 | } |
| 318 | static unsigned long tlb_single_page_flush_ceiling __read_mostly = 33; | 456 | tlb->need_flush_all = 0; |
| 457 | } | ||
| 319 | 458 | ||
| 320 | void radix__flush_tlb_range_psize(struct mm_struct *mm, unsigned long start, | 459 | static inline void __radix__flush_tlb_range_psize(struct mm_struct *mm, |
| 321 | unsigned long end, int psize) | 460 | unsigned long start, unsigned long end, |
| 461 | int psize, bool also_pwc) | ||
| 322 | { | 462 | { |
| 323 | unsigned long pid; | 463 | unsigned long pid; |
| 324 | unsigned long addr; | 464 | unsigned int page_shift = mmu_psize_defs[psize].shift; |
| 325 | int local = mm_is_thread_local(mm); | 465 | unsigned long page_size = 1UL << page_shift; |
| 326 | unsigned long ap = mmu_get_ap(psize); | 466 | unsigned long nr_pages = (end - start) >> page_shift; |
| 327 | unsigned long page_size = 1UL << mmu_psize_defs[psize].shift; | 467 | bool local, full; |
| 328 | 468 | ||
| 469 | pid = mm->context.id; | ||
| 470 | if (unlikely(pid == MMU_NO_CONTEXT)) | ||
| 471 | return; | ||
| 329 | 472 | ||
| 330 | preempt_disable(); | 473 | preempt_disable(); |
| 331 | pid = mm ? mm->context.id : 0; | 474 | if (mm_is_thread_local(mm)) { |
| 332 | if (unlikely(pid == MMU_NO_CONTEXT)) | 475 | local = true; |
| 333 | goto err_out; | 476 | full = (end == TLB_FLUSH_ALL || |
| 477 | nr_pages > tlb_local_single_page_flush_ceiling); | ||
| 478 | } else { | ||
| 479 | local = false; | ||
| 480 | full = (end == TLB_FLUSH_ALL || | ||
| 481 | nr_pages > tlb_single_page_flush_ceiling); | ||
| 482 | } | ||
| 334 | 483 | ||
| 335 | if (end == TLB_FLUSH_ALL || | 484 | if (full) { |
| 336 | (end - start) > tlb_single_page_flush_ceiling * page_size) { | ||
| 337 | if (local) | 485 | if (local) |
| 338 | _tlbiel_pid(pid, RIC_FLUSH_TLB); | 486 | _tlbiel_pid(pid, also_pwc ? RIC_FLUSH_ALL : RIC_FLUSH_TLB); |
| 339 | else | 487 | else |
| 340 | _tlbie_pid(pid, RIC_FLUSH_TLB); | 488 | _tlbie_pid(pid, also_pwc ? RIC_FLUSH_ALL: RIC_FLUSH_TLB); |
| 341 | goto err_out; | 489 | } else { |
| 342 | } | ||
| 343 | for (addr = start; addr < end; addr += page_size) { | ||
| 344 | |||
| 345 | if (local) | 490 | if (local) |
| 346 | _tlbiel_va(addr, pid, ap, RIC_FLUSH_TLB); | 491 | _tlbiel_va_range(start, end, pid, page_size, psize, also_pwc); |
| 347 | else | 492 | else |
| 348 | _tlbie_va(addr, pid, ap, RIC_FLUSH_TLB); | 493 | _tlbie_va_range(start, end, pid, page_size, psize, also_pwc); |
| 349 | } | 494 | } |
| 350 | err_out: | ||
| 351 | preempt_enable(); | 495 | preempt_enable(); |
| 352 | } | 496 | } |
| 353 | 497 | ||
| 498 | void radix__flush_tlb_range_psize(struct mm_struct *mm, unsigned long start, | ||
| 499 | unsigned long end, int psize) | ||
| 500 | { | ||
| 501 | return __radix__flush_tlb_range_psize(mm, start, end, psize, false); | ||
| 502 | } | ||
| 503 | |||
| 504 | static void radix__flush_tlb_pwc_range_psize(struct mm_struct *mm, unsigned long start, | ||
| 505 | unsigned long end, int psize) | ||
| 506 | { | ||
| 507 | __radix__flush_tlb_range_psize(mm, start, end, psize, true); | ||
| 508 | } | ||
| 509 | |||
| 354 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE | 510 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE |
| 355 | void radix__flush_tlb_collapsed_pmd(struct mm_struct *mm, unsigned long addr) | 511 | void radix__flush_tlb_collapsed_pmd(struct mm_struct *mm, unsigned long addr) |
| 356 | { | 512 | { |
| 357 | int local = mm_is_thread_local(mm); | ||
| 358 | unsigned long ap = mmu_get_ap(mmu_virtual_psize); | ||
| 359 | unsigned long pid, end; | 513 | unsigned long pid, end; |
| 360 | 514 | ||
| 361 | 515 | pid = mm->context.id; | |
| 362 | pid = mm ? mm->context.id : 0; | ||
| 363 | preempt_disable(); | ||
| 364 | if (unlikely(pid == MMU_NO_CONTEXT)) | 516 | if (unlikely(pid == MMU_NO_CONTEXT)) |
| 365 | goto no_context; | 517 | return; |
| 366 | 518 | ||
| 367 | /* 4k page size, just blow the world */ | 519 | /* 4k page size, just blow the world */ |
| 368 | if (PAGE_SIZE == 0x1000) { | 520 | if (PAGE_SIZE == 0x1000) { |
| 369 | radix__flush_all_mm(mm); | 521 | radix__flush_all_mm(mm); |
| 370 | preempt_enable(); | ||
| 371 | return; | 522 | return; |
| 372 | } | 523 | } |
| 373 | 524 | ||
| 374 | /* Otherwise first do the PWC */ | ||
| 375 | if (local) | ||
| 376 | _tlbiel_pid(pid, RIC_FLUSH_PWC); | ||
| 377 | else | ||
| 378 | _tlbie_pid(pid, RIC_FLUSH_PWC); | ||
| 379 | |||
| 380 | /* Then iterate the pages */ | ||
| 381 | end = addr + HPAGE_PMD_SIZE; | 525 | end = addr + HPAGE_PMD_SIZE; |
| 382 | for (; addr < end; addr += PAGE_SIZE) { | 526 | |
| 383 | if (local) | 527 | /* Otherwise first do the PWC, then iterate the pages. */ |
| 384 | _tlbiel_va(addr, pid, ap, RIC_FLUSH_TLB); | 528 | preempt_disable(); |
| 385 | else | 529 | |
| 386 | _tlbie_va(addr, pid, ap, RIC_FLUSH_TLB); | 530 | if (mm_is_thread_local(mm)) { |
| 531 | _tlbiel_va_range(addr, end, pid, PAGE_SIZE, mmu_virtual_psize, true); | ||
| 532 | } else { | ||
| 533 | _tlbie_va_range(addr, end, pid, PAGE_SIZE, mmu_virtual_psize, true); | ||
| 387 | } | 534 | } |
| 388 | no_context: | 535 | |
| 389 | preempt_enable(); | 536 | preempt_enable(); |
| 390 | } | 537 | } |
| 391 | #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ | 538 | #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ |
diff --git a/arch/powerpc/net/bpf_jit64.h b/arch/powerpc/net/bpf_jit64.h index 62fa7589db2b..8bdef7ed28a8 100644 --- a/arch/powerpc/net/bpf_jit64.h +++ b/arch/powerpc/net/bpf_jit64.h | |||
| @@ -23,7 +23,7 @@ | |||
| 23 | * [ nv gpr save area ] 8*8 | | 23 | * [ nv gpr save area ] 8*8 | |
| 24 | * [ tail_call_cnt ] 8 | | 24 | * [ tail_call_cnt ] 8 | |
| 25 | * [ local_tmp_var ] 8 | | 25 | * [ local_tmp_var ] 8 | |
| 26 | * fp (r31) --> [ ebpf stack space ] 512 | | 26 | * fp (r31) --> [ ebpf stack space ] upto 512 | |
| 27 | * [ frame header ] 32/112 | | 27 | * [ frame header ] 32/112 | |
| 28 | * sp (r1) ---> [ stack pointer ] -------------- | 28 | * sp (r1) ---> [ stack pointer ] -------------- |
| 29 | */ | 29 | */ |
| @@ -32,8 +32,8 @@ | |||
| 32 | #define BPF_PPC_STACK_SAVE (8*8) | 32 | #define BPF_PPC_STACK_SAVE (8*8) |
| 33 | /* for bpf JIT code internal usage */ | 33 | /* for bpf JIT code internal usage */ |
| 34 | #define BPF_PPC_STACK_LOCALS 16 | 34 | #define BPF_PPC_STACK_LOCALS 16 |
| 35 | /* Ensure this is quadword aligned */ | 35 | /* stack frame excluding BPF stack, ensure this is quadword aligned */ |
| 36 | #define BPF_PPC_STACKFRAME (STACK_FRAME_MIN_SIZE + MAX_BPF_STACK + \ | 36 | #define BPF_PPC_STACKFRAME (STACK_FRAME_MIN_SIZE + \ |
| 37 | BPF_PPC_STACK_LOCALS + BPF_PPC_STACK_SAVE) | 37 | BPF_PPC_STACK_LOCALS + BPF_PPC_STACK_SAVE) |
| 38 | 38 | ||
| 39 | #ifndef __ASSEMBLY__ | 39 | #ifndef __ASSEMBLY__ |
| @@ -103,6 +103,7 @@ struct codegen_context { | |||
| 103 | */ | 103 | */ |
| 104 | unsigned int seen; | 104 | unsigned int seen; |
| 105 | unsigned int idx; | 105 | unsigned int idx; |
| 106 | unsigned int stack_size; | ||
| 106 | }; | 107 | }; |
| 107 | 108 | ||
| 108 | #endif /* !__ASSEMBLY__ */ | 109 | #endif /* !__ASSEMBLY__ */ |
diff --git a/arch/powerpc/net/bpf_jit_comp64.c b/arch/powerpc/net/bpf_jit_comp64.c index a66e64b0b251..46d74e81aff1 100644 --- a/arch/powerpc/net/bpf_jit_comp64.c +++ b/arch/powerpc/net/bpf_jit_comp64.c | |||
| @@ -69,7 +69,7 @@ static inline bool bpf_has_stack_frame(struct codegen_context *ctx) | |||
| 69 | static int bpf_jit_stack_local(struct codegen_context *ctx) | 69 | static int bpf_jit_stack_local(struct codegen_context *ctx) |
| 70 | { | 70 | { |
| 71 | if (bpf_has_stack_frame(ctx)) | 71 | if (bpf_has_stack_frame(ctx)) |
| 72 | return STACK_FRAME_MIN_SIZE + MAX_BPF_STACK; | 72 | return STACK_FRAME_MIN_SIZE + ctx->stack_size; |
| 73 | else | 73 | else |
| 74 | return -(BPF_PPC_STACK_SAVE + 16); | 74 | return -(BPF_PPC_STACK_SAVE + 16); |
| 75 | } | 75 | } |
| @@ -82,8 +82,9 @@ static int bpf_jit_stack_tailcallcnt(struct codegen_context *ctx) | |||
| 82 | static int bpf_jit_stack_offsetof(struct codegen_context *ctx, int reg) | 82 | static int bpf_jit_stack_offsetof(struct codegen_context *ctx, int reg) |
| 83 | { | 83 | { |
| 84 | if (reg >= BPF_PPC_NVR_MIN && reg < 32) | 84 | if (reg >= BPF_PPC_NVR_MIN && reg < 32) |
| 85 | return (bpf_has_stack_frame(ctx) ? BPF_PPC_STACKFRAME : 0) | 85 | return (bpf_has_stack_frame(ctx) ? |
| 86 | - (8 * (32 - reg)); | 86 | (BPF_PPC_STACKFRAME + ctx->stack_size) : 0) |
| 87 | - (8 * (32 - reg)); | ||
| 87 | 88 | ||
| 88 | pr_err("BPF JIT is asking about unknown registers"); | 89 | pr_err("BPF JIT is asking about unknown registers"); |
| 89 | BUG(); | 90 | BUG(); |
| @@ -134,7 +135,7 @@ static void bpf_jit_build_prologue(u32 *image, struct codegen_context *ctx) | |||
| 134 | PPC_BPF_STL(0, 1, PPC_LR_STKOFF); | 135 | PPC_BPF_STL(0, 1, PPC_LR_STKOFF); |
| 135 | } | 136 | } |
| 136 | 137 | ||
| 137 | PPC_BPF_STLU(1, 1, -BPF_PPC_STACKFRAME); | 138 | PPC_BPF_STLU(1, 1, -(BPF_PPC_STACKFRAME + ctx->stack_size)); |
| 138 | } | 139 | } |
| 139 | 140 | ||
| 140 | /* | 141 | /* |
| @@ -161,7 +162,7 @@ static void bpf_jit_build_prologue(u32 *image, struct codegen_context *ctx) | |||
| 161 | /* Setup frame pointer to point to the bpf stack area */ | 162 | /* Setup frame pointer to point to the bpf stack area */ |
| 162 | if (bpf_is_seen_register(ctx, BPF_REG_FP)) | 163 | if (bpf_is_seen_register(ctx, BPF_REG_FP)) |
| 163 | PPC_ADDI(b2p[BPF_REG_FP], 1, | 164 | PPC_ADDI(b2p[BPF_REG_FP], 1, |
| 164 | STACK_FRAME_MIN_SIZE + MAX_BPF_STACK); | 165 | STACK_FRAME_MIN_SIZE + ctx->stack_size); |
| 165 | } | 166 | } |
| 166 | 167 | ||
| 167 | static void bpf_jit_emit_common_epilogue(u32 *image, struct codegen_context *ctx) | 168 | static void bpf_jit_emit_common_epilogue(u32 *image, struct codegen_context *ctx) |
| @@ -183,7 +184,7 @@ static void bpf_jit_emit_common_epilogue(u32 *image, struct codegen_context *ctx | |||
| 183 | 184 | ||
| 184 | /* Tear down our stack frame */ | 185 | /* Tear down our stack frame */ |
| 185 | if (bpf_has_stack_frame(ctx)) { | 186 | if (bpf_has_stack_frame(ctx)) { |
| 186 | PPC_ADDI(1, 1, BPF_PPC_STACKFRAME); | 187 | PPC_ADDI(1, 1, BPF_PPC_STACKFRAME + ctx->stack_size); |
| 187 | if (ctx->seen & SEEN_FUNC) { | 188 | if (ctx->seen & SEEN_FUNC) { |
| 188 | PPC_BPF_LL(0, 1, PPC_LR_STKOFF); | 189 | PPC_BPF_LL(0, 1, PPC_LR_STKOFF); |
| 189 | PPC_MTLR(0); | 190 | PPC_MTLR(0); |
| @@ -1013,6 +1014,9 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp) | |||
| 1013 | 1014 | ||
| 1014 | memset(&cgctx, 0, sizeof(struct codegen_context)); | 1015 | memset(&cgctx, 0, sizeof(struct codegen_context)); |
| 1015 | 1016 | ||
| 1017 | /* Make sure that the stack is quadword aligned. */ | ||
| 1018 | cgctx.stack_size = round_up(fp->aux->stack_depth, 16); | ||
| 1019 | |||
| 1016 | /* Scouting faux-generate pass 0 */ | 1020 | /* Scouting faux-generate pass 0 */ |
| 1017 | if (bpf_jit_build_body(fp, 0, &cgctx, addrs)) { | 1021 | if (bpf_jit_build_body(fp, 0, &cgctx, addrs)) { |
| 1018 | /* We hit something illegal or unsupported. */ | 1022 | /* We hit something illegal or unsupported. */ |
diff --git a/arch/powerpc/oprofile/op_model_cell.c b/arch/powerpc/oprofile/op_model_cell.c index c82497a31c54..264b6ab11978 100644 --- a/arch/powerpc/oprofile/op_model_cell.c +++ b/arch/powerpc/oprofile/op_model_cell.c | |||
| @@ -555,9 +555,7 @@ static void cell_virtual_cntr(unsigned long data) | |||
| 555 | 555 | ||
| 556 | static void start_virt_cntrs(void) | 556 | static void start_virt_cntrs(void) |
| 557 | { | 557 | { |
| 558 | init_timer(&timer_virt_cntr); | 558 | setup_timer(&timer_virt_cntr, cell_virtual_cntr, 0UL); |
| 559 | timer_virt_cntr.function = cell_virtual_cntr; | ||
| 560 | timer_virt_cntr.data = 0UL; | ||
| 561 | timer_virt_cntr.expires = jiffies + HZ / 10; | 559 | timer_virt_cntr.expires = jiffies + HZ / 10; |
| 562 | add_timer(&timer_virt_cntr); | 560 | add_timer(&timer_virt_cntr); |
| 563 | } | 561 | } |
| @@ -679,9 +677,7 @@ static void spu_evnt_swap(unsigned long data) | |||
| 679 | 677 | ||
| 680 | static void start_spu_event_swap(void) | 678 | static void start_spu_event_swap(void) |
| 681 | { | 679 | { |
| 682 | init_timer(&timer_spu_event_swap); | 680 | setup_timer(&timer_spu_event_swap, spu_evnt_swap, 0UL); |
| 683 | timer_spu_event_swap.function = spu_evnt_swap; | ||
| 684 | timer_spu_event_swap.data = 0UL; | ||
| 685 | timer_spu_event_swap.expires = jiffies + HZ / 25; | 681 | timer_spu_event_swap.expires = jiffies + HZ / 25; |
| 686 | add_timer(&timer_spu_event_swap); | 682 | add_timer(&timer_spu_event_swap); |
| 687 | } | 683 | } |
diff --git a/arch/powerpc/perf/hv-24x7.c b/arch/powerpc/perf/hv-24x7.c index 9c88b82f6229..72238eedc360 100644 --- a/arch/powerpc/perf/hv-24x7.c +++ b/arch/powerpc/perf/hv-24x7.c | |||
| @@ -540,7 +540,7 @@ static int memord(const void *d1, size_t s1, const void *d2, size_t s2) | |||
| 540 | { | 540 | { |
| 541 | if (s1 < s2) | 541 | if (s1 < s2) |
| 542 | return 1; | 542 | return 1; |
| 543 | if (s2 > s1) | 543 | if (s1 > s2) |
| 544 | return -1; | 544 | return -1; |
| 545 | 545 | ||
| 546 | return memcmp(d1, d2, s1); | 546 | return memcmp(d1, d2, s1); |
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype index a78f255111f2..ae07470fde3c 100644 --- a/arch/powerpc/platforms/Kconfig.cputype +++ b/arch/powerpc/platforms/Kconfig.cputype | |||
| @@ -295,10 +295,6 @@ config PPC_STD_MMU_32 | |||
| 295 | def_bool y | 295 | def_bool y |
| 296 | depends on PPC_STD_MMU && PPC32 | 296 | depends on PPC_STD_MMU && PPC32 |
| 297 | 297 | ||
| 298 | config PPC_STD_MMU_64 | ||
| 299 | def_bool y | ||
| 300 | depends on PPC_STD_MMU && PPC64 | ||
| 301 | |||
| 302 | config PPC_RADIX_MMU | 298 | config PPC_RADIX_MMU |
| 303 | bool "Radix MMU Support" | 299 | bool "Radix MMU Support" |
| 304 | depends on PPC_BOOK3S_64 | 300 | depends on PPC_BOOK3S_64 |
| @@ -309,6 +305,19 @@ config PPC_RADIX_MMU | |||
| 309 | is only implemented by IBM Power9 CPUs, if you don't have one of them | 305 | is only implemented by IBM Power9 CPUs, if you don't have one of them |
| 310 | you can probably disable this. | 306 | you can probably disable this. |
| 311 | 307 | ||
| 308 | config PPC_RADIX_MMU_DEFAULT | ||
| 309 | bool "Default to using the Radix MMU when possible" | ||
| 310 | depends on PPC_RADIX_MMU | ||
| 311 | default y | ||
| 312 | help | ||
| 313 | When the hardware supports the Radix MMU, default to using it unless | ||
| 314 | "disable_radix[=yes]" is specified on the kernel command line. | ||
| 315 | |||
| 316 | If this option is disabled, the Hash MMU will be used by default, | ||
| 317 | unless "disable_radix=no" is specified on the kernel command line. | ||
| 318 | |||
| 319 | If you're unsure, say Y. | ||
| 320 | |||
| 312 | config ARCH_ENABLE_HUGEPAGE_MIGRATION | 321 | config ARCH_ENABLE_HUGEPAGE_MIGRATION |
| 313 | def_bool y | 322 | def_bool y |
| 314 | depends on PPC_BOOK3S_64 && HUGETLB_PAGE && MIGRATION | 323 | depends on PPC_BOOK3S_64 && HUGETLB_PAGE && MIGRATION |
| @@ -324,7 +333,7 @@ config PPC_BOOK3E_MMU | |||
| 324 | 333 | ||
| 325 | config PPC_MM_SLICES | 334 | config PPC_MM_SLICES |
| 326 | bool | 335 | bool |
| 327 | default y if PPC_STD_MMU_64 | 336 | default y if PPC_BOOK3S_64 |
| 328 | default n | 337 | default n |
| 329 | 338 | ||
| 330 | config PPC_HAVE_PMU_SUPPORT | 339 | config PPC_HAVE_PMU_SUPPORT |
diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c index 70183eb3d5c8..39a1d4225e0f 100644 --- a/arch/powerpc/platforms/powermac/low_i2c.c +++ b/arch/powerpc/platforms/powermac/low_i2c.c | |||
| @@ -513,9 +513,7 @@ static struct pmac_i2c_host_kw *__init kw_i2c_host_init(struct device_node *np) | |||
| 513 | mutex_init(&host->mutex); | 513 | mutex_init(&host->mutex); |
| 514 | init_completion(&host->complete); | 514 | init_completion(&host->complete); |
| 515 | spin_lock_init(&host->lock); | 515 | spin_lock_init(&host->lock); |
| 516 | init_timer(&host->timeout_timer); | 516 | setup_timer(&host->timeout_timer, kw_i2c_timeout, (unsigned long)host); |
| 517 | host->timeout_timer.function = kw_i2c_timeout; | ||
| 518 | host->timeout_timer.data = (unsigned long)host; | ||
| 519 | 517 | ||
| 520 | psteps = of_get_property(np, "AAPL,address-step", NULL); | 518 | psteps = of_get_property(np, "AAPL,address-step", NULL); |
| 521 | steps = psteps ? (*psteps) : 0x10; | 519 | steps = psteps ? (*psteps) : 0x10; |
diff --git a/arch/powerpc/platforms/powernv/Makefile b/arch/powerpc/platforms/powernv/Makefile index 7a31c26500e6..3732118a0482 100644 --- a/arch/powerpc/platforms/powernv/Makefile +++ b/arch/powerpc/platforms/powernv/Makefile | |||
| @@ -15,4 +15,5 @@ obj-$(CONFIG_TRACEPOINTS) += opal-tracepoints.o | |||
| 15 | obj-$(CONFIG_OPAL_PRD) += opal-prd.o | 15 | obj-$(CONFIG_OPAL_PRD) += opal-prd.o |
| 16 | obj-$(CONFIG_PERF_EVENTS) += opal-imc.o | 16 | obj-$(CONFIG_PERF_EVENTS) += opal-imc.o |
| 17 | obj-$(CONFIG_PPC_MEMTRACE) += memtrace.o | 17 | obj-$(CONFIG_PPC_MEMTRACE) += memtrace.o |
| 18 | obj-$(CONFIG_PPC_VAS) += vas.o vas-window.o | 18 | obj-$(CONFIG_PPC_VAS) += vas.o vas-window.o vas-debug.o |
| 19 | obj-$(CONFIG_PPC_FTW) += nx-ftw.o | ||
diff --git a/arch/powerpc/platforms/powernv/eeh-powernv.c b/arch/powerpc/platforms/powernv/eeh-powernv.c index 8864065eba22..4650fb294e7a 100644 --- a/arch/powerpc/platforms/powernv/eeh-powernv.c +++ b/arch/powerpc/platforms/powernv/eeh-powernv.c | |||
| @@ -41,7 +41,6 @@ | |||
| 41 | #include "powernv.h" | 41 | #include "powernv.h" |
| 42 | #include "pci.h" | 42 | #include "pci.h" |
| 43 | 43 | ||
| 44 | static bool pnv_eeh_nb_init = false; | ||
| 45 | static int eeh_event_irq = -EINVAL; | 44 | static int eeh_event_irq = -EINVAL; |
| 46 | 45 | ||
| 47 | static int pnv_eeh_init(void) | 46 | static int pnv_eeh_init(void) |
| @@ -197,31 +196,31 @@ PNV_EEH_DBGFS_ENTRY(inbB, 0xE10); | |||
| 197 | * been built. If the I/O cache staff has been built, EEH is | 196 | * been built. If the I/O cache staff has been built, EEH is |
| 198 | * ready to supply service. | 197 | * ready to supply service. |
| 199 | */ | 198 | */ |
| 200 | static int pnv_eeh_post_init(void) | 199 | int pnv_eeh_post_init(void) |
| 201 | { | 200 | { |
| 202 | struct pci_controller *hose; | 201 | struct pci_controller *hose; |
| 203 | struct pnv_phb *phb; | 202 | struct pnv_phb *phb; |
| 204 | int ret = 0; | 203 | int ret = 0; |
| 205 | 204 | ||
| 206 | /* Register OPAL event notifier */ | 205 | /* Probe devices & build address cache */ |
| 207 | if (!pnv_eeh_nb_init) { | 206 | eeh_probe_devices(); |
| 208 | eeh_event_irq = opal_event_request(ilog2(OPAL_EVENT_PCI_ERROR)); | 207 | eeh_addr_cache_build(); |
| 209 | if (eeh_event_irq < 0) { | ||
| 210 | pr_err("%s: Can't register OPAL event interrupt (%d)\n", | ||
| 211 | __func__, eeh_event_irq); | ||
| 212 | return eeh_event_irq; | ||
| 213 | } | ||
| 214 | 208 | ||
| 215 | ret = request_irq(eeh_event_irq, pnv_eeh_event, | 209 | /* Register OPAL event notifier */ |
| 216 | IRQ_TYPE_LEVEL_HIGH, "opal-eeh", NULL); | 210 | eeh_event_irq = opal_event_request(ilog2(OPAL_EVENT_PCI_ERROR)); |
| 217 | if (ret < 0) { | 211 | if (eeh_event_irq < 0) { |
| 218 | irq_dispose_mapping(eeh_event_irq); | 212 | pr_err("%s: Can't register OPAL event interrupt (%d)\n", |
| 219 | pr_err("%s: Can't request OPAL event interrupt (%d)\n", | 213 | __func__, eeh_event_irq); |
| 220 | __func__, eeh_event_irq); | 214 | return eeh_event_irq; |
| 221 | return ret; | 215 | } |
| 222 | } | ||
| 223 | 216 | ||
| 224 | pnv_eeh_nb_init = true; | 217 | ret = request_irq(eeh_event_irq, pnv_eeh_event, |
| 218 | IRQ_TYPE_LEVEL_HIGH, "opal-eeh", NULL); | ||
| 219 | if (ret < 0) { | ||
| 220 | irq_dispose_mapping(eeh_event_irq); | ||
| 221 | pr_err("%s: Can't request OPAL event interrupt (%d)\n", | ||
| 222 | __func__, eeh_event_irq); | ||
| 223 | return ret; | ||
| 225 | } | 224 | } |
| 226 | 225 | ||
| 227 | if (!eeh_enabled()) | 226 | if (!eeh_enabled()) |
| @@ -367,6 +366,10 @@ static void *pnv_eeh_probe(struct pci_dn *pdn, void *data) | |||
| 367 | if ((pdn->class_code >> 8) == PCI_CLASS_BRIDGE_ISA) | 366 | if ((pdn->class_code >> 8) == PCI_CLASS_BRIDGE_ISA) |
| 368 | return NULL; | 367 | return NULL; |
| 369 | 368 | ||
| 369 | /* Skip if we haven't probed yet */ | ||
| 370 | if (phb->ioda.pe_rmap[config_addr] == IODA_INVALID_PE) | ||
| 371 | return NULL; | ||
| 372 | |||
| 370 | /* Initialize eeh device */ | 373 | /* Initialize eeh device */ |
| 371 | edev->class_code = pdn->class_code; | 374 | edev->class_code = pdn->class_code; |
| 372 | edev->mode &= 0xFFFFFF00; | 375 | edev->mode &= 0xFFFFFF00; |
| @@ -1731,7 +1734,6 @@ static int pnv_eeh_restore_config(struct pci_dn *pdn) | |||
| 1731 | static struct eeh_ops pnv_eeh_ops = { | 1734 | static struct eeh_ops pnv_eeh_ops = { |
| 1732 | .name = "powernv", | 1735 | .name = "powernv", |
| 1733 | .init = pnv_eeh_init, | 1736 | .init = pnv_eeh_init, |
| 1734 | .post_init = pnv_eeh_post_init, | ||
| 1735 | .probe = pnv_eeh_probe, | 1737 | .probe = pnv_eeh_probe, |
| 1736 | .set_option = pnv_eeh_set_option, | 1738 | .set_option = pnv_eeh_set_option, |
| 1737 | .get_pe_addr = pnv_eeh_get_pe_addr, | 1739 | .get_pe_addr = pnv_eeh_get_pe_addr, |
diff --git a/arch/powerpc/platforms/powernv/npu-dma.c b/arch/powerpc/platforms/powernv/npu-dma.c index 2cb6cbea4b3b..f6cbc1a71472 100644 --- a/arch/powerpc/platforms/powernv/npu-dma.c +++ b/arch/powerpc/platforms/powernv/npu-dma.c | |||
| @@ -395,6 +395,7 @@ struct npu_context { | |||
| 395 | struct pci_dev *npdev[NV_MAX_NPUS][NV_MAX_LINKS]; | 395 | struct pci_dev *npdev[NV_MAX_NPUS][NV_MAX_LINKS]; |
| 396 | struct mmu_notifier mn; | 396 | struct mmu_notifier mn; |
| 397 | struct kref kref; | 397 | struct kref kref; |
| 398 | bool nmmu_flush; | ||
| 398 | 399 | ||
| 399 | /* Callback to stop translation requests on a given GPU */ | 400 | /* Callback to stop translation requests on a given GPU */ |
| 400 | struct npu_context *(*release_cb)(struct npu_context *, void *); | 401 | struct npu_context *(*release_cb)(struct npu_context *, void *); |
| @@ -545,11 +546,13 @@ static void mmio_invalidate(struct npu_context *npu_context, int va, | |||
| 545 | struct mmio_atsd_reg mmio_atsd_reg[NV_MAX_NPUS]; | 546 | struct mmio_atsd_reg mmio_atsd_reg[NV_MAX_NPUS]; |
| 546 | unsigned long pid = npu_context->mm->context.id; | 547 | unsigned long pid = npu_context->mm->context.id; |
| 547 | 548 | ||
| 548 | /* | 549 | if (npu_context->nmmu_flush) |
| 549 | * Unfortunately the nest mmu does not support flushing specific | 550 | /* |
| 550 | * addresses so we have to flush the whole mm. | 551 | * Unfortunately the nest mmu does not support flushing specific |
| 551 | */ | 552 | * addresses so we have to flush the whole mm once before |
| 552 | flush_tlb_mm(npu_context->mm); | 553 | * shooting down the GPU translation. |
| 554 | */ | ||
| 555 | flush_all_mm(npu_context->mm); | ||
| 553 | 556 | ||
| 554 | /* | 557 | /* |
| 555 | * Loop over all the NPUs this process is active on and launch | 558 | * Loop over all the NPUs this process is active on and launch |
| @@ -722,6 +725,16 @@ struct npu_context *pnv_npu2_init_context(struct pci_dev *gpdev, | |||
| 722 | return ERR_PTR(-ENODEV); | 725 | return ERR_PTR(-ENODEV); |
| 723 | npu_context->npdev[npu->index][nvlink_index] = npdev; | 726 | npu_context->npdev[npu->index][nvlink_index] = npdev; |
| 724 | 727 | ||
| 728 | if (!nphb->npu.nmmu_flush) { | ||
| 729 | /* | ||
| 730 | * If we're not explicitly flushing ourselves we need to mark | ||
| 731 | * the thread for global flushes | ||
| 732 | */ | ||
| 733 | npu_context->nmmu_flush = false; | ||
| 734 | mm_context_add_copro(mm); | ||
| 735 | } else | ||
| 736 | npu_context->nmmu_flush = true; | ||
| 737 | |||
| 725 | return npu_context; | 738 | return npu_context; |
| 726 | } | 739 | } |
| 727 | EXPORT_SYMBOL(pnv_npu2_init_context); | 740 | EXPORT_SYMBOL(pnv_npu2_init_context); |
| @@ -731,6 +744,9 @@ static void pnv_npu2_release_context(struct kref *kref) | |||
| 731 | struct npu_context *npu_context = | 744 | struct npu_context *npu_context = |
| 732 | container_of(kref, struct npu_context, kref); | 745 | container_of(kref, struct npu_context, kref); |
| 733 | 746 | ||
| 747 | if (!npu_context->nmmu_flush) | ||
| 748 | mm_context_remove_copro(npu_context->mm); | ||
| 749 | |||
| 734 | npu_context->mm->context.npu_context = NULL; | 750 | npu_context->mm->context.npu_context = NULL; |
| 735 | mmu_notifier_unregister(&npu_context->mn, | 751 | mmu_notifier_unregister(&npu_context->mn, |
| 736 | npu_context->mm); | 752 | npu_context->mm); |
| @@ -819,6 +835,8 @@ int pnv_npu2_init(struct pnv_phb *phb) | |||
| 819 | static int npu_index; | 835 | static int npu_index; |
| 820 | uint64_t rc = 0; | 836 | uint64_t rc = 0; |
| 821 | 837 | ||
| 838 | phb->npu.nmmu_flush = | ||
| 839 | of_property_read_bool(phb->hose->dn, "ibm,nmmu-flush"); | ||
| 822 | for_each_child_of_node(phb->hose->dn, dn) { | 840 | for_each_child_of_node(phb->hose->dn, dn) { |
| 823 | gpdev = pnv_pci_get_gpu_dev(get_pci_dev(dn)); | 841 | gpdev = pnv_pci_get_gpu_dev(get_pci_dev(dn)); |
| 824 | if (gpdev) { | 842 | if (gpdev) { |
diff --git a/arch/powerpc/platforms/powernv/opal-async.c b/arch/powerpc/platforms/powernv/opal-async.c index cf33769a7b72..18a355fa15e8 100644 --- a/arch/powerpc/platforms/powernv/opal-async.c +++ b/arch/powerpc/platforms/powernv/opal-async.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * PowerNV OPAL asynchronous completion interfaces | 2 | * PowerNV OPAL asynchronous completion interfaces |
| 3 | * | 3 | * |
| 4 | * Copyright 2013 IBM Corp. | 4 | * Copyright 2013-2017 IBM Corp. |
| 5 | * | 5 | * |
| 6 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
| 7 | * modify it under the terms of the GNU General Public License | 7 | * modify it under the terms of the GNU General Public License |
| @@ -23,40 +23,50 @@ | |||
| 23 | #include <asm/machdep.h> | 23 | #include <asm/machdep.h> |
| 24 | #include <asm/opal.h> | 24 | #include <asm/opal.h> |
| 25 | 25 | ||
| 26 | #define N_ASYNC_COMPLETIONS 64 | 26 | enum opal_async_token_state { |
| 27 | ASYNC_TOKEN_UNALLOCATED = 0, | ||
| 28 | ASYNC_TOKEN_ALLOCATED, | ||
| 29 | ASYNC_TOKEN_DISPATCHED, | ||
| 30 | ASYNC_TOKEN_ABANDONED, | ||
| 31 | ASYNC_TOKEN_COMPLETED | ||
| 32 | }; | ||
| 33 | |||
| 34 | struct opal_async_token { | ||
| 35 | enum opal_async_token_state state; | ||
| 36 | struct opal_msg response; | ||
| 37 | }; | ||
| 27 | 38 | ||
| 28 | static DECLARE_BITMAP(opal_async_complete_map, N_ASYNC_COMPLETIONS) = {~0UL}; | ||
| 29 | static DECLARE_BITMAP(opal_async_token_map, N_ASYNC_COMPLETIONS); | ||
| 30 | static DECLARE_WAIT_QUEUE_HEAD(opal_async_wait); | 39 | static DECLARE_WAIT_QUEUE_HEAD(opal_async_wait); |
| 31 | static DEFINE_SPINLOCK(opal_async_comp_lock); | 40 | static DEFINE_SPINLOCK(opal_async_comp_lock); |
| 32 | static struct semaphore opal_async_sem; | 41 | static struct semaphore opal_async_sem; |
| 33 | static struct opal_msg *opal_async_responses; | ||
| 34 | static unsigned int opal_max_async_tokens; | 42 | static unsigned int opal_max_async_tokens; |
| 43 | static struct opal_async_token *opal_async_tokens; | ||
| 35 | 44 | ||
| 36 | int __opal_async_get_token(void) | 45 | static int __opal_async_get_token(void) |
| 37 | { | 46 | { |
| 38 | unsigned long flags; | 47 | unsigned long flags; |
| 39 | int token; | 48 | int i, token = -EBUSY; |
| 40 | 49 | ||
| 41 | spin_lock_irqsave(&opal_async_comp_lock, flags); | 50 | spin_lock_irqsave(&opal_async_comp_lock, flags); |
| 42 | token = find_first_bit(opal_async_complete_map, opal_max_async_tokens); | ||
| 43 | if (token >= opal_max_async_tokens) { | ||
| 44 | token = -EBUSY; | ||
| 45 | goto out; | ||
| 46 | } | ||
| 47 | 51 | ||
| 48 | if (__test_and_set_bit(token, opal_async_token_map)) { | 52 | for (i = 0; i < opal_max_async_tokens; i++) { |
| 49 | token = -EBUSY; | 53 | if (opal_async_tokens[i].state == ASYNC_TOKEN_UNALLOCATED) { |
| 50 | goto out; | 54 | opal_async_tokens[i].state = ASYNC_TOKEN_ALLOCATED; |
| 55 | token = i; | ||
| 56 | break; | ||
| 57 | } | ||
| 51 | } | 58 | } |
| 52 | 59 | ||
| 53 | __clear_bit(token, opal_async_complete_map); | ||
| 54 | |||
| 55 | out: | ||
| 56 | spin_unlock_irqrestore(&opal_async_comp_lock, flags); | 60 | spin_unlock_irqrestore(&opal_async_comp_lock, flags); |
| 57 | return token; | 61 | return token; |
| 58 | } | 62 | } |
| 59 | 63 | ||
| 64 | /* | ||
| 65 | * Note: If the returned token is used in an opal call and opal returns | ||
| 66 | * OPAL_ASYNC_COMPLETION you MUST call one of opal_async_wait_response() or | ||
| 67 | * opal_async_wait_response_interruptible() at least once before calling another | ||
| 68 | * opal_async_* function | ||
| 69 | */ | ||
| 60 | int opal_async_get_token_interruptible(void) | 70 | int opal_async_get_token_interruptible(void) |
| 61 | { | 71 | { |
| 62 | int token; | 72 | int token; |
| @@ -73,9 +83,10 @@ int opal_async_get_token_interruptible(void) | |||
| 73 | } | 83 | } |
| 74 | EXPORT_SYMBOL_GPL(opal_async_get_token_interruptible); | 84 | EXPORT_SYMBOL_GPL(opal_async_get_token_interruptible); |
| 75 | 85 | ||
| 76 | int __opal_async_release_token(int token) | 86 | static int __opal_async_release_token(int token) |
| 77 | { | 87 | { |
| 78 | unsigned long flags; | 88 | unsigned long flags; |
| 89 | int rc; | ||
| 79 | 90 | ||
| 80 | if (token < 0 || token >= opal_max_async_tokens) { | 91 | if (token < 0 || token >= opal_max_async_tokens) { |
| 81 | pr_err("%s: Passed token is out of range, token %d\n", | 92 | pr_err("%s: Passed token is out of range, token %d\n", |
| @@ -84,11 +95,26 @@ int __opal_async_release_token(int token) | |||
| 84 | } | 95 | } |
| 85 | 96 | ||
| 86 | spin_lock_irqsave(&opal_async_comp_lock, flags); | 97 | spin_lock_irqsave(&opal_async_comp_lock, flags); |
| 87 | __set_bit(token, opal_async_complete_map); | 98 | switch (opal_async_tokens[token].state) { |
| 88 | __clear_bit(token, opal_async_token_map); | 99 | case ASYNC_TOKEN_COMPLETED: |
| 100 | case ASYNC_TOKEN_ALLOCATED: | ||
| 101 | opal_async_tokens[token].state = ASYNC_TOKEN_UNALLOCATED; | ||
| 102 | rc = 0; | ||
| 103 | break; | ||
| 104 | /* | ||
| 105 | * DISPATCHED and ABANDONED tokens must wait for OPAL to respond. | ||
| 106 | * Mark a DISPATCHED token as ABANDONED so that the response handling | ||
| 107 | * code knows no one cares and that it can free it then. | ||
| 108 | */ | ||
| 109 | case ASYNC_TOKEN_DISPATCHED: | ||
| 110 | opal_async_tokens[token].state = ASYNC_TOKEN_ABANDONED; | ||
| 111 | /* Fall through */ | ||
| 112 | default: | ||
| 113 | rc = 1; | ||
| 114 | } | ||
| 89 | spin_unlock_irqrestore(&opal_async_comp_lock, flags); | 115 | spin_unlock_irqrestore(&opal_async_comp_lock, flags); |
| 90 | 116 | ||
| 91 | return 0; | 117 | return rc; |
| 92 | } | 118 | } |
| 93 | 119 | ||
| 94 | int opal_async_release_token(int token) | 120 | int opal_async_release_token(int token) |
| @@ -96,12 +122,10 @@ int opal_async_release_token(int token) | |||
| 96 | int ret; | 122 | int ret; |
| 97 | 123 | ||
| 98 | ret = __opal_async_release_token(token); | 124 | ret = __opal_async_release_token(token); |
| 99 | if (ret) | 125 | if (!ret) |
| 100 | return ret; | 126 | up(&opal_async_sem); |
| 101 | |||
| 102 | up(&opal_async_sem); | ||
| 103 | 127 | ||
| 104 | return 0; | 128 | return ret; |
| 105 | } | 129 | } |
| 106 | EXPORT_SYMBOL_GPL(opal_async_release_token); | 130 | EXPORT_SYMBOL_GPL(opal_async_release_token); |
| 107 | 131 | ||
| @@ -117,22 +141,83 @@ int opal_async_wait_response(uint64_t token, struct opal_msg *msg) | |||
| 117 | return -EINVAL; | 141 | return -EINVAL; |
| 118 | } | 142 | } |
| 119 | 143 | ||
| 120 | /* Wakeup the poller before we wait for events to speed things | 144 | /* |
| 145 | * There is no need to mark the token as dispatched, wait_event() | ||
| 146 | * will block until the token completes. | ||
| 147 | * | ||
| 148 | * Wakeup the poller before we wait for events to speed things | ||
| 121 | * up on platforms or simulators where the interrupts aren't | 149 | * up on platforms or simulators where the interrupts aren't |
| 122 | * functional. | 150 | * functional. |
| 123 | */ | 151 | */ |
| 124 | opal_wake_poller(); | 152 | opal_wake_poller(); |
| 125 | wait_event(opal_async_wait, test_bit(token, opal_async_complete_map)); | 153 | wait_event(opal_async_wait, opal_async_tokens[token].state |
| 126 | memcpy(msg, &opal_async_responses[token], sizeof(*msg)); | 154 | == ASYNC_TOKEN_COMPLETED); |
| 155 | memcpy(msg, &opal_async_tokens[token].response, sizeof(*msg)); | ||
| 127 | 156 | ||
| 128 | return 0; | 157 | return 0; |
| 129 | } | 158 | } |
| 130 | EXPORT_SYMBOL_GPL(opal_async_wait_response); | 159 | EXPORT_SYMBOL_GPL(opal_async_wait_response); |
| 131 | 160 | ||
| 161 | int opal_async_wait_response_interruptible(uint64_t token, struct opal_msg *msg) | ||
| 162 | { | ||
| 163 | unsigned long flags; | ||
| 164 | int ret; | ||
| 165 | |||
| 166 | if (token >= opal_max_async_tokens) { | ||
| 167 | pr_err("%s: Invalid token passed\n", __func__); | ||
| 168 | return -EINVAL; | ||
| 169 | } | ||
| 170 | |||
| 171 | if (!msg) { | ||
| 172 | pr_err("%s: Invalid message pointer passed\n", __func__); | ||
| 173 | return -EINVAL; | ||
| 174 | } | ||
| 175 | |||
| 176 | /* | ||
| 177 | * The first time this gets called we mark the token as DISPATCHED | ||
| 178 | * so that if wait_event_interruptible() returns not zero and the | ||
| 179 | * caller frees the token, we know not to actually free the token | ||
| 180 | * until the response comes. | ||
| 181 | * | ||
| 182 | * Only change if the token is ALLOCATED - it may have been | ||
| 183 | * completed even before the caller gets around to calling this | ||
| 184 | * the first time. | ||
| 185 | * | ||
| 186 | * There is also a dirty great comment at the token allocation | ||
| 187 | * function that if the opal call returns OPAL_ASYNC_COMPLETION to | ||
| 188 | * the caller then the caller *must* call this or the not | ||
| 189 | * interruptible version before doing anything else with the | ||
| 190 | * token. | ||
| 191 | */ | ||
| 192 | if (opal_async_tokens[token].state == ASYNC_TOKEN_ALLOCATED) { | ||
| 193 | spin_lock_irqsave(&opal_async_comp_lock, flags); | ||
| 194 | if (opal_async_tokens[token].state == ASYNC_TOKEN_ALLOCATED) | ||
| 195 | opal_async_tokens[token].state = ASYNC_TOKEN_DISPATCHED; | ||
| 196 | spin_unlock_irqrestore(&opal_async_comp_lock, flags); | ||
| 197 | } | ||
| 198 | |||
| 199 | /* | ||
| 200 | * Wakeup the poller before we wait for events to speed things | ||
| 201 | * up on platforms or simulators where the interrupts aren't | ||
| 202 | * functional. | ||
| 203 | */ | ||
| 204 | opal_wake_poller(); | ||
| 205 | ret = wait_event_interruptible(opal_async_wait, | ||
| 206 | opal_async_tokens[token].state == | ||
| 207 | ASYNC_TOKEN_COMPLETED); | ||
| 208 | if (!ret) | ||
| 209 | memcpy(msg, &opal_async_tokens[token].response, sizeof(*msg)); | ||
| 210 | |||
| 211 | return ret; | ||
| 212 | } | ||
| 213 | EXPORT_SYMBOL_GPL(opal_async_wait_response_interruptible); | ||
| 214 | |||
| 215 | /* Called from interrupt context */ | ||
| 132 | static int opal_async_comp_event(struct notifier_block *nb, | 216 | static int opal_async_comp_event(struct notifier_block *nb, |
| 133 | unsigned long msg_type, void *msg) | 217 | unsigned long msg_type, void *msg) |
| 134 | { | 218 | { |
| 135 | struct opal_msg *comp_msg = msg; | 219 | struct opal_msg *comp_msg = msg; |
| 220 | enum opal_async_token_state state; | ||
| 136 | unsigned long flags; | 221 | unsigned long flags; |
| 137 | uint64_t token; | 222 | uint64_t token; |
| 138 | 223 | ||
| @@ -140,11 +225,17 @@ static int opal_async_comp_event(struct notifier_block *nb, | |||
| 140 | return 0; | 225 | return 0; |
| 141 | 226 | ||
| 142 | token = be64_to_cpu(comp_msg->params[0]); | 227 | token = be64_to_cpu(comp_msg->params[0]); |
| 143 | memcpy(&opal_async_responses[token], comp_msg, sizeof(*comp_msg)); | ||
| 144 | spin_lock_irqsave(&opal_async_comp_lock, flags); | 228 | spin_lock_irqsave(&opal_async_comp_lock, flags); |
| 145 | __set_bit(token, opal_async_complete_map); | 229 | state = opal_async_tokens[token].state; |
| 230 | opal_async_tokens[token].state = ASYNC_TOKEN_COMPLETED; | ||
| 146 | spin_unlock_irqrestore(&opal_async_comp_lock, flags); | 231 | spin_unlock_irqrestore(&opal_async_comp_lock, flags); |
| 147 | 232 | ||
| 233 | if (state == ASYNC_TOKEN_ABANDONED) { | ||
| 234 | /* Free the token, no one else will */ | ||
| 235 | opal_async_release_token(token); | ||
| 236 | return 0; | ||
| 237 | } | ||
| 238 | memcpy(&opal_async_tokens[token].response, comp_msg, sizeof(*comp_msg)); | ||
| 148 | wake_up(&opal_async_wait); | 239 | wake_up(&opal_async_wait); |
| 149 | 240 | ||
| 150 | return 0; | 241 | return 0; |
| @@ -178,32 +269,23 @@ int __init opal_async_comp_init(void) | |||
| 178 | } | 269 | } |
| 179 | 270 | ||
| 180 | opal_max_async_tokens = be32_to_cpup(async); | 271 | opal_max_async_tokens = be32_to_cpup(async); |
| 181 | if (opal_max_async_tokens > N_ASYNC_COMPLETIONS) | 272 | opal_async_tokens = kcalloc(opal_max_async_tokens, |
| 182 | opal_max_async_tokens = N_ASYNC_COMPLETIONS; | 273 | sizeof(*opal_async_tokens), GFP_KERNEL); |
| 274 | if (!opal_async_tokens) { | ||
| 275 | err = -ENOMEM; | ||
| 276 | goto out_opal_node; | ||
| 277 | } | ||
| 183 | 278 | ||
| 184 | err = opal_message_notifier_register(OPAL_MSG_ASYNC_COMP, | 279 | err = opal_message_notifier_register(OPAL_MSG_ASYNC_COMP, |
| 185 | &opal_async_comp_nb); | 280 | &opal_async_comp_nb); |
| 186 | if (err) { | 281 | if (err) { |
| 187 | pr_err("%s: Can't register OPAL event notifier (%d)\n", | 282 | pr_err("%s: Can't register OPAL event notifier (%d)\n", |
| 188 | __func__, err); | 283 | __func__, err); |
| 284 | kfree(opal_async_tokens); | ||
| 189 | goto out_opal_node; | 285 | goto out_opal_node; |
| 190 | } | 286 | } |
| 191 | 287 | ||
| 192 | opal_async_responses = kzalloc( | 288 | sema_init(&opal_async_sem, opal_max_async_tokens); |
| 193 | sizeof(*opal_async_responses) * opal_max_async_tokens, | ||
| 194 | GFP_KERNEL); | ||
| 195 | if (!opal_async_responses) { | ||
| 196 | pr_err("%s: Out of memory, failed to do asynchronous " | ||
| 197 | "completion init\n", __func__); | ||
| 198 | err = -ENOMEM; | ||
| 199 | goto out_opal_node; | ||
| 200 | } | ||
| 201 | |||
| 202 | /* Initialize to 1 less than the maximum tokens available, as we may | ||
| 203 | * require to pop one during emergency through synchronous call to | ||
| 204 | * __opal_async_get_token() | ||
| 205 | */ | ||
| 206 | sema_init(&opal_async_sem, opal_max_async_tokens - 1); | ||
| 207 | 289 | ||
| 208 | out_opal_node: | 290 | out_opal_node: |
| 209 | of_node_put(opal_node); | 291 | of_node_put(opal_node); |
diff --git a/arch/powerpc/platforms/powernv/opal-hmi.c b/arch/powerpc/platforms/powernv/opal-hmi.c index d78fed728cdf..c9e1a4ff295c 100644 --- a/arch/powerpc/platforms/powernv/opal-hmi.c +++ b/arch/powerpc/platforms/powernv/opal-hmi.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * OPAL hypervisor Maintenance interrupt handling support in PowreNV. | 2 | * OPAL hypervisor Maintenance interrupt handling support in PowerNV. |
| 3 | * | 3 | * |
| 4 | * This program is free software; you can redistribute it and/or modify | 4 | * This program is free software; you can redistribute it and/or modify |
| 5 | * it under the terms of the GNU General Public License as published by | 5 | * it under the terms of the GNU General Public License as published by |
diff --git a/arch/powerpc/platforms/powernv/opal-irqchip.c b/arch/powerpc/platforms/powernv/opal-irqchip.c index ecdcba9d1220..9d1b8c0aaf93 100644 --- a/arch/powerpc/platforms/powernv/opal-irqchip.c +++ b/arch/powerpc/platforms/powernv/opal-irqchip.c | |||
| @@ -174,8 +174,14 @@ void opal_event_shutdown(void) | |||
| 174 | 174 | ||
| 175 | /* First free interrupts, which will also mask them */ | 175 | /* First free interrupts, which will also mask them */ |
| 176 | for (i = 0; i < opal_irq_count; i++) { | 176 | for (i = 0; i < opal_irq_count; i++) { |
| 177 | if (opal_irqs[i]) | 177 | if (!opal_irqs[i]) |
| 178 | continue; | ||
| 179 | |||
| 180 | if (in_interrupt()) | ||
| 181 | disable_irq_nosync(opal_irqs[i]); | ||
| 182 | else | ||
| 178 | free_irq(opal_irqs[i], NULL); | 183 | free_irq(opal_irqs[i], NULL); |
| 184 | |||
| 179 | opal_irqs[i] = 0; | 185 | opal_irqs[i] = 0; |
| 180 | } | 186 | } |
| 181 | } | 187 | } |
diff --git a/arch/powerpc/platforms/powernv/opal-memory-errors.c b/arch/powerpc/platforms/powernv/opal-memory-errors.c index 4495f428b500..d9916ea62305 100644 --- a/arch/powerpc/platforms/powernv/opal-memory-errors.c +++ b/arch/powerpc/platforms/powernv/opal-memory-errors.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * OPAL asynchronus Memory error handling support in PowreNV. | 2 | * OPAL asynchronus Memory error handling support in PowerNV. |
| 3 | * | 3 | * |
| 4 | * This program is free software; you can redistribute it and/or modify | 4 | * This program is free software; you can redistribute it and/or modify |
| 5 | * it under the terms of the GNU General Public License as published by | 5 | * it under the terms of the GNU General Public License as published by |
diff --git a/arch/powerpc/platforms/powernv/opal-sensor.c b/arch/powerpc/platforms/powernv/opal-sensor.c index aa267f120033..0a7074bb91dc 100644 --- a/arch/powerpc/platforms/powernv/opal-sensor.c +++ b/arch/powerpc/platforms/powernv/opal-sensor.c | |||
| @@ -19,13 +19,10 @@ | |||
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
| 22 | #include <linux/mutex.h> | ||
| 23 | #include <linux/of_platform.h> | 22 | #include <linux/of_platform.h> |
| 24 | #include <asm/opal.h> | 23 | #include <asm/opal.h> |
| 25 | #include <asm/machdep.h> | 24 | #include <asm/machdep.h> |
| 26 | 25 | ||
| 27 | static DEFINE_MUTEX(opal_sensor_mutex); | ||
| 28 | |||
| 29 | /* | 26 | /* |
| 30 | * This will return sensor information to driver based on the requested sensor | 27 | * This will return sensor information to driver based on the requested sensor |
| 31 | * handle. A handle is an opaque id for the powernv, read by the driver from the | 28 | * handle. A handle is an opaque id for the powernv, read by the driver from the |
| @@ -38,13 +35,9 @@ int opal_get_sensor_data(u32 sensor_hndl, u32 *sensor_data) | |||
| 38 | __be32 data; | 35 | __be32 data; |
| 39 | 36 | ||
| 40 | token = opal_async_get_token_interruptible(); | 37 | token = opal_async_get_token_interruptible(); |
| 41 | if (token < 0) { | 38 | if (token < 0) |
| 42 | pr_err("%s: Couldn't get the token, returning\n", __func__); | 39 | return token; |
| 43 | ret = token; | ||
| 44 | goto out; | ||
| 45 | } | ||
| 46 | 40 | ||
| 47 | mutex_lock(&opal_sensor_mutex); | ||
| 48 | ret = opal_sensor_read(sensor_hndl, token, &data); | 41 | ret = opal_sensor_read(sensor_hndl, token, &data); |
| 49 | switch (ret) { | 42 | switch (ret) { |
| 50 | case OPAL_ASYNC_COMPLETION: | 43 | case OPAL_ASYNC_COMPLETION: |
| @@ -52,7 +45,7 @@ int opal_get_sensor_data(u32 sensor_hndl, u32 *sensor_data) | |||
| 52 | if (ret) { | 45 | if (ret) { |
| 53 | pr_err("%s: Failed to wait for the async response, %d\n", | 46 | pr_err("%s: Failed to wait for the async response, %d\n", |
| 54 | __func__, ret); | 47 | __func__, ret); |
| 55 | goto out_token; | 48 | goto out; |
| 56 | } | 49 | } |
| 57 | 50 | ||
| 58 | ret = opal_error_code(opal_get_async_rc(msg)); | 51 | ret = opal_error_code(opal_get_async_rc(msg)); |
| @@ -73,10 +66,8 @@ int opal_get_sensor_data(u32 sensor_hndl, u32 *sensor_data) | |||
| 73 | break; | 66 | break; |
| 74 | } | 67 | } |
| 75 | 68 | ||
| 76 | out_token: | ||
| 77 | mutex_unlock(&opal_sensor_mutex); | ||
| 78 | opal_async_release_token(token); | ||
| 79 | out: | 69 | out: |
| 70 | opal_async_release_token(token); | ||
| 80 | return ret; | 71 | return ret; |
| 81 | } | 72 | } |
| 82 | EXPORT_SYMBOL_GPL(opal_get_sensor_data); | 73 | EXPORT_SYMBOL_GPL(opal_get_sensor_data); |
diff --git a/arch/powerpc/platforms/powernv/opal-wrappers.S b/arch/powerpc/platforms/powernv/opal-wrappers.S index 8c1ede2d3f7e..6f4b00a2ac46 100644 --- a/arch/powerpc/platforms/powernv/opal-wrappers.S +++ b/arch/powerpc/platforms/powernv/opal-wrappers.S | |||
| @@ -94,7 +94,7 @@ opal_return: | |||
| 94 | * bytes (always BE) since MSR:LE will end up fixed up as a side | 94 | * bytes (always BE) since MSR:LE will end up fixed up as a side |
| 95 | * effect of the rfid. | 95 | * effect of the rfid. |
| 96 | */ | 96 | */ |
| 97 | FIXUP_ENDIAN | 97 | FIXUP_ENDIAN_HV |
| 98 | ld r2,PACATOC(r13); | 98 | ld r2,PACATOC(r13); |
| 99 | lwz r4,8(r1); | 99 | lwz r4,8(r1); |
| 100 | ld r5,PPC_LR_STKOFF(r1); | 100 | ld r5,PPC_LR_STKOFF(r1); |
| @@ -120,7 +120,7 @@ opal_real_call: | |||
| 120 | hrfid | 120 | hrfid |
| 121 | 121 | ||
| 122 | opal_return_realmode: | 122 | opal_return_realmode: |
| 123 | FIXUP_ENDIAN | 123 | FIXUP_ENDIAN_HV |
| 124 | ld r2,PACATOC(r13); | 124 | ld r2,PACATOC(r13); |
| 125 | lwz r11,8(r1); | 125 | lwz r11,8(r1); |
| 126 | ld r12,PPC_LR_STKOFF(r1) | 126 | ld r12,PPC_LR_STKOFF(r1) |
| @@ -307,6 +307,7 @@ OPAL_CALL(opal_xive_get_vp_info, OPAL_XIVE_GET_VP_INFO); | |||
| 307 | OPAL_CALL(opal_xive_set_vp_info, OPAL_XIVE_SET_VP_INFO); | 307 | OPAL_CALL(opal_xive_set_vp_info, OPAL_XIVE_SET_VP_INFO); |
| 308 | OPAL_CALL(opal_xive_sync, OPAL_XIVE_SYNC); | 308 | OPAL_CALL(opal_xive_sync, OPAL_XIVE_SYNC); |
| 309 | OPAL_CALL(opal_xive_dump, OPAL_XIVE_DUMP); | 309 | OPAL_CALL(opal_xive_dump, OPAL_XIVE_DUMP); |
| 310 | OPAL_CALL(opal_signal_system_reset, OPAL_SIGNAL_SYSTEM_RESET); | ||
| 310 | OPAL_CALL(opal_npu_init_context, OPAL_NPU_INIT_CONTEXT); | 311 | OPAL_CALL(opal_npu_init_context, OPAL_NPU_INIT_CONTEXT); |
| 311 | OPAL_CALL(opal_npu_destroy_context, OPAL_NPU_DESTROY_CONTEXT); | 312 | OPAL_CALL(opal_npu_destroy_context, OPAL_NPU_DESTROY_CONTEXT); |
| 312 | OPAL_CALL(opal_npu_map_lpar, OPAL_NPU_MAP_LPAR); | 313 | OPAL_CALL(opal_npu_map_lpar, OPAL_NPU_MAP_LPAR); |
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c index 65c79ecf5a4d..041ddbd1fc57 100644 --- a/arch/powerpc/platforms/powernv/opal.c +++ b/arch/powerpc/platforms/powernv/opal.c | |||
| @@ -998,6 +998,7 @@ int opal_error_code(int rc) | |||
| 998 | 998 | ||
| 999 | case OPAL_PARAMETER: return -EINVAL; | 999 | case OPAL_PARAMETER: return -EINVAL; |
| 1000 | case OPAL_ASYNC_COMPLETION: return -EINPROGRESS; | 1000 | case OPAL_ASYNC_COMPLETION: return -EINPROGRESS; |
| 1001 | case OPAL_BUSY: | ||
| 1001 | case OPAL_BUSY_EVENT: return -EBUSY; | 1002 | case OPAL_BUSY_EVENT: return -EBUSY; |
| 1002 | case OPAL_NO_MEM: return -ENOMEM; | 1003 | case OPAL_NO_MEM: return -ENOMEM; |
| 1003 | case OPAL_PERMISSION: return -EPERM; | 1004 | case OPAL_PERMISSION: return -EPERM; |
| @@ -1037,3 +1038,4 @@ EXPORT_SYMBOL_GPL(opal_write_oppanel_async); | |||
| 1037 | /* Export this for KVM */ | 1038 | /* Export this for KVM */ |
| 1038 | EXPORT_SYMBOL_GPL(opal_int_set_mfrr); | 1039 | EXPORT_SYMBOL_GPL(opal_int_set_mfrr); |
| 1039 | EXPORT_SYMBOL_GPL(opal_int_eoi); | 1040 | EXPORT_SYMBOL_GPL(opal_int_eoi); |
| 1041 | EXPORT_SYMBOL_GPL(opal_error_code); | ||
diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 57f9e55f4352..749055553064 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c | |||
| @@ -1002,9 +1002,12 @@ static int pnv_pci_vf_resource_shift(struct pci_dev *dev, int offset) | |||
| 1002 | } | 1002 | } |
| 1003 | 1003 | ||
| 1004 | /* | 1004 | /* |
| 1005 | * After doing so, there would be a "hole" in the /proc/iomem when | 1005 | * Since M64 BAR shares segments among all possible 256 PEs, |
| 1006 | * offset is a positive value. It looks like the device return some | 1006 | * we have to shift the beginning of PF IOV BAR to make it start from |
| 1007 | * mmio back to the system, which actually no one could use it. | 1007 | * the segment which belongs to the PE number assigned to the first VF. |
| 1008 | * This creates a "hole" in the /proc/iomem which could be used for | ||
| 1009 | * allocating other resources so we reserve this area below and | ||
| 1010 | * release when IOV is released. | ||
| 1008 | */ | 1011 | */ |
| 1009 | for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) { | 1012 | for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) { |
| 1010 | res = &dev->resource[i + PCI_IOV_RESOURCES]; | 1013 | res = &dev->resource[i + PCI_IOV_RESOURCES]; |
| @@ -1018,7 +1021,22 @@ static int pnv_pci_vf_resource_shift(struct pci_dev *dev, int offset) | |||
| 1018 | dev_info(&dev->dev, "VF BAR%d: %pR shifted to %pR (%sabling %d VFs shifted by %d)\n", | 1021 | dev_info(&dev->dev, "VF BAR%d: %pR shifted to %pR (%sabling %d VFs shifted by %d)\n", |
| 1019 | i, &res2, res, (offset > 0) ? "En" : "Dis", | 1022 | i, &res2, res, (offset > 0) ? "En" : "Dis", |
| 1020 | num_vfs, offset); | 1023 | num_vfs, offset); |
| 1024 | |||
| 1025 | if (offset < 0) { | ||
| 1026 | devm_release_resource(&dev->dev, &pdn->holes[i]); | ||
| 1027 | memset(&pdn->holes[i], 0, sizeof(pdn->holes[i])); | ||
| 1028 | } | ||
| 1029 | |||
| 1021 | pci_update_resource(dev, i + PCI_IOV_RESOURCES); | 1030 | pci_update_resource(dev, i + PCI_IOV_RESOURCES); |
| 1031 | |||
| 1032 | if (offset > 0) { | ||
| 1033 | pdn->holes[i].start = res2.start; | ||
| 1034 | pdn->holes[i].end = res2.start + size * offset - 1; | ||
| 1035 | pdn->holes[i].flags = IORESOURCE_BUS; | ||
| 1036 | pdn->holes[i].name = "pnv_iov_reserved"; | ||
| 1037 | devm_request_resource(&dev->dev, res->parent, | ||
| 1038 | &pdn->holes[i]); | ||
| 1039 | } | ||
| 1022 | } | 1040 | } |
| 1023 | return 0; | 1041 | return 0; |
| 1024 | } | 1042 | } |
| @@ -2779,7 +2797,7 @@ static long pnv_pci_ioda2_table_alloc_pages(int nid, __u64 bus_offset, | |||
| 2779 | if (!levels || (levels > POWERNV_IOMMU_MAX_LEVELS)) | 2797 | if (!levels || (levels > POWERNV_IOMMU_MAX_LEVELS)) |
| 2780 | return -EINVAL; | 2798 | return -EINVAL; |
| 2781 | 2799 | ||
| 2782 | if ((window_size > memory_hotplug_max()) || !is_power_of_2(window_size)) | 2800 | if (!is_power_of_2(window_size)) |
| 2783 | return -EINVAL; | 2801 | return -EINVAL; |
| 2784 | 2802 | ||
| 2785 | /* Adjust direct table size from window_size and levels */ | 2803 | /* Adjust direct table size from window_size and levels */ |
| @@ -3293,8 +3311,7 @@ static void pnv_pci_ioda_fixup(void) | |||
| 3293 | pnv_pci_ioda_create_dbgfs(); | 3311 | pnv_pci_ioda_create_dbgfs(); |
| 3294 | 3312 | ||
| 3295 | #ifdef CONFIG_EEH | 3313 | #ifdef CONFIG_EEH |
| 3296 | eeh_init(); | 3314 | pnv_eeh_post_init(); |
| 3297 | eeh_addr_cache_build(); | ||
| 3298 | #endif | 3315 | #endif |
| 3299 | } | 3316 | } |
| 3300 | 3317 | ||
diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h index b47f9406d97e..b772d7473896 100644 --- a/arch/powerpc/platforms/powernv/pci.h +++ b/arch/powerpc/platforms/powernv/pci.h | |||
| @@ -188,6 +188,9 @@ struct pnv_phb { | |||
| 188 | 188 | ||
| 189 | /* Bitmask for MMIO register usage */ | 189 | /* Bitmask for MMIO register usage */ |
| 190 | unsigned long mmio_atsd_usage; | 190 | unsigned long mmio_atsd_usage; |
| 191 | |||
| 192 | /* Do we need to explicitly flush the nest mmu? */ | ||
| 193 | bool nmmu_flush; | ||
| 191 | } npu; | 194 | } npu; |
| 192 | 195 | ||
| 193 | #ifdef CONFIG_CXL_BASE | 196 | #ifdef CONFIG_CXL_BASE |
| @@ -235,6 +238,7 @@ extern struct pnv_ioda_pe *pnv_ioda_get_pe(struct pci_dev *dev); | |||
| 235 | extern void pnv_set_msi_irq_chip(struct pnv_phb *phb, unsigned int virq); | 238 | extern void pnv_set_msi_irq_chip(struct pnv_phb *phb, unsigned int virq); |
| 236 | extern bool pnv_pci_enable_device_hook(struct pci_dev *dev); | 239 | extern bool pnv_pci_enable_device_hook(struct pci_dev *dev); |
| 237 | extern void pnv_pci_ioda2_set_bypass(struct pnv_ioda_pe *pe, bool enable); | 240 | extern void pnv_pci_ioda2_set_bypass(struct pnv_ioda_pe *pe, bool enable); |
| 241 | extern int pnv_eeh_post_init(void); | ||
| 238 | 242 | ||
| 239 | extern void pe_level_printk(const struct pnv_ioda_pe *pe, const char *level, | 243 | extern void pe_level_printk(const struct pnv_ioda_pe *pe, const char *level, |
| 240 | const char *fmt, ...); | 244 | const char *fmt, ...); |
diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c index bbb73aa0eb8f..1edfbc1e40f4 100644 --- a/arch/powerpc/platforms/powernv/setup.c +++ b/arch/powerpc/platforms/powernv/setup.c | |||
| @@ -36,6 +36,7 @@ | |||
| 36 | #include <asm/opal.h> | 36 | #include <asm/opal.h> |
| 37 | #include <asm/kexec.h> | 37 | #include <asm/kexec.h> |
| 38 | #include <asm/smp.h> | 38 | #include <asm/smp.h> |
| 39 | #include <asm/tm.h> | ||
| 39 | 40 | ||
| 40 | #include "powernv.h" | 41 | #include "powernv.h" |
| 41 | 42 | ||
| @@ -290,6 +291,7 @@ static void __init pnv_setup_machdep_opal(void) | |||
| 290 | ppc_md.restart = pnv_restart; | 291 | ppc_md.restart = pnv_restart; |
| 291 | pm_power_off = pnv_power_off; | 292 | pm_power_off = pnv_power_off; |
| 292 | ppc_md.halt = pnv_halt; | 293 | ppc_md.halt = pnv_halt; |
| 294 | /* ppc_md.system_reset_exception gets filled in by pnv_smp_init() */ | ||
| 293 | ppc_md.machine_check_exception = opal_machine_check; | 295 | ppc_md.machine_check_exception = opal_machine_check; |
| 294 | ppc_md.mce_check_early_recovery = opal_mce_check_early_recovery; | 296 | ppc_md.mce_check_early_recovery = opal_mce_check_early_recovery; |
| 295 | ppc_md.hmi_exception_early = opal_hmi_exception_early; | 297 | ppc_md.hmi_exception_early = opal_hmi_exception_early; |
| @@ -311,6 +313,28 @@ static int __init pnv_probe(void) | |||
| 311 | return 1; | 313 | return 1; |
| 312 | } | 314 | } |
| 313 | 315 | ||
| 316 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | ||
| 317 | void __init pnv_tm_init(void) | ||
| 318 | { | ||
| 319 | if (!firmware_has_feature(FW_FEATURE_OPAL) || | ||
| 320 | !pvr_version_is(PVR_POWER9) || | ||
| 321 | early_cpu_has_feature(CPU_FTR_TM)) | ||
| 322 | return; | ||
| 323 | |||
| 324 | if (opal_reinit_cpus(OPAL_REINIT_CPUS_TM_SUSPEND_DISABLED) != OPAL_SUCCESS) | ||
| 325 | return; | ||
| 326 | |||
| 327 | pr_info("Enabling TM (Transactional Memory) with Suspend Disabled\n"); | ||
| 328 | cur_cpu_spec->cpu_features |= CPU_FTR_TM; | ||
| 329 | /* Make sure "normal" HTM is off (it should be) */ | ||
| 330 | cur_cpu_spec->cpu_user_features2 &= ~PPC_FEATURE2_HTM; | ||
| 331 | /* Turn on no suspend mode, and HTM no SC */ | ||
| 332 | cur_cpu_spec->cpu_user_features2 |= PPC_FEATURE2_HTM_NO_SUSPEND | \ | ||
| 333 | PPC_FEATURE2_HTM_NOSC; | ||
| 334 | tm_suspend_disabled = true; | ||
| 335 | } | ||
| 336 | #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */ | ||
| 337 | |||
| 314 | /* | 338 | /* |
| 315 | * Returns the cpu frequency for 'cpu' in Hz. This is used by | 339 | * Returns the cpu frequency for 'cpu' in Hz. This is used by |
| 316 | * /proc/cpuinfo | 340 | * /proc/cpuinfo |
| @@ -319,7 +343,7 @@ static unsigned long pnv_get_proc_freq(unsigned int cpu) | |||
| 319 | { | 343 | { |
| 320 | unsigned long ret_freq; | 344 | unsigned long ret_freq; |
| 321 | 345 | ||
| 322 | ret_freq = cpufreq_quick_get(cpu) * 1000ul; | 346 | ret_freq = cpufreq_get(cpu) * 1000ul; |
| 323 | 347 | ||
| 324 | /* | 348 | /* |
| 325 | * If the backend cpufreq driver does not exist, | 349 | * If the backend cpufreq driver does not exist, |
diff --git a/arch/powerpc/platforms/powernv/smp.c b/arch/powerpc/platforms/powernv/smp.c index c17f81e433f7..ba030669eca1 100644 --- a/arch/powerpc/platforms/powernv/smp.c +++ b/arch/powerpc/platforms/powernv/smp.c | |||
| @@ -49,6 +49,13 @@ | |||
| 49 | 49 | ||
| 50 | static void pnv_smp_setup_cpu(int cpu) | 50 | static void pnv_smp_setup_cpu(int cpu) |
| 51 | { | 51 | { |
| 52 | /* | ||
| 53 | * P9 workaround for CI vector load (see traps.c), | ||
| 54 | * enable the corresponding HMI interrupt | ||
| 55 | */ | ||
| 56 | if (pvr_version_is(PVR_POWER9)) | ||
| 57 | mtspr(SPRN_HMEER, mfspr(SPRN_HMEER) | PPC_BIT(17)); | ||
| 58 | |||
| 52 | if (xive_enabled()) | 59 | if (xive_enabled()) |
| 53 | xive_smp_setup_cpu(); | 60 | xive_smp_setup_cpu(); |
| 54 | else if (cpu != boot_cpuid) | 61 | else if (cpu != boot_cpuid) |
| @@ -290,6 +297,54 @@ static void __init pnv_smp_probe(void) | |||
| 290 | } | 297 | } |
| 291 | } | 298 | } |
| 292 | 299 | ||
| 300 | static int pnv_system_reset_exception(struct pt_regs *regs) | ||
| 301 | { | ||
| 302 | if (smp_handle_nmi_ipi(regs)) | ||
| 303 | return 1; | ||
| 304 | return 0; | ||
| 305 | } | ||
| 306 | |||
| 307 | static int pnv_cause_nmi_ipi(int cpu) | ||
| 308 | { | ||
| 309 | int64_t rc; | ||
| 310 | |||
| 311 | if (cpu >= 0) { | ||
| 312 | rc = opal_signal_system_reset(get_hard_smp_processor_id(cpu)); | ||
| 313 | if (rc != OPAL_SUCCESS) | ||
| 314 | return 0; | ||
| 315 | return 1; | ||
| 316 | |||
| 317 | } else if (cpu == NMI_IPI_ALL_OTHERS) { | ||
| 318 | bool success = true; | ||
| 319 | int c; | ||
| 320 | |||
| 321 | |||
| 322 | /* | ||
| 323 | * We do not use broadcasts (yet), because it's not clear | ||
| 324 | * exactly what semantics Linux wants or the firmware should | ||
| 325 | * provide. | ||
| 326 | */ | ||
| 327 | for_each_online_cpu(c) { | ||
| 328 | if (c == smp_processor_id()) | ||
| 329 | continue; | ||
| 330 | |||
| 331 | rc = opal_signal_system_reset( | ||
| 332 | get_hard_smp_processor_id(c)); | ||
| 333 | if (rc != OPAL_SUCCESS) | ||
| 334 | success = false; | ||
| 335 | } | ||
| 336 | if (success) | ||
| 337 | return 1; | ||
| 338 | |||
| 339 | /* | ||
| 340 | * Caller will fall back to doorbells, which may pick | ||
| 341 | * up the remainders. | ||
| 342 | */ | ||
| 343 | } | ||
| 344 | |||
| 345 | return 0; | ||
| 346 | } | ||
| 347 | |||
| 293 | static struct smp_ops_t pnv_smp_ops = { | 348 | static struct smp_ops_t pnv_smp_ops = { |
| 294 | .message_pass = NULL, /* Use smp_muxed_ipi_message_pass */ | 349 | .message_pass = NULL, /* Use smp_muxed_ipi_message_pass */ |
| 295 | .cause_ipi = NULL, /* Filled at runtime by pnv_smp_probe() */ | 350 | .cause_ipi = NULL, /* Filled at runtime by pnv_smp_probe() */ |
| @@ -308,6 +363,10 @@ static struct smp_ops_t pnv_smp_ops = { | |||
| 308 | /* This is called very early during platform setup_arch */ | 363 | /* This is called very early during platform setup_arch */ |
| 309 | void __init pnv_smp_init(void) | 364 | void __init pnv_smp_init(void) |
| 310 | { | 365 | { |
| 366 | if (opal_check_token(OPAL_SIGNAL_SYSTEM_RESET)) { | ||
| 367 | ppc_md.system_reset_exception = pnv_system_reset_exception; | ||
| 368 | pnv_smp_ops.cause_nmi_ipi = pnv_cause_nmi_ipi; | ||
| 369 | } | ||
| 311 | smp_ops = &pnv_smp_ops; | 370 | smp_ops = &pnv_smp_ops; |
| 312 | 371 | ||
| 313 | #ifdef CONFIG_HOTPLUG_CPU | 372 | #ifdef CONFIG_HOTPLUG_CPU |
diff --git a/arch/powerpc/platforms/powernv/vas-debug.c b/arch/powerpc/platforms/powernv/vas-debug.c new file mode 100644 index 000000000000..ca22f1eae050 --- /dev/null +++ b/arch/powerpc/platforms/powernv/vas-debug.c | |||
| @@ -0,0 +1,209 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2016-17 IBM Corp. | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or | ||
| 5 | * modify it under the terms of the GNU General Public License | ||
| 6 | * as published by the Free Software Foundation; either version | ||
| 7 | * 2 of the License, or (at your option) any later version. | ||
| 8 | */ | ||
| 9 | |||
| 10 | #define pr_fmt(fmt) "vas: " fmt | ||
| 11 | |||
| 12 | #include <linux/types.h> | ||
| 13 | #include <linux/slab.h> | ||
| 14 | #include <linux/debugfs.h> | ||
| 15 | #include <linux/seq_file.h> | ||
| 16 | #include "vas.h" | ||
| 17 | |||
| 18 | static struct dentry *vas_debugfs; | ||
| 19 | |||
| 20 | static char *cop_to_str(int cop) | ||
| 21 | { | ||
| 22 | switch (cop) { | ||
| 23 | case VAS_COP_TYPE_FAULT: return "Fault"; | ||
| 24 | case VAS_COP_TYPE_842: return "NX-842 Normal Priority"; | ||
| 25 | case VAS_COP_TYPE_842_HIPRI: return "NX-842 High Priority"; | ||
| 26 | case VAS_COP_TYPE_GZIP: return "NX-GZIP Normal Priority"; | ||
| 27 | case VAS_COP_TYPE_GZIP_HIPRI: return "NX-GZIP High Priority"; | ||
| 28 | case VAS_COP_TYPE_FTW: return "Fast Thread-wakeup"; | ||
| 29 | default: return "Unknown"; | ||
| 30 | } | ||
| 31 | } | ||
| 32 | |||
| 33 | static int info_dbg_show(struct seq_file *s, void *private) | ||
| 34 | { | ||
| 35 | struct vas_window *window = s->private; | ||
| 36 | |||
| 37 | mutex_lock(&vas_mutex); | ||
| 38 | |||
| 39 | /* ensure window is not unmapped */ | ||
| 40 | if (!window->hvwc_map) | ||
| 41 | goto unlock; | ||
| 42 | |||
| 43 | seq_printf(s, "Type: %s, %s\n", cop_to_str(window->cop), | ||
| 44 | window->tx_win ? "Send" : "Receive"); | ||
| 45 | seq_printf(s, "Pid : %d\n", window->pid); | ||
| 46 | |||
| 47 | unlock: | ||
| 48 | mutex_unlock(&vas_mutex); | ||
| 49 | return 0; | ||
| 50 | } | ||
| 51 | |||
| 52 | static int info_dbg_open(struct inode *inode, struct file *file) | ||
| 53 | { | ||
| 54 | return single_open(file, info_dbg_show, inode->i_private); | ||
| 55 | } | ||
| 56 | |||
| 57 | static const struct file_operations info_fops = { | ||
| 58 | .open = info_dbg_open, | ||
| 59 | .read = seq_read, | ||
| 60 | .llseek = seq_lseek, | ||
| 61 | .release = single_release, | ||
| 62 | }; | ||
| 63 | |||
| 64 | static inline void print_reg(struct seq_file *s, struct vas_window *win, | ||
| 65 | char *name, u32 reg) | ||
| 66 | { | ||
| 67 | seq_printf(s, "0x%016llx %s\n", read_hvwc_reg(win, name, reg), name); | ||
| 68 | } | ||
| 69 | |||
| 70 | static int hvwc_dbg_show(struct seq_file *s, void *private) | ||
| 71 | { | ||
| 72 | struct vas_window *window = s->private; | ||
| 73 | |||
| 74 | mutex_lock(&vas_mutex); | ||
| 75 | |||
| 76 | /* ensure window is not unmapped */ | ||
| 77 | if (!window->hvwc_map) | ||
| 78 | goto unlock; | ||
| 79 | |||
| 80 | print_reg(s, window, VREG(LPID)); | ||
| 81 | print_reg(s, window, VREG(PID)); | ||
| 82 | print_reg(s, window, VREG(XLATE_MSR)); | ||
| 83 | print_reg(s, window, VREG(XLATE_LPCR)); | ||
| 84 | print_reg(s, window, VREG(XLATE_CTL)); | ||
| 85 | print_reg(s, window, VREG(AMR)); | ||
| 86 | print_reg(s, window, VREG(SEIDR)); | ||
| 87 | print_reg(s, window, VREG(FAULT_TX_WIN)); | ||
| 88 | print_reg(s, window, VREG(OSU_INTR_SRC_RA)); | ||
| 89 | print_reg(s, window, VREG(HV_INTR_SRC_RA)); | ||
| 90 | print_reg(s, window, VREG(PSWID)); | ||
| 91 | print_reg(s, window, VREG(LFIFO_BAR)); | ||
| 92 | print_reg(s, window, VREG(LDATA_STAMP_CTL)); | ||
| 93 | print_reg(s, window, VREG(LDMA_CACHE_CTL)); | ||
| 94 | print_reg(s, window, VREG(LRFIFO_PUSH)); | ||
| 95 | print_reg(s, window, VREG(CURR_MSG_COUNT)); | ||
| 96 | print_reg(s, window, VREG(LNOTIFY_AFTER_COUNT)); | ||
| 97 | print_reg(s, window, VREG(LRX_WCRED)); | ||
| 98 | print_reg(s, window, VREG(LRX_WCRED_ADDER)); | ||
| 99 | print_reg(s, window, VREG(TX_WCRED)); | ||
| 100 | print_reg(s, window, VREG(TX_WCRED_ADDER)); | ||
| 101 | print_reg(s, window, VREG(LFIFO_SIZE)); | ||
| 102 | print_reg(s, window, VREG(WINCTL)); | ||
| 103 | print_reg(s, window, VREG(WIN_STATUS)); | ||
| 104 | print_reg(s, window, VREG(WIN_CTX_CACHING_CTL)); | ||
| 105 | print_reg(s, window, VREG(TX_RSVD_BUF_COUNT)); | ||
| 106 | print_reg(s, window, VREG(LRFIFO_WIN_PTR)); | ||
| 107 | print_reg(s, window, VREG(LNOTIFY_CTL)); | ||
| 108 | print_reg(s, window, VREG(LNOTIFY_PID)); | ||
| 109 | print_reg(s, window, VREG(LNOTIFY_LPID)); | ||
| 110 | print_reg(s, window, VREG(LNOTIFY_TID)); | ||
| 111 | print_reg(s, window, VREG(LNOTIFY_SCOPE)); | ||
| 112 | print_reg(s, window, VREG(NX_UTIL_ADDER)); | ||
| 113 | unlock: | ||
| 114 | mutex_unlock(&vas_mutex); | ||
| 115 | return 0; | ||
| 116 | } | ||
| 117 | |||
| 118 | static int hvwc_dbg_open(struct inode *inode, struct file *file) | ||
| 119 | { | ||
| 120 | return single_open(file, hvwc_dbg_show, inode->i_private); | ||
| 121 | } | ||
| 122 | |||
| 123 | static const struct file_operations hvwc_fops = { | ||
| 124 | .open = hvwc_dbg_open, | ||
| 125 | .read = seq_read, | ||
| 126 | .llseek = seq_lseek, | ||
| 127 | .release = single_release, | ||
| 128 | }; | ||
| 129 | |||
| 130 | void vas_window_free_dbgdir(struct vas_window *window) | ||
| 131 | { | ||
| 132 | if (window->dbgdir) { | ||
| 133 | debugfs_remove_recursive(window->dbgdir); | ||
| 134 | kfree(window->dbgname); | ||
| 135 | window->dbgdir = NULL; | ||
| 136 | window->dbgname = NULL; | ||
| 137 | } | ||
| 138 | } | ||
| 139 | |||
| 140 | void vas_window_init_dbgdir(struct vas_window *window) | ||
| 141 | { | ||
| 142 | struct dentry *f, *d; | ||
| 143 | |||
| 144 | if (!window->vinst->dbgdir) | ||
| 145 | return; | ||
| 146 | |||
| 147 | window->dbgname = kzalloc(16, GFP_KERNEL); | ||
| 148 | if (!window->dbgname) | ||
| 149 | return; | ||
| 150 | |||
| 151 | snprintf(window->dbgname, 16, "w%d", window->winid); | ||
| 152 | |||
| 153 | d = debugfs_create_dir(window->dbgname, window->vinst->dbgdir); | ||
| 154 | if (IS_ERR(d)) | ||
| 155 | goto free_name; | ||
| 156 | |||
| 157 | window->dbgdir = d; | ||
| 158 | |||
| 159 | f = debugfs_create_file("info", 0444, d, window, &info_fops); | ||
| 160 | if (IS_ERR(f)) | ||
| 161 | goto remove_dir; | ||
| 162 | |||
| 163 | f = debugfs_create_file("hvwc", 0444, d, window, &hvwc_fops); | ||
| 164 | if (IS_ERR(f)) | ||
| 165 | goto remove_dir; | ||
| 166 | |||
| 167 | return; | ||
| 168 | |||
| 169 | free_name: | ||
| 170 | kfree(window->dbgname); | ||
| 171 | window->dbgname = NULL; | ||
| 172 | |||
| 173 | remove_dir: | ||
| 174 | debugfs_remove_recursive(window->dbgdir); | ||
| 175 | window->dbgdir = NULL; | ||
| 176 | } | ||
| 177 | |||
| 178 | void vas_instance_init_dbgdir(struct vas_instance *vinst) | ||
| 179 | { | ||
| 180 | struct dentry *d; | ||
| 181 | |||
| 182 | if (!vas_debugfs) | ||
| 183 | return; | ||
| 184 | |||
| 185 | vinst->dbgname = kzalloc(16, GFP_KERNEL); | ||
| 186 | if (!vinst->dbgname) | ||
| 187 | return; | ||
| 188 | |||
| 189 | snprintf(vinst->dbgname, 16, "v%d", vinst->vas_id); | ||
| 190 | |||
| 191 | d = debugfs_create_dir(vinst->dbgname, vas_debugfs); | ||
| 192 | if (IS_ERR(d)) | ||
| 193 | goto free_name; | ||
| 194 | |||
| 195 | vinst->dbgdir = d; | ||
| 196 | return; | ||
| 197 | |||
| 198 | free_name: | ||
| 199 | kfree(vinst->dbgname); | ||
| 200 | vinst->dbgname = NULL; | ||
| 201 | vinst->dbgdir = NULL; | ||
| 202 | } | ||
| 203 | |||
| 204 | void vas_init_dbgdir(void) | ||
| 205 | { | ||
| 206 | vas_debugfs = debugfs_create_dir("vas", NULL); | ||
| 207 | if (IS_ERR(vas_debugfs)) | ||
| 208 | vas_debugfs = NULL; | ||
| 209 | } | ||
diff --git a/arch/powerpc/platforms/powernv/vas-window.c b/arch/powerpc/platforms/powernv/vas-window.c index 5aae845b8cd9..2b3eb01ab110 100644 --- a/arch/powerpc/platforms/powernv/vas-window.c +++ b/arch/powerpc/platforms/powernv/vas-window.c | |||
| @@ -16,7 +16,8 @@ | |||
| 16 | #include <linux/log2.h> | 16 | #include <linux/log2.h> |
| 17 | #include <linux/rcupdate.h> | 17 | #include <linux/rcupdate.h> |
| 18 | #include <linux/cred.h> | 18 | #include <linux/cred.h> |
| 19 | 19 | #include <asm/switch_to.h> | |
| 20 | #include <asm/ppc-opcode.h> | ||
| 20 | #include "vas.h" | 21 | #include "vas.h" |
| 21 | #include "copy-paste.h" | 22 | #include "copy-paste.h" |
| 22 | 23 | ||
| @@ -40,6 +41,16 @@ static void compute_paste_address(struct vas_window *window, u64 *addr, int *len | |||
| 40 | pr_debug("Txwin #%d: Paste addr 0x%llx\n", winid, *addr); | 41 | pr_debug("Txwin #%d: Paste addr 0x%llx\n", winid, *addr); |
| 41 | } | 42 | } |
| 42 | 43 | ||
| 44 | u64 vas_win_paste_addr(struct vas_window *win) | ||
| 45 | { | ||
| 46 | u64 addr; | ||
| 47 | |||
| 48 | compute_paste_address(win, &addr, NULL); | ||
| 49 | |||
| 50 | return addr; | ||
| 51 | } | ||
| 52 | EXPORT_SYMBOL(vas_win_paste_addr); | ||
| 53 | |||
| 43 | static inline void get_hvwc_mmio_bar(struct vas_window *window, | 54 | static inline void get_hvwc_mmio_bar(struct vas_window *window, |
| 44 | u64 *start, int *len) | 55 | u64 *start, int *len) |
| 45 | { | 56 | { |
| @@ -145,23 +156,37 @@ static void unmap_paste_region(struct vas_window *window) | |||
| 145 | } | 156 | } |
| 146 | 157 | ||
| 147 | /* | 158 | /* |
| 148 | * Unmap the MMIO regions for a window. | 159 | * Unmap the MMIO regions for a window. Hold the vas_mutex so we don't |
| 160 | * unmap when the window's debugfs dir is in use. This serializes close | ||
| 161 | * of a window even on another VAS instance but since its not a critical | ||
| 162 | * path, just minimize the time we hold the mutex for now. We can add | ||
| 163 | * a per-instance mutex later if necessary. | ||
| 149 | */ | 164 | */ |
| 150 | static void unmap_winctx_mmio_bars(struct vas_window *window) | 165 | static void unmap_winctx_mmio_bars(struct vas_window *window) |
| 151 | { | 166 | { |
| 152 | int len; | 167 | int len; |
| 168 | void *uwc_map; | ||
| 169 | void *hvwc_map; | ||
| 153 | u64 busaddr_start; | 170 | u64 busaddr_start; |
| 154 | 171 | ||
| 155 | if (window->hvwc_map) { | 172 | mutex_lock(&vas_mutex); |
| 173 | |||
| 174 | hvwc_map = window->hvwc_map; | ||
| 175 | window->hvwc_map = NULL; | ||
| 176 | |||
| 177 | uwc_map = window->uwc_map; | ||
| 178 | window->uwc_map = NULL; | ||
| 179 | |||
| 180 | mutex_unlock(&vas_mutex); | ||
| 181 | |||
| 182 | if (hvwc_map) { | ||
| 156 | get_hvwc_mmio_bar(window, &busaddr_start, &len); | 183 | get_hvwc_mmio_bar(window, &busaddr_start, &len); |
| 157 | unmap_region(window->hvwc_map, busaddr_start, len); | 184 | unmap_region(hvwc_map, busaddr_start, len); |
| 158 | window->hvwc_map = NULL; | ||
| 159 | } | 185 | } |
| 160 | 186 | ||
| 161 | if (window->uwc_map) { | 187 | if (uwc_map) { |
| 162 | get_uwc_mmio_bar(window, &busaddr_start, &len); | 188 | get_uwc_mmio_bar(window, &busaddr_start, &len); |
| 163 | unmap_region(window->uwc_map, busaddr_start, len); | 189 | unmap_region(uwc_map, busaddr_start, len); |
| 164 | window->uwc_map = NULL; | ||
| 165 | } | 190 | } |
| 166 | } | 191 | } |
| 167 | 192 | ||
| @@ -528,6 +553,9 @@ static void vas_window_free(struct vas_window *window) | |||
| 528 | struct vas_instance *vinst = window->vinst; | 553 | struct vas_instance *vinst = window->vinst; |
| 529 | 554 | ||
| 530 | unmap_winctx_mmio_bars(window); | 555 | unmap_winctx_mmio_bars(window); |
| 556 | |||
| 557 | vas_window_free_dbgdir(window); | ||
| 558 | |||
| 531 | kfree(window); | 559 | kfree(window); |
| 532 | 560 | ||
| 533 | vas_release_window_id(&vinst->ida, winid); | 561 | vas_release_window_id(&vinst->ida, winid); |
| @@ -552,6 +580,8 @@ static struct vas_window *vas_window_alloc(struct vas_instance *vinst) | |||
| 552 | if (map_winctx_mmio_bars(window)) | 580 | if (map_winctx_mmio_bars(window)) |
| 553 | goto out_free; | 581 | goto out_free; |
| 554 | 582 | ||
| 583 | vas_window_init_dbgdir(window); | ||
| 584 | |||
| 555 | return window; | 585 | return window; |
| 556 | 586 | ||
| 557 | out_free: | 587 | out_free: |
| @@ -569,6 +599,32 @@ static void put_rx_win(struct vas_window *rxwin) | |||
| 569 | } | 599 | } |
| 570 | 600 | ||
| 571 | /* | 601 | /* |
| 602 | * Find the user space receive window given the @pswid. | ||
| 603 | * - We must have a valid vasid and it must belong to this instance. | ||
| 604 | * (so both send and receive windows are on the same VAS instance) | ||
| 605 | * - The window must refer to an OPEN, FTW, RECEIVE window. | ||
| 606 | * | ||
| 607 | * NOTE: We access ->windows[] table and assume that vinst->mutex is held. | ||
| 608 | */ | ||
| 609 | static struct vas_window *get_user_rxwin(struct vas_instance *vinst, u32 pswid) | ||
| 610 | { | ||
| 611 | int vasid, winid; | ||
| 612 | struct vas_window *rxwin; | ||
| 613 | |||
| 614 | decode_pswid(pswid, &vasid, &winid); | ||
| 615 | |||
| 616 | if (vinst->vas_id != vasid) | ||
| 617 | return ERR_PTR(-EINVAL); | ||
| 618 | |||
| 619 | rxwin = vinst->windows[winid]; | ||
| 620 | |||
| 621 | if (!rxwin || rxwin->tx_win || rxwin->cop != VAS_COP_TYPE_FTW) | ||
| 622 | return ERR_PTR(-EINVAL); | ||
| 623 | |||
| 624 | return rxwin; | ||
| 625 | } | ||
| 626 | |||
| 627 | /* | ||
| 572 | * Get the VAS receive window associated with NX engine identified | 628 | * Get the VAS receive window associated with NX engine identified |
| 573 | * by @cop and if applicable, @pswid. | 629 | * by @cop and if applicable, @pswid. |
| 574 | * | 630 | * |
| @@ -581,10 +637,10 @@ static struct vas_window *get_vinst_rxwin(struct vas_instance *vinst, | |||
| 581 | 637 | ||
| 582 | mutex_lock(&vinst->mutex); | 638 | mutex_lock(&vinst->mutex); |
| 583 | 639 | ||
| 584 | if (cop == VAS_COP_TYPE_842 || cop == VAS_COP_TYPE_842_HIPRI) | 640 | if (cop == VAS_COP_TYPE_FTW) |
| 585 | rxwin = vinst->rxwin[cop] ?: ERR_PTR(-EINVAL); | 641 | rxwin = get_user_rxwin(vinst, pswid); |
| 586 | else | 642 | else |
| 587 | rxwin = ERR_PTR(-EINVAL); | 643 | rxwin = vinst->rxwin[cop] ?: ERR_PTR(-EINVAL); |
| 588 | 644 | ||
| 589 | if (!IS_ERR(rxwin)) | 645 | if (!IS_ERR(rxwin)) |
| 590 | atomic_inc(&rxwin->num_txwins); | 646 | atomic_inc(&rxwin->num_txwins); |
| @@ -674,15 +730,18 @@ static void init_winctx_for_rxwin(struct vas_window *rxwin, | |||
| 674 | 730 | ||
| 675 | winctx->rx_fifo = rxattr->rx_fifo; | 731 | winctx->rx_fifo = rxattr->rx_fifo; |
| 676 | winctx->rx_fifo_size = rxattr->rx_fifo_size; | 732 | winctx->rx_fifo_size = rxattr->rx_fifo_size; |
| 677 | winctx->wcreds_max = rxattr->wcreds_max ?: VAS_WCREDS_DEFAULT; | 733 | winctx->wcreds_max = rxwin->wcreds_max; |
| 678 | winctx->pin_win = rxattr->pin_win; | 734 | winctx->pin_win = rxattr->pin_win; |
| 679 | 735 | ||
| 680 | winctx->nx_win = rxattr->nx_win; | 736 | winctx->nx_win = rxattr->nx_win; |
| 681 | winctx->fault_win = rxattr->fault_win; | 737 | winctx->fault_win = rxattr->fault_win; |
| 738 | winctx->user_win = rxattr->user_win; | ||
| 739 | winctx->rej_no_credit = rxattr->rej_no_credit; | ||
| 682 | winctx->rx_word_mode = rxattr->rx_win_ord_mode; | 740 | winctx->rx_word_mode = rxattr->rx_win_ord_mode; |
| 683 | winctx->tx_word_mode = rxattr->tx_win_ord_mode; | 741 | winctx->tx_word_mode = rxattr->tx_win_ord_mode; |
| 684 | winctx->rx_wcred_mode = rxattr->rx_wcred_mode; | 742 | winctx->rx_wcred_mode = rxattr->rx_wcred_mode; |
| 685 | winctx->tx_wcred_mode = rxattr->tx_wcred_mode; | 743 | winctx->tx_wcred_mode = rxattr->tx_wcred_mode; |
| 744 | winctx->notify_early = rxattr->notify_early; | ||
| 686 | 745 | ||
| 687 | if (winctx->nx_win) { | 746 | if (winctx->nx_win) { |
| 688 | winctx->data_stamp = true; | 747 | winctx->data_stamp = true; |
| @@ -723,7 +782,10 @@ static void init_winctx_for_rxwin(struct vas_window *rxwin, | |||
| 723 | static bool rx_win_args_valid(enum vas_cop_type cop, | 782 | static bool rx_win_args_valid(enum vas_cop_type cop, |
| 724 | struct vas_rx_win_attr *attr) | 783 | struct vas_rx_win_attr *attr) |
| 725 | { | 784 | { |
| 726 | dump_rx_win_attr(attr); | 785 | pr_debug("Rxattr: fault %d, notify %d, intr %d, early %d, fifo %d\n", |
| 786 | attr->fault_win, attr->notify_disable, | ||
| 787 | attr->intr_disable, attr->notify_early, | ||
| 788 | attr->rx_fifo_size); | ||
| 727 | 789 | ||
| 728 | if (cop >= VAS_COP_TYPE_MAX) | 790 | if (cop >= VAS_COP_TYPE_MAX) |
| 729 | return false; | 791 | return false; |
| @@ -735,6 +797,9 @@ static bool rx_win_args_valid(enum vas_cop_type cop, | |||
| 735 | if (attr->rx_fifo_size > VAS_RX_FIFO_SIZE_MAX) | 797 | if (attr->rx_fifo_size > VAS_RX_FIFO_SIZE_MAX) |
| 736 | return false; | 798 | return false; |
| 737 | 799 | ||
| 800 | if (attr->wcreds_max > VAS_RX_WCREDS_MAX) | ||
| 801 | return false; | ||
| 802 | |||
| 738 | if (attr->nx_win) { | 803 | if (attr->nx_win) { |
| 739 | /* cannot be fault or user window if it is nx */ | 804 | /* cannot be fault or user window if it is nx */ |
| 740 | if (attr->fault_win || attr->user_win) | 805 | if (attr->fault_win || attr->user_win) |
| @@ -835,6 +900,7 @@ struct vas_window *vas_rx_win_open(int vasid, enum vas_cop_type cop, | |||
| 835 | rxwin->nx_win = rxattr->nx_win; | 900 | rxwin->nx_win = rxattr->nx_win; |
| 836 | rxwin->user_win = rxattr->user_win; | 901 | rxwin->user_win = rxattr->user_win; |
| 837 | rxwin->cop = cop; | 902 | rxwin->cop = cop; |
| 903 | rxwin->wcreds_max = rxattr->wcreds_max ?: VAS_WCREDS_DEFAULT; | ||
| 838 | if (rxattr->user_win) | 904 | if (rxattr->user_win) |
| 839 | rxwin->pid = task_pid_vnr(current); | 905 | rxwin->pid = task_pid_vnr(current); |
| 840 | 906 | ||
| @@ -884,21 +950,23 @@ static void init_winctx_for_txwin(struct vas_window *txwin, | |||
| 884 | */ | 950 | */ |
| 885 | memset(winctx, 0, sizeof(struct vas_winctx)); | 951 | memset(winctx, 0, sizeof(struct vas_winctx)); |
| 886 | 952 | ||
| 887 | winctx->wcreds_max = txattr->wcreds_max ?: VAS_WCREDS_DEFAULT; | 953 | winctx->wcreds_max = txwin->wcreds_max; |
| 888 | 954 | ||
| 889 | winctx->user_win = txattr->user_win; | 955 | winctx->user_win = txattr->user_win; |
| 890 | winctx->nx_win = txwin->rxwin->nx_win; | 956 | winctx->nx_win = txwin->rxwin->nx_win; |
| 891 | winctx->pin_win = txattr->pin_win; | 957 | winctx->pin_win = txattr->pin_win; |
| 958 | winctx->rej_no_credit = txattr->rej_no_credit; | ||
| 959 | winctx->rsvd_txbuf_enable = txattr->rsvd_txbuf_enable; | ||
| 892 | 960 | ||
| 893 | winctx->rx_wcred_mode = txattr->rx_wcred_mode; | 961 | winctx->rx_wcred_mode = txattr->rx_wcred_mode; |
| 894 | winctx->tx_wcred_mode = txattr->tx_wcred_mode; | 962 | winctx->tx_wcred_mode = txattr->tx_wcred_mode; |
| 895 | winctx->rx_word_mode = txattr->rx_win_ord_mode; | 963 | winctx->rx_word_mode = txattr->rx_win_ord_mode; |
| 896 | winctx->tx_word_mode = txattr->tx_win_ord_mode; | 964 | winctx->tx_word_mode = txattr->tx_win_ord_mode; |
| 965 | winctx->rsvd_txbuf_count = txattr->rsvd_txbuf_count; | ||
| 897 | 966 | ||
| 898 | if (winctx->nx_win) { | 967 | winctx->intr_disable = true; |
| 968 | if (winctx->nx_win) | ||
| 899 | winctx->data_stamp = true; | 969 | winctx->data_stamp = true; |
| 900 | winctx->intr_disable = true; | ||
| 901 | } | ||
| 902 | 970 | ||
| 903 | winctx->lpid = txattr->lpid; | 971 | winctx->lpid = txattr->lpid; |
| 904 | winctx->pidr = txattr->pidr; | 972 | winctx->pidr = txattr->pidr; |
| @@ -921,6 +989,9 @@ static bool tx_win_args_valid(enum vas_cop_type cop, | |||
| 921 | if (cop > VAS_COP_TYPE_MAX) | 989 | if (cop > VAS_COP_TYPE_MAX) |
| 922 | return false; | 990 | return false; |
| 923 | 991 | ||
| 992 | if (attr->wcreds_max > VAS_TX_WCREDS_MAX) | ||
| 993 | return false; | ||
| 994 | |||
| 924 | if (attr->user_win && | 995 | if (attr->user_win && |
| 925 | (cop != VAS_COP_TYPE_FTW || attr->rsvd_txbuf_count)) | 996 | (cop != VAS_COP_TYPE_FTW || attr->rsvd_txbuf_count)) |
| 926 | return false; | 997 | return false; |
| @@ -940,6 +1011,14 @@ struct vas_window *vas_tx_win_open(int vasid, enum vas_cop_type cop, | |||
| 940 | if (!tx_win_args_valid(cop, attr)) | 1011 | if (!tx_win_args_valid(cop, attr)) |
| 941 | return ERR_PTR(-EINVAL); | 1012 | return ERR_PTR(-EINVAL); |
| 942 | 1013 | ||
| 1014 | /* | ||
| 1015 | * If caller did not specify a vasid but specified the PSWID of a | ||
| 1016 | * receive window (applicable only to FTW windows), use the vasid | ||
| 1017 | * from that receive window. | ||
| 1018 | */ | ||
| 1019 | if (vasid == -1 && attr->pswid) | ||
| 1020 | decode_pswid(attr->pswid, &vasid, NULL); | ||
| 1021 | |||
| 943 | vinst = find_vas_instance(vasid); | 1022 | vinst = find_vas_instance(vasid); |
| 944 | if (!vinst) { | 1023 | if (!vinst) { |
| 945 | pr_devel("vasid %d not found!\n", vasid); | 1024 | pr_devel("vasid %d not found!\n", vasid); |
| @@ -958,11 +1037,13 @@ struct vas_window *vas_tx_win_open(int vasid, enum vas_cop_type cop, | |||
| 958 | goto put_rxwin; | 1037 | goto put_rxwin; |
| 959 | } | 1038 | } |
| 960 | 1039 | ||
| 1040 | txwin->cop = cop; | ||
| 961 | txwin->tx_win = 1; | 1041 | txwin->tx_win = 1; |
| 962 | txwin->rxwin = rxwin; | 1042 | txwin->rxwin = rxwin; |
| 963 | txwin->nx_win = txwin->rxwin->nx_win; | 1043 | txwin->nx_win = txwin->rxwin->nx_win; |
| 964 | txwin->pid = attr->pid; | 1044 | txwin->pid = attr->pid; |
| 965 | txwin->user_win = attr->user_win; | 1045 | txwin->user_win = attr->user_win; |
| 1046 | txwin->wcreds_max = attr->wcreds_max ?: VAS_WCREDS_DEFAULT; | ||
| 966 | 1047 | ||
| 967 | init_winctx_for_txwin(txwin, attr, &winctx); | 1048 | init_winctx_for_txwin(txwin, attr, &winctx); |
| 968 | 1049 | ||
| @@ -984,6 +1065,14 @@ struct vas_window *vas_tx_win_open(int vasid, enum vas_cop_type cop, | |||
| 984 | } | 1065 | } |
| 985 | } | 1066 | } |
| 986 | 1067 | ||
| 1068 | /* | ||
| 1069 | * Now that we have a send window, ensure context switch issues | ||
| 1070 | * CP_ABORT for this thread. | ||
| 1071 | */ | ||
| 1072 | rc = -EINVAL; | ||
| 1073 | if (set_thread_uses_vas() < 0) | ||
| 1074 | goto free_window; | ||
| 1075 | |||
| 987 | set_vinst_win(vinst, txwin); | 1076 | set_vinst_win(vinst, txwin); |
| 988 | 1077 | ||
| 989 | return txwin; | 1078 | return txwin; |
| @@ -1038,50 +1127,110 @@ int vas_paste_crb(struct vas_window *txwin, int offset, bool re) | |||
| 1038 | else | 1127 | else |
| 1039 | rc = -EINVAL; | 1128 | rc = -EINVAL; |
| 1040 | 1129 | ||
| 1041 | print_fifo_msg_count(txwin); | 1130 | pr_debug("Txwin #%d: Msg count %llu\n", txwin->winid, |
| 1131 | read_hvwc_reg(txwin, VREG(LRFIFO_PUSH))); | ||
| 1042 | 1132 | ||
| 1043 | return rc; | 1133 | return rc; |
| 1044 | } | 1134 | } |
| 1045 | EXPORT_SYMBOL_GPL(vas_paste_crb); | 1135 | EXPORT_SYMBOL_GPL(vas_paste_crb); |
| 1046 | 1136 | ||
| 1137 | /* | ||
| 1138 | * If credit checking is enabled for this window, poll for the return | ||
| 1139 | * of window credits (i.e for NX engines to process any outstanding CRBs). | ||
| 1140 | * Since NX-842 waits for the CRBs to be processed before closing the | ||
| 1141 | * window, we should not have to wait for too long. | ||
| 1142 | * | ||
| 1143 | * TODO: We retry in 10ms intervals now. We could/should probably peek at | ||
| 1144 | * the VAS_LRFIFO_PUSH_OFFSET register to get an estimate of pending | ||
| 1145 | * CRBs on the FIFO and compute the delay dynamically on each retry. | ||
| 1146 | * But that is not really needed until we support NX-GZIP access from | ||
| 1147 | * user space. (NX-842 driver waits for CSB and Fast thread-wakeup | ||
| 1148 | * doesn't use credit checking). | ||
| 1149 | */ | ||
| 1150 | static void poll_window_credits(struct vas_window *window) | ||
| 1151 | { | ||
| 1152 | u64 val; | ||
| 1153 | int creds, mode; | ||
| 1154 | |||
| 1155 | val = read_hvwc_reg(window, VREG(WINCTL)); | ||
| 1156 | if (window->tx_win) | ||
| 1157 | mode = GET_FIELD(VAS_WINCTL_TX_WCRED_MODE, val); | ||
| 1158 | else | ||
| 1159 | mode = GET_FIELD(VAS_WINCTL_RX_WCRED_MODE, val); | ||
| 1160 | |||
| 1161 | if (!mode) | ||
| 1162 | return; | ||
| 1163 | retry: | ||
| 1164 | if (window->tx_win) { | ||
| 1165 | val = read_hvwc_reg(window, VREG(TX_WCRED)); | ||
| 1166 | creds = GET_FIELD(VAS_TX_WCRED, val); | ||
| 1167 | } else { | ||
| 1168 | val = read_hvwc_reg(window, VREG(LRX_WCRED)); | ||
| 1169 | creds = GET_FIELD(VAS_LRX_WCRED, val); | ||
| 1170 | } | ||
| 1171 | |||
| 1172 | if (creds < window->wcreds_max) { | ||
| 1173 | val = 0; | ||
| 1174 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
| 1175 | schedule_timeout(msecs_to_jiffies(10)); | ||
| 1176 | goto retry; | ||
| 1177 | } | ||
| 1178 | } | ||
| 1179 | |||
| 1180 | /* | ||
| 1181 | * Wait for the window to go to "not-busy" state. It should only take a | ||
| 1182 | * short time to queue a CRB, so window should not be busy for too long. | ||
| 1183 | * Trying 5ms intervals. | ||
| 1184 | */ | ||
| 1047 | static void poll_window_busy_state(struct vas_window *window) | 1185 | static void poll_window_busy_state(struct vas_window *window) |
| 1048 | { | 1186 | { |
| 1049 | int busy; | 1187 | int busy; |
| 1050 | u64 val; | 1188 | u64 val; |
| 1051 | 1189 | ||
| 1052 | retry: | 1190 | retry: |
| 1053 | /* | ||
| 1054 | * Poll Window Busy flag | ||
| 1055 | */ | ||
| 1056 | val = read_hvwc_reg(window, VREG(WIN_STATUS)); | 1191 | val = read_hvwc_reg(window, VREG(WIN_STATUS)); |
| 1057 | busy = GET_FIELD(VAS_WIN_BUSY, val); | 1192 | busy = GET_FIELD(VAS_WIN_BUSY, val); |
| 1058 | if (busy) { | 1193 | if (busy) { |
| 1059 | val = 0; | 1194 | val = 0; |
| 1060 | set_current_state(TASK_UNINTERRUPTIBLE); | 1195 | set_current_state(TASK_UNINTERRUPTIBLE); |
| 1061 | schedule_timeout(HZ); | 1196 | schedule_timeout(msecs_to_jiffies(5)); |
| 1062 | goto retry; | 1197 | goto retry; |
| 1063 | } | 1198 | } |
| 1064 | } | 1199 | } |
| 1065 | 1200 | ||
| 1201 | /* | ||
| 1202 | * Have the hardware cast a window out of cache and wait for it to | ||
| 1203 | * be completed. | ||
| 1204 | * | ||
| 1205 | * NOTE: It can take a relatively long time to cast the window context | ||
| 1206 | * out of the cache. It is not strictly necessary to cast out if: | ||
| 1207 | * | ||
| 1208 | * - we clear the "Pin Window" bit (so hardware is free to evict) | ||
| 1209 | * | ||
| 1210 | * - we re-initialize the window context when it is reassigned. | ||
| 1211 | * | ||
| 1212 | * We do the former in vas_win_close() and latter in vas_win_open(). | ||
| 1213 | * So, ignoring the cast-out for now. We can add it as needed. If | ||
| 1214 | * casting out becomes necessary we should consider offloading the | ||
| 1215 | * job to a worker thread, so the window close can proceed quickly. | ||
| 1216 | */ | ||
| 1066 | static void poll_window_castout(struct vas_window *window) | 1217 | static void poll_window_castout(struct vas_window *window) |
| 1067 | { | 1218 | { |
| 1068 | int cached; | 1219 | /* stub for now */ |
| 1069 | u64 val; | 1220 | } |
| 1070 | 1221 | ||
| 1071 | /* Cast window context out of the cache */ | 1222 | /* |
| 1072 | retry: | 1223 | * Unpin and close a window so no new requests are accepted and the |
| 1073 | val = read_hvwc_reg(window, VREG(WIN_CTX_CACHING_CTL)); | 1224 | * hardware can evict this window from cache if necessary. |
| 1074 | cached = GET_FIELD(VAS_WIN_CACHE_STATUS, val); | 1225 | */ |
| 1075 | if (cached) { | 1226 | static void unpin_close_window(struct vas_window *window) |
| 1076 | val = 0ULL; | 1227 | { |
| 1077 | val = SET_FIELD(VAS_CASTOUT_REQ, val, 1); | 1228 | u64 val; |
| 1078 | val = SET_FIELD(VAS_PUSH_TO_MEM, val, 0); | ||
| 1079 | write_hvwc_reg(window, VREG(WIN_CTX_CACHING_CTL), val); | ||
| 1080 | 1229 | ||
| 1081 | set_current_state(TASK_UNINTERRUPTIBLE); | 1230 | val = read_hvwc_reg(window, VREG(WINCTL)); |
| 1082 | schedule_timeout(HZ); | 1231 | val = SET_FIELD(VAS_WINCTL_PIN, val, 0); |
| 1083 | goto retry; | 1232 | val = SET_FIELD(VAS_WINCTL_OPEN, val, 0); |
| 1084 | } | 1233 | write_hvwc_reg(window, VREG(WINCTL), val); |
| 1085 | } | 1234 | } |
| 1086 | 1235 | ||
| 1087 | /* | 1236 | /* |
| @@ -1098,8 +1247,6 @@ retry: | |||
| 1098 | */ | 1247 | */ |
| 1099 | int vas_win_close(struct vas_window *window) | 1248 | int vas_win_close(struct vas_window *window) |
| 1100 | { | 1249 | { |
| 1101 | u64 val; | ||
| 1102 | |||
| 1103 | if (!window) | 1250 | if (!window) |
| 1104 | return 0; | 1251 | return 0; |
| 1105 | 1252 | ||
| @@ -1115,11 +1262,9 @@ int vas_win_close(struct vas_window *window) | |||
| 1115 | 1262 | ||
| 1116 | poll_window_busy_state(window); | 1263 | poll_window_busy_state(window); |
| 1117 | 1264 | ||
| 1118 | /* Unpin window from cache and close it */ | 1265 | unpin_close_window(window); |
| 1119 | val = read_hvwc_reg(window, VREG(WINCTL)); | 1266 | |
| 1120 | val = SET_FIELD(VAS_WINCTL_PIN, val, 0); | 1267 | poll_window_credits(window); |
| 1121 | val = SET_FIELD(VAS_WINCTL_OPEN, val, 0); | ||
| 1122 | write_hvwc_reg(window, VREG(WINCTL), val); | ||
| 1123 | 1268 | ||
| 1124 | poll_window_castout(window); | 1269 | poll_window_castout(window); |
| 1125 | 1270 | ||
| @@ -1132,3 +1277,12 @@ int vas_win_close(struct vas_window *window) | |||
| 1132 | return 0; | 1277 | return 0; |
| 1133 | } | 1278 | } |
| 1134 | EXPORT_SYMBOL_GPL(vas_win_close); | 1279 | EXPORT_SYMBOL_GPL(vas_win_close); |
| 1280 | |||
| 1281 | /* | ||
| 1282 | * Return a system-wide unique window id for the window @win. | ||
| 1283 | */ | ||
| 1284 | u32 vas_win_id(struct vas_window *win) | ||
| 1285 | { | ||
| 1286 | return encode_pswid(win->vinst->vas_id, win->winid); | ||
| 1287 | } | ||
| 1288 | EXPORT_SYMBOL_GPL(vas_win_id); | ||
diff --git a/arch/powerpc/platforms/powernv/vas.c b/arch/powerpc/platforms/powernv/vas.c index 565a4878fefa..c488621dbec3 100644 --- a/arch/powerpc/platforms/powernv/vas.c +++ b/arch/powerpc/platforms/powernv/vas.c | |||
| @@ -18,15 +18,18 @@ | |||
| 18 | #include <linux/of_platform.h> | 18 | #include <linux/of_platform.h> |
| 19 | #include <linux/of_address.h> | 19 | #include <linux/of_address.h> |
| 20 | #include <linux/of.h> | 20 | #include <linux/of.h> |
| 21 | #include <asm/prom.h> | ||
| 21 | 22 | ||
| 22 | #include "vas.h" | 23 | #include "vas.h" |
| 23 | 24 | ||
| 24 | static DEFINE_MUTEX(vas_mutex); | 25 | DEFINE_MUTEX(vas_mutex); |
| 25 | static LIST_HEAD(vas_instances); | 26 | static LIST_HEAD(vas_instances); |
| 26 | 27 | ||
| 28 | static DEFINE_PER_CPU(int, cpu_vas_id); | ||
| 29 | |||
| 27 | static int init_vas_instance(struct platform_device *pdev) | 30 | static int init_vas_instance(struct platform_device *pdev) |
| 28 | { | 31 | { |
| 29 | int rc, vasid; | 32 | int rc, cpu, vasid; |
| 30 | struct resource *res; | 33 | struct resource *res; |
| 31 | struct vas_instance *vinst; | 34 | struct vas_instance *vinst; |
| 32 | struct device_node *dn = pdev->dev.of_node; | 35 | struct device_node *dn = pdev->dev.of_node; |
| @@ -74,10 +77,17 @@ static int init_vas_instance(struct platform_device *pdev) | |||
| 74 | "paste_win_id_shift 0x%llx\n", pdev->name, vasid, | 77 | "paste_win_id_shift 0x%llx\n", pdev->name, vasid, |
| 75 | vinst->paste_base_addr, vinst->paste_win_id_shift); | 78 | vinst->paste_base_addr, vinst->paste_win_id_shift); |
| 76 | 79 | ||
| 80 | for_each_possible_cpu(cpu) { | ||
| 81 | if (cpu_to_chip_id(cpu) == of_get_ibm_chip_id(dn)) | ||
| 82 | per_cpu(cpu_vas_id, cpu) = vasid; | ||
| 83 | } | ||
| 84 | |||
| 77 | mutex_lock(&vas_mutex); | 85 | mutex_lock(&vas_mutex); |
| 78 | list_add(&vinst->node, &vas_instances); | 86 | list_add(&vinst->node, &vas_instances); |
| 79 | mutex_unlock(&vas_mutex); | 87 | mutex_unlock(&vas_mutex); |
| 80 | 88 | ||
| 89 | vas_instance_init_dbgdir(vinst); | ||
| 90 | |||
| 81 | dev_set_drvdata(&pdev->dev, vinst); | 91 | dev_set_drvdata(&pdev->dev, vinst); |
| 82 | 92 | ||
| 83 | return 0; | 93 | return 0; |
| @@ -98,6 +108,10 @@ struct vas_instance *find_vas_instance(int vasid) | |||
| 98 | struct vas_instance *vinst; | 108 | struct vas_instance *vinst; |
| 99 | 109 | ||
| 100 | mutex_lock(&vas_mutex); | 110 | mutex_lock(&vas_mutex); |
| 111 | |||
| 112 | if (vasid == -1) | ||
| 113 | vasid = per_cpu(cpu_vas_id, smp_processor_id()); | ||
| 114 | |||
| 101 | list_for_each(ent, &vas_instances) { | 115 | list_for_each(ent, &vas_instances) { |
| 102 | vinst = list_entry(ent, struct vas_instance, node); | 116 | vinst = list_entry(ent, struct vas_instance, node); |
| 103 | if (vinst->vas_id == vasid) { | 117 | if (vinst->vas_id == vasid) { |
| @@ -111,6 +125,17 @@ struct vas_instance *find_vas_instance(int vasid) | |||
| 111 | return NULL; | 125 | return NULL; |
| 112 | } | 126 | } |
| 113 | 127 | ||
| 128 | int chip_to_vas_id(int chipid) | ||
| 129 | { | ||
| 130 | int cpu; | ||
| 131 | |||
| 132 | for_each_possible_cpu(cpu) { | ||
| 133 | if (cpu_to_chip_id(cpu) == chipid) | ||
| 134 | return per_cpu(cpu_vas_id, cpu); | ||
| 135 | } | ||
| 136 | return -1; | ||
| 137 | } | ||
| 138 | |||
| 114 | static int vas_probe(struct platform_device *pdev) | 139 | static int vas_probe(struct platform_device *pdev) |
| 115 | { | 140 | { |
| 116 | return init_vas_instance(pdev); | 141 | return init_vas_instance(pdev); |
| @@ -134,6 +159,8 @@ static int __init vas_init(void) | |||
| 134 | int found = 0; | 159 | int found = 0; |
| 135 | struct device_node *dn; | 160 | struct device_node *dn; |
| 136 | 161 | ||
| 162 | vas_init_dbgdir(); | ||
| 163 | |||
| 137 | platform_driver_register(&vas_driver); | 164 | platform_driver_register(&vas_driver); |
| 138 | 165 | ||
| 139 | for_each_compatible_node(dn, NULL, "ibm,vas") { | 166 | for_each_compatible_node(dn, NULL, "ibm,vas") { |
diff --git a/arch/powerpc/platforms/powernv/vas.h b/arch/powerpc/platforms/powernv/vas.h index 38dee5d50f31..ae0100fd35bb 100644 --- a/arch/powerpc/platforms/powernv/vas.h +++ b/arch/powerpc/platforms/powernv/vas.h | |||
| @@ -13,6 +13,8 @@ | |||
| 13 | #include <linux/idr.h> | 13 | #include <linux/idr.h> |
| 14 | #include <asm/vas.h> | 14 | #include <asm/vas.h> |
| 15 | #include <linux/io.h> | 15 | #include <linux/io.h> |
| 16 | #include <linux/dcache.h> | ||
| 17 | #include <linux/mutex.h> | ||
| 16 | 18 | ||
| 17 | /* | 19 | /* |
| 18 | * Overview of Virtual Accelerator Switchboard (VAS). | 20 | * Overview of Virtual Accelerator Switchboard (VAS). |
| @@ -106,8 +108,8 @@ | |||
| 106 | * | 108 | * |
| 107 | * TODO: Needs tuning for per-process credits | 109 | * TODO: Needs tuning for per-process credits |
| 108 | */ | 110 | */ |
| 109 | #define VAS_WCREDS_MIN 16 | 111 | #define VAS_RX_WCREDS_MAX ((64 << 10) - 1) |
| 110 | #define VAS_WCREDS_MAX ((64 << 10) - 1) | 112 | #define VAS_TX_WCREDS_MAX ((4 << 10) - 1) |
| 111 | #define VAS_WCREDS_DEFAULT (1 << 10) | 113 | #define VAS_WCREDS_DEFAULT (1 << 10) |
| 112 | 114 | ||
| 113 | /* | 115 | /* |
| @@ -259,6 +261,16 @@ | |||
| 259 | #define VAS_NX_UTIL_ADDER PPC_BITMASK(32, 63) | 261 | #define VAS_NX_UTIL_ADDER PPC_BITMASK(32, 63) |
| 260 | 262 | ||
| 261 | /* | 263 | /* |
| 264 | * VREG(x): | ||
| 265 | * Expand a register's short name (eg: LPID) into two parameters: | ||
| 266 | * - the register's short name in string form ("LPID"), and | ||
| 267 | * - the name of the macro (eg: VAS_LPID_OFFSET), defining the | ||
| 268 | * register's offset in the window context | ||
| 269 | */ | ||
| 270 | #define VREG_SFX(n, s) __stringify(n), VAS_##n##s | ||
| 271 | #define VREG(r) VREG_SFX(r, _OFFSET) | ||
| 272 | |||
| 273 | /* | ||
| 262 | * Local Notify Scope Control Register. (Receive windows only). | 274 | * Local Notify Scope Control Register. (Receive windows only). |
| 263 | */ | 275 | */ |
| 264 | enum vas_notify_scope { | 276 | enum vas_notify_scope { |
| @@ -307,6 +319,9 @@ struct vas_instance { | |||
| 307 | struct mutex mutex; | 319 | struct mutex mutex; |
| 308 | struct vas_window *rxwin[VAS_COP_TYPE_MAX]; | 320 | struct vas_window *rxwin[VAS_COP_TYPE_MAX]; |
| 309 | struct vas_window *windows[VAS_WINDOWS_PER_CHIP]; | 321 | struct vas_window *windows[VAS_WINDOWS_PER_CHIP]; |
| 322 | |||
| 323 | char *dbgname; | ||
| 324 | struct dentry *dbgdir; | ||
| 310 | }; | 325 | }; |
| 311 | 326 | ||
| 312 | /* | 327 | /* |
| @@ -322,6 +337,10 @@ struct vas_window { | |||
| 322 | void *hvwc_map; /* HV window context */ | 337 | void *hvwc_map; /* HV window context */ |
| 323 | void *uwc_map; /* OS/User window context */ | 338 | void *uwc_map; /* OS/User window context */ |
| 324 | pid_t pid; /* Linux process id of owner */ | 339 | pid_t pid; /* Linux process id of owner */ |
| 340 | int wcreds_max; /* Window credits */ | ||
| 341 | |||
| 342 | char *dbgname; | ||
| 343 | struct dentry *dbgdir; | ||
| 325 | 344 | ||
| 326 | /* Fields applicable only to send windows */ | 345 | /* Fields applicable only to send windows */ |
| 327 | void *paste_kaddr; | 346 | void *paste_kaddr; |
| @@ -383,45 +402,23 @@ struct vas_winctx { | |||
| 383 | enum vas_notify_after_count notify_after_count; | 402 | enum vas_notify_after_count notify_after_count; |
| 384 | }; | 403 | }; |
| 385 | 404 | ||
| 386 | extern struct vas_instance *find_vas_instance(int vasid); | 405 | extern struct mutex vas_mutex; |
| 387 | 406 | ||
| 388 | /* | 407 | extern struct vas_instance *find_vas_instance(int vasid); |
| 389 | * VREG(x): | 408 | extern void vas_init_dbgdir(void); |
| 390 | * Expand a register's short name (eg: LPID) into two parameters: | 409 | extern void vas_instance_init_dbgdir(struct vas_instance *vinst); |
| 391 | * - the register's short name in string form ("LPID"), and | 410 | extern void vas_window_init_dbgdir(struct vas_window *win); |
| 392 | * - the name of the macro (eg: VAS_LPID_OFFSET), defining the | 411 | extern void vas_window_free_dbgdir(struct vas_window *win); |
| 393 | * register's offset in the window context | ||
| 394 | */ | ||
| 395 | #define VREG_SFX(n, s) __stringify(n), VAS_##n##s | ||
| 396 | #define VREG(r) VREG_SFX(r, _OFFSET) | ||
| 397 | |||
| 398 | #ifdef vas_debug | ||
| 399 | static inline void dump_rx_win_attr(struct vas_rx_win_attr *attr) | ||
| 400 | { | ||
| 401 | pr_err("fault %d, notify %d, intr %d early %d\n", | ||
| 402 | attr->fault_win, attr->notify_disable, | ||
| 403 | attr->intr_disable, attr->notify_early); | ||
| 404 | |||
| 405 | pr_err("rx_fifo_size %d, max value %d\n", | ||
| 406 | attr->rx_fifo_size, VAS_RX_FIFO_SIZE_MAX); | ||
| 407 | } | ||
| 408 | 412 | ||
| 409 | static inline void vas_log_write(struct vas_window *win, char *name, | 413 | static inline void vas_log_write(struct vas_window *win, char *name, |
| 410 | void *regptr, u64 val) | 414 | void *regptr, u64 val) |
| 411 | { | 415 | { |
| 412 | if (val) | 416 | if (val) |
| 413 | pr_err("%swin #%d: %s reg %p, val 0x%016llx\n", | 417 | pr_debug("%swin #%d: %s reg %p, val 0x%016llx\n", |
| 414 | win->tx_win ? "Tx" : "Rx", win->winid, name, | 418 | win->tx_win ? "Tx" : "Rx", win->winid, name, |
| 415 | regptr, val); | 419 | regptr, val); |
| 416 | } | 420 | } |
| 417 | 421 | ||
| 418 | #else /* vas_debug */ | ||
| 419 | |||
| 420 | #define vas_log_write(win, name, reg, val) | ||
| 421 | #define dump_rx_win_attr(attr) | ||
| 422 | |||
| 423 | #endif /* vas_debug */ | ||
| 424 | |||
| 425 | static inline void write_uwc_reg(struct vas_window *win, char *name, | 422 | static inline void write_uwc_reg(struct vas_window *win, char *name, |
| 426 | s32 reg, u64 val) | 423 | s32 reg, u64 val) |
| 427 | { | 424 | { |
| @@ -450,18 +447,32 @@ static inline u64 read_hvwc_reg(struct vas_window *win, | |||
| 450 | return in_be64(win->hvwc_map+reg); | 447 | return in_be64(win->hvwc_map+reg); |
| 451 | } | 448 | } |
| 452 | 449 | ||
| 453 | #ifdef vas_debug | 450 | /* |
| 454 | 451 | * Encode/decode the Partition Send Window ID (PSWID) for a window in | |
| 455 | static void print_fifo_msg_count(struct vas_window *txwin) | 452 | * a way that we can uniquely identify any window in the system. i.e. |
| 453 | * we should be able to locate the 'struct vas_window' given the PSWID. | ||
| 454 | * | ||
| 455 | * Bits Usage | ||
| 456 | * 0:7 VAS id (8 bits) | ||
| 457 | * 8:15 Unused, 0 (3 bits) | ||
| 458 | * 16:31 Window id (16 bits) | ||
| 459 | */ | ||
| 460 | static inline u32 encode_pswid(int vasid, int winid) | ||
| 456 | { | 461 | { |
| 457 | uint64_t read_hvwc_reg(struct vas_window *w, char *n, uint64_t o); | 462 | u32 pswid = 0; |
| 458 | pr_devel("Winid %d, Msg count %llu\n", txwin->winid, | ||
| 459 | (uint64_t)read_hvwc_reg(txwin, VREG(LRFIFO_PUSH))); | ||
| 460 | } | ||
| 461 | #else /* vas_debug */ | ||
| 462 | 463 | ||
| 463 | #define print_fifo_msg_count(window) | 464 | pswid |= vasid << (31 - 7); |
| 465 | pswid |= winid; | ||
| 464 | 466 | ||
| 465 | #endif /* vas_debug */ | 467 | return pswid; |
| 468 | } | ||
| 469 | |||
| 470 | static inline void decode_pswid(u32 pswid, int *vasid, int *winid) | ||
| 471 | { | ||
| 472 | if (vasid) | ||
| 473 | *vasid = pswid >> (31 - 7) & 0xFF; | ||
| 466 | 474 | ||
| 475 | if (winid) | ||
| 476 | *winid = pswid & 0xFFFF; | ||
| 477 | } | ||
| 467 | #endif /* _VAS_H */ | 478 | #endif /* _VAS_H */ |
diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c index fadb95efbb9e..a7d14aa7bb7c 100644 --- a/arch/powerpc/platforms/pseries/hotplug-cpu.c +++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c | |||
| @@ -363,6 +363,7 @@ static int dlpar_online_cpu(struct device_node *dn) | |||
| 363 | BUG_ON(get_cpu_current_state(cpu) | 363 | BUG_ON(get_cpu_current_state(cpu) |
| 364 | != CPU_STATE_OFFLINE); | 364 | != CPU_STATE_OFFLINE); |
| 365 | cpu_maps_update_done(); | 365 | cpu_maps_update_done(); |
| 366 | timed_topology_update(1); | ||
| 366 | rc = device_online(get_cpu_device(cpu)); | 367 | rc = device_online(get_cpu_device(cpu)); |
| 367 | if (rc) | 368 | if (rc) |
| 368 | goto out; | 369 | goto out; |
| @@ -533,6 +534,7 @@ static int dlpar_offline_cpu(struct device_node *dn) | |||
| 533 | set_preferred_offline_state(cpu, | 534 | set_preferred_offline_state(cpu, |
| 534 | CPU_STATE_OFFLINE); | 535 | CPU_STATE_OFFLINE); |
| 535 | cpu_maps_update_done(); | 536 | cpu_maps_update_done(); |
| 537 | timed_topology_update(1); | ||
| 536 | rc = device_offline(get_cpu_device(cpu)); | 538 | rc = device_offline(get_cpu_device(cpu)); |
| 537 | if (rc) | 539 | if (rc) |
| 538 | goto out; | 540 | goto out; |
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index 7c181467d0ad..69921f72e2da 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c | |||
| @@ -55,23 +55,23 @@ | |||
| 55 | 55 | ||
| 56 | static struct iommu_table_group *iommu_pseries_alloc_group(int node) | 56 | static struct iommu_table_group *iommu_pseries_alloc_group(int node) |
| 57 | { | 57 | { |
| 58 | struct iommu_table_group *table_group = NULL; | 58 | struct iommu_table_group *table_group; |
| 59 | struct iommu_table *tbl = NULL; | 59 | struct iommu_table *tbl; |
| 60 | struct iommu_table_group_link *tgl = NULL; | 60 | struct iommu_table_group_link *tgl; |
| 61 | 61 | ||
| 62 | table_group = kzalloc_node(sizeof(struct iommu_table_group), GFP_KERNEL, | 62 | table_group = kzalloc_node(sizeof(struct iommu_table_group), GFP_KERNEL, |
| 63 | node); | 63 | node); |
| 64 | if (!table_group) | 64 | if (!table_group) |
| 65 | goto fail_exit; | 65 | return NULL; |
| 66 | 66 | ||
| 67 | tbl = kzalloc_node(sizeof(struct iommu_table), GFP_KERNEL, node); | 67 | tbl = kzalloc_node(sizeof(struct iommu_table), GFP_KERNEL, node); |
| 68 | if (!tbl) | 68 | if (!tbl) |
| 69 | goto fail_exit; | 69 | goto free_group; |
| 70 | 70 | ||
| 71 | tgl = kzalloc_node(sizeof(struct iommu_table_group_link), GFP_KERNEL, | 71 | tgl = kzalloc_node(sizeof(struct iommu_table_group_link), GFP_KERNEL, |
| 72 | node); | 72 | node); |
| 73 | if (!tgl) | 73 | if (!tgl) |
| 74 | goto fail_exit; | 74 | goto free_table; |
| 75 | 75 | ||
| 76 | INIT_LIST_HEAD_RCU(&tbl->it_group_list); | 76 | INIT_LIST_HEAD_RCU(&tbl->it_group_list); |
| 77 | kref_init(&tbl->it_kref); | 77 | kref_init(&tbl->it_kref); |
| @@ -82,11 +82,10 @@ static struct iommu_table_group *iommu_pseries_alloc_group(int node) | |||
| 82 | 82 | ||
| 83 | return table_group; | 83 | return table_group; |
| 84 | 84 | ||
| 85 | fail_exit: | 85 | free_table: |
| 86 | kfree(tgl); | ||
| 87 | kfree(table_group); | ||
| 88 | kfree(tbl); | 86 | kfree(tbl); |
| 89 | 87 | free_group: | |
| 88 | kfree(table_group); | ||
| 90 | return NULL; | 89 | return NULL; |
| 91 | } | 90 | } |
| 92 | 91 | ||
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index 495ba4e7336d..0ee4a469a4ae 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c | |||
| @@ -93,7 +93,7 @@ void vpa_init(int cpu) | |||
| 93 | return; | 93 | return; |
| 94 | } | 94 | } |
| 95 | 95 | ||
| 96 | #ifdef CONFIG_PPC_STD_MMU_64 | 96 | #ifdef CONFIG_PPC_BOOK3S_64 |
| 97 | /* | 97 | /* |
| 98 | * PAPR says this feature is SLB-Buffer but firmware never | 98 | * PAPR says this feature is SLB-Buffer but firmware never |
| 99 | * reports that. All SPLPAR support SLB shadow buffer. | 99 | * reports that. All SPLPAR support SLB shadow buffer. |
| @@ -106,7 +106,7 @@ void vpa_init(int cpu) | |||
| 106 | "cpu %d (hw %d) of area %lx failed with %ld\n", | 106 | "cpu %d (hw %d) of area %lx failed with %ld\n", |
| 107 | cpu, hwcpu, addr, ret); | 107 | cpu, hwcpu, addr, ret); |
| 108 | } | 108 | } |
| 109 | #endif /* CONFIG_PPC_STD_MMU_64 */ | 109 | #endif /* CONFIG_PPC_BOOK3S_64 */ |
| 110 | 110 | ||
| 111 | /* | 111 | /* |
| 112 | * Register dispatch trace log, if one has been allocated. | 112 | * Register dispatch trace log, if one has been allocated. |
| @@ -129,7 +129,7 @@ void vpa_init(int cpu) | |||
| 129 | } | 129 | } |
| 130 | } | 130 | } |
| 131 | 131 | ||
| 132 | #ifdef CONFIG_PPC_STD_MMU_64 | 132 | #ifdef CONFIG_PPC_BOOK3S_64 |
| 133 | 133 | ||
| 134 | static long pSeries_lpar_hpte_insert(unsigned long hpte_group, | 134 | static long pSeries_lpar_hpte_insert(unsigned long hpte_group, |
| 135 | unsigned long vpn, unsigned long pa, | 135 | unsigned long vpn, unsigned long pa, |
| @@ -824,7 +824,7 @@ void arch_free_page(struct page *page, int order) | |||
| 824 | EXPORT_SYMBOL(arch_free_page); | 824 | EXPORT_SYMBOL(arch_free_page); |
| 825 | 825 | ||
| 826 | #endif /* CONFIG_PPC_SMLPAR */ | 826 | #endif /* CONFIG_PPC_SMLPAR */ |
| 827 | #endif /* CONFIG_PPC_STD_MMU_64 */ | 827 | #endif /* CONFIG_PPC_BOOK3S_64 */ |
| 828 | 828 | ||
| 829 | #ifdef CONFIG_TRACEPOINTS | 829 | #ifdef CONFIG_TRACEPOINTS |
| 830 | #ifdef HAVE_JUMP_LABEL | 830 | #ifdef HAVE_JUMP_LABEL |
diff --git a/arch/powerpc/platforms/pseries/lparcfg.c b/arch/powerpc/platforms/pseries/lparcfg.c index 779fc2a1c8f7..b2706c483067 100644 --- a/arch/powerpc/platforms/pseries/lparcfg.c +++ b/arch/powerpc/platforms/pseries/lparcfg.c | |||
| @@ -485,7 +485,7 @@ static int pseries_lparcfg_data(struct seq_file *m, void *v) | |||
| 485 | seq_printf(m, "shared_processor_mode=%d\n", | 485 | seq_printf(m, "shared_processor_mode=%d\n", |
| 486 | lppaca_shared_proc(get_lppaca())); | 486 | lppaca_shared_proc(get_lppaca())); |
| 487 | 487 | ||
| 488 | #ifdef CONFIG_PPC_STD_MMU_64 | 488 | #ifdef CONFIG_PPC_BOOK3S_64 |
| 489 | seq_printf(m, "slb_size=%d\n", mmu_slb_size); | 489 | seq_printf(m, "slb_size=%d\n", mmu_slb_size); |
| 490 | #endif | 490 | #endif |
| 491 | parse_em_data(m); | 491 | parse_em_data(m); |
diff --git a/arch/powerpc/platforms/pseries/vio.c b/arch/powerpc/platforms/pseries/vio.c index 12277bc9fd9e..d86938260a86 100644 --- a/arch/powerpc/platforms/pseries/vio.c +++ b/arch/powerpc/platforms/pseries/vio.c | |||
| @@ -1592,6 +1592,8 @@ ATTRIBUTE_GROUPS(vio_dev); | |||
| 1592 | void vio_unregister_device(struct vio_dev *viodev) | 1592 | void vio_unregister_device(struct vio_dev *viodev) |
| 1593 | { | 1593 | { |
| 1594 | device_unregister(&viodev->dev); | 1594 | device_unregister(&viodev->dev); |
| 1595 | if (viodev->family == VDEVICE) | ||
| 1596 | irq_dispose_mapping(viodev->irq); | ||
| 1595 | } | 1597 | } |
| 1596 | EXPORT_SYMBOL(vio_unregister_device); | 1598 | EXPORT_SYMBOL(vio_unregister_device); |
| 1597 | 1599 | ||
diff --git a/arch/powerpc/sysdev/axonram.c b/arch/powerpc/sysdev/axonram.c index c60e84e4558d..1b307c80b401 100644 --- a/arch/powerpc/sysdev/axonram.c +++ b/arch/powerpc/sysdev/axonram.c | |||
| @@ -184,7 +184,7 @@ static int axon_ram_probe(struct platform_device *device) | |||
| 184 | static int axon_ram_bank_id = -1; | 184 | static int axon_ram_bank_id = -1; |
| 185 | struct axon_ram_bank *bank; | 185 | struct axon_ram_bank *bank; |
| 186 | struct resource resource; | 186 | struct resource resource; |
| 187 | int rc = 0; | 187 | int rc; |
| 188 | 188 | ||
| 189 | axon_ram_bank_id++; | 189 | axon_ram_bank_id++; |
| 190 | 190 | ||
diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c index 16f1edd78c40..535cf1f6941c 100644 --- a/arch/powerpc/sysdev/ipic.c +++ b/arch/powerpc/sysdev/ipic.c | |||
| @@ -846,12 +846,12 @@ void ipic_disable_mcp(enum ipic_mcp_irq mcp_irq) | |||
| 846 | 846 | ||
| 847 | u32 ipic_get_mcp_status(void) | 847 | u32 ipic_get_mcp_status(void) |
| 848 | { | 848 | { |
| 849 | return ipic_read(primary_ipic->regs, IPIC_SERMR); | 849 | return ipic_read(primary_ipic->regs, IPIC_SERSR); |
| 850 | } | 850 | } |
| 851 | 851 | ||
| 852 | void ipic_clear_mcp_status(u32 mask) | 852 | void ipic_clear_mcp_status(u32 mask) |
| 853 | { | 853 | { |
| 854 | ipic_write(primary_ipic->regs, IPIC_SERMR, mask); | 854 | ipic_write(primary_ipic->regs, IPIC_SERSR, mask); |
| 855 | } | 855 | } |
| 856 | 856 | ||
| 857 | /* Return an interrupt vector or 0 if no interrupt is pending. */ | 857 | /* Return an interrupt vector or 0 if no interrupt is pending. */ |
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index 33351c6704b1..1b2d8cb49abb 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c | |||
| @@ -28,6 +28,7 @@ | |||
| 28 | #include <linux/bug.h> | 28 | #include <linux/bug.h> |
| 29 | #include <linux/nmi.h> | 29 | #include <linux/nmi.h> |
| 30 | #include <linux/ctype.h> | 30 | #include <linux/ctype.h> |
| 31 | #include <linux/highmem.h> | ||
| 31 | 32 | ||
| 32 | #include <asm/debugfs.h> | 33 | #include <asm/debugfs.h> |
| 33 | #include <asm/ptrace.h> | 34 | #include <asm/ptrace.h> |
| @@ -127,6 +128,7 @@ static void byterev(unsigned char *, int); | |||
| 127 | static void memex(void); | 128 | static void memex(void); |
| 128 | static int bsesc(void); | 129 | static int bsesc(void); |
| 129 | static void dump(void); | 130 | static void dump(void); |
| 131 | static void show_pte(unsigned long); | ||
| 130 | static void prdump(unsigned long, long); | 132 | static void prdump(unsigned long, long); |
| 131 | static int ppc_inst_dump(unsigned long, long, int); | 133 | static int ppc_inst_dump(unsigned long, long, int); |
| 132 | static void dump_log_buf(void); | 134 | static void dump_log_buf(void); |
| @@ -234,6 +236,7 @@ Commands:\n\ | |||
| 234 | #endif | 236 | #endif |
| 235 | "\ | 237 | "\ |
| 236 | dr dump stream of raw bytes\n\ | 238 | dr dump stream of raw bytes\n\ |
| 239 | dv dump virtual address translation \n\ | ||
| 237 | dt dump the tracing buffers (uses printk)\n\ | 240 | dt dump the tracing buffers (uses printk)\n\ |
| 238 | dtc dump the tracing buffers for current CPU (uses printk)\n\ | 241 | dtc dump the tracing buffers for current CPU (uses printk)\n\ |
| 239 | " | 242 | " |
| @@ -278,6 +281,7 @@ Commands:\n\ | |||
| 278 | #elif defined(CONFIG_44x) || defined(CONFIG_PPC_BOOK3E) | 281 | #elif defined(CONFIG_44x) || defined(CONFIG_PPC_BOOK3E) |
| 279 | " u dump TLB\n" | 282 | " u dump TLB\n" |
| 280 | #endif | 283 | #endif |
| 284 | " U show uptime information\n" | ||
| 281 | " ? help\n" | 285 | " ? help\n" |
| 282 | " # n limit output to n lines per page (for dp, dpa, dl)\n" | 286 | " # n limit output to n lines per page (for dp, dpa, dl)\n" |
| 283 | " zr reboot\n\ | 287 | " zr reboot\n\ |
| @@ -530,14 +534,19 @@ static int xmon_core(struct pt_regs *regs, int fromipi) | |||
| 530 | 534 | ||
| 531 | waiting: | 535 | waiting: |
| 532 | secondary = 1; | 536 | secondary = 1; |
| 537 | spin_begin(); | ||
| 533 | while (secondary && !xmon_gate) { | 538 | while (secondary && !xmon_gate) { |
| 534 | if (in_xmon == 0) { | 539 | if (in_xmon == 0) { |
| 535 | if (fromipi) | 540 | if (fromipi) { |
| 541 | spin_end(); | ||
| 536 | goto leave; | 542 | goto leave; |
| 543 | } | ||
| 537 | secondary = test_and_set_bit(0, &in_xmon); | 544 | secondary = test_and_set_bit(0, &in_xmon); |
| 538 | } | 545 | } |
| 539 | barrier(); | 546 | spin_cpu_relax(); |
| 547 | touch_nmi_watchdog(); | ||
| 540 | } | 548 | } |
| 549 | spin_end(); | ||
| 541 | 550 | ||
| 542 | if (!secondary && !xmon_gate) { | 551 | if (!secondary && !xmon_gate) { |
| 543 | /* we are the first cpu to come in */ | 552 | /* we are the first cpu to come in */ |
| @@ -568,21 +577,25 @@ static int xmon_core(struct pt_regs *regs, int fromipi) | |||
| 568 | mb(); | 577 | mb(); |
| 569 | xmon_gate = 1; | 578 | xmon_gate = 1; |
| 570 | barrier(); | 579 | barrier(); |
| 580 | touch_nmi_watchdog(); | ||
| 571 | } | 581 | } |
| 572 | 582 | ||
| 573 | cmdloop: | 583 | cmdloop: |
| 574 | while (in_xmon) { | 584 | while (in_xmon) { |
| 575 | if (secondary) { | 585 | if (secondary) { |
| 586 | spin_begin(); | ||
| 576 | if (cpu == xmon_owner) { | 587 | if (cpu == xmon_owner) { |
| 577 | if (!test_and_set_bit(0, &xmon_taken)) { | 588 | if (!test_and_set_bit(0, &xmon_taken)) { |
| 578 | secondary = 0; | 589 | secondary = 0; |
| 590 | spin_end(); | ||
| 579 | continue; | 591 | continue; |
| 580 | } | 592 | } |
| 581 | /* missed it */ | 593 | /* missed it */ |
| 582 | while (cpu == xmon_owner) | 594 | while (cpu == xmon_owner) |
| 583 | barrier(); | 595 | spin_cpu_relax(); |
| 584 | } | 596 | } |
| 585 | barrier(); | 597 | spin_cpu_relax(); |
| 598 | touch_nmi_watchdog(); | ||
| 586 | } else { | 599 | } else { |
| 587 | cmd = cmds(regs); | 600 | cmd = cmds(regs); |
| 588 | if (cmd != 0) { | 601 | if (cmd != 0) { |
| @@ -896,6 +909,26 @@ static void remove_cpu_bpts(void) | |||
| 896 | write_ciabr(0); | 909 | write_ciabr(0); |
| 897 | } | 910 | } |
| 898 | 911 | ||
| 912 | /* Based on uptime_proc_show(). */ | ||
| 913 | static void | ||
| 914 | show_uptime(void) | ||
| 915 | { | ||
| 916 | struct timespec uptime; | ||
| 917 | |||
| 918 | if (setjmp(bus_error_jmp) == 0) { | ||
| 919 | catch_memory_errors = 1; | ||
| 920 | sync(); | ||
| 921 | |||
| 922 | get_monotonic_boottime(&uptime); | ||
| 923 | printf("Uptime: %lu.%.2lu seconds\n", (unsigned long)uptime.tv_sec, | ||
| 924 | ((unsigned long)uptime.tv_nsec / (NSEC_PER_SEC/100))); | ||
| 925 | |||
| 926 | sync(); | ||
| 927 | __delay(200); \ | ||
| 928 | } | ||
| 929 | catch_memory_errors = 0; | ||
| 930 | } | ||
| 931 | |||
| 899 | static void set_lpp_cmd(void) | 932 | static void set_lpp_cmd(void) |
| 900 | { | 933 | { |
| 901 | unsigned long lpp; | 934 | unsigned long lpp; |
| @@ -1031,6 +1064,9 @@ cmds(struct pt_regs *excp) | |||
| 1031 | dump_tlb_book3e(); | 1064 | dump_tlb_book3e(); |
| 1032 | break; | 1065 | break; |
| 1033 | #endif | 1066 | #endif |
| 1067 | case 'U': | ||
| 1068 | show_uptime(); | ||
| 1069 | break; | ||
| 1034 | default: | 1070 | default: |
| 1035 | printf("Unrecognized command: "); | 1071 | printf("Unrecognized command: "); |
| 1036 | do { | 1072 | do { |
| @@ -2279,7 +2315,7 @@ static void dump_tracing(void) | |||
| 2279 | static void dump_one_paca(int cpu) | 2315 | static void dump_one_paca(int cpu) |
| 2280 | { | 2316 | { |
| 2281 | struct paca_struct *p; | 2317 | struct paca_struct *p; |
| 2282 | #ifdef CONFIG_PPC_STD_MMU_64 | 2318 | #ifdef CONFIG_PPC_BOOK3S_64 |
| 2283 | int i = 0; | 2319 | int i = 0; |
| 2284 | #endif | 2320 | #endif |
| 2285 | 2321 | ||
| @@ -2320,7 +2356,7 @@ static void dump_one_paca(int cpu) | |||
| 2320 | DUMP(p, hw_cpu_id, "x"); | 2356 | DUMP(p, hw_cpu_id, "x"); |
| 2321 | DUMP(p, cpu_start, "x"); | 2357 | DUMP(p, cpu_start, "x"); |
| 2322 | DUMP(p, kexec_state, "x"); | 2358 | DUMP(p, kexec_state, "x"); |
| 2323 | #ifdef CONFIG_PPC_STD_MMU_64 | 2359 | #ifdef CONFIG_PPC_BOOK3S_64 |
| 2324 | for (i = 0; i < SLB_NUM_BOLTED; i++) { | 2360 | for (i = 0; i < SLB_NUM_BOLTED; i++) { |
| 2325 | u64 esid, vsid; | 2361 | u64 esid, vsid; |
| 2326 | 2362 | ||
| @@ -2351,6 +2387,7 @@ static void dump_one_paca(int cpu) | |||
| 2351 | #endif | 2387 | #endif |
| 2352 | DUMP(p, __current, "p"); | 2388 | DUMP(p, __current, "p"); |
| 2353 | DUMP(p, kstack, "lx"); | 2389 | DUMP(p, kstack, "lx"); |
| 2390 | printf(" kstack_base = 0x%016lx\n", p->kstack & ~(THREAD_SIZE - 1)); | ||
| 2354 | DUMP(p, stab_rr, "lx"); | 2391 | DUMP(p, stab_rr, "lx"); |
| 2355 | DUMP(p, saved_r1, "lx"); | 2392 | DUMP(p, saved_r1, "lx"); |
| 2356 | DUMP(p, trap_save, "x"); | 2393 | DUMP(p, trap_save, "x"); |
| @@ -2475,6 +2512,11 @@ static void dump_xives(void) | |||
| 2475 | unsigned long num; | 2512 | unsigned long num; |
| 2476 | int c; | 2513 | int c; |
| 2477 | 2514 | ||
| 2515 | if (!xive_enabled()) { | ||
| 2516 | printf("Xive disabled on this system\n"); | ||
| 2517 | return; | ||
| 2518 | } | ||
| 2519 | |||
| 2478 | c = inchar(); | 2520 | c = inchar(); |
| 2479 | if (c == 'a') { | 2521 | if (c == 'a') { |
| 2480 | dump_all_xives(); | 2522 | dump_all_xives(); |
| @@ -2574,6 +2616,9 @@ dump(void) | |||
| 2574 | dump_log_buf(); | 2616 | dump_log_buf(); |
| 2575 | } else if (c == 'o') { | 2617 | } else if (c == 'o') { |
| 2576 | dump_opal_msglog(); | 2618 | dump_opal_msglog(); |
| 2619 | } else if (c == 'v') { | ||
| 2620 | /* dump virtual to physical translation */ | ||
| 2621 | show_pte(adrs); | ||
| 2577 | } else if (c == 'r') { | 2622 | } else if (c == 'r') { |
| 2578 | scanhex(&ndump); | 2623 | scanhex(&ndump); |
| 2579 | if (ndump == 0) | 2624 | if (ndump == 0) |
| @@ -2907,6 +2952,116 @@ static void show_task(struct task_struct *tsk) | |||
| 2907 | tsk->comm); | 2952 | tsk->comm); |
| 2908 | } | 2953 | } |
| 2909 | 2954 | ||
| 2955 | #ifdef CONFIG_PPC_BOOK3S_64 | ||
| 2956 | void format_pte(void *ptep, unsigned long pte) | ||
| 2957 | { | ||
| 2958 | printf("ptep @ 0x%016lx = 0x%016lx\n", (unsigned long)ptep, pte); | ||
| 2959 | printf("Maps physical address = 0x%016lx\n", pte & PTE_RPN_MASK); | ||
| 2960 | |||
| 2961 | printf("Flags = %s%s%s%s%s\n", | ||
| 2962 | (pte & _PAGE_ACCESSED) ? "Accessed " : "", | ||
| 2963 | (pte & _PAGE_DIRTY) ? "Dirty " : "", | ||
| 2964 | (pte & _PAGE_READ) ? "Read " : "", | ||
| 2965 | (pte & _PAGE_WRITE) ? "Write " : "", | ||
| 2966 | (pte & _PAGE_EXEC) ? "Exec " : ""); | ||
| 2967 | } | ||
| 2968 | |||
| 2969 | static void show_pte(unsigned long addr) | ||
| 2970 | { | ||
| 2971 | unsigned long tskv = 0; | ||
| 2972 | struct task_struct *tsk = NULL; | ||
| 2973 | struct mm_struct *mm; | ||
| 2974 | pgd_t *pgdp, *pgdir; | ||
| 2975 | pud_t *pudp; | ||
| 2976 | pmd_t *pmdp; | ||
| 2977 | pte_t *ptep; | ||
| 2978 | |||
| 2979 | if (!scanhex(&tskv)) | ||
| 2980 | mm = &init_mm; | ||
| 2981 | else | ||
| 2982 | tsk = (struct task_struct *)tskv; | ||
| 2983 | |||
| 2984 | if (tsk == NULL) | ||
| 2985 | mm = &init_mm; | ||
| 2986 | else | ||
| 2987 | mm = tsk->active_mm; | ||
| 2988 | |||
| 2989 | if (setjmp(bus_error_jmp) != 0) { | ||
| 2990 | catch_memory_errors = 0; | ||
| 2991 | printf("*** Error dumping pte for task %p\n", tsk); | ||
| 2992 | return; | ||
| 2993 | } | ||
| 2994 | |||
| 2995 | catch_memory_errors = 1; | ||
| 2996 | sync(); | ||
| 2997 | |||
| 2998 | if (mm == &init_mm) { | ||
| 2999 | pgdp = pgd_offset_k(addr); | ||
| 3000 | pgdir = pgd_offset_k(0); | ||
| 3001 | } else { | ||
| 3002 | pgdp = pgd_offset(mm, addr); | ||
| 3003 | pgdir = pgd_offset(mm, 0); | ||
| 3004 | } | ||
| 3005 | |||
| 3006 | if (pgd_none(*pgdp)) { | ||
| 3007 | printf("no linux page table for address\n"); | ||
| 3008 | return; | ||
| 3009 | } | ||
| 3010 | |||
| 3011 | printf("pgd @ 0x%016lx\n", pgdir); | ||
| 3012 | |||
| 3013 | if (pgd_huge(*pgdp)) { | ||
| 3014 | format_pte(pgdp, pgd_val(*pgdp)); | ||
| 3015 | return; | ||
| 3016 | } | ||
| 3017 | printf("pgdp @ 0x%016lx = 0x%016lx\n", pgdp, pgd_val(*pgdp)); | ||
| 3018 | |||
| 3019 | pudp = pud_offset(pgdp, addr); | ||
| 3020 | |||
| 3021 | if (pud_none(*pudp)) { | ||
| 3022 | printf("No valid PUD\n"); | ||
| 3023 | return; | ||
| 3024 | } | ||
| 3025 | |||
| 3026 | if (pud_huge(*pudp)) { | ||
| 3027 | format_pte(pudp, pud_val(*pudp)); | ||
| 3028 | return; | ||
| 3029 | } | ||
| 3030 | |||
| 3031 | printf("pudp @ 0x%016lx = 0x%016lx\n", pudp, pud_val(*pudp)); | ||
| 3032 | |||
| 3033 | pmdp = pmd_offset(pudp, addr); | ||
| 3034 | |||
| 3035 | if (pmd_none(*pmdp)) { | ||
| 3036 | printf("No valid PMD\n"); | ||
| 3037 | return; | ||
| 3038 | } | ||
| 3039 | |||
| 3040 | if (pmd_huge(*pmdp)) { | ||
| 3041 | format_pte(pmdp, pmd_val(*pmdp)); | ||
| 3042 | return; | ||
| 3043 | } | ||
| 3044 | printf("pmdp @ 0x%016lx = 0x%016lx\n", pmdp, pmd_val(*pmdp)); | ||
| 3045 | |||
| 3046 | ptep = pte_offset_map(pmdp, addr); | ||
| 3047 | if (pte_none(*ptep)) { | ||
| 3048 | printf("no valid PTE\n"); | ||
| 3049 | return; | ||
| 3050 | } | ||
| 3051 | |||
| 3052 | format_pte(ptep, pte_val(*ptep)); | ||
| 3053 | |||
| 3054 | sync(); | ||
| 3055 | __delay(200); | ||
| 3056 | catch_memory_errors = 0; | ||
| 3057 | } | ||
| 3058 | #else | ||
| 3059 | static void show_pte(unsigned long addr) | ||
| 3060 | { | ||
| 3061 | printf("show_pte not yet implemented\n"); | ||
| 3062 | } | ||
| 3063 | #endif /* CONFIG_PPC_BOOK3S_64 */ | ||
| 3064 | |||
| 2910 | static void show_tasks(void) | 3065 | static void show_tasks(void) |
| 2911 | { | 3066 | { |
| 2912 | unsigned long tskv; | 3067 | unsigned long tskv; |
| @@ -3224,7 +3379,7 @@ static void xmon_print_symbol(unsigned long address, const char *mid, | |||
| 3224 | printf("%s", after); | 3379 | printf("%s", after); |
| 3225 | } | 3380 | } |
| 3226 | 3381 | ||
| 3227 | #ifdef CONFIG_PPC_STD_MMU_64 | 3382 | #ifdef CONFIG_PPC_BOOK3S_64 |
| 3228 | void dump_segments(void) | 3383 | void dump_segments(void) |
| 3229 | { | 3384 | { |
| 3230 | int i; | 3385 | int i; |
