forked from Minki/linux
powerpc updates for 6.0
- Add support for syscall stack randomization. - Add support for atomic operations to the 32 & 64-bit BPF JIT. - Full support for KASAN on 64-bit Book3E. - Add a watchdog driver for the new PowerVM hypervisor watchdog. - Add a number of new selftests for the Power10 PMU support. - Add a driver for the PowerVM Platform KeyStore. - Increase the NMI watchdog timeout during live partition migration, to avoid timeouts due to increased memory access latency. - Add support for using the 'linux,pci-domain' device tree property for PCI domain assignment. - Many other small features and fixes. Thanks to: Alexey Kardashevskiy, Andy Shevchenko, Arnd Bergmann, Athira Rajeev, Bagas Sanjaya, Christophe Leroy, Erhard Furtner, Fabiano Rosas, Greg Kroah-Hartman, Greg Kurz, Haowen Bai, Hari Bathini, Jason A. Donenfeld, Jason Wang, Jiang Jian, Joel Stanley, Juerg Haefliger, Kajol Jain, Kees Cook, Laurent Dufour, Madhavan Srinivasan, Masahiro Yamada, Maxime Bizon, Miaoqian Lin, Murilo Opsfelder Araújo, Nathan Lynch, Naveen N. Rao, Nayna Jain, Nicholas Piggin, Ning Qiang, Pali Rohár, Petr Mladek, Rashmica Gupta, Sachin Sant, Scott Cheloha, Segher Boessenkool, Stephen Rothwell, Uwe Kleine-König, Wolfram Sang, Xiu Jianfeng, Zhouyi Zhou. -----BEGIN PGP SIGNATURE----- iQJHBAABCAAxFiEEJFGtCPCthwEv2Y/bUevqPMjhpYAFAmLuAPgTHG1wZUBlbGxl cm1hbi5pZC5hdQAKCRBR6+o8yOGlgBPpD/9kY/T0qlOXABxlZCgtqeAjPX+2xpnY BF+TlsN1TS1auFcEZL2BapmVacsvOeGEFDVuZHZvZJc69Hx+gSjnjFCnZjp6n+Yz wt6y9w9Pu0t/sjD5vNQ46O15/dXqm6RoVI7um12j/WLMN8Ko5+x3gKAyQONjQd2/ 1kPcxVH6FUosAdnCuvIcqCX4e4IIHl2ZkitHOTXoQUvUy9oAK/mOBnwqZ6zLGUKC E5M+Zyt4RFGxhPs48FkX6Nq6crDGU/P0VJpDKkR/t7GHnE67Bm70gZougAPrzrgP nx8zoTWgDKpqDeuqK7pFcyKgNS3dKbxsN3sAfKHOWu/YnV4wMyy+7fmwagMauki7 lXccKN6F/r+8JcMNx80Jp/dAw3ZdLceP38M3Ryf8IL6lTfkNySumUvrKJn6r1Cu1 wvzhgyEuDawss9KHdEmXcA2i3+XVZvitaipO7JWUC8pblrP1SJMoPfIIe9zh3y3M pyZj0TcGJ8XaK+badvI+PW/K/KeRgXEY8HpC3wDHSoIkli3OE4jDwXn6TiZgvm3n k0sKL8YSmQZ8hP8QAkR+r8NQKYqLlfyPxdslK5omDPxfub5Uzk9ZV2Ep7svkaiQn Wqjq27Dpz8+w0XPjsQ0Tkv+ByTkOhrawOH7x9SpFLHpv9g5otcYmS79NkO/htx8C 6LyPNx1VYn5IRA== =tRkm -----END PGP SIGNATURE----- Merge tag 'powerpc-6.0-1' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux Pull powerpc updates from Michael Ellerman: - Add support for syscall stack randomization - Add support for atomic operations to the 32 & 64-bit BPF JIT - Full support for KASAN on 64-bit Book3E - Add a watchdog driver for the new PowerVM hypervisor watchdog - Add a number of new selftests for the Power10 PMU support - Add a driver for the PowerVM Platform KeyStore - Increase the NMI watchdog timeout during live partition migration, to avoid timeouts due to increased memory access latency - Add support for using the 'linux,pci-domain' device tree property for PCI domain assignment - Many other small features and fixes Thanks to Alexey Kardashevskiy, Andy Shevchenko, Arnd Bergmann, Athira Rajeev, Bagas Sanjaya, Christophe Leroy, Erhard Furtner, Fabiano Rosas, Greg Kroah-Hartman, Greg Kurz, Haowen Bai, Hari Bathini, Jason A. Donenfeld, Jason Wang, Jiang Jian, Joel Stanley, Juerg Haefliger, Kajol Jain, Kees Cook, Laurent Dufour, Madhavan Srinivasan, Masahiro Yamada, Maxime Bizon, Miaoqian Lin, Murilo Opsfelder Araújo, Nathan Lynch, Naveen N. Rao, Nayna Jain, Nicholas Piggin, Ning Qiang, Pali Rohár, Petr Mladek, Rashmica Gupta, Sachin Sant, Scott Cheloha, Segher Boessenkool, Stephen Rothwell, Uwe Kleine-König, Wolfram Sang, Xiu Jianfeng, and Zhouyi Zhou. * tag 'powerpc-6.0-1' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux: (191 commits) powerpc/64e: Fix kexec build error EDAC/ppc_4xx: Include required of_irq header directly powerpc/pci: Fix PHB numbering when using opal-phbid powerpc/64: Init jump labels before parse_early_param() selftests/powerpc: Avoid GCC 12 uninitialised variable warning powerpc/cell/axon_msi: Fix refcount leak in setup_msi_msg_address powerpc/xive: Fix refcount leak in xive_get_max_prio powerpc/spufs: Fix refcount leak in spufs_init_isolated_loader powerpc/perf: Include caps feature for power10 DD1 version powerpc: add support for syscall stack randomization powerpc: Move system_call_exception() to syscall.c powerpc/powernv: rename remaining rng powernv_ functions to pnv_ powerpc/powernv/kvm: Use darn for H_RANDOM on Power9 powerpc/powernv: Avoid crashing if rng is NULL selftests/powerpc: Fix matrix multiply assist test powerpc/signal: Update comment for clarity powerpc: make facility_unavailable_exception 64s powerpc/platforms/83xx/suspend: Remove write-only global variable powerpc/platforms/83xx/suspend: Prevent unloading the driver powerpc/platforms/83xx/suspend: Reorder to get rid of a forward declaration ...
This commit is contained in:
commit
cae4199f93
@ -0,0 +1,18 @@
|
||||
What: /sys/bus/event_source/devices/<dev>/caps
|
||||
Date: May 2022
|
||||
KernelVersion: 5.19
|
||||
Contact: Linux kernel mailing list <linux-kernel@vger.kernel.org>
|
||||
Description:
|
||||
Attribute group to describe the capabilities exposed
|
||||
for a particular pmu. Each attribute of this group can
|
||||
expose information specific to a PMU, say pmu_name, so that
|
||||
userspace can understand some of the feature which the
|
||||
platform specific PMU supports.
|
||||
|
||||
One of the example available capability in supported platform
|
||||
like Intel is pmu_name, which exposes underlying CPU name known
|
||||
to the PMU driver.
|
||||
|
||||
Example output in powerpc:
|
||||
grep . /sys/bus/event_source/devices/cpu/caps/*
|
||||
/sys/bus/event_source/devices/cpu/caps/pmu_name:POWER9
|
@ -3553,9 +3553,6 @@
|
||||
|
||||
noautogroup Disable scheduler automatic task group creation.
|
||||
|
||||
nobats [PPC] Do not use BATs for mapping kernel lowmem
|
||||
on "Classic" PPC cores.
|
||||
|
||||
nocache [ARM]
|
||||
|
||||
nodsp [SH] Disable hardware DSP at boot time.
|
||||
@ -3725,9 +3722,6 @@
|
||||
|
||||
nolapic_timer [X86-32,APIC] Do not use the local APIC timer.
|
||||
|
||||
noltlbs [PPC] Do not use large page/tlb entries for kernel
|
||||
lowmem mapping on PPC40x and PPC8xx
|
||||
|
||||
nomca [IA-64] Disable machine check abort handling
|
||||
|
||||
nomce [X86-32] Disable Machine Check Exception
|
||||
|
@ -592,6 +592,18 @@ to the guest kernel command line (see
|
||||
Documentation/admin-guide/kernel-parameters.rst).
|
||||
|
||||
|
||||
nmi_wd_lpm_factor (PPC only)
|
||||
============================
|
||||
|
||||
Factor to apply to the NMI watchdog timeout (only when ``nmi_watchdog`` is
|
||||
set to 1). This factor represents the percentage added to
|
||||
``watchdog_thresh`` when calculating the NMI watchdog timeout during an
|
||||
LPM. The soft lockup timeout is not impacted.
|
||||
|
||||
A value of 0 means no change. The default value is 200 meaning the NMI
|
||||
watchdog is set to 30s (based on ``watchdog_thresh`` equal to 10).
|
||||
|
||||
|
||||
numa_balancing
|
||||
==============
|
||||
|
||||
|
231
Documentation/powerpc/elf_hwcaps.rst
Normal file
231
Documentation/powerpc/elf_hwcaps.rst
Normal file
@ -0,0 +1,231 @@
|
||||
.. _elf_hwcaps_powerpc:
|
||||
|
||||
==================
|
||||
POWERPC ELF HWCAPs
|
||||
==================
|
||||
|
||||
This document describes the usage and semantics of the powerpc ELF HWCAPs.
|
||||
|
||||
|
||||
1. Introduction
|
||||
---------------
|
||||
|
||||
Some hardware or software features are only available on some CPU
|
||||
implementations, and/or with certain kernel configurations, but have no other
|
||||
discovery mechanism available to userspace code. The kernel exposes the
|
||||
presence of these features to userspace through a set of flags called HWCAPs,
|
||||
exposed in the auxiliary vector.
|
||||
|
||||
Userspace software can test for features by acquiring the AT_HWCAP or
|
||||
AT_HWCAP2 entry of the auxiliary vector, and testing whether the relevant
|
||||
flags are set, e.g.::
|
||||
|
||||
bool floating_point_is_present(void)
|
||||
{
|
||||
unsigned long HWCAPs = getauxval(AT_HWCAP);
|
||||
if (HWCAPs & PPC_FEATURE_HAS_FPU)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Where software relies on a feature described by a HWCAP, it should check the
|
||||
relevant HWCAP flag to verify that the feature is present before attempting to
|
||||
make use of the feature.
|
||||
|
||||
HWCAP is the preferred method to test for the presence of a feature rather
|
||||
than probing through other means, which may not be reliable or may cause
|
||||
unpredictable behaviour.
|
||||
|
||||
Software that targets a particular platform does not necessarily have to
|
||||
test for required or implied features. For example if the program requires
|
||||
FPU, VMX, VSX, it is not necessary to test those HWCAPs, and it may be
|
||||
impossible to do so if the compiler generates code requiring those features.
|
||||
|
||||
2. Facilities
|
||||
-------------
|
||||
|
||||
The Power ISA uses the term "facility" to describe a class of instructions,
|
||||
registers, interrupts, etc. The presence or absence of a facility indicates
|
||||
whether this class is available to be used, but the specifics depend on the
|
||||
ISA version. For example, if the VSX facility is available, the VSX
|
||||
instructions that can be used differ between the v3.0B and v3.1B ISA
|
||||
versions.
|
||||
|
||||
3. Categories
|
||||
-------------
|
||||
|
||||
The Power ISA before v3.0 uses the term "category" to describe certain
|
||||
classes of instructions and operating modes which may be optional or
|
||||
mutually exclusive, the exact meaning of the HWCAP flag may depend on
|
||||
context, e.g., the presence of the BOOKE feature implies that the server
|
||||
category is not implemented.
|
||||
|
||||
4. HWCAP allocation
|
||||
-------------------
|
||||
|
||||
HWCAPs are allocated as described in Power Architecture 64-Bit ELF V2 ABI
|
||||
Specification (which will be reflected in the kernel's uapi headers).
|
||||
|
||||
5. The HWCAPs exposed in AT_HWCAP
|
||||
---------------------------------
|
||||
|
||||
PPC_FEATURE_32
|
||||
32-bit CPU
|
||||
|
||||
PPC_FEATURE_64
|
||||
64-bit CPU (userspace may be running in 32-bit mode).
|
||||
|
||||
PPC_FEATURE_601_INSTR
|
||||
The processor is PowerPC 601.
|
||||
Unused in the kernel since f0ed73f3fa2c ("powerpc: Remove PowerPC 601")
|
||||
|
||||
PPC_FEATURE_HAS_ALTIVEC
|
||||
Vector (aka Altivec, VMX) facility is available.
|
||||
|
||||
PPC_FEATURE_HAS_FPU
|
||||
Floating point facility is available.
|
||||
|
||||
PPC_FEATURE_HAS_MMU
|
||||
Memory management unit is present and enabled.
|
||||
|
||||
PPC_FEATURE_HAS_4xxMAC
|
||||
The processor is 40x or 44x family.
|
||||
|
||||
PPC_FEATURE_UNIFIED_CACHE
|
||||
The processor has a unified L1 cache for instructions and data, as
|
||||
found in NXP e200.
|
||||
Unused in the kernel since 39c8bf2b3cc1 ("powerpc: Retire e200 core (mpc555x processor)")
|
||||
|
||||
PPC_FEATURE_HAS_SPE
|
||||
Signal Processing Engine facility is available.
|
||||
|
||||
PPC_FEATURE_HAS_EFP_SINGLE
|
||||
Embedded Floating Point single precision operations are available.
|
||||
|
||||
PPC_FEATURE_HAS_EFP_DOUBLE
|
||||
Embedded Floating Point double precision operations are available.
|
||||
|
||||
PPC_FEATURE_NO_TB
|
||||
The timebase facility (mftb instruction) is not available.
|
||||
This is a 601 specific HWCAP, so if it is known that the processor
|
||||
running is not a 601, via other HWCAPs or other means, it is not
|
||||
required to test this bit before using the timebase.
|
||||
Unused in the kernel since f0ed73f3fa2c ("powerpc: Remove PowerPC 601")
|
||||
|
||||
PPC_FEATURE_POWER4
|
||||
The processor is POWER4 or PPC970/FX/MP.
|
||||
POWER4 support dropped from the kernel since 471d7ff8b51b ("powerpc/64s: Remove POWER4 support")
|
||||
|
||||
PPC_FEATURE_POWER5
|
||||
The processor is POWER5.
|
||||
|
||||
PPC_FEATURE_POWER5_PLUS
|
||||
The processor is POWER5+.
|
||||
|
||||
PPC_FEATURE_CELL
|
||||
The processor is Cell.
|
||||
|
||||
PPC_FEATURE_BOOKE
|
||||
The processor implements the embedded category ("BookE") architecture.
|
||||
|
||||
PPC_FEATURE_SMT
|
||||
The processor implements SMT.
|
||||
|
||||
PPC_FEATURE_ICACHE_SNOOP
|
||||
The processor icache is coherent with the dcache, and instruction storage
|
||||
can be made consistent with data storage for the purpose of executing
|
||||
instructions with the sequence (as described in, e.g., POWER9 Processor
|
||||
User's Manual, 4.6.2.2 Instruction Cache Block Invalidate (icbi))::
|
||||
|
||||
sync
|
||||
icbi (to any address)
|
||||
isync
|
||||
|
||||
PPC_FEATURE_ARCH_2_05
|
||||
The processor supports the v2.05 userlevel architecture. Processors
|
||||
supporting later architectures DO NOT set this feature.
|
||||
|
||||
PPC_FEATURE_PA6T
|
||||
The processor is PA6T.
|
||||
|
||||
PPC_FEATURE_HAS_DFP
|
||||
DFP facility is available.
|
||||
|
||||
PPC_FEATURE_POWER6_EXT
|
||||
The processor is POWER6.
|
||||
|
||||
PPC_FEATURE_ARCH_2_06
|
||||
The processor supports the v2.06 userlevel architecture. Processors
|
||||
supporting later architectures also set this feature.
|
||||
|
||||
PPC_FEATURE_HAS_VSX
|
||||
VSX facility is available.
|
||||
|
||||
PPC_FEATURE_PSERIES_PERFMON_COMPAT
|
||||
The processor supports architected PMU events in the range 0xE0-0xFF.
|
||||
|
||||
PPC_FEATURE_TRUE_LE
|
||||
The processor supports true little-endian mode.
|
||||
|
||||
PPC_FEATURE_PPC_LE
|
||||
The processor supports "PowerPC Little-Endian", that uses address
|
||||
munging to make storage access appear to be little-endian, but the
|
||||
data is stored in a different format that is unsuitable to be
|
||||
accessed by other agents not running in this mode.
|
||||
|
||||
6. The HWCAPs exposed in AT_HWCAP2
|
||||
----------------------------------
|
||||
|
||||
PPC_FEATURE2_ARCH_2_07
|
||||
The processor supports the v2.07 userlevel architecture. Processors
|
||||
supporting later architectures also set this feature.
|
||||
|
||||
PPC_FEATURE2_HTM
|
||||
Transactional Memory feature is available.
|
||||
|
||||
PPC_FEATURE2_DSCR
|
||||
DSCR facility is available.
|
||||
|
||||
PPC_FEATURE2_EBB
|
||||
EBB facility is available.
|
||||
|
||||
PPC_FEATURE2_ISEL
|
||||
isel instruction is available. This is superseded by ARCH_2_07 and
|
||||
later.
|
||||
|
||||
PPC_FEATURE2_TAR
|
||||
TAR facility is available.
|
||||
|
||||
PPC_FEATURE2_VEC_CRYPTO
|
||||
v2.07 crypto instructions are available.
|
||||
|
||||
PPC_FEATURE2_HTM_NOSC
|
||||
System calls fail if called in a transactional state, see
|
||||
Documentation/powerpc/syscall64-abi.rst
|
||||
|
||||
PPC_FEATURE2_ARCH_3_00
|
||||
The processor supports the v3.0B / v3.0C userlevel architecture. Processors
|
||||
supporting later architectures also set this feature.
|
||||
|
||||
PPC_FEATURE2_HAS_IEEE128
|
||||
IEEE 128-bit binary floating point is supported with VSX
|
||||
quad-precision instructions and data types.
|
||||
|
||||
PPC_FEATURE2_DARN
|
||||
darn instruction is available.
|
||||
|
||||
PPC_FEATURE2_SCV
|
||||
The scv 0 instruction may be used for system calls, see
|
||||
Documentation/powerpc/syscall64-abi.rst.
|
||||
|
||||
PPC_FEATURE2_HTM_NO_SUSPEND
|
||||
A limited Transactional Memory facility that does not support suspend is
|
||||
available, see Documentation/powerpc/transactional_memory.rst.
|
||||
|
||||
PPC_FEATURE2_ARCH_3_1
|
||||
The processor supports the v3.1 userlevel architecture. Processors
|
||||
supporting later architectures also set this feature.
|
||||
|
||||
PPC_FEATURE2_MMA
|
||||
MMA facility is available.
|
@ -17,6 +17,7 @@ powerpc
|
||||
dawr-power9
|
||||
dscr
|
||||
eeh-pci-error-recovery
|
||||
elf_hwcaps
|
||||
elfnote
|
||||
firmware-assisted-dump
|
||||
hvcs
|
||||
|
@ -425,6 +425,18 @@ pnx833x_wdt:
|
||||
|
||||
-------------------------------------------------
|
||||
|
||||
pseries-wdt:
|
||||
action:
|
||||
Action taken when watchdog expires: 0 (power off), 1 (restart),
|
||||
2 (dump and restart). (default=1)
|
||||
timeout:
|
||||
Initial watchdog timeout in seconds. (default=60)
|
||||
nowayout:
|
||||
Watchdog cannot be stopped once started.
|
||||
(default=kernel config parameter)
|
||||
|
||||
-------------------------------------------------
|
||||
|
||||
rc32434_wdt:
|
||||
timeout:
|
||||
Watchdog timeout value, in seconds (default=20)
|
||||
|
@ -11628,8 +11628,8 @@ F: drivers/macintosh/
|
||||
|
||||
LINUX FOR POWERPC (32-BIT AND 64-BIT)
|
||||
M: Michael Ellerman <mpe@ellerman.id.au>
|
||||
R: Benjamin Herrenschmidt <benh@kernel.crashing.org>
|
||||
R: Paul Mackerras <paulus@samba.org>
|
||||
R: Nicholas Piggin <npiggin@gmail.com>
|
||||
R: Christophe Leroy <christophe.leroy@csgroup.eu>
|
||||
L: linuxppc-dev@lists.ozlabs.org
|
||||
S: Supported
|
||||
W: https://github.com/linuxppc/wiki/wiki
|
||||
|
@ -11,7 +11,7 @@ config 64BIT
|
||||
|
||||
config LIVEPATCH_64
|
||||
def_bool PPC64
|
||||
depends on LIVEPATCH
|
||||
depends on LIVEPATCH
|
||||
|
||||
config MMU
|
||||
bool
|
||||
@ -192,8 +192,10 @@ config PPC
|
||||
select HAVE_ARCH_JUMP_LABEL_RELATIVE
|
||||
select HAVE_ARCH_KASAN if PPC32 && PPC_PAGE_SHIFT <= 14
|
||||
select HAVE_ARCH_KASAN if PPC_RADIX_MMU
|
||||
select HAVE_ARCH_KASAN if PPC_BOOK3E_64
|
||||
select HAVE_ARCH_KASAN_VMALLOC if HAVE_ARCH_KASAN
|
||||
select HAVE_ARCH_KFENCE if PPC_BOOK3S_32 || PPC_8xx || 40x
|
||||
select HAVE_ARCH_RANDOMIZE_KSTACK_OFFSET
|
||||
select HAVE_ARCH_KGDB
|
||||
select HAVE_ARCH_MMAP_RND_BITS
|
||||
select HAVE_ARCH_MMAP_RND_COMPAT_BITS if COMPAT
|
||||
@ -253,6 +255,7 @@ config PPC
|
||||
select IOMMU_HELPER if PPC64
|
||||
select IRQ_DOMAIN
|
||||
select IRQ_FORCED_THREADING
|
||||
select KASAN_VMALLOC if KASAN && MODULES
|
||||
select MMU_GATHER_PAGE_SIZE
|
||||
select MMU_GATHER_RCU_TABLE_FREE
|
||||
select MMU_GATHER_MERGE_VMAS
|
||||
@ -376,6 +379,17 @@ config PPC_DCR
|
||||
depends on PPC_DCR_NATIVE || PPC_DCR_MMIO
|
||||
default y
|
||||
|
||||
config PPC_PCI_BUS_NUM_DOMAIN_DEPENDENT
|
||||
depends on PPC32
|
||||
depends on !PPC_PMAC && !PPC_CHRP
|
||||
bool "Assign PCI bus numbers from zero individually for each PCI domain"
|
||||
help
|
||||
By default on PPC32 were PCI bus numbers unique across all PCI domains.
|
||||
So system could have only 256 PCI buses independently of available
|
||||
PCI domains. When this option is enabled then PCI bus numbers are
|
||||
PCI domain dependent and each PCI controller on own domain can have
|
||||
256 PCI buses, like it is on other Linux architectures.
|
||||
|
||||
config PPC_OF_PLATFORM_PCI
|
||||
bool
|
||||
depends on PCI
|
||||
@ -452,7 +466,7 @@ choice
|
||||
default MATH_EMULATION_FULL
|
||||
depends on MATH_EMULATION
|
||||
|
||||
config MATH_EMULATION_FULL
|
||||
config MATH_EMULATION_FULL
|
||||
bool "Emulate all the floating point instructions"
|
||||
help
|
||||
Select this option will enable the kernel to support to emulate
|
||||
@ -554,7 +568,6 @@ config KEXEC_FILE
|
||||
bool "kexec file based system call"
|
||||
select KEXEC_CORE
|
||||
select HAVE_IMA_KEXEC if IMA
|
||||
select BUILD_BIN2C
|
||||
select KEXEC_ELF
|
||||
depends on PPC64
|
||||
depends on CRYPTO=y
|
||||
|
@ -305,7 +305,6 @@ config PPC_EARLY_DEBUG_OPAL
|
||||
def_bool y
|
||||
depends on PPC_EARLY_DEBUG_OPAL_RAW || PPC_EARLY_DEBUG_OPAL_HVSI
|
||||
|
||||
|
||||
config PPC_EARLY_DEBUG_HVSI_VTERMNO
|
||||
hex "vterm number to use with early debug HVSI"
|
||||
depends on PPC_EARLY_DEBUG_LPAR_HVSI
|
||||
@ -375,4 +374,5 @@ config KASAN_SHADOW_OFFSET
|
||||
hex
|
||||
depends on KASAN
|
||||
default 0xe0000000 if PPC32
|
||||
default 0xa80e000000000000 if PPC64
|
||||
default 0xa80e000000000000 if PPC_BOOK3S_64
|
||||
default 0xa8001c0000000000 if PPC_BOOK3E_64
|
||||
|
@ -15,23 +15,6 @@ HAS_BIARCH := $(call cc-option-yn, -m32)
|
||||
# Set default 32 bits cross compilers for vdso and boot wrapper
|
||||
CROSS32_COMPILE ?=
|
||||
|
||||
ifeq ($(HAS_BIARCH),y)
|
||||
ifeq ($(CROSS32_COMPILE),)
|
||||
ifdef CONFIG_PPC32
|
||||
# These options will be overridden by any -mcpu option that the CPU
|
||||
# or platform code sets later on the command line, but they are needed
|
||||
# to set a sane 32-bit cpu target for the 64-bit cross compiler which
|
||||
# may default to the wrong ISA.
|
||||
KBUILD_CFLAGS += -mcpu=powerpc
|
||||
KBUILD_AFLAGS += -mcpu=powerpc
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef CONFIG_PPC_BOOK3S_32
|
||||
KBUILD_CFLAGS += -mcpu=powerpc
|
||||
endif
|
||||
|
||||
# If we're on a ppc/ppc64/ppc64le machine use that defconfig, otherwise just use
|
||||
# ppc64_defconfig because we have nothing better to go on.
|
||||
uname := $(shell uname -m)
|
||||
@ -183,24 +166,11 @@ endif
|
||||
endif
|
||||
|
||||
CFLAGS-$(CONFIG_TARGET_CPU_BOOL) += $(call cc-option,-mcpu=$(CONFIG_TARGET_CPU))
|
||||
AFLAGS-$(CONFIG_TARGET_CPU_BOOL) += $(call cc-option,-mcpu=$(CONFIG_TARGET_CPU))
|
||||
|
||||
# Altivec option not allowed with e500mc64 in GCC.
|
||||
ifdef CONFIG_ALTIVEC
|
||||
E5500_CPU := -mcpu=powerpc64
|
||||
else
|
||||
E5500_CPU := $(call cc-option,-mcpu=e500mc64,-mcpu=powerpc64)
|
||||
endif
|
||||
CFLAGS-$(CONFIG_E5500_CPU) += $(E5500_CPU)
|
||||
CFLAGS-$(CONFIG_E5500_CPU) += $(call cc-option,-mcpu=e500mc64,-mcpu=powerpc64)
|
||||
CFLAGS-$(CONFIG_E6500_CPU) += $(call cc-option,-mcpu=e6500,$(E5500_CPU))
|
||||
|
||||
ifdef CONFIG_PPC32
|
||||
ifdef CONFIG_PPC_E500MC
|
||||
CFLAGS-y += $(call cc-option,-mcpu=e500mc,-mcpu=powerpc)
|
||||
else
|
||||
CFLAGS-$(CONFIG_E500) += $(call cc-option,-mcpu=8540 -msoft-float,-mcpu=powerpc)
|
||||
endif
|
||||
endif
|
||||
|
||||
asinstr := $(call as-instr,lis 9$(comma)foo@high,-DHAVE_AS_ATHIGH=1)
|
||||
|
||||
KBUILD_CPPFLAGS += -I $(srctree)/arch/$(ARCH) $(asinstr)
|
||||
|
@ -48,6 +48,7 @@
|
||||
bus-range = <0 255>;
|
||||
clock-frequency = <33333333>;
|
||||
interrupts = <26 2 0 0>;
|
||||
law_trgt_if = <2>;
|
||||
|
||||
pcie@0 {
|
||||
reg = <0 0 0 0 0>;
|
||||
@ -76,6 +77,7 @@
|
||||
bus-range = <0 255>;
|
||||
clock-frequency = <33333333>;
|
||||
interrupts = <25 2 0 0>;
|
||||
law_trgt_if = <1>;
|
||||
|
||||
pcie@0 {
|
||||
reg = <0 0 0 0 0>;
|
||||
@ -105,6 +107,7 @@
|
||||
bus-range = <0 255>;
|
||||
clock-frequency = <33333333>;
|
||||
interrupts = <24 2 0 0>;
|
||||
law_trgt_if = <0>;
|
||||
|
||||
pcie@0 {
|
||||
reg = <0 0 0 0 0>;
|
||||
|
483
arch/powerpc/boot/dts/turris1x.dts
Normal file
483
arch/powerpc/boot/dts/turris1x.dts
Normal file
@ -0,0 +1,483 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Turris 1.x Device Tree Source
|
||||
*
|
||||
* Copyright 2013 - 2022 CZ.NIC z.s.p.o. (http://www.nic.cz/)
|
||||
*
|
||||
* Pinout, Schematics and Altium hardware design files are open source
|
||||
* and available at: https://docs.turris.cz/hw/turris-1x/turris-1x/
|
||||
*/
|
||||
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/leds/common.h>
|
||||
/include/ "fsl/p2020si-pre.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Turris 1.x";
|
||||
compatible = "cznic,turris1x", "fsl,P2020RDB-PC"; /* fsl,P2020RDB-PC is required for booting Linux */
|
||||
|
||||
aliases {
|
||||
ethernet0 = &enet0;
|
||||
ethernet1 = &enet1;
|
||||
ethernet2 = &enet2;
|
||||
serial0 = &serial0;
|
||||
serial1 = &serial1;
|
||||
pci0 = &pci0;
|
||||
pci1 = &pci1;
|
||||
pci2 = &pci2;
|
||||
spi0 = &spi0;
|
||||
};
|
||||
|
||||
memory {
|
||||
device_type = "memory";
|
||||
};
|
||||
|
||||
soc: soc@ffe00000 {
|
||||
ranges = <0x0 0x0 0xffe00000 0x00100000>;
|
||||
|
||||
i2c@3000 {
|
||||
/* PCA9557PW GPIO controller for boot config */
|
||||
gpio-controller@18 {
|
||||
compatible = "nxp,pca9557";
|
||||
label = "bootcfg";
|
||||
reg = <0x18>;
|
||||
#gpio-cells = <2>;
|
||||
gpio-controller;
|
||||
polarity = <0x00>;
|
||||
};
|
||||
|
||||
/* STM32F030R8T6 MCU for power control */
|
||||
power-control@2a {
|
||||
/*
|
||||
* Turris Power Control firmware runs on STM32F0 MCU.
|
||||
* This firmware is open source and available at:
|
||||
* https://gitlab.nic.cz/turris/hw/turris_power_control
|
||||
*/
|
||||
reg = <0x2a>;
|
||||
};
|
||||
|
||||
/* DDR3 SPD/EEPROM PSWP instruction */
|
||||
eeprom@32 {
|
||||
reg = <0x32>;
|
||||
};
|
||||
|
||||
/* SA56004ED temperature control */
|
||||
temperature-sensor@4c {
|
||||
compatible = "nxp,sa56004";
|
||||
reg = <0x4c>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <12 IRQ_TYPE_LEVEL_LOW>, /* GPIO12 - ALERT pin */
|
||||
<13 IRQ_TYPE_LEVEL_LOW>; /* GPIO13 - CRIT pin */
|
||||
};
|
||||
|
||||
/* DDR3 SPD/EEPROM */
|
||||
eeprom@52 {
|
||||
compatible = "atmel,spd";
|
||||
reg = <0x52>;
|
||||
};
|
||||
|
||||
/* MCP79402-I/ST Protected EEPROM */
|
||||
eeprom@57 {
|
||||
reg = <0x57>;
|
||||
};
|
||||
|
||||
/* ATSHA204-TH-DA-T crypto module */
|
||||
crypto@64 {
|
||||
compatible = "atmel,atsha204";
|
||||
reg = <0x64>;
|
||||
};
|
||||
|
||||
/* IDT6V49205BNLGI clock generator */
|
||||
clock-generator@69 {
|
||||
compatible = "idt,6v49205b";
|
||||
reg = <0x69>;
|
||||
};
|
||||
|
||||
/* MCP79402-I/ST RTC */
|
||||
rtc@6f {
|
||||
compatible = "microchip,mcp7940x";
|
||||
reg = <0x6f>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <14 0>; /* GPIO14 - MFP pin */
|
||||
};
|
||||
};
|
||||
|
||||
/* SPI on connector P1 */
|
||||
spi0: spi@7000 {
|
||||
};
|
||||
|
||||
gpio: gpio-controller@fc00 {
|
||||
#interrupt-cells = <2>;
|
||||
interrupt-controller;
|
||||
};
|
||||
|
||||
/* Connected to SMSC USB2412-DZK 2-Port USB 2.0 Hub Controller */
|
||||
usb@22000 {
|
||||
phy_type = "ulpi";
|
||||
dr_mode = "host";
|
||||
};
|
||||
|
||||
enet0: ethernet@24000 {
|
||||
/* Connected to port 6 of QCA8337N-AL3C switch */
|
||||
phy-connection-type = "rgmii-id";
|
||||
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
};
|
||||
};
|
||||
|
||||
mdio@24520 {
|
||||
/* KSZ9031RNXCA ethernet phy for WAN port */
|
||||
phy: ethernet-phy@7 {
|
||||
interrupts = <3 1 0 0>;
|
||||
reg = <0x7>;
|
||||
};
|
||||
|
||||
/* QCA8337N-AL3C switch with integrated ethernet PHYs for LAN ports */
|
||||
switch@10 {
|
||||
compatible = "qca,qca8337";
|
||||
interrupts = <2 1 0 0>;
|
||||
reg = <0x10>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
label = "cpu1";
|
||||
ethernet = <&enet1>;
|
||||
phy-mode = "rgmii-id";
|
||||
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
label = "lan5";
|
||||
};
|
||||
|
||||
port@2 {
|
||||
reg = <2>;
|
||||
label = "lan4";
|
||||
};
|
||||
|
||||
port@3 {
|
||||
reg = <3>;
|
||||
label = "lan3";
|
||||
};
|
||||
|
||||
port@4 {
|
||||
reg = <4>;
|
||||
label = "lan2";
|
||||
};
|
||||
|
||||
port@5 {
|
||||
reg = <5>;
|
||||
label = "lan1";
|
||||
};
|
||||
|
||||
port@6 {
|
||||
reg = <6>;
|
||||
label = "cpu0";
|
||||
ethernet = <&enet0>;
|
||||
phy-mode = "rgmii-id";
|
||||
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
ptp_clock@24e00 {
|
||||
fsl,tclk-period = <5>;
|
||||
fsl,tmr-prsc = <200>;
|
||||
fsl,tmr-add = <0xcccccccd>;
|
||||
fsl,tmr-fiper1 = <0x3b9ac9fb>;
|
||||
fsl,tmr-fiper2 = <0x0001869b>;
|
||||
fsl,max-adj = <249999999>;
|
||||
};
|
||||
|
||||
enet1: ethernet@25000 {
|
||||
/* Connected to port 0 of QCA8337N-AL3C switch */
|
||||
phy-connection-type = "rgmii-id";
|
||||
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
};
|
||||
};
|
||||
|
||||
mdio@25520 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
enet2: ethernet@26000 {
|
||||
/* Connected to KSZ9031RNXCA ethernet phy (WAN port) */
|
||||
label = "wan";
|
||||
phy-handle = <&phy>;
|
||||
phy-connection-type = "rgmii-id";
|
||||
};
|
||||
|
||||
mdio@26520 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
sdhc@2e000 {
|
||||
bus-width = <4>;
|
||||
cd-gpios = <&gpio 8 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
};
|
||||
|
||||
lbc: localbus@ffe05000 {
|
||||
reg = <0 0xffe05000 0 0x1000>;
|
||||
|
||||
ranges = <0x0 0x0 0x0 0xef000000 0x01000000>, /* NOR */
|
||||
<0x1 0x0 0x0 0xff800000 0x00040000>, /* NAND */
|
||||
<0x3 0x0 0x0 0xffa00000 0x00020000>; /* CPLD */
|
||||
|
||||
/* S29GL128P90TFIR10 NOR */
|
||||
nor@0,0 {
|
||||
compatible = "cfi-flash";
|
||||
reg = <0x0 0x0 0x01000000>;
|
||||
bank-width = <2>;
|
||||
device-width = <1>;
|
||||
|
||||
partitions {
|
||||
compatible = "fixed-partitions";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
partition@0 {
|
||||
/* 128 kB for Device Tree Blob */
|
||||
reg = <0x00000000 0x00020000>;
|
||||
label = "dtb";
|
||||
};
|
||||
|
||||
partition@20000 {
|
||||
/* 1.7 MB for Rescue Linux Kernel Image */
|
||||
reg = <0x00020000 0x001a0000>;
|
||||
label = "rescue-kernel";
|
||||
};
|
||||
|
||||
partition@1c0000 {
|
||||
/* 1.5 MB for Rescue JFFS2 Root File System */
|
||||
reg = <0x001c0000 0x00180000>;
|
||||
label = "rescue-rootfs";
|
||||
};
|
||||
|
||||
partition@340000 {
|
||||
/* 11 MB for TAR.XZ Backup with content of NAND Root File System */
|
||||
reg = <0x00340000 0x00b00000>;
|
||||
label = "backup-rootfs";
|
||||
};
|
||||
|
||||
partition@e40000 {
|
||||
/* 768 kB for Certificates JFFS2 File System */
|
||||
reg = <0x00e40000 0x000c0000>;
|
||||
label = "certificates";
|
||||
};
|
||||
|
||||
/* free unused space 0x00f00000-0x00f20000 */
|
||||
|
||||
partition@f20000 {
|
||||
/* 128 kB for U-Boot Environment Variables */
|
||||
reg = <0x00f20000 0x00020000>;
|
||||
label = "u-boot-env";
|
||||
};
|
||||
|
||||
partition@f40000 {
|
||||
/* 768 kB for U-Boot Bootloader Image */
|
||||
reg = <0x00f40000 0x000c0000>;
|
||||
label = "u-boot";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
/* MT29F2G08ABAEAWP:E NAND */
|
||||
nand@1,0 {
|
||||
compatible = "fsl,p2020-fcm-nand", "fsl,elbc-fcm-nand";
|
||||
reg = <0x1 0x0 0x00040000>;
|
||||
nand-ecc-mode = "soft";
|
||||
nand-ecc-algo = "bch";
|
||||
|
||||
partitions {
|
||||
compatible = "fixed-partitions";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
partition@0 {
|
||||
/* 256 MB for UBI with one volume: UBIFS Root File System */
|
||||
reg = <0x00000000 0x10000000>;
|
||||
label = "rootfs";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
/* LCMXO1200C-3FTN256C FPGA */
|
||||
cpld@3,0 {
|
||||
/*
|
||||
* Turris CPLD firmware which runs on this Lattice FPGA,
|
||||
* is extended version of P1021RDB-PC CPLD v4.1 firmware.
|
||||
* It is backward compatible with its original version
|
||||
* and the only extension is support for Turris LEDs.
|
||||
* Turris CPLD firmware is open source and available at:
|
||||
* https://gitlab.nic.cz/turris/hw/turris_cpld/-/blob/master/CZ_NIC_Router_CPLD.v
|
||||
*/
|
||||
compatible = "cznic,turris1x-cpld", "fsl,p1021rdb-pc-cpld", "simple-bus", "syscon";
|
||||
reg = <0x3 0x0 0x30>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges = <0x0 0x3 0x0 0x00020000>;
|
||||
|
||||
/* MAX6370KA+T watchdog */
|
||||
watchdog@2 {
|
||||
/*
|
||||
* CPLD firmware maps SET0, SET1 and SET2
|
||||
* input logic of MAX6370KA+T chip to CPLD
|
||||
* memory space at byte offset 0x2. WDI
|
||||
* input logic is outside of the CPLD and
|
||||
* connected via external GPIO.
|
||||
*/
|
||||
compatible = "maxim,max6370";
|
||||
reg = <0x02 0x01>;
|
||||
gpios = <&gpio 11 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
reboot@d {
|
||||
compatible = "syscon-reboot";
|
||||
reg = <0x0d 0x01>;
|
||||
offset = <0x0d>;
|
||||
mask = <0x01>;
|
||||
value = <0x01>;
|
||||
};
|
||||
|
||||
led-controller@13 {
|
||||
/*
|
||||
* LEDs are controlled by CPLD firmware.
|
||||
* All five LAN LEDs share common RGB settings
|
||||
* and so it is not possible to set different
|
||||
* colors on different LAN ports.
|
||||
*/
|
||||
compatible = "cznic,turris1x-leds";
|
||||
reg = <0x13 0x1d>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
multi-led@0 {
|
||||
reg = <0x0>;
|
||||
color = <LED_COLOR_ID_RGB>;
|
||||
function = LED_FUNCTION_WAN;
|
||||
};
|
||||
|
||||
multi-led@1 {
|
||||
reg = <0x1>;
|
||||
color = <LED_COLOR_ID_RGB>;
|
||||
function = LED_FUNCTION_LAN;
|
||||
function-enumerator = <5>;
|
||||
};
|
||||
|
||||
multi-led@2 {
|
||||
reg = <0x2>;
|
||||
color = <LED_COLOR_ID_RGB>;
|
||||
function = LED_FUNCTION_LAN;
|
||||
function-enumerator = <4>;
|
||||
};
|
||||
|
||||
multi-led@3 {
|
||||
reg = <0x3>;
|
||||
color = <LED_COLOR_ID_RGB>;
|
||||
function = LED_FUNCTION_LAN;
|
||||
function-enumerator = <3>;
|
||||
};
|
||||
|
||||
multi-led@4 {
|
||||
reg = <0x4>;
|
||||
color = <LED_COLOR_ID_RGB>;
|
||||
function = LED_FUNCTION_LAN;
|
||||
function-enumerator = <2>;
|
||||
};
|
||||
|
||||
multi-led@5 {
|
||||
reg = <0x5>;
|
||||
color = <LED_COLOR_ID_RGB>;
|
||||
function = LED_FUNCTION_LAN;
|
||||
function-enumerator = <1>;
|
||||
};
|
||||
|
||||
multi-led@6 {
|
||||
reg = <0x6>;
|
||||
color = <LED_COLOR_ID_RGB>;
|
||||
function = LED_FUNCTION_WLAN;
|
||||
};
|
||||
|
||||
multi-led@7 {
|
||||
reg = <0x7>;
|
||||
color = <LED_COLOR_ID_RGB>;
|
||||
function = LED_FUNCTION_POWER;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
pci2: pcie@ffe08000 {
|
||||
/*
|
||||
* PCIe bus for on-board TUSB7340RKM USB 3.0 xHCI controller.
|
||||
* This xHCI controller is available only on Turris 1.1 boards.
|
||||
* Turris 1.0 boards have nothing connected to this PCIe bus,
|
||||
* so system would see only PCIe Root Port of this PCIe Root
|
||||
* Complex. TUSB7340RKM xHCI controller has four SuperSpeed
|
||||
* channels. Channel 0 is connected to the front USB 3.0 port,
|
||||
* channel 1 (but only USB 2.0 subset) to USB 2.0 pins on mPCIe
|
||||
* slot 1 (CN5), channels 2 and 3 to connector P600.
|
||||
*
|
||||
* P2020 PCIe Root Port uses 1MB of PCIe MEM and xHCI controller
|
||||
* uses 64kB + 8kB of PCIe MEM. No PCIe IO is used or required.
|
||||
* So allocate 2MB of PCIe MEM for this PCIe bus.
|
||||
*/
|
||||
reg = <0 0xffe08000 0 0x1000>;
|
||||
ranges = <0x02000000 0x0 0xc0000000 0 0xc0000000 0x0 0x00200000>, /* MEM */
|
||||
<0x01000000 0x0 0x00000000 0 0xffc20000 0x0 0x00010000>; /* IO */
|
||||
|
||||
pcie@0 {
|
||||
ranges;
|
||||
};
|
||||
};
|
||||
|
||||
pci1: pcie@ffe09000 {
|
||||
/* PCIe bus on mPCIe slot 2 (CN6) for expansion mPCIe card */
|
||||
reg = <0 0xffe09000 0 0x1000>;
|
||||
ranges = <0x02000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000>, /* MEM */
|
||||
<0x01000000 0x0 0x00000000 0 0xffc10000 0x0 0x00010000>; /* IO */
|
||||
|
||||
pcie@0 {
|
||||
ranges;
|
||||
};
|
||||
};
|
||||
|
||||
pci0: pcie@ffe0a000 {
|
||||
/*
|
||||
* PCIe bus on mPCIe slot 1 (CN5) for expansion mPCIe card.
|
||||
* Turris 1.1 boards have in this mPCIe slot additional USB 2.0
|
||||
* pins via channel 1 of TUSB7340RKM xHCI controller and also
|
||||
* additional SIM card slot, both for USB-based WWAN cards.
|
||||
*/
|
||||
reg = <0 0xffe0a000 0 0x1000>;
|
||||
ranges = <0x02000000 0x0 0x80000000 0 0x80000000 0x0 0x20000000>, /* MEM */
|
||||
<0x01000000 0x0 0x00000000 0 0xffc00000 0x0 0x00010000>; /* IO */
|
||||
|
||||
pcie@0 {
|
||||
ranges;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
/include/ "fsl/p2020si-post.dtsi"
|
@ -118,7 +118,7 @@ CONFIG_CRAMFS=y
|
||||
CONFIG_NLS_DEFAULT="n"
|
||||
CONFIG_NLS_CODEPAGE_437=y
|
||||
CONFIG_NLS_ISO8859_1=y
|
||||
CONFIG_DEBUG_INFO=y
|
||||
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
|
||||
CONFIG_MAGIC_SYSRQ=y
|
||||
CONFIG_DETECT_HUNG_TASK=y
|
||||
CONFIG_XMON=y
|
||||
|
@ -73,7 +73,7 @@ CONFIG_NFS_FS=y
|
||||
CONFIG_NFS_V3_ACL=y
|
||||
CONFIG_NFS_V4=y
|
||||
CONFIG_NLS_DEFAULT="n"
|
||||
CONFIG_DEBUG_INFO=y
|
||||
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
|
||||
CONFIG_MAGIC_SYSRQ=y
|
||||
CONFIG_DETECT_HUNG_TASK=y
|
||||
CONFIG_XMON=y
|
||||
|
@ -110,7 +110,7 @@ CONFIG_XZ_DEC=y
|
||||
CONFIG_PRINTK_TIME=y
|
||||
CONFIG_MESSAGE_LOGLEVEL_DEFAULT=3
|
||||
CONFIG_DYNAMIC_DEBUG=y
|
||||
CONFIG_DEBUG_INFO=y
|
||||
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
|
||||
CONFIG_MAGIC_SYSRQ=y
|
||||
CONFIG_DETECT_HUNG_TASK=y
|
||||
CONFIG_CRYPTO_CBC=y
|
||||
|
@ -56,7 +56,7 @@ CONFIG_PROC_KCORE=y
|
||||
CONFIG_TMPFS=y
|
||||
CONFIG_CRAMFS=y
|
||||
# CONFIG_NETWORK_FILESYSTEMS is not set
|
||||
CONFIG_DEBUG_INFO=y
|
||||
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
|
||||
CONFIG_MAGIC_SYSRQ=y
|
||||
CONFIG_DETECT_HUNG_TASK=y
|
||||
CONFIG_PPC_EARLY_DEBUG=y
|
||||
|
@ -88,7 +88,7 @@ CONFIG_NLS_UTF8=y
|
||||
CONFIG_CRC_CCITT=y
|
||||
CONFIG_CRC_T10DIF=y
|
||||
CONFIG_PRINTK_TIME=y
|
||||
CONFIG_DEBUG_INFO=y
|
||||
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
|
||||
CONFIG_DEBUG_FS=y
|
||||
CONFIG_MAGIC_SYSRQ=y
|
||||
CONFIG_DETECT_HUNG_TASK=y
|
||||
|
@ -58,6 +58,6 @@ CONFIG_NFS_FS=y
|
||||
CONFIG_NFS_V4=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_PRINTK_TIME=y
|
||||
CONFIG_DEBUG_INFO=y
|
||||
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
|
||||
CONFIG_DETECT_HUNG_TASK=y
|
||||
# CONFIG_DEBUG_BUGVERBOSE is not set
|
||||
|
@ -84,7 +84,7 @@ CONFIG_ROOT_NFS=y
|
||||
CONFIG_NLS_CODEPAGE_437=y
|
||||
CONFIG_NLS_ISO8859_1=y
|
||||
CONFIG_PRINTK_TIME=y
|
||||
CONFIG_DEBUG_INFO=y
|
||||
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
|
||||
CONFIG_DETECT_HUNG_TASK=y
|
||||
# CONFIG_DEBUG_BUGVERBOSE is not set
|
||||
CONFIG_CRYPTO_ECB=y
|
||||
|
@ -85,7 +85,7 @@ CONFIG_ROOT_NFS=y
|
||||
CONFIG_NLS_CODEPAGE_437=y
|
||||
CONFIG_NLS_ISO8859_1=y
|
||||
CONFIG_PRINTK_TIME=y
|
||||
CONFIG_DEBUG_INFO=y
|
||||
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
|
||||
CONFIG_DETECT_HUNG_TASK=y
|
||||
# CONFIG_DEBUG_BUGVERBOSE is not set
|
||||
CONFIG_CRYPTO_ECB=y
|
||||
|
@ -45,7 +45,7 @@ CONFIG_CRAMFS=y
|
||||
CONFIG_NFS_FS=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_CRC32_SLICEBY4=y
|
||||
CONFIG_DEBUG_INFO=y
|
||||
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
|
||||
CONFIG_DEBUG_FS=y
|
||||
CONFIG_MAGIC_SYSRQ=y
|
||||
CONFIG_DETECT_HUNG_TASK=y
|
||||
|
@ -59,7 +59,7 @@ CONFIG_NLS_CODEPAGE_437=y
|
||||
CONFIG_NLS_ASCII=y
|
||||
CONFIG_NLS_ISO8859_1=y
|
||||
CONFIG_NLS_UTF8=y
|
||||
CONFIG_DEBUG_INFO=y
|
||||
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
|
||||
CONFIG_MAGIC_SYSRQ=y
|
||||
# CONFIG_SCHED_DEBUG is not set
|
||||
CONFIG_BDI_SWITCH=y
|
||||
|
@ -48,6 +48,6 @@ CONFIG_CRAMFS=y
|
||||
CONFIG_NFS_FS=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_CRC32_SLICEBY4=y
|
||||
CONFIG_DEBUG_INFO=y
|
||||
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
|
||||
CONFIG_MAGIC_SYSRQ=y
|
||||
CONFIG_DETECT_HUNG_TASK=y
|
||||
|
@ -24,7 +24,7 @@ CONFIG_CRYPTO_PCBC=m
|
||||
CONFIG_CRYPTO_SHA256=y
|
||||
CONFIG_CRYPTO_SHA512=y
|
||||
CONFIG_DEBUG_FS=y
|
||||
CONFIG_DEBUG_INFO=y
|
||||
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
|
||||
CONFIG_DEBUG_KERNEL=y
|
||||
CONFIG_DEBUG_SHIRQ=y
|
||||
CONFIG_DETECT_HUNG_TASK=y
|
||||
|
@ -73,7 +73,7 @@ CONFIG_NLS_CODEPAGE_437=y
|
||||
CONFIG_NLS_ASCII=y
|
||||
CONFIG_NLS_ISO8859_1=y
|
||||
CONFIG_NLS_UTF8=y
|
||||
CONFIG_DEBUG_INFO=y
|
||||
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
|
||||
CONFIG_DEBUG_FS=y
|
||||
CONFIG_MAGIC_SYSRQ=y
|
||||
# CONFIG_SCHED_DEBUG is not set
|
||||
|
@ -122,6 +122,6 @@ CONFIG_ROOT_NFS=y
|
||||
CONFIG_NLS_CODEPAGE_437=y
|
||||
CONFIG_NLS_ISO8859_1=y
|
||||
CONFIG_PRINTK_TIME=y
|
||||
CONFIG_DEBUG_INFO=y
|
||||
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
|
||||
CONFIG_DEBUG_KERNEL=y
|
||||
CONFIG_DETECT_HUNG_TASK=y
|
||||
|
@ -67,7 +67,7 @@ CONFIG_NLS_CODEPAGE_437=y
|
||||
CONFIG_NLS_ASCII=y
|
||||
CONFIG_NLS_ISO8859_1=y
|
||||
CONFIG_NLS_UTF8=y
|
||||
CONFIG_DEBUG_INFO=y
|
||||
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
|
||||
CONFIG_MAGIC_SYSRQ=y
|
||||
CONFIG_DETECT_HUNG_TASK=y
|
||||
CONFIG_BDI_SWITCH=y
|
||||
|
@ -71,7 +71,7 @@ CONFIG_ROOT_NFS=y
|
||||
CONFIG_CRYPTO=y
|
||||
CONFIG_CRYPTO_DEV_TALITOS=y
|
||||
CONFIG_CRC32_SLICEBY4=y
|
||||
CONFIG_DEBUG_INFO=y
|
||||
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
|
||||
CONFIG_MAGIC_SYSRQ=y
|
||||
CONFIG_DEBUG_FS=y
|
||||
CONFIG_DEBUG_VM_PGTABLE=y
|
||||
|
@ -1065,7 +1065,7 @@ CONFIG_NLS_ISO8859_14=m
|
||||
CONFIG_NLS_ISO8859_15=m
|
||||
CONFIG_NLS_KOI8_R=m
|
||||
CONFIG_NLS_KOI8_U=m
|
||||
CONFIG_DEBUG_INFO=y
|
||||
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
|
||||
CONFIG_HEADERS_INSTALL=y
|
||||
CONFIG_MAGIC_SYSRQ=y
|
||||
CONFIG_DEBUG_KERNEL=y
|
||||
|
@ -68,7 +68,7 @@ CONFIG_NLS_CODEPAGE_437=y
|
||||
CONFIG_NLS_ASCII=y
|
||||
CONFIG_NLS_ISO8859_1=y
|
||||
CONFIG_NLS_UTF8=y
|
||||
CONFIG_DEBUG_INFO=y
|
||||
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
|
||||
CONFIG_MAGIC_SYSRQ=y
|
||||
CONFIG_DETECT_HUNG_TASK=y
|
||||
# CONFIG_SCHED_DEBUG is not set
|
||||
|
@ -153,7 +153,7 @@ CONFIG_NLS_CODEPAGE_437=y
|
||||
CONFIG_NLS_ISO8859_1=y
|
||||
CONFIG_CRC_CCITT=m
|
||||
CONFIG_CRC_T10DIF=y
|
||||
CONFIG_DEBUG_INFO=y
|
||||
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
|
||||
CONFIG_MAGIC_SYSRQ=y
|
||||
CONFIG_DEBUG_MEMORY_INIT=y
|
||||
CONFIG_DEBUG_STACKOVERFLOW=y
|
||||
|
@ -55,6 +55,6 @@ CONFIG_CRAMFS=y
|
||||
CONFIG_NFS_FS=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_CRC32_SLICEBY4=y
|
||||
CONFIG_DEBUG_INFO=y
|
||||
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
|
||||
CONFIG_MAGIC_SYSRQ=y
|
||||
CONFIG_DETECT_HUNG_TASK=y
|
||||
|
@ -17,12 +17,7 @@ static inline size_t __must_check arch_get_random_seed_longs(unsigned long *v, s
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PPC_POWERNV
|
||||
int powernv_hwrng_present(void);
|
||||
int powernv_get_random_long(unsigned long *v);
|
||||
int powernv_get_random_real_mode(unsigned long *v);
|
||||
#else
|
||||
static inline int powernv_hwrng_present(void) { return 0; }
|
||||
static inline int powernv_get_random_real_mode(unsigned long *v) { return 0; }
|
||||
int pnv_get_random_long(unsigned long *v);
|
||||
#endif
|
||||
|
||||
#endif /* _ASM_POWERPC_ARCHRANDOM_H */
|
||||
|
@ -2,8 +2,9 @@
|
||||
#ifndef _ASM_POWERPC_ASM_PROTOTYPES_H
|
||||
#define _ASM_POWERPC_ASM_PROTOTYPES_H
|
||||
/*
|
||||
* This file is for prototypes of C functions that are only called
|
||||
* from asm, and any associated variables.
|
||||
* This file is for C prototypes of asm symbols that are EXPORTed.
|
||||
* It allows the modversions logic to see their prototype and
|
||||
* generate proper CRCs for them.
|
||||
*
|
||||
* Copyright 2016, Daniel Axtens, IBM Corporation.
|
||||
*/
|
||||
@ -34,12 +35,6 @@ int64_t __opal_call(int64_t a0, int64_t a1, int64_t a2, int64_t a3,
|
||||
int64_t a4, int64_t a5, int64_t a6, int64_t a7,
|
||||
int64_t opcode, uint64_t msr);
|
||||
|
||||
/* prom_init (OpenFirmware) */
|
||||
unsigned long __init prom_init(unsigned long r3, unsigned long r4,
|
||||
unsigned long pp,
|
||||
unsigned long r6, unsigned long r7,
|
||||
unsigned long kbase);
|
||||
|
||||
/* misc runtime */
|
||||
extern u64 __bswapdi2(u64);
|
||||
extern s64 __lshrdi3(s64, int);
|
||||
|
@ -42,6 +42,8 @@
|
||||
/* The sub-arch has lwsync */
|
||||
#if defined(CONFIG_PPC64) || defined(CONFIG_PPC_E500MC)
|
||||
# define SMPWMB LWSYNC
|
||||
#elif defined(CONFIG_BOOKE)
|
||||
# define SMPWMB mbar
|
||||
#else
|
||||
# define SMPWMB eieio
|
||||
#endif
|
||||
|
@ -1,6 +1,9 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _ASM_POWERPC_BOOK3S_64_HUGETLB_H
|
||||
#define _ASM_POWERPC_BOOK3S_64_HUGETLB_H
|
||||
|
||||
#include <asm/firmware.h>
|
||||
|
||||
/*
|
||||
* For radix we want generic code to handle hugetlb. But then if we want
|
||||
* both hash and radix to be enabled together we need to workaround the
|
||||
|
@ -138,9 +138,29 @@ static inline void flush_all_mm(struct mm_struct *mm)
|
||||
static inline void flush_tlb_fix_spurious_fault(struct vm_area_struct *vma,
|
||||
unsigned long address)
|
||||
{
|
||||
/* See ptep_set_access_flags comment */
|
||||
if (atomic_read(&vma->vm_mm->context.copros) > 0)
|
||||
flush_tlb_page(vma, address);
|
||||
/*
|
||||
* Book3S 64 does not require spurious fault flushes because the PTE
|
||||
* must be re-fetched in case of an access permission problem. So the
|
||||
* only reason for a spurious fault should be concurrent modification
|
||||
* to the PTE, in which case the PTE will eventually be re-fetched by
|
||||
* the MMU when it attempts the access again.
|
||||
*
|
||||
* See: Power ISA Version 3.1B, 6.10.1.2 Modifying a Translation Table
|
||||
* Entry, Setting a Reference or Change Bit or Upgrading Access
|
||||
* Authority (PTE Subject to Atomic Hardware Updates):
|
||||
*
|
||||
* "If the only change being made to a valid PTE that is subject to
|
||||
* atomic hardware updates is to set the Reference or Change bit to
|
||||
* 1 or to upgrade access authority, a simpler sequence suffices
|
||||
* because the translation hardware will refetch the PTE if an
|
||||
* access is attempted for which the only problems were reference
|
||||
* and/or change bits needing to be set or insufficient access
|
||||
* authority."
|
||||
*
|
||||
* The nest MMU in POWER9 does not perform this PTE re-fetch, but
|
||||
* it avoids the spurious fault problem by flushing the TLB before
|
||||
* upgrading PTE permissions, see radix__ptep_set_access_flags.
|
||||
*/
|
||||
}
|
||||
|
||||
extern bool tlbie_capable;
|
||||
|
@ -70,9 +70,6 @@ struct cpu_spec {
|
||||
/* Used to restore cpu setup on secondary processors and at resume */
|
||||
cpu_restore_t cpu_restore;
|
||||
|
||||
/* Used by oprofile userspace to select the right counters */
|
||||
char *oprofile_cpu_type;
|
||||
|
||||
/* Name of processor class, for the ELF AT_PLATFORM entry */
|
||||
char *platform;
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <asm/div64.h>
|
||||
#include <asm/time.h>
|
||||
#include <asm/param.h>
|
||||
#include <asm/firmware.h>
|
||||
|
||||
typedef u64 __nocast cputime_t;
|
||||
typedef u64 __nocast cputime64_t;
|
||||
|
@ -55,6 +55,7 @@
|
||||
#define FW_FEATURE_RPT_INVALIDATE ASM_CONST(0x0000010000000000)
|
||||
#define FW_FEATURE_FORM2_AFFINITY ASM_CONST(0x0000020000000000)
|
||||
#define FW_FEATURE_ENERGY_SCALE_INFO ASM_CONST(0x0000040000000000)
|
||||
#define FW_FEATURE_WATCHDOG ASM_CONST(0x0000080000000000)
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
@ -76,7 +77,7 @@ enum {
|
||||
FW_FEATURE_DRC_INFO | FW_FEATURE_BLOCK_REMOVE |
|
||||
FW_FEATURE_PAPR_SCM | FW_FEATURE_ULTRAVISOR |
|
||||
FW_FEATURE_RPT_INVALIDATE | FW_FEATURE_FORM2_AFFINITY |
|
||||
FW_FEATURE_ENERGY_SCALE_INFO,
|
||||
FW_FEATURE_ENERGY_SCALE_INFO | FW_FEATURE_WATCHDOG,
|
||||
FW_FEATURE_PSERIES_ALWAYS = 0,
|
||||
FW_FEATURE_POWERNV_POSSIBLE = FW_FEATURE_OPAL | FW_FEATURE_ULTRAVISOR,
|
||||
FW_FEATURE_POWERNV_ALWAYS = 0,
|
||||
|
@ -79,6 +79,7 @@
|
||||
#define H_NOT_ENOUGH_RESOURCES -44
|
||||
#define H_R_STATE -45
|
||||
#define H_RESCINDED -46
|
||||
#define H_P1 -54
|
||||
#define H_P2 -55
|
||||
#define H_P3 -56
|
||||
#define H_P4 -57
|
||||
@ -87,6 +88,7 @@
|
||||
#define H_P7 -60
|
||||
#define H_P8 -61
|
||||
#define H_P9 -62
|
||||
#define H_NOOP -63
|
||||
#define H_TOO_BIG -64
|
||||
#define H_UNSUPPORTED -67
|
||||
#define H_OVERLAP -68
|
||||
@ -97,6 +99,8 @@
|
||||
#define H_OP_MODE -73
|
||||
#define H_COP_HW -74
|
||||
#define H_STATE -75
|
||||
#define H_IN_USE -77
|
||||
#define H_ABORTED -78
|
||||
#define H_UNSUPPORTED_FLAG_START -256
|
||||
#define H_UNSUPPORTED_FLAG_END -511
|
||||
#define H_MULTI_THREADS_ACTIVE -9005
|
||||
@ -321,10 +325,19 @@
|
||||
#define H_SCM_UNBIND_ALL 0x3FC
|
||||
#define H_SCM_HEALTH 0x400
|
||||
#define H_SCM_PERFORMANCE_STATS 0x418
|
||||
#define H_PKS_GET_CONFIG 0x41C
|
||||
#define H_PKS_SET_PASSWORD 0x420
|
||||
#define H_PKS_GEN_PASSWORD 0x424
|
||||
#define H_PKS_WRITE_OBJECT 0x42C
|
||||
#define H_PKS_GEN_KEY 0x430
|
||||
#define H_PKS_READ_OBJECT 0x434
|
||||
#define H_PKS_REMOVE_OBJECT 0x438
|
||||
#define H_PKS_CONFIRM_OBJECT_FLUSHED 0x43C
|
||||
#define H_RPT_INVALIDATE 0x448
|
||||
#define H_SCM_FLUSH 0x44C
|
||||
#define H_GET_ENERGY_SCALE_INFO 0x450
|
||||
#define MAX_HCALL_OPCODE H_GET_ENERGY_SCALE_INFO
|
||||
#define H_WATCHDOG 0x45C
|
||||
#define MAX_HCALL_OPCODE H_WATCHDOG
|
||||
|
||||
/* Scope args for H_SCM_UNBIND_ALL */
|
||||
#define H_UNBIND_SCOPE_ALL (0x1)
|
||||
@ -350,6 +363,14 @@
|
||||
/* Platform specific hcalls, used by KVM */
|
||||
#define H_RTAS 0xf000
|
||||
|
||||
/*
|
||||
* Platform specific hcalls, used by QEMU/SLOF. These are ignored by
|
||||
* KVM and only kept here so we can identify them during tracing.
|
||||
*/
|
||||
#define H_LOGICAL_MEMOP 0xF001
|
||||
#define H_CAS 0XF002
|
||||
#define H_UPDATE_DT 0XF003
|
||||
|
||||
/* "Platform specific hcalls", provided by PHYP */
|
||||
#define H_GET_24X7_CATALOG_PAGE 0xF078
|
||||
#define H_GET_24X7_DATA 0xF07C
|
||||
|
@ -113,14 +113,7 @@ static inline void __hard_RI_enable(void)
|
||||
|
||||
static inline notrace unsigned long irq_soft_mask_return(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
asm volatile(
|
||||
"lbz %0,%1(13)"
|
||||
: "=r" (flags)
|
||||
: "i" (offsetof(struct paca_struct, irq_soft_mask)));
|
||||
|
||||
return flags;
|
||||
return READ_ONCE(local_paca->irq_soft_mask);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -130,7 +123,6 @@ static inline notrace unsigned long irq_soft_mask_return(void)
|
||||
*/
|
||||
static inline notrace void irq_soft_mask_set(unsigned long mask)
|
||||
{
|
||||
#ifdef CONFIG_PPC_IRQ_SOFT_MASK_DEBUG
|
||||
/*
|
||||
* The irq mask must always include the STD bit if any are set.
|
||||
*
|
||||
@ -145,49 +137,27 @@ static inline notrace void irq_soft_mask_set(unsigned long mask)
|
||||
* unmasks to be replayed, among other things. For now, take
|
||||
* the simple approach.
|
||||
*/
|
||||
WARN_ON(mask && !(mask & IRQS_DISABLED));
|
||||
#endif
|
||||
if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG))
|
||||
WARN_ON(mask && !(mask & IRQS_DISABLED));
|
||||
|
||||
asm volatile(
|
||||
"stb %0,%1(13)"
|
||||
:
|
||||
: "r" (mask),
|
||||
"i" (offsetof(struct paca_struct, irq_soft_mask))
|
||||
: "memory");
|
||||
WRITE_ONCE(local_paca->irq_soft_mask, mask);
|
||||
barrier();
|
||||
}
|
||||
|
||||
static inline notrace unsigned long irq_soft_mask_set_return(unsigned long mask)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned long flags = irq_soft_mask_return();
|
||||
|
||||
#ifdef CONFIG_PPC_IRQ_SOFT_MASK_DEBUG
|
||||
WARN_ON(mask && !(mask & IRQS_DISABLED));
|
||||
#endif
|
||||
|
||||
asm volatile(
|
||||
"lbz %0,%1(13); stb %2,%1(13)"
|
||||
: "=&r" (flags)
|
||||
: "i" (offsetof(struct paca_struct, irq_soft_mask)),
|
||||
"r" (mask)
|
||||
: "memory");
|
||||
irq_soft_mask_set(mask);
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
static inline notrace unsigned long irq_soft_mask_or_return(unsigned long mask)
|
||||
{
|
||||
unsigned long flags, tmp;
|
||||
unsigned long flags = irq_soft_mask_return();
|
||||
|
||||
asm volatile(
|
||||
"lbz %0,%2(13); or %1,%0,%3; stb %1,%2(13)"
|
||||
: "=&r" (flags), "=r" (tmp)
|
||||
: "i" (offsetof(struct paca_struct, irq_soft_mask)),
|
||||
"r" (mask)
|
||||
: "memory");
|
||||
|
||||
#ifdef CONFIG_PPC_IRQ_SOFT_MASK_DEBUG
|
||||
WARN_ON((mask | flags) && !((mask | flags) & IRQS_DISABLED));
|
||||
#endif
|
||||
irq_soft_mask_set(flags | mask);
|
||||
|
||||
return flags;
|
||||
}
|
||||
@ -312,9 +282,7 @@ static inline bool pmi_irq_pending(void)
|
||||
flags = irq_soft_mask_set_return(IRQS_ALL_DISABLED); \
|
||||
local_paca->irq_happened |= PACA_IRQ_HARD_DIS; \
|
||||
if (!arch_irqs_disabled_flags(flags)) { \
|
||||
asm ("stdx %%r1, 0, %1 ;" \
|
||||
: "=m" (local_paca->saved_r1) \
|
||||
: "b" (&local_paca->saved_r1)); \
|
||||
WRITE_ONCE(local_paca->saved_r1, current_stack_pointer);\
|
||||
trace_hardirqs_off(); \
|
||||
} \
|
||||
} while(0)
|
||||
@ -353,11 +321,13 @@ bool power_pmu_wants_prompt_pmi(void);
|
||||
*/
|
||||
static inline bool should_hard_irq_enable(void)
|
||||
{
|
||||
#ifdef CONFIG_PPC_IRQ_SOFT_MASK_DEBUG
|
||||
WARN_ON(irq_soft_mask_return() == IRQS_ENABLED);
|
||||
WARN_ON(mfmsr() & MSR_EE);
|
||||
#endif
|
||||
#ifdef CONFIG_PERF_EVENTS
|
||||
if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG)) {
|
||||
WARN_ON(irq_soft_mask_return() == IRQS_ENABLED);
|
||||
WARN_ON(mfmsr() & MSR_EE);
|
||||
}
|
||||
|
||||
if (!IS_ENABLED(CONFIG_PERF_EVENTS))
|
||||
return false;
|
||||
/*
|
||||
* If the PMU is not running, there is not much reason to enable
|
||||
* MSR[EE] in irq handlers because any interrupts would just be
|
||||
@ -372,9 +342,6 @@ static inline bool should_hard_irq_enable(void)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@ -382,11 +349,11 @@ static inline bool should_hard_irq_enable(void)
|
||||
*/
|
||||
static inline void do_hard_irq_enable(void)
|
||||
{
|
||||
#ifdef CONFIG_PPC_IRQ_SOFT_MASK_DEBUG
|
||||
WARN_ON(irq_soft_mask_return() == IRQS_ENABLED);
|
||||
WARN_ON(get_paca()->irq_happened & PACA_IRQ_MUST_HARD_MASK);
|
||||
WARN_ON(mfmsr() & MSR_EE);
|
||||
#endif
|
||||
if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG)) {
|
||||
WARN_ON(irq_soft_mask_return() == IRQS_ENABLED);
|
||||
WARN_ON(get_paca()->irq_happened & PACA_IRQ_MUST_HARD_MASK);
|
||||
WARN_ON(mfmsr() & MSR_EE);
|
||||
}
|
||||
/*
|
||||
* This allows PMI interrupts (and watchdog soft-NMIs) through.
|
||||
* There is no other reason to enable this way.
|
||||
|
@ -139,25 +139,6 @@ static inline void ppc_inst_write(u32 *ptr, ppc_inst_t x)
|
||||
*(u64 *)ptr = ppc_inst_as_ulong(x);
|
||||
}
|
||||
|
||||
#define PPC_INST_STR_LEN sizeof("00000000 00000000")
|
||||
|
||||
static inline char *__ppc_inst_as_str(char str[PPC_INST_STR_LEN], ppc_inst_t x)
|
||||
{
|
||||
if (ppc_inst_prefixed(x))
|
||||
sprintf(str, "%08x %08x", ppc_inst_val(x), ppc_inst_suffix(x));
|
||||
else
|
||||
sprintf(str, "%08x", ppc_inst_val(x));
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
#define ppc_inst_as_str(x) \
|
||||
({ \
|
||||
char __str[PPC_INST_STR_LEN]; \
|
||||
__ppc_inst_as_str(__str, x); \
|
||||
__str; \
|
||||
})
|
||||
|
||||
static inline int __copy_inst_from_kernel_nofault(ppc_inst_t *inst, u32 *src)
|
||||
{
|
||||
unsigned int val, suffix;
|
||||
|
@ -69,6 +69,7 @@
|
||||
#include <linux/context_tracking.h>
|
||||
#include <linux/hardirq.h>
|
||||
#include <asm/cputime.h>
|
||||
#include <asm/firmware.h>
|
||||
#include <asm/ftrace.h>
|
||||
#include <asm/kprobes.h>
|
||||
#include <asm/runlatch.h>
|
||||
|
@ -33,7 +33,6 @@ extern struct pci_dev *isa_bridge_pcidev;
|
||||
#include <asm/delay.h>
|
||||
#include <asm/mmiowb.h>
|
||||
#include <asm/mmu.h>
|
||||
#include <asm/ppc_asm.h>
|
||||
|
||||
#define SIO_CONFIG_RA 0x398
|
||||
#define SIO_CONFIG_RD 0x399
|
||||
|
@ -54,7 +54,6 @@ extern void *softirq_ctx[NR_CPUS];
|
||||
|
||||
void __do_IRQ(struct pt_regs *regs);
|
||||
extern void __init init_IRQ(void);
|
||||
extern void __do_irq(struct pt_regs *regs);
|
||||
|
||||
int irq_choose_cpu(const struct cpumask *mask);
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
#define KASAN_SHADOW_SCALE_SHIFT 3
|
||||
|
||||
#ifdef CONFIG_MODULES
|
||||
#if defined(CONFIG_MODULES) && defined(CONFIG_PPC32)
|
||||
#define KASAN_KERN_START ALIGN_DOWN(PAGE_OFFSET - SZ_256M, SZ_256M)
|
||||
#else
|
||||
#define KASAN_KERN_START PAGE_OFFSET
|
||||
@ -39,6 +39,17 @@
|
||||
* c00e000000000000 << 3 + a80e000000000000 = c00fc00000000000
|
||||
*/
|
||||
#define KASAN_SHADOW_END 0xc00fc00000000000UL
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* The shadow ends before the highest accessible address
|
||||
* because we don't need a shadow for the shadow.
|
||||
* But it doesn't hurt to have a shadow for the shadow,
|
||||
* keep shadow end aligned eases things.
|
||||
*/
|
||||
#define KASAN_SHADOW_END 0xc000200000000000UL
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_KASAN
|
||||
|
@ -83,6 +83,7 @@ extern void default_machine_crash_shutdown(struct pt_regs *regs);
|
||||
extern int crash_shutdown_register(crash_shutdown_t handler);
|
||||
extern int crash_shutdown_unregister(crash_shutdown_t handler);
|
||||
|
||||
extern void crash_kexec_prepare(void);
|
||||
extern void crash_kexec_secondary(struct pt_regs *regs);
|
||||
int __init overlaps_crashkernel(unsigned long start, unsigned long size);
|
||||
extern void reserve_crashkernel(void);
|
||||
|
@ -29,7 +29,7 @@
|
||||
struct pt_regs;
|
||||
struct kprobe;
|
||||
|
||||
typedef ppc_opcode_t kprobe_opcode_t;
|
||||
typedef u32 kprobe_opcode_t;
|
||||
|
||||
extern kprobe_opcode_t optinsn_slot;
|
||||
|
||||
|
@ -280,9 +280,6 @@ extern void kvmppc_copy_to_svcpu(struct kvm_vcpu *vcpu);
|
||||
extern void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu);
|
||||
|
||||
long kvmppc_read_intr(void);
|
||||
void kvmppc_bad_interrupt(struct pt_regs *regs);
|
||||
void kvmhv_p9_set_lpcr(struct kvm_split_mode *sip);
|
||||
void kvmhv_p9_restore_lpcr(struct kvm_split_mode *sip);
|
||||
void kvmppc_set_msr_hv(struct kvm_vcpu *vcpu, u64 msr);
|
||||
void kvmppc_inject_interrupt_hv(struct kvm_vcpu *vcpu, int vec, u64 srr1_flags);
|
||||
|
||||
|
@ -523,7 +523,11 @@ struct kvm_vcpu_arch {
|
||||
struct kvmppc_book3s_shadow_vcpu *shadow_vcpu;
|
||||
#endif
|
||||
|
||||
struct pt_regs regs;
|
||||
/*
|
||||
* This is passed along to the HV via H_ENTER_NESTED. Align to
|
||||
* prevent it crossing a real 4K page.
|
||||
*/
|
||||
struct pt_regs regs __aligned(512);
|
||||
|
||||
struct thread_fp_state fp;
|
||||
|
||||
@ -830,11 +834,21 @@ struct kvm_vcpu_arch {
|
||||
#ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING
|
||||
struct kvmhv_tb_accumulator *cur_activity; /* What we're timing */
|
||||
u64 cur_tb_start; /* when it started */
|
||||
#ifdef CONFIG_KVM_BOOK3S_HV_P9_TIMING
|
||||
struct kvmhv_tb_accumulator vcpu_entry;
|
||||
struct kvmhv_tb_accumulator vcpu_exit;
|
||||
struct kvmhv_tb_accumulator in_guest;
|
||||
struct kvmhv_tb_accumulator hcall;
|
||||
struct kvmhv_tb_accumulator pg_fault;
|
||||
struct kvmhv_tb_accumulator guest_entry;
|
||||
struct kvmhv_tb_accumulator guest_exit;
|
||||
#else
|
||||
struct kvmhv_tb_accumulator rm_entry; /* real-mode entry code */
|
||||
struct kvmhv_tb_accumulator rm_intr; /* real-mode intr handling */
|
||||
struct kvmhv_tb_accumulator rm_exit; /* real-mode exit code */
|
||||
struct kvmhv_tb_accumulator guest_time; /* guest execution */
|
||||
struct kvmhv_tb_accumulator cede_time; /* time napping inside guest */
|
||||
#endif
|
||||
#endif /* CONFIG_KVM_BOOK3S_HV_EXIT_TIMING */
|
||||
};
|
||||
|
||||
|
@ -8,8 +8,6 @@
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/export.h>
|
||||
|
||||
#include <asm/setup.h>
|
||||
|
||||
struct pt_regs;
|
||||
struct pci_bus;
|
||||
struct device_node;
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <linux/mm.h>
|
||||
#include <linux/pkeys.h>
|
||||
#include <asm/cpu_has_feature.h>
|
||||
#include <asm/firmware.h>
|
||||
|
||||
static inline unsigned long arch_calc_vm_prot_bits(unsigned long prot,
|
||||
unsigned long pkey)
|
||||
|
@ -96,15 +96,6 @@
|
||||
*/
|
||||
#define MMU_FTR_NEED_DTLB_SW_LRU ASM_CONST(0x00200000)
|
||||
|
||||
/* Enable use of TLB reservation. Processor should support tlbsrx.
|
||||
* instruction and MAS0[WQ].
|
||||
*/
|
||||
#define MMU_FTR_USE_TLBRSRV ASM_CONST(0x00800000)
|
||||
|
||||
/* Use paired MAS registers (MAS7||MAS3, etc.)
|
||||
*/
|
||||
#define MMU_FTR_USE_PAIRED_MAS ASM_CONST(0x01000000)
|
||||
|
||||
/* Doesn't support the B bit (1T segment) in SLBIE
|
||||
*/
|
||||
#define MMU_FTR_NO_SLBIE_B ASM_CONST(0x02000000)
|
||||
@ -180,9 +171,6 @@ enum {
|
||||
#ifdef CONFIG_PPC_83xx
|
||||
MMU_FTR_NEED_DTLB_SW_LRU |
|
||||
#endif
|
||||
#ifdef CONFIG_PPC_BOOK3E_64
|
||||
MMU_FTR_USE_TLBRSRV | MMU_FTR_USE_PAIRED_MAS |
|
||||
#endif
|
||||
#ifdef CONFIG_PPC_BOOK3S_64
|
||||
MMU_FTR_KERNEL_RO |
|
||||
#ifdef CONFIG_PPC_64S_HASH_MMU
|
||||
|
@ -15,7 +15,6 @@
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#include <asm/types.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/mpc5xxx.h>
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
@ -268,13 +267,14 @@ struct mpc52xx_intr {
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
struct device_node;
|
||||
|
||||
/* mpc52xx_common.c */
|
||||
extern void mpc5200_setup_xlb_arbiter(void);
|
||||
extern void mpc52xx_declare_of_platform_devices(void);
|
||||
extern int mpc5200_psc_ac97_gpio_reset(int psc_number);
|
||||
extern void mpc52xx_map_common_devices(void);
|
||||
extern int mpc52xx_set_psc_clkdiv(int psc_id, int clkdiv);
|
||||
extern unsigned int mpc52xx_get_xtal_freq(struct device_node *node);
|
||||
extern void __noreturn mpc52xx_restart(char *cmd);
|
||||
|
||||
/* mpc52xx_gpt.c */
|
||||
|
@ -11,7 +11,14 @@
|
||||
#ifndef __ASM_POWERPC_MPC5xxx_H__
|
||||
#define __ASM_POWERPC_MPC5xxx_H__
|
||||
|
||||
extern unsigned long mpc5xxx_get_bus_frequency(struct device_node *node);
|
||||
#include <linux/property.h>
|
||||
|
||||
unsigned long mpc5xxx_fwnode_get_bus_frequency(struct fwnode_handle *fwnode);
|
||||
|
||||
static inline unsigned long mpc5xxx_get_bus_frequency(struct device *dev)
|
||||
{
|
||||
return mpc5xxx_fwnode_get_bus_frequency(dev_fwnode(dev));
|
||||
}
|
||||
|
||||
#endif /* __ASM_POWERPC_MPC5xxx_H__ */
|
||||
|
||||
|
@ -5,8 +5,10 @@
|
||||
#ifdef CONFIG_PPC_WATCHDOG
|
||||
extern void arch_touch_nmi_watchdog(void);
|
||||
long soft_nmi_interrupt(struct pt_regs *regs);
|
||||
void watchdog_nmi_set_timeout_pct(u64 pct);
|
||||
#else
|
||||
static inline void arch_touch_nmi_watchdog(void) {}
|
||||
static inline void watchdog_nmi_set_timeout_pct(u64 pct) {}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NMI_IPI
|
||||
|
@ -15,7 +15,10 @@ struct vmemmap_backing {
|
||||
};
|
||||
extern struct vmemmap_backing *vmemmap_list;
|
||||
|
||||
#define p4d_populate(MM, P4D, PUD) p4d_set(P4D, (unsigned long)PUD)
|
||||
static inline void p4d_populate(struct mm_struct *mm, p4d_t *p4d, pud_t *pud)
|
||||
{
|
||||
p4d_set(p4d, (unsigned long)pud);
|
||||
}
|
||||
|
||||
static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
|
||||
{
|
||||
|
@ -25,7 +25,7 @@
|
||||
/*
|
||||
* Define the address range of the kernel non-linear virtual area
|
||||
*/
|
||||
#define KERN_VIRT_START ASM_CONST(0x8000000000000000)
|
||||
#define KERN_VIRT_START ASM_CONST(0xc000100000000000)
|
||||
#define KERN_VIRT_SIZE ASM_CONST(0x0000100000000000)
|
||||
|
||||
/*
|
||||
@ -38,15 +38,16 @@
|
||||
#define VMALLOC_END (VMALLOC_START + VMALLOC_SIZE)
|
||||
|
||||
/*
|
||||
* The second half of the kernel virtual space is used for IO mappings,
|
||||
* The third quarter of the kernel virtual space is used for IO mappings,
|
||||
* it's itself carved into the PIO region (ISA and PHB IO space) and
|
||||
* the ioremap space
|
||||
*
|
||||
* ISA_IO_BASE = KERN_IO_START, 64K reserved area
|
||||
* PHB_IO_BASE = ISA_IO_BASE + 64K to ISA_IO_BASE + 2G, PHB IO spaces
|
||||
* IOREMAP_BASE = ISA_IO_BASE + 2G to VMALLOC_START + PGTABLE_RANGE
|
||||
* IOREMAP_BASE = ISA_IO_BASE + 2G to KERN_IO_START + KERN_IO_SIZE
|
||||
*/
|
||||
#define KERN_IO_START (KERN_VIRT_START + (KERN_VIRT_SIZE >> 1))
|
||||
#define KERN_IO_SIZE (KERN_VIRT_SIZE >> 2)
|
||||
#define FULL_IO_SIZE 0x80000000ul
|
||||
#define ISA_IO_BASE (KERN_IO_START)
|
||||
#define ISA_IO_END (KERN_IO_START + 0x10000ul)
|
||||
@ -54,21 +55,9 @@
|
||||
#define PHB_IO_END (KERN_IO_START + FULL_IO_SIZE)
|
||||
#define IOREMAP_BASE (PHB_IO_END)
|
||||
#define IOREMAP_START (ioremap_bot)
|
||||
#define IOREMAP_END (KERN_VIRT_START + KERN_VIRT_SIZE - FIXADDR_SIZE)
|
||||
#define IOREMAP_END (KERN_IO_START + KERN_IO_SIZE - FIXADDR_SIZE)
|
||||
#define FIXADDR_SIZE SZ_32M
|
||||
|
||||
|
||||
/*
|
||||
* Region IDs
|
||||
*/
|
||||
#define REGION_SHIFT 60UL
|
||||
#define REGION_MASK (0xfUL << REGION_SHIFT)
|
||||
#define REGION_ID(ea) (((unsigned long)(ea)) >> REGION_SHIFT)
|
||||
|
||||
#define VMALLOC_REGION_ID (REGION_ID(VMALLOC_START))
|
||||
#define KERNEL_REGION_ID (REGION_ID(PAGE_OFFSET))
|
||||
#define USER_REGION_ID (0UL)
|
||||
|
||||
/*
|
||||
* Defines the address of the vmemap area, in its own region on
|
||||
* after the vmalloc space on Book3E
|
||||
@ -83,8 +72,6 @@
|
||||
*/
|
||||
#include <asm/nohash/pte-book3e.h>
|
||||
|
||||
#define _PAGE_SAO 0
|
||||
|
||||
#define PTE_RPN_MASK (~((1UL << PTE_RPN_SHIFT) - 1))
|
||||
|
||||
/*
|
||||
|
@ -193,7 +193,7 @@ static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr,
|
||||
if (IS_ENABLED(CONFIG_PPC32) && IS_ENABLED(CONFIG_PTE_64BIT) && !percpu) {
|
||||
__asm__ __volatile__("\
|
||||
stw%X0 %2,%0\n\
|
||||
eieio\n\
|
||||
mbar\n\
|
||||
stw%X1 %L2,%1"
|
||||
: "=m" (*ptep), "=m" (*((unsigned char *)ptep+4))
|
||||
: "r" (pte) : "memory");
|
||||
|
@ -170,11 +170,15 @@ static inline struct pci_controller *pci_bus_to_host(const struct pci_bus *bus)
|
||||
return bus->sysdata;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PPC_PMAC
|
||||
extern int pci_device_from_OF_node(struct device_node *node,
|
||||
u8 *bus, u8 *devfn);
|
||||
#endif
|
||||
#ifndef CONFIG_PPC64
|
||||
|
||||
#ifdef CONFIG_PPC_CHRP
|
||||
extern void pci_create_OF_bus_map(void);
|
||||
#endif
|
||||
|
||||
#else /* CONFIG_PPC64 */
|
||||
|
||||
|
@ -14,7 +14,6 @@
|
||||
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/pci-bridge.h>
|
||||
|
||||
/* Return values for pci_controller_ops.probe_mode function */
|
||||
|
@ -43,11 +43,10 @@ static inline long extended_cede_processor(unsigned long latency_hint)
|
||||
set_cede_latency_hint(latency_hint);
|
||||
|
||||
rc = cede_processor();
|
||||
#ifdef CONFIG_PPC_IRQ_SOFT_MASK_DEBUG
|
||||
|
||||
/* Ensure that H_CEDE returns with IRQs on */
|
||||
if (WARN_ON(!(mfmsr() & MSR_EE)))
|
||||
if (WARN_ON(IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG) && !(mfmsr() & MSR_EE)))
|
||||
__hard_irq_enable();
|
||||
#endif
|
||||
|
||||
set_cede_latency_hint(old_latency_hint);
|
||||
|
||||
|
@ -290,7 +290,6 @@
|
||||
#define PPC_INST_STRING 0x7c00042a
|
||||
#define PPC_INST_STRING_MASK 0xfc0007fe
|
||||
#define PPC_INST_STRING_GEN_MASK 0xfc00067e
|
||||
#define PPC_INST_SETB 0x7c000100
|
||||
#define PPC_INST_STSWI 0x7c0005aa
|
||||
#define PPC_INST_STSWX 0x7c00052a
|
||||
#define PPC_INST_TRECHKPT 0x7c0007dd
|
||||
@ -581,6 +580,9 @@
|
||||
|
||||
#define PPC_RAW_BRANCH(offset) (0x48000000 | PPC_LI(offset))
|
||||
#define PPC_RAW_BL(offset) (0x48000001 | PPC_LI(offset))
|
||||
#define PPC_RAW_TW(t0, a, b) (0x7f000008 | ___PPC_RS(t0) | ___PPC_RA(a) | ___PPC_RB(b))
|
||||
#define PPC_RAW_TRAP() PPC_RAW_TW(31, 0, 0)
|
||||
#define PPC_RAW_SETB(t, bfa) (0x7c000100 | ___PPC_RT(t) | ___PPC_RA((bfa) << 2))
|
||||
|
||||
/* Deal with instructions that older assemblers aren't aware of */
|
||||
#define PPC_BCCTR_FLUSH stringify_in_c(.long PPC_INST_BCCTR_FLUSH)
|
||||
|
@ -9,9 +9,9 @@
|
||||
*/
|
||||
#include <linux/types.h>
|
||||
#include <asm/disassemble.h>
|
||||
#include <asm/ppc-opcode.h>
|
||||
|
||||
typedef u32 ppc_opcode_t;
|
||||
#define BREAKPOINT_INSTRUCTION 0x7fe00008 /* trap */
|
||||
#define BREAKPOINT_INSTRUCTION PPC_RAW_TRAP() /* trap */
|
||||
|
||||
/* Trap definitions per ISA */
|
||||
#define IS_TW(instr) (((instr) & 0xfc0007fe) == 0x7c000008)
|
||||
|
@ -12,15 +12,10 @@
|
||||
* Updates for PPC64 by Peter Bergner & David Engebretsen, IBM Corp.
|
||||
*/
|
||||
#include <linux/types.h>
|
||||
#include <asm/irq.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <asm/firmware.h>
|
||||
|
||||
/* These includes should be removed once implicit includes are cleaned up. */
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_fdt.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/platform_device.h>
|
||||
struct device_node;
|
||||
struct property;
|
||||
|
||||
#define OF_DT_BEGIN_NODE 0x1 /* Start of node, full name */
|
||||
#define OF_DT_END_NODE 0x2 /* End node */
|
||||
|
@ -12,7 +12,6 @@ extern unsigned long long memory_limit;
|
||||
extern void *zalloc_maybe_bootmem(size_t size, gfp_t mask);
|
||||
|
||||
struct device_node;
|
||||
extern void note_scsi_host(struct device_node *, void *);
|
||||
|
||||
/* Used in very early kernel initialization. */
|
||||
extern unsigned long reloc_offset(void);
|
||||
@ -85,6 +84,11 @@ void __init machine_init(u64 dt_ptr);
|
||||
void __init early_setup(unsigned long dt_ptr);
|
||||
void early_setup_secondary(void);
|
||||
|
||||
/* prom_init (OpenFirmware) */
|
||||
unsigned long __init prom_init(unsigned long r3, unsigned long r4,
|
||||
unsigned long pp, unsigned long r6,
|
||||
unsigned long r7, unsigned long kbase);
|
||||
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
|
||||
#endif /* _ASM_POWERPC_SETUP_H */
|
||||
|
@ -14,7 +14,10 @@ extern void do_lwsync_fixups(unsigned long value, void *fixup_start,
|
||||
|
||||
static inline void eieio(void)
|
||||
{
|
||||
__asm__ __volatile__ ("eieio" : : : "memory");
|
||||
if (IS_ENABLED(CONFIG_BOOKE))
|
||||
__asm__ __volatile__ ("mbar" : : : "memory");
|
||||
else
|
||||
__asm__ __volatile__ ("eieio" : : : "memory");
|
||||
}
|
||||
|
||||
static inline void isync(void)
|
||||
|
@ -2,7 +2,6 @@
|
||||
#ifndef _ARCH_POWERPC_UACCESS_H
|
||||
#define _ARCH_POWERPC_UACCESS_H
|
||||
|
||||
#include <asm/ppc_asm.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/extable.h>
|
||||
|
@ -12,7 +12,7 @@
|
||||
#include <linux/notifier.h>
|
||||
#include <asm/probes.h>
|
||||
|
||||
typedef ppc_opcode_t uprobe_opcode_t;
|
||||
typedef u32 uprobe_opcode_t;
|
||||
|
||||
#define MAX_UINSN_BYTES 8
|
||||
#define UPROBE_XOL_SLOT_BYTES (MAX_UINSN_BYTES)
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <asm/asm-compat.h>
|
||||
#include <asm/ppc_asm.h>
|
||||
#include <asm/extable.h>
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
|
||||
|
@ -54,6 +54,13 @@ CFLAGS_cputable.o += -DDISABLE_BRANCH_PROFILING
|
||||
CFLAGS_btext.o += -DDISABLE_BRANCH_PROFILING
|
||||
endif
|
||||
|
||||
#ifdef CONFIG_RANDOMIZE_KSTACK_OFFSET
|
||||
# Remove stack protector to avoid triggering unneeded stack canary
|
||||
# checks due to randomize_kstack_offset.
|
||||
CFLAGS_REMOVE_syscall.o = -fstack-protector -fstack-protector-strong
|
||||
CFLAGS_syscall.o += -fno-stack-protector
|
||||
#endif
|
||||
|
||||
obj-y := cputable.o syscalls.o \
|
||||
irq.o align.o signal_$(BITS).o pmc.o vdso.o \
|
||||
process.o systbl.o idle.o \
|
||||
@ -62,9 +69,9 @@ obj-y := cputable.o syscalls.o \
|
||||
udbg.o misc.o io.o misc_$(BITS).o \
|
||||
of_platform.o prom_parse.o firmware.o \
|
||||
hw_breakpoint_constraints.o interrupt.o \
|
||||
kdebugfs.o stacktrace.o
|
||||
kdebugfs.o stacktrace.o syscall.o
|
||||
obj-y += ptrace/
|
||||
obj-$(CONFIG_PPC64) += setup_64.o \
|
||||
obj-$(CONFIG_PPC64) += setup_64.o irq_64.o\
|
||||
paca.o nvram_64.o note.o
|
||||
obj-$(CONFIG_COMPAT) += sys_ppc32.o signal_32.o
|
||||
obj-$(CONFIG_VDSO32) += vdso32_wrapper.o
|
||||
|
@ -379,7 +379,7 @@ int main(void)
|
||||
OFFSET(VCPU_SPRG2, kvm_vcpu, arch.shregs.sprg2);
|
||||
OFFSET(VCPU_SPRG3, kvm_vcpu, arch.shregs.sprg3);
|
||||
#endif
|
||||
#ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING
|
||||
#ifdef CONFIG_KVM_BOOK3S_HV_P8_TIMING
|
||||
OFFSET(VCPU_TB_RMENTRY, kvm_vcpu, arch.rm_entry);
|
||||
OFFSET(VCPU_TB_RMINTR, kvm_vcpu, arch.rm_intr);
|
||||
OFFSET(VCPU_TB_RMEXIT, kvm_vcpu, arch.rm_exit);
|
||||
|
@ -73,7 +73,7 @@ static inline void rmci_maybe_off(void)
|
||||
* the display during identify_machine() and MMU_Init()
|
||||
*
|
||||
* The display is mapped to virtual address 0xD0000000, rather
|
||||
* than 1:1, because some some CHRP machines put the frame buffer
|
||||
* than 1:1, because some CHRP machines put the frame buffer
|
||||
* in the region starting at 0xC0000000 (PAGE_OFFSET).
|
||||
* This mapping is temporary and will disappear as soon as the
|
||||
* setup done by MMU_Init() is applied.
|
||||
|
@ -149,7 +149,6 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.pmc_type = PPC_PMC_IBM,
|
||||
.cpu_setup = __setup_cpu_ppc970,
|
||||
.cpu_restore = __restore_cpu_ppc970,
|
||||
.oprofile_cpu_type = "ppc64/970",
|
||||
.platform = "ppc970",
|
||||
},
|
||||
{ /* PPC970FX */
|
||||
@ -166,7 +165,6 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.pmc_type = PPC_PMC_IBM,
|
||||
.cpu_setup = __setup_cpu_ppc970,
|
||||
.cpu_restore = __restore_cpu_ppc970,
|
||||
.oprofile_cpu_type = "ppc64/970",
|
||||
.platform = "ppc970",
|
||||
},
|
||||
{ /* PPC970MP DD1.0 - no DEEPNAP, use regular 970 init */
|
||||
@ -183,7 +181,6 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.pmc_type = PPC_PMC_IBM,
|
||||
.cpu_setup = __setup_cpu_ppc970,
|
||||
.cpu_restore = __restore_cpu_ppc970,
|
||||
.oprofile_cpu_type = "ppc64/970MP",
|
||||
.platform = "ppc970",
|
||||
},
|
||||
{ /* PPC970MP */
|
||||
@ -200,7 +197,6 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.pmc_type = PPC_PMC_IBM,
|
||||
.cpu_setup = __setup_cpu_ppc970MP,
|
||||
.cpu_restore = __restore_cpu_ppc970,
|
||||
.oprofile_cpu_type = "ppc64/970MP",
|
||||
.platform = "ppc970",
|
||||
},
|
||||
{ /* PPC970GX */
|
||||
@ -216,7 +212,6 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.num_pmcs = 8,
|
||||
.pmc_type = PPC_PMC_IBM,
|
||||
.cpu_setup = __setup_cpu_ppc970,
|
||||
.oprofile_cpu_type = "ppc64/970",
|
||||
.platform = "ppc970",
|
||||
},
|
||||
{ /* Power5 GR */
|
||||
@ -230,7 +225,6 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.dcache_bsize = 128,
|
||||
.num_pmcs = 6,
|
||||
.pmc_type = PPC_PMC_IBM,
|
||||
.oprofile_cpu_type = "ppc64/power5",
|
||||
.platform = "power5",
|
||||
},
|
||||
{ /* Power5++ */
|
||||
@ -243,7 +237,6 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.icache_bsize = 128,
|
||||
.dcache_bsize = 128,
|
||||
.num_pmcs = 6,
|
||||
.oprofile_cpu_type = "ppc64/power5++",
|
||||
.platform = "power5+",
|
||||
},
|
||||
{ /* Power5 GS */
|
||||
@ -257,7 +250,6 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.dcache_bsize = 128,
|
||||
.num_pmcs = 6,
|
||||
.pmc_type = PPC_PMC_IBM,
|
||||
.oprofile_cpu_type = "ppc64/power5+",
|
||||
.platform = "power5+",
|
||||
},
|
||||
{ /* POWER6 in P5+ mode; 2.04-compliant processor */
|
||||
@ -269,7 +261,6 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.mmu_features = MMU_FTRS_POWER5,
|
||||
.icache_bsize = 128,
|
||||
.dcache_bsize = 128,
|
||||
.oprofile_cpu_type = "ppc64/ibm-compat-v1",
|
||||
.platform = "power5+",
|
||||
},
|
||||
{ /* Power6 */
|
||||
@ -284,7 +275,6 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.dcache_bsize = 128,
|
||||
.num_pmcs = 6,
|
||||
.pmc_type = PPC_PMC_IBM,
|
||||
.oprofile_cpu_type = "ppc64/power6",
|
||||
.platform = "power6x",
|
||||
},
|
||||
{ /* 2.05-compliant processor, i.e. Power6 "architected" mode */
|
||||
@ -296,7 +286,6 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.mmu_features = MMU_FTRS_POWER6,
|
||||
.icache_bsize = 128,
|
||||
.dcache_bsize = 128,
|
||||
.oprofile_cpu_type = "ppc64/ibm-compat-v1",
|
||||
.platform = "power6",
|
||||
},
|
||||
{ /* 2.06-compliant processor, i.e. Power7 "architected" mode */
|
||||
@ -309,7 +298,6 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.mmu_features = MMU_FTRS_POWER7,
|
||||
.icache_bsize = 128,
|
||||
.dcache_bsize = 128,
|
||||
.oprofile_cpu_type = "ppc64/ibm-compat-v1",
|
||||
.cpu_setup = __setup_cpu_power7,
|
||||
.cpu_restore = __restore_cpu_power7,
|
||||
.machine_check_early = __machine_check_early_realmode_p7,
|
||||
@ -325,7 +313,6 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.mmu_features = MMU_FTRS_POWER8,
|
||||
.icache_bsize = 128,
|
||||
.dcache_bsize = 128,
|
||||
.oprofile_cpu_type = "ppc64/ibm-compat-v1",
|
||||
.cpu_setup = __setup_cpu_power8,
|
||||
.cpu_restore = __restore_cpu_power8,
|
||||
.machine_check_early = __machine_check_early_realmode_p8,
|
||||
@ -341,7 +328,6 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.mmu_features = MMU_FTRS_POWER9,
|
||||
.icache_bsize = 128,
|
||||
.dcache_bsize = 128,
|
||||
.oprofile_cpu_type = "ppc64/ibm-compat-v1",
|
||||
.cpu_setup = __setup_cpu_power9,
|
||||
.cpu_restore = __restore_cpu_power9,
|
||||
.platform = "power9",
|
||||
@ -356,7 +342,6 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.mmu_features = MMU_FTRS_POWER10,
|
||||
.icache_bsize = 128,
|
||||
.dcache_bsize = 128,
|
||||
.oprofile_cpu_type = "ppc64/ibm-compat-v1",
|
||||
.cpu_setup = __setup_cpu_power10,
|
||||
.cpu_restore = __restore_cpu_power10,
|
||||
.platform = "power10",
|
||||
@ -373,7 +358,6 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.dcache_bsize = 128,
|
||||
.num_pmcs = 6,
|
||||
.pmc_type = PPC_PMC_IBM,
|
||||
.oprofile_cpu_type = "ppc64/power7",
|
||||
.cpu_setup = __setup_cpu_power7,
|
||||
.cpu_restore = __restore_cpu_power7,
|
||||
.machine_check_early = __machine_check_early_realmode_p7,
|
||||
@ -391,7 +375,6 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.dcache_bsize = 128,
|
||||
.num_pmcs = 6,
|
||||
.pmc_type = PPC_PMC_IBM,
|
||||
.oprofile_cpu_type = "ppc64/power7",
|
||||
.cpu_setup = __setup_cpu_power7,
|
||||
.cpu_restore = __restore_cpu_power7,
|
||||
.machine_check_early = __machine_check_early_realmode_p7,
|
||||
@ -409,7 +392,6 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.dcache_bsize = 128,
|
||||
.num_pmcs = 6,
|
||||
.pmc_type = PPC_PMC_IBM,
|
||||
.oprofile_cpu_type = "ppc64/power8",
|
||||
.cpu_setup = __setup_cpu_power8,
|
||||
.cpu_restore = __restore_cpu_power8,
|
||||
.machine_check_early = __machine_check_early_realmode_p8,
|
||||
@ -427,7 +409,6 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.dcache_bsize = 128,
|
||||
.num_pmcs = 6,
|
||||
.pmc_type = PPC_PMC_IBM,
|
||||
.oprofile_cpu_type = "ppc64/power8",
|
||||
.cpu_setup = __setup_cpu_power8,
|
||||
.cpu_restore = __restore_cpu_power8,
|
||||
.machine_check_early = __machine_check_early_realmode_p8,
|
||||
@ -445,7 +426,6 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.dcache_bsize = 128,
|
||||
.num_pmcs = 6,
|
||||
.pmc_type = PPC_PMC_IBM,
|
||||
.oprofile_cpu_type = "ppc64/power8",
|
||||
.cpu_setup = __setup_cpu_power8,
|
||||
.cpu_restore = __restore_cpu_power8,
|
||||
.machine_check_early = __machine_check_early_realmode_p8,
|
||||
@ -463,7 +443,6 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.dcache_bsize = 128,
|
||||
.num_pmcs = 6,
|
||||
.pmc_type = PPC_PMC_IBM,
|
||||
.oprofile_cpu_type = "ppc64/power9",
|
||||
.cpu_setup = __setup_cpu_power9,
|
||||
.cpu_restore = __restore_cpu_power9,
|
||||
.machine_check_early = __machine_check_early_realmode_p9,
|
||||
@ -481,7 +460,6 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.dcache_bsize = 128,
|
||||
.num_pmcs = 6,
|
||||
.pmc_type = PPC_PMC_IBM,
|
||||
.oprofile_cpu_type = "ppc64/power9",
|
||||
.cpu_setup = __setup_cpu_power9,
|
||||
.cpu_restore = __restore_cpu_power9,
|
||||
.machine_check_early = __machine_check_early_realmode_p9,
|
||||
@ -499,7 +477,6 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.dcache_bsize = 128,
|
||||
.num_pmcs = 6,
|
||||
.pmc_type = PPC_PMC_IBM,
|
||||
.oprofile_cpu_type = "ppc64/power9",
|
||||
.cpu_setup = __setup_cpu_power9,
|
||||
.cpu_restore = __restore_cpu_power9,
|
||||
.machine_check_early = __machine_check_early_realmode_p9,
|
||||
@ -517,7 +494,6 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.dcache_bsize = 128,
|
||||
.num_pmcs = 6,
|
||||
.pmc_type = PPC_PMC_IBM,
|
||||
.oprofile_cpu_type = "ppc64/power9",
|
||||
.cpu_setup = __setup_cpu_power9,
|
||||
.cpu_restore = __restore_cpu_power9,
|
||||
.machine_check_early = __machine_check_early_realmode_p9,
|
||||
@ -535,7 +511,6 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.dcache_bsize = 128,
|
||||
.num_pmcs = 6,
|
||||
.pmc_type = PPC_PMC_IBM,
|
||||
.oprofile_cpu_type = "ppc64/power10",
|
||||
.cpu_setup = __setup_cpu_power10,
|
||||
.cpu_restore = __restore_cpu_power10,
|
||||
.machine_check_early = __machine_check_early_realmode_p10,
|
||||
@ -554,7 +529,6 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.dcache_bsize = 128,
|
||||
.num_pmcs = 4,
|
||||
.pmc_type = PPC_PMC_IBM,
|
||||
.oprofile_cpu_type = "ppc64/cell-be",
|
||||
.platform = "ppc-cell-be",
|
||||
},
|
||||
{ /* PA Semi PA6T */
|
||||
@ -570,7 +544,6 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.pmc_type = PPC_PMC_PA6T,
|
||||
.cpu_setup = __setup_cpu_pa6t,
|
||||
.cpu_restore = __restore_cpu_pa6t,
|
||||
.oprofile_cpu_type = "ppc64/pa6t",
|
||||
.platform = "pa6t",
|
||||
},
|
||||
{ /* default match */
|
||||
@ -734,7 +707,6 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.cpu_setup = __setup_cpu_750,
|
||||
.machine_check = machine_check_generic,
|
||||
.platform = "ppc750",
|
||||
.oprofile_cpu_type = "ppc/750",
|
||||
},
|
||||
{ /* 745/755 */
|
||||
.pvr_mask = 0xfffff000,
|
||||
@ -765,7 +737,6 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.cpu_setup = __setup_cpu_750,
|
||||
.machine_check = machine_check_generic,
|
||||
.platform = "ppc750",
|
||||
.oprofile_cpu_type = "ppc/750",
|
||||
},
|
||||
{ /* 750FX rev 2.0 must disable HID0[DPM] */
|
||||
.pvr_mask = 0xffffffff,
|
||||
@ -781,7 +752,6 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.cpu_setup = __setup_cpu_750,
|
||||
.machine_check = machine_check_generic,
|
||||
.platform = "ppc750",
|
||||
.oprofile_cpu_type = "ppc/750",
|
||||
},
|
||||
{ /* 750FX (All revs except 2.0) */
|
||||
.pvr_mask = 0xffff0000,
|
||||
@ -797,7 +767,6 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.cpu_setup = __setup_cpu_750fx,
|
||||
.machine_check = machine_check_generic,
|
||||
.platform = "ppc750",
|
||||
.oprofile_cpu_type = "ppc/750",
|
||||
},
|
||||
{ /* 750GX */
|
||||
.pvr_mask = 0xffff0000,
|
||||
@ -813,7 +782,6 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.cpu_setup = __setup_cpu_750fx,
|
||||
.machine_check = machine_check_generic,
|
||||
.platform = "ppc750",
|
||||
.oprofile_cpu_type = "ppc/750",
|
||||
},
|
||||
{ /* 740/750 (L2CR bit need fixup for 740) */
|
||||
.pvr_mask = 0xffff0000,
|
||||
@ -891,7 +859,6 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.num_pmcs = 6,
|
||||
.pmc_type = PPC_PMC_G4,
|
||||
.cpu_setup = __setup_cpu_745x,
|
||||
.oprofile_cpu_type = "ppc/7450",
|
||||
.machine_check = machine_check_generic,
|
||||
.platform = "ppc7450",
|
||||
},
|
||||
@ -908,7 +875,6 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.num_pmcs = 6,
|
||||
.pmc_type = PPC_PMC_G4,
|
||||
.cpu_setup = __setup_cpu_745x,
|
||||
.oprofile_cpu_type = "ppc/7450",
|
||||
.machine_check = machine_check_generic,
|
||||
.platform = "ppc7450",
|
||||
},
|
||||
@ -925,7 +891,6 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.num_pmcs = 6,
|
||||
.pmc_type = PPC_PMC_G4,
|
||||
.cpu_setup = __setup_cpu_745x,
|
||||
.oprofile_cpu_type = "ppc/7450",
|
||||
.machine_check = machine_check_generic,
|
||||
.platform = "ppc7450",
|
||||
},
|
||||
@ -942,7 +907,6 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.num_pmcs = 6,
|
||||
.pmc_type = PPC_PMC_G4,
|
||||
.cpu_setup = __setup_cpu_745x,
|
||||
.oprofile_cpu_type = "ppc/7450",
|
||||
.machine_check = machine_check_generic,
|
||||
.platform = "ppc7450",
|
||||
},
|
||||
@ -959,7 +923,6 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.num_pmcs = 6,
|
||||
.pmc_type = PPC_PMC_G4,
|
||||
.cpu_setup = __setup_cpu_745x,
|
||||
.oprofile_cpu_type = "ppc/7450",
|
||||
.machine_check = machine_check_generic,
|
||||
.platform = "ppc7450",
|
||||
},
|
||||
@ -976,7 +939,6 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.num_pmcs = 6,
|
||||
.pmc_type = PPC_PMC_G4,
|
||||
.cpu_setup = __setup_cpu_745x,
|
||||
.oprofile_cpu_type = "ppc/7450",
|
||||
.machine_check = machine_check_generic,
|
||||
.platform = "ppc7450",
|
||||
},
|
||||
@ -993,7 +955,6 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.num_pmcs = 6,
|
||||
.pmc_type = PPC_PMC_G4,
|
||||
.cpu_setup = __setup_cpu_745x,
|
||||
.oprofile_cpu_type = "ppc/7450",
|
||||
.machine_check = machine_check_generic,
|
||||
.platform = "ppc7450",
|
||||
},
|
||||
@ -1010,7 +971,6 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.num_pmcs = 6,
|
||||
.pmc_type = PPC_PMC_G4,
|
||||
.cpu_setup = __setup_cpu_745x,
|
||||
.oprofile_cpu_type = "ppc/7450",
|
||||
.machine_check = machine_check_generic,
|
||||
.platform = "ppc7450",
|
||||
},
|
||||
@ -1026,7 +986,6 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.num_pmcs = 6,
|
||||
.pmc_type = PPC_PMC_G4,
|
||||
.cpu_setup = __setup_cpu_745x,
|
||||
.oprofile_cpu_type = "ppc/7450",
|
||||
.machine_check = machine_check_generic,
|
||||
.platform = "ppc7450",
|
||||
},
|
||||
@ -1043,7 +1002,6 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.num_pmcs = 6,
|
||||
.pmc_type = PPC_PMC_G4,
|
||||
.cpu_setup = __setup_cpu_745x,
|
||||
.oprofile_cpu_type = "ppc/7450",
|
||||
.machine_check = machine_check_generic,
|
||||
.platform = "ppc7450",
|
||||
},
|
||||
@ -1060,7 +1018,6 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.num_pmcs = 6,
|
||||
.pmc_type = PPC_PMC_G4,
|
||||
.cpu_setup = __setup_cpu_745x,
|
||||
.oprofile_cpu_type = "ppc/7450",
|
||||
.machine_check = machine_check_generic,
|
||||
.platform = "ppc7450",
|
||||
},
|
||||
@ -1172,7 +1129,6 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.cpu_setup = __setup_cpu_603,
|
||||
.machine_check = machine_check_83xx,
|
||||
.num_pmcs = 4,
|
||||
.oprofile_cpu_type = "ppc/e300",
|
||||
.platform = "ppc603",
|
||||
},
|
||||
{ /* e300c4 (e300c1, plus one IU) */
|
||||
@ -1188,7 +1144,6 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.cpu_setup = __setup_cpu_603,
|
||||
.machine_check = machine_check_83xx,
|
||||
.num_pmcs = 4,
|
||||
.oprofile_cpu_type = "ppc/e300",
|
||||
.platform = "ppc603",
|
||||
},
|
||||
#endif
|
||||
@ -1884,7 +1839,6 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.icache_bsize = 32,
|
||||
.dcache_bsize = 32,
|
||||
.num_pmcs = 4,
|
||||
.oprofile_cpu_type = "ppc/e500",
|
||||
.cpu_setup = __setup_cpu_e500v1,
|
||||
.machine_check = machine_check_e500,
|
||||
.platform = "ppc8540",
|
||||
@ -1903,7 +1857,6 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.icache_bsize = 32,
|
||||
.dcache_bsize = 32,
|
||||
.num_pmcs = 4,
|
||||
.oprofile_cpu_type = "ppc/e500",
|
||||
.cpu_setup = __setup_cpu_e500v2,
|
||||
.machine_check = machine_check_e500,
|
||||
.platform = "ppc8548",
|
||||
@ -1922,7 +1875,6 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.icache_bsize = 64,
|
||||
.dcache_bsize = 64,
|
||||
.num_pmcs = 4,
|
||||
.oprofile_cpu_type = "ppc/e500mc",
|
||||
.cpu_setup = __setup_cpu_e500mc,
|
||||
.machine_check = machine_check_e500mc,
|
||||
.platform = "ppce500mc",
|
||||
@ -1943,7 +1895,6 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.icache_bsize = 64,
|
||||
.dcache_bsize = 64,
|
||||
.num_pmcs = 4,
|
||||
.oprofile_cpu_type = "ppc/e500mc",
|
||||
.cpu_setup = __setup_cpu_e5500,
|
||||
#ifndef CONFIG_PPC32
|
||||
.cpu_restore = __restore_cpu_e5500,
|
||||
@ -1965,7 +1916,6 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
||||
.icache_bsize = 64,
|
||||
.dcache_bsize = 64,
|
||||
.num_pmcs = 6,
|
||||
.oprofile_cpu_type = "ppc/e6500",
|
||||
.cpu_setup = __setup_cpu_e6500,
|
||||
#ifndef CONFIG_PPC32
|
||||
.cpu_restore = __restore_cpu_e6500,
|
||||
@ -2033,23 +1983,10 @@ static struct cpu_spec * __init setup_cpu_spec(unsigned long offset,
|
||||
t->pmc_type = old.pmc_type;
|
||||
|
||||
/*
|
||||
* If we have passed through this logic once before and
|
||||
* have pulled the default case because the real PVR was
|
||||
* not found inside cpu_specs[], then we are possibly
|
||||
* running in compatibility mode. In that case, let the
|
||||
* oprofiler know which set of compatibility counters to
|
||||
* pull from by making sure the oprofile_cpu_type string
|
||||
* is set to that of compatibility mode. If the
|
||||
* oprofile_cpu_type already has a value, then we are
|
||||
* possibly overriding a real PVR with a logical one,
|
||||
* and, in that case, keep the current value for
|
||||
* oprofile_cpu_type. Furthermore, let's ensure that the
|
||||
* Let's ensure that the
|
||||
* fix for the PMAO bug is enabled on compatibility mode.
|
||||
*/
|
||||
if (old.oprofile_cpu_type != NULL) {
|
||||
t->oprofile_cpu_type = old.oprofile_cpu_type;
|
||||
t->cpu_features |= old.cpu_features & CPU_FTR_PMAO_BUG;
|
||||
}
|
||||
t->cpu_features |= old.cpu_features & CPU_FTR_PMAO_BUG;
|
||||
}
|
||||
|
||||
*PTRRELOC(&cur_cpu_spec) = &the_cpu_spec;
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <linux/debugfs.h>
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/hvcall.h>
|
||||
#include <asm/firmware.h>
|
||||
|
||||
bool dawr_force_enable;
|
||||
EXPORT_SYMBOL_GPL(dawr_force_enable);
|
||||
|
@ -102,7 +102,6 @@ static struct cpu_spec __initdata base_cpu_spec = {
|
||||
.dcache_bsize = 32, /* cache info init. */
|
||||
.num_pmcs = 0,
|
||||
.pmc_type = PPC_PMC_DEFAULT,
|
||||
.oprofile_cpu_type = NULL,
|
||||
.cpu_setup = NULL,
|
||||
.cpu_restore = __restore_cpu_cpufeatures,
|
||||
.machine_check_early = NULL,
|
||||
@ -387,7 +386,6 @@ static int __init feat_enable_pmu_power8(struct dt_cpu_feature *f)
|
||||
|
||||
cur_cpu_spec->num_pmcs = 6;
|
||||
cur_cpu_spec->pmc_type = PPC_PMC_IBM;
|
||||
cur_cpu_spec->oprofile_cpu_type = "ppc64/power8";
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -423,7 +421,6 @@ static int __init feat_enable_pmu_power9(struct dt_cpu_feature *f)
|
||||
|
||||
cur_cpu_spec->num_pmcs = 6;
|
||||
cur_cpu_spec->pmc_type = PPC_PMC_IBM;
|
||||
cur_cpu_spec->oprofile_cpu_type = "ppc64/power9";
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -449,7 +446,6 @@ static int __init feat_enable_pmu_power10(struct dt_cpu_feature *f)
|
||||
|
||||
cur_cpu_spec->num_pmcs = 6;
|
||||
cur_cpu_spec->pmc_type = PPC_PMC_IBM;
|
||||
cur_cpu_spec->oprofile_cpu_type = "ppc64/power10";
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -750,7 +750,7 @@ static void eeh_pe_cleanup(struct eeh_pe *pe)
|
||||
* @pdev: pci_dev to check
|
||||
*
|
||||
* This function may return a false positive if we can't determine the slot's
|
||||
* presence state. This might happen for for PCIe slots if the PE containing
|
||||
* presence state. This might happen for PCIe slots if the PE containing
|
||||
* the upstream bridge is also frozen, or the bridge is part of the same PE
|
||||
* as the device.
|
||||
*
|
||||
|
@ -2779,7 +2779,7 @@ EXC_COMMON_BEGIN(soft_nmi_common)
|
||||
|
||||
/*
|
||||
* An interrupt came in while soft-disabled. We set paca->irq_happened, then:
|
||||
* - If it was a decrementer interrupt, we bump the dec to max and and return.
|
||||
* - If it was a decrementer interrupt, we bump the dec to max and return.
|
||||
* - If it was a doorbell we return immediately since doorbells are edge
|
||||
* triggered and won't automatically refire.
|
||||
* - If it was a HMI we return immediately since we handled it in realmode
|
||||
|
@ -965,6 +965,9 @@ start_here_multiplatform:
|
||||
* and SLB setup before we turn on relocation.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_KASAN
|
||||
bl kasan_early_init
|
||||
#endif
|
||||
/* Restore parameters passed from prom_init/kexec */
|
||||
mr r3,r31
|
||||
LOAD_REG_ADDR(r12, DOTSYM(early_setup))
|
||||
|
@ -418,14 +418,14 @@ InstructionTLBMiss:
|
||||
*/
|
||||
/* Get PTE (linux-style) and check access */
|
||||
mfspr r3,SPRN_IMISS
|
||||
#if defined(CONFIG_MODULES) || defined(CONFIG_DEBUG_PAGEALLOC) || defined(CONFIG_KFENCE)
|
||||
#ifdef CONFIG_MODULES
|
||||
lis r1, TASK_SIZE@h /* check if kernel address */
|
||||
cmplw 0,r1,r3
|
||||
#endif
|
||||
mfspr r2, SPRN_SDR1
|
||||
li r1,_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_EXEC | _PAGE_USER
|
||||
rlwinm r2, r2, 28, 0xfffff000
|
||||
#if defined(CONFIG_MODULES) || defined(CONFIG_DEBUG_PAGEALLOC) || defined(CONFIG_KFENCE)
|
||||
#ifdef CONFIG_MODULES
|
||||
bgt- 112f
|
||||
lis r2, (swapper_pg_dir - PAGE_OFFSET)@ha /* if kernel address, use */
|
||||
li r1,_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_EXEC
|
||||
|
@ -24,8 +24,6 @@
|
||||
unsigned long global_dbcr0[NR_CPUS];
|
||||
#endif
|
||||
|
||||
typedef long (*syscall_fn)(long, long, long, long, long, long);
|
||||
|
||||
#ifdef CONFIG_PPC_BOOK3S_64
|
||||
DEFINE_STATIC_KEY_FALSE(interrupt_exit_not_reentrant);
|
||||
static inline bool exit_must_hard_disable(void)
|
||||
@ -73,165 +71,6 @@ static notrace __always_inline bool prep_irq_for_enabled_exit(bool restartable)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Has to run notrace because it is entered not completely "reconciled" */
|
||||
notrace long system_call_exception(long r3, long r4, long r5,
|
||||
long r6, long r7, long r8,
|
||||
unsigned long r0, struct pt_regs *regs)
|
||||
{
|
||||
syscall_fn f;
|
||||
|
||||
kuap_lock();
|
||||
|
||||
regs->orig_gpr3 = r3;
|
||||
|
||||
if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG))
|
||||
BUG_ON(irq_soft_mask_return() != IRQS_ALL_DISABLED);
|
||||
|
||||
trace_hardirqs_off(); /* finish reconciling */
|
||||
|
||||
CT_WARN_ON(ct_state() == CONTEXT_KERNEL);
|
||||
user_exit_irqoff();
|
||||
|
||||
BUG_ON(regs_is_unrecoverable(regs));
|
||||
BUG_ON(!(regs->msr & MSR_PR));
|
||||
BUG_ON(arch_irq_disabled_regs(regs));
|
||||
|
||||
#ifdef CONFIG_PPC_PKEY
|
||||
if (mmu_has_feature(MMU_FTR_PKEY)) {
|
||||
unsigned long amr, iamr;
|
||||
bool flush_needed = false;
|
||||
/*
|
||||
* When entering from userspace we mostly have the AMR/IAMR
|
||||
* different from kernel default values. Hence don't compare.
|
||||
*/
|
||||
amr = mfspr(SPRN_AMR);
|
||||
iamr = mfspr(SPRN_IAMR);
|
||||
regs->amr = amr;
|
||||
regs->iamr = iamr;
|
||||
if (mmu_has_feature(MMU_FTR_BOOK3S_KUAP)) {
|
||||
mtspr(SPRN_AMR, AMR_KUAP_BLOCKED);
|
||||
flush_needed = true;
|
||||
}
|
||||
if (mmu_has_feature(MMU_FTR_BOOK3S_KUEP)) {
|
||||
mtspr(SPRN_IAMR, AMR_KUEP_BLOCKED);
|
||||
flush_needed = true;
|
||||
}
|
||||
if (flush_needed)
|
||||
isync();
|
||||
} else
|
||||
#endif
|
||||
kuap_assert_locked();
|
||||
|
||||
booke_restore_dbcr0();
|
||||
|
||||
account_cpu_user_entry();
|
||||
|
||||
account_stolen_time();
|
||||
|
||||
/*
|
||||
* This is not required for the syscall exit path, but makes the
|
||||
* stack frame look nicer. If this was initialised in the first stack
|
||||
* frame, or if the unwinder was taught the first stack frame always
|
||||
* returns to user with IRQS_ENABLED, this store could be avoided!
|
||||
*/
|
||||
irq_soft_mask_regs_set_state(regs, IRQS_ENABLED);
|
||||
|
||||
/*
|
||||
* If system call is called with TM active, set _TIF_RESTOREALL to
|
||||
* prevent RFSCV being used to return to userspace, because POWER9
|
||||
* TM implementation has problems with this instruction returning to
|
||||
* transactional state. Final register values are not relevant because
|
||||
* the transaction will be aborted upon return anyway. Or in the case
|
||||
* of unsupported_scv SIGILL fault, the return state does not much
|
||||
* matter because it's an edge case.
|
||||
*/
|
||||
if (IS_ENABLED(CONFIG_PPC_TRANSACTIONAL_MEM) &&
|
||||
unlikely(MSR_TM_TRANSACTIONAL(regs->msr)))
|
||||
set_bits(_TIF_RESTOREALL, ¤t_thread_info()->flags);
|
||||
|
||||
/*
|
||||
* If the system call was made with a transaction active, doom it and
|
||||
* return without performing the system call. Unless it was an
|
||||
* unsupported scv vector, in which case it's treated like an illegal
|
||||
* instruction.
|
||||
*/
|
||||
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
|
||||
if (unlikely(MSR_TM_TRANSACTIONAL(regs->msr)) &&
|
||||
!trap_is_unsupported_scv(regs)) {
|
||||
/* Enable TM in the kernel, and disable EE (for scv) */
|
||||
hard_irq_disable();
|
||||
mtmsr(mfmsr() | MSR_TM);
|
||||
|
||||
/* tabort, this dooms the transaction, nothing else */
|
||||
asm volatile(".long 0x7c00071d | ((%0) << 16)"
|
||||
:: "r"(TM_CAUSE_SYSCALL|TM_CAUSE_PERSISTENT));
|
||||
|
||||
/*
|
||||
* Userspace will never see the return value. Execution will
|
||||
* resume after the tbegin. of the aborted transaction with the
|
||||
* checkpointed register state. A context switch could occur
|
||||
* or signal delivered to the process before resuming the
|
||||
* doomed transaction context, but that should all be handled
|
||||
* as expected.
|
||||
*/
|
||||
return -ENOSYS;
|
||||
}
|
||||
#endif // CONFIG_PPC_TRANSACTIONAL_MEM
|
||||
|
||||
local_irq_enable();
|
||||
|
||||
if (unlikely(read_thread_flags() & _TIF_SYSCALL_DOTRACE)) {
|
||||
if (unlikely(trap_is_unsupported_scv(regs))) {
|
||||
/* Unsupported scv vector */
|
||||
_exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
|
||||
return regs->gpr[3];
|
||||
}
|
||||
/*
|
||||
* We use the return value of do_syscall_trace_enter() as the
|
||||
* syscall number. If the syscall was rejected for any reason
|
||||
* do_syscall_trace_enter() returns an invalid syscall number
|
||||
* and the test against NR_syscalls will fail and the return
|
||||
* value to be used is in regs->gpr[3].
|
||||
*/
|
||||
r0 = do_syscall_trace_enter(regs);
|
||||
if (unlikely(r0 >= NR_syscalls))
|
||||
return regs->gpr[3];
|
||||
r3 = regs->gpr[3];
|
||||
r4 = regs->gpr[4];
|
||||
r5 = regs->gpr[5];
|
||||
r6 = regs->gpr[6];
|
||||
r7 = regs->gpr[7];
|
||||
r8 = regs->gpr[8];
|
||||
|
||||
} else if (unlikely(r0 >= NR_syscalls)) {
|
||||
if (unlikely(trap_is_unsupported_scv(regs))) {
|
||||
/* Unsupported scv vector */
|
||||
_exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
|
||||
return regs->gpr[3];
|
||||
}
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
/* May be faster to do array_index_nospec? */
|
||||
barrier_nospec();
|
||||
|
||||
if (unlikely(is_compat_task())) {
|
||||
f = (void *)compat_sys_call_table[r0];
|
||||
|
||||
r3 &= 0x00000000ffffffffULL;
|
||||
r4 &= 0x00000000ffffffffULL;
|
||||
r5 &= 0x00000000ffffffffULL;
|
||||
r6 &= 0x00000000ffffffffULL;
|
||||
r7 &= 0x00000000ffffffffULL;
|
||||
r8 &= 0x00000000ffffffffULL;
|
||||
|
||||
} else {
|
||||
f = (void *)sys_call_table[r0];
|
||||
}
|
||||
|
||||
return f(r3, r4, r5, r6, r7, r8);
|
||||
}
|
||||
|
||||
static notrace void booke_load_dbcr0(void)
|
||||
{
|
||||
#ifdef CONFIG_PPC_ADV_DEBUG_REGS
|
||||
|
@ -775,6 +775,11 @@ bool iommu_table_in_use(struct iommu_table *tbl)
|
||||
/* ignore reserved bit0 */
|
||||
if (tbl->it_offset == 0)
|
||||
start = 1;
|
||||
|
||||
/* Simple case with no reserved MMIO32 region */
|
||||
if (!tbl->it_reserved_start && !tbl->it_reserved_end)
|
||||
return find_next_bit(tbl->it_map, tbl->it_size, start) != tbl->it_size;
|
||||
|
||||
end = tbl->it_reserved_start - tbl->it_offset;
|
||||
if (find_next_bit(tbl->it_map, end, start) != end)
|
||||
return true;
|
||||
|
@ -65,13 +65,8 @@
|
||||
#include <asm/smp.h>
|
||||
#include <asm/hw_irq.h>
|
||||
#include <asm/softirq_stack.h>
|
||||
#include <asm/ppc_asm.h>
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
#include <asm/paca.h>
|
||||
#include <asm/firmware.h>
|
||||
#include <asm/lv1call.h>
|
||||
#include <asm/dbell.h>
|
||||
#endif
|
||||
#define CREATE_TRACE_POINTS
|
||||
#include <asm/trace.h>
|
||||
#include <asm/cpu_has_feature.h>
|
||||
@ -88,411 +83,6 @@ u32 tau_interrupts(unsigned long cpu);
|
||||
#endif
|
||||
#endif /* CONFIG_PPC32 */
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
|
||||
int distribute_irqs = 1;
|
||||
|
||||
static inline notrace unsigned long get_irq_happened(void)
|
||||
{
|
||||
unsigned long happened;
|
||||
|
||||
__asm__ __volatile__("lbz %0,%1(13)"
|
||||
: "=r" (happened) : "i" (offsetof(struct paca_struct, irq_happened)));
|
||||
|
||||
return happened;
|
||||
}
|
||||
|
||||
void replay_soft_interrupts(void)
|
||||
{
|
||||
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.
|
||||
*
|
||||
* We use local_paca rather than get_paca() to avoid all the
|
||||
* debug_smp_processor_id() business in this low level function.
|
||||
*/
|
||||
|
||||
ppc_save_regs(®s);
|
||||
regs.softe = IRQS_ENABLED;
|
||||
regs.msr |= MSR_EE;
|
||||
|
||||
again:
|
||||
if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG))
|
||||
WARN_ON_ONCE(mfmsr() & MSR_EE);
|
||||
|
||||
/*
|
||||
* Force the delivery of pending soft-disabled interrupts on PS3.
|
||||
* Any HV call will have this side effect.
|
||||
*/
|
||||
if (firmware_has_feature(FW_FEATURE_PS3_LV1)) {
|
||||
u64 tmp, tmp2;
|
||||
lv1_get_version_info(&tmp, &tmp2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if an hypervisor Maintenance interrupt happened.
|
||||
* This is a higher priority interrupt than the others, so
|
||||
* replay it first.
|
||||
*/
|
||||
if (IS_ENABLED(CONFIG_PPC_BOOK3S) && (local_paca->irq_happened & PACA_IRQ_HMI)) {
|
||||
local_paca->irq_happened &= ~PACA_IRQ_HMI;
|
||||
regs.trap = INTERRUPT_HMI;
|
||||
handle_hmi_exception(®s);
|
||||
if (!(local_paca->irq_happened & PACA_IRQ_HARD_DIS))
|
||||
hard_irq_disable();
|
||||
}
|
||||
|
||||
if (local_paca->irq_happened & PACA_IRQ_DEC) {
|
||||
local_paca->irq_happened &= ~PACA_IRQ_DEC;
|
||||
regs.trap = INTERRUPT_DECREMENTER;
|
||||
timer_interrupt(®s);
|
||||
if (!(local_paca->irq_happened & PACA_IRQ_HARD_DIS))
|
||||
hard_irq_disable();
|
||||
}
|
||||
|
||||
if (local_paca->irq_happened & PACA_IRQ_EE) {
|
||||
local_paca->irq_happened &= ~PACA_IRQ_EE;
|
||||
regs.trap = INTERRUPT_EXTERNAL;
|
||||
do_IRQ(®s);
|
||||
if (!(local_paca->irq_happened & PACA_IRQ_HARD_DIS))
|
||||
hard_irq_disable();
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_PPC_DOORBELL) && (local_paca->irq_happened & PACA_IRQ_DBELL)) {
|
||||
local_paca->irq_happened &= ~PACA_IRQ_DBELL;
|
||||
regs.trap = INTERRUPT_DOORBELL;
|
||||
doorbell_exception(®s);
|
||||
if (!(local_paca->irq_happened & PACA_IRQ_HARD_DIS))
|
||||
hard_irq_disable();
|
||||
}
|
||||
|
||||
/* Book3E does not support soft-masking PMI interrupts */
|
||||
if (IS_ENABLED(CONFIG_PPC_BOOK3S) && (local_paca->irq_happened & PACA_IRQ_PMI)) {
|
||||
local_paca->irq_happened &= ~PACA_IRQ_PMI;
|
||||
regs.trap = INTERRUPT_PERFMON;
|
||||
performance_monitor_exception(®s);
|
||||
if (!(local_paca->irq_happened & PACA_IRQ_HARD_DIS))
|
||||
hard_irq_disable();
|
||||
}
|
||||
|
||||
if (local_paca->irq_happened & ~PACA_IRQ_HARD_DIS) {
|
||||
/*
|
||||
* We are responding to the next interrupt, so interrupt-off
|
||||
* latencies should be reset here.
|
||||
*/
|
||||
trace_hardirqs_on();
|
||||
trace_hardirqs_off();
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_PPC_BOOK3S_64) && defined(CONFIG_PPC_KUAP)
|
||||
static inline void replay_soft_interrupts_irqrestore(void)
|
||||
{
|
||||
unsigned long kuap_state = get_kuap();
|
||||
|
||||
/*
|
||||
* Check if anything calls local_irq_enable/restore() when KUAP is
|
||||
* disabled (user access enabled). We handle that case here by saving
|
||||
* and re-locking AMR but we shouldn't get here in the first place,
|
||||
* hence the warning.
|
||||
*/
|
||||
kuap_assert_locked();
|
||||
|
||||
if (kuap_state != AMR_KUAP_BLOCKED)
|
||||
set_kuap(AMR_KUAP_BLOCKED);
|
||||
|
||||
replay_soft_interrupts();
|
||||
|
||||
if (kuap_state != AMR_KUAP_BLOCKED)
|
||||
set_kuap(kuap_state);
|
||||
}
|
||||
#else
|
||||
#define replay_soft_interrupts_irqrestore() replay_soft_interrupts()
|
||||
#endif
|
||||
|
||||
notrace void arch_local_irq_restore(unsigned long mask)
|
||||
{
|
||||
unsigned char irq_happened;
|
||||
|
||||
/* Write the new soft-enabled value if it is a disable */
|
||||
if (mask) {
|
||||
irq_soft_mask_set(mask);
|
||||
return;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG))
|
||||
WARN_ON_ONCE(in_nmi() || in_hardirq());
|
||||
|
||||
/*
|
||||
* After the stb, interrupts are unmasked and there are no interrupts
|
||||
* pending replay. The restart sequence makes this atomic with
|
||||
* respect to soft-masked interrupts. If this was just a simple code
|
||||
* sequence, a soft-masked interrupt could become pending right after
|
||||
* the comparison and before the stb.
|
||||
*
|
||||
* This allows interrupts to be unmasked without hard disabling, and
|
||||
* also without new hard interrupts coming in ahead of pending ones.
|
||||
*/
|
||||
asm_volatile_goto(
|
||||
"1: \n"
|
||||
" lbz 9,%0(13) \n"
|
||||
" cmpwi 9,0 \n"
|
||||
" bne %l[happened] \n"
|
||||
" stb 9,%1(13) \n"
|
||||
"2: \n"
|
||||
RESTART_TABLE(1b, 2b, 1b)
|
||||
: : "i" (offsetof(struct paca_struct, irq_happened)),
|
||||
"i" (offsetof(struct paca_struct, irq_soft_mask))
|
||||
: "cr0", "r9"
|
||||
: happened);
|
||||
|
||||
if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG))
|
||||
WARN_ON_ONCE(!(mfmsr() & MSR_EE));
|
||||
|
||||
return;
|
||||
|
||||
happened:
|
||||
irq_happened = get_irq_happened();
|
||||
if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG))
|
||||
WARN_ON_ONCE(!irq_happened);
|
||||
|
||||
if (irq_happened == PACA_IRQ_HARD_DIS) {
|
||||
if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG))
|
||||
WARN_ON_ONCE(mfmsr() & MSR_EE);
|
||||
irq_soft_mask_set(IRQS_ENABLED);
|
||||
local_paca->irq_happened = 0;
|
||||
__hard_irq_enable();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Have interrupts to replay, need to hard disable first */
|
||||
if (!(irq_happened & PACA_IRQ_HARD_DIS)) {
|
||||
if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG)) {
|
||||
if (!(mfmsr() & MSR_EE)) {
|
||||
/*
|
||||
* An interrupt could have come in and cleared
|
||||
* MSR[EE] and set IRQ_HARD_DIS, so check
|
||||
* IRQ_HARD_DIS again and warn if it is still
|
||||
* clear.
|
||||
*/
|
||||
irq_happened = get_irq_happened();
|
||||
WARN_ON_ONCE(!(irq_happened & PACA_IRQ_HARD_DIS));
|
||||
}
|
||||
}
|
||||
__hard_irq_disable();
|
||||
local_paca->irq_happened |= PACA_IRQ_HARD_DIS;
|
||||
} else {
|
||||
if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG)) {
|
||||
if (WARN_ON_ONCE(mfmsr() & MSR_EE))
|
||||
__hard_irq_disable();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable preempt here, so that the below preempt_enable will
|
||||
* perform resched if required (a replayed interrupt may set
|
||||
* need_resched).
|
||||
*/
|
||||
preempt_disable();
|
||||
irq_soft_mask_set(IRQS_ALL_DISABLED);
|
||||
trace_hardirqs_off();
|
||||
|
||||
replay_soft_interrupts_irqrestore();
|
||||
local_paca->irq_happened = 0;
|
||||
|
||||
trace_hardirqs_on();
|
||||
irq_soft_mask_set(IRQS_ENABLED);
|
||||
__hard_irq_enable();
|
||||
preempt_enable();
|
||||
}
|
||||
EXPORT_SYMBOL(arch_local_irq_restore);
|
||||
|
||||
/*
|
||||
* This is a helper to use when about to go into idle low-power
|
||||
* when the latter has the side effect of re-enabling interrupts
|
||||
* (such as calling H_CEDE under pHyp).
|
||||
*
|
||||
* You call this function with interrupts soft-disabled (this is
|
||||
* already the case when ppc_md.power_save is called). The function
|
||||
* will return whether to enter power save or just return.
|
||||
*
|
||||
* In the former case, it will have notified lockdep of interrupts
|
||||
* being re-enabled and generally sanitized the lazy irq state,
|
||||
* and in the latter case it will leave with interrupts hard
|
||||
* disabled and marked as such, so the local_irq_enable() call
|
||||
* in arch_cpu_idle() will properly re-enable everything.
|
||||
*/
|
||||
bool prep_irq_for_idle(void)
|
||||
{
|
||||
/*
|
||||
* First we need to hard disable to ensure no interrupt
|
||||
* occurs before we effectively enter the low power state
|
||||
*/
|
||||
__hard_irq_disable();
|
||||
local_paca->irq_happened |= PACA_IRQ_HARD_DIS;
|
||||
|
||||
/*
|
||||
* If anything happened while we were soft-disabled,
|
||||
* we return now and do not enter the low power state.
|
||||
*/
|
||||
if (lazy_irq_pending())
|
||||
return false;
|
||||
|
||||
/* Tell lockdep we are about to re-enable */
|
||||
trace_hardirqs_on();
|
||||
|
||||
/*
|
||||
* Mark interrupts as soft-enabled and clear the
|
||||
* PACA_IRQ_HARD_DIS from the pending mask since we
|
||||
* are about to hard enable as well as a side effect
|
||||
* of entering the low power state.
|
||||
*/
|
||||
local_paca->irq_happened &= ~PACA_IRQ_HARD_DIS;
|
||||
irq_soft_mask_set(IRQS_ENABLED);
|
||||
|
||||
/* Tell the caller to enter the low power state */
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PPC_BOOK3S
|
||||
/*
|
||||
* This is for idle sequences that return with IRQs off, but the
|
||||
* idle state itself wakes on interrupt. Tell the irq tracer that
|
||||
* IRQs are enabled for the duration of idle so it does not get long
|
||||
* off times. Must be paired with fini_irq_for_idle_irqsoff.
|
||||
*/
|
||||
bool prep_irq_for_idle_irqsoff(void)
|
||||
{
|
||||
WARN_ON(!irqs_disabled());
|
||||
|
||||
/*
|
||||
* First we need to hard disable to ensure no interrupt
|
||||
* occurs before we effectively enter the low power state
|
||||
*/
|
||||
__hard_irq_disable();
|
||||
local_paca->irq_happened |= PACA_IRQ_HARD_DIS;
|
||||
|
||||
/*
|
||||
* If anything happened while we were soft-disabled,
|
||||
* we return now and do not enter the low power state.
|
||||
*/
|
||||
if (lazy_irq_pending())
|
||||
return false;
|
||||
|
||||
/* Tell lockdep we are about to re-enable */
|
||||
trace_hardirqs_on();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Take the SRR1 wakeup reason, index into this table to find the
|
||||
* appropriate irq_happened bit.
|
||||
*
|
||||
* Sytem reset exceptions taken in idle state also come through here,
|
||||
* but they are NMI interrupts so do not need to wait for IRQs to be
|
||||
* restored, and should be taken as early as practical. These are marked
|
||||
* with 0xff in the table. The Power ISA specifies 0100b as the system
|
||||
* reset interrupt reason.
|
||||
*/
|
||||
#define IRQ_SYSTEM_RESET 0xff
|
||||
|
||||
static const u8 srr1_to_lazyirq[0x10] = {
|
||||
0, 0, 0,
|
||||
PACA_IRQ_DBELL,
|
||||
IRQ_SYSTEM_RESET,
|
||||
PACA_IRQ_DBELL,
|
||||
PACA_IRQ_DEC,
|
||||
0,
|
||||
PACA_IRQ_EE,
|
||||
PACA_IRQ_EE,
|
||||
PACA_IRQ_HMI,
|
||||
0, 0, 0, 0, 0 };
|
||||
|
||||
void replay_system_reset(void)
|
||||
{
|
||||
struct pt_regs regs;
|
||||
|
||||
ppc_save_regs(®s);
|
||||
regs.trap = 0x100;
|
||||
get_paca()->in_nmi = 1;
|
||||
system_reset_exception(®s);
|
||||
get_paca()->in_nmi = 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(replay_system_reset);
|
||||
|
||||
void irq_set_pending_from_srr1(unsigned long srr1)
|
||||
{
|
||||
unsigned int idx = (srr1 & SRR1_WAKEMASK_P8) >> 18;
|
||||
u8 reason = srr1_to_lazyirq[idx];
|
||||
|
||||
/*
|
||||
* Take the system reset now, which is immediately after registers
|
||||
* are restored from idle. It's an NMI, so interrupts need not be
|
||||
* re-enabled before it is taken.
|
||||
*/
|
||||
if (unlikely(reason == IRQ_SYSTEM_RESET)) {
|
||||
replay_system_reset();
|
||||
return;
|
||||
}
|
||||
|
||||
if (reason == PACA_IRQ_DBELL) {
|
||||
/*
|
||||
* When doorbell triggers a system reset wakeup, the message
|
||||
* is not cleared, so if the doorbell interrupt is replayed
|
||||
* and the IPI handled, the doorbell interrupt would still
|
||||
* fire when EE is enabled.
|
||||
*
|
||||
* To avoid taking the superfluous doorbell interrupt,
|
||||
* execute a msgclr here before the interrupt is replayed.
|
||||
*/
|
||||
ppc_msgclr(PPC_DBELL_MSGTYPE);
|
||||
}
|
||||
|
||||
/*
|
||||
* The 0 index (SRR1[42:45]=b0000) must always evaluate to 0,
|
||||
* so this can be called unconditionally with the SRR1 wake
|
||||
* reason as returned by the idle code, which uses 0 to mean no
|
||||
* interrupt.
|
||||
*
|
||||
* If a future CPU was to designate this as an interrupt reason,
|
||||
* then a new index for no interrupt must be assigned.
|
||||
*/
|
||||
local_paca->irq_happened |= reason;
|
||||
}
|
||||
#endif /* CONFIG_PPC_BOOK3S */
|
||||
|
||||
/*
|
||||
* Force a replay of the external interrupt handler on this CPU.
|
||||
*/
|
||||
void force_external_irq_replay(void)
|
||||
{
|
||||
/*
|
||||
* This must only be called with interrupts soft-disabled,
|
||||
* the replay will happen when re-enabling.
|
||||
*/
|
||||
WARN_ON(!arch_irqs_disabled());
|
||||
|
||||
/*
|
||||
* Interrupts must always be hard disabled before irq_happened is
|
||||
* modified (to prevent lost update in case of interrupt between
|
||||
* load and store).
|
||||
*/
|
||||
__hard_irq_disable();
|
||||
local_paca->irq_happened |= PACA_IRQ_HARD_DIS;
|
||||
|
||||
/* Indicate in the PACA that we have an interrupt to replay */
|
||||
local_paca->irq_happened |= PACA_IRQ_EE;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PPC64 */
|
||||
|
||||
int arch_show_interrupts(struct seq_file *p, int prec)
|
||||
{
|
||||
int j;
|
||||
@ -595,17 +185,15 @@ u64 arch_irq_stat_cpu(unsigned int cpu)
|
||||
return sum;
|
||||
}
|
||||
|
||||
static inline void check_stack_overflow(void)
|
||||
static inline void check_stack_overflow(unsigned long sp)
|
||||
{
|
||||
long sp;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_DEBUG_STACKOVERFLOW))
|
||||
return;
|
||||
|
||||
sp = current_stack_pointer & (THREAD_SIZE - 1);
|
||||
sp &= THREAD_SIZE - 1;
|
||||
|
||||
/* check for stack overflow: is there less than 2KB free? */
|
||||
if (unlikely(sp < 2048)) {
|
||||
/* check for stack overflow: is there less than 1/4th free? */
|
||||
if (unlikely(sp < THREAD_SIZE / 4)) {
|
||||
pr_err("do_IRQ: stack overflow: %ld\n", sp);
|
||||
dump_stack();
|
||||
}
|
||||
@ -632,36 +220,16 @@ static __always_inline void call_do_softirq(const void *sp)
|
||||
}
|
||||
#endif
|
||||
|
||||
static __always_inline void call_do_irq(struct pt_regs *regs, void *sp)
|
||||
{
|
||||
register unsigned long r3 asm("r3") = (unsigned long)regs;
|
||||
|
||||
/* Temporarily switch r1 to sp, call __do_irq() then restore r1. */
|
||||
asm volatile (
|
||||
PPC_STLU " %%r1, %[offset](%[sp]) ;"
|
||||
"mr %%r1, %[sp] ;"
|
||||
"bl %[callee] ;"
|
||||
PPC_LL " %%r1, 0(%%r1) ;"
|
||||
: // Outputs
|
||||
"+r" (r3)
|
||||
: // Inputs
|
||||
[sp] "b" (sp), [offset] "i" (THREAD_SIZE - STACK_FRAME_OVERHEAD),
|
||||
[callee] "i" (__do_irq)
|
||||
: // Clobbers
|
||||
"lr", "xer", "ctr", "memory", "cr0", "cr1", "cr5", "cr6",
|
||||
"cr7", "r0", "r4", "r5", "r6", "r7", "r8", "r9", "r10",
|
||||
"r11", "r12"
|
||||
);
|
||||
}
|
||||
|
||||
DEFINE_STATIC_CALL_RET0(ppc_get_irq, *ppc_md.get_irq);
|
||||
|
||||
void __do_irq(struct pt_regs *regs)
|
||||
static void __do_irq(struct pt_regs *regs, unsigned long oldsp)
|
||||
{
|
||||
unsigned int irq;
|
||||
|
||||
trace_irq_entry(regs);
|
||||
|
||||
check_stack_overflow(oldsp);
|
||||
|
||||
/*
|
||||
* Query the platform PIC for the interrupt & ack it.
|
||||
*
|
||||
@ -682,6 +250,29 @@ void __do_irq(struct pt_regs *regs)
|
||||
trace_irq_exit(regs);
|
||||
}
|
||||
|
||||
static __always_inline void call_do_irq(struct pt_regs *regs, void *sp)
|
||||
{
|
||||
register unsigned long r3 asm("r3") = (unsigned long)regs;
|
||||
|
||||
/* Temporarily switch r1 to sp, call __do_irq() then restore r1. */
|
||||
asm volatile (
|
||||
PPC_STLU " %%r1, %[offset](%[sp]) ;"
|
||||
"mr %%r4, %%r1 ;"
|
||||
"mr %%r1, %[sp] ;"
|
||||
"bl %[callee] ;"
|
||||
PPC_LL " %%r1, 0(%%r1) ;"
|
||||
: // Outputs
|
||||
"+r" (r3)
|
||||
: // Inputs
|
||||
[sp] "b" (sp), [offset] "i" (THREAD_SIZE - STACK_FRAME_OVERHEAD),
|
||||
[callee] "i" (__do_irq)
|
||||
: // Clobbers
|
||||
"lr", "xer", "ctr", "memory", "cr0", "cr1", "cr5", "cr6",
|
||||
"cr7", "r0", "r4", "r5", "r6", "r7", "r8", "r9", "r10",
|
||||
"r11", "r12"
|
||||
);
|
||||
}
|
||||
|
||||
void __do_IRQ(struct pt_regs *regs)
|
||||
{
|
||||
struct pt_regs *old_regs = set_irq_regs(regs);
|
||||
@ -692,16 +283,11 @@ void __do_IRQ(struct pt_regs *regs)
|
||||
irqsp = hardirq_ctx[raw_smp_processor_id()];
|
||||
sirqsp = softirq_ctx[raw_smp_processor_id()];
|
||||
|
||||
check_stack_overflow();
|
||||
|
||||
/* Already there ? */
|
||||
if (unlikely(cursp == irqsp || cursp == sirqsp)) {
|
||||
__do_irq(regs);
|
||||
set_irq_regs(old_regs);
|
||||
return;
|
||||
}
|
||||
/* Switch stack and call */
|
||||
call_do_irq(regs, irqsp);
|
||||
/* Already there ? If not switch stack and call */
|
||||
if (unlikely(cursp == irqsp || cursp == sirqsp))
|
||||
__do_irq(regs, current_stack_pointer);
|
||||
else
|
||||
call_do_irq(regs, irqsp);
|
||||
|
||||
set_irq_regs(old_regs);
|
||||
}
|
||||
@ -798,13 +384,3 @@ int irq_choose_cpu(const struct cpumask *mask)
|
||||
return hard_smp_processor_id();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
static int __init setup_noirqdistrib(char *str)
|
||||
{
|
||||
distribute_irqs = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
__setup("noirqdistrib", setup_noirqdistrib);
|
||||
#endif /* CONFIG_PPC64 */
|
||||
|
466
arch/powerpc/kernel/irq_64.c
Normal file
466
arch/powerpc/kernel/irq_64.c
Normal file
@ -0,0 +1,466 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Derived from arch/i386/kernel/irq.c
|
||||
* Copyright (C) 1992 Linus Torvalds
|
||||
* Adapted from arch/i386 by Gary Thomas
|
||||
* Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
|
||||
* Updated and modified by Cort Dougan <cort@fsmlabs.com>
|
||||
* Copyright (C) 1996-2001 Cort Dougan
|
||||
* Adapted for Power Macintosh by Paul Mackerras
|
||||
* Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au)
|
||||
*
|
||||
* This file contains the code used by various IRQ handling routines:
|
||||
* asking for different IRQ's should be done through these routines
|
||||
* instead of just grabbing them. Thus setups with different IRQ numbers
|
||||
* shouldn't result in any weird surprises, and installing new handlers
|
||||
* should be easier.
|
||||
*/
|
||||
|
||||
#undef DEBUG
|
||||
|
||||
#include <linux/export.h>
|
||||
#include <linux/threads.h>
|
||||
#include <linux/kernel_stat.h>
|
||||
#include <linux/signal.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/timex.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/cpumask.h>
|
||||
#include <linux/profile.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/radix-tree.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/pgtable.h>
|
||||
#include <linux/static_call.h>
|
||||
|
||||
#include <linux/uaccess.h>
|
||||
#include <asm/interrupt.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/cache.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/udbg.h>
|
||||
#include <asm/smp.h>
|
||||
#include <asm/hw_irq.h>
|
||||
#include <asm/softirq_stack.h>
|
||||
#include <asm/ppc_asm.h>
|
||||
|
||||
#include <asm/paca.h>
|
||||
#include <asm/firmware.h>
|
||||
#include <asm/lv1call.h>
|
||||
#include <asm/dbell.h>
|
||||
#include <asm/trace.h>
|
||||
#include <asm/cpu_has_feature.h>
|
||||
|
||||
int distribute_irqs = 1;
|
||||
|
||||
void replay_soft_interrupts(void)
|
||||
{
|
||||
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.
|
||||
*
|
||||
* We use local_paca rather than get_paca() to avoid all the
|
||||
* debug_smp_processor_id() business in this low level function.
|
||||
*/
|
||||
|
||||
ppc_save_regs(®s);
|
||||
regs.softe = IRQS_ENABLED;
|
||||
regs.msr |= MSR_EE;
|
||||
|
||||
again:
|
||||
if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG))
|
||||
WARN_ON_ONCE(mfmsr() & MSR_EE);
|
||||
|
||||
/*
|
||||
* Force the delivery of pending soft-disabled interrupts on PS3.
|
||||
* Any HV call will have this side effect.
|
||||
*/
|
||||
if (firmware_has_feature(FW_FEATURE_PS3_LV1)) {
|
||||
u64 tmp, tmp2;
|
||||
lv1_get_version_info(&tmp, &tmp2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if an hypervisor Maintenance interrupt happened.
|
||||
* This is a higher priority interrupt than the others, so
|
||||
* replay it first.
|
||||
*/
|
||||
if (IS_ENABLED(CONFIG_PPC_BOOK3S) && (local_paca->irq_happened & PACA_IRQ_HMI)) {
|
||||
local_paca->irq_happened &= ~PACA_IRQ_HMI;
|
||||
regs.trap = INTERRUPT_HMI;
|
||||
handle_hmi_exception(®s);
|
||||
if (!(local_paca->irq_happened & PACA_IRQ_HARD_DIS))
|
||||
hard_irq_disable();
|
||||
}
|
||||
|
||||
if (local_paca->irq_happened & PACA_IRQ_DEC) {
|
||||
local_paca->irq_happened &= ~PACA_IRQ_DEC;
|
||||
regs.trap = INTERRUPT_DECREMENTER;
|
||||
timer_interrupt(®s);
|
||||
if (!(local_paca->irq_happened & PACA_IRQ_HARD_DIS))
|
||||
hard_irq_disable();
|
||||
}
|
||||
|
||||
if (local_paca->irq_happened & PACA_IRQ_EE) {
|
||||
local_paca->irq_happened &= ~PACA_IRQ_EE;
|
||||
regs.trap = INTERRUPT_EXTERNAL;
|
||||
do_IRQ(®s);
|
||||
if (!(local_paca->irq_happened & PACA_IRQ_HARD_DIS))
|
||||
hard_irq_disable();
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_PPC_DOORBELL) && (local_paca->irq_happened & PACA_IRQ_DBELL)) {
|
||||
local_paca->irq_happened &= ~PACA_IRQ_DBELL;
|
||||
regs.trap = INTERRUPT_DOORBELL;
|
||||
doorbell_exception(®s);
|
||||
if (!(local_paca->irq_happened & PACA_IRQ_HARD_DIS))
|
||||
hard_irq_disable();
|
||||
}
|
||||
|
||||
/* Book3E does not support soft-masking PMI interrupts */
|
||||
if (IS_ENABLED(CONFIG_PPC_BOOK3S) && (local_paca->irq_happened & PACA_IRQ_PMI)) {
|
||||
local_paca->irq_happened &= ~PACA_IRQ_PMI;
|
||||
regs.trap = INTERRUPT_PERFMON;
|
||||
performance_monitor_exception(®s);
|
||||
if (!(local_paca->irq_happened & PACA_IRQ_HARD_DIS))
|
||||
hard_irq_disable();
|
||||
}
|
||||
|
||||
if (local_paca->irq_happened & ~PACA_IRQ_HARD_DIS) {
|
||||
/*
|
||||
* We are responding to the next interrupt, so interrupt-off
|
||||
* latencies should be reset here.
|
||||
*/
|
||||
trace_hardirqs_on();
|
||||
trace_hardirqs_off();
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_PPC_BOOK3S_64) && defined(CONFIG_PPC_KUAP)
|
||||
static inline void replay_soft_interrupts_irqrestore(void)
|
||||
{
|
||||
unsigned long kuap_state = get_kuap();
|
||||
|
||||
/*
|
||||
* Check if anything calls local_irq_enable/restore() when KUAP is
|
||||
* disabled (user access enabled). We handle that case here by saving
|
||||
* and re-locking AMR but we shouldn't get here in the first place,
|
||||
* hence the warning.
|
||||
*/
|
||||
kuap_assert_locked();
|
||||
|
||||
if (kuap_state != AMR_KUAP_BLOCKED)
|
||||
set_kuap(AMR_KUAP_BLOCKED);
|
||||
|
||||
replay_soft_interrupts();
|
||||
|
||||
if (kuap_state != AMR_KUAP_BLOCKED)
|
||||
set_kuap(kuap_state);
|
||||
}
|
||||
#else
|
||||
#define replay_soft_interrupts_irqrestore() replay_soft_interrupts()
|
||||
#endif
|
||||
|
||||
notrace void arch_local_irq_restore(unsigned long mask)
|
||||
{
|
||||
unsigned char irq_happened;
|
||||
|
||||
/* Write the new soft-enabled value if it is a disable */
|
||||
if (mask) {
|
||||
irq_soft_mask_set(mask);
|
||||
return;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG))
|
||||
WARN_ON_ONCE(in_nmi() || in_hardirq());
|
||||
|
||||
/*
|
||||
* After the stb, interrupts are unmasked and there are no interrupts
|
||||
* pending replay. The restart sequence makes this atomic with
|
||||
* respect to soft-masked interrupts. If this was just a simple code
|
||||
* sequence, a soft-masked interrupt could become pending right after
|
||||
* the comparison and before the stb.
|
||||
*
|
||||
* This allows interrupts to be unmasked without hard disabling, and
|
||||
* also without new hard interrupts coming in ahead of pending ones.
|
||||
*/
|
||||
asm_volatile_goto(
|
||||
"1: \n"
|
||||
" lbz 9,%0(13) \n"
|
||||
" cmpwi 9,0 \n"
|
||||
" bne %l[happened] \n"
|
||||
" stb 9,%1(13) \n"
|
||||
"2: \n"
|
||||
RESTART_TABLE(1b, 2b, 1b)
|
||||
: : "i" (offsetof(struct paca_struct, irq_happened)),
|
||||
"i" (offsetof(struct paca_struct, irq_soft_mask))
|
||||
: "cr0", "r9"
|
||||
: happened);
|
||||
|
||||
if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG))
|
||||
WARN_ON_ONCE(!(mfmsr() & MSR_EE));
|
||||
|
||||
return;
|
||||
|
||||
happened:
|
||||
irq_happened = READ_ONCE(local_paca->irq_happened);
|
||||
if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG))
|
||||
WARN_ON_ONCE(!irq_happened);
|
||||
|
||||
if (irq_happened == PACA_IRQ_HARD_DIS) {
|
||||
if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG))
|
||||
WARN_ON_ONCE(mfmsr() & MSR_EE);
|
||||
irq_soft_mask_set(IRQS_ENABLED);
|
||||
local_paca->irq_happened = 0;
|
||||
__hard_irq_enable();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Have interrupts to replay, need to hard disable first */
|
||||
if (!(irq_happened & PACA_IRQ_HARD_DIS)) {
|
||||
if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG)) {
|
||||
if (!(mfmsr() & MSR_EE)) {
|
||||
/*
|
||||
* An interrupt could have come in and cleared
|
||||
* MSR[EE] and set IRQ_HARD_DIS, so check
|
||||
* IRQ_HARD_DIS again and warn if it is still
|
||||
* clear.
|
||||
*/
|
||||
irq_happened = READ_ONCE(local_paca->irq_happened);
|
||||
WARN_ON_ONCE(!(irq_happened & PACA_IRQ_HARD_DIS));
|
||||
}
|
||||
}
|
||||
__hard_irq_disable();
|
||||
local_paca->irq_happened |= PACA_IRQ_HARD_DIS;
|
||||
} else {
|
||||
if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG)) {
|
||||
if (WARN_ON_ONCE(mfmsr() & MSR_EE))
|
||||
__hard_irq_disable();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable preempt here, so that the below preempt_enable will
|
||||
* perform resched if required (a replayed interrupt may set
|
||||
* need_resched).
|
||||
*/
|
||||
preempt_disable();
|
||||
irq_soft_mask_set(IRQS_ALL_DISABLED);
|
||||
trace_hardirqs_off();
|
||||
|
||||
replay_soft_interrupts_irqrestore();
|
||||
local_paca->irq_happened = 0;
|
||||
|
||||
trace_hardirqs_on();
|
||||
irq_soft_mask_set(IRQS_ENABLED);
|
||||
__hard_irq_enable();
|
||||
preempt_enable();
|
||||
}
|
||||
EXPORT_SYMBOL(arch_local_irq_restore);
|
||||
|
||||
/*
|
||||
* This is a helper to use when about to go into idle low-power
|
||||
* when the latter has the side effect of re-enabling interrupts
|
||||
* (such as calling H_CEDE under pHyp).
|
||||
*
|
||||
* You call this function with interrupts soft-disabled (this is
|
||||
* already the case when ppc_md.power_save is called). The function
|
||||
* will return whether to enter power save or just return.
|
||||
*
|
||||
* In the former case, it will have notified lockdep of interrupts
|
||||
* being re-enabled and generally sanitized the lazy irq state,
|
||||
* and in the latter case it will leave with interrupts hard
|
||||
* disabled and marked as such, so the local_irq_enable() call
|
||||
* in arch_cpu_idle() will properly re-enable everything.
|
||||
*/
|
||||
bool prep_irq_for_idle(void)
|
||||
{
|
||||
/*
|
||||
* First we need to hard disable to ensure no interrupt
|
||||
* occurs before we effectively enter the low power state
|
||||
*/
|
||||
__hard_irq_disable();
|
||||
local_paca->irq_happened |= PACA_IRQ_HARD_DIS;
|
||||
|
||||
/*
|
||||
* If anything happened while we were soft-disabled,
|
||||
* we return now and do not enter the low power state.
|
||||
*/
|
||||
if (lazy_irq_pending())
|
||||
return false;
|
||||
|
||||
/* Tell lockdep we are about to re-enable */
|
||||
trace_hardirqs_on();
|
||||
|
||||
/*
|
||||
* Mark interrupts as soft-enabled and clear the
|
||||
* PACA_IRQ_HARD_DIS from the pending mask since we
|
||||
* are about to hard enable as well as a side effect
|
||||
* of entering the low power state.
|
||||
*/
|
||||
local_paca->irq_happened &= ~PACA_IRQ_HARD_DIS;
|
||||
irq_soft_mask_set(IRQS_ENABLED);
|
||||
|
||||
/* Tell the caller to enter the low power state */
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PPC_BOOK3S
|
||||
/*
|
||||
* This is for idle sequences that return with IRQs off, but the
|
||||
* idle state itself wakes on interrupt. Tell the irq tracer that
|
||||
* IRQs are enabled for the duration of idle so it does not get long
|
||||
* off times. Must be paired with fini_irq_for_idle_irqsoff.
|
||||
*/
|
||||
bool prep_irq_for_idle_irqsoff(void)
|
||||
{
|
||||
WARN_ON(!irqs_disabled());
|
||||
|
||||
/*
|
||||
* First we need to hard disable to ensure no interrupt
|
||||
* occurs before we effectively enter the low power state
|
||||
*/
|
||||
__hard_irq_disable();
|
||||
local_paca->irq_happened |= PACA_IRQ_HARD_DIS;
|
||||
|
||||
/*
|
||||
* If anything happened while we were soft-disabled,
|
||||
* we return now and do not enter the low power state.
|
||||
*/
|
||||
if (lazy_irq_pending())
|
||||
return false;
|
||||
|
||||
/* Tell lockdep we are about to re-enable */
|
||||
trace_hardirqs_on();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Take the SRR1 wakeup reason, index into this table to find the
|
||||
* appropriate irq_happened bit.
|
||||
*
|
||||
* Sytem reset exceptions taken in idle state also come through here,
|
||||
* but they are NMI interrupts so do not need to wait for IRQs to be
|
||||
* restored, and should be taken as early as practical. These are marked
|
||||
* with 0xff in the table. The Power ISA specifies 0100b as the system
|
||||
* reset interrupt reason.
|
||||
*/
|
||||
#define IRQ_SYSTEM_RESET 0xff
|
||||
|
||||
static const u8 srr1_to_lazyirq[0x10] = {
|
||||
0, 0, 0,
|
||||
PACA_IRQ_DBELL,
|
||||
IRQ_SYSTEM_RESET,
|
||||
PACA_IRQ_DBELL,
|
||||
PACA_IRQ_DEC,
|
||||
0,
|
||||
PACA_IRQ_EE,
|
||||
PACA_IRQ_EE,
|
||||
PACA_IRQ_HMI,
|
||||
0, 0, 0, 0, 0 };
|
||||
|
||||
void replay_system_reset(void)
|
||||
{
|
||||
struct pt_regs regs;
|
||||
|
||||
ppc_save_regs(®s);
|
||||
regs.trap = 0x100;
|
||||
get_paca()->in_nmi = 1;
|
||||
system_reset_exception(®s);
|
||||
get_paca()->in_nmi = 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(replay_system_reset);
|
||||
|
||||
void irq_set_pending_from_srr1(unsigned long srr1)
|
||||
{
|
||||
unsigned int idx = (srr1 & SRR1_WAKEMASK_P8) >> 18;
|
||||
u8 reason = srr1_to_lazyirq[idx];
|
||||
|
||||
/*
|
||||
* Take the system reset now, which is immediately after registers
|
||||
* are restored from idle. It's an NMI, so interrupts need not be
|
||||
* re-enabled before it is taken.
|
||||
*/
|
||||
if (unlikely(reason == IRQ_SYSTEM_RESET)) {
|
||||
replay_system_reset();
|
||||
return;
|
||||
}
|
||||
|
||||
if (reason == PACA_IRQ_DBELL) {
|
||||
/*
|
||||
* When doorbell triggers a system reset wakeup, the message
|
||||
* is not cleared, so if the doorbell interrupt is replayed
|
||||
* and the IPI handled, the doorbell interrupt would still
|
||||
* fire when EE is enabled.
|
||||
*
|
||||
* To avoid taking the superfluous doorbell interrupt,
|
||||
* execute a msgclr here before the interrupt is replayed.
|
||||
*/
|
||||
ppc_msgclr(PPC_DBELL_MSGTYPE);
|
||||
}
|
||||
|
||||
/*
|
||||
* The 0 index (SRR1[42:45]=b0000) must always evaluate to 0,
|
||||
* so this can be called unconditionally with the SRR1 wake
|
||||
* reason as returned by the idle code, which uses 0 to mean no
|
||||
* interrupt.
|
||||
*
|
||||
* If a future CPU was to designate this as an interrupt reason,
|
||||
* then a new index for no interrupt must be assigned.
|
||||
*/
|
||||
local_paca->irq_happened |= reason;
|
||||
}
|
||||
#endif /* CONFIG_PPC_BOOK3S */
|
||||
|
||||
/*
|
||||
* Force a replay of the external interrupt handler on this CPU.
|
||||
*/
|
||||
void force_external_irq_replay(void)
|
||||
{
|
||||
/*
|
||||
* This must only be called with interrupts soft-disabled,
|
||||
* the replay will happen when re-enabling.
|
||||
*/
|
||||
WARN_ON(!arch_irqs_disabled());
|
||||
|
||||
/*
|
||||
* Interrupts must always be hard disabled before irq_happened is
|
||||
* modified (to prevent lost update in case of interrupt between
|
||||
* load and store).
|
||||
*/
|
||||
__hard_irq_disable();
|
||||
local_paca->irq_happened |= PACA_IRQ_HARD_DIS;
|
||||
|
||||
/* Indicate in the PACA that we have an interrupt to replay */
|
||||
local_paca->irq_happened |= PACA_IRQ_EE;
|
||||
}
|
||||
|
||||
static int __init setup_noirqdistrib(char *str)
|
||||
{
|
||||
distribute_irqs = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
__setup("noirqdistrib", setup_noirqdistrib);
|
@ -269,7 +269,7 @@ static int try_to_emulate(struct kprobe *p, struct pt_regs *regs)
|
||||
* So, we should never get here... but, its still
|
||||
* good to catch them, just in case...
|
||||
*/
|
||||
printk("Can't step on instruction %s\n", ppc_inst_as_str(insn));
|
||||
printk("Can't step on instruction %08lx\n", ppc_inst_as_ulong(insn));
|
||||
BUG();
|
||||
} else {
|
||||
/*
|
||||
|
@ -756,7 +756,7 @@ void __init mce_init(void)
|
||||
mce_info = memblock_alloc_try_nid(sizeof(*mce_info),
|
||||
__alignof__(*mce_info),
|
||||
MEMBLOCK_LOW_LIMIT,
|
||||
limit, cpu_to_node(i));
|
||||
limit, early_cpu_to_node(i));
|
||||
if (!mce_info)
|
||||
goto err;
|
||||
paca_ptrs[i]->mce_info = mce_info;
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/ppc-pci.h>
|
||||
#include <asm/eeh.h>
|
||||
#include <asm/setup.h>
|
||||
|
||||
#include "../../../drivers/pci/pci.h"
|
||||
|
||||
@ -74,16 +75,32 @@ void __init set_pci_dma_ops(const struct dma_map_ops *dma_ops)
|
||||
static int get_phb_number(struct device_node *dn)
|
||||
{
|
||||
int ret, phb_id = -1;
|
||||
u32 prop_32;
|
||||
u64 prop;
|
||||
|
||||
/*
|
||||
* Try fixed PHB numbering first, by checking archs and reading
|
||||
* the respective device-tree properties. Firstly, try powernv by
|
||||
* reading "ibm,opal-phbid", only present in OPAL environment.
|
||||
* the respective device-tree properties. Firstly, try reading
|
||||
* standard "linux,pci-domain", then try reading "ibm,opal-phbid"
|
||||
* (only present in powernv OPAL environment), then try device-tree
|
||||
* alias and as the last try to use lower bits of "reg" property.
|
||||
*/
|
||||
ret = of_property_read_u64(dn, "ibm,opal-phbid", &prop);
|
||||
ret = of_get_pci_domain_nr(dn);
|
||||
if (ret >= 0) {
|
||||
prop = ret;
|
||||
ret = 0;
|
||||
}
|
||||
if (ret)
|
||||
ret = of_property_read_u64(dn, "ibm,opal-phbid", &prop);
|
||||
|
||||
if (ret) {
|
||||
ret = of_alias_get_id(dn, "pci");
|
||||
if (ret >= 0) {
|
||||
prop = ret;
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
if (ret) {
|
||||
u32 prop_32;
|
||||
ret = of_property_read_u32_index(dn, "reg", 1, &prop_32);
|
||||
prop = prop_32;
|
||||
}
|
||||
@ -95,10 +112,7 @@ static int get_phb_number(struct device_node *dn)
|
||||
if ((phb_id >= 0) && !test_and_set_bit(phb_id, phb_bitmap))
|
||||
return phb_id;
|
||||
|
||||
/*
|
||||
* If not pseries nor powernv, or if fixed PHB numbering tried to add
|
||||
* the same PHB number twice, then fallback to dynamic PHB numbering.
|
||||
*/
|
||||
/* If everything fails then fallback to dynamic PHB numbering. */
|
||||
phb_id = find_first_zero_bit(phb_bitmap, MAX_PHBS);
|
||||
BUG_ON(phb_id >= MAX_PHBS);
|
||||
set_bit(phb_id, phb_bitmap);
|
||||
@ -1087,7 +1101,7 @@ void pcibios_fixup_bus(struct pci_bus *bus)
|
||||
*/
|
||||
pci_read_bridge_bases(bus);
|
||||
|
||||
/* Now fixup the bus bus */
|
||||
/* Now fixup the bus */
|
||||
pcibios_setup_bus_self(bus);
|
||||
}
|
||||
EXPORT_SYMBOL(pcibios_fixup_bus);
|
||||
|
@ -36,18 +36,13 @@ int pcibios_assign_bus_offset = 1;
|
||||
EXPORT_SYMBOL(isa_io_base);
|
||||
EXPORT_SYMBOL(pci_dram_offset);
|
||||
|
||||
void __init pcibios_make_OF_bus_map(void);
|
||||
|
||||
static void fixup_cpc710_pci64(struct pci_dev* dev);
|
||||
static u8* pci_to_OF_bus_map;
|
||||
|
||||
/* By default, we don't re-assign bus numbers. We do this only on
|
||||
* some pmacs
|
||||
*/
|
||||
static int pci_assign_all_buses;
|
||||
|
||||
static int pci_bus_count;
|
||||
|
||||
/* This will remain NULL for now, until isa-bridge.c is made common
|
||||
* to both 32-bit and 64-bit.
|
||||
*/
|
||||
@ -67,6 +62,11 @@ fixup_cpc710_pci64(struct pci_dev* dev)
|
||||
}
|
||||
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)
|
||||
|
||||
static u8* pci_to_OF_bus_map;
|
||||
static int pci_bus_count;
|
||||
|
||||
/*
|
||||
* Functions below are used on OpenFirmware machines.
|
||||
*/
|
||||
@ -108,7 +108,7 @@ make_one_node_map(struct device_node* node, u8 pci_bus)
|
||||
}
|
||||
}
|
||||
|
||||
void __init
|
||||
static void __init
|
||||
pcibios_make_OF_bus_map(void)
|
||||
{
|
||||
int i;
|
||||
@ -154,6 +154,7 @@ pcibios_make_OF_bus_map(void)
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_PPC_PMAC
|
||||
/*
|
||||
* Returns the PCI device matching a given OF node
|
||||
*/
|
||||
@ -193,7 +194,9 @@ int pci_device_from_OF_node(struct device_node *node, u8 *bus, u8 *devfn)
|
||||
return -ENODEV;
|
||||
}
|
||||
EXPORT_SYMBOL(pci_device_from_OF_node);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PPC_CHRP
|
||||
/* We create the "pci-OF-bus-map" property now so it appears in the
|
||||
* /proc device tree
|
||||
*/
|
||||
@ -218,6 +221,9 @@ pci_create_OF_bus_map(void)
|
||||
of_node_put(dn);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_CHRP) */
|
||||
|
||||
void pcibios_setup_phb_io_space(struct pci_controller *hose)
|
||||
{
|
||||
@ -233,7 +239,9 @@ void pcibios_setup_phb_io_space(struct pci_controller *hose)
|
||||
static int __init pcibios_init(void)
|
||||
{
|
||||
struct pci_controller *hose, *tmp;
|
||||
#ifndef CONFIG_PPC_PCI_BUS_NUM_DOMAIN_DEPENDENT
|
||||
int next_busno = 0;
|
||||
#endif
|
||||
|
||||
printk(KERN_INFO "PCI: Probing PCI hardware\n");
|
||||
|
||||
@ -242,14 +250,20 @@ static int __init pcibios_init(void)
|
||||
|
||||
/* Scan all of the recorded PCI controllers. */
|
||||
list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
|
||||
#ifndef CONFIG_PPC_PCI_BUS_NUM_DOMAIN_DEPENDENT
|
||||
if (pci_assign_all_buses)
|
||||
hose->first_busno = next_busno;
|
||||
#endif
|
||||
hose->last_busno = 0xff;
|
||||
pcibios_scan_phb(hose);
|
||||
pci_bus_add_devices(hose->bus);
|
||||
#ifndef CONFIG_PPC_PCI_BUS_NUM_DOMAIN_DEPENDENT
|
||||
if (pci_assign_all_buses || next_busno <= hose->last_busno)
|
||||
next_busno = hose->last_busno + pcibios_assign_bus_offset;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_CHRP)
|
||||
pci_bus_count = next_busno;
|
||||
|
||||
/* OpenFirmware based machines need a map of OF bus
|
||||
@ -258,6 +272,7 @@ static int __init pcibios_init(void)
|
||||
*/
|
||||
if (pci_assign_all_buses)
|
||||
pcibios_make_OF_bus_map();
|
||||
#endif
|
||||
|
||||
/* Call common code to handle resource allocation */
|
||||
pcibios_resource_survey();
|
||||
|
@ -286,6 +286,7 @@ int pcibus_to_node(struct pci_bus *bus)
|
||||
EXPORT_SYMBOL(pcibus_to_node);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PPC_PMAC
|
||||
int pci_device_from_OF_node(struct device_node *np, u8 *bus, u8 *devfn)
|
||||
{
|
||||
if (!PCI_DN(np))
|
||||
@ -294,3 +295,4 @@ int pci_device_from_OF_node(struct device_node *np, u8 *bus, u8 *devfn)
|
||||
*devfn = PCI_DN(np)->devfn;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
@ -259,7 +259,7 @@ void remove_sriov_vf_pdns(struct pci_dev *pdev)
|
||||
if (edev) {
|
||||
/*
|
||||
* We allocate pci_dn's for the totalvfs count,
|
||||
* but only only the vfs that were activated
|
||||
* but only the vfs that were activated
|
||||
* have a configured PE.
|
||||
*/
|
||||
if (edev->pe)
|
||||
|
@ -44,7 +44,7 @@
|
||||
#include <asm/iommu.h>
|
||||
#include <asm/btext.h>
|
||||
#include <asm/sections.h>
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/setup.h>
|
||||
#include <asm/pci-bridge.h>
|
||||
#include <asm/kexec.h>
|
||||
#include <asm/opal.h>
|
||||
@ -54,6 +54,7 @@
|
||||
#include <asm/dt_cpu_ftrs.h>
|
||||
#include <asm/drmem.h>
|
||||
#include <asm/ultravisor.h>
|
||||
#include <asm/prom.h>
|
||||
|
||||
#include <mm/mmu_decl.h>
|
||||
|
||||
@ -751,6 +752,13 @@ void __init early_init_devtree(void *params)
|
||||
early_init_dt_scan_root();
|
||||
early_init_dt_scan_memory_ppc();
|
||||
|
||||
/*
|
||||
* As generic code authors expect to be able to use static keys
|
||||
* in early_param() handlers, we initialize the static keys just
|
||||
* before parsing early params (it's fine to call jump_label_init()
|
||||
* more than once).
|
||||
*/
|
||||
jump_label_init();
|
||||
parse_early_param();
|
||||
|
||||
/* make sure we've parsed cmdline for mem= before this */
|
||||
|
@ -42,7 +42,7 @@
|
||||
#include <asm/iommu.h>
|
||||
#include <asm/btext.h>
|
||||
#include <asm/sections.h>
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/setup.h>
|
||||
#include <asm/asm-prototypes.h>
|
||||
#include <asm/ultravisor-api.h>
|
||||
|
||||
|
@ -71,7 +71,7 @@ int fpr_set(struct task_struct *target, const struct user_regset *regset,
|
||||
}
|
||||
|
||||
/*
|
||||
* Currently to set and and get all the vsx state, you need to call
|
||||
* Currently to set and get all the vsx state, you need to call
|
||||
* the fp and VMX calls as well. This only get/sets the lower 32
|
||||
* 128bit VSX registers.
|
||||
*/
|
||||
|
@ -113,7 +113,6 @@ void __init setup_tlb_core_data(void)
|
||||
* Should we panic instead?
|
||||
*/
|
||||
WARN_ONCE(smt_enabled_at_boot >= 2 &&
|
||||
!mmu_has_feature(MMU_FTR_USE_TLBRSRV) &&
|
||||
book3e_htw_mode != PPC_HTW_E6500,
|
||||
"%s: unsupported MMU configuration\n", __func__);
|
||||
}
|
||||
|
@ -377,9 +377,12 @@ static long notrace __unsafe_restore_sigcontext(struct task_struct *tsk, sigset_
|
||||
unsafe_get_user(set->sig[0], &sc->oldmask, efault_out);
|
||||
|
||||
/*
|
||||
* Force reload of FP/VEC.
|
||||
* This has to be done before copying stuff into tsk->thread.fpr/vr
|
||||
* for the reasons explained in the previous comment.
|
||||
* Force reload of FP/VEC/VSX so userspace sees any changes.
|
||||
* Clear these bits from the user process' MSR before copying into the
|
||||
* thread struct. If we are rescheduled or preempted and another task
|
||||
* uses FP/VEC/VSX, and this process has the MSR bits set, then the
|
||||
* context switch code will save the current CPU state into the
|
||||
* thread_struct - possibly overwriting the data we are updating here.
|
||||
*/
|
||||
regs_set_return_msr(regs, regs->msr & ~(MSR_FP | MSR_FE0 | MSR_FE1 | MSR_VEC | MSR_VSX));
|
||||
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include <linux/stackprotector.h>
|
||||
#include <linux/pgtable.h>
|
||||
#include <linux/clockchips.h>
|
||||
#include <linux/kexec.h>
|
||||
|
||||
#include <asm/ptrace.h>
|
||||
#include <linux/atomic.h>
|
||||
@ -55,7 +56,6 @@
|
||||
#endif
|
||||
#include <asm/vdso.h>
|
||||
#include <asm/debug.h>
|
||||
#include <asm/kexec.h>
|
||||
#include <asm/cpu_has_feature.h>
|
||||
#include <asm/ftrace.h>
|
||||
#include <asm/kup.h>
|
||||
@ -619,20 +619,6 @@ void crash_send_ipi(void (*crash_ipi_callback)(struct pt_regs *))
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NMI_IPI
|
||||
static void crash_stop_this_cpu(struct pt_regs *regs)
|
||||
#else
|
||||
static void crash_stop_this_cpu(void *dummy)
|
||||
#endif
|
||||
{
|
||||
/*
|
||||
* Just busy wait here and avoid marking CPU as offline to ensure
|
||||
* register data is captured appropriately.
|
||||
*/
|
||||
while (1)
|
||||
cpu_relax();
|
||||
}
|
||||
|
||||
void crash_smp_send_stop(void)
|
||||
{
|
||||
static bool stopped = false;
|
||||
@ -651,11 +637,14 @@ void crash_smp_send_stop(void)
|
||||
|
||||
stopped = true;
|
||||
|
||||
#ifdef CONFIG_NMI_IPI
|
||||
smp_send_nmi_ipi(NMI_IPI_ALL_OTHERS, crash_stop_this_cpu, 1000000);
|
||||
#else
|
||||
smp_call_function(crash_stop_this_cpu, NULL, 0);
|
||||
#endif /* CONFIG_NMI_IPI */
|
||||
#ifdef CONFIG_KEXEC_CORE
|
||||
if (kexec_crash_image) {
|
||||
crash_kexec_prepare();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
smp_send_stop();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NMI_IPI
|
||||
|
190
arch/powerpc/kernel/syscall.c
Normal file
190
arch/powerpc/kernel/syscall.c
Normal file
@ -0,0 +1,190 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <linux/compat.h>
|
||||
#include <linux/context_tracking.h>
|
||||
#include <linux/randomize_kstack.h>
|
||||
|
||||
#include <asm/interrupt.h>
|
||||
#include <asm/kup.h>
|
||||
#include <asm/syscall.h>
|
||||
#include <asm/time.h>
|
||||
#include <asm/tm.h>
|
||||
#include <asm/unistd.h>
|
||||
|
||||
|
||||
typedef long (*syscall_fn)(long, long, long, long, long, long);
|
||||
|
||||
/* Has to run notrace because it is entered not completely "reconciled" */
|
||||
notrace long system_call_exception(long r3, long r4, long r5,
|
||||
long r6, long r7, long r8,
|
||||
unsigned long r0, struct pt_regs *regs)
|
||||
{
|
||||
long ret;
|
||||
syscall_fn f;
|
||||
|
||||
kuap_lock();
|
||||
|
||||
add_random_kstack_offset();
|
||||
regs->orig_gpr3 = r3;
|
||||
|
||||
if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG))
|
||||
BUG_ON(irq_soft_mask_return() != IRQS_ALL_DISABLED);
|
||||
|
||||
trace_hardirqs_off(); /* finish reconciling */
|
||||
|
||||
CT_WARN_ON(ct_state() == CONTEXT_KERNEL);
|
||||
user_exit_irqoff();
|
||||
|
||||
BUG_ON(regs_is_unrecoverable(regs));
|
||||
BUG_ON(!(regs->msr & MSR_PR));
|
||||
BUG_ON(arch_irq_disabled_regs(regs));
|
||||
|
||||
#ifdef CONFIG_PPC_PKEY
|
||||
if (mmu_has_feature(MMU_FTR_PKEY)) {
|
||||
unsigned long amr, iamr;
|
||||
bool flush_needed = false;
|
||||
/*
|
||||
* When entering from userspace we mostly have the AMR/IAMR
|
||||
* different from kernel default values. Hence don't compare.
|
||||
*/
|
||||
amr = mfspr(SPRN_AMR);
|
||||
iamr = mfspr(SPRN_IAMR);
|
||||
regs->amr = amr;
|
||||
regs->iamr = iamr;
|
||||
if (mmu_has_feature(MMU_FTR_BOOK3S_KUAP)) {
|
||||
mtspr(SPRN_AMR, AMR_KUAP_BLOCKED);
|
||||
flush_needed = true;
|
||||
}
|
||||
if (mmu_has_feature(MMU_FTR_BOOK3S_KUEP)) {
|
||||
mtspr(SPRN_IAMR, AMR_KUEP_BLOCKED);
|
||||
flush_needed = true;
|
||||
}
|
||||
if (flush_needed)
|
||||
isync();
|
||||
} else
|
||||
#endif
|
||||
kuap_assert_locked();
|
||||
|
||||
booke_restore_dbcr0();
|
||||
|
||||
account_cpu_user_entry();
|
||||
|
||||
account_stolen_time();
|
||||
|
||||
/*
|
||||
* This is not required for the syscall exit path, but makes the
|
||||
* stack frame look nicer. If this was initialised in the first stack
|
||||
* frame, or if the unwinder was taught the first stack frame always
|
||||
* returns to user with IRQS_ENABLED, this store could be avoided!
|
||||
*/
|
||||
irq_soft_mask_regs_set_state(regs, IRQS_ENABLED);
|
||||
|
||||
/*
|
||||
* If system call is called with TM active, set _TIF_RESTOREALL to
|
||||
* prevent RFSCV being used to return to userspace, because POWER9
|
||||
* TM implementation has problems with this instruction returning to
|
||||
* transactional state. Final register values are not relevant because
|
||||
* the transaction will be aborted upon return anyway. Or in the case
|
||||
* of unsupported_scv SIGILL fault, the return state does not much
|
||||
* matter because it's an edge case.
|
||||
*/
|
||||
if (IS_ENABLED(CONFIG_PPC_TRANSACTIONAL_MEM) &&
|
||||
unlikely(MSR_TM_TRANSACTIONAL(regs->msr)))
|
||||
set_bits(_TIF_RESTOREALL, ¤t_thread_info()->flags);
|
||||
|
||||
/*
|
||||
* If the system call was made with a transaction active, doom it and
|
||||
* return without performing the system call. Unless it was an
|
||||
* unsupported scv vector, in which case it's treated like an illegal
|
||||
* instruction.
|
||||
*/
|
||||
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
|
||||
if (unlikely(MSR_TM_TRANSACTIONAL(regs->msr)) &&
|
||||
!trap_is_unsupported_scv(regs)) {
|
||||
/* Enable TM in the kernel, and disable EE (for scv) */
|
||||
hard_irq_disable();
|
||||
mtmsr(mfmsr() | MSR_TM);
|
||||
|
||||
/* tabort, this dooms the transaction, nothing else */
|
||||
asm volatile(".long 0x7c00071d | ((%0) << 16)"
|
||||
:: "r"(TM_CAUSE_SYSCALL|TM_CAUSE_PERSISTENT));
|
||||
|
||||
/*
|
||||
* Userspace will never see the return value. Execution will
|
||||
* resume after the tbegin. of the aborted transaction with the
|
||||
* checkpointed register state. A context switch could occur
|
||||
* or signal delivered to the process before resuming the
|
||||
* doomed transaction context, but that should all be handled
|
||||
* as expected.
|
||||
*/
|
||||
return -ENOSYS;
|
||||
}
|
||||
#endif // CONFIG_PPC_TRANSACTIONAL_MEM
|
||||
|
||||
local_irq_enable();
|
||||
|
||||
if (unlikely(read_thread_flags() & _TIF_SYSCALL_DOTRACE)) {
|
||||
if (unlikely(trap_is_unsupported_scv(regs))) {
|
||||
/* Unsupported scv vector */
|
||||
_exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
|
||||
return regs->gpr[3];
|
||||
}
|
||||
/*
|
||||
* We use the return value of do_syscall_trace_enter() as the
|
||||
* syscall number. If the syscall was rejected for any reason
|
||||
* do_syscall_trace_enter() returns an invalid syscall number
|
||||
* and the test against NR_syscalls will fail and the return
|
||||
* value to be used is in regs->gpr[3].
|
||||
*/
|
||||
r0 = do_syscall_trace_enter(regs);
|
||||
if (unlikely(r0 >= NR_syscalls))
|
||||
return regs->gpr[3];
|
||||
r3 = regs->gpr[3];
|
||||
r4 = regs->gpr[4];
|
||||
r5 = regs->gpr[5];
|
||||
r6 = regs->gpr[6];
|
||||
r7 = regs->gpr[7];
|
||||
r8 = regs->gpr[8];
|
||||
|
||||
} else if (unlikely(r0 >= NR_syscalls)) {
|
||||
if (unlikely(trap_is_unsupported_scv(regs))) {
|
||||
/* Unsupported scv vector */
|
||||
_exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
|
||||
return regs->gpr[3];
|
||||
}
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
/* May be faster to do array_index_nospec? */
|
||||
barrier_nospec();
|
||||
|
||||
if (unlikely(is_compat_task())) {
|
||||
f = (void *)compat_sys_call_table[r0];
|
||||
|
||||
r3 &= 0x00000000ffffffffULL;
|
||||
r4 &= 0x00000000ffffffffULL;
|
||||
r5 &= 0x00000000ffffffffULL;
|
||||
r6 &= 0x00000000ffffffffULL;
|
||||
r7 &= 0x00000000ffffffffULL;
|
||||
r8 &= 0x00000000ffffffffULL;
|
||||
|
||||
} else {
|
||||
f = (void *)sys_call_table[r0];
|
||||
}
|
||||
|
||||
ret = f(r3, r4, r5, r6, r7, r8);
|
||||
|
||||
/*
|
||||
* Ultimately, this value will get limited by KSTACK_OFFSET_MAX(),
|
||||
* so the maximum stack offset is 1k bytes (10 bits).
|
||||
*
|
||||
* The actual entropy will be further reduced by the compiler when
|
||||
* applying stack alignment constraints: the powerpc architecture
|
||||
* may have two kinds of stack alignment (16-bytes and 8-bytes).
|
||||
*
|
||||
* So the resulting 6 or 7 bits of entropy is seen in SP[9:4] or SP[9:3].
|
||||
*/
|
||||
choose_random_kstack_offset(mftb());
|
||||
|
||||
return ret;
|
||||
}
|
@ -69,8 +69,8 @@ ftrace_modify_code(unsigned long ip, ppc_inst_t old, ppc_inst_t new)
|
||||
|
||||
/* Make sure it is what we expect it to be */
|
||||
if (!ppc_inst_equal(replaced, old)) {
|
||||
pr_err("%p: replaced (%s) != old (%s)",
|
||||
(void *)ip, ppc_inst_as_str(replaced), ppc_inst_as_str(old));
|
||||
pr_err("%p: replaced (%08lx) != old (%08lx)", (void *)ip,
|
||||
ppc_inst_as_ulong(replaced), ppc_inst_as_ulong(old));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -125,9 +125,9 @@ __ftrace_make_nop(struct module *mod,
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
/* Make sure that that this is still a 24bit jump */
|
||||
/* Make sure that this is still a 24bit jump */
|
||||
if (!is_bl_op(op)) {
|
||||
pr_err("Not expected bl: opcode is %s\n", ppc_inst_as_str(op));
|
||||
pr_err("Not expected bl: opcode is %08lx\n", ppc_inst_as_ulong(op));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -159,8 +159,8 @@ __ftrace_make_nop(struct module *mod,
|
||||
/* We expect either a mflr r0, or a std r0, LRSAVE(r1) */
|
||||
if (!ppc_inst_equal(op, ppc_inst(PPC_RAW_MFLR(_R0))) &&
|
||||
!ppc_inst_equal(op, ppc_inst(PPC_INST_STD_LR))) {
|
||||
pr_err("Unexpected instruction %s around bl _mcount\n",
|
||||
ppc_inst_as_str(op));
|
||||
pr_err("Unexpected instruction %08lx around bl _mcount\n",
|
||||
ppc_inst_as_ulong(op));
|
||||
return -EINVAL;
|
||||
}
|
||||
} else if (IS_ENABLED(CONFIG_PPC64)) {
|
||||
@ -174,7 +174,8 @@ __ftrace_make_nop(struct module *mod,
|
||||
}
|
||||
|
||||
if (!ppc_inst_equal(op, ppc_inst(PPC_INST_LD_TOC))) {
|
||||
pr_err("Expected %08lx found %s\n", PPC_INST_LD_TOC, ppc_inst_as_str(op));
|
||||
pr_err("Expected %08lx found %08lx\n", PPC_INST_LD_TOC,
|
||||
ppc_inst_as_ulong(op));
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
@ -310,9 +311,9 @@ static int __ftrace_make_nop_kernel(struct dyn_ftrace *rec, unsigned long addr)
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
/* Make sure that that this is still a 24bit jump */
|
||||
/* Make sure that this is still a 24bit jump */
|
||||
if (!is_bl_op(op)) {
|
||||
pr_err("Not expected bl: opcode is %s\n", ppc_inst_as_str(op));
|
||||
pr_err("Not expected bl: opcode is %08lx\n", ppc_inst_as_ulong(op));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -416,8 +417,8 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
|
||||
return -EFAULT;
|
||||
|
||||
if (!expected_nop_sequence(ip, op[0], op[1])) {
|
||||
pr_err("Unexpected call sequence at %p: %s %s\n",
|
||||
ip, ppc_inst_as_str(op[0]), ppc_inst_as_str(op[1]));
|
||||
pr_err("Unexpected call sequence at %p: %08lx %08lx\n", ip,
|
||||
ppc_inst_as_ulong(op[0]), ppc_inst_as_ulong(op[1]));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -486,7 +487,8 @@ static int __ftrace_make_call_kernel(struct dyn_ftrace *rec, unsigned long addr)
|
||||
}
|
||||
|
||||
if (!ppc_inst_equal(op, ppc_inst(PPC_RAW_NOP()))) {
|
||||
pr_err("Unexpected call sequence at %p: %s\n", ip, ppc_inst_as_str(op));
|
||||
pr_err("Unexpected call sequence at %p: %08lx\n",
|
||||
ip, ppc_inst_as_ulong(op));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -562,9 +564,9 @@ __ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
/* Make sure that that this is still a 24bit jump */
|
||||
/* Make sure that this is still a 24bit jump */
|
||||
if (!is_bl_op(op)) {
|
||||
pr_err("Not expected bl: opcode is %s\n", ppc_inst_as_str(op));
|
||||
pr_err("Not expected bl: opcode is %08lx\n", ppc_inst_as_ulong(op));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -1676,7 +1676,7 @@ DEFINE_INTERRUPT_HANDLER(vsx_unavailable_exception)
|
||||
die("Unrecoverable VSX Unavailable Exception", regs, SIGABRT);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
#ifdef CONFIG_PPC_BOOK3S_64
|
||||
static void tm_unavailable(struct pt_regs *regs)
|
||||
{
|
||||
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user