1
0
Fork 0

powerpc updates for 4.13

Highlights include:
 
  - Support for STRICT_KERNEL_RWX on 64-bit server CPUs.
 
  - Platform support for FSP2 (476fpe) board
 
  - Enable ZONE_DEVICE on 64-bit server CPUs.
 
  - Generic & powerpc spin loop primitives to optimise busy waiting
 
  - Convert VDSO update function to use new update_vsyscall() interface
 
  - Optimisations to hypercall/syscall/context-switch paths
 
  - Improvements to the CPU idle code on Power8 and Power9.
 
 As well as many other fixes and improvements.
 
 Thanks to:
   Akshay Adiga, Andrew Donnellan, Andrew Jeffery, Anshuman Khandual, Anton
   Blanchard, Balbir Singh, Benjamin Herrenschmidt, Christophe Leroy, Christophe
   Lombard, Colin Ian King, Dan Carpenter, Gautham R. Shenoy, Hari Bathini, Ian
   Munsie, Ivan Mikhaylov, Javier Martinez Canillas, Madhavan Srinivasan,
   Masahiro Yamada, Matt Brown, Michael Neuling, Michal Suchanek, Murilo
   Opsfelder Araujo, Naveen N. Rao, Nicholas Piggin, Oliver O'Halloran, Paul
   Mackerras, Pavel Machek, Russell Currey, Santosh Sivaraj, Stephen Rothwell,
   Thiago Jung Bauermann, Yang Li.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABAgAGBQJZXyPCAAoJEFHr6jzI4aWAI9QQAISf2x5y//cqCi4ISyQB5pTq
 KLS/yQajNkQOw7c0fzBZOaH5Xd/SJ6AcKWDg8yDlpDR3+sRRsr98iIRECgKS5I7/
 DxD9ywcbSoMXFQQo1ZMCp5CeuMUIJRtugBnUQM+JXCSUCPbznCY5DchDTLyTBTpO
 MeMVhI//JxthhoOMA9MudiEGaYCU9ho442Z4OJUSiLUv8WRbvQX9pTqoc4vx1fxA
 BWf2mflztBVcIfKIyxIIIlDLukkMzix6gSYPMCbC7lzkbnU7JSqKiheJXjo1gJS2
 ePHKDxeNR2/QP0g/j3aT/MR1uTt9MaNBSX3gANE1xQ9OoJ8m1sOtCO4gNbSdLWae
 eXhDnoiEp930DRZOeEioOItuWWoxFaMyYk3BMmRKV4QNdYL3y3TRVeL2/XmRGqYL
 Lxz4IY/x5TteFEJNGcRX90uizNSi8AaEXPF16pUk8Ctt6eH3ZSwPMv2fHeYVCMr0
 KFlKHyaPEKEoztyzLcUR6u9QB56yxDN58bvLpd32AeHvKhqyxFoySy59x9bZbatn
 B2y8mmDItg860e0tIG6jrtplpOVvL8i5jla5RWFVoQDuxxrLAds3vG9JZQs+eRzx
 Fiic93bqeUAS6RzhXbJ6QQJYIyhE7yqpcgv7ME1W87SPef3HPBk9xlp3yIDwdA2z
 bBDvrRnvupusz8qCWrxe
 =w8rj
 -----END PGP SIGNATURE-----

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

Pull powerpc updates from Michael Ellerman:
 "Highlights include:

   - Support for STRICT_KERNEL_RWX on 64-bit server CPUs.

   - Platform support for FSP2 (476fpe) board

   - Enable ZONE_DEVICE on 64-bit server CPUs.

   - Generic & powerpc spin loop primitives to optimise busy waiting

   - Convert VDSO update function to use new update_vsyscall() interface

   - Optimisations to hypercall/syscall/context-switch paths

   - Improvements to the CPU idle code on Power8 and Power9.

  As well as many other fixes and improvements.

  Thanks to: Akshay Adiga, Andrew Donnellan, Andrew Jeffery, Anshuman
  Khandual, Anton Blanchard, Balbir Singh, Benjamin Herrenschmidt,
  Christophe Leroy, Christophe Lombard, Colin Ian King, Dan Carpenter,
  Gautham R. Shenoy, Hari Bathini, Ian Munsie, Ivan Mikhaylov, Javier
  Martinez Canillas, Madhavan Srinivasan, Masahiro Yamada, Matt Brown,
  Michael Neuling, Michal Suchanek, Murilo Opsfelder Araujo, Naveen N.
  Rao, Nicholas Piggin, Oliver O'Halloran, Paul Mackerras, Pavel Machek,
  Russell Currey, Santosh Sivaraj, Stephen Rothwell, Thiago Jung
  Bauermann, Yang Li"

* tag 'powerpc-4.13-1' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux: (158 commits)
  powerpc/Kconfig: Enable STRICT_KERNEL_RWX for some configs
  powerpc/mm/radix: Implement STRICT_RWX/mark_rodata_ro() for Radix
  powerpc/mm/hash: Implement mark_rodata_ro() for hash
  powerpc/vmlinux.lds: Align __init_begin to 16M
  powerpc/lib/code-patching: Use alternate map for patch_instruction()
  powerpc/xmon: Add patch_instruction() support for xmon
  powerpc/kprobes/optprobes: Use patch_instruction()
  powerpc/kprobes: Move kprobes over to patch_instruction()
  powerpc/mm/radix: Fix execute permissions for interrupt_vectors
  powerpc/pseries: Fix passing of pp0 in updatepp() and updateboltedpp()
  powerpc/64s: Blacklist rtas entry/exit from kprobes
  powerpc/64s: Blacklist functions invoked on a trap
  powerpc/64s: Un-blacklist system_call() from kprobes
  powerpc/64s: Move system_call() symbol to just after setting MSR_EE
  powerpc/64s: Blacklist system_call() and system_call_common() from kprobes
  powerpc/64s: Convert .L__replay_interrupt_return to a local label
  powerpc64/elfv1: Only dereference function descriptor for non-text symbols
  cxl: Export library to support IBM XSL
  powerpc/dts: Use #include "..." to include local DT
  powerpc/perf/hv-24x7: Aggregate result elements on POWER9 SMT8
  ...
zero-colors
Linus Torvalds 2017-07-07 13:55:45 -07:00
commit d691b7e7d1
161 changed files with 4327 additions and 1081 deletions

View File

@ -61,8 +61,8 @@ as follows:
boot successfully. For syntax of crashkernel= parameter,
refer to Documentation/kdump/kdump.txt. If any offset is
provided in crashkernel= parameter, it will be ignored
as fadump reserves memory at end of RAM for boot memory
dump preservation in case of a crash.
as fadump uses a predefined offset to reserve memory
for boot memory dump preservation in case of a crash.
-- After the low memory (boot memory) area has been saved, the
firmware will reset PCI and other hardware state. It will

View File

@ -3781,8 +3781,8 @@ S: Supported
F: drivers/net/ethernet/chelsio/cxgb4vf/
CXL (IBM Coherent Accelerator Processor Interface CAPI) DRIVER
M: Ian Munsie <imunsie@au1.ibm.com>
M: Frederic Barrat <fbarrat@linux.vnet.ibm.com>
M: Andrew Donnellan <andrew.donnellan@au1.ibm.com>
L: linuxppc-dev@lists.ozlabs.org
S: Supported
F: arch/powerpc/platforms/powernv/pci-cxl.c
@ -5352,7 +5352,7 @@ S: Maintained
F: drivers/video/fbdev/fsl-diu-fb.*
FREESCALE DMA DRIVER
M: Li Yang <leoli@freescale.com>
M: Li Yang <leoyang.li@nxp.com>
M: Zhang Wei <zw@zh-kernel.org>
L: linuxppc-dev@lists.ozlabs.org
S: Maintained
@ -5417,11 +5417,11 @@ S: Maintained
F: drivers/net/ethernet/freescale/dpaa
FREESCALE SOC DRIVERS
M: Scott Wood <oss@buserror.net>
M: Li Yang <leoyang.li@nxp.com>
L: linuxppc-dev@lists.ozlabs.org
L: linux-arm-kernel@lists.infradead.org
S: Maintained
F: Documentation/devicetree/bindings/powerpc/fsl/
F: Documentation/devicetree/bindings/soc/fsl/
F: drivers/soc/fsl/
F: include/linux/fsl/
@ -5434,14 +5434,14 @@ F: include/soc/fsl/*qe*.h
F: include/soc/fsl/*ucc*.h
FREESCALE USB PERIPHERAL DRIVERS
M: Li Yang <leoli@freescale.com>
M: Li Yang <leoyang.li@nxp.com>
L: linux-usb@vger.kernel.org
L: linuxppc-dev@lists.ozlabs.org
S: Maintained
F: drivers/usb/gadget/udc/fsl*
FREESCALE QUICC ENGINE UCC ETHERNET DRIVER
M: Li Yang <leoli@freescale.com>
M: Li Yang <leoyang.li@nxp.com>
L: netdev@vger.kernel.org
L: linuxppc-dev@lists.ozlabs.org
S: Maintained
@ -7784,6 +7784,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/scottwood/linux.git
S: Maintained
F: arch/powerpc/platforms/83xx/
F: arch/powerpc/platforms/85xx/
F: Documentation/devicetree/bindings/powerpc/fsl/
LINUX FOR POWERPC PA SEMI PWRFICIENT
L: linuxppc-dev@lists.ozlabs.org

View File

@ -109,14 +109,6 @@ config GENERIC_LOCKBREAK
default y
depends on SMP && PREEMPT
config ARCH_HAS_ILOG2_U32
bool
default y
config ARCH_HAS_ILOG2_U64
bool
default y if 64BIT
config GENERIC_HWEIGHT
bool
default y
@ -138,6 +130,7 @@ config PPC
select ARCH_HAS_SG_CHAIN
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
select ARCH_HAS_UBSAN_SANITIZE_ALL
select ARCH_HAS_ZONE_DEVICE if PPC_BOOK3S_64
select ARCH_HAVE_NMI_SAFE_CMPXCHG
select ARCH_MIGHT_HAVE_PC_PARPORT
select ARCH_MIGHT_HAVE_PC_SERIO
@ -163,7 +156,7 @@ config PPC
select GENERIC_SMP_IDLE_THREAD
select GENERIC_STRNCPY_FROM_USER
select GENERIC_STRNLEN_USER
select GENERIC_TIME_VSYSCALL_OLD
select GENERIC_TIME_VSYSCALL
select HAVE_ARCH_AUDITSYSCALL
select HAVE_ARCH_JUMP_LABEL
select HAVE_ARCH_KGDB
@ -171,6 +164,8 @@ config PPC
select HAVE_ARCH_MMAP_RND_COMPAT_BITS if COMPAT
select HAVE_ARCH_SECCOMP_FILTER
select HAVE_ARCH_TRACEHOOK
select ARCH_HAS_STRICT_KERNEL_RWX if (PPC_BOOK3S_64 && !RELOCATABLE && !HIBERNATION)
select ARCH_OPTIONAL_KERNEL_RWX if ARCH_HAS_STRICT_KERNEL_RWX
select HAVE_CBPF_JIT if !PPC64
select HAVE_CONTEXT_TRACKING if PPC64
select HAVE_DEBUG_KMEMLEAK
@ -208,6 +203,7 @@ config PPC
select HAVE_REGS_AND_STACK_ACCESS_API
select HAVE_SYSCALL_TRACEPOINTS
select HAVE_VIRT_CPU_ACCOUNTING
select HAVE_IRQ_TIME_ACCOUNTING
select IRQ_DOMAIN
select IRQ_FORCED_THREADING
select MODULES_USE_ELF_RELA
@ -438,6 +434,17 @@ config PPC_TRANSACTIONAL_MEM
---help---
Support user-mode Transactional Memory on POWERPC.
config LD_HEAD_STUB_CATCH
bool "Reserve 256 bytes to cope with linker stubs in HEAD text" if EXPERT
depends on PPC64
default n
help
Very large kernels can cause linker branch stubs to be generated by
code in head_64.S, which moves the head text sections out of their
specified location. This option can work around the problem.
If unsure, say "N".
config DISABLE_MPROFILE_KERNEL
bool "Disable use of mprofile-kernel for kernel tracing"
depends on PPC64 && CPU_LITTLE_ENDIAN

View File

@ -98,6 +98,7 @@ endif
LDFLAGS_vmlinux-y := -Bstatic
LDFLAGS_vmlinux-$(CONFIG_RELOCATABLE) := -pie
LDFLAGS_vmlinux := $(LDFLAGS_vmlinux-y)
LDFLAGS_vmlinux += $(call ld-option,--orphan-handling=warn)
ifeq ($(CONFIG_PPC64),y)
ifeq ($(call cc-option-yn,-mcmodel=medium),y)
@ -189,7 +190,17 @@ else
CHECKFLAGS += -D__LITTLE_ENDIAN__
endif
ifdef CONFIG_PPC32
KBUILD_LDFLAGS_MODULE += arch/powerpc/lib/crtsavres.o
else
ifeq ($(call ld-ifversion, -ge, 225000000, y),y)
# Have the linker provide sfpr if possible.
# There is a corresponding test in arch/powerpc/lib/Makefile
KBUILD_LDFLAGS_MODULE += --save-restore-funcs
else
KBUILD_LDFLAGS_MODULE += arch/powerpc/lib/crtsavres.o
endif
endif
ifeq ($(CONFIG_476FPE_ERR46),y)
KBUILD_LDFLAGS_MODULE += --ppc476-workaround \

View File

@ -10,13 +10,26 @@ __archpost:
-include include/config/auto.conf
include scripts/Kbuild.include
quiet_cmd_head_check = CHKHEAD $@
cmd_head_check = $(CONFIG_SHELL) $(srctree)/arch/powerpc/tools/head_check.sh "$(NM)" "$@"
quiet_cmd_relocs_check = CHKREL $@
cmd_relocs_check = $(CONFIG_SHELL) $(srctree)/arch/powerpc/tools/relocs_check.sh "$(OBJDUMP)" "$@"
ifdef CONFIG_PPC_BOOK3S_64
cmd_relocs_check = \
$(CONFIG_SHELL) $(srctree)/arch/powerpc/tools/relocs_check.sh "$(OBJDUMP)" "$@" ; \
$(CONFIG_SHELL) $(srctree)/arch/powerpc/tools/unrel_branch_check.sh "$(OBJDUMP)" "$@"
else
cmd_relocs_check = \
$(CONFIG_SHELL) $(srctree)/arch/powerpc/tools/relocs_check.sh "$(OBJDUMP)" "$@"
endif
# `@true` prevents complaint when there is nothing to be done
vmlinux: FORCE
@true
ifdef CONFIG_PPC64
$(call cmd,head_check)
endif
ifdef CONFIG_RELOCATABLE
$(call if_changed,relocs_check)
endif
@ -25,7 +38,7 @@ endif
@true
clean:
@true
rm -f .tmp_symbols.txt
PHONY += FORCE clean

View File

@ -95,13 +95,16 @@ libfdtheader := fdt.h libfdt.h libfdt_internal.h
$(addprefix $(obj)/,$(libfdt) libfdt-wrapper.o simpleboot.o epapr.o opal.o): \
$(addprefix $(obj)/,$(libfdtheader))
src-wlib-y := string.S crt0.S crtsavres.S stdio.c decompress.c main.c \
src-wlib-y := string.S crt0.S stdio.c decompress.c main.c \
$(libfdt) libfdt-wrapper.c \
ns16550.c serial.c simple_alloc.c div64.S util.S \
elf_util.c $(zlib-y) devtree.c stdlib.c \
oflib.c ofconsole.c cuboot.c mpsc.c cpm-serial.c \
uartlite.c mpc52xx-psc.c opal.c
src-wlib-$(CONFIG_PPC64_BOOT_WRAPPER) += opal-calls.S
ifndef CONFIG_PPC64_BOOT_WRAPPER
src-wlib-y += crtsavres.S
endif
src-wlib-$(CONFIG_40x) += 4xx.c planetcore.c
src-wlib-$(CONFIG_44x) += 4xx.c ebony.c bamboo.c
src-wlib-$(CONFIG_8xx) += mpc8xx.c planetcore.c fsl-soc.c

View File

@ -37,12 +37,13 @@
* the executable file might be covered by the GNU General Public License.
*/
#ifdef __powerpc64__
#error "On PPC64, FPR save/restore functions are provided by the linker."
#endif
.file "crtsavres.S"
.section ".text"
/* On PowerPC64 Linux, these functions are provided by the linker. */
#ifndef __powerpc64__
#define _GLOBAL(name) \
.type name,@function; \
.globl name; \
@ -230,4 +231,3 @@ _GLOBAL(_rest32gpr_31_x)
mtlr 0
mr 1,11
blr
#endif

View File

@ -10,7 +10,7 @@
*/
#include <mpc5121.dtsi>
#include "mpc5121.dtsi"
/ {
model = "ac14xx";

View File

@ -73,7 +73,7 @@
i2c@3d00 {
eeprom@50 {
compatible = "at,24c08";
compatible = "atmel,24c08";
reg = <0x50>;
};

View File

@ -166,19 +166,19 @@
reg = <0>;
eeprom@50 {
compatible = "at24,24c64";
compatible = "atmel,24c64";
reg = <0x50>;
};
eeprom@51 {
compatible = "at24,24c256";
compatible = "atmel,24c256";
reg = <0x51>;
};
eeprom@53 {
compatible = "at24,24c256";
compatible = "atmel,24c256";
reg = <0x53>;
};
eeprom@57 {
compatible = "at24,24c256";
compatible = "atmel,24c256";
reg = <0x57>;
};
rtc@68 {

View File

@ -153,7 +153,7 @@
&soc {
i2c@3000 {
eeprom@50 {
compatible = "st,24c1024";
compatible = "st,24c1024", "atmel,24c1024";
reg = <0x50>;
};

View File

@ -89,7 +89,7 @@
&board_soc {
i2c@3000 {
eeprom@50 {
compatible = "st,24c256";
compatible = "st,24c256", "atmel,24c256";
reg = <0x50>;
};

View File

@ -79,7 +79,7 @@
i2c@3000 {
eeprom@53 {
compatible = "at24,24c04";
compatible = "atmel,24c04";
reg = <0x53>;
};

View File

@ -127,7 +127,7 @@
reg = <0x48>;
};
eeprom@50 {
compatible = "at24,24c256";
compatible = "atmel,24c256";
reg = <0x50>;
};
rtc@68 {
@ -142,7 +142,7 @@
i2c@118100 {
eeprom@50 {
compatible = "at24,24c256";
compatible = "atmel,24c256";
reg = <0x50>;
};
};

View File

@ -124,11 +124,11 @@
i2c@118100 {
eeprom@51 {
compatible = "at24,24c256";
compatible = "atmel,24c256";
reg = <0x51>;
};
eeprom@52 {
compatible = "at24,24c256";
compatible = "atmel,24c256";
reg = <0x52>;
};
};

View File

@ -125,11 +125,11 @@
i2c@118100 {
eeprom@51 {
compatible = "at24,24c256";
compatible = "atmel,24c256";
reg = <0x51>;
};
eeprom@52 {
compatible = "at24,24c256";
compatible = "atmel,24c256";
reg = <0x52>;
};
rtc@68 {

View File

@ -124,11 +124,11 @@
i2c@118100 {
eeprom@51 {
compatible = "at24,24c256";
compatible = "atmel,24c256";
reg = <0x51>;
};
eeprom@52 {
compatible = "at24,24c256";
compatible = "atmel,24c256";
reg = <0x52>;
};
};

View File

@ -133,11 +133,11 @@
i2c@118100 {
eeprom@51 {
compatible = "at24,24c256";
compatible = "atmel,24c256";
reg = <0x51>;
};
eeprom@52 {
compatible = "at24,24c256";
compatible = "atmel,24c256";
reg = <0x52>;
};
};

View File

@ -147,17 +147,17 @@
reg = <0x0>;
eeprom@50 {
compatible = "at24,24c512";
compatible = "atmel,24c512";
reg = <0x50>;
};
eeprom@51 {
compatible = "at24,24c02";
compatible = "atmel,24c02";
reg = <0x51>;
};
eeprom@57 {
compatible = "at24,24c02";
compatible = "atmel,24c02";
reg = <0x57>;
};
@ -174,7 +174,7 @@
reg = <0x1>;
eeprom@55 {
compatible = "at24,24c02";
compatible = "atmel,24c02";
reg = <0x55>;
};
};

View File

@ -377,27 +377,27 @@
reg = <0>;
eeprom@51 {
compatible = "at24,24c256";
compatible = "atmel,24c256";
reg = <0x51>;
};
eeprom@52 {
compatible = "at24,24c256";
compatible = "atmel,24c256";
reg = <0x52>;
};
eeprom@53 {
compatible = "at24,24c256";
compatible = "atmel,24c256";
reg = <0x53>;
};
eeprom@54 {
compatible = "at24,24c256";
compatible = "atmel,24c256";
reg = <0x54>;
};
eeprom@55 {
compatible = "at24,24c256";
compatible = "atmel,24c256";
reg = <0x55>;
};
eeprom@56 {
compatible = "at24,24c256";
compatible = "atmel,24c256";
reg = <0x56>;
};
rtc@68 {

View File

@ -130,15 +130,15 @@
reg = <0x2f>;
};
eeprom@52 {
compatible = "at24,24c256";
compatible = "atmel,24c256";
reg = <0x52>;
};
eeprom@54 {
compatible = "at24,24c256";
compatible = "atmel,24c256";
reg = <0x54>;
};
eeprom@56 {
compatible = "at24,24c256";
compatible = "atmel,24c256";
reg = <0x56>;
};
rtc@68 {

View File

@ -0,0 +1,608 @@
/*
* Device Tree Source for FSP2
*
* Copyright 2010,2012 IBM Corp.
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without
* any warranty of any kind, whether express or implied.
*/
/dts-v1/;
/ {
#address-cells = <2>;
#size-cells = <1>;
model = "ibm,fsp2";
compatible = "ibm,fsp2";
dcr-parent = <&{/cpus/cpu@0}>;
aliases {
ethernet0 = &EMAC0;
ethernet1 = &EMAC1;
serial0 = &UART0;
};
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu@0 {
device_type = "cpu";
model = "PowerPC, 476FSP2";
reg = <0x0>;
clock-frequency = <0>; /* Filled in by cuboot */
timebase-frequency = <0>; /* Filled in by cuboot */
i-cache-line-size = <32>;
d-cache-line-size = <32>;
d-cache-size = <32768>;
i-cache-size = <32768>;
dcr-controller;
dcr-access-method = "native";
};
};
memory {
device_type = "memory";
reg = <0x00000000 0x00000000 0x00000000>; /* Filled in by
cuboot */
};
clocks {
mmc_clk: mmc_clk {
compatible = "fixed-clock";
clock-frequency = <50000000>;
clock-output-names = "mmc_clk";
};
};
UIC0: uic0 {
#address-cells = <0>;
#size-cells = <0>;
#interrupt-cells = <2>;
compatible = "ibm,uic";
interrupt-controller;
cell-index = <0>;
dcr-reg = <0x2c0 0x8>;
};
/* "interrupts" field is <bit level bit level>
first pair is non-critical, second is critical */
UIC1_0: uic1_0 {
#address-cells = <0>;
#size-cells = <0>;
#interrupt-cells = <2>;
compatible = "ibm,uic";
interrupt-controller;
cell-index = <1>;
dcr-reg = <0x2c8 0x8>;
interrupt-parent = <&UIC0>;
interrupts = <21 0x4 4 0x84>;
};
/* PSI and DMA */
UIC1_1: uic1_1 {
#address-cells = <0>;
#size-cells = <0>;
#interrupt-cells = <2>;
compatible = "ibm,uic";
interrupt-controller;
cell-index = <2>;
dcr-reg = <0x350 0x8>;
interrupt-parent = <&UIC0>;
interrupts = <22 0x4 5 0x84>;
};
/* Ethernet and USB */
UIC1_2: uic1_2 {
#address-cells = <0>;
#size-cells = <0>;
#interrupt-cells = <2>;
compatible = "ibm,uic";
interrupt-controller;
cell-index = <3>;
dcr-reg = <0x358 0x8>;
interrupt-parent = <&UIC0>;
interrupts = <23 0x4 6 0x84>;
};
/* PLB Errors */
UIC1_3: uic1_3 {
#address-cells = <0>;
#size-cells = <0>;
#interrupt-cells = <2>;
compatible = "ibm,uic";
interrupt-controller;
cell-index = <4>;
dcr-reg = <0x360 0x8>;
interrupt-parent = <&UIC0>;
interrupts = <24 0x4 7 0x84>;
};
UIC1_4: uic1_4 {
#address-cells = <0>;
#size-cells = <0>;
#interrupt-cells = <2>;
compatible = "ibm,uic";
interrupt-controller;
cell-index = <5>;
dcr-reg = <0x368 0x8>;
interrupt-parent = <&UIC0>;
interrupts = <25 0x4 8 0x84>;
};
UIC1_5: uic1_5 {
#address-cells = <0>;
#size-cells = <0>;
#interrupt-cells = <2>;
compatible = "ibm,uic";
interrupt-controller;
cell-index = <6>;
dcr-reg = <0x370 0x8>;
interrupt-parent = <&UIC0>;
interrupts = <26 0x4 9 0x84>;
};
/* 2nd level UICs for FSI */
UIC2_0: uic2_0 {
#address-cells = <0>;
#size-cells = <0>;
#interrupt-cells = <2>;
compatible = "ibm,uic";
interrupt-controller;
cell-index = <7>;
dcr-reg = <0x2d0 0x8>;
interrupt-parent = <&UIC1_0>;
interrupts = <16 0x4 0 0x84>;
};
UIC2_1: uic2_1 {
#address-cells = <0>;
#size-cells = <0>;
#interrupt-cells = <2>;
compatible = "ibm,uic";
interrupt-controller;
cell-index = <8>;
dcr-reg = <0x2d8 0x8>;
interrupt-parent = <&UIC1_0>;
interrupts = <17 0x4 1 0x84>;
};
UIC2_2: uic2_2 {
#address-cells = <0>;
#size-cells = <0>;
#interrupt-cells = <2>;
compatible = "ibm,uic";
interrupt-controller;
cell-index = <9>;
dcr-reg = <0x2e0 0x8>;
interrupt-parent = <&UIC1_0>;
interrupts = <18 0x4 2 0x84>;
};
UIC2_3: uic2_3 {
#address-cells = <0>;
#size-cells = <0>;
#interrupt-cells = <2>;
compatible = "ibm,uic";
interrupt-controller;
cell-index = <10>;
dcr-reg = <0x2e8 0x8>;
interrupt-parent = <&UIC1_0>;
interrupts = <19 0x4 3 0x84>;
};
UIC2_4: uic2_4 {
#address-cells = <0>;
#size-cells = <0>;
#interrupt-cells = <2>;
compatible = "ibm,uic";
interrupt-controller;
cell-index = <11>;
dcr-reg = <0x2f0 0x8>;
interrupt-parent = <&UIC1_0>;
interrupts = <20 0x4 4 0x84>;
};
UIC2_5: uic2_5 {
#address-cells = <0>;
#size-cells = <0>;
#interrupt-cells = <2>;
compatible = "ibm,uic";
interrupt-controller;
cell-index = <12>;
dcr-reg = <0x2f8 0x8>;
interrupt-parent = <&UIC1_0>;
interrupts = <21 0x4 5 0x84>;
};
UIC2_6: uic2_6 {
#address-cells = <0>;
#size-cells = <0>;
#interrupt-cells = <2>;
compatible = "ibm,uic";
interrupt-controller;
cell-index = <13>;
dcr-reg = <0x300 0x8>;
interrupt-parent = <&UIC1_0>;
interrupts = <22 0x4 6 0x84>;
};
UIC2_7: uic2_7 {
#address-cells = <0>;
#size-cells = <0>;
#interrupt-cells = <2>;
compatible = "ibm,uic";
interrupt-controller;
cell-index = <14>;
dcr-reg = <0x308 0x8>;
interrupt-parent = <&UIC1_0>;
interrupts = <23 0x4 7 0x84>;
};
UIC2_8: uic2_8 {
#address-cells = <0>;
#size-cells = <0>;
#interrupt-cells = <2>;
compatible = "ibm,uic";
interrupt-controller;
cell-index = <15>;
dcr-reg = <0x310 0x8>;
interrupt-parent = <&UIC1_0>;
interrupts = <24 0x4 8 0x84>;
};
UIC2_9: uic2_9 {
#address-cells = <0>;
#size-cells = <0>;
#interrupt-cells = <2>;
compatible = "ibm,uic";
interrupt-controller;
cell-index = <16>;
dcr-reg = <0x318 0x8>;
interrupt-parent = <&UIC1_0>;
interrupts = <25 0x4 9 0x84>;
};
UIC2_10: uic2_10 {
#address-cells = <0>;
#size-cells = <0>;
#interrupt-cells = <2>;
compatible = "ibm,uic";
interrupt-controller;
cell-index = <17>;
dcr-reg = <0x320 0x8>;
interrupt-parent = <&UIC1_0>;
interrupts = <26 0x4 10 0x84>;
};
UIC2_11: uic2_11 {
#address-cells = <0>;
#size-cells = <0>;
#interrupt-cells = <2>;
compatible = "ibm,uic";
interrupt-controller;
cell-index = <18>;
dcr-reg = <0x328 0x8>;
interrupt-parent = <&UIC1_0>;
interrupts = <27 0x4 11 0x84>;
};
UIC2_12: uic2_12 {
#address-cells = <0>;
#size-cells = <0>;
#interrupt-cells = <2>;
compatible = "ibm,uic";
interrupt-controller;
cell-index = <19>;
dcr-reg = <0x330 0x8>;
interrupt-parent = <&UIC1_0>;
interrupts = <28 0x4 12 0x84>;
};
UIC2_13: uic2_13 {
#address-cells = <0>;
#size-cells = <0>;
#interrupt-cells = <2>;
compatible = "ibm,uic";
interrupt-controller;
cell-index = <20>;
dcr-reg = <0x338 0x8>;
interrupt-parent = <&UIC1_0>;
interrupts = <29 0x4 13 0x84>;
};
UIC2_14: uic2_14 {
#address-cells = <0>;
#size-cells = <0>;
#interrupt-cells = <2>;
compatible = "ibm,uic";
interrupt-controller;
cell-index = <21>;
dcr-reg = <0x340 0x8>;
interrupt-parent = <&UIC1_0>;
interrupts = <30 0x4 14 0x84>;
};
UIC2_15: uic2_15 {
#address-cells = <0>;
#size-cells = <0>;
#interrupt-cells = <2>;
compatible = "ibm,uic";
interrupt-controller;
cell-index = <22>;
dcr-reg = <0x348 0x8>;
interrupt-parent = <&UIC1_0>;
interrupts = <31 0x4 15 0x84>;
};
mmc0: sdhci@020c0000 {
compatible = "st,sdhci-stih407", "st,sdhci";
status = "disabled";
reg = <0x020c0000 0x20000>;
reg-names = "mmc";
interrupt-parent = <&UIC1_3>;
interrupts = <21 0x4 22 0x4>;
interrupt-names = "mmcirq";
pinctrl-names = "default";
pinctrl-0 = <>;
clock-names = "mmc";
clocks = <&mmc_clk>;
};
plb6 {
compatible = "ibm,plb6";
#address-cells = <2>;
#size-cells = <1>;
ranges;
MCW0: memory-controller-wrapper {
compatible = "ibm,cw-476fsp2";
dcr-reg = <0x11111800 0x40>;
};
MCIF0: memory-controller {
compatible = "ibm,sdram-476fsp2", "ibm,sdram-4xx-ddr3";
dcr-reg = <0x11120000 0x10000>;
mcer-device = <&MCW0>;
interrupt-parent = <&UIC0>;
interrupts = <10 0x84 /* ECC UE */
11 0x84>; /* ECC CE */
};
};
plb4 {
compatible = "ibm,plb4";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x00000000 0x00000010 0x00000000 0x80000000
0x80000000 0x00000010 0x80000000 0x80000000>;
clock-frequency = <333333334>;
plb6-system-hung-irq {
compatible = "ibm,bus-error-irq";
#interrupt-cells = <2>;
interrupt-parent = <&UIC0>;
interrupts = <0 0x84>;
};
l2-error-irq {
compatible = "ibm,bus-error-irq";
#interrupt-cells = <2>;
interrupt-parent = <&UIC0>;
interrupts = <20 0x84>;
};
plb6-plb4-irq {
compatible = "ibm,bus-error-irq";
#interrupt-cells = <2>;
interrupt-parent = <&UIC0>;
interrupts = <1 0x84>;
};
plb4-ahb-irq {
compatible = "ibm,bus-error-irq";
#interrupt-cells = <2>;
interrupt-parent = <&UIC1_3>;
interrupts = <20 0x84>;
};
opbd-error-irq {
compatible = "ibm,opbd-error-irq";
#interrupt-cells = <2>;
interrupt-parent = <&UIC1_4>;
interrupts = <5 0x84>;
};
cmu-error-irq {
compatible = "ibm,cmu-error-irq";
#interrupt-cells = <2>;
interrupt-parent = <&UIC0>;
interrupts = <28 0x84>;
};
conf-error-irq {
compatible = "ibm,conf-error-irq";
#interrupt-cells = <2>;
interrupt-parent = <&UIC1_4>;
interrupts = <11 0x84>;
};
mc-ue-irq {
compatible = "ibm,mc-ue-irq";
#interrupt-cells = <2>;
interrupt-parent = <&UIC0>;
interrupts = <10 0x84>;
};
reset-warning-irq {
compatible = "ibm,reset-warning-irq";
#interrupt-cells = <2>;
interrupt-parent = <&UIC0>;
interrupts = <17 0x84>;
};
MAL0: mcmal0 {
#interrupt-cells = <1>;
#address-cells = <0>;
#size-cells = <0>;
compatible = "ibm,mcmal";
dcr-reg = <0x80 0x80>;
num-tx-chans = <1>;
num-rx-chans = <1>;
interrupt-parent = <&MAL0>;
interrupts = <0 1 2 3 4>;
/* index interrupt-parent interrupt# type */
interrupt-map = </*TXEOB*/ 0 &UIC1_2 4 0x4
/*RXEOB*/ 1 &UIC1_2 3 0x4
/*SERR*/ 2 &UIC1_2 7 0x4
/*TXDE*/ 3 &UIC1_2 6 0x4
/*RXDE*/ 4 &UIC1_2 5 0x4>;
};
MAL1: mcmal1 {
#interrupt-cells = <1>;
#address-cells = <0>;
#size-cells = <0>;
compatible = "ibm,mcmal";
dcr-reg = <0x100 0x80>;
num-tx-chans = <1>;
num-rx-chans = <1>;
interrupt-parent = <&MAL1>;
interrupts = <0 1 2 3 4>;
/* index interrupt-parent interrupt# type */
interrupt-map = </*TXEOB*/ 0 &UIC1_2 12 0x4
/*RXEOB*/ 1 &UIC1_2 11 0x4
/*SERR*/ 2 &UIC1_2 15 0x4
/*TXDE*/ 3 &UIC1_2 14 0x4
/*RXDE*/ 4 &UIC1_2 13 0x4>;
};
opb {
compatible = "ibm,opb";
#address-cells = <1>;
#size-cells = <1>;
ranges; // pass-thru to parent bus
clock-frequency = <83333334>;
EMAC0: ethernet@b0000000 {
linux,network-index = <0>;
device_type = "network";
compatible = "ibm,emac4sync";
has-inverted-stacr-oc;
interrupt-parent = <&UIC1_2>;
interrupts = <1 0x4 0 0x4>;
reg = <0xb0000000 0x100>;
local-mac-address = [000000000000]; /* Filled in by
cuboot */
mal-device = <&MAL0>;
mal-tx-channel = <0>;
mal-rx-channel = <0>;
cell-index = <0>;
max-frame-size = <1500>;
rx-fifo-size = <4096>;
tx-fifo-size = <4096>;
rx-fifo-size-gige = <16384>;
tx-fifo-size-gige = <8192>;
phy-address = <1>;
phy-mode = "rgmii";
phy-map = <00000003>;
rgmii-device = <&RGMII>;
rgmii-channel = <0>;
};
EMAC1: ethernet@b0000100 {
linux,network-index = <1>;
device_type = "network";
compatible = "ibm,emac4sync";
has-inverted-stacr-oc;
interrupt-parent = <&UIC1_2>;
interrupts = <9 0x4 8 0x4>;
reg = <0xb0000100 0x100>;
local-mac-address = [000000000000]; /* Filled in by
cuboot */
mal-device = <&MAL1>;
mal-tx-channel = <0>;
mal-rx-channel = <0>;
cell-index = <1>;
max-frame-size = <1500>;
rx-fifo-size = <4096>;
tx-fifo-size = <4096>;
rx-fifo-size-gige = <16384>;
tx-fifo-size-gige = <8192>;
phy-address = <2>;
phy-mode = "rgmii";
phy-map = <00000003>;
rgmii-device = <&RGMII>;
rgmii-channel = <1>;
};
RGMII: rgmii@b0000600 {
compatible = "ibm,rgmii";
has-mdio;
reg = <0xb0000600 0x8>;
};
UART0: serial@b0020000 {
device_type = "serial";
compatible = "ns16550";
reg = <0xb0020000 0x8>;
virtual-reg = <0xb0020000>;
clock-frequency = <20833333>;
current-speed = <115200>;
interrupt-parent = <&UIC0>;
interrupts = <31 0x4>;
};
};
OHCI1: ohci@02040000 {
compatible = "ohci-le";
reg = <0x02040000 0xa0>;
interrupt-parent = <&UIC1_3>;
interrupts = <28 0x8 29 0x8>;
};
OHCI2: ohci@02080000 {
compatible = "ohci-le";
reg = <0x02080000 0xa0>;
interrupt-parent = <&UIC1_3>;
interrupts = <30 0x8 31 0x8>;
};
EHCI: ehci@02000000 {
compatible = "usb-ehci";
reg = <0x02000000 0xa4>;
interrupt-parent = <&UIC1_3>;
interrupts = <23 0x4>;
};
};
chosen {
linux,stdout-path = "/plb/opb/serial@b0020000";
bootargs = "console=ttyS0,115200 rw log_buf_len=32768 debug";
};
};

View File

@ -9,7 +9,7 @@
* option) any later version.
*/
#include <mpc5121.dtsi>
#include "mpc5121.dtsi"
/ {
model = "mpc5121ads";
@ -94,7 +94,7 @@
};
eeprom@50 {
compatible = "at,24c32";
compatible = "atmel,24c32";
reg = <0x50>;
};

View File

@ -123,7 +123,7 @@
interrupt-parent = <&ipic>;
dfsrr;
fram@50 {
compatible = "ramtron,24c64";
compatible = "ramtron,24c64", "atmel,24c64";
reg = <0x50>;
};
};

View File

@ -92,7 +92,7 @@
dfsrr;
eeprom: at24@50 {
compatible = "st,24c256";
compatible = "st,24c256", "atmel,24c256";
reg = <0x50>;
};
@ -130,7 +130,7 @@
};
spd: at24@51 {
compatible = "at24,spd";
compatible = "atmel,spd";
reg = <0x51>;
};

View File

@ -150,7 +150,7 @@
};
at24@50 {
compatible = "at24,24c256";
compatible = "atmel,24c256";
reg = <0x50>;
};

View File

@ -135,7 +135,7 @@
dfsrr;
at24@50 {
compatible = "at24,24c256";
compatible = "atmel,24c256";
reg = <0x50>;
};

View File

@ -150,7 +150,7 @@
};
at24@50 {
compatible = "at24,24c256";
compatible = "atmel,24c256";
reg = <0x50>;
};

View File

@ -148,7 +148,7 @@
};
at24@50 {
compatible = "at24,24c256";
compatible = "atmel,24c256";
reg = <0x50>;
};

View File

@ -71,7 +71,7 @@
reg = <0x51>;
};
eeprom@52 {
compatible = "catalyst,24c32";
compatible = "catalyst,24c32", "atmel,24c32";
reg = <0x52>;
pagesize = <32>;
};

View File

@ -75,7 +75,7 @@
reg = <0x51>;
};
eeprom@52 {
compatible = "catalyst,24c32";
compatible = "catalyst,24c32", "atmel,24c32";
reg = <0x52>;
pagesize = <32>;
};

View File

@ -13,7 +13,7 @@
* option) any later version.
*/
#include <mpc5121.dtsi>
#include "mpc5121.dtsi"
/ {
model = "pdm360ng";

View File

@ -229,7 +229,7 @@
};
partition@84000 {
label = "user";
reg = <0x00000000 0x01f7c000>;
reg = <0x00084000 0x01f7c000>;
};
};
};

View File

@ -238,7 +238,7 @@
/* This will create 52 and 53 */
at24@52 {
compatible = "at,24c04";
compatible = "atmel,24c04";
reg = <0x52>;
};
};

View File

@ -67,13 +67,15 @@
#define MSR_LE 0x0000000000000001
#define FIXUP_ENDIAN \
tdi 0, 0, 0x48; /* Reverse endian of b . + 8 */ \
b $+36; /* Skip trampoline if endian is good */ \
.long 0x05009f42; /* bcl 20,31,$+4 */ \
.long 0xa602487d; /* mflr r10 */ \
.long 0x1c004a39; /* addi r10,r10,28 */ \
tdi 0,0,0x48; /* Reverse endian of b . + 8 */ \
b $+44; /* Skip trampoline if endian is good */ \
.long 0xa600607d; /* mfmsr r11 */ \
.long 0x01006b69; /* xori r11,r11,1 */ \
.long 0x00004039; /* li r10,0 */ \
.long 0x6401417d; /* mtmsrd r10,1 */ \
.long 0x05009f42; /* bcl 20,31,$+4 */ \
.long 0xa602487d; /* mflr r10 */ \
.long 0x14004a39; /* addi r10,r10,20 */ \
.long 0xa6035a7d; /* mtsrr0 r10 */ \
.long 0xa6037b7d; /* mtsrr1 r11 */ \
.long 0x2400004c /* rfid */

View File

@ -0,0 +1,126 @@
CONFIG_44x=y
# CONFIG_SWAP is not set
CONFIG_SYSVIPC=y
# CONFIG_CROSS_MEMORY_ATTACH is not set
# CONFIG_FHANDLE is not set
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=16
CONFIG_BLK_DEV_INITRD=y
# CONFIG_RD_LZMA is not set
# CONFIG_RD_XZ is not set
# CONFIG_RD_LZO is not set
# CONFIG_RD_LZ4 is not set
CONFIG_KALLSYMS_ALL=y
CONFIG_BPF_SYSCALL=y
CONFIG_EMBEDDED=y
CONFIG_PROFILING=y
CONFIG_OPROFILE=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_BLK_DEV_BSG is not set
CONFIG_PPC_47x=y
# CONFIG_EBONY is not set
CONFIG_FSP2=y
CONFIG_476FPE_ERR46=y
CONFIG_SWIOTLB=y
CONFIG_KEXEC=y
CONFIG_CRASH_DUMP=y
CONFIG_CMDLINE_BOOL=y
CONFIG_CMDLINE="ip=on rw"
# CONFIG_SUSPEND is not set
# CONFIG_PCI is not set
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_INET=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
# CONFIG_INET_XFRM_MODE_TUNNEL is not set
# CONFIG_INET_XFRM_MODE_BEET is not set
# CONFIG_IPV6 is not set
CONFIG_VLAN_8021Q=m
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
CONFIG_CONNECTOR=y
CONFIG_MTD=y
CONFIG_MTD_BLOCK=y
CONFIG_MTD_JEDECPROBE=y
CONFIG_MTD_CFI_AMDSTD=y
CONFIG_MTD_PHYSMAP_OF=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=35000
# CONFIG_SCSI_PROC_FS is not set
CONFIG_BLK_DEV_SD=y
# CONFIG_SCSI_LOWLEVEL is not set
CONFIG_ATA=y
# CONFIG_SATA_PMP is not set
# CONFIG_ATA_SFF is not set
CONFIG_NETDEVICES=y
CONFIG_BONDING=m
CONFIG_IBM_EMAC=m
# CONFIG_INPUT is not set
# CONFIG_SERIO is not set
# CONFIG_VT is not set
# CONFIG_LEGACY_PTYS is not set
# CONFIG_DEVMEM is not set
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_8250_NR_UARTS=32
CONFIG_SERIAL_8250_RUNTIME_UARTS=32
CONFIG_SERIAL_8250_EXTENDED=y
CONFIG_SERIAL_8250_SHARE_IRQ=y
CONFIG_SERIAL_OF_PLATFORM=y
# CONFIG_HW_RANDOM is not set
CONFIG_I2C=y
CONFIG_I2C_IBM_IIC=y
CONFIG_PTP_1588_CLOCK=y
# CONFIG_HWMON is not set
CONFIG_THERMAL=y
CONFIG_WATCHDOG=y
CONFIG_BOOKE_WDT=y
CONFIG_USB=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_OHCI_HCD=y
CONFIG_MMC=y
CONFIG_MMC_DEBUG=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_PLTFM=y
CONFIG_MMC_SDHCI_OF_ARASAN=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_M41T80=y
CONFIG_EXT2_FS=y
CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_POSIX_ACL=y
CONFIG_EXT4_FS_SECURITY=y
CONFIG_PROC_KCORE=y
CONFIG_TMPFS=y
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_WBUF_VERIFY=y
CONFIG_JFFS2_SUMMARY=y
CONFIG_JFFS2_FS_XATTR=y
CONFIG_CRAMFS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3_ACL=y
CONFIG_NFS_V4=y
CONFIG_ROOT_NFS=y
CONFIG_NLS_DEFAULT="n"
CONFIG_XZ_DEC=y
CONFIG_PRINTK_TIME=y
CONFIG_MESSAGE_LOGLEVEL_DEFAULT=3
CONFIG_DYNAMIC_DEBUG=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_FS=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_DETECT_HUNG_TASK=y
CONFIG_CRYPTO_CBC=y
CONFIG_CRYPTO_ECB=y
CONFIG_CRYPTO_PCBC=y
CONFIG_CRYPTO_MD5=y
CONFIG_CRYPTO_DES=y
# CONFIG_CRYPTO_HW is not set

View File

@ -74,6 +74,11 @@ do { \
___p1; \
})
/*
* This must resolve to hwsync on SMP for the context switch path.
* See _switch, and core scheduler context switch memory ordering
* comments.
*/
#define smp_mb__before_spinlock() smp_mb()
#include <asm-generic/barrier.h>

View File

@ -206,68 +206,13 @@ static __inline__ void __clear_bit_unlock(int nr, volatile unsigned long *addr)
* Return the zero-based bit position (LE, not IBM bit numbering) of
* the most significant 1-bit in a double word.
*/
static __inline__ __attribute__((const))
int __ilog2(unsigned long x)
{
int lz;
#define __ilog2(x) ilog2(x)
asm (PPC_CNTLZL "%0,%1" : "=r" (lz) : "r" (x));
return BITS_PER_LONG - 1 - lz;
}
#include <asm-generic/bitops/ffz.h>
static inline __attribute__((const))
int __ilog2_u32(u32 n)
{
int bit;
asm ("cntlzw %0,%1" : "=r" (bit) : "r" (n));
return 31 - bit;
}
#include <asm-generic/bitops/builtin-__ffs.h>
#ifdef __powerpc64__
static inline __attribute__((const))
int __ilog2_u64(u64 n)
{
int bit;
asm ("cntlzd %0,%1" : "=r" (bit) : "r" (n));
return 63 - bit;
}
#endif
/*
* Determines the bit position of the least significant 0 bit in the
* specified double word. The returned bit position will be
* zero-based, starting from the right side (63/31 - 0).
*/
static __inline__ unsigned long ffz(unsigned long x)
{
/* no zero exists anywhere in the 8 byte area. */
if ((x = ~x) == 0)
return BITS_PER_LONG;
/*
* Calculate the bit position of the least significant '1' bit in x
* (since x has been changed this will actually be the least significant
* '0' bit in * the original x). Note: (x & -x) gives us a mask that
* is the least significant * (RIGHT-most) 1-bit of the value in x.
*/
return __ilog2(x & -x);
}
static __inline__ unsigned long __ffs(unsigned long x)
{
return __ilog2(x & -x);
}
/*
* ffs: find first bit set. This is defined the same way as
* the libc and compiler builtin ffs routines, therefore
* differs in spirit from the above ffz (man ffs).
*/
static __inline__ int ffs(int x)
{
unsigned long i = (unsigned long)x;
return __ilog2(i & -i) + 1;
}
#include <asm-generic/bitops/builtin-ffs.h>
/*
* fls: find last (most-significant) bit set.
@ -275,33 +220,15 @@ static __inline__ int ffs(int x)
*/
static __inline__ int fls(unsigned int x)
{
int lz;
asm ("cntlzw %0,%1" : "=r" (lz) : "r" (x));
return 32 - lz;
return 32 - __builtin_clz(x);
}
static __inline__ unsigned long __fls(unsigned long x)
{
return __ilog2(x);
}
#include <asm-generic/bitops/builtin-__fls.h>
/*
* 64-bit can do this using one cntlzd (count leading zeroes doubleword)
* instruction; for 32-bit we use the generic version, which does two
* 32-bit fls calls.
*/
#ifdef __powerpc64__
static __inline__ int fls64(__u64 x)
{
int lz;
asm ("cntlzd %0,%1" : "=r" (lz) : "r" (x));
return 64 - lz;
return 64 - __builtin_clzll(x);
}
#else
#include <asm-generic/bitops/fls64.h>
#endif /* __powerpc64__ */
#ifdef CONFIG_PPC64
unsigned int __arch_hweight8(unsigned int w);

View File

@ -31,7 +31,8 @@ extern struct kmem_cache *pgtable_cache[];
static inline pgd_t *pgd_alloc(struct mm_struct *mm)
{
return kmem_cache_alloc(PGT_CACHE(PGD_INDEX_SIZE), GFP_KERNEL);
return kmem_cache_alloc(PGT_CACHE(PGD_INDEX_SIZE),
pgtable_gfp_flags(mm, GFP_KERNEL));
}
static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)

View File

@ -297,6 +297,8 @@ static inline void __ptep_set_access_flags(struct mm_struct *mm,
extern int get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep,
pmd_t **pmdp);
int map_kernel_page(unsigned long va, phys_addr_t pa, int flags);
/* Generic accessors to PTE bits */
static inline int pte_write(pte_t pte) { return !!(pte_val(pte) & _PAGE_RW);}
static inline int pte_dirty(pte_t pte) { return !!(pte_val(pte) & _PAGE_DIRTY); }

View File

@ -89,6 +89,9 @@ static inline int hash__pgd_bad(pgd_t pgd)
{
return (pgd_val(pgd) == 0);
}
#ifdef CONFIG_STRICT_KERNEL_RWX
extern void hash__mark_rodata_ro(void);
#endif
extern void hpte_need_flush(struct mm_struct *mm, unsigned long addr,
pte_t *ptep, unsigned long pte, int huge);

View File

@ -53,10 +53,11 @@ extern void __tlb_remove_table(void *_table);
static inline pgd_t *radix__pgd_alloc(struct mm_struct *mm)
{
#ifdef CONFIG_PPC_64K_PAGES
return (pgd_t *)__get_free_page(PGALLOC_GFP);
return (pgd_t *)__get_free_page(pgtable_gfp_flags(mm, PGALLOC_GFP));
#else
struct page *page;
page = alloc_pages(PGALLOC_GFP | __GFP_REPEAT, 4);
page = alloc_pages(pgtable_gfp_flags(mm, PGALLOC_GFP | __GFP_REPEAT),
4);
if (!page)
return NULL;
return (pgd_t *) page_address(page);
@ -76,7 +77,8 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm)
{
if (radix_enabled())
return radix__pgd_alloc(mm);
return kmem_cache_alloc(PGT_CACHE(PGD_INDEX_SIZE), GFP_KERNEL);
return kmem_cache_alloc(PGT_CACHE(PGD_INDEX_SIZE),
pgtable_gfp_flags(mm, GFP_KERNEL));
}
static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
@ -93,7 +95,8 @@ static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pud_t *pud)
static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
{
return kmem_cache_alloc(PGT_CACHE(PUD_INDEX_SIZE), GFP_KERNEL);
return kmem_cache_alloc(PGT_CACHE(PUD_INDEX_SIZE),
pgtable_gfp_flags(mm, GFP_KERNEL));
}
static inline void pud_free(struct mm_struct *mm, pud_t *pud)
@ -119,7 +122,8 @@ static inline void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pud,
static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
{
return kmem_cache_alloc(PGT_CACHE(PMD_CACHE_INDEX), GFP_KERNEL);
return kmem_cache_alloc(PGT_CACHE(PMD_CACHE_INDEX),
pgtable_gfp_flags(mm, GFP_KERNEL));
}
static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
@ -168,7 +172,7 @@ static inline pgtable_t pte_alloc_one(struct mm_struct *mm,
struct page *page;
pte_t *pte;
pte = pte_alloc_one_kernel(mm, address);
pte = (pte_t *)__get_free_page(GFP_KERNEL | __GFP_ZERO | __GFP_ACCOUNT);
if (!pte)
return NULL;
page = virt_to_page(pte);

View File

@ -5,6 +5,7 @@
#ifndef __ASSEMBLY__
#include <linux/mmdebug.h>
#include <linux/bug.h>
#endif
/*
@ -79,6 +80,9 @@
#define _PAGE_SOFT_DIRTY _RPAGE_SW3 /* software: software dirty tracking */
#define _PAGE_SPECIAL _RPAGE_SW2 /* software: special page */
#define _PAGE_DEVMAP _RPAGE_SW1 /* software: ZONE_DEVICE page */
#define __HAVE_ARCH_PTE_DEVMAP
/*
* Drivers request for cache inhibited pte mapping using _PAGE_NO_CACHE
* Instead of fixing all of them, add an alternate define which
@ -599,6 +603,16 @@ static inline pte_t pte_mkhuge(pte_t pte)
return pte;
}
static inline pte_t pte_mkdevmap(pte_t pte)
{
return __pte(pte_val(pte) | _PAGE_SPECIAL|_PAGE_DEVMAP);
}
static inline int pte_devmap(pte_t pte)
{
return !!(pte_raw(pte) & cpu_to_be64(_PAGE_DEVMAP));
}
static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
{
/* FIXME!! check whether this need to be a conditional */
@ -1146,6 +1160,37 @@ static inline bool arch_needs_pgtable_deposit(void)
return true;
}
static inline pmd_t pmd_mkdevmap(pmd_t pmd)
{
return __pmd(pmd_val(pmd) | (_PAGE_PTE | _PAGE_DEVMAP));
}
static inline int pmd_devmap(pmd_t pmd)
{
return pte_devmap(pmd_pte(pmd));
}
static inline int pud_devmap(pud_t pud)
{
return 0;
}
static inline int pgd_devmap(pgd_t pgd)
{
return 0;
}
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
static inline const int pud_pfn(pud_t pud)
{
/*
* Currently all calls to pud_pfn() are gated around a pud_devmap()
* check so this should never be used. If it grows another user we
* want to know about it.
*/
BUILD_BUG();
return 0;
}
#endif /* __ASSEMBLY__ */
#endif /* _ASM_POWERPC_BOOK3S_64_PGTABLE_H_ */

View File

@ -116,6 +116,10 @@
#define RADIX_PUD_TABLE_SIZE (sizeof(pud_t) << RADIX_PUD_INDEX_SIZE)
#define RADIX_PGD_TABLE_SIZE (sizeof(pgd_t) << RADIX_PGD_INDEX_SIZE)
#ifdef CONFIG_STRICT_KERNEL_RWX
extern void radix__mark_rodata_ro(void);
#endif
static inline unsigned long __radix_pte_update(pte_t *ptep, unsigned long clr,
unsigned long set)
{
@ -252,7 +256,7 @@ static inline int radix__pgd_bad(pgd_t pgd)
static inline int radix__pmd_trans_huge(pmd_t pmd)
{
return !!(pmd_val(pmd) & _PAGE_PTE);
return (pmd_val(pmd) & (_PAGE_PTE | _PAGE_DEVMAP)) == _PAGE_PTE;
}
static inline pmd_t radix__pmd_mkhuge(pmd_t pmd)

View File

@ -83,8 +83,16 @@ static inline unsigned long ppc_function_entry(void *func)
* On PPC64 ABIv1 the function pointer actually points to the
* function's descriptor. The first entry in the descriptor is the
* address of the function text.
*
* However, we may also receive pointer to an assembly symbol. To
* detect that, we first check if the function pointer we receive
* already points to kernel/module text and we only dereference it
* if it doesn't.
*/
return ((func_descr_t *)func)->entry;
if (kernel_text_address((unsigned long)func))
return (unsigned long)func;
else
return ((func_descr_t *)func)->entry;
#else
return (unsigned long)func;
#endif

View File

@ -56,6 +56,19 @@ static inline void ppc_msgsync(void)
: : "i" (CPU_FTR_HVMODE|CPU_FTR_ARCH_300));
}
static inline void _ppc_msgclr(u32 msg)
{
__asm__ __volatile__ (ASM_FTR_IFSET(PPC_MSGCLR(%1), PPC_MSGCLRP(%1), %0)
: : "i" (CPU_FTR_HVMODE), "r" (msg));
}
static inline void ppc_msgclr(enum ppc_dbell type)
{
u32 msg = PPC_DBELL_TYPE(type);
_ppc_msgclr(msg);
}
#else /* CONFIG_PPC_BOOK3S */
#define PPC_DBELL_MSGTYPE PPC_DBELL

View File

@ -2,6 +2,7 @@
#define _ASM_POWERPC_DELAY_H
#ifdef __KERNEL__
#include <linux/processor.h>
#include <asm/time.h>
/*
@ -58,11 +59,18 @@ extern void udelay(unsigned long usecs);
typeof(condition) __ret; \
unsigned long __loops = tb_ticks_per_usec * timeout; \
unsigned long __start = get_tbl(); \
while (!(__ret = (condition)) && (tb_ticks_since(__start) <= __loops)) \
if (delay) \
\
if (delay) { \
while (!(__ret = (condition)) && \
(tb_ticks_since(__start) <= __loops)) \
udelay(delay); \
else \
cpu_relax(); \
} else { \
spin_begin(); \
while (!(__ret = (condition)) && \
(tb_ticks_since(__start) <= __loops)) \
spin_cpu_relax(); \
spin_end(); \
} \
if (!__ret) \
__ret = (condition); \
__ret; \

View File

@ -36,20 +36,38 @@
*/
#include <asm/head-64.h>
/* PACA save area offsets (exgen, exmc, etc) */
#define EX_R9 0
#define EX_R10 8
#define EX_R11 16
#define EX_R12 24
#define EX_R13 32
#define EX_SRR0 40
#define EX_DAR 48
#define EX_DSISR 56
#define EX_CCR 60
#define EX_R3 64
#define EX_LR 72
#define EX_CFAR 80
#define EX_PPR 88 /* SMT thread status register (priority) */
#define EX_CTR 96
#define EX_DAR 40
#define EX_DSISR 48
#define EX_CCR 52
#define EX_CFAR 56
#define EX_PPR 64
#if defined(CONFIG_RELOCATABLE)
#define EX_CTR 72
#define EX_SIZE 10 /* size in u64 units */
#else
#define EX_SIZE 9 /* size in u64 units */
#endif
/*
* EX_LR is only used in EXSLB and where it does not overlap with EX_DAR
* EX_CCR similarly with DSISR, but being 4 byte registers there is a hole
* in the save area so it's not necessary to overlap them. Could be used
* for future savings though if another 4 byte register was to be saved.
*/
#define EX_LR EX_DAR
/*
* EX_R3 is only used by the bad_stack handler. bad_stack reloads and
* saves DAR from SPRN_DAR, and EX_DAR is not used. So EX_R3 can overlap
* with EX_DAR.
*/
#define EX_R3 EX_DAR
#ifdef CONFIG_RELOCATABLE
#define __EXCEPTION_RELON_PROLOG_PSERIES_1(label, h) \
@ -236,6 +254,19 @@ END_FTR_SECTION_NESTED(ftr,ftr,943)
#define kvmppc_interrupt kvmppc_interrupt_pr
#endif
/*
* Branch to label using its 0xC000 address. This results in instruction
* address suitable for MSR[IR]=0 or 1, which allows relocation to be turned
* on using mtmsr rather than rfid.
*
* This could set the 0xc bits for !RELOCATABLE as an immediate, rather than
* load KBASE for a slight optimisation.
*/
#define BRANCH_TO_C000(reg, label) \
__LOAD_HANDLER(reg, label); \
mtctr reg; \
bctr
#ifdef CONFIG_RELOCATABLE
#define BRANCH_TO_COMMON(reg, label) \
__LOAD_HANDLER(reg, label); \

View File

@ -43,6 +43,9 @@
#define MIN_BOOT_MEM (((RMA_END < (0x1UL << 28)) ? (0x1UL << 28) : RMA_END) \
+ (0x1UL << 26))
/* The upper limit percentage for user specified boot memory size (25%) */
#define MAX_BOOT_MEM_RATIO 4
#define memblock_num_regions(memblock_type) (memblock.memblock_type.cnt)
/* Firmware provided dump sections */
@ -200,6 +203,7 @@ struct fad_crash_memory_ranges {
unsigned long long size;
};
extern int is_fadump_boot_memory_area(u64 addr, ulong size);
extern int early_init_dt_scan_fw_dump(unsigned long node,
const char *uname, int depth, void *data);
extern int fadump_reserve_mem(void);

View File

@ -3,6 +3,7 @@
#include <asm/cache.h>
#ifdef __ASSEMBLY__
/*
* We can't do CPP stringification and concatination directly into the section
* name for some reason, so these macros can do it for us.
@ -49,8 +50,8 @@
* CLOSE_FIXED_SECTION() or elsewhere, there may be something
* unexpected being added there. Remove the '. = x_len' line, rebuild, and
* check what is pushing the section down.
* - If the build dies in linking, check arch/powerpc/kernel/vmlinux.lds.S
* for instructions.
* - If the build dies in linking, check arch/powerpc/tools/head_check.sh
* comments.
* - If the kernel crashes or hangs in very early boot, it could be linker
* stubs at the start of the main text.
*/
@ -63,11 +64,29 @@
. = 0x0; \
start_##sname:
/*
* .linker_stub_catch section is used to catch linker stubs from being
* inserted in our .text section, above the start_text label (which breaks
* the ABS_ADDR calculation). See kernel/vmlinux.lds.S and tools/head_check.sh
* for more details. We would prefer to just keep a cacheline (0x80), but
* 0x100 seems to be how the linker aligns branch stub groups.
*/
#ifdef CONFIG_LD_HEAD_STUB_CATCH
#define OPEN_TEXT_SECTION(start) \
.section ".linker_stub_catch","ax",@progbits; \
linker_stub_catch: \
. = 0x4; \
text_start = (start) + 0x100; \
.section ".text","ax",@progbits; \
.balign 0x100; \
start_text:
#else
#define OPEN_TEXT_SECTION(start) \
text_start = (start); \
.section ".text","ax",@progbits; \
. = 0x0; \
start_text:
#endif
#define ZERO_FIXED_SECTION(sname, start, end) \
sname##_start = (start); \
@ -397,4 +416,6 @@ name:
EXC_COMMON_BEGIN(name); \
STD_EXCEPTION_COMMON(realvec + 0x2, name, hdlr); \
#endif /* __ASSEMBLY__ */
#endif /* _ASM_POWERPC_HEAD_64_H */

View File

@ -129,6 +129,10 @@ static inline bool arch_irq_disabled_regs(struct pt_regs *regs)
}
extern bool prep_irq_for_idle(void);
extern bool prep_irq_for_idle_irqsoff(void);
extern void irq_set_pending_from_srr1(unsigned long srr1);
#define fini_irq_for_idle_irqsoff() trace_hardirqs_off();
extern void force_external_irq_replay(void);

View File

@ -226,6 +226,7 @@ struct machdep_calls {
extern void e500_idle(void);
extern void power4_idle(void);
extern void power7_idle(void);
extern void power9_idle(void);
extern void ppc6xx_idle(void);
extern void book3e_idle(void);

View File

@ -90,13 +90,14 @@ enum MCE_UserErrorType {
enum MCE_RaErrorType {
MCE_RA_ERROR_INDETERMINATE = 0,
MCE_RA_ERROR_IFETCH = 1,
MCE_RA_ERROR_PAGE_TABLE_WALK_IFETCH = 2,
MCE_RA_ERROR_PAGE_TABLE_WALK_IFETCH_FOREIGN = 3,
MCE_RA_ERROR_LOAD = 4,
MCE_RA_ERROR_STORE = 5,
MCE_RA_ERROR_PAGE_TABLE_WALK_LOAD_STORE = 6,
MCE_RA_ERROR_PAGE_TABLE_WALK_LOAD_STORE_FOREIGN = 7,
MCE_RA_ERROR_LOAD_STORE_FOREIGN = 8,
MCE_RA_ERROR_IFETCH_FOREIGN = 2,
MCE_RA_ERROR_PAGE_TABLE_WALK_IFETCH = 3,
MCE_RA_ERROR_PAGE_TABLE_WALK_IFETCH_FOREIGN = 4,
MCE_RA_ERROR_LOAD = 5,
MCE_RA_ERROR_STORE = 6,
MCE_RA_ERROR_PAGE_TABLE_WALK_LOAD_STORE = 7,
MCE_RA_ERROR_PAGE_TABLE_WALK_LOAD_STORE_FOREIGN = 8,
MCE_RA_ERROR_LOAD_STORE_FOREIGN = 9,
};
enum MCE_LinkErrorType {

View File

@ -31,7 +31,8 @@ extern struct kmem_cache *pgtable_cache[];
static inline pgd_t *pgd_alloc(struct mm_struct *mm)
{
return kmem_cache_alloc(PGT_CACHE(PGD_INDEX_SIZE), GFP_KERNEL);
return kmem_cache_alloc(PGT_CACHE(PGD_INDEX_SIZE),
pgtable_gfp_flags(mm, GFP_KERNEL));
}
static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)

View File

@ -340,6 +340,8 @@ static inline void __ptep_set_access_flags(struct mm_struct *mm,
extern int get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep,
pmd_t **pmdp);
int map_kernel_page(unsigned long va, phys_addr_t pa, int flags);
#endif /* !__ASSEMBLY__ */
#endif /* __ASM_POWERPC_NOHASH_32_PGTABLE_H */

View File

@ -43,7 +43,8 @@ extern struct kmem_cache *pgtable_cache[];
static inline pgd_t *pgd_alloc(struct mm_struct *mm)
{
return kmem_cache_alloc(PGT_CACHE(PGD_INDEX_SIZE), GFP_KERNEL);
return kmem_cache_alloc(PGT_CACHE(PGD_INDEX_SIZE),
pgtable_gfp_flags(mm, GFP_KERNEL));
}
static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
@ -57,7 +58,8 @@ static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
{
return kmem_cache_alloc(PGT_CACHE(PUD_INDEX_SIZE), GFP_KERNEL);
return kmem_cache_alloc(PGT_CACHE(PUD_INDEX_SIZE),
pgtable_gfp_flags(mm, GFP_KERNEL));
}
static inline void pud_free(struct mm_struct *mm, pud_t *pud)
@ -96,7 +98,7 @@ static inline pgtable_t pte_alloc_one(struct mm_struct *mm,
struct page *page;
pte_t *pte;
pte = pte_alloc_one_kernel(mm, address);
pte = (pte_t *)__get_free_page(GFP_KERNEL | __GFP_ZERO | __GFP_ACCOUNT);
if (!pte)
return NULL;
page = virt_to_page(pte);
@ -189,7 +191,8 @@ static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t table,
static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
{
return kmem_cache_alloc(PGT_CACHE(PMD_CACHE_INDEX), GFP_KERNEL);
return kmem_cache_alloc(PGT_CACHE(PMD_CACHE_INDEX),
pgtable_gfp_flags(mm, GFP_KERNEL));
}
static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)

View File

@ -667,12 +667,14 @@ enum {
enum {
OPAL_PHB_ERROR_DATA_TYPE_P7IOC = 1,
OPAL_PHB_ERROR_DATA_TYPE_PHB3 = 2
OPAL_PHB_ERROR_DATA_TYPE_PHB3 = 2,
OPAL_PHB_ERROR_DATA_TYPE_PHB4 = 3
};
enum {
OPAL_P7IOC_NUM_PEST_REGS = 128,
OPAL_PHB3_NUM_PEST_REGS = 256
OPAL_PHB3_NUM_PEST_REGS = 256,
OPAL_PHB4_NUM_PEST_REGS = 512
};
struct OpalIoPhbErrorCommon {
@ -802,6 +804,75 @@ struct OpalIoPhb3ErrorData {
__be64 pestB[OPAL_PHB3_NUM_PEST_REGS];
};
struct OpalIoPhb4ErrorData {
struct OpalIoPhbErrorCommon common;
__be32 brdgCtl;
/* PHB4 cfg regs */
__be32 deviceStatus;
__be32 slotStatus;
__be32 linkStatus;
__be32 devCmdStatus;
__be32 devSecStatus;
/* cfg AER regs */
__be32 rootErrorStatus;
__be32 uncorrErrorStatus;
__be32 corrErrorStatus;
__be32 tlpHdr1;
__be32 tlpHdr2;
__be32 tlpHdr3;
__be32 tlpHdr4;
__be32 sourceId;
/* PHB4 ETU Error Regs */
__be64 nFir; /* 000 */
__be64 nFirMask; /* 003 */
__be64 nFirWOF; /* 008 */
__be64 phbPlssr; /* 120 */
__be64 phbCsr; /* 110 */
__be64 lemFir; /* C00 */
__be64 lemErrorMask; /* C18 */
__be64 lemWOF; /* C40 */
__be64 phbErrorStatus; /* C80 */
__be64 phbFirstErrorStatus; /* C88 */
__be64 phbErrorLog0; /* CC0 */
__be64 phbErrorLog1; /* CC8 */
__be64 phbTxeErrorStatus; /* D00 */
__be64 phbTxeFirstErrorStatus; /* D08 */
__be64 phbTxeErrorLog0; /* D40 */
__be64 phbTxeErrorLog1; /* D48 */
__be64 phbRxeArbErrorStatus; /* D80 */
__be64 phbRxeArbFirstErrorStatus; /* D88 */
__be64 phbRxeArbErrorLog0; /* DC0 */
__be64 phbRxeArbErrorLog1; /* DC8 */
__be64 phbRxeMrgErrorStatus; /* E00 */
__be64 phbRxeMrgFirstErrorStatus; /* E08 */
__be64 phbRxeMrgErrorLog0; /* E40 */
__be64 phbRxeMrgErrorLog1; /* E48 */
__be64 phbRxeTceErrorStatus; /* E80 */
__be64 phbRxeTceFirstErrorStatus; /* E88 */
__be64 phbRxeTceErrorLog0; /* EC0 */
__be64 phbRxeTceErrorLog1; /* EC8 */
/* PHB4 REGB Error Regs */
__be64 phbPblErrorStatus; /* 1900 */
__be64 phbPblFirstErrorStatus; /* 1908 */
__be64 phbPblErrorLog0; /* 1940 */
__be64 phbPblErrorLog1; /* 1948 */
__be64 phbPcieDlpErrorLog1; /* 1AA0 */
__be64 phbPcieDlpErrorLog2; /* 1AA8 */
__be64 phbPcieDlpErrorStatus; /* 1AB0 */
__be64 phbRegbErrorStatus; /* 1C00 */
__be64 phbRegbFirstErrorStatus; /* 1C08 */
__be64 phbRegbErrorLog0; /* 1C40 */
__be64 phbRegbErrorLog1; /* 1C48 */
__be64 pestA[OPAL_PHB4_NUM_PEST_REGS];
__be64 pestB[OPAL_PHB4_NUM_PEST_REGS];
};
enum {
OPAL_REINIT_CPUS_HILE_BE = (1 << 0),
OPAL_REINIT_CPUS_HILE_LE = (1 << 1),
@ -877,6 +948,7 @@ enum {
OPAL_PHB_CAPI_MODE_SNOOP_OFF = 2,
OPAL_PHB_CAPI_MODE_SNOOP_ON = 3,
OPAL_PHB_CAPI_MODE_DMA = 4,
OPAL_PHB_CAPI_MODE_DMA_TVT1 = 5,
};
/* OPAL I2C request */

View File

@ -21,7 +21,11 @@
#include <asm/lppaca.h>
#include <asm/mmu.h>
#include <asm/page.h>
#ifdef CONFIG_PPC_BOOK3E
#include <asm/exception-64e.h>
#else
#include <asm/exception-64s.h>
#endif
#ifdef CONFIG_KVM_BOOK3S_64_HANDLER
#include <asm/kvm_book3s_asm.h>
#endif
@ -98,8 +102,8 @@ struct paca_struct {
* Now, starting in cacheline 2, the exception save areas
*/
/* used for most interrupts/exceptions */
u64 exgen[13] __attribute__((aligned(0x80)));
u64 exslb[13]; /* used for SLB/segment table misses
u64 exgen[EX_SIZE] __attribute__((aligned(0x80)));
u64 exslb[EX_SIZE]; /* used for SLB/segment table misses
* on the linear mapping */
/* SLB related definitions */
u16 vmalloc_sllp;
@ -177,12 +181,14 @@ struct paca_struct {
* to the sibling threads' paca.
*/
struct paca_struct **thread_sibling_pacas;
/* The PSSCR value that the kernel requested before going to stop */
u64 requested_psscr;
#endif
#ifdef CONFIG_PPC_STD_MMU_64
/* Non-maskable exceptions that are not performance critical */
u64 exnmi[13]; /* used for system reset (nmi) */
u64 exmc[13]; /* used for machine checks */
u64 exnmi[EX_SIZE]; /* used for system reset (nmi) */
u64 exmc[EX_SIZE]; /* used for machine checks */
#endif
#ifdef CONFIG_PPC_BOOK3S_64
/* Exclusive stacks for system reset and machine check exception. */

View File

@ -3,6 +3,20 @@
#include <linux/mm.h>
#ifndef MODULE
static inline gfp_t pgtable_gfp_flags(struct mm_struct *mm, gfp_t gfp)
{
if (unlikely(mm == &init_mm))
return gfp;
return gfp | __GFP_ACCOUNT;
}
#else /* !MODULE */
static inline gfp_t pgtable_gfp_flags(struct mm_struct *mm, gfp_t gfp)
{
return gfp | __GFP_ACCOUNT;
}
#endif /* MODULE */
#ifdef CONFIG_PPC_BOOK3S
#include <asm/book3s/pgalloc.h>
#else

View File

@ -191,8 +191,7 @@
/* sorted alphabetically */
#define PPC_INST_BHRBE 0x7c00025c
#define PPC_INST_CLRBHRB 0x7c00035c
#define PPC_INST_COPY 0x7c00060c
#define PPC_INST_COPY_FIRST 0x7c20060c
#define PPC_INST_COPY 0x7c20060c
#define PPC_INST_CP_ABORT 0x7c00068c
#define PPC_INST_DCBA 0x7c0005ec
#define PPC_INST_DCBA_MASK 0xfc0007fe
@ -223,10 +222,10 @@
#define PPC_INST_MSGCLR 0x7c0001dc
#define PPC_INST_MSGSYNC 0x7c0006ec
#define PPC_INST_MSGSNDP 0x7c00011c
#define PPC_INST_MSGCLRP 0x7c00015c
#define PPC_INST_MTTMR 0x7c0003dc
#define PPC_INST_NOP 0x60000000
#define PPC_INST_PASTE 0x7c00070c
#define PPC_INST_PASTE_LAST 0x7c20070d
#define PPC_INST_PASTE 0x7c20070d
#define PPC_INST_POPCNTB 0x7c0000f4
#define PPC_INST_POPCNTB_MASK 0xfc0007fe
#define PPC_INST_POPCNTD 0x7c0003f4
@ -394,6 +393,8 @@
/* Deal with instructions that older assemblers aren't aware of */
#define PPC_CP_ABORT stringify_in_c(.long PPC_INST_CP_ABORT)
#define PPC_COPY(a, b) stringify_in_c(.long PPC_INST_COPY | \
___PPC_RA(a) | ___PPC_RB(b))
#define PPC_DCBAL(a, b) stringify_in_c(.long PPC_INST_DCBAL | \
__PPC_RA(a) | __PPC_RB(b))
#define PPC_DCBZL(a, b) stringify_in_c(.long PPC_INST_DCBZL | \
@ -411,6 +412,8 @@
___PPC_RB(b))
#define PPC_MSGSNDP(b) stringify_in_c(.long PPC_INST_MSGSNDP | \
___PPC_RB(b))
#define PPC_MSGCLRP(b) stringify_in_c(.long PPC_INST_MSGCLRP | \
___PPC_RB(b))
#define PPC_POPCNTB(a, s) stringify_in_c(.long PPC_INST_POPCNTB | \
__PPC_RA(a) | __PPC_RS(s))
#define PPC_POPCNTD(a, s) stringify_in_c(.long PPC_INST_POPCNTD | \

View File

@ -770,15 +770,18 @@ END_FTR_SECTION_IFCLR(CPU_FTR_601)
#else
#define FIXUP_ENDIAN \
tdi 0,0,0x48; /* Reverse endian of b . + 8 */ \
b $+36; /* Skip trampoline if endian is good */ \
.long 0x05009f42; /* bcl 20,31,$+4 */ \
.long 0xa602487d; /* mflr r10 */ \
.long 0x1c004a39; /* addi r10,r10,28 */ \
b $+44; /* Skip trampoline if endian is good */ \
.long 0xa600607d; /* mfmsr r11 */ \
.long 0x01006b69; /* xori r11,r11,1 */ \
.long 0x00004039; /* li r10,0 */ \
.long 0x6401417d; /* mtmsrd r10,1 */ \
.long 0x05009f42; /* bcl 20,31,$+4 */ \
.long 0xa602487d; /* mflr r10 */ \
.long 0x14004a39; /* addi r10,r10,20 */ \
.long 0xa6035a7d; /* mtsrr0 r10 */ \
.long 0xa6037b7d; /* mtsrr1 r11 */ \
.long 0x2400004c /* rfid */
#endif /* !CONFIG_PPC_BOOK3E */
#endif /* __ASSEMBLY__ */

View File

@ -421,6 +421,26 @@ static inline unsigned long __pack_fe01(unsigned int fpmode)
#ifdef CONFIG_PPC64
#define cpu_relax() do { HMT_low(); HMT_medium(); barrier(); } while (0)
#define spin_begin() HMT_low()
#define spin_cpu_relax() barrier()
#define spin_cpu_yield() spin_cpu_relax()
#define spin_end() HMT_medium()
#define spin_until_cond(cond) \
do { \
if (unlikely(!(cond))) { \
spin_begin(); \
do { \
spin_cpu_relax(); \
} while (!(cond)); \
spin_end(); \
} \
} while (0)
#else
#define cpu_relax() barrier()
#endif
@ -474,11 +494,11 @@ extern unsigned long cpuidle_disable;
enum idle_boot_override {IDLE_NO_OVERRIDE = 0, IDLE_POWERSAVE_OFF};
extern int powersave_nap; /* set if nap mode can be used in idle loop */
extern unsigned long power7_nap(int check_irq);
extern unsigned long power7_sleep(void);
extern unsigned long power7_winkle(void);
extern unsigned long power9_idle_stop(unsigned long stop_psscr_val,
unsigned long stop_psscr_mask);
extern unsigned long power7_idle_insn(unsigned long type); /* PNV_THREAD_NAP/etc*/
extern void power7_idle_type(unsigned long type);
extern unsigned long power9_idle_stop(unsigned long psscr_val);
extern void power9_idle_type(unsigned long stop_psscr_val,
unsigned long stop_psscr_mask);
extern void flush_instruction_cache(void);
extern void hard_reset_now(void);

View File

@ -168,6 +168,39 @@ TRACE_EVENT(hash_fault,
__entry->addr, __entry->access, __entry->trap)
);
TRACE_EVENT(tlbie,
TP_PROTO(unsigned long lpid, unsigned long local, unsigned long rb,
unsigned long rs, unsigned long ric, unsigned long prs,
unsigned long r),
TP_ARGS(lpid, local, rb, rs, ric, prs, r),
TP_STRUCT__entry(
__field(unsigned long, lpid)
__field(unsigned long, local)
__field(unsigned long, rb)
__field(unsigned long, rs)
__field(unsigned long, ric)
__field(unsigned long, prs)
__field(unsigned long, r)
),
TP_fast_assign(
__entry->lpid = lpid;
__entry->local = local;
__entry->rb = rb;
__entry->rs = rs;
__entry->ric = ric;
__entry->prs = prs;
__entry->r = r;
),
TP_printk("lpid=%ld, local=%ld, rb=0x%lx, rs=0x%lx, ric=0x%lx, "
"prs=0x%lx, r=0x%lx", __entry->lpid, __entry->local,
__entry->rb, __entry->rs, __entry->ric, __entry->prs,
__entry->r)
);
#endif /* _TRACE_POWERPC_H */
#undef TRACE_INCLUDE_PATH

View File

@ -1,2 +1,8 @@
# UAPI Header export list
include include/uapi/asm-generic/Kbuild.asm
generic-y += param.h
generic-y += poll.h
generic-y += resource.h
generic-y += sockios.h
generic-y += statfs.h

View File

@ -1 +0,0 @@
#include <asm-generic/param.h>

View File

@ -1 +0,0 @@
#include <asm-generic/poll.h>

View File

@ -1 +0,0 @@
#include <asm-generic/resource.h>

View File

@ -1,20 +0,0 @@
#ifndef _ASM_POWERPC_SOCKIOS_H
#define _ASM_POWERPC_SOCKIOS_H
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
/* Socket-level I/O control calls. */
#define FIOSETOWN 0x8901
#define SIOCSPGRP 0x8902
#define FIOGETOWN 0x8903
#define SIOCGPGRP 0x8904
#define SIOCATMARK 0x8905
#define SIOCGSTAMP 0x8906 /* Get stamp (timeval) */
#define SIOCGSTAMPNS 0x8907 /* Get stamp (timespec) */
#endif /* _ASM_POWERPC_SOCKIOS_H */

View File

@ -1,6 +0,0 @@
#ifndef _ASM_POWERPC_STATFS_H
#define _ASM_POWERPC_STATFS_H
#include <asm-generic/statfs.h>
#endif

View File

@ -25,8 +25,6 @@ CFLAGS_REMOVE_cputable.o = -mno-sched-epilog $(CC_FLAGS_FTRACE)
CFLAGS_REMOVE_prom_init.o = -mno-sched-epilog $(CC_FLAGS_FTRACE)
CFLAGS_REMOVE_btext.o = -mno-sched-epilog $(CC_FLAGS_FTRACE)
CFLAGS_REMOVE_prom.o = -mno-sched-epilog $(CC_FLAGS_FTRACE)
# timers used by tracing
CFLAGS_REMOVE_time.o = -mno-sched-epilog $(CC_FLAGS_FTRACE)
endif
obj-y := cputable.o ptrace.o syscalls.o \

View File

@ -100,12 +100,12 @@ int main(void)
OFFSET(THREAD_NORMSAVES, thread_struct, normsave[0]);
#endif
OFFSET(THREAD_FPEXC_MODE, thread_struct, fpexc_mode);
OFFSET(THREAD_FPSTATE, thread_struct, fp_state);
OFFSET(THREAD_FPSTATE, thread_struct, fp_state.fpr);
OFFSET(THREAD_FPSAVEAREA, thread_struct, fp_save_area);
OFFSET(FPSTATE_FPSCR, thread_fp_state, fpscr);
OFFSET(THREAD_LOAD_FP, thread_struct, load_fp);
#ifdef CONFIG_ALTIVEC
OFFSET(THREAD_VRSTATE, thread_struct, vr_state);
OFFSET(THREAD_VRSTATE, thread_struct, vr_state.vr);
OFFSET(THREAD_VRSAVEAREA, thread_struct, vr_save_area);
OFFSET(THREAD_VRSAVE, thread_struct, vrsave);
OFFSET(THREAD_USED_VR, thread_struct, used_vr);
@ -145,9 +145,9 @@ int main(void)
OFFSET(THREAD_TM_PPR, thread_struct, tm_ppr);
OFFSET(THREAD_TM_DSCR, thread_struct, tm_dscr);
OFFSET(PT_CKPT_REGS, thread_struct, ckpt_regs);
OFFSET(THREAD_CKVRSTATE, thread_struct, ckvr_state);
OFFSET(THREAD_CKVRSTATE, thread_struct, ckvr_state.vr);
OFFSET(THREAD_CKVRSAVE, thread_struct, ckvrsave);
OFFSET(THREAD_CKFPSTATE, thread_struct, ckfp_state);
OFFSET(THREAD_CKFPSTATE, thread_struct, ckfp_state.fpr);
/* Local pt_regs on stack for Transactional Memory funcs. */
DEFINE(TM_FRAME_SIZE, STACK_FRAME_OVERHEAD +
sizeof(struct pt_regs) + 16);
@ -745,9 +745,11 @@ int main(void)
OFFSET(PACA_THREAD_MASK, paca_struct, thread_mask);
OFFSET(PACA_SUBCORE_SIBLING_MASK, paca_struct, subcore_sibling_mask);
OFFSET(PACA_SIBLING_PACA_PTRS, paca_struct, thread_sibling_pacas);
OFFSET(PACA_REQ_PSSCR, paca_struct, requested_psscr);
#endif
DEFINE(PPC_DBELL_SERVER, PPC_DBELL_SERVER);
DEFINE(PPC_DBELL_MSGTYPE, PPC_DBELL_MSGTYPE);
#ifdef CONFIG_PPC_8xx
DEFINE(VIRT_IMMR_BASE, (u64)__fix_to_virt(FIX_IMMR_BASE));

View File

@ -57,7 +57,7 @@ system_call_common:
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
BEGIN_FTR_SECTION
extrdi. r10, r12, 1, (63-MSR_TS_T_LG) /* transaction active? */
bne tabort_syscall
bne .Ltabort_syscall
END_FTR_SECTION_IFSET(CPU_FTR_TM)
#endif
andi. r10,r12,MSR_PR
@ -143,6 +143,7 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR)
mtmsrd r11,1
#endif /* CONFIG_PPC_BOOK3E */
system_call: /* label this so stack traces look sane */
/* We do need to set SOFTE in the stack frame or the return
* from interrupt will be painful
*/
@ -152,11 +153,11 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR)
CURRENT_THREAD_INFO(r11, r1)
ld r10,TI_FLAGS(r11)
andi. r11,r10,_TIF_SYSCALL_DOTRACE
bne syscall_dotrace /* does not return */
bne .Lsyscall_dotrace /* does not return */
cmpldi 0,r0,NR_syscalls
bge- syscall_enosys
bge- .Lsyscall_enosys
system_call: /* label this so stack traces look sane */
.Lsyscall:
/*
* Need to vector to 32 Bit or default sys_call_table here,
* based on caller's run-mode / personality.
@ -185,8 +186,20 @@ system_call: /* label this so stack traces look sane */
#ifdef CONFIG_PPC_BOOK3S
/* No MSR:RI on BookE */
andi. r10,r8,MSR_RI
beq- unrecov_restore
beq- .Lunrecov_restore
#endif
/*
* This is a few instructions into the actual syscall exit path (which actually
* starts at .Lsyscall_exit) to cater to kprobe blacklisting and to reduce the
* number of visible symbols for profiling purposes.
*
* We can probe from system_call until this point as MSR_RI is set. But once it
* is cleared below, we won't be able to take a trap.
*
* This is blacklisted from kprobes further below with _ASM_NOKPROBE_SYMBOL().
*/
system_call_exit:
/*
* Disable interrupts so current_thread_info()->flags can't change,
* and so that we don't get interrupted after loading SRR0/1.
@ -208,31 +221,21 @@ system_call: /* label this so stack traces look sane */
ld r9,TI_FLAGS(r12)
li r11,-MAX_ERRNO
andi. r0,r9,(_TIF_SYSCALL_DOTRACE|_TIF_SINGLESTEP|_TIF_USER_WORK_MASK|_TIF_PERSYSCALL_MASK)
bne- syscall_exit_work
bne- .Lsyscall_exit_work
andi. r0,r8,MSR_FP
beq 2f
/* If MSR_FP and MSR_VEC are set in user msr, then no need to restore */
li r7,MSR_FP
#ifdef CONFIG_ALTIVEC
andis. r0,r8,MSR_VEC@h
bne 3f
oris r7,r7,MSR_VEC@h
#endif
2: addi r3,r1,STACK_FRAME_OVERHEAD
#ifdef CONFIG_PPC_BOOK3S
li r10,MSR_RI
mtmsrd r10,1 /* Restore RI */
#endif
bl restore_math
#ifdef CONFIG_PPC_BOOK3S
li r11,0
mtmsrd r11,1
#endif
ld r8,_MSR(r1)
ld r3,RESULT(r1)
li r11,-MAX_ERRNO
and r0,r8,r7
cmpd r0,r7
bne .Lsyscall_restore_math
.Lsyscall_restore_math_cont:
3: cmpld r3,r11
cmpld r3,r11
ld r5,_CCR(r1)
bge- syscall_error
bge- .Lsyscall_error
.Lsyscall_error_cont:
ld r7,_NIP(r1)
BEGIN_FTR_SECTION
@ -258,14 +261,48 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
RFI
b . /* prevent speculative execution */
syscall_error:
.Lsyscall_error:
oris r5,r5,0x1000 /* Set SO bit in CR */
neg r3,r3
std r5,_CCR(r1)
b .Lsyscall_error_cont
.Lsyscall_restore_math:
/*
* Some initial tests from restore_math to avoid the heavyweight
* C code entry and MSR manipulations.
*/
LOAD_REG_IMMEDIATE(r0, MSR_TS_MASK)
and. r0,r0,r8
bne 1f
ld r7,PACACURRENT(r13)
lbz r0,THREAD+THREAD_LOAD_FP(r7)
#ifdef CONFIG_ALTIVEC
lbz r6,THREAD+THREAD_LOAD_VEC(r7)
add r0,r0,r6
#endif
cmpdi r0,0
beq .Lsyscall_restore_math_cont
1: addi r3,r1,STACK_FRAME_OVERHEAD
#ifdef CONFIG_PPC_BOOK3S
li r10,MSR_RI
mtmsrd r10,1 /* Restore RI */
#endif
bl restore_math
#ifdef CONFIG_PPC_BOOK3S
li r11,0
mtmsrd r11,1
#endif
/* Restore volatiles, reload MSR from updated one */
ld r8,_MSR(r1)
ld r3,RESULT(r1)
li r11,-MAX_ERRNO
b .Lsyscall_restore_math_cont
/* Traced system call support */
syscall_dotrace:
.Lsyscall_dotrace:
bl save_nvgprs
addi r3,r1,STACK_FRAME_OVERHEAD
bl do_syscall_trace_enter
@ -286,23 +323,23 @@ syscall_dotrace:
ld r7,GPR7(r1)
ld r8,GPR8(r1)
/* Repopulate r9 and r10 for the system_call path */
/* Repopulate r9 and r10 for the syscall path */
addi r9,r1,STACK_FRAME_OVERHEAD
CURRENT_THREAD_INFO(r10, r1)
ld r10,TI_FLAGS(r10)
cmpldi r0,NR_syscalls
blt+ system_call
blt+ .Lsyscall
/* Return code is already in r3 thanks to do_syscall_trace_enter() */
b .Lsyscall_exit
syscall_enosys:
.Lsyscall_enosys:
li r3,-ENOSYS
b .Lsyscall_exit
syscall_exit_work:
.Lsyscall_exit_work:
#ifdef CONFIG_PPC_BOOK3S
li r10,MSR_RI
mtmsrd r10,1 /* Restore RI */
@ -362,7 +399,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
b ret_from_except
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
tabort_syscall:
.Ltabort_syscall:
/* Firstly we need to enable TM in the kernel */
mfmsr r10
li r9, 1
@ -388,6 +425,8 @@ tabort_syscall:
rfid
b . /* prevent speculative execution */
#endif
_ASM_NOKPROBE_SYMBOL(system_call_common);
_ASM_NOKPROBE_SYMBOL(system_call_exit);
/* Save non-volatile GPRs, if not already saved. */
_GLOBAL(save_nvgprs)
@ -398,6 +437,7 @@ _GLOBAL(save_nvgprs)
clrrdi r0,r11,1
std r0,_TRAP(r1)
blr
_ASM_NOKPROBE_SYMBOL(save_nvgprs);
/*
@ -488,33 +528,30 @@ _GLOBAL(_switch)
std r23,_CCR(r1)
std r1,KSP(r3) /* Set old stack pointer */
#ifdef CONFIG_SMP
/* We need a sync somewhere here to make sure that if the
* previous task gets rescheduled on another CPU, it sees all
* stores it has performed on this one.
/*
* On SMP kernels, care must be taken because a task may be
* scheduled off CPUx and on to CPUy. Memory ordering must be
* considered.
*
* Cacheable stores on CPUx will be visible when the task is
* scheduled on CPUy by virtue of the core scheduler barriers
* (see "Notes on Program-Order guarantees on SMP systems." in
* kernel/sched/core.c).
*
* Uncacheable stores in the case of involuntary preemption must
* be taken care of. The smp_mb__before_spin_lock() in __schedule()
* is implemented as hwsync on powerpc, which orders MMIO too. So
* long as there is an hwsync in the context switch path, it will
* be executed on the source CPU after the task has performed
* all MMIO ops on that CPU, and on the destination CPU before the
* task performs any MMIO ops there.
*/
sync
#endif /* CONFIG_SMP */
/*
* If we optimise away the clear of the reservation in system
* calls because we know the CPU tracks the address of the
* reservation, then we need to clear it here to cover the
* case that the kernel context switch path has no larx
* instructions.
* The kernel context switch path must contain a spin_lock,
* which contains larx/stcx, which will clear any reservation
* of the task being switched.
*/
BEGIN_FTR_SECTION
ldarx r6,0,r1
END_FTR_SECTION_IFSET(CPU_FTR_STCX_CHECKS_ADDRESS)
BEGIN_FTR_SECTION
/*
* A cp_abort (copy paste abort) here ensures that when context switching, a
* copy from one process can't leak into the paste of another.
*/
PPC_CP_ABORT
END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
#ifdef CONFIG_PPC_BOOK3S
/* Cancel all explict user streams as they will have no use after context
* switch and will stop the HW from creating streams itself
@ -583,6 +620,14 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
top of the kernel stack. */
addi r7,r7,THREAD_SIZE-SWITCH_FRAME_SIZE
/*
* PMU interrupts in radix may come in here. They will use r1, not
* PACAKSAVE, so this stack switch will not cause a problem. They
* will store to the process stack, which may then be migrated to
* another CPU. However the rq lock release on this CPU paired with
* the rq lock acquire on the new CPU before the stack becomes
* active on the new CPU, will order those stores.
*/
mr r1,r8 /* start using new stack pointer */
std r7,PACAKSAVE(r13)
@ -763,11 +808,11 @@ restore:
ld r5,SOFTE(r1)
lbz r6,PACASOFTIRQEN(r13)
cmpwi cr0,r5,0
beq restore_irq_off
beq .Lrestore_irq_off
/* We are enabling, were we already enabled ? Yes, just return */
cmpwi cr0,r6,1
beq cr0,do_restore
beq cr0,.Ldo_restore
/*
* We are about to soft-enable interrupts (we are hard disabled
@ -776,14 +821,14 @@ restore:
*/
lbz r0,PACAIRQHAPPENED(r13)
cmpwi cr0,r0,0
bne- restore_check_irq_replay
bne- .Lrestore_check_irq_replay
/*
* Get here when nothing happened while soft-disabled, just
* soft-enable and move-on. We will hard-enable as a side
* effect of rfi
*/
restore_no_replay:
.Lrestore_no_replay:
TRACE_ENABLE_INTS
li r0,1
stb r0,PACASOFTIRQEN(r13);
@ -791,7 +836,7 @@ restore_no_replay:
/*
* Final return path. BookE is handled in a different file
*/
do_restore:
.Ldo_restore:
#ifdef CONFIG_PPC_BOOK3E
b exception_return_book3e
#else
@ -825,7 +870,7 @@ fast_exception_return:
REST_8GPRS(5, r1)
andi. r0,r3,MSR_RI
beq- unrecov_restore
beq- .Lunrecov_restore
/* Load PPR from thread struct before we clear MSR:RI */
BEGIN_FTR_SECTION
@ -883,7 +928,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
* make sure that in this case, we also clear PACA_IRQ_HARD_DIS
* or that bit can get out of sync and bad things will happen
*/
restore_irq_off:
.Lrestore_irq_off:
ld r3,_MSR(r1)
lbz r7,PACAIRQHAPPENED(r13)
andi. r0,r3,MSR_EE
@ -893,13 +938,13 @@ restore_irq_off:
1: li r0,0
stb r0,PACASOFTIRQEN(r13);
TRACE_DISABLE_INTS
b do_restore
b .Ldo_restore
/*
* Something did happen, check if a re-emit is needed
* (this also clears paca->irq_happened)
*/
restore_check_irq_replay:
.Lrestore_check_irq_replay:
/* XXX: We could implement a fast path here where we check
* for irq_happened being just 0x01, in which case we can
* clear it and return. That means that we would potentially
@ -909,7 +954,7 @@ restore_check_irq_replay:
*/
bl __check_irq_replay
cmpwi cr0,r3,0
beq restore_no_replay
beq .Lrestore_no_replay
/*
* We need to re-emit an interrupt. We do so by re-using our
@ -958,10 +1003,18 @@ restore_check_irq_replay:
#endif /* CONFIG_PPC_DOORBELL */
1: b ret_from_except /* What else to do here ? */
unrecov_restore:
.Lunrecov_restore:
addi r3,r1,STACK_FRAME_OVERHEAD
bl unrecoverable_exception
b unrecov_restore
b .Lunrecov_restore
_ASM_NOKPROBE_SYMBOL(ret_from_except);
_ASM_NOKPROBE_SYMBOL(ret_from_except_lite);
_ASM_NOKPROBE_SYMBOL(resume_kernel);
_ASM_NOKPROBE_SYMBOL(fast_exc_return_irq);
_ASM_NOKPROBE_SYMBOL(restore);
_ASM_NOKPROBE_SYMBOL(fast_exception_return);
#ifdef CONFIG_PPC_RTAS
/*
@ -1038,6 +1091,8 @@ _GLOBAL(enter_rtas)
rldicr r9,r9,MSR_SF_LG,(63-MSR_SF_LG)
ori r9,r9,MSR_IR|MSR_DR|MSR_FE0|MSR_FE1|MSR_FP|MSR_RI|MSR_LE
andc r6,r0,r9
__enter_rtas:
sync /* disable interrupts so SRR0/1 */
mtmsrd r0 /* don't get trashed */
@ -1074,6 +1129,8 @@ rtas_return_loc:
mtspr SPRN_SRR1,r4
rfid
b . /* prevent speculative execution */
_ASM_NOKPROBE_SYMBOL(__enter_rtas)
_ASM_NOKPROBE_SYMBOL(rtas_return_loc)
.align 3
1: .llong rtas_restore_regs

View File

@ -99,7 +99,11 @@ EXC_VIRT_NONE(0x4000, 0x100)
#ifdef CONFIG_PPC_P7_NAP
/*
* If running native on arch 2.06 or later, check if we are waking up
* from nap/sleep/winkle, and branch to idle handler.
* from nap/sleep/winkle, and branch to idle handler. This tests SRR1
* bits 46:47. A non-0 value indicates that we are coming from a power
* saving state. The idle wakeup handler initially runs in real mode,
* but we branch to the 0xc000... address so we can turn on relocation
* with mtmsr.
*/
#define IDLETEST(n) \
BEGIN_FTR_SECTION ; \
@ -107,7 +111,7 @@ EXC_VIRT_NONE(0x4000, 0x100)
rlwinm. r10,r10,47-31,30,31 ; \
beq- 1f ; \
cmpwi cr3,r10,2 ; \
BRANCH_TO_COMMON(r10, system_reset_idle_common) ; \
BRANCH_TO_C000(r10, system_reset_idle_common) ; \
1: \
END_FTR_SECTION_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206)
#else
@ -128,6 +132,7 @@ EXC_VIRT_NONE(0x4100, 0x100)
#ifdef CONFIG_PPC_P7_NAP
EXC_COMMON_BEGIN(system_reset_idle_common)
mfspr r12,SPRN_SRR1
b pnv_powersave_wakeup
#endif
@ -507,46 +512,22 @@ EXC_REAL_BEGIN(data_access_slb, 0x380, 0x80)
SET_SCRATCH0(r13)
EXCEPTION_PROLOG_0(PACA_EXSLB)
EXCEPTION_PROLOG_1(PACA_EXSLB, KVMTEST_PR, 0x380)
std r3,PACA_EXSLB+EX_R3(r13)
mr r12,r3 /* save r3 */
mfspr r3,SPRN_DAR
mfspr r12,SPRN_SRR1
mfspr r11,SPRN_SRR1
crset 4*cr6+eq
#ifndef CONFIG_RELOCATABLE
b slb_miss_realmode
#else
/*
* We can't just use a direct branch to slb_miss_realmode
* because the distance from here to there depends on where
* the kernel ends up being put.
*/
mfctr r11
LOAD_HANDLER(r10, slb_miss_realmode)
mtctr r10
bctr
#endif
BRANCH_TO_COMMON(r10, slb_miss_common)
EXC_REAL_END(data_access_slb, 0x380, 0x80)
EXC_VIRT_BEGIN(data_access_slb, 0x4380, 0x80)
SET_SCRATCH0(r13)
EXCEPTION_PROLOG_0(PACA_EXSLB)
EXCEPTION_PROLOG_1(PACA_EXSLB, NOTEST, 0x380)
std r3,PACA_EXSLB+EX_R3(r13)
mr r12,r3 /* save r3 */
mfspr r3,SPRN_DAR
mfspr r12,SPRN_SRR1
mfspr r11,SPRN_SRR1
crset 4*cr6+eq
#ifndef CONFIG_RELOCATABLE
b slb_miss_realmode
#else
/*
* We can't just use a direct branch to slb_miss_realmode
* because the distance from here to there depends on where
* the kernel ends up being put.
*/
mfctr r11
LOAD_HANDLER(r10, slb_miss_realmode)
mtctr r10
bctr
#endif
BRANCH_TO_COMMON(r10, slb_miss_common)
EXC_VIRT_END(data_access_slb, 0x4380, 0x80)
TRAMP_KVM_SKIP(PACA_EXSLB, 0x380)
@ -575,88 +556,82 @@ EXC_REAL_BEGIN(instruction_access_slb, 0x480, 0x80)
SET_SCRATCH0(r13)
EXCEPTION_PROLOG_0(PACA_EXSLB)
EXCEPTION_PROLOG_1(PACA_EXSLB, KVMTEST_PR, 0x480)
std r3,PACA_EXSLB+EX_R3(r13)
mr r12,r3 /* save r3 */
mfspr r3,SPRN_SRR0 /* SRR0 is faulting address */
mfspr r12,SPRN_SRR1
mfspr r11,SPRN_SRR1
crclr 4*cr6+eq
#ifndef CONFIG_RELOCATABLE
b slb_miss_realmode
#else
mfctr r11
LOAD_HANDLER(r10, slb_miss_realmode)
mtctr r10
bctr
#endif
BRANCH_TO_COMMON(r10, slb_miss_common)
EXC_REAL_END(instruction_access_slb, 0x480, 0x80)
EXC_VIRT_BEGIN(instruction_access_slb, 0x4480, 0x80)
SET_SCRATCH0(r13)
EXCEPTION_PROLOG_0(PACA_EXSLB)
EXCEPTION_PROLOG_1(PACA_EXSLB, NOTEST, 0x480)
std r3,PACA_EXSLB+EX_R3(r13)
mr r12,r3 /* save r3 */
mfspr r3,SPRN_SRR0 /* SRR0 is faulting address */
mfspr r12,SPRN_SRR1
mfspr r11,SPRN_SRR1
crclr 4*cr6+eq
#ifndef CONFIG_RELOCATABLE
b slb_miss_realmode
#else
mfctr r11
LOAD_HANDLER(r10, slb_miss_realmode)
mtctr r10
bctr
#endif
BRANCH_TO_COMMON(r10, slb_miss_common)
EXC_VIRT_END(instruction_access_slb, 0x4480, 0x80)
TRAMP_KVM(PACA_EXSLB, 0x480)
/* This handler is used by both 0x380 and 0x480 slb miss interrupts */
EXC_COMMON_BEGIN(slb_miss_realmode)
/*
* This handler is used by the 0x380 and 0x480 SLB miss interrupts, as well as
* the virtual mode 0x4380 and 0x4480 interrupts if AIL is enabled.
*/
EXC_COMMON_BEGIN(slb_miss_common)
/*
* r13 points to the PACA, r9 contains the saved CR,
* r12 contain the saved SRR1, SRR0 is still ready for return
* r12 contains the saved r3,
* r11 contain the saved SRR1, SRR0 is still ready for return
* r3 has the faulting address
* r9 - r13 are saved in paca->exslb.
* r3 is saved in paca->slb_r3
* cr6.eq is set for a D-SLB miss, clear for a I-SLB miss
* We assume we aren't going to take any exceptions during this
* procedure.
*/
mflr r10
#ifdef CONFIG_RELOCATABLE
mtctr r11
#endif
stw r9,PACA_EXSLB+EX_CCR(r13) /* save CR in exc. frame */
std r10,PACA_EXSLB+EX_LR(r13) /* save LR */
std r3,PACA_EXSLB+EX_DAR(r13)
/*
* Test MSR_RI before calling slb_allocate_realmode, because the
* MSR in r11 gets clobbered. However we still want to allocate
* SLB in case MSR_RI=0, to minimise the risk of getting stuck in
* recursive SLB faults. So use cr5 for this, which is preserved.
*/
andi. r11,r11,MSR_RI /* check for unrecoverable exception */
cmpdi cr5,r11,MSR_RI
crset 4*cr0+eq
#ifdef CONFIG_PPC_STD_MMU_64
BEGIN_MMU_FTR_SECTION
bl slb_allocate_realmode
bl slb_allocate
END_MMU_FTR_SECTION_IFCLR(MMU_FTR_TYPE_RADIX)
#endif
ld r10,PACA_EXSLB+EX_LR(r13)
ld r3,PACA_EXSLB+EX_R3(r13)
lwz r9,PACA_EXSLB+EX_CCR(r13) /* get saved CR */
mtlr r10
beq 8f /* if bad address, make full stack frame */
beq- 8f /* if bad address, make full stack frame */
andi. r10,r12,MSR_RI /* check for unrecoverable exception */
beq- 2f
bne- cr5,2f /* if unrecoverable exception, oops */
/* All done -- return from exception. */
.machine push
.machine "power4"
mtcrf 0x80,r9
mtcrf 0x04,r9 /* MSR[RI] indication is in cr5 */
mtcrf 0x02,r9 /* I/D indication is in cr6 */
mtcrf 0x01,r9 /* slb_allocate uses cr0 and cr7 */
.machine pop
RESTORE_CTR(r9, PACA_EXSLB)
RESTORE_PPR_PACA(PACA_EXSLB, r9)
mr r3,r12
ld r9,PACA_EXSLB+EX_R9(r13)
ld r10,PACA_EXSLB+EX_R10(r13)
ld r11,PACA_EXSLB+EX_R11(r13)
@ -665,7 +640,10 @@ END_MMU_FTR_SECTION_IFCLR(MMU_FTR_TYPE_RADIX)
rfid
b . /* prevent speculative execution */
2: mfspr r11,SPRN_SRR0
2: std r3,PACA_EXSLB+EX_DAR(r13)
mr r3,r12
mfspr r11,SPRN_SRR0
mfspr r12,SPRN_SRR1
LOAD_HANDLER(r10,unrecov_slb)
mtspr SPRN_SRR0,r10
ld r10,PACAKMSR(r13)
@ -673,7 +651,10 @@ END_MMU_FTR_SECTION_IFCLR(MMU_FTR_TYPE_RADIX)
rfid
b .
8: mfspr r11,SPRN_SRR0
8: std r3,PACA_EXSLB+EX_DAR(r13)
mr r3,r12
mfspr r11,SPRN_SRR0
mfspr r12,SPRN_SRR1
LOAD_HANDLER(r10,bad_addr_slb)
mtspr SPRN_SRR0,r10
ld r10,PACAKMSR(r13)
@ -821,46 +802,80 @@ EXC_VIRT(trap_0b, 0x4b00, 0x100, 0xb00)
TRAMP_KVM(PACA_EXGEN, 0xb00)
EXC_COMMON(trap_0b_common, 0xb00, unknown_exception)
/*
* system call / hypercall (0xc00, 0x4c00)
*
* The system call exception is invoked with "sc 0" and does not alter HV bit.
* There is support for kernel code to invoke system calls but there are no
* in-tree users.
*
* The hypercall is invoked with "sc 1" and sets HV=1.
*
* In HPT, sc 1 always goes to 0xc00 real mode. In RADIX, sc 1 can go to
* 0x4c00 virtual mode.
*
* Call convention:
*
* syscall register convention is in Documentation/powerpc/syscall64-abi.txt
*
* For hypercalls, the register convention is as follows:
* r0 volatile
* r1-2 nonvolatile
* r3 volatile parameter and return value for status
* r4-r10 volatile input and output value
* r11 volatile hypercall number and output value
* r12 volatile
* r13-r31 nonvolatile
* LR nonvolatile
* CTR volatile
* XER volatile
* CR0-1 CR5-7 volatile
* CR2-4 nonvolatile
* Other registers nonvolatile
*
* The intersection of volatile registers that don't contain possible
* inputs is: r12, cr0, xer, ctr. We may use these as scratch regs
* upon entry without saving.
*/
#ifdef CONFIG_KVM_BOOK3S_64_HANDLER
/*
* If CONFIG_KVM_BOOK3S_64_HANDLER is set, save the PPR (on systems
* that support it) before changing to HMT_MEDIUM. That allows the KVM
* code to save that value into the guest state (it is the guest's PPR
* value). Otherwise just change to HMT_MEDIUM as userspace has
* already saved the PPR.
*/
/*
* There is a little bit of juggling to get syscall and hcall
* working well. Save r10 in ctr to be restored in case it is a
* hcall.
*
* Userspace syscalls have already saved the PPR, hcalls must save
* it before setting HMT_MEDIUM.
*/
#define SYSCALL_KVMTEST \
SET_SCRATCH0(r13); \
mr r12,r13; \
GET_PACA(r13); \
std r9,PACA_EXGEN+EX_R9(r13); \
OPT_GET_SPR(r9, SPRN_PPR, CPU_FTR_HAS_PPR); \
mtctr r10; \
KVMTEST_PR(0xc00); /* uses r10, branch to do_kvm_0xc00_system_call */ \
HMT_MEDIUM; \
std r10,PACA_EXGEN+EX_R10(r13); \
OPT_SAVE_REG_TO_PACA(PACA_EXGEN+EX_PPR, r9, CPU_FTR_HAS_PPR); \
mfcr r9; \
KVMTEST_PR(0xc00); \
GET_SCRATCH0(r13)
mr r9,r12; \
#else
#define SYSCALL_KVMTEST \
HMT_MEDIUM
HMT_MEDIUM; \
mr r9,r13; \
GET_PACA(r13);
#endif
#define LOAD_SYSCALL_HANDLER(reg) \
__LOAD_HANDLER(reg, system_call_common)
/* Syscall routine is used twice, in reloc-off and reloc-on paths */
#define SYSCALL_PSERIES_1 \
#define SYSCALL_FASTENDIAN_TEST \
BEGIN_FTR_SECTION \
cmpdi r0,0x1ebe ; \
beq- 1f ; \
END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE) \
mr r9,r13 ; \
GET_PACA(r13) ; \
mfspr r11,SPRN_SRR0 ; \
0:
#define SYSCALL_PSERIES_2_RFID \
/*
* After SYSCALL_KVMTEST, we reach here with PACA in r13, r13 in r9,
* and HMT_MEDIUM.
*/
#define SYSCALL_REAL \
mfspr r11,SPRN_SRR0 ; \
mfspr r12,SPRN_SRR1 ; \
LOAD_SYSCALL_HANDLER(r10) ; \
mtspr SPRN_SRR0,r10 ; \
@ -869,11 +884,12 @@ END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE) \
rfid ; \
b . ; /* prevent speculative execution */
#define SYSCALL_PSERIES_3 \
#define SYSCALL_FASTENDIAN \
/* Fast LE/BE switch system call */ \
1: mfspr r12,SPRN_SRR1 ; \
xori r12,r12,MSR_LE ; \
mtspr SPRN_SRR1,r12 ; \
mr r13,r9 ; \
rfid ; /* return to userspace */ \
b . ; /* prevent speculative execution */
@ -882,16 +898,18 @@ END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE) \
* We can't branch directly so we do it via the CTR which
* is volatile across system calls.
*/
#define SYSCALL_PSERIES_2_DIRECT \
LOAD_SYSCALL_HANDLER(r12) ; \
mtctr r12 ; \
#define SYSCALL_VIRT \
LOAD_SYSCALL_HANDLER(r10) ; \
mtctr r10 ; \
mfspr r11,SPRN_SRR0 ; \
mfspr r12,SPRN_SRR1 ; \
li r10,MSR_RI ; \
mtmsrd r10,1 ; \
bctr ;
#else
/* We can branch directly */
#define SYSCALL_PSERIES_2_DIRECT \
#define SYSCALL_VIRT \
mfspr r11,SPRN_SRR0 ; \
mfspr r12,SPRN_SRR1 ; \
li r10,MSR_RI ; \
mtmsrd r10,1 ; /* Set RI (EE=0) */ \
@ -899,20 +917,43 @@ END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE) \
#endif
EXC_REAL_BEGIN(system_call, 0xc00, 0x100)
SYSCALL_KVMTEST
SYSCALL_PSERIES_1
SYSCALL_PSERIES_2_RFID
SYSCALL_PSERIES_3
SYSCALL_KVMTEST /* loads PACA into r13, and saves r13 to r9 */
SYSCALL_FASTENDIAN_TEST
SYSCALL_REAL
SYSCALL_FASTENDIAN
EXC_REAL_END(system_call, 0xc00, 0x100)
EXC_VIRT_BEGIN(system_call, 0x4c00, 0x100)
SYSCALL_KVMTEST
SYSCALL_PSERIES_1
SYSCALL_PSERIES_2_DIRECT
SYSCALL_PSERIES_3
SYSCALL_KVMTEST /* loads PACA into r13, and saves r13 to r9 */
SYSCALL_FASTENDIAN_TEST
SYSCALL_VIRT
SYSCALL_FASTENDIAN
EXC_VIRT_END(system_call, 0x4c00, 0x100)
TRAMP_KVM(PACA_EXGEN, 0xc00)
#ifdef CONFIG_KVM_BOOK3S_64_HANDLER
/*
* This is a hcall, so register convention is as above, with these
* differences:
* r13 = PACA
* r12 = orig r13
* ctr = orig r10
*/
TRAMP_KVM_BEGIN(do_kvm_0xc00)
/*
* Save the PPR (on systems that support it) before changing to
* HMT_MEDIUM. That allows the KVM code to save that value into the
* guest state (it is the guest's PPR value).
*/
OPT_GET_SPR(r0, SPRN_PPR, CPU_FTR_HAS_PPR)
HMT_MEDIUM
OPT_SAVE_REG_TO_PACA(PACA_EXGEN+EX_PPR, r0, CPU_FTR_HAS_PPR)
mfctr r10
SET_SCRATCH0(r12)
std r9,PACA_EXGEN+EX_R9(r13)
mfcr r9
std r10,PACA_EXGEN+EX_R10(r13)
KVM_HANDLER(PACA_EXGEN, EXC_STD, 0xc00)
#endif
EXC_REAL(single_step, 0xd00, 0x100)
@ -1553,6 +1594,26 @@ END_FTR_SECTION_IFSET(CPU_FTR_CFAR)
1: addi r3,r1,STACK_FRAME_OVERHEAD
bl kernel_bad_stack
b 1b
_ASM_NOKPROBE_SYMBOL(bad_stack);
/*
* When doorbell is triggered from system reset wakeup, the message is
* not cleared, so it would fire again when EE is enabled.
*
* When coming from local_irq_enable, there may be the same problem if
* we were hard disabled.
*
* Execute msgclr to clear pending exceptions before handling it.
*/
h_doorbell_common_msgclr:
LOAD_REG_IMMEDIATE(r3, PPC_DBELL_MSGTYPE << (63-36))
PPC_MSGCLR(3)
b h_doorbell_common
doorbell_super_common_msgclr:
LOAD_REG_IMMEDIATE(r3, PPC_DBELL_MSGTYPE << (63-36))
PPC_MSGCLRP(3)
b doorbell_super_common
/*
* Called from arch_local_irq_enable when an interrupt needs
@ -1563,6 +1624,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_CFAR)
* Note: While MSR:EE is off, we need to make sure that _MSR
* in the generated frame has EE set to 1 or the exception
* handler will not properly re-enable them.
*
* Note that we don't specify LR as the NIP (return address) for
* the interrupt because that would unbalance the return branch
* predictor.
*/
_GLOBAL(__replay_interrupt)
/* We are going to jump to the exception common code which
@ -1570,7 +1635,7 @@ _GLOBAL(__replay_interrupt)
* we don't give a damn about, so we don't bother storing them.
*/
mfmsr r12
mflr r11
LOAD_REG_ADDR(r11, 1f)
mfcr r9
ori r12,r12,MSR_EE
cmpwi r3,0x900
@ -1579,13 +1644,16 @@ _GLOBAL(__replay_interrupt)
beq hardware_interrupt_common
BEGIN_FTR_SECTION
cmpwi r3,0xe80
beq h_doorbell_common
beq h_doorbell_common_msgclr
cmpwi r3,0xea0
beq h_virt_irq_common
cmpwi r3,0xe60
beq hmi_exception_common
FTR_SECTION_ELSE
cmpwi r3,0xa00
beq doorbell_super_common
beq doorbell_super_common_msgclr
ALT_FTR_SECTION_END_IFSET(CPU_FTR_HVMODE)
1:
blr
_ASM_NOKPROBE_SYMBOL(__replay_interrupt)

View File

@ -113,11 +113,55 @@ int __init early_init_dt_scan_fw_dump(unsigned long node,
return 1;
}
/*
* If fadump is registered, check if the memory provided
* falls within boot memory area.
*/
int is_fadump_boot_memory_area(u64 addr, ulong size)
{
if (!fw_dump.dump_registered)
return 0;
return (addr + size) > RMA_START && addr <= fw_dump.boot_memory_size;
}
int is_fadump_active(void)
{
return fw_dump.dump_active;
}
/*
* Returns 1, if there are no holes in boot memory area,
* 0 otherwise.
*/
static int is_boot_memory_area_contiguous(void)
{
struct memblock_region *reg;
unsigned long tstart, tend;
unsigned long start_pfn = PHYS_PFN(RMA_START);
unsigned long end_pfn = PHYS_PFN(RMA_START + fw_dump.boot_memory_size);
unsigned int ret = 0;
for_each_memblock(memory, reg) {
tstart = max(start_pfn, memblock_region_memory_base_pfn(reg));
tend = min(end_pfn, memblock_region_memory_end_pfn(reg));
if (tstart < tend) {
/* Memory hole from start_pfn to tstart */
if (tstart > start_pfn)
break;
if (tend == end_pfn) {
ret = 1;
break;
}
start_pfn = tend + 1;
}
}
return ret;
}
/* Print firmware assisted dump configurations for debugging purpose. */
static void fadump_show_config(void)
{
@ -212,20 +256,46 @@ static inline unsigned long fadump_calculate_reserve_size(void)
int ret;
unsigned long long base, size;
if (fw_dump.reserve_bootvar)
pr_warn("'fadump_reserve_mem=' parameter is deprecated in favor of 'crashkernel=' parameter.\n");
/*
* Check if the size is specified through crashkernel= cmdline
* option. If yes, then use that but ignore base as fadump
* reserves memory at end of RAM.
* option. If yes, then use that but ignore base as fadump reserves
* memory at a predefined offset.
*/
ret = parse_crashkernel(boot_command_line, memblock_phys_mem_size(),
&size, &base);
if (ret == 0 && size > 0) {
unsigned long max_size;
if (fw_dump.reserve_bootvar)
pr_info("Using 'crashkernel=' parameter for memory reservation.\n");
fw_dump.reserve_bootvar = (unsigned long)size;
/*
* Adjust if the boot memory size specified is above
* the upper limit.
*/
max_size = memblock_phys_mem_size() / MAX_BOOT_MEM_RATIO;
if (fw_dump.reserve_bootvar > max_size) {
fw_dump.reserve_bootvar = max_size;
pr_info("Adjusted boot memory size to %luMB\n",
(fw_dump.reserve_bootvar >> 20));
}
return fw_dump.reserve_bootvar;
} else if (fw_dump.reserve_bootvar) {
/*
* 'fadump_reserve_mem=' is being used to reserve memory
* for firmware-assisted dump.
*/
return fw_dump.reserve_bootvar;
}
/* divide by 20 to get 5% of value */
size = memblock_end_of_DRAM() / 20;
size = memblock_phys_mem_size() / 20;
/* round it down in multiples of 256 */
size = size & ~0x0FFFFFFFUL;
@ -377,9 +447,22 @@ static int __init early_fadump_param(char *p)
}
early_param("fadump", early_fadump_param);
static void register_fw_dump(struct fadump_mem_struct *fdm)
/*
* Look for fadump_reserve_mem= cmdline option
* TODO: Remove references to 'fadump_reserve_mem=' parameter,
* the sooner 'crashkernel=' parameter is accustomed to.
*/
static int __init early_fadump_reserve_mem(char *p)
{
int rc;
if (p)
fw_dump.reserve_bootvar = memparse(p, &p);
return 0;
}
early_param("fadump_reserve_mem", early_fadump_reserve_mem);
static int register_fw_dump(struct fadump_mem_struct *fdm)
{
int rc, err;
unsigned int wait_time;
pr_debug("Registering for firmware-assisted kernel dump...\n");
@ -396,26 +479,38 @@ static void register_fw_dump(struct fadump_mem_struct *fdm)
} while (wait_time);
err = -EIO;
switch (rc) {
default:
pr_err("Failed to register. Unknown Error(%d).\n", rc);
break;
case -1:
printk(KERN_ERR "Failed to register firmware-assisted kernel"
" dump. Hardware Error(%d).\n", rc);
break;
case -3:
if (!is_boot_memory_area_contiguous())
pr_err("Can't have holes in boot memory area while "
"registering fadump\n");
printk(KERN_ERR "Failed to register firmware-assisted kernel"
" dump. Parameter Error(%d).\n", rc);
err = -EINVAL;
break;
case -9:
printk(KERN_ERR "firmware-assisted kernel dump is already "
" registered.");
fw_dump.dump_registered = 1;
err = -EEXIST;
break;
case 0:
printk(KERN_INFO "firmware-assisted kernel dump registration"
" is successful\n");
fw_dump.dump_registered = 1;
err = 0;
break;
}
return err;
}
void crash_fadump(struct pt_regs *regs, const char *str)
@ -831,8 +926,19 @@ static void fadump_setup_crash_memory_ranges(void)
for_each_memblock(memory, reg) {
start = (unsigned long long)reg->base;
end = start + (unsigned long long)reg->size;
if (start == RMA_START && end >= fw_dump.boot_memory_size)
start = fw_dump.boot_memory_size;
/*
* skip the first memory chunk that is already added (RMA_START
* through boot_memory_size). This logic needs a relook if and
* when RMA_START changes to a non-zero value.
*/
BUILD_BUG_ON(RMA_START != 0);
if (start < fw_dump.boot_memory_size) {
if (end > fw_dump.boot_memory_size)
start = fw_dump.boot_memory_size;
else
continue;
}
/* add this range excluding the reserved dump area. */
fadump_exclude_reserved_area(start, end);
@ -956,7 +1062,7 @@ static unsigned long init_fadump_header(unsigned long addr)
return addr;
}
static void register_fadump(void)
static int register_fadump(void)
{
unsigned long addr;
void *vaddr;
@ -966,7 +1072,7 @@ static void register_fadump(void)
* assisted dump.
*/
if (!fw_dump.reserve_dump_area_size)
return;
return -ENODEV;
fadump_setup_crash_memory_ranges();
@ -979,7 +1085,7 @@ static void register_fadump(void)
fadump_create_elfcore_headers(vaddr);
/* register the future kernel dump with firmware. */
register_fw_dump(&fdm);
return register_fw_dump(&fdm);
}
static int fadump_unregister_dump(struct fadump_mem_struct *fdm)
@ -1046,28 +1152,71 @@ void fadump_cleanup(void)
}
}
static void fadump_free_reserved_memory(unsigned long start_pfn,
unsigned long end_pfn)
{
unsigned long pfn;
unsigned long time_limit = jiffies + HZ;
pr_info("freeing reserved memory (0x%llx - 0x%llx)\n",
PFN_PHYS(start_pfn), PFN_PHYS(end_pfn));
for (pfn = start_pfn; pfn < end_pfn; pfn++) {
free_reserved_page(pfn_to_page(pfn));
if (time_after(jiffies, time_limit)) {
cond_resched();
time_limit = jiffies + HZ;
}
}
}
/*
* Skip memory holes and free memory that was actually reserved.
*/
static void fadump_release_reserved_area(unsigned long start, unsigned long end)
{
struct memblock_region *reg;
unsigned long tstart, tend;
unsigned long start_pfn = PHYS_PFN(start);
unsigned long end_pfn = PHYS_PFN(end);
for_each_memblock(memory, reg) {
tstart = max(start_pfn, memblock_region_memory_base_pfn(reg));
tend = min(end_pfn, memblock_region_memory_end_pfn(reg));
if (tstart < tend) {
fadump_free_reserved_memory(tstart, tend);
if (tend == end_pfn)
break;
start_pfn = tend + 1;
}
}
}
/*
* Release the memory that was reserved in early boot to preserve the memory
* contents. The released memory will be available for general use.
*/
static void fadump_release_memory(unsigned long begin, unsigned long end)
{
unsigned long addr;
unsigned long ra_start, ra_end;
ra_start = fw_dump.reserve_dump_area_start;
ra_end = ra_start + fw_dump.reserve_dump_area_size;
for (addr = begin; addr < end; addr += PAGE_SIZE) {
/*
* exclude the dump reserve area. Will reuse it for next
* fadump registration.
*/
if (addr <= ra_end && ((addr + PAGE_SIZE) > ra_start))
continue;
free_reserved_page(pfn_to_page(addr >> PAGE_SHIFT));
}
/*
* exclude the dump reserve area. Will reuse it for next
* fadump registration.
*/
if (begin < ra_end && end > ra_start) {
if (begin < ra_start)
fadump_release_reserved_area(begin, ra_start);
if (end > ra_end)
fadump_release_reserved_area(ra_end, end);
} else
fadump_release_reserved_area(begin, end);
}
static void fadump_invalidate_release_mem(void)
@ -1161,7 +1310,6 @@ static ssize_t fadump_register_store(struct kobject *kobj,
switch (buf[0]) {
case '0':
if (fw_dump.dump_registered == 0) {
ret = -EINVAL;
goto unlock_out;
}
/* Un-register Firmware-assisted dump */
@ -1169,11 +1317,11 @@ static ssize_t fadump_register_store(struct kobject *kobj,
break;
case '1':
if (fw_dump.dump_registered == 1) {
ret = -EINVAL;
ret = -EEXIST;
goto unlock_out;
}
/* Register Firmware-assisted dump */
register_fadump();
ret = register_fadump();
break;
default:
ret = -EINVAL;

View File

@ -31,6 +31,7 @@
* registers for winkle support.
*/
#define _SDR1 GPR3
#define _PTCR GPR3
#define _RPR GPR4
#define _SPURR GPR5
#define _PURR GPR6
@ -39,7 +40,7 @@
#define _AMOR GPR9
#define _WORT GPR10
#define _WORC GPR11
#define _PTCR GPR12
#define _LPCR GPR12
#define PSSCR_EC_ESL_MASK_SHIFTED (PSSCR_EC | PSSCR_ESL) >> 16
@ -55,12 +56,14 @@ save_sprs_to_stack:
* here since any thread in the core might wake up first
*/
BEGIN_FTR_SECTION
mfspr r3,SPRN_PTCR
std r3,_PTCR(r1)
/*
* Note - SDR1 is dropped in Power ISA v3. Hence not restoring
* SDR1 here
*/
mfspr r3,SPRN_PTCR
std r3,_PTCR(r1)
mfspr r3,SPRN_LPCR
std r3,_LPCR(r1)
FTR_SECTION_ELSE
mfspr r3,SPRN_SDR1
std r3,_SDR1(r1)
@ -106,13 +109,9 @@ core_idle_lock_held:
/*
* Pass requested state in r3:
* r3 - PNV_THREAD_NAP/SLEEP/WINKLE in POWER8
* - Requested STOP state in POWER9
* - Requested PSSCR value in POWER9
*
* To check IRQ_HAPPENED in r4
* 0 - don't check
* 1 - check
*
* Address to 'rfid' to in r5
* Address of idle handler to branch to in realmode in r4
*/
pnv_powersave_common:
/* Use r3 to pass state nap/sleep/winkle */
@ -122,37 +121,14 @@ pnv_powersave_common:
* need to save PC, some CR bits and the NV GPRs,
* but for now an interrupt frame will do.
*/
mtctr r4
mflr r0
std r0,16(r1)
stdu r1,-INT_FRAME_SIZE(r1)
std r0,_LINK(r1)
std r0,_NIP(r1)
/* Hard disable interrupts */
mfmsr r9
rldicl r9,r9,48,1
rotldi r9,r9,16
mtmsrd r9,1 /* hard-disable interrupts */
/* Check if something happened while soft-disabled */
lbz r0,PACAIRQHAPPENED(r13)
andi. r0,r0,~PACA_IRQ_HARD_DIS@l
beq 1f
cmpwi cr0,r4,0
beq 1f
addi r1,r1,INT_FRAME_SIZE
ld r0,16(r1)
li r3,0 /* Return 0 (no nap) */
mtlr r0
blr
1: /* We mark irqs hard disabled as this is the state we'll
* be in when returning and we need to tell arch_local_irq_restore()
* about it
*/
li r0,PACA_IRQ_HARD_DIS
stb r0,PACAIRQHAPPENED(r13)
/* We haven't lost state ... yet */
li r0,0
stb r0,PACA_NAPSTATELOST(r13)
@ -160,9 +136,8 @@ pnv_powersave_common:
/* Continue saving state */
SAVE_GPR(2, r1)
SAVE_NVGPRS(r1)
mfcr r4
std r4,_CCR(r1)
std r9,_MSR(r1)
mfcr r5
std r5,_CCR(r1)
std r1,PACAR1(r13)
/*
@ -172,12 +147,8 @@ pnv_powersave_common:
* the MMU context to the guest.
*/
LOAD_REG_IMMEDIATE(r7, MSR_IDLE)
li r6, MSR_RI
andc r6, r9, r6
mtmsrd r6, 1 /* clear RI before setting SRR0/1 */
mtspr SPRN_SRR0, r5
mtspr SPRN_SRR1, r7
rfid
mtmsrd r7,0
bctr
.globl pnv_enter_arch207_idle_mode
pnv_enter_arch207_idle_mode:
@ -285,6 +256,19 @@ power_enter_stop:
bne .Lhandle_esl_ec_set
IDLE_STATE_ENTER_SEQ(PPC_STOP)
li r3,0 /* Since we didn't lose state, return 0 */
/*
* pnv_wakeup_noloss() expects r12 to contain the SRR1 value so
* it can determine if the wakeup reason is an HMI in
* CHECK_HMI_INTERRUPT.
*
* However, when we wakeup with ESL=0, SRR1 will not contain the wakeup
* reason, so there is no point setting r12 to SRR1.
*
* Further, we clear r12 here, so that we don't accidentally enter the
* HMI in pnv_wakeup_noloss() if the value of r12[42:45] == WAKE_HMI.
*/
li r12, 0
b pnv_wakeup_noloss
.Lhandle_esl_ec_set:
@ -319,45 +303,23 @@ lwarx_loop_stop:
IDLE_STATE_ENTER_SEQ_NORET(PPC_STOP)
_GLOBAL(power7_idle)
/*
* Entered with MSR[EE]=0 and no soft-masked interrupts pending.
* r3 contains desired idle state (PNV_THREAD_NAP/SLEEP/WINKLE).
*/
_GLOBAL(power7_idle_insn)
/* Now check if user or arch enabled NAP mode */
LOAD_REG_ADDRBASE(r3,powersave_nap)
lwz r4,ADDROFF(powersave_nap)(r3)
cmpwi 0,r4,0
beqlr
li r3, 1
/* fall through */
_GLOBAL(power7_nap)
mr r4,r3
li r3,PNV_THREAD_NAP
LOAD_REG_ADDR(r5, pnv_enter_arch207_idle_mode)
LOAD_REG_ADDR(r4, pnv_enter_arch207_idle_mode)
b pnv_powersave_common
/* No return */
_GLOBAL(power7_sleep)
li r3,PNV_THREAD_SLEEP
li r4,1
LOAD_REG_ADDR(r5, pnv_enter_arch207_idle_mode)
b pnv_powersave_common
/* No return */
_GLOBAL(power7_winkle)
li r3,PNV_THREAD_WINKLE
li r4,1
LOAD_REG_ADDR(r5, pnv_enter_arch207_idle_mode)
b pnv_powersave_common
/* No return */
#define CHECK_HMI_INTERRUPT \
mfspr r0,SPRN_SRR1; \
BEGIN_FTR_SECTION_NESTED(66); \
rlwinm r0,r0,45-31,0xf; /* extract wake reason field (P8) */ \
rlwinm r0,r12,45-31,0xf; /* extract wake reason field (P8) */ \
FTR_SECTION_ELSE_NESTED(66); \
rlwinm r0,r0,45-31,0xe; /* P7 wake reason field is 3 bits */ \
rlwinm r0,r12,45-31,0xe; /* P7 wake reason field is 3 bits */ \
ALT_FTR_SECTION_END_NESTED_IFSET(CPU_FTR_ARCH_207S, 66); \
cmpwi r0,0xa; /* Hypervisor maintenance ? */ \
bne 20f; \
bne+ 20f; \
/* Invoke opal call to handle hmi */ \
ld r2,PACATOC(r13); \
ld r1,PACAR1(r13); \
@ -369,16 +331,13 @@ ALT_FTR_SECTION_END_NESTED_IFSET(CPU_FTR_ARCH_207S, 66); \
20: nop;
/*
* r3 - The PSSCR value corresponding to the stop state.
* r4 - The PSSCR mask corrresonding to the stop state.
* Entered with MSR[EE]=0 and no soft-masked interrupts pending.
* r3 contains desired PSSCR register value.
*/
_GLOBAL(power9_idle_stop)
mfspr r5,SPRN_PSSCR
andc r5,r5,r4
or r3,r3,r5
std r3, PACA_REQ_PSSCR(r13)
mtspr SPRN_PSSCR,r3
LOAD_REG_ADDR(r5,power_enter_stop)
li r4,1
LOAD_REG_ADDR(r4,power_enter_stop)
b pnv_powersave_common
/* No return */
@ -436,17 +395,17 @@ pnv_powersave_wakeup_mce:
/*
* Now put the original SRR1 with SRR1_WAKEMCE_RESVD as the wake
* reason into SRR1, which allows reuse of the system reset wakeup
* reason into r12, which allows reuse of the system reset wakeup
* code without being mistaken for another type of wakeup.
*/
oris r3,r3,SRR1_WAKEMCE_RESVD@h
mtspr SPRN_SRR1,r3
oris r12,r3,SRR1_WAKEMCE_RESVD@h
b pnv_powersave_wakeup
/*
* Called from reset vector for powersave wakeups.
* cr3 - set to gt if waking up with partial/complete hypervisor state loss
* r12 - SRR1
*/
.global pnv_powersave_wakeup
pnv_powersave_wakeup:
@ -464,6 +423,8 @@ ALT_FTR_SECTION_END_IFSET(CPU_FTR_ARCH_300)
li r0,PNV_THREAD_RUNNING
stb r0,PACA_THREAD_IDLE_STATE(r13) /* Clear thread state */
mr r3,r12
#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
li r0,KVM_HWTHREAD_IN_KERNEL
stb r0,HSTATE_HWTHREAD_STATE(r13)
@ -477,7 +438,6 @@ ALT_FTR_SECTION_END_IFSET(CPU_FTR_ARCH_300)
#endif
/* Return SRR1 from power7_nap() */
mfspr r3,SPRN_SRR1
blt cr3,pnv_wakeup_noloss
b pnv_wakeup_loss
@ -488,6 +448,13 @@ ALT_FTR_SECTION_END_IFSET(CPU_FTR_ARCH_300)
* cr3 - set to gt if waking up with partial/complete hypervisor state loss
*/
pnv_restore_hyp_resource_arch300:
/*
* Workaround for POWER9, if we lost resources, the ERAT
* might have been mixed up and needs flushing.
*/
blt cr3,1f
PPC_INVALIDATE_ERAT
1:
/*
* POWER ISA 3. Use PSSCR to determine if we
* are waking up from deep idle state
@ -495,12 +462,22 @@ pnv_restore_hyp_resource_arch300:
LOAD_REG_ADDRBASE(r5,pnv_first_deep_stop_state)
ld r4,ADDROFF(pnv_first_deep_stop_state)(r5)
mfspr r5,SPRN_PSSCR
BEGIN_FTR_SECTION_NESTED(71)
/*
* Assume that we are waking up from the state
* same as the Requested Level (RL) in the PSSCR
* which are Bits 60-63
*/
ld r5,PACA_REQ_PSSCR(r13)
rldicl r5,r5,0,60
FTR_SECTION_ELSE_NESTED(71)
/*
* 0-3 bits correspond to Power-Saving Level Status
* which indicates the idle state we are waking up from
*/
mfspr r5, SPRN_PSSCR
rldicl r5,r5,4,60
ALT_FTR_SECTION_END_NESTED_IFSET(CPU_FTR_POWER9_DD1, 71)
cmpd cr4,r5,r4
bge cr4,pnv_wakeup_tb_loss /* returns to caller */
@ -567,9 +544,9 @@ pnv_wakeup_tb_loss:
* is required to return back to reset vector after hypervisor state
* restore is complete.
*/
mr r19,r12
mr r18,r4
mflr r17
mfspr r16,SPRN_SRR1
BEGIN_FTR_SECTION
CHECK_HMI_INTERRUPT
END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
@ -731,13 +708,14 @@ timebase_resync:
* Use cr3 which indicates that we are waking up with atleast partial
* hypervisor state loss to determine if TIMEBASE RESYNC is needed.
*/
ble cr3,clear_lock
ble cr3,.Ltb_resynced
/* Time base re-sync */
bl opal_resync_timebase;
/*
* If waking up from sleep, per core state is not lost, skip to
* clear_lock.
* If waking up from sleep (POWER8), per core state
* is not lost, skip to clear_lock.
*/
.Ltb_resynced:
blt cr4,clear_lock
/*
@ -812,9 +790,13 @@ no_segments:
mtctr r12
bctrl
BEGIN_FTR_SECTION
ld r4,_LPCR(r1)
mtspr SPRN_LPCR,r4
END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
hypervisor_state_restored:
mtspr SPRN_SRR1,r16
mr r12,r19
mtlr r17
blr /* return to pnv_powersave_wakeup */
@ -827,6 +809,7 @@ fastsleep_workaround_at_exit:
/*
* R3 here contains the value that will be returned to the caller
* of power7_nap.
* R12 contains SRR1 for CHECK_HMI_INTERRUPT.
*/
.global pnv_wakeup_loss
pnv_wakeup_loss:
@ -836,32 +819,33 @@ BEGIN_FTR_SECTION
END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
REST_NVGPRS(r1)
REST_GPR(2, r1)
ld r4,PACAKMSR(r13)
ld r5,_LINK(r1)
ld r6,_CCR(r1)
ld r4,_MSR(r1)
ld r5,_NIP(r1)
addi r1,r1,INT_FRAME_SIZE
mtlr r5
mtcr r6
mtspr SPRN_SRR1,r4
mtspr SPRN_SRR0,r5
rfid
mtmsrd r4
blr
/*
* R3 here contains the value that will be returned to the caller
* of power7_nap.
* R12 contains SRR1 for CHECK_HMI_INTERRUPT.
*/
pnv_wakeup_noloss:
lbz r0,PACA_NAPSTATELOST(r13)
cmpwi r0,0
bne pnv_wakeup_loss
ld r1,PACAR1(r13)
BEGIN_FTR_SECTION
CHECK_HMI_INTERRUPT
END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
ld r1,PACAR1(r13)
ld r6,_CCR(r1)
ld r4,_MSR(r1)
ld r4,PACAKMSR(r13)
ld r5,_NIP(r1)
ld r6,_CCR(r1)
addi r1,r1,INT_FRAME_SIZE
mtlr r5
mtcr r6
mtspr SPRN_SRR1,r4
mtspr SPRN_SRR0,r5
rfid
mtmsrd r4
blr

View File

@ -322,7 +322,8 @@ 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();
__hard_irq_disable();
local_paca->irq_happened |= PACA_IRQ_HARD_DIS;
/*
* If anything happened while we were soft-disabled,
@ -347,6 +348,65 @@ bool prep_irq_for_idle(void)
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.
*/
static const u8 srr1_to_lazyirq[0x10] = {
0, 0, 0,
PACA_IRQ_DBELL,
0,
PACA_IRQ_DBELL,
PACA_IRQ_DEC,
0,
PACA_IRQ_EE,
PACA_IRQ_EE,
PACA_IRQ_HMI,
0, 0, 0, 0, 0 };
void irq_set_pending_from_srr1(unsigned long srr1)
{
unsigned int idx = (srr1 & SRR1_WAKEMASK_P8) >> 18;
/*
* The 0 index (SRR1[42:45]=b0000) must always evaluate to 0,
* so this can be called unconditionally with srr1 wake reason.
*/
local_paca->irq_happened |= srr1_to_lazyirq[idx];
}
#endif /* CONFIG_PPC_BOOK3S */
/*
* Force a replay of the external interrupt handler on this CPU.
*/

View File

@ -164,17 +164,13 @@ NOKPROBE_SYMBOL(arch_prepare_kprobe);
void arch_arm_kprobe(struct kprobe *p)
{
*p->addr = BREAKPOINT_INSTRUCTION;
flush_icache_range((unsigned long) p->addr,
(unsigned long) p->addr + sizeof(kprobe_opcode_t));
patch_instruction(p->addr, BREAKPOINT_INSTRUCTION);
}
NOKPROBE_SYMBOL(arch_arm_kprobe);
void arch_disarm_kprobe(struct kprobe *p)
{
*p->addr = p->opcode;
flush_icache_range((unsigned long) p->addr,
(unsigned long) p->addr + sizeof(kprobe_opcode_t));
patch_instruction(p->addr, p->opcode);
}
NOKPROBE_SYMBOL(arch_disarm_kprobe);

View File

@ -268,6 +268,7 @@ void machine_check_print_event_info(struct machine_check_event *evt,
static const char *mc_ra_types[] = {
"Indeterminate",
"Instruction fetch (bad)",
"Instruction fetch (foreign)",
"Page table walk ifetch (bad)",
"Page table walk ifetch (foreign)",
"Load (bad)",

View File

@ -236,6 +236,9 @@ static const struct mce_ierror_table mce_p9_ierror_table[] = {
{ 0x00000000081c0000, 0x0000000000180000, true,
MCE_ERROR_TYPE_UE, MCE_UE_ERROR_PAGE_TABLE_WALK_IFETCH,
MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
{ 0x00000000081c0000, 0x00000000001c0000, true,
MCE_ERROR_TYPE_RA, MCE_RA_ERROR_IFETCH_FOREIGN,
MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },
{ 0x00000000081c0000, 0x0000000008000000, true,
MCE_ERROR_TYPE_LINK,MCE_LINK_ERROR_IFETCH_TIMEOUT,
MCE_INITIATOR_CPU, MCE_SEV_ERROR_SYNC, },

View File

@ -244,8 +244,7 @@ _GLOBAL(_nmask_and_or_msr)
*/
_GLOBAL(real_readb)
mfmsr r7
ori r0,r7,MSR_DR
xori r0,r0,MSR_DR
rlwinm r0,r7,0,~MSR_DR
sync
mtmsr r0
sync
@ -262,8 +261,7 @@ _GLOBAL(real_readb)
*/
_GLOBAL(real_writeb)
mfmsr r7
ori r0,r7,MSR_DR
xori r0,r0,MSR_DR
rlwinm r0,r7,0,~MSR_DR
sync
mtmsr r0
sync

View File

@ -158,12 +158,13 @@ void arch_remove_optimized_kprobe(struct optimized_kprobe *op)
void patch_imm32_load_insns(unsigned int val, kprobe_opcode_t *addr)
{
/* addis r4,0,(insn)@h */
*addr++ = PPC_INST_ADDIS | ___PPC_RT(4) |
((val >> 16) & 0xffff);
patch_instruction(addr, PPC_INST_ADDIS | ___PPC_RT(4) |
((val >> 16) & 0xffff));
addr++;
/* ori r4,r4,(insn)@l */
*addr = PPC_INST_ORI | ___PPC_RA(4) | ___PPC_RS(4) |
(val & 0xffff);
patch_instruction(addr, PPC_INST_ORI | ___PPC_RA(4) |
___PPC_RS(4) | (val & 0xffff));
}
/*
@ -173,24 +174,28 @@ void patch_imm32_load_insns(unsigned int val, kprobe_opcode_t *addr)
void patch_imm64_load_insns(unsigned long val, kprobe_opcode_t *addr)
{
/* lis r3,(op)@highest */
*addr++ = PPC_INST_ADDIS | ___PPC_RT(3) |
((val >> 48) & 0xffff);
patch_instruction(addr, PPC_INST_ADDIS | ___PPC_RT(3) |
((val >> 48) & 0xffff));
addr++;
/* ori r3,r3,(op)@higher */
*addr++ = PPC_INST_ORI | ___PPC_RA(3) | ___PPC_RS(3) |
((val >> 32) & 0xffff);
patch_instruction(addr, PPC_INST_ORI | ___PPC_RA(3) |
___PPC_RS(3) | ((val >> 32) & 0xffff));
addr++;
/* rldicr r3,r3,32,31 */
*addr++ = PPC_INST_RLDICR | ___PPC_RA(3) | ___PPC_RS(3) |
__PPC_SH64(32) | __PPC_ME64(31);
patch_instruction(addr, PPC_INST_RLDICR | ___PPC_RA(3) |
___PPC_RS(3) | __PPC_SH64(32) | __PPC_ME64(31));
addr++;
/* oris r3,r3,(op)@h */
*addr++ = PPC_INST_ORIS | ___PPC_RA(3) | ___PPC_RS(3) |
((val >> 16) & 0xffff);
patch_instruction(addr, PPC_INST_ORIS | ___PPC_RA(3) |
___PPC_RS(3) | ((val >> 16) & 0xffff));
addr++;
/* ori r3,r3,(op)@l */
*addr = PPC_INST_ORI | ___PPC_RA(3) | ___PPC_RS(3) |
(val & 0xffff);
patch_instruction(addr, PPC_INST_ORI | ___PPC_RA(3) |
___PPC_RS(3) | (val & 0xffff));
}
int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe *p)
@ -198,7 +203,8 @@ int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe *p)
kprobe_opcode_t *buff, branch_op_callback, branch_emulate_step;
kprobe_opcode_t *op_callback_addr, *emulate_step_addr;
long b_offset;
unsigned long nip;
unsigned long nip, size;
int rc, i;
kprobe_ppc_optinsn_slots.insn_size = MAX_OPTINSN_SIZE;
@ -231,8 +237,14 @@ int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe *p)
goto error;
/* Setup template */
memcpy(buff, optprobe_template_entry,
TMPL_END_IDX * sizeof(kprobe_opcode_t));
/* We can optimize this via patch_instruction_window later */
size = (TMPL_END_IDX * sizeof(kprobe_opcode_t)) / sizeof(int);
pr_devel("Copying template to %p, size %lu\n", buff, size);
for (i = 0; i < size; i++) {
rc = patch_instruction(buff + i, *(optprobe_template_entry + i));
if (rc < 0)
goto error;
}
/*
* Fixup the template with instructions to:
@ -261,8 +273,8 @@ int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe *p)
if (!branch_op_callback || !branch_emulate_step)
goto error;
buff[TMPL_CALL_HDLR_IDX] = branch_op_callback;
buff[TMPL_EMULATE_IDX] = branch_emulate_step;
patch_instruction(buff + TMPL_CALL_HDLR_IDX, branch_op_callback);
patch_instruction(buff + TMPL_EMULATE_IDX, branch_emulate_step);
/*
* 3. load instruction to be emulated into relevant register, and
@ -272,8 +284,7 @@ int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe *p)
/*
* 4. branch back from trampoline
*/
buff[TMPL_RET_IDX] = create_branch((unsigned int *)buff + TMPL_RET_IDX,
(unsigned long)nip, 0);
patch_branch(buff + TMPL_RET_IDX, (unsigned long)nip, 0);
flush_icache_range((unsigned long)buff,
(unsigned long)(&buff[TMPL_END_IDX]));

View File

@ -511,6 +511,10 @@ void restore_math(struct pt_regs *regs)
{
unsigned long msr;
/*
* Syscall exit makes a similar initial check before branching
* to restore_math. Keep them in synch.
*/
if (!msr_tm_active(regs->msr) &&
!current->thread.load_fp && !loadvec(current->thread))
return;
@ -1133,6 +1137,11 @@ static inline void restore_sprs(struct thread_struct *old_thread,
#endif
}
#ifdef CONFIG_PPC_BOOK3S_64
#define CP_SIZE 128
static const u8 dummy_copy_buffer[CP_SIZE] __attribute__((aligned(CP_SIZE)));
#endif
struct task_struct *__switch_to(struct task_struct *prev,
struct task_struct *new)
{
@ -1195,12 +1204,14 @@ struct task_struct *__switch_to(struct task_struct *prev,
__switch_to_tm(prev, new);
/*
* We can't take a PMU exception inside _switch() since there is a
* window where the kernel stack SLB and the kernel stack are out
* of sync. Hard disable here.
*/
hard_irq_disable();
if (!radix_enabled()) {
/*
* We can't take a PMU exception inside _switch() since there
* is a window where the kernel stack SLB and the kernel stack
* are out of sync. Hard disable here.
*/
hard_irq_disable();
}
/*
* Call restore_sprs() before calling _switch(). If we move it after
@ -1220,8 +1231,28 @@ struct task_struct *__switch_to(struct task_struct *prev,
batch->active = 1;
}
if (current_thread_info()->task->thread.regs)
if (current_thread_info()->task->thread.regs) {
restore_math(current_thread_info()->task->thread.regs);
/*
* The copy-paste buffer can only store into foreign real
* addresses, so unprivileged processes can not see the
* data or use it in any way unless they have foreign real
* mappings. We don't have a VAS driver that allocates those
* yet, so no cpabort is required.
*/
if (cpu_has_feature(CPU_FTR_POWER9_DD1)) {
/*
* DD1 allows paste into normal system memory, so we
* do an unpaired copy here to clear the buffer and
* prevent a covert channel being set up.
*
* cpabort is not used because it is quite expensive.
*/
asm volatile(PPC_COPY(%0, %1)
: : "r"(dummy_copy_buffer), "r"(0));
}
}
#endif /* CONFIG_PPC_STD_MMU_64 */
return last;

View File

@ -335,6 +335,10 @@ static int show_cpuinfo(struct seq_file *m, void *v)
maj = ((pvr >> 8) & 0xFF) - 1;
min = pvr & 0xFF;
break;
case 0x004e: /* POWER9 bits 12-15 give chip type */
maj = (pvr >> 8) & 0x0F;
min = pvr & 0xFF;
break;
default:
maj = (pvr >> 8) & 0xFF;
min = pvr & 0xFF;

View File

@ -33,6 +33,7 @@
#include <linux/notifier.h>
#include <linux/topology.h>
#include <linux/profile.h>
#include <linux/processor.h>
#include <asm/ptrace.h>
#include <linux/atomic.h>
@ -112,7 +113,8 @@ int smp_generic_cpu_bootable(unsigned int nr)
#ifdef CONFIG_PPC64
int smp_generic_kick_cpu(int nr)
{
BUG_ON(nr < 0 || nr >= NR_CPUS);
if (nr < 0 || nr >= nr_cpu_ids)
return -EINVAL;
/*
* The processor is currently spinning, waiting for the
@ -766,8 +768,7 @@ int __cpu_up(unsigned int cpu, struct task_struct *tidle)
smp_ops->give_timebase();
/* Wait until cpu puts itself in the online & active maps */
while (!cpu_online(cpu))
cpu_relax();
spin_until_cond(cpu_online(cpu));
return 0;
}

View File

@ -59,10 +59,10 @@
#include <linux/suspend.h>
#include <linux/rtc.h>
#include <linux/sched/cputime.h>
#include <linux/processor.h>
#include <asm/trace.h>
#include <asm/io.h>
#include <asm/processor.h>
#include <asm/nvram.h>
#include <asm/cache.h>
#include <asm/machdep.h>
@ -442,6 +442,7 @@ void __delay(unsigned long loops)
unsigned long start;
int diff;
spin_begin();
if (__USE_RTC()) {
start = get_rtcl();
do {
@ -449,13 +450,14 @@ void __delay(unsigned long loops)
diff = get_rtcl() - start;
if (diff < 0)
diff += 1000000000;
spin_cpu_relax();
} while (diff < loops);
} else {
start = get_tbl();
while (get_tbl() - start < loops)
HMT_low();
HMT_medium();
spin_cpu_relax();
}
spin_end();
}
EXPORT_SYMBOL(__delay);
@ -675,7 +677,7 @@ EXPORT_SYMBOL_GPL(tb_to_ns);
* the high 64 bits of a * b, i.e. (a * b) >> 64, where a and b
* are 64-bit unsigned numbers.
*/
unsigned long long sched_clock(void)
notrace unsigned long long sched_clock(void)
{
if (__USE_RTC())
return get_rtc();
@ -739,12 +741,20 @@ static int __init get_freq(char *name, int cells, unsigned long *val)
static void start_cpu_decrementer(void)
{
#if defined(CONFIG_BOOKE) || defined(CONFIG_40x)
unsigned int tcr;
/* Clear any pending timer interrupts */
mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS);
/* Enable decrementer interrupt */
mtspr(SPRN_TCR, TCR_DIE);
#endif /* defined(CONFIG_BOOKE) || defined(CONFIG_40x) */
tcr = mfspr(SPRN_TCR);
/*
* The watchdog may have already been enabled by u-boot. So leave
* TRC[WP] (Watchdog Period) alone.
*/
tcr &= TCR_WP_MASK; /* Clear all bits except for TCR[WP] */
tcr |= TCR_DIE; /* Enable decrementer */
mtspr(SPRN_TCR, tcr);
#endif
}
void __init generic_calibrate_decr(void)
@ -823,38 +833,76 @@ void read_persistent_clock(struct timespec *ts)
}
/* clocksource code */
static u64 rtc_read(struct clocksource *cs)
static notrace u64 rtc_read(struct clocksource *cs)
{
return (u64)get_rtc();
}
static u64 timebase_read(struct clocksource *cs)
static notrace u64 timebase_read(struct clocksource *cs)
{
return (u64)get_tb();
}
void update_vsyscall_old(struct timespec *wall_time, struct timespec *wtm,
struct clocksource *clock, u32 mult, u64 cycle_last)
void update_vsyscall(struct timekeeper *tk)
{
struct timespec xt;
struct clocksource *clock = tk->tkr_mono.clock;
u32 mult = tk->tkr_mono.mult;
u32 shift = tk->tkr_mono.shift;
u64 cycle_last = tk->tkr_mono.cycle_last;
u64 new_tb_to_xs, new_stamp_xsec;
u32 frac_sec;
u64 frac_sec;
if (clock != &clocksource_timebase)
return;
xt.tv_sec = tk->xtime_sec;
xt.tv_nsec = (long)(tk->tkr_mono.xtime_nsec >> tk->tkr_mono.shift);
/* Make userspace gettimeofday spin until we're done. */
++vdso_data->tb_update_count;
smp_mb();
/* 19342813113834067 ~= 2^(20+64) / 1e9 */
new_tb_to_xs = (u64) mult * (19342813113834067ULL >> clock->shift);
new_stamp_xsec = (u64) wall_time->tv_nsec * XSEC_PER_SEC;
do_div(new_stamp_xsec, 1000000000);
new_stamp_xsec += (u64) wall_time->tv_sec * XSEC_PER_SEC;
/*
* This computes ((2^20 / 1e9) * mult) >> shift as a
* 0.64 fixed-point fraction.
* The computation in the else clause below won't overflow
* (as long as the timebase frequency is >= 1.049 MHz)
* but loses precision because we lose the low bits of the constant
* in the shift. Note that 19342813113834067 ~= 2^(20+64) / 1e9.
* For a shift of 24 the error is about 0.5e-9, or about 0.5ns
* over a second. (Shift values are usually 22, 23 or 24.)
* For high frequency clocks such as the 512MHz timebase clock
* on POWER[6789], the mult value is small (e.g. 32768000)
* and so we can shift the constant by 16 initially
* (295147905179 ~= 2^(20+64-16) / 1e9) and then do the
* remaining shifts after the multiplication, which gives a
* more accurate result (e.g. with mult = 32768000, shift = 24,
* the error is only about 1.2e-12, or 0.7ns over 10 minutes).
*/
if (mult <= 62500000 && clock->shift >= 16)
new_tb_to_xs = ((u64) mult * 295147905179ULL) >> (clock->shift - 16);
else
new_tb_to_xs = (u64) mult * (19342813113834067ULL >> clock->shift);
BUG_ON(wall_time->tv_nsec >= NSEC_PER_SEC);
/* this is tv_nsec / 1e9 as a 0.32 fraction */
frac_sec = ((u64) wall_time->tv_nsec * 18446744073ULL) >> 32;
/*
* Compute the fractional second in units of 2^-32 seconds.
* The fractional second is tk->tkr_mono.xtime_nsec >> tk->tkr_mono.shift
* in nanoseconds, so multiplying that by 2^32 / 1e9 gives
* it in units of 2^-32 seconds.
* We assume shift <= 32 because clocks_calc_mult_shift()
* generates shift values in the range 0 - 32.
*/
frac_sec = tk->tkr_mono.xtime_nsec << (32 - shift);
do_div(frac_sec, NSEC_PER_SEC);
/*
* Work out new stamp_xsec value for any legacy users of systemcfg.
* stamp_xsec is in units of 2^-20 seconds.
*/
new_stamp_xsec = frac_sec >> 12;
new_stamp_xsec += tk->xtime_sec * XSEC_PER_SEC;
/*
* tb_update_count is used to allow the userspace gettimeofday code
@ -864,15 +912,13 @@ void update_vsyscall_old(struct timespec *wall_time, struct timespec *wtm,
* the two values of tb_update_count match and are even then the
* tb_to_xs and stamp_xsec values are consistent. If not, then it
* loops back and reads them again until this criteria is met.
* We expect the caller to have done the first increment of
* vdso_data->tb_update_count already.
*/
vdso_data->tb_orig_stamp = cycle_last;
vdso_data->stamp_xsec = new_stamp_xsec;
vdso_data->tb_to_xs = new_tb_to_xs;
vdso_data->wtom_clock_sec = wtm->tv_sec;
vdso_data->wtom_clock_nsec = wtm->tv_nsec;
vdso_data->stamp_xtime = *wall_time;
vdso_data->wtom_clock_sec = tk->wall_to_monotonic.tv_sec;
vdso_data->wtom_clock_nsec = tk->wall_to_monotonic.tv_nsec;
vdso_data->stamp_xtime = xt;
vdso_data->stamp_sec_fraction = frac_sec;
smp_wmb();
++(vdso_data->tb_update_count);

View File

@ -313,8 +313,8 @@ dont_backup_fp:
blr
/* void tm_recheckpoint(struct thread_struct *thread,
* unsigned long orig_msr)
/* void __tm_recheckpoint(struct thread_struct *thread,
* unsigned long orig_msr)
* - Restore the checkpointed register state saved by tm_reclaim
* when we switch_to a process.
*

View File

@ -237,6 +237,7 @@ void die(const char *str, struct pt_regs *regs, long err)
err = 0;
oops_end(flags, regs, err);
}
NOKPROBE_SYMBOL(die);
void user_single_step_siginfo(struct task_struct *tsk,
struct pt_regs *regs, siginfo_t *info)
@ -1968,6 +1969,7 @@ void unrecoverable_exception(struct pt_regs *regs)
regs->trap, regs->nip);
die("Unrecoverable exception", regs, SIGABRT);
}
NOKPROBE_SYMBOL(unrecoverable_exception);
#if defined(CONFIG_BOOKE_WDT) || defined(CONFIG_40x)
/*
@ -1998,6 +2000,7 @@ void kernel_bad_stack(struct pt_regs *regs)
regs->gpr[1], regs->nip);
die("Bad kernel stack pointer", regs, SIGABRT);
}
NOKPROBE_SYMBOL(kernel_bad_stack);
void __init trap_init(void)
{

View File

@ -8,6 +8,12 @@
#include <asm/cache.h>
#include <asm/thread_info.h>
#ifdef CONFIG_STRICT_KERNEL_RWX
#define STRICT_ALIGN_SIZE (1 << 24)
#else
#define STRICT_ALIGN_SIZE PAGE_SIZE
#endif
ENTRY(_stext)
PHDRS {
@ -58,7 +64,6 @@ SECTIONS
#ifdef CONFIG_PPC64
KEEP(*(.head.text.first_256B));
#ifdef CONFIG_PPC_BOOK3E
# define END_FIXED 0x100
#else
KEEP(*(.head.text.real_vectors));
*(.head.text.real_trampolines);
@ -66,12 +71,8 @@ SECTIONS
*(.head.text.virt_trampolines);
# if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV)
KEEP(*(.head.data.fwnmi_page));
# define END_FIXED 0x8000
# else
# define END_FIXED 0x7000
# endif
#endif
ASSERT((. == END_FIXED), "vmlinux.lds.S: fixed section overflow error");
#else /* !CONFIG_PPC64 */
HEAD_TEXT
#endif
@ -79,23 +80,6 @@ SECTIONS
__head_end = .;
/*
* If the build dies here, it's likely code in head_64.S is referencing
* labels it can't reach, and the linker inserting stubs without the
* assembler's knowledge. To debug, remove the above assert and
* rebuild. Look for branch stubs in the fixed section region.
*
* Linker stub generation could be allowed in "trampoline"
* sections if absolutely necessary, but this would require
* some rework of the fixed sections. Before resorting to this,
* consider references that have sufficient addressing range,
* (e.g., hand coded trampolines) so the linker does not have
* to add stubs.
*
* Linker stubs at the top of the main text section are currently not
* detected, and will result in a crash at boot due to offsets being
* wrong.
*/
#ifdef CONFIG_PPC64
/*
* BLOCK(0) overrides the default output section alignment because
@ -103,18 +87,31 @@ SECTIONS
* section placement to work.
*/
.text BLOCK(0) : AT(ADDR(.text) - LOAD_OFFSET) {
#ifdef CONFIG_LD_HEAD_STUB_CATCH
*(.linker_stub_catch);
. = . ;
#endif
#else
.text : AT(ADDR(.text) - LOAD_OFFSET) {
ALIGN_FUNCTION();
#endif
/* careful! __ftr_alt_* sections need to be close to .text */
*(.text .fixup __ftr_alt_* .ref.text)
*(.text.hot .text .text.fixup .text.unlikely .fixup __ftr_alt_* .ref.text);
SCHED_TEXT
CPUIDLE_TEXT
LOCK_TEXT
KPROBES_TEXT
IRQENTRY_TEXT
SOFTIRQENTRY_TEXT
/*
* -Os builds call FP save/restore functions. The powerpc64
* linker generates those on demand in the .sfpr section.
* .sfpr gets placed at the beginning of a group of input
* sections, which can break start-of-text offset if it is
* included with the main text sections, so put it by itself.
*/
*(.sfpr);
MEM_KEEP(init.text)
MEM_KEEP(exit.text)
@ -132,7 +129,7 @@ SECTIONS
PROVIDE32 (etext = .);
/* Read-only data */
RODATA
RO_DATA(PAGE_SIZE)
EXCEPTION_TABLE(0)
@ -149,7 +146,7 @@ SECTIONS
/*
* Init sections discarded at runtime
*/
. = ALIGN(PAGE_SIZE);
. = ALIGN(STRICT_ALIGN_SIZE);
__init_begin = .;
INIT_TEXT_SECTION(PAGE_SIZE) :kernel
@ -267,7 +264,9 @@ SECTIONS
.data : AT(ADDR(.data) - LOAD_OFFSET) {
DATA_DATA
*(.sdata)
*(.sdata2)
*(.got.plt) *(.got)
*(.plt)
}
#else
.data : AT(ADDR(.data) - LOAD_OFFSET) {
@ -330,6 +329,16 @@ SECTIONS
_end = . ;
PROVIDE32 (end = .);
/* Sections to be discarded. */
STABS_DEBUG
DWARF_DEBUG
DISCARDS
/DISCARD/ : {
*(*.EMB.apuinfo)
*(.glink .iplt .plt .rela* .comment)
*(.gnu.version*)
*(.gnu.attributes)
*(.eh_frame)
}
}

View File

@ -15,6 +15,7 @@
#include <linux/log2.h>
#include <asm/tlbflush.h>
#include <asm/trace.h>
#include <asm/kvm_ppc.h>
#include <asm/kvm_book3s.h>
#include <asm/book3s/64/mmu-hash.h>
@ -443,17 +444,23 @@ static void do_tlbies(struct kvm *kvm, unsigned long *rbvalues,
cpu_relax();
if (need_sync)
asm volatile("ptesync" : : : "memory");
for (i = 0; i < npages; ++i)
for (i = 0; i < npages; ++i) {
asm volatile(PPC_TLBIE_5(%0,%1,0,0,0) : :
"r" (rbvalues[i]), "r" (kvm->arch.lpid));
trace_tlbie(kvm->arch.lpid, 0, rbvalues[i],
kvm->arch.lpid, 0, 0, 0);
}
asm volatile("eieio; tlbsync; ptesync" : : : "memory");
kvm->arch.tlbie_lock = 0;
} else {
if (need_sync)
asm volatile("ptesync" : : : "memory");
for (i = 0; i < npages; ++i)
for (i = 0; i < npages; ++i) {
asm volatile(PPC_TLBIEL(%0,%1,0,0,0) : :
"r" (rbvalues[i]), "r" (0));
trace_tlbie(kvm->arch.lpid, 1, rbvalues[i],
0, 0, 0, 0);
}
asm volatile("ptesync" : : : "memory");
}
}

View File

@ -313,15 +313,21 @@ kvm_novcpu_exit:
* We come in here when wakened from nap mode.
* Relocation is off and most register values are lost.
* r13 points to the PACA.
* r3 contains the SRR1 wakeup value, SRR1 is trashed.
*/
.globl kvm_start_guest
kvm_start_guest:
/* Set runlatch bit the minute you wake up from nap */
mfspr r0, SPRN_CTRLF
ori r0, r0, 1
mtspr SPRN_CTRLT, r0
/*
* Could avoid this and pass it through in r3. For now,
* code expects it to be in SRR1.
*/
mtspr SPRN_SRR1,r3
ld r2,PACATOC(r13)
li r0,KVM_HWTHREAD_IN_KVM
@ -440,13 +446,15 @@ kvm_no_guest:
/*
* We jump to pnv_wakeup_loss, which will return to the caller
* of power7_nap in the powernv cpu offline loop. The value we
* put in r3 becomes the return value for power7_nap.
* put in r3 becomes the return value for power7_nap. pnv_wakeup_loss
* requires SRR1 in r12.
*/
li r3, LPCR_PECE0
mfspr r4, SPRN_LPCR
rlwimi r4, r3, 0, LPCR_PECE0 | LPCR_PECE1
mtspr SPRN_LPCR, r4
li r3, 0
mfspr r12,SPRN_SRR1
b pnv_wakeup_loss
53: HMT_LOW

View File

@ -9,10 +9,17 @@ ccflags-$(CONFIG_PPC64) := $(NO_MINIMAL_TOC)
CFLAGS_REMOVE_code-patching.o = $(CC_FLAGS_FTRACE)
CFLAGS_REMOVE_feature-fixups.o = $(CC_FLAGS_FTRACE)
obj-y += string.o alloc.o crtsavres.o code-patching.o \
feature-fixups.o
obj-y += string.o alloc.o code-patching.o feature-fixups.o
obj-$(CONFIG_PPC32) += div64.o copy_32.o
obj-$(CONFIG_PPC32) += div64.o copy_32.o crtsavres.o
# See corresponding test in arch/powerpc/Makefile
# 64-bit linker creates .sfpr on demand for final link (vmlinux),
# so it is only needed for modules, and only for older linkers which
# do not support --save-restore-funcs
ifeq ($(call ld-ifversion, -lt, 225000000, y),y)
extra-$(CONFIG_PPC64) += crtsavres.o
endif
obj64-y += copypage_64.o copyuser_64.o mem_64.o hweight_64.o \
copyuser_power7.o string_64.o copypage_power7.o memcpy_power7.o \
@ -30,7 +37,7 @@ obj-$(CONFIG_PPC_LIB_RHEAP) += rheap.o
obj-$(CONFIG_FTR_FIXUP_SELFTEST) += feature-fixups-test.o
obj-$(CONFIG_ALTIVEC) += xor_vmx.o
obj-$(CONFIG_ALTIVEC) += xor_vmx.o xor_vmx_glue.o
CFLAGS_xor_vmx.o += -maltivec $(call cc-option,-mabi=altivec)
obj-$(CONFIG_PPC64) += $(obj64-y)

View File

@ -12,23 +12,186 @@
#include <linux/vmalloc.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <asm/page.h>
#include <asm/code-patching.h>
#include <linux/cpuhotplug.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/kprobes.h>
#include <asm/pgtable.h>
#include <asm/tlbflush.h>
#include <asm/page.h>
#include <asm/code-patching.h>
int patch_instruction(unsigned int *addr, unsigned int instr)
static int __patch_instruction(unsigned int *addr, unsigned int instr)
{
int err;
__put_user_size(instr, addr, 4, err);
if (err)
return err;
asm ("dcbst 0, %0; sync; icbi 0,%0; sync; isync" : : "r" (addr));
asm ("dcbst 0, %0; sync; icbi 0,%0; sync; isync" :: "r" (addr));
return 0;
}
#ifdef CONFIG_STRICT_KERNEL_RWX
static DEFINE_PER_CPU(struct vm_struct *, text_poke_area);
static int text_area_cpu_up(unsigned int cpu)
{
struct vm_struct *area;
area = get_vm_area(PAGE_SIZE, VM_ALLOC);
if (!area) {
WARN_ONCE(1, "Failed to create text area for cpu %d\n",
cpu);
return -1;
}
this_cpu_write(text_poke_area, area);
return 0;
}
static int text_area_cpu_down(unsigned int cpu)
{
free_vm_area(this_cpu_read(text_poke_area));
return 0;
}
/*
* Run as a late init call. This allows all the boot time patching to be done
* simply by patching the code, and then we're called here prior to
* mark_rodata_ro(), which happens after all init calls are run. Although
* BUG_ON() is rude, in this case it should only happen if ENOMEM, and we judge
* it as being preferable to a kernel that will crash later when someone tries
* to use patch_instruction().
*/
static int __init setup_text_poke_area(void)
{
BUG_ON(!cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,
"powerpc/text_poke:online", text_area_cpu_up,
text_area_cpu_down));
return 0;
}
late_initcall(setup_text_poke_area);
/*
* This can be called for kernel text or a module.
*/
static int map_patch_area(void *addr, unsigned long text_poke_addr)
{
unsigned long pfn;
int err;
if (is_vmalloc_addr(addr))
pfn = vmalloc_to_pfn(addr);
else
pfn = __pa_symbol(addr) >> PAGE_SHIFT;
err = map_kernel_page(text_poke_addr, (pfn << PAGE_SHIFT),
pgprot_val(PAGE_KERNEL));
pr_devel("Mapped addr %lx with pfn %lx:%d\n", text_poke_addr, pfn, err);
if (err)
return -1;
return 0;
}
static inline int unmap_patch_area(unsigned long addr)
{
pte_t *ptep;
pmd_t *pmdp;
pud_t *pudp;
pgd_t *pgdp;
pgdp = pgd_offset_k(addr);
if (unlikely(!pgdp))
return -EINVAL;
pudp = pud_offset(pgdp, addr);
if (unlikely(!pudp))
return -EINVAL;
pmdp = pmd_offset(pudp, addr);
if (unlikely(!pmdp))
return -EINVAL;
ptep = pte_offset_kernel(pmdp, addr);
if (unlikely(!ptep))
return -EINVAL;
pr_devel("clearing mm %p, pte %p, addr %lx\n", &init_mm, ptep, addr);
/*
* In hash, pte_clear flushes the tlb, in radix, we have to
*/
pte_clear(&init_mm, addr, ptep);
flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
return 0;
}
int patch_instruction(unsigned int *addr, unsigned int instr)
{
int err;
unsigned int *dest = NULL;
unsigned long flags;
unsigned long text_poke_addr;
unsigned long kaddr = (unsigned long)addr;
/*
* During early early boot patch_instruction is called
* when text_poke_area is not ready, but we still need
* to allow patching. We just do the plain old patching
* We use slab_is_available and per cpu read * via this_cpu_read
* of text_poke_area. Per-CPU areas might not be up early
* this can create problems with just using this_cpu_read()
*/
if (!slab_is_available() || !this_cpu_read(text_poke_area))
return __patch_instruction(addr, instr);
local_irq_save(flags);
text_poke_addr = (unsigned long)__this_cpu_read(text_poke_area)->addr;
if (map_patch_area(addr, text_poke_addr)) {
err = -1;
goto out;
}
dest = (unsigned int *)(text_poke_addr) +
((kaddr & ~PAGE_MASK) / sizeof(unsigned int));
/*
* We use __put_user_size so that we can handle faults while
* writing to dest and return err to handle faults gracefully
*/
__put_user_size(instr, dest, 4, err);
if (!err)
asm ("dcbst 0, %0; sync; icbi 0,%0; icbi 0,%1; sync; isync"
::"r" (dest), "r"(addr));
err = unmap_patch_area(text_poke_addr);
if (err)
pr_warn("failed to unmap %lx\n", text_poke_addr);
out:
local_irq_restore(flags);
return err;
}
#else /* !CONFIG_STRICT_KERNEL_RWX */
int patch_instruction(unsigned int *addr, unsigned int instr)
{
return __patch_instruction(addr, instr);
}
#endif /* CONFIG_STRICT_KERNEL_RWX */
NOKPROBE_SYMBOL(patch_instruction);
int patch_branch(unsigned int *addr, unsigned long target, int flags)
{
return patch_instruction(addr, create_branch(addr, target, flags));

View File

@ -82,14 +82,14 @@
_GLOBAL(__copy_tofrom_user_power7)
#ifdef CONFIG_ALTIVEC
cmpldi r5,16
cmpldi cr1,r5,4096
cmpldi cr1,r5,3328
std r3,-STACKFRAMESIZE+STK_REG(R31)(r1)
std r4,-STACKFRAMESIZE+STK_REG(R30)(r1)
std r5,-STACKFRAMESIZE+STK_REG(R29)(r1)
blt .Lshort_copy
bgt cr1,.Lvmx_copy
bge cr1,.Lvmx_copy
#else
cmpldi r5,16

View File

@ -44,10 +44,10 @@
#ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
#ifndef CONFIG_PPC64
.section ".text"
#ifndef CONFIG_PPC64
/* Routines for saving integer registers, called by the compiler. */
/* Called with r11 pointing to the stack header word of the caller of the */
/* function, just beyond the end of the integer save area. */
@ -314,8 +314,6 @@ _GLOBAL(_restvr_31)
#else /* CONFIG_PPC64 */
.section ".text.save.restore","ax",@progbits
.globl _savegpr0_14
_savegpr0_14:
std r14,-144(r1)

View File

@ -29,10 +29,7 @@
#define vector __attribute__((vector_size(16)))
#endif
#include <linux/preempt.h>
#include <linux/export.h>
#include <linux/sched.h>
#include <asm/switch_to.h>
#include "xor_vmx.h"
typedef vector signed char unative_t;
@ -64,16 +61,13 @@ typedef vector signed char unative_t;
V1##_3 = vec_xor(V1##_3, V2##_3); \
} while (0)
void xor_altivec_2(unsigned long bytes, unsigned long *v1_in,
unsigned long *v2_in)
void __xor_altivec_2(unsigned long bytes, unsigned long *v1_in,
unsigned long *v2_in)
{
DEFINE(v1);
DEFINE(v2);
unsigned long lines = bytes / (sizeof(unative_t)) / 4;
preempt_disable();
enable_kernel_altivec();
do {
LOAD(v1);
LOAD(v2);
@ -83,23 +77,16 @@ void xor_altivec_2(unsigned long bytes, unsigned long *v1_in,
v1 += 4;
v2 += 4;
} while (--lines > 0);
disable_kernel_altivec();
preempt_enable();
}
EXPORT_SYMBOL(xor_altivec_2);
void xor_altivec_3(unsigned long bytes, unsigned long *v1_in,
unsigned long *v2_in, unsigned long *v3_in)
void __xor_altivec_3(unsigned long bytes, unsigned long *v1_in,
unsigned long *v2_in, unsigned long *v3_in)
{
DEFINE(v1);
DEFINE(v2);
DEFINE(v3);
unsigned long lines = bytes / (sizeof(unative_t)) / 4;
preempt_disable();
enable_kernel_altivec();
do {
LOAD(v1);
LOAD(v2);
@ -112,15 +99,11 @@ void xor_altivec_3(unsigned long bytes, unsigned long *v1_in,
v2 += 4;
v3 += 4;
} while (--lines > 0);
disable_kernel_altivec();
preempt_enable();
}
EXPORT_SYMBOL(xor_altivec_3);
void xor_altivec_4(unsigned long bytes, unsigned long *v1_in,
unsigned long *v2_in, unsigned long *v3_in,
unsigned long *v4_in)
void __xor_altivec_4(unsigned long bytes, unsigned long *v1_in,
unsigned long *v2_in, unsigned long *v3_in,
unsigned long *v4_in)
{
DEFINE(v1);
DEFINE(v2);
@ -128,9 +111,6 @@ void xor_altivec_4(unsigned long bytes, unsigned long *v1_in,
DEFINE(v4);
unsigned long lines = bytes / (sizeof(unative_t)) / 4;
preempt_disable();
enable_kernel_altivec();
do {
LOAD(v1);
LOAD(v2);
@ -146,15 +126,11 @@ void xor_altivec_4(unsigned long bytes, unsigned long *v1_in,
v3 += 4;
v4 += 4;
} while (--lines > 0);
disable_kernel_altivec();
preempt_enable();
}
EXPORT_SYMBOL(xor_altivec_4);
void xor_altivec_5(unsigned long bytes, unsigned long *v1_in,
unsigned long *v2_in, unsigned long *v3_in,
unsigned long *v4_in, unsigned long *v5_in)
void __xor_altivec_5(unsigned long bytes, unsigned long *v1_in,
unsigned long *v2_in, unsigned long *v3_in,
unsigned long *v4_in, unsigned long *v5_in)
{
DEFINE(v1);
DEFINE(v2);
@ -163,9 +139,6 @@ void xor_altivec_5(unsigned long bytes, unsigned long *v1_in,
DEFINE(v5);
unsigned long lines = bytes / (sizeof(unative_t)) / 4;
preempt_disable();
enable_kernel_altivec();
do {
LOAD(v1);
LOAD(v2);
@ -184,8 +157,4 @@ void xor_altivec_5(unsigned long bytes, unsigned long *v1_in,
v4 += 4;
v5 += 4;
} while (--lines > 0);
disable_kernel_altivec();
preempt_enable();
}
EXPORT_SYMBOL(xor_altivec_5);

View File

@ -0,0 +1,20 @@
/*
* Simple interface to link xor_vmx.c and xor_vmx_glue.c
*
* Separating these file ensures that no altivec instructions are run
* outside of the enable/disable altivec block.
*/
void __xor_altivec_2(unsigned long bytes, unsigned long *v1_in,
unsigned long *v2_in);
void __xor_altivec_3(unsigned long bytes, unsigned long *v1_in,
unsigned long *v2_in, unsigned long *v3_in);
void __xor_altivec_4(unsigned long bytes, unsigned long *v1_in,
unsigned long *v2_in, unsigned long *v3_in,
unsigned long *v4_in);
void __xor_altivec_5(unsigned long bytes, unsigned long *v1_in,
unsigned long *v2_in, unsigned long *v3_in,
unsigned long *v4_in, unsigned long *v5_in);

View File

@ -0,0 +1,62 @@
/*
* Altivec XOR operations
*
* Copyright 2017 IBM Corp.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#include <linux/preempt.h>
#include <linux/export.h>
#include <linux/sched.h>
#include <asm/switch_to.h>
#include "xor_vmx.h"
void xor_altivec_2(unsigned long bytes, unsigned long *v1_in,
unsigned long *v2_in)
{
preempt_disable();
enable_kernel_altivec();
__xor_altivec_2(bytes, v1_in, v2_in);
disable_kernel_altivec();
preempt_enable();
}
EXPORT_SYMBOL(xor_altivec_2);
void xor_altivec_3(unsigned long bytes, unsigned long *v1_in,
unsigned long *v2_in, unsigned long *v3_in)
{
preempt_disable();
enable_kernel_altivec();
__xor_altivec_3(bytes, v1_in, v2_in, v3_in);
disable_kernel_altivec();
preempt_enable();
}
EXPORT_SYMBOL(xor_altivec_3);
void xor_altivec_4(unsigned long bytes, unsigned long *v1_in,
unsigned long *v2_in, unsigned long *v3_in,
unsigned long *v4_in)
{
preempt_disable();
enable_kernel_altivec();
__xor_altivec_4(bytes, v1_in, v2_in, v3_in, v4_in);
disable_kernel_altivec();
preempt_enable();
}
EXPORT_SYMBOL(xor_altivec_4);
void xor_altivec_5(unsigned long bytes, unsigned long *v1_in,
unsigned long *v2_in, unsigned long *v3_in,
unsigned long *v4_in, unsigned long *v5_in)
{
preempt_disable();
enable_kernel_altivec();
__xor_altivec_5(bytes, v1_in, v2_in, v3_in, v4_in, v5_in);
disable_kernel_altivec();
preempt_enable();
}
EXPORT_SYMBOL(xor_altivec_5);

View File

@ -88,7 +88,7 @@ static void mmu_mapin_immr(void)
int offset;
for (offset = 0; offset < IMMR_SIZE; offset += PAGE_SIZE)
map_page(v + offset, p + offset, f);
map_kernel_page(v + offset, p + offset, f);
}
/* Address of instructions to patch */

View File

@ -227,7 +227,7 @@ __dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t
do {
SetPageReserved(page);
map_page(vaddr, page_to_phys(page),
map_kernel_page(vaddr, page_to_phys(page),
pgprot_val(pgprot_noncached(PAGE_KERNEL)));
page++;
vaddr += PAGE_SIZE;

View File

@ -335,7 +335,7 @@ static unsigned long hpte_find(struct pg_state *st, unsigned long ea, int psize)
unsigned long rpn, lp_bits;
int base_psize = 0, actual_psize = 0;
if (ea <= PAGE_OFFSET)
if (ea < PAGE_OFFSET)
return -1;
/* Look in primary table */

Some files were not shown because too many files have changed in this diff Show More