Commit d0a32f55 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'powerpc-6.3-1' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux

Pull powerpc updates from Michael Ellerman:

 - Support for configuring secure boot with user-defined keys on PowerVM
   LPARs

 - Simplify the replay of soft-masked IRQs by making it non-recursive

 - Add support for KCSAN on 64-bit Book3S

 - Improvements to the API & code which interacts with RTAS (pseries
   firmware)

 - Change 32-bit powermac to assign PCI bus numbers per domain by
   default

 - Some improvements to the 32-bit BPF JIT

 - Various other small features and fixes

Thanks to Anders Roxell, Andrew Donnellan, Andrew Jeffery, Benjamin
Gray, Christophe Leroy, Frederic Barrat, Ganesh Goudar, Geoff Levand,
Greg Kroah-Hartman, Jan-Benedict Glaw, Josh Poimboeuf, Kajol Jain,
Laurent Dufour, Mahesh Salgaonkar, Mathieu Desnoyers, Mimi Zohar, Murphy
Zhou, Nathan Chancellor, Nathan Lynch, Nayna Jain, Nicholas Piggin, Pali
Rohár, Petr Mladek, Rohan McLure, Russell Currey, Sachin Sant, Sathvika
Vasireddy, Sourabh Jain, Stefan Berger, Stephen Rothwell, and Sudhakar
Kuppusamy.

* tag 'powerpc-6.3-1' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux: (114 commits)
  powerpc/pseries: Avoid hcall in plpks_is_available() on non-pseries
  powerpc: dts: turris1x.dts: Set lower priority for CPLD syscon-reboot
  powerpc/e500: Add missing prototype for 'relocate_init'
  powerpc/64: Fix unannotated intra-function call warning
  powerpc/epapr: Don't use wrteei on non booke
  powerpc: Pass correct CPU reference to assembler
  powerpc/mm: Rearrange if-else block to avoid clang warning
  powerpc/nohash: Fix build with llvm-as
  powerpc/nohash: Fix build error with binutils >= 2.38
  powerpc/pseries: Fix endianness issue when parsing PLPKS secvar flags
  macintosh: windfarm: Use unsigned type for 1-bit bitfields
  powerpc/kexec_file: print error string on usable memory property update failure
  powerpc/machdep: warn when machine_is() used too early
  powerpc/64: Replace -mcpu=e500mc64 by -mcpu=e5500
  powerpc/eeh: Set channel state after notifying the drivers
  selftests/powerpc: Fix incorrect kernel headers search path
  powerpc/rtas: arch-wide function token lookup conversions
  powerpc/rtas: introduce rtas_function_token() API
  powerpc/pseries/lpar: convert to papr_sysparm API
  powerpc/pseries/hv-24x7: convert to papr_sysparm API
  ...
parents 5596c6ad f82cdc37
...@@ -18,6 +18,14 @@ Description: A string indicating which backend is in use by the firmware. ...@@ -18,6 +18,14 @@ Description: A string indicating which backend is in use by the firmware.
This determines the format of the variable and the accepted This determines the format of the variable and the accepted
format of variable updates. format of variable updates.
On powernv/OPAL, this value is provided by the OPAL firmware
and is expected to be "ibm,edk2-compat-v1".
On pseries/PLPKS, this is generated by the kernel based on the
version number in the SB_VERSION variable in the keystore, and
has the form "ibm,plpks-sb-v<version>", or
"ibm,plpks-sb-unknown" if there is no SB_VERSION variable.
What: /sys/firmware/secvar/vars/<variable name> What: /sys/firmware/secvar/vars/<variable name>
Date: August 2019 Date: August 2019
Contact: Nayna Jain <nayna@linux.ibm.com> Contact: Nayna Jain <nayna@linux.ibm.com>
...@@ -34,7 +42,7 @@ Description: An integer representation of the size of the content of the ...@@ -34,7 +42,7 @@ Description: An integer representation of the size of the content of the
What: /sys/firmware/secvar/vars/<variable_name>/data What: /sys/firmware/secvar/vars/<variable_name>/data
Date: August 2019 Date: August 2019
Contact: Nayna Jain h<nayna@linux.ibm.com> Contact: Nayna Jain <nayna@linux.ibm.com>
Description: A read-only file containing the value of the variable. The size Description: A read-only file containing the value of the variable. The size
of the file represents the maximum size of the variable data. of the file represents the maximum size of the variable data.
...@@ -44,3 +52,68 @@ Contact: Nayna Jain <nayna@linux.ibm.com> ...@@ -44,3 +52,68 @@ Contact: Nayna Jain <nayna@linux.ibm.com>
Description: A write-only file that is used to submit the new value for the Description: A write-only file that is used to submit the new value for the
variable. The size of the file represents the maximum size of variable. The size of the file represents the maximum size of
the variable data that can be written. the variable data that can be written.
What: /sys/firmware/secvar/config
Date: February 2023
Contact: Nayna Jain <nayna@linux.ibm.com>
Description: This optional directory contains read-only config attributes as
defined by the secure variable implementation. All data is in
ASCII format. The directory is only created if the backing
implementation provides variables to populate it, which at
present is only PLPKS on the pseries platform.
What: /sys/firmware/secvar/config/version
Date: February 2023
Contact: Nayna Jain <nayna@linux.ibm.com>
Description: Config version as reported by the hypervisor in ASCII decimal
format.
Currently only provided by PLPKS on the pseries platform.
What: /sys/firmware/secvar/config/max_object_size
Date: February 2023
Contact: Nayna Jain <nayna@linux.ibm.com>
Description: Maximum allowed size of objects in the keystore in bytes,
represented in ASCII decimal format.
This is not necessarily the same as the max size that can be
written to an update file as writes can contain more than
object data, you should use the size of the update file for
that purpose.
Currently only provided by PLPKS on the pseries platform.
What: /sys/firmware/secvar/config/total_size
Date: February 2023
Contact: Nayna Jain <nayna@linux.ibm.com>
Description: Total size of the PLPKS in bytes, represented in ASCII decimal
format.
Currently only provided by PLPKS on the pseries platform.
What: /sys/firmware/secvar/config/used_space
Date: February 2023
Contact: Nayna Jain <nayna@linux.ibm.com>
Description: Current space consumed by the key store, in bytes, represented
in ASCII decimal format.
Currently only provided by PLPKS on the pseries platform.
What: /sys/firmware/secvar/config/supported_policies
Date: February 2023
Contact: Nayna Jain <nayna@linux.ibm.com>
Description: Bitmask of supported policy flags by the hypervisor,
represented as an 8 byte hexadecimal ASCII string. Consult the
hypervisor documentation for what these flags are.
Currently only provided by PLPKS on the pseries platform.
What: /sys/firmware/secvar/config/signed_update_algorithms
Date: February 2023
Contact: Nayna Jain <nayna@linux.ibm.com>
Description: Bitmask of flags indicating which algorithms the hypervisor
supports for signed update of objects, represented as a 16 byte
hexadecimal ASCII string. Consult the hypervisor documentation
for what these flags mean.
Currently only provided by PLPKS on the pseries platform.
...@@ -197,6 +197,7 @@ config PPC ...@@ -197,6 +197,7 @@ config PPC
select HAVE_ARCH_KASAN if PPC_RADIX_MMU select HAVE_ARCH_KASAN if PPC_RADIX_MMU
select HAVE_ARCH_KASAN if PPC_BOOK3E_64 select HAVE_ARCH_KASAN if PPC_BOOK3E_64
select HAVE_ARCH_KASAN_VMALLOC if HAVE_ARCH_KASAN select HAVE_ARCH_KASAN_VMALLOC if HAVE_ARCH_KASAN
select HAVE_ARCH_KCSAN if PPC_BOOK3S_64
select HAVE_ARCH_KFENCE if ARCH_SUPPORTS_DEBUG_PAGEALLOC select HAVE_ARCH_KFENCE if ARCH_SUPPORTS_DEBUG_PAGEALLOC
select HAVE_ARCH_RANDOMIZE_KSTACK_OFFSET select HAVE_ARCH_RANDOMIZE_KSTACK_OFFSET
select HAVE_ARCH_KGDB select HAVE_ARCH_KGDB
...@@ -206,7 +207,7 @@ config PPC ...@@ -206,7 +207,7 @@ config PPC
select HAVE_ARCH_SECCOMP_FILTER select HAVE_ARCH_SECCOMP_FILTER
select HAVE_ARCH_TRACEHOOK select HAVE_ARCH_TRACEHOOK
select HAVE_ASM_MODVERSIONS select HAVE_ASM_MODVERSIONS
select HAVE_CONTEXT_TRACKING_USER if PPC64 select HAVE_CONTEXT_TRACKING_USER
select HAVE_C_RECORDMCOUNT select HAVE_C_RECORDMCOUNT
select HAVE_DEBUG_KMEMLEAK select HAVE_DEBUG_KMEMLEAK
select HAVE_DEBUG_STACKOVERFLOW select HAVE_DEBUG_STACKOVERFLOW
...@@ -256,6 +257,7 @@ config PPC ...@@ -256,6 +257,7 @@ config PPC
select HAVE_STATIC_CALL if PPC32 select HAVE_STATIC_CALL if PPC32
select HAVE_SYSCALL_TRACEPOINTS select HAVE_SYSCALL_TRACEPOINTS
select HAVE_VIRT_CPU_ACCOUNTING select HAVE_VIRT_CPU_ACCOUNTING
select HAVE_VIRT_CPU_ACCOUNTING_GEN
select HUGETLB_PAGE_SIZE_VARIABLE if PPC_BOOK3S_64 && HUGETLB_PAGE select HUGETLB_PAGE_SIZE_VARIABLE if PPC_BOOK3S_64 && HUGETLB_PAGE
select IOMMU_HELPER if PPC64 select IOMMU_HELPER if PPC64
select IRQ_DOMAIN select IRQ_DOMAIN
...@@ -387,10 +389,22 @@ config PPC_DCR ...@@ -387,10 +389,22 @@ config PPC_DCR
depends on PPC_DCR_NATIVE || PPC_DCR_MMIO depends on PPC_DCR_NATIVE || PPC_DCR_MMIO
default y default y
config PPC_PCI_OF_BUS_MAP
bool "Use pci_to_OF_bus_map (deprecated)"
depends on PPC32
depends on PPC_PMAC || PPC_CHRP
help
This option uses pci_to_OF_bus_map to map OF nodes to PCI devices, which
restricts the system to only having 256 PCI buses. On CHRP it also causes
the "pci-OF-bus-map" property to be created in the device tree.
If unsure, say "N".
config PPC_PCI_BUS_NUM_DOMAIN_DEPENDENT config PPC_PCI_BUS_NUM_DOMAIN_DEPENDENT
depends on PPC32 depends on PPC32
depends on !PPC_PMAC && !PPC_CHRP depends on !PPC_PCI_OF_BUS_MAP
bool "Assign PCI bus numbers from zero individually for each PCI domain" bool "Assign PCI bus numbers from zero individually for each PCI domain"
default y
help help
By default on PPC32 were PCI bus numbers unique across all PCI domains. By default on PPC32 were PCI bus numbers unique across all PCI domains.
So system could have only 256 PCI buses independently of available So system could have only 256 PCI buses independently of available
...@@ -1028,6 +1042,7 @@ config PPC_SECURE_BOOT ...@@ -1028,6 +1042,7 @@ config PPC_SECURE_BOOT
depends on PPC_POWERNV || PPC_PSERIES depends on PPC_POWERNV || PPC_PSERIES
depends on IMA_ARCH_POLICY depends on IMA_ARCH_POLICY
imply IMA_SECURE_AND_OR_TRUSTED_BOOT imply IMA_SECURE_AND_OR_TRUSTED_BOOT
select PSERIES_PLPKS if PPC_PSERIES
help help
Systems with firmware secure boot enabled need to define security Systems with firmware secure boot enabled need to define security
policies to extend secure boot to the OS. This config allows a user policies to extend secure boot to the OS. This config allows a user
......
...@@ -146,19 +146,6 @@ CFLAGS-$(CONFIG_PPC32) += $(call cc-option, $(MULTIPLEWORD)) ...@@ -146,19 +146,6 @@ CFLAGS-$(CONFIG_PPC32) += $(call cc-option, $(MULTIPLEWORD))
CFLAGS-$(CONFIG_PPC32) += $(call cc-option,-mno-readonly-in-sdata) CFLAGS-$(CONFIG_PPC32) += $(call cc-option,-mno-readonly-in-sdata)
ifdef CONFIG_PPC_BOOK3S_64
ifdef CONFIG_CPU_LITTLE_ENDIAN
CFLAGS-$(CONFIG_GENERIC_CPU) += -mcpu=power8
else
CFLAGS-$(CONFIG_GENERIC_CPU) += -mcpu=power4
endif
CFLAGS-$(CONFIG_GENERIC_CPU) += $(call cc-option,-mtune=power10, \
$(call cc-option,-mtune=power9, \
$(call cc-option,-mtune=power8)))
else ifdef CONFIG_PPC_BOOK3E_64
CFLAGS-$(CONFIG_GENERIC_CPU) += -mcpu=powerpc64
endif
ifdef CONFIG_FUNCTION_TRACER ifdef CONFIG_FUNCTION_TRACER
CC_FLAGS_FTRACE := -pg CC_FLAGS_FTRACE := -pg
ifdef CONFIG_MPROFILE_KERNEL ifdef CONFIG_MPROFILE_KERNEL
...@@ -166,11 +153,12 @@ CC_FLAGS_FTRACE += -mprofile-kernel ...@@ -166,11 +153,12 @@ CC_FLAGS_FTRACE += -mprofile-kernel
endif endif
endif endif
CFLAGS-$(CONFIG_TARGET_CPU_BOOL) += $(call cc-option,-mcpu=$(CONFIG_TARGET_CPU)) CFLAGS-$(CONFIG_TARGET_CPU_BOOL) += -mcpu=$(CONFIG_TARGET_CPU)
AFLAGS-$(CONFIG_TARGET_CPU_BOOL) += $(call cc-option,-mcpu=$(CONFIG_TARGET_CPU)) AFLAGS-$(CONFIG_TARGET_CPU_BOOL) += -mcpu=$(CONFIG_TARGET_CPU)
CFLAGS-$(CONFIG_E5500_CPU) += $(call cc-option,-mcpu=e500mc64,-mcpu=powerpc64) CFLAGS-$(CONFIG_POWERPC64_CPU) += $(call cc-option,-mtune=power10, \
CFLAGS-$(CONFIG_E6500_CPU) += $(call cc-option,-mcpu=e6500,$(E5500_CPU)) $(call cc-option,-mtune=power9, \
$(call cc-option,-mtune=power8)))
asinstr := $(call as-instr,lis 9$(comma)foo@high,-DHAVE_AS_ATHIGH=1) asinstr := $(call as-instr,lis 9$(comma)foo@high,-DHAVE_AS_ATHIGH=1)
...@@ -213,10 +201,7 @@ KBUILD_CFLAGS += -fno-asynchronous-unwind-tables ...@@ -213,10 +201,7 @@ KBUILD_CFLAGS += -fno-asynchronous-unwind-tables
# often slow when they are implemented at all # often slow when they are implemented at all
KBUILD_CFLAGS += $(call cc-option,-mno-string) KBUILD_CFLAGS += $(call cc-option,-mno-string)
cpu-as-$(CONFIG_40x) += -Wa,-m405
cpu-as-$(CONFIG_44x) += -Wa,-m440
cpu-as-$(CONFIG_ALTIVEC) += $(call as-option,-Wa$(comma)-maltivec) cpu-as-$(CONFIG_ALTIVEC) += $(call as-option,-Wa$(comma)-maltivec)
cpu-as-$(CONFIG_PPC_E500) += -Wa,-me500
# When using '-many -mpower4' gas will first try and find a matching power4 # When using '-many -mpower4' gas will first try and find a matching power4
# mnemonic and failing that it will allow any valid mnemonic that GAS knows # mnemonic and failing that it will allow any valid mnemonic that GAS knows
...@@ -224,7 +209,6 @@ cpu-as-$(CONFIG_PPC_E500) += -Wa,-me500 ...@@ -224,7 +209,6 @@ cpu-as-$(CONFIG_PPC_E500) += -Wa,-me500
# LLVM IAS doesn't understand either flag: https://github.com/ClangBuiltLinux/linux/issues/675 # LLVM IAS doesn't understand either flag: https://github.com/ClangBuiltLinux/linux/issues/675
# but LLVM IAS only supports ISA >= 2.06 for Book3S 64 anyway... # but LLVM IAS only supports ISA >= 2.06 for Book3S 64 anyway...
cpu-as-$(CONFIG_PPC_BOOK3S_64) += $(call as-option,-Wa$(comma)-mpower4) $(call as-option,-Wa$(comma)-many) cpu-as-$(CONFIG_PPC_BOOK3S_64) += $(call as-option,-Wa$(comma)-mpower4) $(call as-option,-Wa$(comma)-many)
cpu-as-$(CONFIG_PPC_E500MC) += $(call as-option,-Wa$(comma)-me500mc)
KBUILD_AFLAGS += $(cpu-as-y) KBUILD_AFLAGS += $(cpu-as-y)
KBUILD_CFLAGS += $(cpu-as-y) KBUILD_CFLAGS += $(cpu-as-y)
......
...@@ -39,13 +39,19 @@ BOOTCFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \ ...@@ -39,13 +39,19 @@ BOOTCFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
$(LINUXINCLUDE) $(LINUXINCLUDE)
ifdef CONFIG_PPC64_BOOT_WRAPPER ifdef CONFIG_PPC64_BOOT_WRAPPER
ifdef CONFIG_CPU_LITTLE_ENDIAN BOOTCFLAGS += -m64
BOOTCFLAGS += -m64 -mcpu=powerpc64le
else else
BOOTCFLAGS += -m64 -mcpu=powerpc64 BOOTCFLAGS += -m32
endif endif
ifdef CONFIG_TARGET_CPU_BOOL
BOOTCFLAGS += -mcpu=$(CONFIG_TARGET_CPU)
else ifdef CONFIG_PPC64_BOOT_WRAPPER
ifdef CONFIG_CPU_LITTLE_ENDIAN
BOOTCFLAGS += -mcpu=powerpc64le
else else
BOOTCFLAGS += -m32 -mcpu=powerpc BOOTCFLAGS += -mcpu=powerpc64
endif
endif endif
BOOTCFLAGS += -isystem $(shell $(BOOTCC) -print-file-name=include) BOOTCFLAGS += -isystem $(shell $(BOOTCC) -print-file-name=include)
......
...@@ -367,11 +367,34 @@ watchdog@2 { ...@@ -367,11 +367,34 @@ watchdog@2 {
}; };
reboot@d { reboot@d {
/*
* CPLD firmware which manages system reset and
* watchdog registers has bugs. It does not
* autoclear system reset register after change
* and watchdog ignores reset line on immediate
* succeeding reset cycle triggered by watchdog.
* These bugs have to be workarounded in U-Boot
* bootloader. So use system reset via syscon as
* a last resort because older U-Boot versions
* do not have workaround for watchdog.
*
* Reset method via rstcr's global-utilities
* (the preferred one) has priority level 128,
* watchdog has priority level 0 and default
* syscon-reboot priority level is 192.
*
* So define syscon-reboot with custom priority
* level 64 (between rstcr and watchdog) because
* rstcr should stay as default preferred reset
* method and reset via watchdog is more broken
* than system reset via syscon.
*/
compatible = "syscon-reboot"; compatible = "syscon-reboot";
reg = <0x0d 0x01>; reg = <0x0d 0x01>;
offset = <0x0d>; offset = <0x0d>;
mask = <0x01>; mask = <0x01>;
value = <0x01>; value = <0x01>;
priority = <64>;
}; };
led-controller@13 { led-controller@13 {
......
CONFIG_PPC64=y
CONFIG_CELL_CPU=y
CONFIG_ALTIVEC=y
CONFIG_SMP=y
CONFIG_NR_CPUS=2
CONFIG_SYSVIPC=y CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y CONFIG_POSIX_MQUEUE=y
CONFIG_HIGH_RES_TIMERS=y CONFIG_HIGH_RES_TIMERS=y
...@@ -10,11 +5,12 @@ CONFIG_BLK_DEV_INITRD=y ...@@ -10,11 +5,12 @@ CONFIG_BLK_DEV_INITRD=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_EMBEDDED=y CONFIG_EMBEDDED=y
# CONFIG_PERF_EVENTS is not set # CONFIG_PERF_EVENTS is not set
# CONFIG_COMPAT_BRK is not set
CONFIG_SLAB=y
CONFIG_PROFILING=y CONFIG_PROFILING=y
CONFIG_MODULES=y CONFIG_PPC64=y
CONFIG_MODULE_UNLOAD=y CONFIG_CELL_CPU=y
CONFIG_ALTIVEC=y
CONFIG_SMP=y
CONFIG_NR_CPUS=2
# CONFIG_PPC_POWERNV is not set # CONFIG_PPC_POWERNV is not set
# CONFIG_PPC_PSERIES is not set # CONFIG_PPC_PSERIES is not set
# CONFIG_PPC_PMAC is not set # CONFIG_PPC_PMAC is not set
...@@ -27,17 +23,20 @@ CONFIG_PS3_FLASH=y ...@@ -27,17 +23,20 @@ CONFIG_PS3_FLASH=y
CONFIG_PS3_VRAM=m CONFIG_PS3_VRAM=m
CONFIG_PS3_LPM=m CONFIG_PS3_LPM=m
# CONFIG_PPC_OF_BOOT_TRAMPOLINE is not set # CONFIG_PPC_OF_BOOT_TRAMPOLINE is not set
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
CONFIG_BINFMT_MISC=y
CONFIG_KEXEC=y CONFIG_KEXEC=y
CONFIG_PPC_4K_PAGES=y CONFIG_PPC_4K_PAGES=y
# CONFIG_SPARSEMEM_VMEMMAP is not set
# CONFIG_COMPACTION is not set
CONFIG_SCHED_SMT=y CONFIG_SCHED_SMT=y
CONFIG_PM=y CONFIG_PM=y
CONFIG_PM_DEBUG=y CONFIG_PM_DEBUG=y
# CONFIG_SECCOMP is not set # CONFIG_SECCOMP is not set
# CONFIG_PCI is not set CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
CONFIG_BINFMT_MISC=y
CONFIG_SLAB=y
# CONFIG_COMPAT_BRK is not set
# CONFIG_SPARSEMEM_VMEMMAP is not set
# CONFIG_COMPACTION is not set
CONFIG_NET=y CONFIG_NET=y
CONFIG_PACKET=y CONFIG_PACKET=y
CONFIG_UNIX=y CONFIG_UNIX=y
...@@ -87,7 +86,6 @@ CONFIG_USB_USBNET=m ...@@ -87,7 +86,6 @@ CONFIG_USB_USBNET=m
# CONFIG_USB_NET_NET1080 is not set # CONFIG_USB_NET_NET1080 is not set
# CONFIG_USB_NET_CDC_SUBSET is not set # CONFIG_USB_NET_CDC_SUBSET is not set
# CONFIG_USB_NET_ZAURUS is not set # CONFIG_USB_NET_ZAURUS is not set
CONFIG_INPUT_FF_MEMLESS=m
CONFIG_INPUT_JOYDEV=m CONFIG_INPUT_JOYDEV=m
CONFIG_INPUT_EVDEV=m CONFIG_INPUT_EVDEV=m
# CONFIG_INPUT_KEYBOARD is not set # CONFIG_INPUT_KEYBOARD is not set
...@@ -110,13 +108,10 @@ CONFIG_SND=m ...@@ -110,13 +108,10 @@ CONFIG_SND=m
# CONFIG_SND_DRIVERS is not set # CONFIG_SND_DRIVERS is not set
CONFIG_SND_USB_AUDIO=m CONFIG_SND_USB_AUDIO=m
CONFIG_HIDRAW=y CONFIG_HIDRAW=y
CONFIG_HID_APPLE=m
CONFIG_HID_BELKIN=m CONFIG_HID_BELKIN=m
CONFIG_HID_CHERRY=m CONFIG_HID_CHERRY=m
CONFIG_HID_EZKEY=m CONFIG_HID_EZKEY=m
CONFIG_HID_TWINHAN=m CONFIG_HID_TWINHAN=m
CONFIG_HID_LOGITECH=m
CONFIG_HID_LOGITECH_DJ=m
CONFIG_HID_MICROSOFT=m CONFIG_HID_MICROSOFT=m
CONFIG_HID_SUNPLUS=m CONFIG_HID_SUNPLUS=m
CONFIG_HID_SMARTJOYPLUS=m CONFIG_HID_SMARTJOYPLUS=m
...@@ -151,8 +146,12 @@ CONFIG_CIFS=m ...@@ -151,8 +146,12 @@ CONFIG_CIFS=m
CONFIG_NLS=y CONFIG_NLS=y
CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ISO8859_1=y CONFIG_NLS_ISO8859_1=y
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_LZO=m
CONFIG_CRC_CCITT=m CONFIG_CRC_CCITT=m
CONFIG_CRC_T10DIF=y CONFIG_CRC_T10DIF=y
CONFIG_PRINTK_TIME=y
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
CONFIG_MAGIC_SYSRQ=y CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_MEMORY_INIT=y CONFIG_DEBUG_MEMORY_INIT=y
...@@ -163,7 +162,3 @@ CONFIG_DEBUG_LOCKDEP=y ...@@ -163,7 +162,3 @@ CONFIG_DEBUG_LOCKDEP=y
CONFIG_DEBUG_LIST=y CONFIG_DEBUG_LIST=y
CONFIG_RCU_CPU_STALL_TIMEOUT=60 CONFIG_RCU_CPU_STALL_TIMEOUT=60
# CONFIG_FTRACE is not set # CONFIG_FTRACE is not set
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_LZO=m
CONFIG_PRINTK_TIME=y
...@@ -113,9 +113,7 @@ FUNC_START(CRC_FUNCTION_NAME) ...@@ -113,9 +113,7 @@ FUNC_START(CRC_FUNCTION_NAME)
#endif #endif
#ifdef BYTESWAP_DATA #ifdef BYTESWAP_DATA
addis r3,r2,.byteswap_constant@toc@ha LOAD_REG_ADDR(r3, .byteswap_constant)
addi r3,r3,.byteswap_constant@toc@l
lvx byteswap,0,r3 lvx byteswap,0,r3
addi r3,r3,16 addi r3,r3,16
#endif #endif
...@@ -150,8 +148,7 @@ FUNC_START(CRC_FUNCTION_NAME) ...@@ -150,8 +148,7 @@ FUNC_START(CRC_FUNCTION_NAME)
addi r7,r7,-1 addi r7,r7,-1
mtctr r7 mtctr r7
addis r3,r2,.constants@toc@ha LOAD_REG_ADDR(r3, .constants)
addi r3,r3,.constants@toc@l
/* Find the start of our constants */ /* Find the start of our constants */
add r3,r3,r8 add r3,r3,r8
...@@ -506,8 +503,7 @@ FUNC_START(CRC_FUNCTION_NAME) ...@@ -506,8 +503,7 @@ FUNC_START(CRC_FUNCTION_NAME)
.Lbarrett_reduction: .Lbarrett_reduction:
/* Barrett constants */ /* Barrett constants */
addis r3,r2,.barrett_constants@toc@ha LOAD_REG_ADDR(r3, .barrett_constants)
addi r3,r3,.barrett_constants@toc@l
lvx const1,0,r3 lvx const1,0,r3
lvx const2,off16,r3 lvx const2,off16,r3
...@@ -610,8 +606,7 @@ FUNC_START(CRC_FUNCTION_NAME) ...@@ -610,8 +606,7 @@ FUNC_START(CRC_FUNCTION_NAME)
cmpdi r5,0 cmpdi r5,0
beq .Lzero beq .Lzero
addis r3,r2,.short_constants@toc@ha LOAD_REG_ADDR(r3, .short_constants)
addi r3,r3,.short_constants@toc@l
/* Calculate where in the constant table we need to start */ /* Calculate where in the constant table we need to start */
subfic r6,r5,256 subfic r6,r5,256
......
...@@ -35,9 +35,9 @@ ...@@ -35,9 +35,9 @@
* However, on CPUs that don't support lwsync, lwsync actually maps to a * However, on CPUs that don't support lwsync, lwsync actually maps to a
* heavy-weight sync, so smp_wmb() can be a lighter-weight eieio. * heavy-weight sync, so smp_wmb() can be a lighter-weight eieio.
*/ */
#define mb() __asm__ __volatile__ ("sync" : : : "memory") #define __mb() __asm__ __volatile__ ("sync" : : : "memory")
#define rmb() __asm__ __volatile__ ("sync" : : : "memory") #define __rmb() __asm__ __volatile__ ("sync" : : : "memory")
#define wmb() __asm__ __volatile__ ("sync" : : : "memory") #define __wmb() __asm__ __volatile__ ("sync" : : : "memory")
/* The sub-arch has lwsync */ /* The sub-arch has lwsync */
#if defined(CONFIG_PPC64) || defined(CONFIG_PPC_E500MC) #if defined(CONFIG_PPC64) || defined(CONFIG_PPC_E500MC)
...@@ -51,12 +51,12 @@ ...@@ -51,12 +51,12 @@
/* clang defines this macro for a builtin, which will not work with runtime patching */ /* clang defines this macro for a builtin, which will not work with runtime patching */
#undef __lwsync #undef __lwsync
#define __lwsync() __asm__ __volatile__ (stringify_in_c(LWSYNC) : : :"memory") #define __lwsync() __asm__ __volatile__ (stringify_in_c(LWSYNC) : : :"memory")
#define dma_rmb() __lwsync() #define __dma_rmb() __lwsync()
#define dma_wmb() __asm__ __volatile__ (stringify_in_c(SMPWMB) : : :"memory") #define __dma_wmb() __asm__ __volatile__ (stringify_in_c(SMPWMB) : : :"memory")
#define __smp_lwsync() __lwsync() #define __smp_lwsync() __lwsync()
#define __smp_mb() mb() #define __smp_mb() __mb()
#define __smp_rmb() __lwsync() #define __smp_rmb() __lwsync()
#define __smp_wmb() __asm__ __volatile__ (stringify_in_c(SMPWMB) : : :"memory") #define __smp_wmb() __asm__ __volatile__ (stringify_in_c(SMPWMB) : : :"memory")
......
...@@ -335,6 +335,7 @@ ...@@ -335,6 +335,7 @@
#define H_RPT_INVALIDATE 0x448 #define H_RPT_INVALIDATE 0x448
#define H_SCM_FLUSH 0x44C #define H_SCM_FLUSH 0x44C
#define H_GET_ENERGY_SCALE_INFO 0x450 #define H_GET_ENERGY_SCALE_INFO 0x450
#define H_PKS_SIGNED_UPDATE 0x454
#define H_WATCHDOG 0x45C #define H_WATCHDOG 0x45C
#define MAX_HCALL_OPCODE H_WATCHDOG #define MAX_HCALL_OPCODE H_WATCHDOG
......
...@@ -36,15 +36,17 @@ ...@@ -36,15 +36,17 @@
#define PACA_IRQ_DEC 0x08 /* Or FIT */ #define PACA_IRQ_DEC 0x08 /* Or FIT */
#define PACA_IRQ_HMI 0x10 #define PACA_IRQ_HMI 0x10
#define PACA_IRQ_PMI 0x20 #define PACA_IRQ_PMI 0x20
#define PACA_IRQ_REPLAYING 0x40
/* /*
* Some soft-masked interrupts must be hard masked until they are replayed * Some soft-masked interrupts must be hard masked until they are replayed
* (e.g., because the soft-masked handler does not clear the exception). * (e.g., because the soft-masked handler does not clear the exception).
* Interrupt replay itself must remain hard masked too.
*/ */
#ifdef CONFIG_PPC_BOOK3S #ifdef CONFIG_PPC_BOOK3S
#define PACA_IRQ_MUST_HARD_MASK (PACA_IRQ_EE|PACA_IRQ_PMI) #define PACA_IRQ_MUST_HARD_MASK (PACA_IRQ_EE|PACA_IRQ_PMI|PACA_IRQ_REPLAYING)
#else #else
#define PACA_IRQ_MUST_HARD_MASK (PACA_IRQ_EE) #define PACA_IRQ_MUST_HARD_MASK (PACA_IRQ_EE|PACA_IRQ_REPLAYING)
#endif #endif
#endif /* CONFIG_PPC64 */ #endif /* CONFIG_PPC64 */
......
...@@ -74,17 +74,18 @@ ...@@ -74,17 +74,18 @@
#include <asm/kprobes.h> #include <asm/kprobes.h>
#include <asm/runlatch.h> #include <asm/runlatch.h>
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC_IRQ_SOFT_MASK_DEBUG
/* /*
* WARN/BUG is handled with a program interrupt so minimise checks here to * WARN/BUG is handled with a program interrupt so minimise checks here to
* avoid recursion and maximise the chance of getting the first oops handled. * avoid recursion and maximise the chance of getting the first oops handled.
*/ */
#define INT_SOFT_MASK_BUG_ON(regs, cond) \ #define INT_SOFT_MASK_BUG_ON(regs, cond) \
do { \ do { \
if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG) && \ if ((user_mode(regs) || (TRAP(regs) != INTERRUPT_PROGRAM))) \
(user_mode(regs) || (TRAP(regs) != INTERRUPT_PROGRAM))) \
BUG_ON(cond); \ BUG_ON(cond); \
} while (0) } while (0)
#else
#define INT_SOFT_MASK_BUG_ON(regs, cond)
#endif #endif
#ifdef CONFIG_PPC_BOOK3S_64 #ifdef CONFIG_PPC_BOOK3S_64
...@@ -151,28 +152,8 @@ static inline void booke_restore_dbcr0(void) ...@@ -151,28 +152,8 @@ static inline void booke_restore_dbcr0(void)
static inline void interrupt_enter_prepare(struct pt_regs *regs) static inline void interrupt_enter_prepare(struct pt_regs *regs)
{ {
#ifdef CONFIG_PPC32
if (!arch_irq_disabled_regs(regs))
trace_hardirqs_off();
if (user_mode(regs))
kuap_lock();
else
kuap_save_and_lock(regs);
if (user_mode(regs))
account_cpu_user_entry();
#endif
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
bool trace_enable = false; irq_soft_mask_set(IRQS_ALL_DISABLED);
if (IS_ENABLED(CONFIG_TRACE_IRQFLAGS)) {
if (irq_soft_mask_set_return(IRQS_ALL_DISABLED) == IRQS_ENABLED)
trace_enable = true;
} else {
irq_soft_mask_set(IRQS_ALL_DISABLED);
}
/* /*
* If the interrupt was taken with HARD_DIS clear, then enable MSR[EE]. * If the interrupt was taken with HARD_DIS clear, then enable MSR[EE].
...@@ -188,9 +169,10 @@ static inline void interrupt_enter_prepare(struct pt_regs *regs) ...@@ -188,9 +169,10 @@ static inline void interrupt_enter_prepare(struct pt_regs *regs)
} else { } else {
__hard_RI_enable(); __hard_RI_enable();
} }
/* Enable MSR[RI] early, to support kernel SLB and hash faults */
#endif
/* Do this when RI=1 because it can cause SLB faults */ if (!arch_irq_disabled_regs(regs))
if (trace_enable)
trace_hardirqs_off(); trace_hardirqs_off();
if (user_mode(regs)) { if (user_mode(regs)) {
...@@ -215,7 +197,6 @@ static inline void interrupt_enter_prepare(struct pt_regs *regs) ...@@ -215,7 +197,6 @@ static inline void interrupt_enter_prepare(struct pt_regs *regs)
} }
INT_SOFT_MASK_BUG_ON(regs, !arch_irq_disabled_regs(regs) && INT_SOFT_MASK_BUG_ON(regs, !arch_irq_disabled_regs(regs) &&
!(regs->msr & MSR_EE)); !(regs->msr & MSR_EE));
#endif
booke_restore_dbcr0(); booke_restore_dbcr0();
} }
......
...@@ -16,9 +16,6 @@ ...@@ -16,9 +16,6 @@
extern atomic_t ppc_n_lost_interrupts; extern atomic_t ppc_n_lost_interrupts;
/* This number is used when no interrupt has been assigned */
#define NO_IRQ (0)
/* Total number of virq in the platform */ /* Total number of virq in the platform */
#define NR_IRQS CONFIG_NR_IRQS #define NR_IRQS CONFIG_NR_IRQS
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#define _ASM_POWERPC_MACHDEP_H #define _ASM_POWERPC_MACHDEP_H
#ifdef __KERNEL__ #ifdef __KERNEL__
#include <linux/compiler.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
...@@ -220,11 +221,16 @@ extern struct machdep_calls *machine_id; ...@@ -220,11 +221,16 @@ extern struct machdep_calls *machine_id;
EXPORT_SYMBOL(mach_##name); \ EXPORT_SYMBOL(mach_##name); \
struct machdep_calls mach_##name __machine_desc = struct machdep_calls mach_##name __machine_desc =
#define machine_is(name) \ static inline bool __machine_is(const struct machdep_calls *md)
({ \ {
extern struct machdep_calls mach_##name \ WARN_ON(!machine_id); // complain if used before probe_machine()
__attribute__((weak)); \ return machine_id == md;
machine_id == &mach_##name; \ }
#define machine_is(name) \
({ \
extern struct machdep_calls mach_##name __weak; \
__machine_is(&mach_##name); \
}) })
static inline void log_error(char *buf, unsigned int err_type, int fatal) static inline void log_error(char *buf, unsigned int err_type, int fatal)
......
...@@ -295,7 +295,6 @@ extern void free_unused_pacas(void); ...@@ -295,7 +295,6 @@ extern void free_unused_pacas(void);
#else /* CONFIG_PPC64 */ #else /* CONFIG_PPC64 */
static inline void allocate_paca_ptrs(void) { }
static inline void allocate_paca(int cpu) { } static inline void allocate_paca(int cpu) { }
static inline void free_unused_pacas(void) { } static inline void free_unused_pacas(void) { }
......
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef _ASM_POWERPC_PAPR_SYSPARM_H
#define _ASM_POWERPC_PAPR_SYSPARM_H
typedef struct {
const u32 token;
} papr_sysparm_t;
#define mk_papr_sysparm(x_) ((papr_sysparm_t){ .token = x_, })
/*
* Derived from the "Defined Parameters" table in PAPR 7.3.16 System
* Parameters Option. Where the spec says "characteristics", we use
* "attrs" in the symbolic names to keep them from getting too
* unwieldy.
*/
#define PAPR_SYSPARM_SHARED_PROC_LPAR_ATTRS mk_papr_sysparm(20)
#define PAPR_SYSPARM_PROC_MODULE_INFO mk_papr_sysparm(43)
#define PAPR_SYSPARM_COOP_MEM_OVERCOMMIT_ATTRS mk_papr_sysparm(44)
#define PAPR_SYSPARM_TLB_BLOCK_INVALIDATE_ATTRS mk_papr_sysparm(50)
#define PAPR_SYSPARM_LPAR_NAME mk_papr_sysparm(55)
enum {
PAPR_SYSPARM_MAX_INPUT = 1024,
PAPR_SYSPARM_MAX_OUTPUT = 4000,
};
struct papr_sysparm_buf {
__be16 len;
char val[PAPR_SYSPARM_MAX_OUTPUT];
};
struct papr_sysparm_buf *papr_sysparm_buf_alloc(void);
void papr_sysparm_buf_free(struct papr_sysparm_buf *buf);
int papr_sysparm_set(papr_sysparm_t param, const struct papr_sysparm_buf *buf);
int papr_sysparm_get(papr_sysparm_t param, struct papr_sysparm_buf *buf);
#endif /* _ASM_POWERPC_PAPR_SYSPARM_H */
...@@ -176,8 +176,10 @@ extern int pci_device_from_OF_node(struct device_node *node, ...@@ -176,8 +176,10 @@ extern int pci_device_from_OF_node(struct device_node *node,
#endif #endif
#ifndef CONFIG_PPC64 #ifndef CONFIG_PPC64
#ifdef CONFIG_PPC_CHRP #ifdef CONFIG_PPC_PCI_OF_BUS_MAP
extern void pci_create_OF_bus_map(void); extern void pci_create_OF_bus_map(void);
#else
static inline void pci_create_OF_bus_map(void) {}
#endif #endif
#else /* CONFIG_PPC64 */ #else /* CONFIG_PPC64 */
......
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2022 IBM Corporation
* Author: Nayna Jain <nayna@linux.ibm.com>
*
* Platform keystore for pseries LPAR(PLPKS).
*/
#ifndef _ASM_POWERPC_PLPKS_H
#define _ASM_POWERPC_PLPKS_H
#ifdef CONFIG_PSERIES_PLPKS
#include <linux/types.h>
#include <linux/list.h>
// Object policy flags from supported_policies
#define PLPKS_OSSECBOOTAUDIT PPC_BIT32(1) // OS secure boot must be audit/enforce
#define PLPKS_OSSECBOOTENFORCE PPC_BIT32(2) // OS secure boot must be enforce
#define PLPKS_PWSET PPC_BIT32(3) // No access without password set
#define PLPKS_WORLDREADABLE PPC_BIT32(4) // Readable without authentication
#define PLPKS_IMMUTABLE PPC_BIT32(5) // Once written, object cannot be removed
#define PLPKS_TRANSIENT PPC_BIT32(6) // Object does not persist through reboot
#define PLPKS_SIGNEDUPDATE PPC_BIT32(7) // Object can only be modified by signed updates
#define PLPKS_HVPROVISIONED PPC_BIT32(28) // Hypervisor has provisioned this object
// Signature algorithm flags from signed_update_algorithms
#define PLPKS_ALG_RSA2048 PPC_BIT(0)
#define PLPKS_ALG_RSA4096 PPC_BIT(1)
// Object label OS metadata flags
#define PLPKS_VAR_LINUX 0x02
#define PLPKS_VAR_COMMON 0x04
// Flags for which consumer owns an object is owned by
#define PLPKS_FW_OWNER 0x1
#define PLPKS_BOOTLOADER_OWNER 0x2
#define PLPKS_OS_OWNER 0x3
// Flags for label metadata fields
#define PLPKS_LABEL_VERSION 0
#define PLPKS_MAX_LABEL_ATTR_SIZE 16
#define PLPKS_MAX_NAME_SIZE 239
#define PLPKS_MAX_DATA_SIZE 4000
// Timeouts for PLPKS operations
#define PLPKS_MAX_TIMEOUT 5000 // msec
#define PLPKS_FLUSH_SLEEP 10 // msec
#define PLPKS_FLUSH_SLEEP_RANGE 400
struct plpks_var {
char *component;
u8 *name;
u8 *data;
u32 policy;
u16 namelen;
u16 datalen;
u8 os;
};
struct plpks_var_name {
u8 *name;
u16 namelen;
};
struct plpks_var_name_list {
u32 varcount;
struct plpks_var_name varlist[];
};
/**
* Updates the authenticated variable. It expects NULL as the component.
*/
int plpks_signed_update_var(struct plpks_var *var, u64 flags);
/**
* Writes the specified var and its data to PKS.
* Any caller of PKS driver should present a valid component type for
* their variable.
*/
int plpks_write_var(struct plpks_var var);
/**
* Removes the specified var and its data from PKS.
*/
int plpks_remove_var(char *component, u8 varos,
struct plpks_var_name vname);
/**
* Returns the data for the specified os variable.
*
* Caller must allocate a buffer in var->data with length in var->datalen.
* If no buffer is provided, var->datalen will be populated with the object's
* size.
*/
int plpks_read_os_var(struct plpks_var *var);
/**
* Returns the data for the specified firmware variable.
*
* Caller must allocate a buffer in var->data with length in var->datalen.
* If no buffer is provided, var->datalen will be populated with the object's
* size.
*/
int plpks_read_fw_var(struct plpks_var *var);
/**
* Returns the data for the specified bootloader variable.
*
* Caller must allocate a buffer in var->data with length in var->datalen.
* If no buffer is provided, var->datalen will be populated with the object's
* size.
*/
int plpks_read_bootloader_var(struct plpks_var *var);
/**
* Returns if PKS is available on this LPAR.
*/
bool plpks_is_available(void);
/**
* Returns version of the Platform KeyStore.
*/
u8 plpks_get_version(void);
/**
* Returns hypervisor storage overhead per object, not including the size of
* the object or label. Only valid for config version >= 2
*/
u16 plpks_get_objoverhead(void);
/**
* Returns maximum password size. Must be >= 32 bytes
*/
u16 plpks_get_maxpwsize(void);
/**
* Returns maximum object size supported by Platform KeyStore.
*/
u16 plpks_get_maxobjectsize(void);
/**
* Returns maximum object label size supported by Platform KeyStore.
*/
u16 plpks_get_maxobjectlabelsize(void);
/**
* Returns total size of the configured Platform KeyStore.
*/
u32 plpks_get_totalsize(void);
/**
* Returns used space from the total size of the Platform KeyStore.
*/
u32 plpks_get_usedspace(void);
/**
* Returns bitmask of policies supported by the hypervisor.
*/
u32 plpks_get_supportedpolicies(void);
/**
* Returns maximum byte size of a single object supported by the hypervisor.
* Only valid for config version >= 3
*/
u32 plpks_get_maxlargeobjectsize(void);
/**
* Returns bitmask of signature algorithms supported for signed updates.
* Only valid for config version >= 3
*/
u64 plpks_get_signedupdatealgorithms(void);
/**
* Returns the length of the PLPKS password in bytes.
*/
u16 plpks_get_passwordlen(void);
/**
* Called in early init to retrieve and clear the PLPKS password from the DT.
*/
void plpks_early_init_devtree(void);
/**
* Populates the FDT with the PLPKS password to prepare for kexec.
*/
int plpks_populate_fdt(void *fdt);
#else // CONFIG_PSERIES_PLPKS
static inline bool plpks_is_available(void) { return false; }
static inline u16 plpks_get_passwordlen(void) { BUILD_BUG(); }
static inline void plpks_early_init_devtree(void) { }
static inline int plpks_populate_fdt(void *fdt) { BUILD_BUG(); }
#endif // CONFIG_PSERIES_PLPKS
#endif // _ASM_POWERPC_PLPKS_H
...@@ -18,8 +18,6 @@ struct rtas_t { ...@@ -18,8 +18,6 @@ struct rtas_t {
unsigned long entry; /* physical address pointer */ unsigned long entry; /* physical address pointer */
unsigned long base; /* physical address pointer */ unsigned long base; /* physical address pointer */
unsigned long size; unsigned long size;
arch_spinlock_t lock;
struct rtas_args args;
struct device_node *dev; /* virtual address pointer */ struct device_node *dev; /* virtual address pointer */
}; };
......
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef _ASM_POWERPC_RTAS_WORK_AREA_H
#define _ASM_POWERPC_RTAS_WORK_AREA_H
#include <linux/build_bug.h>
#include <linux/sizes.h>
#include <linux/types.h>
#include <asm/page.h>
/**
* struct rtas_work_area - RTAS work area descriptor.
*
* Descriptor for a "work area" in PAPR terminology that satisfies
* RTAS addressing requirements.
*/
struct rtas_work_area {
/* private: Use the APIs provided below. */
char *buf;
size_t size;
};
enum {
/* Maximum allocation size, enforced at build time. */
RTAS_WORK_AREA_MAX_ALLOC_SZ = SZ_128K,
};
/**
* rtas_work_area_alloc() - Acquire a work area of the requested size.
* @size_: Allocation size. Must be compile-time constant and not more
* than %RTAS_WORK_AREA_MAX_ALLOC_SZ.
*
* Allocate a buffer suitable for passing to RTAS functions that have
* a memory address parameter, often (but not always) referred to as a
* "work area" in PAPR. Although callers are allowed to block while
* holding a work area, the amount of memory reserved for this purpose
* is limited, and allocations should be short-lived. A good guideline
* is to release any allocated work area before returning from a
* system call.
*
* This function does not fail. It blocks until the allocation
* succeeds. To prevent deadlocks, callers are discouraged from
* allocating more than one work area simultaneously in a single task
* context.
*
* Context: This function may sleep.
* Return: A &struct rtas_work_area descriptor for the allocated work area.
*/
#define rtas_work_area_alloc(size_) ({ \
static_assert(__builtin_constant_p(size_)); \
static_assert((size_) > 0); \
static_assert((size_) <= RTAS_WORK_AREA_MAX_ALLOC_SZ); \
__rtas_work_area_alloc(size_); \
})
/*
* Do not call __rtas_work_area_alloc() directly. Use
* rtas_work_area_alloc().
*/
struct rtas_work_area *__rtas_work_area_alloc(size_t size);
/**
* rtas_work_area_free() - Release a work area.
* @area: Work area descriptor as returned from rtas_work_area_alloc().
*
* Return a work area buffer to the pool.
*/
void rtas_work_area_free(struct rtas_work_area *area);
static inline char *rtas_work_area_raw_buf(const struct rtas_work_area *area)
{
return area->buf;
}
static inline size_t rtas_work_area_size(const struct rtas_work_area *area)
{
return area->size;
}
static inline phys_addr_t rtas_work_area_phys(const struct rtas_work_area *area)
{
return __pa(area->buf);
}
/*
* Early setup for the work area allocator. Call from
* rtas_initialize() only.
*/
#ifdef CONFIG_PPC_PSERIES
void rtas_work_area_reserve_arena(phys_addr_t limit);
#else /* CONFIG_PPC_PSERIES */
static inline void rtas_work_area_reserve_arena(phys_addr_t limit) {}
#endif /* CONFIG_PPC_PSERIES */
#endif /* _ASM_POWERPC_RTAS_WORK_AREA_H */
This diff is collapsed.
...@@ -10,25 +10,30 @@ ...@@ -10,25 +10,30 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/sysfs.h>
extern const struct secvar_operations *secvar_ops; extern const struct secvar_operations *secvar_ops;
struct secvar_operations { struct secvar_operations {
int (*get)(const char *key, uint64_t key_len, u8 *data, int (*get)(const char *key, u64 key_len, u8 *data, u64 *data_size);
uint64_t *data_size); int (*get_next)(const char *key, u64 *key_len, u64 keybufsize);
int (*get_next)(const char *key, uint64_t *key_len, int (*set)(const char *key, u64 key_len, u8 *data, u64 data_size);
uint64_t keybufsize); ssize_t (*format)(char *buf, size_t bufsize);
int (*set)(const char *key, uint64_t key_len, u8 *data, int (*max_size)(u64 *max_size);
uint64_t data_size); const struct attribute **config_attrs;
// NULL-terminated array of fixed variable names
// Only used if get_next() isn't provided
const char * const *var_names;
}; };
#ifdef CONFIG_PPC_SECURE_BOOT #ifdef CONFIG_PPC_SECURE_BOOT
extern void set_secvar_ops(const struct secvar_operations *ops); int set_secvar_ops(const struct secvar_operations *ops);
#else #else
static inline void set_secvar_ops(const struct secvar_operations *ops) { } static inline int set_secvar_ops(const struct secvar_operations *ops) { return 0; }
#endif #endif
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <asm/percpu.h> #include <asm/percpu.h>
extern int boot_cpuid; extern int boot_cpuid;
extern int boot_cpu_hwid; /* PPC64 only */
extern int spinning_secondaries; extern int spinning_secondaries;
extern u32 *cpu_to_phys_id; extern u32 *cpu_to_phys_id;
extern bool coregroup_enabled; extern bool coregroup_enabled;
......
...@@ -119,6 +119,109 @@ TRACE_EVENT_FN_COND(hcall_exit, ...@@ -119,6 +119,109 @@ TRACE_EVENT_FN_COND(hcall_exit,
); );
#endif #endif
#ifdef CONFIG_PPC_RTAS
#include <asm/rtas-types.h>
TRACE_EVENT(rtas_input,
TP_PROTO(struct rtas_args *rtas_args, const char *name),
TP_ARGS(rtas_args, name),
TP_STRUCT__entry(
__field(__u32, nargs)
__string(name, name)
__dynamic_array(__u32, inputs, be32_to_cpu(rtas_args->nargs))
),
TP_fast_assign(
__entry->nargs = be32_to_cpu(rtas_args->nargs);
__assign_str(name, name);
be32_to_cpu_array(__get_dynamic_array(inputs), rtas_args->args, __entry->nargs);
),
TP_printk("%s arguments: %s", __get_str(name),
__print_array(__get_dynamic_array(inputs), __entry->nargs, 4)
)
);
TRACE_EVENT(rtas_output,
TP_PROTO(struct rtas_args *rtas_args, const char *name),
TP_ARGS(rtas_args, name),
TP_STRUCT__entry(
__field(__u32, nr_other)
__field(__s32, status)
__string(name, name)
__dynamic_array(__u32, other_outputs, be32_to_cpu(rtas_args->nret) - 1)
),
TP_fast_assign(
__entry->nr_other = be32_to_cpu(rtas_args->nret) - 1;
__entry->status = be32_to_cpu(rtas_args->rets[0]);
__assign_str(name, name);
be32_to_cpu_array(__get_dynamic_array(other_outputs),
&rtas_args->rets[1], __entry->nr_other);
),
TP_printk("%s status: %d, other outputs: %s", __get_str(name), __entry->status,
__print_array(__get_dynamic_array(other_outputs),
__entry->nr_other, 4)
)
);
DECLARE_EVENT_CLASS(rtas_parameter_block,
TP_PROTO(struct rtas_args *rtas_args),
TP_ARGS(rtas_args),
TP_STRUCT__entry(
__field(u32, token)
__field(u32, nargs)
__field(u32, nret)
__array(__u32, params, 16)
),
TP_fast_assign(
__entry->token = be32_to_cpu(rtas_args->token);
__entry->nargs = be32_to_cpu(rtas_args->nargs);
__entry->nret = be32_to_cpu(rtas_args->nret);
be32_to_cpu_array(__entry->params, rtas_args->args, ARRAY_SIZE(rtas_args->args));
),
TP_printk("token=%u nargs=%u nret=%u params:"
" [0]=0x%08x [1]=0x%08x [2]=0x%08x [3]=0x%08x"
" [4]=0x%08x [5]=0x%08x [6]=0x%08x [7]=0x%08x"
" [8]=0x%08x [9]=0x%08x [10]=0x%08x [11]=0x%08x"
" [12]=0x%08x [13]=0x%08x [14]=0x%08x [15]=0x%08x",
__entry->token, __entry->nargs, __entry->nret,
__entry->params[0], __entry->params[1], __entry->params[2], __entry->params[3],
__entry->params[4], __entry->params[5], __entry->params[6], __entry->params[7],
__entry->params[8], __entry->params[9], __entry->params[10], __entry->params[11],
__entry->params[12], __entry->params[13], __entry->params[14], __entry->params[15]
)
);
DEFINE_EVENT(rtas_parameter_block, rtas_ll_entry,
TP_PROTO(struct rtas_args *rtas_args),
TP_ARGS(rtas_args)
);
DEFINE_EVENT(rtas_parameter_block, rtas_ll_exit,
TP_PROTO(struct rtas_args *rtas_args),
TP_ARGS(rtas_args)
);
#endif /* CONFIG_PPC_RTAS */
#ifdef CONFIG_PPC_POWERNV #ifdef CONFIG_PPC_POWERNV
extern int opal_tracepoint_regfunc(void); extern int opal_tracepoint_regfunc(void);
extern void opal_tracepoint_unregfunc(void); extern void opal_tracepoint_unregfunc(void);
......
...@@ -54,6 +54,13 @@ CFLAGS_cputable.o += -DDISABLE_BRANCH_PROFILING ...@@ -54,6 +54,13 @@ CFLAGS_cputable.o += -DDISABLE_BRANCH_PROFILING
CFLAGS_btext.o += -DDISABLE_BRANCH_PROFILING CFLAGS_btext.o += -DDISABLE_BRANCH_PROFILING
endif endif
KCSAN_SANITIZE_early_32.o := n
KCSAN_SANITIZE_early_64.o := n
KCSAN_SANITIZE_cputable.o := n
KCSAN_SANITIZE_btext.o := n
KCSAN_SANITIZE_paca.o := n
KCSAN_SANITIZE_setup_64.o := n
#ifdef CONFIG_RANDOMIZE_KSTACK_OFFSET #ifdef CONFIG_RANDOMIZE_KSTACK_OFFSET
# Remove stack protector to avoid triggering unneeded stack canary # Remove stack protector to avoid triggering unneeded stack canary
# checks due to randomize_kstack_offset. # checks due to randomize_kstack_offset.
...@@ -177,12 +184,15 @@ obj-$(CONFIG_PPC_SECVAR_SYSFS) += secvar-sysfs.o ...@@ -177,12 +184,15 @@ obj-$(CONFIG_PPC_SECVAR_SYSFS) += secvar-sysfs.o
# Disable GCOV, KCOV & sanitizers in odd or sensitive code # Disable GCOV, KCOV & sanitizers in odd or sensitive code
GCOV_PROFILE_prom_init.o := n GCOV_PROFILE_prom_init.o := n
KCOV_INSTRUMENT_prom_init.o := n KCOV_INSTRUMENT_prom_init.o := n
KCSAN_SANITIZE_prom_init.o := n
UBSAN_SANITIZE_prom_init.o := n UBSAN_SANITIZE_prom_init.o := n
GCOV_PROFILE_kprobes.o := n GCOV_PROFILE_kprobes.o := n
KCOV_INSTRUMENT_kprobes.o := n KCOV_INSTRUMENT_kprobes.o := n
KCSAN_SANITIZE_kprobes.o := n
UBSAN_SANITIZE_kprobes.o := n UBSAN_SANITIZE_kprobes.o := n
GCOV_PROFILE_kprobes-ftrace.o := n GCOV_PROFILE_kprobes-ftrace.o := n
KCOV_INSTRUMENT_kprobes-ftrace.o := n KCOV_INSTRUMENT_kprobes-ftrace.o := n
KCSAN_SANITIZE_kprobes-ftrace.o := n
UBSAN_SANITIZE_kprobes-ftrace.o := n UBSAN_SANITIZE_kprobes-ftrace.o := n
GCOV_PROFILE_syscall_64.o := n GCOV_PROFILE_syscall_64.o := n
KCOV_INSTRUMENT_syscall_64.o := n KCOV_INSTRUMENT_syscall_64.o := n
......
...@@ -1065,10 +1065,10 @@ void eeh_handle_normal_event(struct eeh_pe *pe) ...@@ -1065,10 +1065,10 @@ void eeh_handle_normal_event(struct eeh_pe *pe)
eeh_slot_error_detail(pe, EEH_LOG_PERM); eeh_slot_error_detail(pe, EEH_LOG_PERM);
/* Notify all devices that they're about to go down. */ /* Notify all devices that they're about to go down. */
eeh_set_channel_state(pe, pci_channel_io_perm_failure);
eeh_set_irq_state(pe, false); eeh_set_irq_state(pe, false);
eeh_pe_report("error_detected(permanent failure)", pe, eeh_pe_report("error_detected(permanent failure)", pe,
eeh_report_failure, NULL); eeh_report_failure, NULL);
eeh_set_channel_state(pe, pci_channel_io_perm_failure);
/* Mark the PE to be removed permanently */ /* Mark the PE to be removed permanently */
eeh_pe_state_mark(pe, EEH_PE_REMOVED); eeh_pe_state_mark(pe, EEH_PE_REMOVED);
...@@ -1185,10 +1185,10 @@ void eeh_handle_special_event(void) ...@@ -1185,10 +1185,10 @@ void eeh_handle_special_event(void)
/* Notify all devices to be down */ /* Notify all devices to be down */
eeh_pe_state_clear(pe, EEH_PE_PRI_BUS, true); eeh_pe_state_clear(pe, EEH_PE_PRI_BUS, true);
eeh_set_channel_state(pe, pci_channel_io_perm_failure);
eeh_pe_report( eeh_pe_report(
"error_detected(permanent failure)", pe, "error_detected(permanent failure)", pe,
eeh_report_failure, NULL); eeh_report_failure, NULL);
eeh_set_channel_state(pe, pci_channel_io_perm_failure);
pci_lock_rescan_remove(); pci_lock_rescan_remove();
list_for_each_entry(hose, &hose_list, list_node) { list_for_each_entry(hose, &hose_list, list_node) {
......
...@@ -21,7 +21,13 @@ _GLOBAL(epapr_ev_idle) ...@@ -21,7 +21,13 @@ _GLOBAL(epapr_ev_idle)
ori r4, r4,_TLF_NAPPING /* so when we take an exception */ ori r4, r4,_TLF_NAPPING /* so when we take an exception */
PPC_STL r4, TI_LOCAL_FLAGS(r2) /* it will return to our caller */ PPC_STL r4, TI_LOCAL_FLAGS(r2) /* it will return to our caller */
#ifdef CONFIG_BOOKE_OR_40x
wrteei 1 wrteei 1
#else
mfmsr r4
ori r4, r4, MSR_EE
mtmsr r4
#endif
idle_loop: idle_loop:
LOAD_REG_IMMEDIATE(r11, EV_HCALL_TOKEN(EV_IDLE)) LOAD_REG_IMMEDIATE(r11, EV_HCALL_TOKEN(EV_IDLE))
......
...@@ -160,12 +160,8 @@ __secondary_hold: ...@@ -160,12 +160,8 @@ __secondary_hold:
std r24,(ABS_ADDR(__secondary_hold_acknowledge, first_256B))(0) std r24,(ABS_ADDR(__secondary_hold_acknowledge, first_256B))(0)
sync sync
li r26,0
#ifdef CONFIG_PPC_BOOK3E_64
tovirt(r26,r26)
#endif
/* All secondary cpus wait here until told to start. */ /* All secondary cpus wait here until told to start. */
100: ld r12,(ABS_ADDR(__secondary_hold_spinloop, first_256B))(r26) 100: ld r12,(ABS_ADDR(__secondary_hold_spinloop, first_256B))(0)
cmpdi 0,r12,0 cmpdi 0,r12,0
beq 100b beq 100b
...@@ -475,8 +471,31 @@ SYM_FUNC_START_LOCAL(__mmu_off) ...@@ -475,8 +471,31 @@ SYM_FUNC_START_LOCAL(__mmu_off)
rfid rfid
b . /* prevent speculative execution */ b . /* prevent speculative execution */
SYM_FUNC_END(__mmu_off) SYM_FUNC_END(__mmu_off)
#endif
SYM_FUNC_START_LOCAL(start_initialization_book3s)
mflr r25
/* Setup some critical 970 SPRs before switching MMU off */
mfspr r0,SPRN_PVR
srwi r0,r0,16
cmpwi r0,0x39 /* 970 */
beq 1f
cmpwi r0,0x3c /* 970FX */
beq 1f
cmpwi r0,0x44 /* 970MP */
beq 1f
cmpwi r0,0x45 /* 970GX */
bne 2f
1: bl __cpu_preinit_ppc970
2:
/* Switch off MMU if not already off */
bl __mmu_off
mtlr r25
blr
SYM_FUNC_END(start_initialization_book3s)
#endif
/* /*
* Here is our main kernel entry point. We support currently 2 kind of entries * Here is our main kernel entry point. We support currently 2 kind of entries
...@@ -523,26 +542,10 @@ __start_initialization_multiplatform: ...@@ -523,26 +542,10 @@ __start_initialization_multiplatform:
#ifdef CONFIG_PPC_BOOK3E_64 #ifdef CONFIG_PPC_BOOK3E_64
bl start_initialization_book3e bl start_initialization_book3e
b __after_prom_start
#else #else
/* Setup some critical 970 SPRs before switching MMU off */ bl start_initialization_book3s
mfspr r0,SPRN_PVR
srwi r0,r0,16
cmpwi r0,0x39 /* 970 */
beq 1f
cmpwi r0,0x3c /* 970FX */
beq 1f
cmpwi r0,0x44 /* 970MP */
beq 1f
cmpwi r0,0x45 /* 970GX */
bne 2f
1: bl __cpu_preinit_ppc970
2:
/* Switch off MMU if not already off */
bl __mmu_off
b __after_prom_start
#endif /* CONFIG_PPC_BOOK3E_64 */ #endif /* CONFIG_PPC_BOOK3E_64 */
b __after_prom_start
__REF __REF
__boot_from_prom: __boot_from_prom:
......
...@@ -67,11 +67,9 @@ static void iommu_debugfs_add(struct iommu_table *tbl) ...@@ -67,11 +67,9 @@ static void iommu_debugfs_add(struct iommu_table *tbl)
static void iommu_debugfs_del(struct iommu_table *tbl) static void iommu_debugfs_del(struct iommu_table *tbl)
{ {
char name[10]; char name[10];
struct dentry *liobn_entry;
sprintf(name, "%08lx", tbl->it_index); sprintf(name, "%08lx", tbl->it_index);
liobn_entry = debugfs_lookup(name, iommu_debugfs_dir); debugfs_lookup_and_remove(name, iommu_debugfs_dir);
debugfs_remove(liobn_entry);
} }
#else #else
static void iommu_debugfs_add(struct iommu_table *tbl){} static void iommu_debugfs_add(struct iommu_table *tbl){}
......
...@@ -70,22 +70,19 @@ int distribute_irqs = 1; ...@@ -70,22 +70,19 @@ int distribute_irqs = 1;
static inline void next_interrupt(struct pt_regs *regs) static inline void next_interrupt(struct pt_regs *regs)
{ {
/* if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG)) {
* Softirq processing can enable/disable irqs, which will leave WARN_ON(!(local_paca->irq_happened & PACA_IRQ_HARD_DIS));
* MSR[EE] enabled and the soft mask set to IRQS_DISABLED. Fix WARN_ON(irq_soft_mask_return() != IRQS_ALL_DISABLED);
* this up. }
*/
if (!(local_paca->irq_happened & PACA_IRQ_HARD_DIS))
hard_irq_disable();
else
irq_soft_mask_set(IRQS_ALL_DISABLED);
/* /*
* We are responding to the next interrupt, so interrupt-off * We are responding to the next interrupt, so interrupt-off
* latencies should be reset here. * latencies should be reset here.
*/ */
lockdep_hardirq_exit();
trace_hardirqs_on(); trace_hardirqs_on();
trace_hardirqs_off(); trace_hardirqs_off();
lockdep_hardirq_enter();
} }
static inline bool irq_happened_test_and_clear(u8 irq) static inline bool irq_happened_test_and_clear(u8 irq)
...@@ -97,22 +94,11 @@ static inline bool irq_happened_test_and_clear(u8 irq) ...@@ -97,22 +94,11 @@ static inline bool irq_happened_test_and_clear(u8 irq)
return false; return false;
} }
void replay_soft_interrupts(void) static __no_kcsan void __replay_soft_interrupts(void)
{ {
struct pt_regs regs; struct pt_regs regs;
/* /*
* Be careful here, calling these interrupt handlers can cause
* softirqs to be raised, which they may run when calling irq_exit,
* which will cause local_irq_enable() to be run, which can then
* recurse into this function. Don't keep any state across
* interrupt handler calls which may change underneath us.
*
* Softirqs can not be disabled over replay to stop this recursion
* because interrupts taken in idle code may require RCU softirq
* to run in the irq RCU tracking context. This is a hard problem
* to fix without changes to the softirq or idle layer.
*
* We use local_paca rather than get_paca() to avoid all the * We use local_paca rather than get_paca() to avoid all the
* debug_smp_processor_id() business in this low level function. * debug_smp_processor_id() business in this low level function.
*/ */
...@@ -120,13 +106,20 @@ void replay_soft_interrupts(void) ...@@ -120,13 +106,20 @@ void replay_soft_interrupts(void)
if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG)) { if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG)) {
WARN_ON_ONCE(mfmsr() & MSR_EE); WARN_ON_ONCE(mfmsr() & MSR_EE);
WARN_ON(!(local_paca->irq_happened & PACA_IRQ_HARD_DIS)); WARN_ON(!(local_paca->irq_happened & PACA_IRQ_HARD_DIS));
WARN_ON(local_paca->irq_happened & PACA_IRQ_REPLAYING);
} }
/*
* PACA_IRQ_REPLAYING prevents interrupt handlers from enabling
* MSR[EE] to get PMIs, which can result in more IRQs becoming
* pending.
*/
local_paca->irq_happened |= PACA_IRQ_REPLAYING;
ppc_save_regs(&regs); ppc_save_regs(&regs);
regs.softe = IRQS_ENABLED; regs.softe = IRQS_ENABLED;
regs.msr |= MSR_EE; regs.msr |= MSR_EE;
again:
/* /*
* Force the delivery of pending soft-disabled interrupts on PS3. * Force the delivery of pending soft-disabled interrupts on PS3.
* Any HV call will have this side effect. * Any HV call will have this side effect.
...@@ -175,17 +168,18 @@ void replay_soft_interrupts(void) ...@@ -175,17 +168,18 @@ void replay_soft_interrupts(void)
next_interrupt(&regs); next_interrupt(&regs);
} }
/* local_paca->irq_happened &= ~PACA_IRQ_REPLAYING;
* Softirq processing can enable and disable interrupts, which can }
* result in new irqs becoming pending. Must keep looping until we
* have cleared out all pending interrupts. __no_kcsan void replay_soft_interrupts(void)
*/ {
if (local_paca->irq_happened & ~PACA_IRQ_HARD_DIS) irq_enter(); /* See comment in arch_local_irq_restore */
goto again; __replay_soft_interrupts();
irq_exit();
} }
#if defined(CONFIG_PPC_BOOK3S_64) && defined(CONFIG_PPC_KUAP) #if defined(CONFIG_PPC_BOOK3S_64) && defined(CONFIG_PPC_KUAP)
static inline void replay_soft_interrupts_irqrestore(void) static inline __no_kcsan void replay_soft_interrupts_irqrestore(void)
{ {
unsigned long kuap_state = get_kuap(); unsigned long kuap_state = get_kuap();
...@@ -200,16 +194,16 @@ static inline void replay_soft_interrupts_irqrestore(void) ...@@ -200,16 +194,16 @@ static inline void replay_soft_interrupts_irqrestore(void)
if (kuap_state != AMR_KUAP_BLOCKED) if (kuap_state != AMR_KUAP_BLOCKED)
set_kuap(AMR_KUAP_BLOCKED); set_kuap(AMR_KUAP_BLOCKED);
replay_soft_interrupts(); __replay_soft_interrupts();
if (kuap_state != AMR_KUAP_BLOCKED) if (kuap_state != AMR_KUAP_BLOCKED)
set_kuap(kuap_state); set_kuap(kuap_state);
} }
#else #else
#define replay_soft_interrupts_irqrestore() replay_soft_interrupts() #define replay_soft_interrupts_irqrestore() __replay_soft_interrupts()
#endif #endif
notrace void arch_local_irq_restore(unsigned long mask) notrace __no_kcsan void arch_local_irq_restore(unsigned long mask)
{ {
unsigned char irq_happened; unsigned char irq_happened;
...@@ -219,9 +213,13 @@ notrace void arch_local_irq_restore(unsigned long mask) ...@@ -219,9 +213,13 @@ notrace void arch_local_irq_restore(unsigned long mask)
return; return;
} }
if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG)) if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG)) {
WARN_ON_ONCE(in_nmi() || in_hardirq()); WARN_ON_ONCE(in_nmi());
WARN_ON_ONCE(in_hardirq());
WARN_ON_ONCE(local_paca->irq_happened & PACA_IRQ_REPLAYING);
}
again:
/* /*
* After the stb, interrupts are unmasked and there are no interrupts * After the stb, interrupts are unmasked and there are no interrupts
* pending replay. The restart sequence makes this atomic with * pending replay. The restart sequence makes this atomic with
...@@ -248,6 +246,12 @@ notrace void arch_local_irq_restore(unsigned long mask) ...@@ -248,6 +246,12 @@ notrace void arch_local_irq_restore(unsigned long mask)
if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG)) if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG))
WARN_ON_ONCE(!(mfmsr() & MSR_EE)); WARN_ON_ONCE(!(mfmsr() & MSR_EE));
/*
* If we came here from the replay below, we might have a preempt
* pending (due to preempt_enable_no_resched()). Have to check now.
*/
preempt_check_resched();
return; return;
happened: happened:
...@@ -261,6 +265,7 @@ notrace void arch_local_irq_restore(unsigned long mask) ...@@ -261,6 +265,7 @@ notrace void arch_local_irq_restore(unsigned long mask)
irq_soft_mask_set(IRQS_ENABLED); irq_soft_mask_set(IRQS_ENABLED);
local_paca->irq_happened = 0; local_paca->irq_happened = 0;
__hard_irq_enable(); __hard_irq_enable();
preempt_check_resched();
return; return;
} }
...@@ -296,12 +301,38 @@ notrace void arch_local_irq_restore(unsigned long mask) ...@@ -296,12 +301,38 @@ notrace void arch_local_irq_restore(unsigned long mask)
irq_soft_mask_set(IRQS_ALL_DISABLED); irq_soft_mask_set(IRQS_ALL_DISABLED);
trace_hardirqs_off(); trace_hardirqs_off();
/*
* Now enter interrupt context. The interrupt handlers themselves
* also call irq_enter/exit (which is okay, they can nest). But call
* it here now to hold off softirqs until the below irq_exit(). If
* we allowed replayed handlers to run softirqs, that enables irqs,
* which must replay interrupts, which recurses in here and makes
* things more complicated. The recursion is limited to 2, and it can
* be made to work, but it's complicated.
*
* local_bh_disable can not be used here because interrupts taken in
* idle are not in the right context (RCU, tick, etc) to run softirqs
* so irq_enter must be called.
*/
irq_enter();
replay_soft_interrupts_irqrestore(); replay_soft_interrupts_irqrestore();
irq_exit();
if (unlikely(local_paca->irq_happened != PACA_IRQ_HARD_DIS)) {
/*
* The softirq processing in irq_exit() may enable interrupts
* temporarily, which can result in MSR[EE] being enabled and
* more irqs becoming pending. Go around again if that happens.
*/
trace_hardirqs_on();
preempt_enable_no_resched();
goto again;
}
trace_hardirqs_on(); trace_hardirqs_on();
irq_soft_mask_set(IRQS_ENABLED); irq_soft_mask_set(IRQS_ENABLED);
if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG))
WARN_ON(local_paca->irq_happened != PACA_IRQ_HARD_DIS);
local_paca->irq_happened = 0; local_paca->irq_happened = 0;
__hard_irq_enable(); __hard_irq_enable();
preempt_enable(); preempt_enable();
......
...@@ -131,6 +131,13 @@ void save_mce_event(struct pt_regs *regs, long handled, ...@@ -131,6 +131,13 @@ void save_mce_event(struct pt_regs *regs, long handled,
if (mce->error_type == MCE_ERROR_TYPE_UE) if (mce->error_type == MCE_ERROR_TYPE_UE)
mce->u.ue_error.ignore_event = mce_err->ignore_event; mce->u.ue_error.ignore_event = mce_err->ignore_event;
/*
* Raise irq work, So that we don't miss to log the error for
* unrecoverable errors.
*/
if (mce->disposition == MCE_DISPOSITION_NOT_RECOVERED)
mce_irq_work_queue();
if (!addr) if (!addr)
return; return;
...@@ -233,9 +240,6 @@ static void machine_check_ue_event(struct machine_check_event *evt) ...@@ -233,9 +240,6 @@ static void machine_check_ue_event(struct machine_check_event *evt)
} }
memcpy(&local_paca->mce_info->mce_ue_event_queue[index], memcpy(&local_paca->mce_info->mce_ue_event_queue[index],
evt, sizeof(*evt)); evt, sizeof(*evt));
/* Queue work to process this event later. */
mce_irq_work_queue();
} }
/* /*
......
...@@ -502,9 +502,10 @@ static unsigned long stub_for_addr(const Elf64_Shdr *sechdrs, ...@@ -502,9 +502,10 @@ static unsigned long stub_for_addr(const Elf64_Shdr *sechdrs,
static int restore_r2(const char *name, u32 *instruction, struct module *me) static int restore_r2(const char *name, u32 *instruction, struct module *me)
{ {
u32 *prev_insn = instruction - 1; u32 *prev_insn = instruction - 1;
u32 insn_val = *instruction;
if (is_mprofile_ftrace_call(name)) if (is_mprofile_ftrace_call(name))
return 1; return 0;
/* /*
* Make sure the branch isn't a sibling call. Sibling calls aren't * Make sure the branch isn't a sibling call. Sibling calls aren't
...@@ -512,19 +513,25 @@ static int restore_r2(const char *name, u32 *instruction, struct module *me) ...@@ -512,19 +513,25 @@ static int restore_r2(const char *name, u32 *instruction, struct module *me)
* restore afterwards. * restore afterwards.
*/ */
if (!instr_is_relative_link_branch(ppc_inst(*prev_insn))) if (!instr_is_relative_link_branch(ppc_inst(*prev_insn)))
return 1; return 0;
if (*instruction != PPC_RAW_NOP()) { /*
pr_err("%s: Expected nop after call, got %08x at %pS\n", * For livepatch, the restore r2 instruction might have already been
me->name, *instruction, instruction); * written previously, if the referenced symbol is in a previously
* unloaded module which is now being loaded again. In that case, skip
* the warning and the instruction write.
*/
if (insn_val == PPC_INST_LD_TOC)
return 0; return 0;
if (insn_val != PPC_RAW_NOP()) {
pr_err("%s: Expected nop after call, got %08x at %pS\n",
me->name, insn_val, instruction);
return -ENOEXEC;
} }
/* ld r2,R2_STACK_OFFSET(r1) */ /* ld r2,R2_STACK_OFFSET(r1) */
if (patch_instruction(instruction, ppc_inst(PPC_INST_LD_TOC))) return patch_instruction(instruction, ppc_inst(PPC_INST_LD_TOC));
return 0;
return 1;
} }
int apply_relocate_add(Elf64_Shdr *sechdrs, int apply_relocate_add(Elf64_Shdr *sechdrs,
...@@ -648,8 +655,8 @@ int apply_relocate_add(Elf64_Shdr *sechdrs, ...@@ -648,8 +655,8 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
strtab + sym->st_name); strtab + sym->st_name);
if (!value) if (!value)
return -ENOENT; return -ENOENT;
if (!restore_r2(strtab + sym->st_name, if (restore_r2(strtab + sym->st_name,
(u32 *)location + 1, me)) (u32 *)location + 1, me))
return -ENOEXEC; return -ENOEXEC;
} else } else
value += local_entry_offset(sym); value += local_entry_offset(sym);
......
...@@ -62,7 +62,7 @@ fixup_cpc710_pci64(struct pci_dev* dev) ...@@ -62,7 +62,7 @@ fixup_cpc710_pci64(struct pci_dev* dev)
} }
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CPC710_PCI64, fixup_cpc710_pci64); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CPC710_PCI64, fixup_cpc710_pci64);
#if defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_CHRP) #ifdef CONFIG_PPC_PCI_OF_BUS_MAP
static u8* pci_to_OF_bus_map; static u8* pci_to_OF_bus_map;
static int pci_bus_count; static int pci_bus_count;
...@@ -152,6 +152,7 @@ pcibios_make_OF_bus_map(void) ...@@ -152,6 +152,7 @@ pcibios_make_OF_bus_map(void)
} }
#endif #endif
} }
#endif // CONFIG_PPC_PCI_OF_BUS_MAP
#ifdef CONFIG_PPC_PMAC #ifdef CONFIG_PPC_PMAC
...@@ -160,7 +161,9 @@ pcibios_make_OF_bus_map(void) ...@@ -160,7 +161,9 @@ pcibios_make_OF_bus_map(void)
*/ */
int pci_device_from_OF_node(struct device_node *node, u8 *bus, u8 *devfn) int pci_device_from_OF_node(struct device_node *node, u8 *bus, u8 *devfn)
{ {
#ifdef CONFIG_PPC_PCI_OF_BUS_MAP
struct pci_dev *dev = NULL; struct pci_dev *dev = NULL;
#endif
const __be32 *reg; const __be32 *reg;
int size; int size;
...@@ -175,6 +178,9 @@ int pci_device_from_OF_node(struct device_node *node, u8 *bus, u8 *devfn) ...@@ -175,6 +178,9 @@ int pci_device_from_OF_node(struct device_node *node, u8 *bus, u8 *devfn)
*bus = (be32_to_cpup(&reg[0]) >> 16) & 0xff; *bus = (be32_to_cpup(&reg[0]) >> 16) & 0xff;
*devfn = (be32_to_cpup(&reg[0]) >> 8) & 0xff; *devfn = (be32_to_cpup(&reg[0]) >> 8) & 0xff;
#ifndef CONFIG_PPC_PCI_OF_BUS_MAP
return 0;
#else
/* Ok, here we need some tweak. If we have already renumbered /* Ok, here we need some tweak. If we have already renumbered
* all busses, we can't rely on the OF bus number any more. * all busses, we can't rely on the OF bus number any more.
* the pci_to_OF_bus_map is not enough as several PCI busses * the pci_to_OF_bus_map is not enough as several PCI busses
...@@ -192,11 +198,12 @@ int pci_device_from_OF_node(struct device_node *node, u8 *bus, u8 *devfn) ...@@ -192,11 +198,12 @@ int pci_device_from_OF_node(struct device_node *node, u8 *bus, u8 *devfn)
} }
return -ENODEV; return -ENODEV;
#endif // CONFIG_PPC_PCI_OF_BUS_MAP
} }
EXPORT_SYMBOL(pci_device_from_OF_node); EXPORT_SYMBOL(pci_device_from_OF_node);
#endif #endif
#ifdef CONFIG_PPC_CHRP #ifdef CONFIG_PPC_PCI_OF_BUS_MAP
/* We create the "pci-OF-bus-map" property now so it appears in the /* We create the "pci-OF-bus-map" property now so it appears in the
* /proc device tree * /proc device tree
*/ */
...@@ -221,9 +228,7 @@ pci_create_OF_bus_map(void) ...@@ -221,9 +228,7 @@ pci_create_OF_bus_map(void)
of_node_put(dn); of_node_put(dn);
} }
} }
#endif #endif // CONFIG_PPC_PCI_OF_BUS_MAP
#endif /* defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_CHRP) */
void pcibios_setup_phb_io_space(struct pci_controller *hose) void pcibios_setup_phb_io_space(struct pci_controller *hose)
{ {
...@@ -273,6 +278,7 @@ static int __init pcibios_init(void) ...@@ -273,6 +278,7 @@ static int __init pcibios_init(void)
} }
#if defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_CHRP) #if defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_CHRP)
#ifdef CONFIG_PPC_PCI_OF_BUS_MAP
pci_bus_count = next_busno; pci_bus_count = next_busno;
/* OpenFirmware based machines need a map of OF bus /* OpenFirmware based machines need a map of OF bus
...@@ -281,6 +287,7 @@ static int __init pcibios_init(void) ...@@ -281,6 +287,7 @@ static int __init pcibios_init(void)
*/ */
if (pci_assign_all_buses) if (pci_assign_all_buses)
pcibios_make_OF_bus_map(); pcibios_make_OF_bus_map();
#endif
#endif #endif
/* Call common code to handle resource allocation */ /* Call common code to handle resource allocation */
......
...@@ -1405,8 +1405,7 @@ static void show_instructions(struct pt_regs *regs) ...@@ -1405,8 +1405,7 @@ static void show_instructions(struct pt_regs *regs)
for (i = 0; i < NR_INSN_TO_PRINT; i++) { for (i = 0; i < NR_INSN_TO_PRINT; i++) {
int instr; int instr;
if (!__kernel_text_address(pc) || if (get_kernel_nofault(instr, (const void *)pc)) {
get_kernel_nofault(instr, (const void *)pc)) {
pr_cont("XXXXXXXX "); pr_cont("XXXXXXXX ");
} else { } else {
if (nip == pc) if (nip == pc)
...@@ -2118,6 +2117,9 @@ static inline int valid_irq_stack(unsigned long sp, struct task_struct *p, ...@@ -2118,6 +2117,9 @@ static inline int valid_irq_stack(unsigned long sp, struct task_struct *p,
unsigned long stack_page; unsigned long stack_page;
unsigned long cpu = task_cpu(p); unsigned long cpu = task_cpu(p);
if (!hardirq_ctx[cpu] || !softirq_ctx[cpu])
return 0;
stack_page = (unsigned long)hardirq_ctx[cpu]; stack_page = (unsigned long)hardirq_ctx[cpu];
if (sp >= stack_page && sp <= stack_page + THREAD_SIZE - nbytes) if (sp >= stack_page && sp <= stack_page + THREAD_SIZE - nbytes)
return 1; return 1;
...@@ -2139,6 +2141,14 @@ static inline int valid_emergency_stack(unsigned long sp, struct task_struct *p, ...@@ -2139,6 +2141,14 @@ static inline int valid_emergency_stack(unsigned long sp, struct task_struct *p,
if (!paca_ptrs) if (!paca_ptrs)
return 0; return 0;
if (!paca_ptrs[cpu]->emergency_sp)
return 0;
# ifdef CONFIG_PPC_BOOK3S_64
if (!paca_ptrs[cpu]->nmi_emergency_sp || !paca_ptrs[cpu]->mc_emergency_sp)
return 0;
#endif
stack_page = (unsigned long)paca_ptrs[cpu]->emergency_sp - THREAD_SIZE; stack_page = (unsigned long)paca_ptrs[cpu]->emergency_sp - THREAD_SIZE;
if (sp >= stack_page && sp <= stack_page + THREAD_SIZE - nbytes) if (sp >= stack_page && sp <= stack_page + THREAD_SIZE - nbytes)
return 1; return 1;
......
...@@ -56,6 +56,7 @@ ...@@ -56,6 +56,7 @@
#include <asm/drmem.h> #include <asm/drmem.h>
#include <asm/ultravisor.h> #include <asm/ultravisor.h>
#include <asm/prom.h> #include <asm/prom.h>
#include <asm/plpks.h>
#include <mm/mmu_decl.h> #include <mm/mmu_decl.h>
...@@ -370,8 +371,8 @@ static int __init early_init_dt_scan_cpus(unsigned long node, ...@@ -370,8 +371,8 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
be32_to_cpu(intserv[found_thread])); be32_to_cpu(intserv[found_thread]));
boot_cpuid = found; boot_cpuid = found;
// Pass the boot CPU's hard CPU id back to our caller if (IS_ENABLED(CONFIG_PPC64))
*((u32 *)data) = be32_to_cpu(intserv[found_thread]); boot_cpu_hwid = be32_to_cpu(intserv[found_thread]);
/* /*
* PAPR defines "logical" PVR values for cpus that * PAPR defines "logical" PVR values for cpus that
...@@ -755,7 +756,6 @@ static inline void save_fscr_to_task(void) {} ...@@ -755,7 +756,6 @@ static inline void save_fscr_to_task(void) {}
void __init early_init_devtree(void *params) void __init early_init_devtree(void *params)
{ {
u32 boot_cpu_hwid;
phys_addr_t limit; phys_addr_t limit;
DBG(" -> early_init_devtree(%px)\n", params); DBG(" -> early_init_devtree(%px)\n", params);
...@@ -851,7 +851,7 @@ void __init early_init_devtree(void *params) ...@@ -851,7 +851,7 @@ void __init early_init_devtree(void *params)
/* Retrieve CPU related informations from the flat tree /* Retrieve CPU related informations from the flat tree
* (altivec support, boot CPU ID, ...) * (altivec support, boot CPU ID, ...)
*/ */
of_scan_flat_dt(early_init_dt_scan_cpus, &boot_cpu_hwid); of_scan_flat_dt(early_init_dt_scan_cpus, NULL);
if (boot_cpuid < 0) { if (boot_cpuid < 0) {
printk("Failed to identify boot CPU !\n"); printk("Failed to identify boot CPU !\n");
BUG(); BUG();
...@@ -868,11 +868,6 @@ void __init early_init_devtree(void *params) ...@@ -868,11 +868,6 @@ void __init early_init_devtree(void *params)
mmu_early_init_devtree(); mmu_early_init_devtree();
// NB. paca is not installed until later in early_setup()
allocate_paca_ptrs();
allocate_paca(boot_cpuid);
set_hard_smp_processor_id(boot_cpuid, boot_cpu_hwid);
#ifdef CONFIG_PPC_POWERNV #ifdef CONFIG_PPC_POWERNV
/* Scan and build the list of machine check recoverable ranges */ /* Scan and build the list of machine check recoverable ranges */
of_scan_flat_dt(early_init_dt_scan_recoverable_ranges, NULL); of_scan_flat_dt(early_init_dt_scan_recoverable_ranges, NULL);
...@@ -893,6 +888,9 @@ void __init early_init_devtree(void *params) ...@@ -893,6 +888,9 @@ void __init early_init_devtree(void *params)
powerpc_firmware_features |= FW_FEATURE_PS3_POSSIBLE; powerpc_firmware_features |= FW_FEATURE_PS3_POSSIBLE;
#endif #endif
/* If kexec left a PLPKS password in the DT, get it and clear it */
plpks_early_init_devtree();
tm_init(); tm_init();
DBG(" <- early_init_devtree()\n"); DBG(" <- early_init_devtree()\n");
......
...@@ -287,9 +287,9 @@ static ssize_t ppc_rtas_poweron_write(struct file *file, ...@@ -287,9 +287,9 @@ static ssize_t ppc_rtas_poweron_write(struct file *file,
rtc_time64_to_tm(nowtime, &tm); rtc_time64_to_tm(nowtime, &tm);
error = rtas_call(rtas_token("set-time-for-power-on"), 7, 1, NULL, error = rtas_call(rtas_function_token(RTAS_FN_SET_TIME_FOR_POWER_ON), 7, 1, NULL,
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec, 0 /* nano */); tm.tm_hour, tm.tm_min, tm.tm_sec, 0 /* nano */);
if (error) if (error)
printk(KERN_WARNING "error: setting poweron time returned: %s\n", printk(KERN_WARNING "error: setting poweron time returned: %s\n",
ppc_rtas_process_error(error)); ppc_rtas_process_error(error));
...@@ -350,9 +350,9 @@ static ssize_t ppc_rtas_clock_write(struct file *file, ...@@ -350,9 +350,9 @@ static ssize_t ppc_rtas_clock_write(struct file *file,
return error; return error;
rtc_time64_to_tm(nowtime, &tm); rtc_time64_to_tm(nowtime, &tm);
error = rtas_call(rtas_token("set-time-of-day"), 7, 1, NULL, error = rtas_call(rtas_function_token(RTAS_FN_SET_TIME_OF_DAY), 7, 1, NULL,
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec, 0); tm.tm_hour, tm.tm_min, tm.tm_sec, 0);
if (error) if (error)
printk(KERN_WARNING "error: setting the clock returned: %s\n", printk(KERN_WARNING "error: setting the clock returned: %s\n",
ppc_rtas_process_error(error)); ppc_rtas_process_error(error));
...@@ -362,7 +362,7 @@ static ssize_t ppc_rtas_clock_write(struct file *file, ...@@ -362,7 +362,7 @@ static ssize_t ppc_rtas_clock_write(struct file *file,
static int ppc_rtas_clock_show(struct seq_file *m, void *v) static int ppc_rtas_clock_show(struct seq_file *m, void *v)
{ {
int ret[8]; int ret[8];
int error = rtas_call(rtas_token("get-time-of-day"), 0, 8, ret); int error = rtas_call(rtas_function_token(RTAS_FN_GET_TIME_OF_DAY), 0, 8, ret);
if (error) { if (error) {
printk(KERN_WARNING "error: reading the clock returned: %s\n", printk(KERN_WARNING "error: reading the clock returned: %s\n",
...@@ -385,7 +385,7 @@ static int ppc_rtas_sensors_show(struct seq_file *m, void *v) ...@@ -385,7 +385,7 @@ static int ppc_rtas_sensors_show(struct seq_file *m, void *v)
{ {
int i,j; int i,j;
int state, error; int state, error;
int get_sensor_state = rtas_token("get-sensor-state"); int get_sensor_state = rtas_function_token(RTAS_FN_GET_SENSOR_STATE);
seq_printf(m, "RTAS (RunTime Abstraction Services) Sensor Information\n"); seq_printf(m, "RTAS (RunTime Abstraction Services) Sensor Information\n");
seq_printf(m, "Sensor\t\tValue\t\tCondition\tLocation\n"); seq_printf(m, "Sensor\t\tValue\t\tCondition\tLocation\n");
...@@ -708,8 +708,8 @@ static ssize_t ppc_rtas_tone_freq_write(struct file *file, ...@@ -708,8 +708,8 @@ static ssize_t ppc_rtas_tone_freq_write(struct file *file,
return error; return error;
rtas_tone_frequency = freq; /* save it for later */ rtas_tone_frequency = freq; /* save it for later */
error = rtas_call(rtas_token("set-indicator"), 3, 1, NULL, error = rtas_call(rtas_function_token(RTAS_FN_SET_INDICATOR), 3, 1, NULL,
TONE_FREQUENCY, 0, freq); TONE_FREQUENCY, 0, freq);
if (error) if (error)
printk(KERN_WARNING "error: setting tone frequency returned: %s\n", printk(KERN_WARNING "error: setting tone frequency returned: %s\n",
ppc_rtas_process_error(error)); ppc_rtas_process_error(error));
...@@ -736,8 +736,8 @@ static ssize_t ppc_rtas_tone_volume_write(struct file *file, ...@@ -736,8 +736,8 @@ static ssize_t ppc_rtas_tone_volume_write(struct file *file,
volume = 100; volume = 100;
rtas_tone_volume = volume; /* save it for later */ rtas_tone_volume = volume; /* save it for later */
error = rtas_call(rtas_token("set-indicator"), 3, 1, NULL, error = rtas_call(rtas_function_token(RTAS_FN_SET_INDICATOR), 3, 1, NULL,
TONE_VOLUME, 0, volume); TONE_VOLUME, 0, volume);
if (error) if (error)
printk(KERN_WARNING "error: setting tone volume returned: %s\n", printk(KERN_WARNING "error: setting tone volume returned: %s\n",
ppc_rtas_process_error(error)); ppc_rtas_process_error(error));
......
...@@ -21,7 +21,7 @@ time64_t __init rtas_get_boot_time(void) ...@@ -21,7 +21,7 @@ time64_t __init rtas_get_boot_time(void)
max_wait_tb = get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT; max_wait_tb = get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT;
do { do {
error = rtas_call(rtas_token("get-time-of-day"), 0, 8, ret); error = rtas_call(rtas_function_token(RTAS_FN_GET_TIME_OF_DAY), 0, 8, ret);
wait_time = rtas_busy_delay_time(error); wait_time = rtas_busy_delay_time(error);
if (wait_time) { if (wait_time) {
...@@ -53,7 +53,7 @@ void rtas_get_rtc_time(struct rtc_time *rtc_tm) ...@@ -53,7 +53,7 @@ void rtas_get_rtc_time(struct rtc_time *rtc_tm)
max_wait_tb = get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT; max_wait_tb = get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT;
do { do {
error = rtas_call(rtas_token("get-time-of-day"), 0, 8, ret); error = rtas_call(rtas_function_token(RTAS_FN_GET_TIME_OF_DAY), 0, 8, ret);
wait_time = rtas_busy_delay_time(error); wait_time = rtas_busy_delay_time(error);
if (wait_time) { if (wait_time) {
...@@ -90,7 +90,7 @@ int rtas_set_rtc_time(struct rtc_time *tm) ...@@ -90,7 +90,7 @@ int rtas_set_rtc_time(struct rtc_time *tm)
max_wait_tb = get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT; max_wait_tb = get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT;
do { do {
error = rtas_call(rtas_token("set-time-of-day"), 7, 1, NULL, error = rtas_call(rtas_function_token(RTAS_FN_SET_TIME_OF_DAY), 7, 1, NULL,
tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_year + 1900, tm->tm_mon + 1,
tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_mday, tm->tm_hour, tm->tm_min,
tm->tm_sec, 0); tm->tm_sec, 0);
......
This diff is collapsed.
...@@ -376,7 +376,7 @@ static void manage_flash(struct rtas_manage_flash_t *args_buf, unsigned int op) ...@@ -376,7 +376,7 @@ static void manage_flash(struct rtas_manage_flash_t *args_buf, unsigned int op)
s32 rc; s32 rc;
do { do {
rc = rtas_call(rtas_token("ibm,manage-flash-image"), 1, 1, rc = rtas_call(rtas_function_token(RTAS_FN_IBM_MANAGE_FLASH_IMAGE), 1, 1,
NULL, op); NULL, op);
} while (rtas_busy_delay(rc)); } while (rtas_busy_delay(rc));
...@@ -444,7 +444,7 @@ static ssize_t manage_flash_write(struct file *file, const char __user *buf, ...@@ -444,7 +444,7 @@ static ssize_t manage_flash_write(struct file *file, const char __user *buf,
*/ */
static void validate_flash(struct rtas_validate_flash_t *args_buf) static void validate_flash(struct rtas_validate_flash_t *args_buf)
{ {
int token = rtas_token("ibm,validate-flash-image"); int token = rtas_function_token(RTAS_FN_IBM_VALIDATE_FLASH_IMAGE);
int update_results; int update_results;
s32 rc; s32 rc;
...@@ -570,7 +570,7 @@ static void rtas_flash_firmware(int reboot_type) ...@@ -570,7 +570,7 @@ static void rtas_flash_firmware(int reboot_type)
return; return;
} }
update_token = rtas_token("ibm,update-flash-64-and-reboot"); update_token = rtas_function_token(RTAS_FN_IBM_UPDATE_FLASH_64_AND_REBOOT);
if (update_token == RTAS_UNKNOWN_SERVICE) { if (update_token == RTAS_UNKNOWN_SERVICE) {
printk(KERN_ALERT "FLASH: ibm,update-flash-64-and-reboot " printk(KERN_ALERT "FLASH: ibm,update-flash-64-and-reboot "
"is not available -- not a service partition?\n"); "is not available -- not a service partition?\n");
...@@ -653,7 +653,7 @@ static void rtas_flash_firmware(int reboot_type) ...@@ -653,7 +653,7 @@ static void rtas_flash_firmware(int reboot_type)
*/ */
struct rtas_flash_file { struct rtas_flash_file {
const char *filename; const char *filename;
const char *rtas_call_name; const rtas_fn_handle_t handle;
int *status; int *status;
const struct proc_ops ops; const struct proc_ops ops;
}; };
...@@ -661,7 +661,7 @@ struct rtas_flash_file { ...@@ -661,7 +661,7 @@ struct rtas_flash_file {
static const struct rtas_flash_file rtas_flash_files[] = { static const struct rtas_flash_file rtas_flash_files[] = {
{ {
.filename = "powerpc/rtas/" FIRMWARE_FLASH_NAME, .filename = "powerpc/rtas/" FIRMWARE_FLASH_NAME,
.rtas_call_name = "ibm,update-flash-64-and-reboot", .handle = RTAS_FN_IBM_UPDATE_FLASH_64_AND_REBOOT,
.status = &rtas_update_flash_data.status, .status = &rtas_update_flash_data.status,
.ops.proc_read = rtas_flash_read_msg, .ops.proc_read = rtas_flash_read_msg,
.ops.proc_write = rtas_flash_write, .ops.proc_write = rtas_flash_write,
...@@ -670,7 +670,7 @@ static const struct rtas_flash_file rtas_flash_files[] = { ...@@ -670,7 +670,7 @@ static const struct rtas_flash_file rtas_flash_files[] = {
}, },
{ {
.filename = "powerpc/rtas/" FIRMWARE_UPDATE_NAME, .filename = "powerpc/rtas/" FIRMWARE_UPDATE_NAME,
.rtas_call_name = "ibm,update-flash-64-and-reboot", .handle = RTAS_FN_IBM_UPDATE_FLASH_64_AND_REBOOT,
.status = &rtas_update_flash_data.status, .status = &rtas_update_flash_data.status,
.ops.proc_read = rtas_flash_read_num, .ops.proc_read = rtas_flash_read_num,
.ops.proc_write = rtas_flash_write, .ops.proc_write = rtas_flash_write,
...@@ -679,7 +679,7 @@ static const struct rtas_flash_file rtas_flash_files[] = { ...@@ -679,7 +679,7 @@ static const struct rtas_flash_file rtas_flash_files[] = {
}, },
{ {
.filename = "powerpc/rtas/" VALIDATE_FLASH_NAME, .filename = "powerpc/rtas/" VALIDATE_FLASH_NAME,
.rtas_call_name = "ibm,validate-flash-image", .handle = RTAS_FN_IBM_VALIDATE_FLASH_IMAGE,
.status = &rtas_validate_flash_data.status, .status = &rtas_validate_flash_data.status,
.ops.proc_read = validate_flash_read, .ops.proc_read = validate_flash_read,
.ops.proc_write = validate_flash_write, .ops.proc_write = validate_flash_write,
...@@ -688,7 +688,7 @@ static const struct rtas_flash_file rtas_flash_files[] = { ...@@ -688,7 +688,7 @@ static const struct rtas_flash_file rtas_flash_files[] = {
}, },
{ {
.filename = "powerpc/rtas/" MANAGE_FLASH_NAME, .filename = "powerpc/rtas/" MANAGE_FLASH_NAME,
.rtas_call_name = "ibm,manage-flash-image", .handle = RTAS_FN_IBM_MANAGE_FLASH_IMAGE,
.status = &rtas_manage_flash_data.status, .status = &rtas_manage_flash_data.status,
.ops.proc_read = manage_flash_read, .ops.proc_read = manage_flash_read,
.ops.proc_write = manage_flash_write, .ops.proc_write = manage_flash_write,
...@@ -700,8 +700,7 @@ static int __init rtas_flash_init(void) ...@@ -700,8 +700,7 @@ static int __init rtas_flash_init(void)
{ {
int i; int i;
if (rtas_token("ibm,update-flash-64-and-reboot") == if (rtas_function_token(RTAS_FN_IBM_UPDATE_FLASH_64_AND_REBOOT) == RTAS_UNKNOWN_SERVICE) {
RTAS_UNKNOWN_SERVICE) {
pr_info("rtas_flash: no firmware flash support\n"); pr_info("rtas_flash: no firmware flash support\n");
return -EINVAL; return -EINVAL;
} }
...@@ -730,7 +729,7 @@ static int __init rtas_flash_init(void) ...@@ -730,7 +729,7 @@ static int __init rtas_flash_init(void)
* This code assumes that the status int is the first member of the * This code assumes that the status int is the first member of the
* struct * struct
*/ */
token = rtas_token(f->rtas_call_name); token = rtas_function_token(f->handle);
if (token == RTAS_UNKNOWN_SERVICE) if (token == RTAS_UNKNOWN_SERVICE)
*f->status = FLASH_AUTH; *f->status = FLASH_AUTH;
else else
......
...@@ -191,10 +191,10 @@ static void python_countermeasures(struct device_node *dev) ...@@ -191,10 +191,10 @@ static void python_countermeasures(struct device_node *dev)
void __init init_pci_config_tokens(void) void __init init_pci_config_tokens(void)
{ {
read_pci_config = rtas_token("read-pci-config"); read_pci_config = rtas_function_token(RTAS_FN_READ_PCI_CONFIG);
write_pci_config = rtas_token("write-pci-config"); write_pci_config = rtas_function_token(RTAS_FN_WRITE_PCI_CONFIG);
ibm_read_pci_config = rtas_token("ibm,read-pci-config"); ibm_read_pci_config = rtas_function_token(RTAS_FN_IBM_READ_PCI_CONFIG);
ibm_write_pci_config = rtas_token("ibm,write-pci-config"); ibm_write_pci_config = rtas_function_token(RTAS_FN_IBM_WRITE_PCI_CONFIG);
} }
unsigned long get_phb_buid(struct device_node *phb) unsigned long get_phb_buid(struct device_node *phb)
......
...@@ -506,7 +506,7 @@ static int __init rtas_event_scan_init(void) ...@@ -506,7 +506,7 @@ static int __init rtas_event_scan_init(void)
return 0; return 0;
/* No RTAS */ /* No RTAS */
event_scan = rtas_token("event-scan"); event_scan = rtas_function_token(RTAS_FN_EVENT_SCAN);
if (event_scan == RTAS_UNKNOWN_SERVICE) { if (event_scan == RTAS_UNKNOWN_SERVICE) {
printk(KERN_INFO "rtasd: No event-scan on system\n"); printk(KERN_INFO "rtasd: No event-scan on system\n");
return -ENODEV; return -ENODEV;
......
...@@ -8,10 +8,16 @@ ...@@ -8,10 +8,16 @@
#include <linux/cache.h> #include <linux/cache.h>
#include <asm/secvar.h> #include <asm/secvar.h>
#include <asm/bug.h>
const struct secvar_operations *secvar_ops __ro_after_init; const struct secvar_operations *secvar_ops __ro_after_init = NULL;
void set_secvar_ops(const struct secvar_operations *ops) int set_secvar_ops(const struct secvar_operations *ops)
{ {
if (WARN_ON_ONCE(secvar_ops))
return -EBUSY;
secvar_ops = ops; secvar_ops = ops;
return 0;
} }
...@@ -21,56 +21,48 @@ static struct kset *secvar_kset; ...@@ -21,56 +21,48 @@ static struct kset *secvar_kset;
static ssize_t format_show(struct kobject *kobj, struct kobj_attribute *attr, static ssize_t format_show(struct kobject *kobj, struct kobj_attribute *attr,
char *buf) char *buf)
{ {
ssize_t rc = 0; char tmp[32];
struct device_node *node; ssize_t len = secvar_ops->format(tmp, sizeof(tmp));
const char *format;
node = of_find_compatible_node(NULL, NULL, "ibm,secvar-backend");
if (!of_device_is_available(node)) {
rc = -ENODEV;
goto out;
}
rc = of_property_read_string(node, "format", &format);
if (rc)
goto out;
rc = sprintf(buf, "%s\n", format);
out: if (len > 0)
of_node_put(node); return sysfs_emit(buf, "%s\n", tmp);
else if (len < 0)
pr_err("Error %zd reading format string\n", len);
else
pr_err("Got empty format string from backend\n");
return rc; return -EIO;
} }
static ssize_t size_show(struct kobject *kobj, struct kobj_attribute *attr, static ssize_t size_show(struct kobject *kobj, struct kobj_attribute *attr,
char *buf) char *buf)
{ {
uint64_t dsize; u64 dsize;
int rc; int rc;
rc = secvar_ops->get(kobj->name, strlen(kobj->name) + 1, NULL, &dsize); rc = secvar_ops->get(kobj->name, strlen(kobj->name) + 1, NULL, &dsize);
if (rc) { if (rc) {
pr_err("Error retrieving %s variable size %d\n", kobj->name, if (rc != -ENOENT)
rc); pr_err("Error retrieving %s variable size %d\n", kobj->name, rc);
return rc; return rc;
} }
return sprintf(buf, "%llu\n", dsize); return sysfs_emit(buf, "%llu\n", dsize);
} }
static ssize_t data_read(struct file *filep, struct kobject *kobj, static ssize_t data_read(struct file *filep, struct kobject *kobj,
struct bin_attribute *attr, char *buf, loff_t off, struct bin_attribute *attr, char *buf, loff_t off,
size_t count) size_t count)
{ {
uint64_t dsize;
char *data; char *data;
u64 dsize;
int rc; int rc;
rc = secvar_ops->get(kobj->name, strlen(kobj->name) + 1, NULL, &dsize); rc = secvar_ops->get(kobj->name, strlen(kobj->name) + 1, NULL, &dsize);
if (rc) { if (rc) {
pr_err("Error getting %s variable size %d\n", kobj->name, rc); if (rc != -ENOENT)
pr_err("Error getting %s variable size %d\n", kobj->name, rc);
return rc; return rc;
} }
pr_debug("dsize is %llu\n", dsize); pr_debug("dsize is %llu\n", dsize);
...@@ -141,34 +133,58 @@ static struct kobj_type secvar_ktype = { ...@@ -141,34 +133,58 @@ static struct kobj_type secvar_ktype = {
static int update_kobj_size(void) static int update_kobj_size(void)
{ {
struct device_node *node;
u64 varsize; u64 varsize;
int rc = 0; int rc = secvar_ops->max_size(&varsize);
node = of_find_compatible_node(NULL, NULL, "ibm,secvar-backend");
if (!of_device_is_available(node)) {
rc = -ENODEV;
goto out;
}
rc = of_property_read_u64(node, "max-var-size", &varsize);
if (rc) if (rc)
goto out; return rc;
data_attr.size = varsize; data_attr.size = varsize;
update_attr.size = varsize; update_attr.size = varsize;
out: return 0;
of_node_put(node); }
return rc; static int secvar_sysfs_config(struct kobject *kobj)
{
struct attribute_group config_group = {
.name = "config",
.attrs = (struct attribute **)secvar_ops->config_attrs,
};
if (secvar_ops->config_attrs)
return sysfs_create_group(kobj, &config_group);
return 0;
}
static int add_var(const char *name)
{
struct kobject *kobj;
int rc;
kobj = kzalloc(sizeof(*kobj), GFP_KERNEL);
if (!kobj)
return -ENOMEM;
kobject_init(kobj, &secvar_ktype);
rc = kobject_add(kobj, &secvar_kset->kobj, "%s", name);
if (rc) {
pr_warn("kobject_add error %d for attribute: %s\n", rc,
name);
kobject_put(kobj);
return rc;
}
kobject_uevent(kobj, KOBJ_ADD);
return 0;
} }
static int secvar_sysfs_load(void) static int secvar_sysfs_load(void)
{ {
u64 namesize = 0;
char *name; char *name;
uint64_t namesize = 0;
struct kobject *kobj;
int rc; int rc;
name = kzalloc(NAME_MAX_SIZE, GFP_KERNEL); name = kzalloc(NAME_MAX_SIZE, GFP_KERNEL);
...@@ -179,73 +195,99 @@ static int secvar_sysfs_load(void) ...@@ -179,73 +195,99 @@ static int secvar_sysfs_load(void)
rc = secvar_ops->get_next(name, &namesize, NAME_MAX_SIZE); rc = secvar_ops->get_next(name, &namesize, NAME_MAX_SIZE);
if (rc) { if (rc) {
if (rc != -ENOENT) if (rc != -ENOENT)
pr_err("error getting secvar from firmware %d\n", pr_err("error getting secvar from firmware %d\n", rc);
rc); else
break; rc = 0;
}
kobj = kzalloc(sizeof(*kobj), GFP_KERNEL);
if (!kobj) {
rc = -ENOMEM;
break; break;
} }
kobject_init(kobj, &secvar_ktype); rc = add_var(name);
rc = kobject_add(kobj, &secvar_kset->kobj, "%s", name);
if (rc) {
pr_warn("kobject_add error %d for attribute: %s\n", rc,
name);
kobject_put(kobj);
kobj = NULL;
}
if (kobj)
kobject_uevent(kobj, KOBJ_ADD);
} while (!rc); } while (!rc);
kfree(name); kfree(name);
return rc; return rc;
} }
static int secvar_sysfs_load_static(void)
{
const char * const *name_ptr = secvar_ops->var_names;
int rc;
while (*name_ptr) {
rc = add_var(*name_ptr);
if (rc)
return rc;
name_ptr++;
}
return 0;
}
static int secvar_sysfs_init(void) static int secvar_sysfs_init(void)
{ {
u64 max_size;
int rc; int rc;
if (!secvar_ops) { if (!secvar_ops) {
pr_warn("secvar: failed to retrieve secvar operations.\n"); pr_warn("Failed to retrieve secvar operations\n");
return -ENODEV; return -ENODEV;
} }
secvar_kobj = kobject_create_and_add("secvar", firmware_kobj); secvar_kobj = kobject_create_and_add("secvar", firmware_kobj);
if (!secvar_kobj) { if (!secvar_kobj) {
pr_err("secvar: Failed to create firmware kobj\n"); pr_err("Failed to create firmware kobj\n");
return -ENOMEM; return -ENOMEM;
} }
rc = sysfs_create_file(secvar_kobj, &format_attr.attr); rc = sysfs_create_file(secvar_kobj, &format_attr.attr);
if (rc) { if (rc) {
kobject_put(secvar_kobj); pr_err("Failed to create format object\n");
return -ENOMEM; rc = -ENOMEM;
goto err;
} }
secvar_kset = kset_create_and_add("vars", NULL, secvar_kobj); secvar_kset = kset_create_and_add("vars", NULL, secvar_kobj);
if (!secvar_kset) { if (!secvar_kset) {
pr_err("secvar: sysfs kobject registration failed.\n"); pr_err("sysfs kobject registration failed\n");
kobject_put(secvar_kobj); rc = -ENOMEM;
return -ENOMEM; goto err;
} }
rc = update_kobj_size(); rc = update_kobj_size();
if (rc) { if (rc) {
pr_err("Cannot read the size of the attribute\n"); pr_err("Cannot read the size of the attribute\n");
return rc; goto err;
}
rc = secvar_sysfs_config(secvar_kobj);
if (rc) {
pr_err("Failed to create config directory\n");
goto err;
} }
secvar_sysfs_load(); if (secvar_ops->get_next)
rc = secvar_sysfs_load();
else
rc = secvar_sysfs_load_static();
if (rc) {
pr_err("Failed to create variable attributes\n");
goto err;
}
// Due to sysfs limitations, we will only ever get a write buffer of
// up to 1 page in size. Print a warning if this is potentially going
// to cause problems, so that the user is aware.
secvar_ops->max_size(&max_size);
if (max_size > PAGE_SIZE)
pr_warn_ratelimited("PAGE_SIZE (%lu) is smaller than maximum object size (%llu), writes are limited to PAGE_SIZE\n",
PAGE_SIZE, max_size);
return 0; return 0;
err:
kobject_put(secvar_kobj);
return rc;
} }
late_initcall(secvar_sysfs_init); late_initcall(secvar_sysfs_init);
...@@ -87,6 +87,10 @@ EXPORT_SYMBOL(machine_id); ...@@ -87,6 +87,10 @@ EXPORT_SYMBOL(machine_id);
int boot_cpuid = -1; int boot_cpuid = -1;
EXPORT_SYMBOL_GPL(boot_cpuid); EXPORT_SYMBOL_GPL(boot_cpuid);
#ifdef CONFIG_PPC64
int boot_cpu_hwid = -1;
#endif
/* /*
* These are used in binfmt_elf.c to put aux entries on the stack * These are used in binfmt_elf.c to put aux entries on the stack
* for each elf executable being started. * for each elf executable being started.
......
...@@ -385,17 +385,21 @@ void __init early_setup(unsigned long dt_ptr) ...@@ -385,17 +385,21 @@ void __init early_setup(unsigned long dt_ptr)
/* /*
* Do early initialization using the flattened device * Do early initialization using the flattened device
* tree, such as retrieving the physical memory map or * tree, such as retrieving the physical memory map or
* calculating/retrieving the hash table size. * calculating/retrieving the hash table size, discover
* boot_cpuid and boot_cpu_hwid.
*/ */
early_init_devtree(__va(dt_ptr)); early_init_devtree(__va(dt_ptr));
/* Now we know the logical id of our boot cpu, setup the paca. */ allocate_paca_ptrs();
if (boot_cpuid != 0) { allocate_paca(boot_cpuid);
/* Poison paca_ptrs[0] again if it's not the boot cpu */ set_hard_smp_processor_id(boot_cpuid, boot_cpu_hwid);
memset(&paca_ptrs[0], 0x88, sizeof(paca_ptrs[0]));
}
fixup_boot_paca(paca_ptrs[boot_cpuid]); fixup_boot_paca(paca_ptrs[boot_cpuid]);
setup_paca(paca_ptrs[boot_cpuid]); /* install the paca into registers */ setup_paca(paca_ptrs[boot_cpuid]); /* install the paca into registers */
// smp_processor_id() now reports boot_cpuid
#ifdef CONFIG_SMP
task_thread_info(current)->cpu = boot_cpuid; // fix task_cpu(current)
#endif
/* /*
* Configure exception handlers. This include setting up trampolines * Configure exception handlers. This include setting up trampolines
......
...@@ -356,7 +356,7 @@ void vtime_flush(struct task_struct *tsk) ...@@ -356,7 +356,7 @@ void vtime_flush(struct task_struct *tsk)
} }
#endif /* CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */ #endif /* CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */
void __delay(unsigned long loops) void __no_kcsan __delay(unsigned long loops)
{ {
unsigned long start; unsigned long start;
...@@ -377,7 +377,7 @@ void __delay(unsigned long loops) ...@@ -377,7 +377,7 @@ void __delay(unsigned long loops)
} }
EXPORT_SYMBOL(__delay); EXPORT_SYMBOL(__delay);
void udelay(unsigned long usecs) void __no_kcsan udelay(unsigned long usecs)
{ {
__delay(tb_ticks_per_usec * usecs); __delay(tb_ticks_per_usec * usecs);
} }
......
...@@ -23,4 +23,5 @@ obj-$(CONFIG_PPC32) += $(obj32-y) ...@@ -23,4 +23,5 @@ obj-$(CONFIG_PPC32) += $(obj32-y)
# Disable GCOV, KCOV & sanitizers in odd or sensitive code # Disable GCOV, KCOV & sanitizers in odd or sensitive code
GCOV_PROFILE_ftrace.o := n GCOV_PROFILE_ftrace.o := n
KCOV_INSTRUMENT_ftrace.o := n KCOV_INSTRUMENT_ftrace.o := n
KCSAN_SANITIZE_ftrace.o := n
UBSAN_SANITIZE_ftrace.o := n UBSAN_SANITIZE_ftrace.o := n
...@@ -46,6 +46,7 @@ GCOV_PROFILE := n ...@@ -46,6 +46,7 @@ GCOV_PROFILE := n
KCOV_INSTRUMENT := n KCOV_INSTRUMENT := n
UBSAN_SANITIZE := n UBSAN_SANITIZE := n
KASAN_SANITIZE := n KASAN_SANITIZE := n
KCSAN_SANITIZE := n
ccflags-y := -shared -fno-common -fno-builtin -nostdlib -Wl,--hash-style=both ccflags-y := -shared -fno-common -fno-builtin -nostdlib -Wl,--hash-style=both
ccflags-$(CONFIG_LD_IS_LLD) += $(call cc-option,--ld-path=$(LD),-fuse-ld=lld) ccflags-$(CONFIG_LD_IS_LLD) += $(call cc-option,--ld-path=$(LD),-fuse-ld=lld)
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include <asm/crashdump-ppc64.h> #include <asm/crashdump-ppc64.h>
#include <asm/mmzone.h> #include <asm/mmzone.h>
#include <asm/prom.h> #include <asm/prom.h>
#include <asm/plpks.h>
struct umem_info { struct umem_info {
u64 *buf; /* data buffer for usable-memory property */ u64 *buf; /* data buffer for usable-memory property */
...@@ -689,7 +690,8 @@ static int update_usable_mem_fdt(void *fdt, struct crash_mem *usable_mem) ...@@ -689,7 +690,8 @@ static int update_usable_mem_fdt(void *fdt, struct crash_mem *usable_mem)
ret = fdt_setprop(fdt, node, "linux,drconf-usable-memory", ret = fdt_setprop(fdt, node, "linux,drconf-usable-memory",
um_info.buf, (um_info.idx * sizeof(u64))); um_info.buf, (um_info.idx * sizeof(u64)));
if (ret) { if (ret) {
pr_err("Failed to update fdt with linux,drconf-usable-memory property"); pr_err("Failed to update fdt with linux,drconf-usable-memory property: %s",
fdt_strerror(ret));
goto out; goto out;
} }
} }
...@@ -978,12 +980,17 @@ static unsigned int cpu_node_size(void) ...@@ -978,12 +980,17 @@ static unsigned int cpu_node_size(void)
*/ */
unsigned int kexec_extra_fdt_size_ppc64(struct kimage *image) unsigned int kexec_extra_fdt_size_ppc64(struct kimage *image)
{ {
unsigned int cpu_nodes, extra_size; unsigned int cpu_nodes, extra_size = 0;
struct device_node *dn; struct device_node *dn;
u64 usm_entries; u64 usm_entries;
// Budget some space for the password blob. There's already extra space
// for the key name
if (plpks_is_available())
extra_size += (unsigned int)plpks_get_passwordlen();
if (image->type != KEXEC_TYPE_CRASH) if (image->type != KEXEC_TYPE_CRASH)
return 0; return extra_size;
/* /*
* For kdump kernel, account for linux,usable-memory and * For kdump kernel, account for linux,usable-memory and
...@@ -993,9 +1000,7 @@ unsigned int kexec_extra_fdt_size_ppc64(struct kimage *image) ...@@ -993,9 +1000,7 @@ unsigned int kexec_extra_fdt_size_ppc64(struct kimage *image)
if (drmem_lmb_size()) { if (drmem_lmb_size()) {
usm_entries = ((memory_hotplug_max() / drmem_lmb_size()) + usm_entries = ((memory_hotplug_max() / drmem_lmb_size()) +
(2 * (resource_size(&crashk_res) / drmem_lmb_size()))); (2 * (resource_size(&crashk_res) / drmem_lmb_size())));
extra_size = (unsigned int)(usm_entries * sizeof(u64)); extra_size += (unsigned int)(usm_entries * sizeof(u64));
} else {
extra_size = 0;
} }
/* /*
...@@ -1234,6 +1239,10 @@ int setup_new_fdt_ppc64(const struct kimage *image, void *fdt, ...@@ -1234,6 +1239,10 @@ int setup_new_fdt_ppc64(const struct kimage *image, void *fdt,
} }
} }
// If we have PLPKS active, we need to provide the password to the new kernel
if (plpks_is_available())
ret = plpks_populate_fdt(fdt);
out: out:
kfree(rmem); kfree(rmem);
kfree(umem); kfree(umem);
......
...@@ -16,6 +16,8 @@ KASAN_SANITIZE_feature-fixups.o := n ...@@ -16,6 +16,8 @@ KASAN_SANITIZE_feature-fixups.o := n
# restart_table.o contains functions called in the NMI interrupt path # restart_table.o contains functions called in the NMI interrupt path
# which can be in real mode. Disable KASAN. # which can be in real mode. Disable KASAN.
KASAN_SANITIZE_restart_table.o := n KASAN_SANITIZE_restart_table.o := n
KCSAN_SANITIZE_code-patching.o := n
KCSAN_SANITIZE_feature-fixups.o := n
ifdef CONFIG_KASAN ifdef CONFIG_KASAN
CFLAGS_code-patching.o += -DDISABLE_BRANCH_PROFILING CFLAGS_code-patching.o += -DDISABLE_BRANCH_PROFILING
......
...@@ -1051,7 +1051,8 @@ static void __init htab_initialize(void) ...@@ -1051,7 +1051,8 @@ static void __init htab_initialize(void)
static_branch_enable(&stress_hpt_key); static_branch_enable(&stress_hpt_key);
// Too early to use nr_cpu_ids, so use NR_CPUS // Too early to use nr_cpu_ids, so use NR_CPUS
tmp = memblock_phys_alloc_range(sizeof(struct stress_hpt_struct) * NR_CPUS, tmp = memblock_phys_alloc_range(sizeof(struct stress_hpt_struct) * NR_CPUS,
0, 0, MEMBLOCK_ALLOC_ANYWHERE); __alignof__(struct stress_hpt_struct),
0, MEMBLOCK_ALLOC_ANYWHERE);
memset((void *)tmp, 0xff, sizeof(struct stress_hpt_struct) * NR_CPUS); memset((void *)tmp, 0xff, sizeof(struct stress_hpt_struct) * NR_CPUS);
stress_hpt_struct = __va(tmp); stress_hpt_struct = __va(tmp);
......
...@@ -700,12 +700,13 @@ static inline void _tlbiel_va_range_multicast(struct mm_struct *mm, ...@@ -700,12 +700,13 @@ static inline void _tlbiel_va_range_multicast(struct mm_struct *mm,
*/ */
void radix__local_flush_tlb_mm(struct mm_struct *mm) void radix__local_flush_tlb_mm(struct mm_struct *mm)
{ {
unsigned long pid; unsigned long pid = mm->context.id;
if (WARN_ON_ONCE(pid == MMU_NO_CONTEXT))
return;
preempt_disable(); preempt_disable();
pid = mm->context.id; _tlbiel_pid(pid, RIC_FLUSH_TLB);
if (pid != MMU_NO_CONTEXT)
_tlbiel_pid(pid, RIC_FLUSH_TLB);
preempt_enable(); preempt_enable();
} }
EXPORT_SYMBOL(radix__local_flush_tlb_mm); EXPORT_SYMBOL(radix__local_flush_tlb_mm);
...@@ -713,12 +714,13 @@ EXPORT_SYMBOL(radix__local_flush_tlb_mm); ...@@ -713,12 +714,13 @@ EXPORT_SYMBOL(radix__local_flush_tlb_mm);
#ifndef CONFIG_SMP #ifndef CONFIG_SMP
void radix__local_flush_all_mm(struct mm_struct *mm) void radix__local_flush_all_mm(struct mm_struct *mm)
{ {
unsigned long pid; unsigned long pid = mm->context.id;
if (WARN_ON_ONCE(pid == MMU_NO_CONTEXT))
return;
preempt_disable(); preempt_disable();
pid = mm->context.id; _tlbiel_pid(pid, RIC_FLUSH_ALL);
if (pid != MMU_NO_CONTEXT)
_tlbiel_pid(pid, RIC_FLUSH_ALL);
preempt_enable(); preempt_enable();
} }
EXPORT_SYMBOL(radix__local_flush_all_mm); EXPORT_SYMBOL(radix__local_flush_all_mm);
...@@ -732,12 +734,13 @@ static void __flush_all_mm(struct mm_struct *mm, bool fullmm) ...@@ -732,12 +734,13 @@ static void __flush_all_mm(struct mm_struct *mm, bool fullmm)
void radix__local_flush_tlb_page_psize(struct mm_struct *mm, unsigned long vmaddr, void radix__local_flush_tlb_page_psize(struct mm_struct *mm, unsigned long vmaddr,
int psize) int psize)
{ {
unsigned long pid; unsigned long pid = mm->context.id;
if (WARN_ON_ONCE(pid == MMU_NO_CONTEXT))
return;
preempt_disable(); preempt_disable();
pid = mm->context.id; _tlbiel_va(vmaddr, pid, psize, RIC_FLUSH_TLB);
if (pid != MMU_NO_CONTEXT)
_tlbiel_va(vmaddr, pid, psize, RIC_FLUSH_TLB);
preempt_enable(); preempt_enable();
} }
...@@ -945,7 +948,7 @@ void radix__flush_tlb_mm(struct mm_struct *mm) ...@@ -945,7 +948,7 @@ void radix__flush_tlb_mm(struct mm_struct *mm)
enum tlb_flush_type type; enum tlb_flush_type type;
pid = mm->context.id; pid = mm->context.id;
if (unlikely(pid == MMU_NO_CONTEXT)) if (WARN_ON_ONCE(pid == MMU_NO_CONTEXT))
return; return;
preempt_disable(); preempt_disable();
...@@ -985,7 +988,7 @@ static void __flush_all_mm(struct mm_struct *mm, bool fullmm) ...@@ -985,7 +988,7 @@ static void __flush_all_mm(struct mm_struct *mm, bool fullmm)
enum tlb_flush_type type; enum tlb_flush_type type;
pid = mm->context.id; pid = mm->context.id;
if (unlikely(pid == MMU_NO_CONTEXT)) if (WARN_ON_ONCE(pid == MMU_NO_CONTEXT))
return; return;
preempt_disable(); preempt_disable();
...@@ -1024,7 +1027,7 @@ void radix__flush_tlb_page_psize(struct mm_struct *mm, unsigned long vmaddr, ...@@ -1024,7 +1027,7 @@ void radix__flush_tlb_page_psize(struct mm_struct *mm, unsigned long vmaddr,
enum tlb_flush_type type; enum tlb_flush_type type;
pid = mm->context.id; pid = mm->context.id;
if (unlikely(pid == MMU_NO_CONTEXT)) if (WARN_ON_ONCE(pid == MMU_NO_CONTEXT))
return; return;
preempt_disable(); preempt_disable();
...@@ -1104,6 +1107,9 @@ void radix__flush_tlb_kernel_range(unsigned long start, unsigned long end) ...@@ -1104,6 +1107,9 @@ void radix__flush_tlb_kernel_range(unsigned long start, unsigned long end)
} }
EXPORT_SYMBOL(radix__flush_tlb_kernel_range); EXPORT_SYMBOL(radix__flush_tlb_kernel_range);
/*
* Doesn't appear to be used anywhere. Remove.
*/
#define TLB_FLUSH_ALL -1UL #define TLB_FLUSH_ALL -1UL
/* /*
...@@ -1125,23 +1131,22 @@ static inline void __radix__flush_tlb_range(struct mm_struct *mm, ...@@ -1125,23 +1131,22 @@ static inline void __radix__flush_tlb_range(struct mm_struct *mm,
unsigned int page_shift = mmu_psize_defs[mmu_virtual_psize].shift; unsigned int page_shift = mmu_psize_defs[mmu_virtual_psize].shift;
unsigned long page_size = 1UL << page_shift; unsigned long page_size = 1UL << page_shift;
unsigned long nr_pages = (end - start) >> page_shift; unsigned long nr_pages = (end - start) >> page_shift;
bool fullmm = (end == TLB_FLUSH_ALL);
bool flush_pid, flush_pwc = false; bool flush_pid, flush_pwc = false;
enum tlb_flush_type type; enum tlb_flush_type type;
pid = mm->context.id; pid = mm->context.id;
if (unlikely(pid == MMU_NO_CONTEXT)) if (WARN_ON_ONCE(pid == MMU_NO_CONTEXT))
return; return;
WARN_ON_ONCE(end == TLB_FLUSH_ALL);
preempt_disable(); preempt_disable();
smp_mb(); /* see radix__flush_tlb_mm */ smp_mb(); /* see radix__flush_tlb_mm */
type = flush_type_needed(mm, fullmm); type = flush_type_needed(mm, false);
if (type == FLUSH_TYPE_NONE) if (type == FLUSH_TYPE_NONE)
goto out; goto out;
if (fullmm) if (type == FLUSH_TYPE_GLOBAL)
flush_pid = true;
else if (type == FLUSH_TYPE_GLOBAL)
flush_pid = nr_pages > tlb_single_page_flush_ceiling; flush_pid = nr_pages > tlb_single_page_flush_ceiling;
else else
flush_pid = nr_pages > tlb_local_single_page_flush_ceiling; flush_pid = nr_pages > tlb_local_single_page_flush_ceiling;
...@@ -1179,15 +1184,12 @@ static inline void __radix__flush_tlb_range(struct mm_struct *mm, ...@@ -1179,15 +1184,12 @@ static inline void __radix__flush_tlb_range(struct mm_struct *mm,
} }
} }
} else { } else {
bool hflush = false; bool hflush;
unsigned long hstart, hend; unsigned long hstart, hend;
if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE)) { hstart = (start + PMD_SIZE - 1) & PMD_MASK;
hstart = (start + PMD_SIZE - 1) & PMD_MASK; hend = end & PMD_MASK;
hend = end & PMD_MASK; hflush = IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE) && hstart < hend;
if (hstart < hend)
hflush = true;
}
if (type == FLUSH_TYPE_LOCAL) { if (type == FLUSH_TYPE_LOCAL) {
asm volatile("ptesync": : :"memory"); asm volatile("ptesync": : :"memory");
...@@ -1302,7 +1304,7 @@ void radix__tlb_flush(struct mmu_gather *tlb) ...@@ -1302,7 +1304,7 @@ void radix__tlb_flush(struct mmu_gather *tlb)
* that flushes the process table entry cache upon process teardown. * that flushes the process table entry cache upon process teardown.
* See the comment for radix in arch_exit_mmap(). * See the comment for radix in arch_exit_mmap().
*/ */
if (tlb->fullmm || tlb->need_flush_all) { if (tlb->fullmm) {
__flush_all_mm(mm, true); __flush_all_mm(mm, true);
} else if ( (psize = radix_get_mmu_psize(page_size)) == -1) { } else if ( (psize = radix_get_mmu_psize(page_size)) == -1) {
if (!tlb->freed_tables) if (!tlb->freed_tables)
...@@ -1325,25 +1327,22 @@ static void __radix__flush_tlb_range_psize(struct mm_struct *mm, ...@@ -1325,25 +1327,22 @@ static void __radix__flush_tlb_range_psize(struct mm_struct *mm,
unsigned int page_shift = mmu_psize_defs[psize].shift; unsigned int page_shift = mmu_psize_defs[psize].shift;
unsigned long page_size = 1UL << page_shift; unsigned long page_size = 1UL << page_shift;
unsigned long nr_pages = (end - start) >> page_shift; unsigned long nr_pages = (end - start) >> page_shift;
bool fullmm = (end == TLB_FLUSH_ALL);
bool flush_pid; bool flush_pid;
enum tlb_flush_type type; enum tlb_flush_type type;
pid = mm->context.id; pid = mm->context.id;
if (unlikely(pid == MMU_NO_CONTEXT)) if (WARN_ON_ONCE(pid == MMU_NO_CONTEXT))
return; return;
fullmm = (end == TLB_FLUSH_ALL); WARN_ON_ONCE(end == TLB_FLUSH_ALL);
preempt_disable(); preempt_disable();
smp_mb(); /* see radix__flush_tlb_mm */ smp_mb(); /* see radix__flush_tlb_mm */
type = flush_type_needed(mm, fullmm); type = flush_type_needed(mm, false);
if (type == FLUSH_TYPE_NONE) if (type == FLUSH_TYPE_NONE)
goto out; goto out;
if (fullmm) if (type == FLUSH_TYPE_GLOBAL)
flush_pid = true;
else if (type == FLUSH_TYPE_GLOBAL)
flush_pid = nr_pages > tlb_single_page_flush_ceiling; flush_pid = nr_pages > tlb_single_page_flush_ceiling;
else else
flush_pid = nr_pages > tlb_local_single_page_flush_ceiling; flush_pid = nr_pages > tlb_local_single_page_flush_ceiling;
...@@ -1406,7 +1405,7 @@ void radix__flush_tlb_collapsed_pmd(struct mm_struct *mm, unsigned long addr) ...@@ -1406,7 +1405,7 @@ void radix__flush_tlb_collapsed_pmd(struct mm_struct *mm, unsigned long addr)
enum tlb_flush_type type; enum tlb_flush_type type;
pid = mm->context.id; pid = mm->context.id;
if (unlikely(pid == MMU_NO_CONTEXT)) if (WARN_ON_ONCE(pid == MMU_NO_CONTEXT))
return; return;
/* 4k page size, just blow the world */ /* 4k page size, just blow the world */
......
...@@ -120,6 +120,7 @@ extern int switch_to_as1(void); ...@@ -120,6 +120,7 @@ extern int switch_to_as1(void);
extern void restore_to_as0(int esel, int offset, void *dt_ptr, int bootcpu); extern void restore_to_as0(int esel, int offset, void *dt_ptr, int bootcpu);
void create_kaslr_tlb_entry(int entry, unsigned long virt, phys_addr_t phys); void create_kaslr_tlb_entry(int entry, unsigned long virt, phys_addr_t phys);
void reloc_kernel_entry(void *fdt, int addr); void reloc_kernel_entry(void *fdt, int addr);
void relocate_init(u64 dt_ptr, phys_addr_t start);
extern int is_second_reloc; extern int is_second_reloc;
#endif #endif
extern void loadcam_entry(unsigned int index); extern void loadcam_entry(unsigned int index);
......
...@@ -45,7 +45,9 @@ static inline void book3e_tlb_lock(void) ...@@ -45,7 +45,9 @@ static inline void book3e_tlb_lock(void)
if (!cpu_has_feature(CPU_FTR_SMT)) if (!cpu_has_feature(CPU_FTR_SMT))
return; return;
asm volatile("1: lbarx %0, 0, %1;" asm volatile(".machine push;"
".machine e6500;"
"1: lbarx %0, 0, %1;"
"cmpwi %0, 0;" "cmpwi %0, 0;"
"bne 2f;" "bne 2f;"
"stbcx. %2, 0, %1;" "stbcx. %2, 0, %1;"
...@@ -56,6 +58,7 @@ static inline void book3e_tlb_lock(void) ...@@ -56,6 +58,7 @@ static inline void book3e_tlb_lock(void)
"bne 2b;" "bne 2b;"
"b 1b;" "b 1b;"
"3:" "3:"
".machine pop;"
: "=&r" (tmp) : "=&r" (tmp)
: "r" (&paca->tcd_ptr->lock), "r" (token) : "r" (&paca->tcd_ptr->lock), "r" (token)
: "memory"); : "memory");
......
...@@ -351,7 +351,7 @@ END_FTR_SECTION_NESTED(CPU_FTR_EMB_HV,CPU_FTR_EMB_HV,532) ...@@ -351,7 +351,7 @@ END_FTR_SECTION_NESTED(CPU_FTR_EMB_HV,CPU_FTR_EMB_HV,532)
mfspr r15,SPRN_MAS2 mfspr r15,SPRN_MAS2
isync isync
tlbilxva 0,r15 PPC_TLBILX_VA(0,R15)
isync isync
mtspr SPRN_MAS6,r10 mtspr SPRN_MAS6,r10
......
...@@ -169,7 +169,7 @@ static inline void bpf_clear_seen_register(struct codegen_context *ctx, int i) ...@@ -169,7 +169,7 @@ static inline void bpf_clear_seen_register(struct codegen_context *ctx, int i)
void bpf_jit_init_reg_mapping(struct codegen_context *ctx); void bpf_jit_init_reg_mapping(struct codegen_context *ctx);
int bpf_jit_emit_func_call_rel(u32 *image, struct codegen_context *ctx, u64 func); int bpf_jit_emit_func_call_rel(u32 *image, struct codegen_context *ctx, u64 func);
int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *ctx, int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *ctx,
u32 *addrs, int pass); u32 *addrs, int pass, bool extra_pass);
void bpf_jit_build_prologue(u32 *image, struct codegen_context *ctx); void bpf_jit_build_prologue(u32 *image, struct codegen_context *ctx);
void bpf_jit_build_epilogue(u32 *image, struct codegen_context *ctx); void bpf_jit_build_epilogue(u32 *image, struct codegen_context *ctx);
void bpf_jit_realloc_regs(struct codegen_context *ctx); void bpf_jit_realloc_regs(struct codegen_context *ctx);
......
...@@ -23,74 +23,6 @@ static void bpf_jit_fill_ill_insns(void *area, unsigned int size) ...@@ -23,74 +23,6 @@ static void bpf_jit_fill_ill_insns(void *area, unsigned int size)
memset32(area, BREAKPOINT_INSTRUCTION, size / 4); memset32(area, BREAKPOINT_INSTRUCTION, size / 4);
} }
/* Fix updated addresses (for subprog calls, ldimm64, et al) during extra pass */
static int bpf_jit_fixup_addresses(struct bpf_prog *fp, u32 *image,
struct codegen_context *ctx, u32 *addrs)
{
const struct bpf_insn *insn = fp->insnsi;
bool func_addr_fixed;
u64 func_addr;
u32 tmp_idx;
int i, j, ret;
for (i = 0; i < fp->len; i++) {
/*
* During the extra pass, only the branch target addresses for
* the subprog calls need to be fixed. All other instructions
* can left untouched.
*
* The JITed image length does not change because we already
* ensure that the JITed instruction sequence for these calls
* are of fixed length by padding them with NOPs.
*/
if (insn[i].code == (BPF_JMP | BPF_CALL) &&
insn[i].src_reg == BPF_PSEUDO_CALL) {
ret = bpf_jit_get_func_addr(fp, &insn[i], true,
&func_addr,
&func_addr_fixed);
if (ret < 0)
return ret;
/*
* Save ctx->idx as this would currently point to the
* end of the JITed image and set it to the offset of
* the instruction sequence corresponding to the
* subprog call temporarily.
*/
tmp_idx = ctx->idx;
ctx->idx = addrs[i] / 4;
ret = bpf_jit_emit_func_call_rel(image, ctx, func_addr);
if (ret)
return ret;
/*
* Restore ctx->idx here. This is safe as the length
* of the JITed sequence remains unchanged.
*/
ctx->idx = tmp_idx;
} else if (insn[i].code == (BPF_LD | BPF_IMM | BPF_DW)) {
tmp_idx = ctx->idx;
ctx->idx = addrs[i] / 4;
#ifdef CONFIG_PPC32
PPC_LI32(bpf_to_ppc(insn[i].dst_reg) - 1, (u32)insn[i + 1].imm);
PPC_LI32(bpf_to_ppc(insn[i].dst_reg), (u32)insn[i].imm);
for (j = ctx->idx - addrs[i] / 4; j < 4; j++)
EMIT(PPC_RAW_NOP());
#else
func_addr = ((u64)(u32)insn[i].imm) | (((u64)(u32)insn[i + 1].imm) << 32);
PPC_LI64(bpf_to_ppc(insn[i].dst_reg), func_addr);
/* overwrite rest with nops */
for (j = ctx->idx - addrs[i] / 4; j < 5; j++)
EMIT(PPC_RAW_NOP());
#endif
ctx->idx = tmp_idx;
i++;
}
}
return 0;
}
int bpf_jit_emit_exit_insn(u32 *image, struct codegen_context *ctx, int tmp_reg, long exit_addr) int bpf_jit_emit_exit_insn(u32 *image, struct codegen_context *ctx, int tmp_reg, long exit_addr)
{ {
if (!exit_addr || is_offset_in_branch_range(exit_addr - (ctx->idx * 4))) { if (!exit_addr || is_offset_in_branch_range(exit_addr - (ctx->idx * 4))) {
...@@ -185,7 +117,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp) ...@@ -185,7 +117,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
cgctx.stack_size = round_up(fp->aux->stack_depth, 16); cgctx.stack_size = round_up(fp->aux->stack_depth, 16);
/* Scouting faux-generate pass 0 */ /* Scouting faux-generate pass 0 */
if (bpf_jit_build_body(fp, 0, &cgctx, addrs, 0)) { if (bpf_jit_build_body(fp, 0, &cgctx, addrs, 0, false)) {
/* We hit something illegal or unsupported. */ /* We hit something illegal or unsupported. */
fp = org_fp; fp = org_fp;
goto out_addrs; goto out_addrs;
...@@ -200,7 +132,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp) ...@@ -200,7 +132,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
*/ */
if (cgctx.seen & SEEN_TAILCALL || !is_offset_in_branch_range((long)cgctx.idx * 4)) { if (cgctx.seen & SEEN_TAILCALL || !is_offset_in_branch_range((long)cgctx.idx * 4)) {
cgctx.idx = 0; cgctx.idx = 0;
if (bpf_jit_build_body(fp, 0, &cgctx, addrs, 0)) { if (bpf_jit_build_body(fp, 0, &cgctx, addrs, 0, false)) {
fp = org_fp; fp = org_fp;
goto out_addrs; goto out_addrs;
} }
...@@ -234,29 +166,13 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp) ...@@ -234,29 +166,13 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
skip_init_ctx: skip_init_ctx:
code_base = (u32 *)(image + FUNCTION_DESCR_SIZE); code_base = (u32 *)(image + FUNCTION_DESCR_SIZE);
if (extra_pass) {
/*
* Do not touch the prologue and epilogue as they will remain
* unchanged. Only fix the branch target address for subprog
* calls in the body, and ldimm64 instructions.
*
* This does not change the offsets and lengths of the subprog
* call instruction sequences and hence, the size of the JITed
* image as well.
*/
bpf_jit_fixup_addresses(fp, code_base, &cgctx, addrs);
/* There is no need to perform the usual passes. */
goto skip_codegen_passes;
}
/* Code generation passes 1-2 */ /* Code generation passes 1-2 */
for (pass = 1; pass < 3; pass++) { for (pass = 1; pass < 3; pass++) {
/* Now build the prologue, body code & epilogue for real. */ /* Now build the prologue, body code & epilogue for real. */
cgctx.idx = 0; cgctx.idx = 0;
cgctx.alt_exit_addr = 0; cgctx.alt_exit_addr = 0;
bpf_jit_build_prologue(code_base, &cgctx); bpf_jit_build_prologue(code_base, &cgctx);
if (bpf_jit_build_body(fp, code_base, &cgctx, addrs, pass)) { if (bpf_jit_build_body(fp, code_base, &cgctx, addrs, pass, extra_pass)) {
bpf_jit_binary_free(bpf_hdr); bpf_jit_binary_free(bpf_hdr);
fp = org_fp; fp = org_fp;
goto out_addrs; goto out_addrs;
...@@ -268,7 +184,6 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp) ...@@ -268,7 +184,6 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
proglen - (cgctx.idx * 4), cgctx.seen); proglen - (cgctx.idx * 4), cgctx.seen);
} }
skip_codegen_passes:
if (bpf_jit_enable > 1) if (bpf_jit_enable > 1)
/* /*
* Note that we output the base address of the code_base * Note that we output the base address of the code_base
......
This diff is collapsed.
...@@ -240,13 +240,14 @@ int bpf_jit_emit_func_call_rel(u32 *image, struct codegen_context *ctx, u64 func ...@@ -240,13 +240,14 @@ int bpf_jit_emit_func_call_rel(u32 *image, struct codegen_context *ctx, u64 func
* load the callee's address, but this may optimize the number of * load the callee's address, but this may optimize the number of
* instructions required based on the nature of the address. * instructions required based on the nature of the address.
* *
* Since we don't want the number of instructions emitted to change, * Since we don't want the number of instructions emitted to increase,
* we pad the optimized PPC_LI64() call with NOPs to guarantee that * we pad the optimized PPC_LI64() call with NOPs to guarantee that
* we always have a five-instruction sequence, which is the maximum * we always have a five-instruction sequence, which is the maximum
* that PPC_LI64() can emit. * that PPC_LI64() can emit.
*/ */
for (i = ctx->idx - ctx_idx; i < 5; i++) if (!image)
EMIT(PPC_RAW_NOP()); for (i = ctx->idx - ctx_idx; i < 5; i++)
EMIT(PPC_RAW_NOP());
EMIT(PPC_RAW_MTCTR(_R12)); EMIT(PPC_RAW_MTCTR(_R12));
EMIT(PPC_RAW_BCTRL()); EMIT(PPC_RAW_BCTRL());
...@@ -343,7 +344,7 @@ asm ( ...@@ -343,7 +344,7 @@ asm (
/* Assemble the body code between the prologue & epilogue */ /* Assemble the body code between the prologue & epilogue */
int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *ctx, int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *ctx,
u32 *addrs, int pass) u32 *addrs, int pass, bool extra_pass)
{ {
enum stf_barrier_type stf_barrier = stf_barrier_type_get(); enum stf_barrier_type stf_barrier = stf_barrier_type_get();
const struct bpf_insn *insn = fp->insnsi; const struct bpf_insn *insn = fp->insnsi;
...@@ -938,8 +939,9 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context * ...@@ -938,8 +939,9 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *
tmp_idx = ctx->idx; tmp_idx = ctx->idx;
PPC_LI64(dst_reg, imm64); PPC_LI64(dst_reg, imm64);
/* padding to allow full 5 instructions for later patching */ /* padding to allow full 5 instructions for later patching */
for (j = ctx->idx - tmp_idx; j < 5; j++) if (!image)
EMIT(PPC_RAW_NOP()); for (j = ctx->idx - tmp_idx; j < 5; j++)
EMIT(PPC_RAW_NOP());
/* Adjust for two bpf instructions */ /* Adjust for two bpf instructions */
addrs[++i] = ctx->idx * 4; addrs[++i] = ctx->idx * 4;
break; break;
...@@ -967,7 +969,7 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context * ...@@ -967,7 +969,7 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *
case BPF_JMP | BPF_CALL: case BPF_JMP | BPF_CALL:
ctx->seen |= SEEN_FUNC; ctx->seen |= SEEN_FUNC;
ret = bpf_jit_get_func_addr(fp, &insn[i], false, ret = bpf_jit_get_func_addr(fp, &insn[i], extra_pass,
&func_addr, &func_addr_fixed); &func_addr, &func_addr_fixed);
if (ret < 0) if (ret < 0)
return ret; return ret;
......
This diff is collapsed.
...@@ -205,7 +205,7 @@ static void __init node_irq_request(const char *compat, irq_handler_t errirq_han ...@@ -205,7 +205,7 @@ static void __init node_irq_request(const char *compat, irq_handler_t errirq_han
for_each_compatible_node(np, NULL, compat) { for_each_compatible_node(np, NULL, compat) {
irq = irq_of_parse_and_map(np, 0); irq = irq_of_parse_and_map(np, 0);
if (irq == NO_IRQ) { if (!irq) {
pr_err("device tree node %pOFn is missing a interrupt", pr_err("device tree node %pOFn is missing a interrupt",
np); np);
of_node_put(np); of_node_put(np);
......
...@@ -41,7 +41,7 @@ static int rtas_read_config(struct pci_bus *bus, unsigned int devfn, int offset, ...@@ -41,7 +41,7 @@ static int rtas_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
int ret = -1; int ret = -1;
int rval; int rval;
rval = rtas_call(rtas_token("read-pci-config"), 2, 2, &ret, addr, len); rval = rtas_call(rtas_function_token(RTAS_FN_READ_PCI_CONFIG), 2, 2, &ret, addr, len);
*val = ret; *val = ret;
return rval ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; return rval ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
} }
...@@ -55,7 +55,7 @@ static int rtas_write_config(struct pci_bus *bus, unsigned int devfn, ...@@ -55,7 +55,7 @@ static int rtas_write_config(struct pci_bus *bus, unsigned int devfn,
| (hose->global_number << 24); | (hose->global_number << 24);
int rval; int rval;
rval = rtas_call(rtas_token("write-pci-config"), 3, 1, NULL, rval = rtas_call(rtas_function_token(RTAS_FN_WRITE_PCI_CONFIG), 3, 1, NULL,
addr, len, val); addr, len, val);
return rval ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; return rval ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
} }
......
This diff is collapsed.
...@@ -297,8 +297,8 @@ int cbe_sysreset_hack(void) ...@@ -297,8 +297,8 @@ int cbe_sysreset_hack(void)
static int __init cbe_ptcal_init(void) static int __init cbe_ptcal_init(void)
{ {
int ret; int ret;
ptcal_start_tok = rtas_token("ibm,cbe-start-ptcal"); ptcal_start_tok = rtas_function_token(RTAS_FN_IBM_CBE_START_PTCAL);
ptcal_stop_tok = rtas_token("ibm,cbe-stop-ptcal"); ptcal_stop_tok = rtas_function_token(RTAS_FN_IBM_CBE_STOP_PTCAL);
if (ptcal_start_tok == RTAS_UNKNOWN_SERVICE if (ptcal_start_tok == RTAS_UNKNOWN_SERVICE
|| ptcal_stop_tok == RTAS_UNKNOWN_SERVICE) || ptcal_stop_tok == RTAS_UNKNOWN_SERVICE)
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -323,11 +323,11 @@ static void __init chrp_setup_arch(void) ...@@ -323,11 +323,11 @@ static void __init chrp_setup_arch(void)
printk("chrp type = %x [%s]\n", _chrp_type, chrp_names[_chrp_type]); printk("chrp type = %x [%s]\n", _chrp_type, chrp_names[_chrp_type]);
rtas_initialize(); rtas_initialize();
if (rtas_token("display-character") >= 0) if (rtas_function_token(RTAS_FN_DISPLAY_CHARACTER) >= 0)
ppc_md.progress = rtas_progress; ppc_md.progress = rtas_progress;
/* use RTAS time-of-day routines if available */ /* use RTAS time-of-day routines if available */
if (rtas_token("get-time-of-day") != RTAS_UNKNOWN_SERVICE) { if (rtas_function_token(RTAS_FN_GET_TIME_OF_DAY) != RTAS_UNKNOWN_SERVICE) {
ppc_md.get_boot_time = rtas_get_boot_time; ppc_md.get_boot_time = rtas_get_boot_time;
ppc_md.get_rtc_time = rtas_get_rtc_time; ppc_md.get_rtc_time = rtas_get_rtc_time;
ppc_md.set_rtc_time = rtas_set_rtc_time; ppc_md.set_rtc_time = rtas_set_rtc_time;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment