mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-01 18:53:30 +00:00
powerpc updates for 5.16
- Enable STRICT_KERNEL_RWX for Freescale 85xx platforms. - Activate CONFIG_STRICT_KERNEL_RWX by default, while still allowing it to be disabled. - Add support for out-of-line static calls on 32-bit. - Fix oopses doing bpf-to-bpf calls when STRICT_KERNEL_RWX is enabled. - Fix boot hangs on e5500 due to stale value in ESR passed to do_page_fault(). - Fix several bugs on pseries in handling of device tree cache information for hotplugged CPUs, and/or during partition migration. - Various other small features and fixes. Thanks to: Alexey Kardashevskiy, Alistair Popple, Anatolij Gustschin, Andrew Donnellan, Athira Rajeev, Bixuan Cui, Bjorn Helgaas, Cédric Le Goater, Christophe Leroy, Daniel Axtens, Daniel Henrique Barboza, Denis Kirjanov, Fabiano Rosas, Frederic Barrat, Gustavo A. R. Silva, Hari Bathini, Jacques de Laval, Joel Stanley, Kai Song, Kajol Jain, Laurent Vivier, Leonardo Bras, Madhavan Srinivasan, Nathan Chancellor, Nathan Lynch, Naveen N. Rao, Nicholas Piggin, Nick Desaulniers, Niklas Schnelle, Oliver O'Halloran, Rob Herring, Russell Currey, Srikar Dronamraju, Stan Johnson, Tyrel Datwyler, Uwe Kleine-König, Vasant Hegde, Wan Jiabing, Xiaoming Ni, -----BEGIN PGP SIGNATURE----- iQJHBAABCAAxFiEEJFGtCPCthwEv2Y/bUevqPMjhpYAFAmGFDPoTHG1wZUBlbGxl cm1hbi5pZC5hdQAKCRBR6+o8yOGlgNbsEACVczMVwMBEny5a7W1tqq1bnY9RFVw3 K+/rE7/FpSLX+RrwgoMkmqfPvfyc9WISVLlIQDKz4XhkBjaXv0+Y4OMsymuDCbxL Qk7F1ff22UfLmPjjJk39gHJ8QZQqZk3wmFu2QzTO4yBZbz2SqqXFLxwyoLpZ0LJ8 pdGl51+bIsTkDJzrdkhX9X4AKS/fYyjbQxq5u7FS89ZCCs+KvzjLcDRo0GZYaOK/ hgDBa60DCCszL/9yjbh0ANZxmM2Z3+6AXkvAAXrtXzIGk4JzenZfiV+VEzmq8Tt0 UpWSsUEe7VgykMR3MTrL9G8op70PpKX6OMUPegJq4iRQ24h4mpFCK4oV9OMKJqpF ifN9NO2ZZKOz1ke4l7Xe8SEHLX7rq5U/P7INh3AsKYNYwo6HkJhSPxiCBWUTlnZ3 OYoZ7czyO4gMPHWP92z4CoSiTYVBFuyhYexRcnQskg60TIwbr+lMXziRyPRGI8b6 taf2rD8eAiyUJnvkFUsyAHtYHpkSkuMeiVqY2CDQdh2SdtIFgwKzB2RjFL0gzaBZ XP9RWD+HernGQAJSlIk7cVthont3JHklcKk+ohhDbsWzPeUJcz6t4ChtgRq0x4q4 Hpes1lsVfXpyxj5ouBK/E/t+diwPvBLM0dCcarQJE6ExgMzBC/C7Br7jCSgyVJA2 VhtcZaCYh+vRlQ== =f7HE -----END PGP SIGNATURE----- Merge tag 'powerpc-5.16-1' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux Pull powerpc updates from Michael Ellerman: - Enable STRICT_KERNEL_RWX for Freescale 85xx platforms. - Activate CONFIG_STRICT_KERNEL_RWX by default, while still allowing it to be disabled. - Add support for out-of-line static calls on 32-bit. - Fix oopses doing bpf-to-bpf calls when STRICT_KERNEL_RWX is enabled. - Fix boot hangs on e5500 due to stale value in ESR passed to do_page_fault(). - Fix several bugs on pseries in handling of device tree cache information for hotplugged CPUs, and/or during partition migration. - Various other small features and fixes. Thanks to Alexey Kardashevskiy, Alistair Popple, Anatolij Gustschin, Andrew Donnellan, Athira Rajeev, Bixuan Cui, Bjorn Helgaas, Cédric Le Goater, Christophe Leroy, Daniel Axtens, Daniel Henrique Barboza, Denis Kirjanov, Fabiano Rosas, Frederic Barrat, Gustavo A. R. Silva, Hari Bathini, Jacques de Laval, Joel Stanley, Kai Song, Kajol Jain, Laurent Vivier, Leonardo Bras, Madhavan Srinivasan, Nathan Chancellor, Nathan Lynch, Naveen N. Rao, Nicholas Piggin, Nick Desaulniers, Niklas Schnelle, Oliver O'Halloran, Rob Herring, Russell Currey, Srikar Dronamraju, Stan Johnson, Tyrel Datwyler, Uwe Kleine-König, Vasant Hegde, Wan Jiabing, and Xiaoming Ni, * tag 'powerpc-5.16-1' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux: (73 commits) powerpc/8xx: Fix Oops with STRICT_KERNEL_RWX without DEBUG_RODATA_TEST powerpc/32e: Ignore ESR in instruction storage interrupt handler powerpc/powernv/prd: Unregister OPAL_MSG_PRD2 notifier during module unload powerpc: Don't provide __kernel_map_pages() without ARCH_SUPPORTS_DEBUG_PAGEALLOC MAINTAINERS: Update powerpc KVM entry powerpc/xmon: fix task state output powerpc/44x/fsp2: add missing of_node_put powerpc/dcr: Use cmplwi instead of 3-argument cmpli KVM: PPC: Tick accounting should defer vtime accounting 'til after IRQ handling powerpc/security: Use a mutex for interrupt exit code patching powerpc/83xx/mpc8349emitx: Make mcu_gpiochip_remove() return void powerpc/fsl_booke: Fix setting of exec flag when setting TLBCAMs powerpc/book3e: Fix set_memory_x() and set_memory_nx() powerpc/nohash: Fix __ptep_set_access_flags() and ptep_set_wrprotect() powerpc/bpf: Fix write protecting JIT code selftests/powerpc: Use date instead of EPOCHSECONDS in mitigation-patching.sh powerpc/64s/interrupt: Fix check_return_regs_valid() false positive powerpc/boot: Set LC_ALL=C in wrapper script powerpc/64s: Default to 64K pages for 64 bit book3s Revert "powerpc/audit: Convert powerpc to AUDIT_ARCH_COMPAT_GENERIC" ...
This commit is contained in:
commit
5c0b0c676a
@ -10388,11 +10388,8 @@ F: arch/mips/include/uapi/asm/kvm*
|
||||
F: arch/mips/kvm/
|
||||
|
||||
KERNEL VIRTUAL MACHINE FOR POWERPC (KVM/powerpc)
|
||||
M: Paul Mackerras <paulus@ozlabs.org>
|
||||
L: kvm-ppc@vger.kernel.org
|
||||
S: Supported
|
||||
W: http://www.linux-kvm.org/
|
||||
T: git git://github.com/agraf/linux-2.6.git
|
||||
L: linuxppc-dev@lists.ozlabs.org
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git topic/ppc-kvm
|
||||
F: arch/powerpc/include/asm/kvm*
|
||||
F: arch/powerpc/include/uapi/asm/kvm*
|
||||
F: arch/powerpc/kernel/kvm*
|
||||
|
@ -138,7 +138,8 @@ config PPC
|
||||
select ARCH_HAS_PTE_SPECIAL
|
||||
select ARCH_HAS_SCALED_CPUTIME if VIRT_CPU_ACCOUNTING_NATIVE && PPC_BOOK3S_64
|
||||
select ARCH_HAS_SET_MEMORY
|
||||
select ARCH_HAS_STRICT_KERNEL_RWX if ((PPC_BOOK3S_64 || PPC32) && !HIBERNATION)
|
||||
select ARCH_HAS_STRICT_KERNEL_RWX if (PPC_BOOK3S || PPC_8xx || 40x) && !HIBERNATION
|
||||
select ARCH_HAS_STRICT_KERNEL_RWX if FSL_BOOKE && !HIBERNATION && !RANDOMIZE_BASE
|
||||
select ARCH_HAS_STRICT_MODULE_RWX if ARCH_HAS_STRICT_KERNEL_RWX && !PPC_BOOK3S_32
|
||||
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
|
||||
select ARCH_HAS_UACCESS_FLUSHCACHE
|
||||
@ -148,9 +149,10 @@ config PPC
|
||||
select ARCH_MIGHT_HAVE_PC_PARPORT
|
||||
select ARCH_MIGHT_HAVE_PC_SERIO
|
||||
select ARCH_OPTIONAL_KERNEL_RWX if ARCH_HAS_STRICT_KERNEL_RWX
|
||||
select ARCH_OPTIONAL_KERNEL_RWX_DEFAULT
|
||||
select ARCH_STACKWALK
|
||||
select ARCH_SUPPORTS_ATOMIC_RMW
|
||||
select ARCH_SUPPORTS_DEBUG_PAGEALLOC if PPC32 || PPC_BOOK3S_64
|
||||
select ARCH_SUPPORTS_DEBUG_PAGEALLOC if PPC_BOOK3S || PPC_8xx || 40x
|
||||
select ARCH_USE_BUILTIN_BSWAP
|
||||
select ARCH_USE_CMPXCHG_LOCKREF if PPC64
|
||||
select ARCH_USE_MEMTEST
|
||||
@ -190,7 +192,7 @@ config PPC
|
||||
select HAVE_ARCH_JUMP_LABEL_RELATIVE
|
||||
select HAVE_ARCH_KASAN if PPC32 && PPC_PAGE_SHIFT <= 14
|
||||
select HAVE_ARCH_KASAN_VMALLOC if PPC32 && PPC_PAGE_SHIFT <= 14
|
||||
select HAVE_ARCH_KFENCE if PPC32
|
||||
select HAVE_ARCH_KFENCE if PPC_BOOK3S_32 || PPC_8xx || 40x
|
||||
select HAVE_ARCH_KGDB
|
||||
select HAVE_ARCH_MMAP_RND_BITS
|
||||
select HAVE_ARCH_MMAP_RND_COMPAT_BITS if COMPAT
|
||||
@ -241,6 +243,7 @@ config PPC
|
||||
select HAVE_SOFTIRQ_ON_OWN_STACK
|
||||
select HAVE_STACKPROTECTOR if PPC32 && $(cc-option,-mstack-protector-guard=tls -mstack-protector-guard-reg=r2)
|
||||
select HAVE_STACKPROTECTOR if PPC64 && $(cc-option,-mstack-protector-guard=tls -mstack-protector-guard-reg=r13)
|
||||
select HAVE_STATIC_CALL if PPC32
|
||||
select HAVE_SYSCALL_TRACEPOINTS
|
||||
select HAVE_VIRT_CPU_ACCOUNTING
|
||||
select HUGETLB_PAGE_SIZE_VARIABLE if PPC_BOOK3S_64 && HUGETLB_PAGE
|
||||
@ -707,6 +710,7 @@ config ARCH_MEMORY_PROBE
|
||||
|
||||
choice
|
||||
prompt "Page size"
|
||||
default PPC_64K_PAGES if PPC_BOOK3S_64
|
||||
default PPC_4K_PAGES
|
||||
help
|
||||
Select the kernel logical page size. Increasing the page size
|
||||
@ -778,7 +782,8 @@ config DATA_SHIFT_BOOL
|
||||
bool "Set custom data alignment"
|
||||
depends on ADVANCED_OPTIONS
|
||||
depends on STRICT_KERNEL_RWX || DEBUG_PAGEALLOC || KFENCE
|
||||
depends on PPC_BOOK3S_32 || (PPC_8xx && !PIN_TLB_DATA && !STRICT_KERNEL_RWX)
|
||||
depends on PPC_BOOK3S_32 || (PPC_8xx && !PIN_TLB_DATA && !STRICT_KERNEL_RWX) || \
|
||||
FSL_BOOKE
|
||||
help
|
||||
This option allows you to set the kernel data alignment. When
|
||||
RAM is mapped by blocks, the alignment needs to fit the size and
|
||||
@ -791,11 +796,13 @@ config DATA_SHIFT
|
||||
default 24 if STRICT_KERNEL_RWX && PPC64
|
||||
range 17 28 if (STRICT_KERNEL_RWX || DEBUG_PAGEALLOC || KFENCE) && PPC_BOOK3S_32
|
||||
range 19 23 if (STRICT_KERNEL_RWX || DEBUG_PAGEALLOC || KFENCE) && PPC_8xx
|
||||
range 20 24 if (STRICT_KERNEL_RWX || DEBUG_PAGEALLOC || KFENCE) && PPC_FSL_BOOKE
|
||||
default 22 if STRICT_KERNEL_RWX && PPC_BOOK3S_32
|
||||
default 18 if (DEBUG_PAGEALLOC || KFENCE) && PPC_BOOK3S_32
|
||||
default 23 if STRICT_KERNEL_RWX && PPC_8xx
|
||||
default 23 if (DEBUG_PAGEALLOC || KFENCE) && PPC_8xx && PIN_TLB_DATA
|
||||
default 19 if (DEBUG_PAGEALLOC || KFENCE) && PPC_8xx
|
||||
default 24 if STRICT_KERNEL_RWX && FSL_BOOKE
|
||||
default PPC_PAGE_SHIFT
|
||||
help
|
||||
On Book3S 32 (603+), DBATs are used to map kernel text and rodata RO.
|
||||
@ -1123,7 +1130,10 @@ config LOWMEM_CAM_NUM_BOOL
|
||||
config LOWMEM_CAM_NUM
|
||||
depends on FSL_BOOKE
|
||||
int "Number of CAMs to use to map low memory" if LOWMEM_CAM_NUM_BOOL
|
||||
default 3
|
||||
default 3 if !STRICT_KERNEL_RWX
|
||||
default 9 if DATA_SHIFT >= 24
|
||||
default 12 if DATA_SHIFT >= 22
|
||||
default 15
|
||||
|
||||
config DYNAMIC_MEMSTART
|
||||
bool "Enable page aligned dynamic load address for kernel"
|
||||
|
@ -123,7 +123,7 @@ src-wlib-y := string.S crt0.S stdio.c decompress.c main.c \
|
||||
oflib.c ofconsole.c cuboot.c
|
||||
|
||||
src-wlib-$(CONFIG_PPC_MPC52xx) += mpc52xx-psc.c
|
||||
src-wlib-$(CONFIG_PPC64_BOOT_WRAPPER) += opal-calls.S opal.c
|
||||
src-wlib-$(CONFIG_PPC_POWERNV) += opal-calls.S opal.c
|
||||
ifndef CONFIG_PPC64_BOOT_WRAPPER
|
||||
src-wlib-y += crtsavres.S
|
||||
endif
|
||||
|
@ -140,8 +140,8 @@ pci@f0000d00 {
|
||||
clock-frequency = <0>; /* From boot loader */
|
||||
interrupts = <2 8 0 2 9 0 2 10 0>;
|
||||
bus-range = <0 0>;
|
||||
ranges = <0x42000000 0 0x80000000 0x80000000 0 0x10000000
|
||||
0x02000000 0 0x90000000 0x90000000 0 0x10000000
|
||||
0x01000000 0 0x00000000 0xa0000000 0 0x01000000>;
|
||||
ranges = <0x42000000 0 0x80000000 0x80000000 0 0x10000000>,
|
||||
<0x02000000 0 0x90000000 0x90000000 0 0x10000000>,
|
||||
<0x01000000 0 0x00000000 0xa0000000 0 0x01000000>;
|
||||
};
|
||||
};
|
||||
|
@ -35,7 +35,7 @@ PowerPC,5200@0 {
|
||||
};
|
||||
};
|
||||
|
||||
memory {
|
||||
memory@0 {
|
||||
device_type = "memory";
|
||||
reg = <0x00000000 0x08000000>; // 128MB
|
||||
};
|
||||
@ -225,8 +225,8 @@ pci@f0000d00 {
|
||||
clock-frequency = <0>; // From boot loader
|
||||
interrupts = <2 8 0 2 9 0 2 10 0>;
|
||||
bus-range = <0 0>;
|
||||
ranges = <0x42000000 0 0x80000000 0x80000000 0 0x10000000
|
||||
0x02000000 0 0x90000000 0x90000000 0 0x10000000
|
||||
0x01000000 0 0x00000000 0xa0000000 0 0x01000000>;
|
||||
ranges = <0x42000000 0 0x80000000 0x80000000 0 0x10000000>,
|
||||
<0x02000000 0 0x90000000 0x90000000 0 0x10000000>,
|
||||
<0x01000000 0 0x00000000 0xa0000000 0 0x01000000>;
|
||||
};
|
||||
};
|
||||
|
@ -16,7 +16,7 @@ / {
|
||||
model = "intercontrol,digsy-mtc";
|
||||
compatible = "intercontrol,digsy-mtc";
|
||||
|
||||
memory {
|
||||
memory@0 {
|
||||
reg = <0x00000000 0x02000000>; // 32MB
|
||||
};
|
||||
|
||||
@ -98,9 +98,9 @@ pci@f0000d00 {
|
||||
clock-frequency = <0>; // From boot loader
|
||||
interrupts = <2 8 0 2 9 0 2 10 0>;
|
||||
bus-range = <0 0>;
|
||||
ranges = <0x42000000 0 0x80000000 0x80000000 0 0x10000000
|
||||
0x02000000 0 0x90000000 0x90000000 0 0x10000000
|
||||
0x01000000 0 0x00000000 0xa0000000 0 0x01000000>;
|
||||
ranges = <0x42000000 0 0x80000000 0x80000000 0 0x10000000>,
|
||||
<0x02000000 0 0x90000000 0x90000000 0 0x10000000>,
|
||||
<0x01000000 0 0x00000000 0xa0000000 0 0x01000000>;
|
||||
};
|
||||
|
||||
localbus {
|
||||
|
@ -32,7 +32,7 @@ PowerPC,5200@0 {
|
||||
};
|
||||
};
|
||||
|
||||
memory {
|
||||
memory@0 {
|
||||
device_type = "memory";
|
||||
reg = <0x00000000 0x04000000>; // 64MB
|
||||
};
|
||||
@ -283,9 +283,9 @@ pci@f0000d00 {
|
||||
clock-frequency = <0>; // From boot loader
|
||||
interrupts = <2 8 0 2 9 0 2 10 0>;
|
||||
bus-range = <0 0>;
|
||||
ranges = <0x42000000 0 0x80000000 0x80000000 0 0x20000000
|
||||
0x02000000 0 0xa0000000 0xa0000000 0 0x10000000
|
||||
0x01000000 0 0x00000000 0xb0000000 0 0x01000000>;
|
||||
ranges = <0x42000000 0 0x80000000 0x80000000 0 0x20000000>,
|
||||
<0x02000000 0 0xa0000000 0xa0000000 0 0x10000000>,
|
||||
<0x01000000 0 0x00000000 0xb0000000 0 0x01000000>;
|
||||
};
|
||||
|
||||
localbus {
|
||||
|
@ -31,7 +31,7 @@ tmr3 {
|
||||
led4 { gpios = <&gpio_simple 2 1>; };
|
||||
};
|
||||
|
||||
memory {
|
||||
memory@0 {
|
||||
reg = <0x00000000 0x10000000>; // 256MB
|
||||
};
|
||||
|
||||
@ -116,9 +116,9 @@ pci@f0000d00 {
|
||||
clock-frequency = <0>; // From boot loader
|
||||
interrupts = <2 8 0 2 9 0 2 10 0>;
|
||||
bus-range = <0 0>;
|
||||
ranges = <0x42000000 0 0x80000000 0x80000000 0 0x20000000
|
||||
0x02000000 0 0xa0000000 0xa0000000 0 0x10000000
|
||||
0x01000000 0 0x00000000 0xb0000000 0 0x01000000>;
|
||||
ranges = <0x42000000 0 0x80000000 0x80000000 0 0x20000000>,
|
||||
<0x02000000 0 0xa0000000 0xa0000000 0 0x10000000>,
|
||||
<0x01000000 0 0x00000000 0xb0000000 0 0x01000000>;
|
||||
};
|
||||
|
||||
localbus {
|
||||
|
@ -32,7 +32,7 @@ PowerPC,5200@0 {
|
||||
};
|
||||
};
|
||||
|
||||
memory {
|
||||
memory@0 {
|
||||
reg = <0x00000000 0x08000000>; // 128MB RAM
|
||||
};
|
||||
|
||||
@ -96,9 +96,9 @@ pci@f0000d00 {
|
||||
|
||||
0xe000 0 0 1 &media5200_fpga 0 5 // CoralIP
|
||||
>;
|
||||
ranges = <0x42000000 0 0x80000000 0x80000000 0 0x20000000
|
||||
0x02000000 0 0xa0000000 0xa0000000 0 0x10000000
|
||||
0x01000000 0 0x00000000 0xb0000000 0 0x01000000>;
|
||||
ranges = <0x42000000 0 0x80000000 0x80000000 0 0x20000000>,
|
||||
<0x02000000 0 0xa0000000 0xa0000000 0 0x10000000>,
|
||||
<0x01000000 0 0x00000000 0xb0000000 0 0x01000000>;
|
||||
interrupt-parent = <&mpc5200_pic>;
|
||||
};
|
||||
|
||||
|
@ -33,7 +33,7 @@ powerpc: PowerPC,5200@0 {
|
||||
};
|
||||
};
|
||||
|
||||
memory: memory {
|
||||
memory: memory@0 {
|
||||
device_type = "memory";
|
||||
reg = <0x00000000 0x04000000>; // 64MB
|
||||
};
|
||||
@ -276,7 +276,9 @@ pci: pci@f0000d00 {
|
||||
clock-frequency = <0>; // From boot loader
|
||||
interrupts = <2 8 0 2 9 0 2 10 0>;
|
||||
bus-range = <0 0>;
|
||||
// ranges = need to add
|
||||
ranges = <0x42000000 0 0x80000000 0x80000000 0 0x10000000>,
|
||||
<0x02000000 0 0x90000000 0x90000000 0 0x10000000>,
|
||||
<0x01000000 0 0x00000000 0xa0000000 0 0x01000000>;
|
||||
};
|
||||
|
||||
localbus: localbus {
|
||||
|
@ -106,9 +106,9 @@ pci@f0000d00 {
|
||||
0x8000 0 0 3 &mpc5200_pic 0 2 3
|
||||
0x8000 0 0 4 &mpc5200_pic 0 1 3
|
||||
>;
|
||||
ranges = <0x42000000 0 0x60000000 0x60000000 0 0x10000000
|
||||
0x02000000 0 0x90000000 0x90000000 0 0x10000000
|
||||
0x01000000 0 0x00000000 0xa0000000 0 0x01000000>;
|
||||
ranges = <0x42000000 0 0x60000000 0x60000000 0 0x10000000>,
|
||||
<0x02000000 0 0x90000000 0x90000000 0 0x10000000>,
|
||||
<0x01000000 0 0x00000000 0xa0000000 0 0x01000000>;
|
||||
};
|
||||
|
||||
localbus {
|
||||
|
@ -12,7 +12,7 @@ / {
|
||||
model = "ifm,o2d";
|
||||
compatible = "ifm,o2d";
|
||||
|
||||
memory {
|
||||
memory@0 {
|
||||
reg = <0x00000000 0x08000000>; // 128MB
|
||||
};
|
||||
|
||||
|
@ -19,7 +19,7 @@ / {
|
||||
model = "ifm,o2d";
|
||||
compatible = "ifm,o2d";
|
||||
|
||||
memory {
|
||||
memory@0 {
|
||||
reg = <0x00000000 0x04000000>; // 64MB
|
||||
};
|
||||
|
||||
|
@ -12,7 +12,7 @@ / {
|
||||
model = "ifm,o2dnt2";
|
||||
compatible = "ifm,o2d";
|
||||
|
||||
memory {
|
||||
memory@0 {
|
||||
reg = <0x00000000 0x08000000>; // 128MB
|
||||
};
|
||||
|
||||
|
@ -12,7 +12,7 @@ / {
|
||||
model = "ifm,o3dnt";
|
||||
compatible = "ifm,o2d";
|
||||
|
||||
memory {
|
||||
memory@0 {
|
||||
reg = <0x00000000 0x04000000>; // 64MB
|
||||
};
|
||||
|
||||
|
@ -90,9 +90,9 @@ pci@f0000d00 {
|
||||
0xc800 0 0 2 &mpc5200_pic 1 2 3
|
||||
0xc800 0 0 3 &mpc5200_pic 1 3 3
|
||||
0xc800 0 0 4 &mpc5200_pic 0 0 3>;
|
||||
ranges = <0x42000000 0 0x80000000 0x80000000 0 0x20000000
|
||||
0x02000000 0 0xa0000000 0xa0000000 0 0x10000000
|
||||
0x01000000 0 0x00000000 0xb0000000 0 0x01000000>;
|
||||
ranges = <0x42000000 0 0x80000000 0x80000000 0 0x20000000>,
|
||||
<0x02000000 0 0xa0000000 0xa0000000 0 0x10000000>,
|
||||
<0x01000000 0 0x00000000 0xb0000000 0 0x01000000>;
|
||||
};
|
||||
|
||||
localbus {
|
||||
|
@ -20,7 +20,7 @@ / {
|
||||
model = "phytec,pcm032";
|
||||
compatible = "phytec,pcm032";
|
||||
|
||||
memory {
|
||||
memory@0 {
|
||||
reg = <0x00000000 0x08000000>; // 128MB
|
||||
};
|
||||
|
||||
@ -87,9 +87,9 @@ pci@f0000d00 {
|
||||
0xc800 0 0 2 &mpc5200_pic 1 2 3
|
||||
0xc800 0 0 3 &mpc5200_pic 1 3 3
|
||||
0xc800 0 0 4 &mpc5200_pic 0 0 3>;
|
||||
ranges = <0x42000000 0 0x80000000 0x80000000 0 0x20000000
|
||||
0x02000000 0 0xa0000000 0xa0000000 0 0x10000000
|
||||
0x01000000 0 0x00000000 0xb0000000 0 0x01000000>;
|
||||
ranges = <0x42000000 0 0x80000000 0x80000000 0 0x20000000>,
|
||||
<0x02000000 0 0xa0000000 0xa0000000 0 0x10000000>,
|
||||
<0x01000000 0 0x00000000 0xb0000000 0 0x01000000>;
|
||||
};
|
||||
|
||||
localbus {
|
||||
|
@ -32,7 +32,7 @@ PowerPC,5200@0 {
|
||||
};
|
||||
};
|
||||
|
||||
memory {
|
||||
memory@0 {
|
||||
device_type = "memory";
|
||||
reg = <0x00000000 0x04000000>; // 64MB
|
||||
};
|
||||
@ -200,8 +200,8 @@ pci@f0000d00 {
|
||||
clock-frequency = <0>; // From boot loader
|
||||
interrupts = <2 8 0 2 9 0 2 10 0>;
|
||||
bus-range = <0 0>;
|
||||
ranges = <0x42000000 0 0x80000000 0x80000000 0 0x10000000
|
||||
0x02000000 0 0x90000000 0x90000000 0 0x10000000
|
||||
0x01000000 0 0x00000000 0xa0000000 0 0x01000000>;
|
||||
ranges = <0x42000000 0 0x80000000 0x80000000 0 0x10000000>,
|
||||
<0x02000000 0 0x90000000 0x90000000 0 0x10000000>,
|
||||
<0x01000000 0 0x00000000 0xa0000000 0 0x01000000>;
|
||||
};
|
||||
};
|
||||
|
@ -132,7 +132,7 @@ int serial_console_init(void)
|
||||
else if (dt_is_compatible(devp, "fsl,mpc5200-psc-uart"))
|
||||
rc = mpc5200_psc_console_init(devp, &serial_cd);
|
||||
#endif
|
||||
#ifdef CONFIG_PPC64_BOOT_WRAPPER
|
||||
#ifdef CONFIG_PPC_POWERNV
|
||||
else if (dt_is_compatible(devp, "ibm,opal-console-raw"))
|
||||
rc = opal_console_init(devp, &serial_cd);
|
||||
#endif
|
||||
|
@ -26,6 +26,8 @@
|
||||
# Stop execution if any command fails
|
||||
set -e
|
||||
|
||||
export LC_ALL=C
|
||||
|
||||
# Allow for verbose output
|
||||
if [ "$V" = 1 ]; then
|
||||
set -x
|
||||
|
@ -36,7 +36,6 @@ CONFIG_GEN_RTC=y
|
||||
CONFIG_BINFMT_MISC=m
|
||||
CONFIG_IRQ_ALL_CPUS=y
|
||||
CONFIG_NUMA=y
|
||||
CONFIG_PPC_64K_PAGES=y
|
||||
CONFIG_SCHED_SMT=y
|
||||
CONFIG_PCIEPORTBUS=y
|
||||
CONFIG_NET=y
|
||||
|
@ -26,6 +26,7 @@ CONFIG_CPU_FREQ_PMAC64=y
|
||||
CONFIG_GEN_RTC=y
|
||||
CONFIG_KEXEC=y
|
||||
CONFIG_IRQ_ALL_CPUS=y
|
||||
CONFIG_PPC_4K_PAGES=y
|
||||
CONFIG_PCI_MSI=y
|
||||
CONFIG_NET=y
|
||||
CONFIG_PACKET=y
|
||||
|
@ -25,6 +25,7 @@ CONFIG_UDBG_RTAS_CONSOLE=y
|
||||
CONFIG_GEN_RTC=y
|
||||
CONFIG_KEXEC=y
|
||||
CONFIG_IRQ_ALL_CPUS=y
|
||||
CONFIG_PPC_4K_PAGES=y
|
||||
CONFIG_PCI_MSI=y
|
||||
CONFIG_NET=y
|
||||
CONFIG_PACKET=y
|
||||
|
@ -26,6 +26,7 @@ CONFIG_PPC_MICROWATT=y
|
||||
# CONFIG_PPC_OF_BOOT_TRAMPOLINE is not set
|
||||
CONFIG_CPU_FREQ=y
|
||||
CONFIG_HZ_100=y
|
||||
CONFIG_PPC_4K_PAGES=y
|
||||
# CONFIG_PPC_MEM_KEYS is not set
|
||||
# CONFIG_SECCOMP is not set
|
||||
# CONFIG_MQ_IOSCHED_KYBER is not set
|
||||
|
@ -22,7 +22,6 @@ CONFIG_CPU_FREQ_GOV_POWERSAVE=y
|
||||
CONFIG_CPU_FREQ_GOV_USERSPACE=y
|
||||
CONFIG_CPU_FREQ_GOV_ONDEMAND=y
|
||||
CONFIG_HZ_1000=y
|
||||
CONFIG_PPC_64K_PAGES=y
|
||||
# CONFIG_SECCOMP is not set
|
||||
CONFIG_PCI_MSI=y
|
||||
CONFIG_PCCARD=y
|
||||
|
@ -62,7 +62,6 @@ CONFIG_MEMORY_FAILURE=y
|
||||
CONFIG_HWPOISON_INJECT=m
|
||||
CONFIG_TRANSPARENT_HUGEPAGE=y
|
||||
CONFIG_DEFERRED_STRUCT_PAGE_INIT=y
|
||||
CONFIG_PPC_64K_PAGES=y
|
||||
CONFIG_SCHED_SMT=y
|
||||
CONFIG_PM=y
|
||||
CONFIG_HOTPLUG_PCI=y
|
||||
|
@ -52,7 +52,6 @@ CONFIG_KEXEC_FILE=y
|
||||
CONFIG_CRASH_DUMP=y
|
||||
CONFIG_FA_DUMP=y
|
||||
CONFIG_IRQ_ALL_CPUS=y
|
||||
CONFIG_PPC_64K_PAGES=y
|
||||
CONFIG_SCHED_SMT=y
|
||||
CONFIG_HOTPLUG_PCI=y
|
||||
CONFIG_HOTPLUG_PCI_RPA=m
|
||||
|
@ -30,6 +30,7 @@ CONFIG_PS3_LPM=m
|
||||
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
|
||||
CONFIG_BINFMT_MISC=y
|
||||
CONFIG_KEXEC=y
|
||||
CONFIG_PPC_4K_PAGES=y
|
||||
# CONFIG_SPARSEMEM_VMEMMAP is not set
|
||||
# CONFIG_COMPACTION is not set
|
||||
CONFIG_SCHED_SMT=y
|
||||
|
@ -56,7 +56,6 @@ CONFIG_MEMORY_HOTPLUG=y
|
||||
CONFIG_MEMORY_HOTREMOVE=y
|
||||
CONFIG_KSM=y
|
||||
CONFIG_TRANSPARENT_HUGEPAGE=y
|
||||
CONFIG_PPC_64K_PAGES=y
|
||||
CONFIG_SCHED_SMT=y
|
||||
CONFIG_HOTPLUG_PCI=y
|
||||
CONFIG_HOTPLUG_PCI_RPA=m
|
||||
|
@ -43,7 +43,6 @@ CONFIG_KEXEC_FILE=y
|
||||
CONFIG_PRESERVE_FA_DUMP=y
|
||||
CONFIG_IRQ_ALL_CPUS=y
|
||||
CONFIG_NUMA=y
|
||||
CONFIG_PPC_64K_PAGES=y
|
||||
CONFIG_SCHED_SMT=y
|
||||
CONFIG_CMDLINE="console=tty0 console=hvc0 ipr.fast_reboot=1 quiet"
|
||||
# CONFIG_SECCOMP is not set
|
||||
|
@ -12,6 +12,4 @@
|
||||
# define ASM_CONST(x) __ASM_CONST(x)
|
||||
#endif
|
||||
|
||||
#define UPD_CONSTR "<>"
|
||||
|
||||
#endif /* _ASM_POWERPC_ASM_CONST_H */
|
||||
|
@ -27,14 +27,14 @@ static __inline__ int arch_atomic_read(const atomic_t *v)
|
||||
{
|
||||
int t;
|
||||
|
||||
__asm__ __volatile__("lwz%U1%X1 %0,%1" : "=r"(t) : "m"UPD_CONSTR(v->counter));
|
||||
__asm__ __volatile__("lwz%U1%X1 %0,%1" : "=r"(t) : "m<>"(v->counter));
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
static __inline__ void arch_atomic_set(atomic_t *v, int i)
|
||||
{
|
||||
__asm__ __volatile__("stw%U0%X0 %1,%0" : "=m"UPD_CONSTR(v->counter) : "r"(i));
|
||||
__asm__ __volatile__("stw%U0%X0 %1,%0" : "=m<>"(v->counter) : "r"(i));
|
||||
}
|
||||
|
||||
#define ATOMIC_OP(op, asm_op) \
|
||||
@ -320,14 +320,14 @@ static __inline__ s64 arch_atomic64_read(const atomic64_t *v)
|
||||
{
|
||||
s64 t;
|
||||
|
||||
__asm__ __volatile__("ld%U1%X1 %0,%1" : "=r"(t) : "m"UPD_CONSTR(v->counter));
|
||||
__asm__ __volatile__("ld%U1%X1 %0,%1" : "=r"(t) : "m<>"(v->counter));
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
static __inline__ void arch_atomic64_set(atomic64_t *v, s64 i)
|
||||
{
|
||||
__asm__ __volatile__("std%U0%X0 %1,%0" : "=m"UPD_CONSTR(v->counter) : "r"(i));
|
||||
__asm__ __volatile__("std%U0%X0 %1,%0" : "=m<>"(v->counter) : "r"(i));
|
||||
}
|
||||
|
||||
#define ATOMIC64_OP(op, asm_op) \
|
||||
|
@ -255,6 +255,8 @@ int hash__create_section_mapping(unsigned long start, unsigned long end,
|
||||
int nid, pgprot_t prot);
|
||||
int hash__remove_section_mapping(unsigned long start, unsigned long end);
|
||||
|
||||
void hash__kernel_map_pages(struct page *page, int numpages, int enable);
|
||||
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* _ASM_POWERPC_BOOK3S_64_HASH_H */
|
||||
|
@ -1101,6 +1101,16 @@ static inline void vmemmap_remove_mapping(unsigned long start,
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DEBUG_PAGEALLOC
|
||||
static inline void __kernel_map_pages(struct page *page, int numpages, int enable)
|
||||
{
|
||||
if (radix_enabled())
|
||||
radix__kernel_map_pages(page, numpages, enable);
|
||||
else
|
||||
hash__kernel_map_pages(page, numpages, enable);
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline pte_t pmd_pte(pmd_t pmd)
|
||||
{
|
||||
return __pte_raw(pmd_raw(pmd));
|
||||
|
@ -316,5 +316,8 @@ int radix__create_section_mapping(unsigned long start, unsigned long end,
|
||||
int nid, pgprot_t prot);
|
||||
int radix__remove_section_mapping(unsigned long start, unsigned long end);
|
||||
#endif /* CONFIG_MEMORY_HOTPLUG */
|
||||
|
||||
void radix__kernel_map_pages(struct page *page, int numpages, int enable);
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif
|
||||
|
@ -122,7 +122,7 @@ static inline u##size name(const volatile u##size __iomem *addr) \
|
||||
{ \
|
||||
u##size ret; \
|
||||
__asm__ __volatile__("sync;"#insn"%U1%X1 %0,%1;twi 0,%0,0;isync"\
|
||||
: "=r" (ret) : "m"UPD_CONSTR (*addr) : "memory"); \
|
||||
: "=r" (ret) : "m<>" (*addr) : "memory"); \
|
||||
return ret; \
|
||||
}
|
||||
|
||||
@ -130,7 +130,7 @@ static inline u##size name(const volatile u##size __iomem *addr) \
|
||||
static inline void name(volatile u##size __iomem *addr, u##size val) \
|
||||
{ \
|
||||
__asm__ __volatile__("sync;"#insn"%U0%X0 %1,%0" \
|
||||
: "=m"UPD_CONSTR (*addr) : "r" (val) : "memory"); \
|
||||
: "=m<>" (*addr) : "r" (val) : "memory"); \
|
||||
mmiowb_set_pending(); \
|
||||
}
|
||||
|
||||
|
@ -280,12 +280,6 @@ extern void iommu_init_early_dart(struct pci_controller_ops *controller_ops);
|
||||
extern void iommu_init_early_pasemi(void);
|
||||
|
||||
#if defined(CONFIG_PPC64) && defined(CONFIG_PM)
|
||||
static inline void iommu_save(void)
|
||||
{
|
||||
if (ppc_md.iommu_save)
|
||||
ppc_md.iommu_save();
|
||||
}
|
||||
|
||||
static inline void iommu_restore(void)
|
||||
{
|
||||
if (ppc_md.iommu_restore)
|
||||
|
@ -79,7 +79,6 @@ extern int crash_wake_offline;
|
||||
struct kimage;
|
||||
struct pt_regs;
|
||||
extern void default_machine_kexec(struct kimage *image);
|
||||
extern int default_machine_kexec_prepare(struct kimage *image);
|
||||
extern void default_machine_crash_shutdown(struct pt_regs *regs);
|
||||
extern int crash_shutdown_register(crash_shutdown_t handler);
|
||||
extern int crash_shutdown_unregister(crash_shutdown_t handler);
|
||||
|
@ -378,6 +378,10 @@ static inline unsigned long compute_tlbie_rb(unsigned long v, unsigned long r,
|
||||
rb |= 1; /* L field */
|
||||
rb |= r & 0xff000 & ((1ul << a_pgshift) - 1); /* LP field */
|
||||
}
|
||||
/*
|
||||
* This sets both bits of the B field in the PTE. 0b1x values are
|
||||
* reserved, but those will have been filtered by kvmppc_do_h_enter.
|
||||
*/
|
||||
rb |= (v >> HPTE_V_SSIZE_SHIFT) << 8; /* B field */
|
||||
return rb;
|
||||
}
|
||||
|
@ -29,7 +29,6 @@ struct machdep_calls {
|
||||
char *name;
|
||||
#ifdef CONFIG_PPC64
|
||||
#ifdef CONFIG_PM
|
||||
void (*iommu_save)(void);
|
||||
void (*iommu_restore)(void);
|
||||
#endif
|
||||
#ifdef CONFIG_MEMORY_HOTPLUG_SPARSE
|
||||
@ -43,7 +42,6 @@ struct machdep_calls {
|
||||
void (*setup_arch)(void); /* Optional, may be NULL */
|
||||
/* Optional, may be NULL. */
|
||||
void (*show_cpuinfo)(struct seq_file *m);
|
||||
void (*show_percpuinfo)(struct seq_file *m, int i);
|
||||
/* Returns the current operating frequency of "cpu" in Hz */
|
||||
unsigned long (*get_proc_freq)(unsigned int cpu);
|
||||
|
||||
@ -74,8 +72,6 @@ struct machdep_calls {
|
||||
int (*set_rtc_time)(struct rtc_time *);
|
||||
void (*get_rtc_time)(struct rtc_time *);
|
||||
time64_t (*get_boot_time)(void);
|
||||
unsigned char (*rtc_read_val)(int addr);
|
||||
void (*rtc_write_val)(int addr, unsigned char val);
|
||||
|
||||
void (*calibrate_decr)(void);
|
||||
|
||||
@ -141,8 +137,6 @@ struct machdep_calls {
|
||||
May be NULL. */
|
||||
void (*init)(void);
|
||||
|
||||
void (*kgdb_map_scc)(void);
|
||||
|
||||
/*
|
||||
* optional PCI "hooks"
|
||||
*/
|
||||
@ -187,13 +181,6 @@ struct machdep_calls {
|
||||
#ifdef CONFIG_KEXEC_CORE
|
||||
void (*kexec_cpu_down)(int crash_shutdown, int secondary);
|
||||
|
||||
/* Called to do what every setup is needed on image and the
|
||||
* reboot code buffer. Returns 0 on success.
|
||||
* Provide your own (maybe dummy) implementation if your platform
|
||||
* claims to support kexec.
|
||||
*/
|
||||
int (*machine_kexec_prepare)(struct kimage *image);
|
||||
|
||||
/* Called to perform the _real_ kexec.
|
||||
* Do NOT allocate memory or fail here. We are past the point of
|
||||
* no return.
|
||||
|
@ -193,10 +193,12 @@ static inline pte_t pte_wrprotect(pte_t pte)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef pte_mkexec
|
||||
static inline pte_t pte_mkexec(pte_t pte)
|
||||
{
|
||||
return __pte(pte_val(pte) | _PAGE_EXEC);
|
||||
}
|
||||
#endif
|
||||
|
||||
#define pmd_none(pmd) (!pmd_val(pmd))
|
||||
#define pmd_bad(pmd) (pmd_val(pmd) & _PMD_BAD)
|
||||
@ -245,7 +247,7 @@ static int number_of_cells_per_pte(pmd_t *pmd, pte_basic_t val, int huge)
|
||||
static inline pte_basic_t pte_update(struct mm_struct *mm, unsigned long addr, pte_t *p,
|
||||
unsigned long clr, unsigned long set, int huge)
|
||||
{
|
||||
pte_basic_t *entry = &p->pte;
|
||||
pte_basic_t *entry = (pte_basic_t *)p;
|
||||
pte_basic_t old = pte_val(*p);
|
||||
pte_basic_t new = (old & ~(pte_basic_t)clr) | set;
|
||||
int num, i;
|
||||
@ -306,30 +308,29 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
|
||||
}
|
||||
|
||||
#define __HAVE_ARCH_PTEP_SET_WRPROTECT
|
||||
#ifndef ptep_set_wrprotect
|
||||
static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
|
||||
pte_t *ptep)
|
||||
{
|
||||
unsigned long clr = ~pte_val(pte_wrprotect(__pte(~0)));
|
||||
unsigned long set = pte_val(pte_wrprotect(__pte(0)));
|
||||
|
||||
pte_update(mm, addr, ptep, clr, set, 0);
|
||||
pte_update(mm, addr, ptep, _PAGE_RW, 0, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef __ptep_set_access_flags
|
||||
static inline void __ptep_set_access_flags(struct vm_area_struct *vma,
|
||||
pte_t *ptep, pte_t entry,
|
||||
unsigned long address,
|
||||
int psize)
|
||||
{
|
||||
pte_t pte_set = pte_mkyoung(pte_mkdirty(pte_mkwrite(pte_mkexec(__pte(0)))));
|
||||
pte_t pte_clr = pte_mkyoung(pte_mkdirty(pte_mkwrite(pte_mkexec(__pte(~0)))));
|
||||
unsigned long set = pte_val(entry) & pte_val(pte_set);
|
||||
unsigned long clr = ~pte_val(entry) & ~pte_val(pte_clr);
|
||||
unsigned long set = pte_val(entry) &
|
||||
(_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW | _PAGE_EXEC);
|
||||
int huge = psize > mmu_virtual_psize ? 1 : 0;
|
||||
|
||||
pte_update(vma->vm_mm, address, ptep, clr, set, huge);
|
||||
pte_update(vma->vm_mm, address, ptep, 0, set, huge);
|
||||
|
||||
flush_tlb_page(vma, address);
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline int pte_young(pte_t pte)
|
||||
{
|
||||
|
@ -136,6 +136,28 @@ static inline pte_t pte_mkhuge(pte_t pte)
|
||||
|
||||
#define pte_mkhuge pte_mkhuge
|
||||
|
||||
static inline pte_basic_t pte_update(struct mm_struct *mm, unsigned long addr, pte_t *p,
|
||||
unsigned long clr, unsigned long set, int huge);
|
||||
|
||||
static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
|
||||
{
|
||||
pte_update(mm, addr, ptep, 0, _PAGE_RO, 0);
|
||||
}
|
||||
#define ptep_set_wrprotect ptep_set_wrprotect
|
||||
|
||||
static inline void __ptep_set_access_flags(struct vm_area_struct *vma, pte_t *ptep,
|
||||
pte_t entry, unsigned long address, int psize)
|
||||
{
|
||||
unsigned long set = pte_val(entry) & (_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_EXEC);
|
||||
unsigned long clr = ~pte_val(entry) & _PAGE_RO;
|
||||
int huge = psize > mmu_virtual_psize ? 1 : 0;
|
||||
|
||||
pte_update(vma->vm_mm, address, ptep, clr, set, huge);
|
||||
|
||||
flush_tlb_page(vma, address);
|
||||
}
|
||||
#define __ptep_set_access_flags __ptep_set_access_flags
|
||||
|
||||
static inline unsigned long pgd_leaf_size(pgd_t pgd)
|
||||
{
|
||||
if (pgd_val(pgd) & _PMD_PAGE_8M)
|
||||
|
@ -118,11 +118,6 @@ static inline pte_t pte_wrprotect(pte_t pte)
|
||||
return __pte(pte_val(pte) & ~_PAGE_RW);
|
||||
}
|
||||
|
||||
static inline pte_t pte_mkexec(pte_t pte)
|
||||
{
|
||||
return __pte(pte_val(pte) | _PAGE_EXEC);
|
||||
}
|
||||
|
||||
#define PMD_BAD_BITS (PTE_TABLE_SIZE-1)
|
||||
#define PUD_BAD_BITS (PMD_TABLE_SIZE-1)
|
||||
|
||||
|
@ -48,7 +48,7 @@
|
||||
#define _PAGE_WRITETHRU 0x800000 /* W: cache write-through */
|
||||
|
||||
/* "Higher level" linux bit combinations */
|
||||
#define _PAGE_EXEC _PAGE_BAP_UX /* .. and was cache cleaned */
|
||||
#define _PAGE_EXEC (_PAGE_BAP_SX | _PAGE_BAP_UX) /* .. and was cache cleaned */
|
||||
#define _PAGE_RW (_PAGE_BAP_SW | _PAGE_BAP_UW) /* User write permission */
|
||||
#define _PAGE_KERNEL_RW (_PAGE_BAP_SW | _PAGE_BAP_SR | _PAGE_DIRTY)
|
||||
#define _PAGE_KERNEL_RO (_PAGE_BAP_SR)
|
||||
@ -93,11 +93,11 @@
|
||||
/* Permission masks used to generate the __P and __S table */
|
||||
#define PAGE_NONE __pgprot(_PAGE_BASE)
|
||||
#define PAGE_SHARED __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW)
|
||||
#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_EXEC)
|
||||
#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_BAP_UX)
|
||||
#define PAGE_COPY __pgprot(_PAGE_BASE | _PAGE_USER)
|
||||
#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
|
||||
#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_BAP_UX)
|
||||
#define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_USER)
|
||||
#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
|
||||
#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_BAP_UX)
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
static inline pte_t pte_mkprivileged(pte_t pte)
|
||||
@ -113,6 +113,16 @@ static inline pte_t pte_mkuser(pte_t pte)
|
||||
}
|
||||
|
||||
#define pte_mkuser pte_mkuser
|
||||
|
||||
static inline pte_t pte_mkexec(pte_t pte)
|
||||
{
|
||||
if (pte_val(pte) & _PAGE_BAP_UR)
|
||||
return __pte((pte_val(pte) & ~_PAGE_BAP_SX) | _PAGE_BAP_UX);
|
||||
else
|
||||
return __pte((pte_val(pte) & ~_PAGE_BAP_UX) | _PAGE_BAP_SX);
|
||||
}
|
||||
#define pte_mkexec pte_mkexec
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
@ -32,11 +32,26 @@ extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
|
||||
unsigned long end);
|
||||
extern void flush_tlb_kernel_range(unsigned long start, unsigned long end);
|
||||
|
||||
#ifdef CONFIG_PPC_8xx
|
||||
static inline void local_flush_tlb_mm(struct mm_struct *mm)
|
||||
{
|
||||
unsigned int pid = READ_ONCE(mm->context.id);
|
||||
|
||||
if (pid != MMU_NO_CONTEXT)
|
||||
asm volatile ("sync; tlbia; isync" : : : "memory");
|
||||
}
|
||||
|
||||
static inline void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
|
||||
{
|
||||
asm volatile ("tlbie %0; sync" : : "r" (vmaddr) : "memory");
|
||||
}
|
||||
#else
|
||||
extern void local_flush_tlb_mm(struct mm_struct *mm);
|
||||
extern void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
|
||||
|
||||
extern void __local_flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr,
|
||||
int tsize, int ind);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
extern void flush_tlb_mm(struct mm_struct *mm);
|
||||
|
@ -21,7 +21,7 @@ static inline bool is_shared_processor(void)
|
||||
return static_branch_unlikely(&shared_processor);
|
||||
}
|
||||
|
||||
/* If bit 0 is set, the cpu has been preempted */
|
||||
/* If bit 0 is set, the cpu has been ceded, conferred, or preempted */
|
||||
static inline u32 yield_count_of(int cpu)
|
||||
{
|
||||
__be32 yield_count = READ_ONCE(lppaca_of(cpu).yield_count);
|
||||
@ -92,17 +92,47 @@ static inline void prod_cpu(int cpu)
|
||||
#define vcpu_is_preempted vcpu_is_preempted
|
||||
static inline bool vcpu_is_preempted(int cpu)
|
||||
{
|
||||
/*
|
||||
* The dispatch/yield bit alone is an imperfect indicator of
|
||||
* whether the hypervisor has dispatched @cpu to run on a physical
|
||||
* processor. When it is clear, @cpu is definitely not preempted.
|
||||
* But when it is set, it means only that it *might* be, subject to
|
||||
* other conditions. So we check other properties of the VM and
|
||||
* @cpu first, resorting to the yield count last.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Hypervisor preemption isn't possible in dedicated processor
|
||||
* mode by definition.
|
||||
*/
|
||||
if (!is_shared_processor())
|
||||
return false;
|
||||
|
||||
#ifdef CONFIG_PPC_SPLPAR
|
||||
if (!is_kvm_guest()) {
|
||||
int first_cpu = cpu_first_thread_sibling(smp_processor_id());
|
||||
int first_cpu;
|
||||
|
||||
/*
|
||||
* Preemption can only happen at core granularity. This CPU
|
||||
* is not preempted if one of the CPU of this core is not
|
||||
* preempted.
|
||||
* The result of vcpu_is_preempted() is used in a
|
||||
* speculative way, and is always subject to invalidation
|
||||
* by events internal and external to Linux. While we can
|
||||
* be called in preemptable context (in the Linux sense),
|
||||
* we're not accessing per-cpu resources in a way that can
|
||||
* race destructively with Linux scheduler preemption and
|
||||
* migration, and callers can tolerate the potential for
|
||||
* error introduced by sampling the CPU index without
|
||||
* pinning the task to it. So it is permissible to use
|
||||
* raw_smp_processor_id() here to defeat the preempt debug
|
||||
* warnings that can arise from using smp_processor_id()
|
||||
* in arbitrary contexts.
|
||||
*/
|
||||
first_cpu = cpu_first_thread_sibling(raw_smp_processor_id());
|
||||
|
||||
/*
|
||||
* The PowerVM hypervisor dispatches VMs on a whole core
|
||||
* basis. So we know that a thread sibling of the local CPU
|
||||
* cannot have been preempted by the hypervisor, even if it
|
||||
* has called H_CONFER, which will set the yield bit.
|
||||
*/
|
||||
if (cpu_first_thread_sibling(cpu) == first_cpu)
|
||||
return false;
|
||||
|
@ -2,17 +2,33 @@
|
||||
#ifndef _ASM_POWERPC_PGTABLE_TYPES_H
|
||||
#define _ASM_POWERPC_PGTABLE_TYPES_H
|
||||
|
||||
#if defined(__CHECKER__) || !defined(CONFIG_PPC32)
|
||||
#define STRICT_MM_TYPECHECKS
|
||||
#endif
|
||||
|
||||
/* PTE level */
|
||||
#if defined(CONFIG_PPC_8xx) && defined(CONFIG_PPC_16K_PAGES)
|
||||
typedef struct { pte_basic_t pte, pte1, pte2, pte3; } pte_t;
|
||||
#else
|
||||
#elif defined(STRICT_MM_TYPECHECKS)
|
||||
typedef struct { pte_basic_t pte; } pte_t;
|
||||
#else
|
||||
typedef pte_basic_t pte_t;
|
||||
#endif
|
||||
|
||||
#if defined(STRICT_MM_TYPECHECKS) || \
|
||||
(defined(CONFIG_PPC_8xx) && defined(CONFIG_PPC_16K_PAGES))
|
||||
#define __pte(x) ((pte_t) { (x) })
|
||||
static inline pte_basic_t pte_val(pte_t x)
|
||||
{
|
||||
return x.pte;
|
||||
}
|
||||
#else
|
||||
#define __pte(x) ((pte_t)(x))
|
||||
static inline pte_basic_t pte_val(pte_t x)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* PMD level */
|
||||
#ifdef CONFIG_PPC64
|
||||
|
@ -28,8 +28,8 @@
|
||||
#else
|
||||
#define SAVE_GPR(n, base) stw n,GPR0+4*(n)(base)
|
||||
#define REST_GPR(n, base) lwz n,GPR0+4*(n)(base)
|
||||
#define SAVE_NVGPRS(base) stmw 13, GPR0+4*13(base)
|
||||
#define REST_NVGPRS(base) lmw 13, GPR0+4*13(base)
|
||||
#define SAVE_NVGPRS(base) SAVE_GPR(13, base); SAVE_8GPRS(14, base); SAVE_10GPRS(22, base)
|
||||
#define REST_NVGPRS(base) REST_GPR(13, base); REST_8GPRS(14, base); REST_10GPRS(22, base)
|
||||
#endif
|
||||
|
||||
#define SAVE_2GPRS(n, base) SAVE_GPR(n, base); SAVE_GPR(n+1, base)
|
||||
|
28
arch/powerpc/include/asm/static_call.h
Normal file
28
arch/powerpc/include/asm/static_call.h
Normal file
@ -0,0 +1,28 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _ASM_POWERPC_STATIC_CALL_H
|
||||
#define _ASM_POWERPC_STATIC_CALL_H
|
||||
|
||||
#define __PPC_SCT(name, inst) \
|
||||
asm(".pushsection .text, \"ax\" \n" \
|
||||
".align 5 \n" \
|
||||
".globl " STATIC_CALL_TRAMP_STR(name) " \n" \
|
||||
STATIC_CALL_TRAMP_STR(name) ": \n" \
|
||||
inst " \n" \
|
||||
" lis 12,2f@ha \n" \
|
||||
" lwz 12,2f@l(12) \n" \
|
||||
" mtctr 12 \n" \
|
||||
" bctr \n" \
|
||||
"1: li 3, 0 \n" \
|
||||
" blr \n" \
|
||||
"2: .long 0 \n" \
|
||||
".type " STATIC_CALL_TRAMP_STR(name) ", @function \n" \
|
||||
".size " STATIC_CALL_TRAMP_STR(name) ", . - " STATIC_CALL_TRAMP_STR(name) " \n" \
|
||||
".popsection \n")
|
||||
|
||||
#define PPC_SCT_RET0 20 /* Offset of label 1 */
|
||||
#define PPC_SCT_DATA 28 /* Offset of label 2 */
|
||||
|
||||
#define ARCH_DEFINE_STATIC_CALL_TRAMP(name, func) __PPC_SCT(name, "b " #func)
|
||||
#define ARCH_DEFINE_STATIC_CALL_NULL_TRAMP(name) __PPC_SCT(name, "blr")
|
||||
|
||||
#endif /* _ASM_POWERPC_STATIC_CALL_H */
|
@ -86,7 +86,7 @@ __pu_failed: \
|
||||
"1: " op "%U1%X1 %0,%1 # put_user\n" \
|
||||
EX_TABLE(1b, %l2) \
|
||||
: \
|
||||
: "r" (x), "m"UPD_CONSTR (*addr) \
|
||||
: "r" (x), "m<>" (*addr) \
|
||||
: \
|
||||
: label)
|
||||
|
||||
@ -143,7 +143,7 @@ do { \
|
||||
"1: "op"%U1%X1 %0, %1 # get_user\n" \
|
||||
EX_TABLE(1b, %l2) \
|
||||
: "=r" (x) \
|
||||
: "m"UPD_CONSTR (*addr) \
|
||||
: "m<>" (*addr) \
|
||||
: \
|
||||
: label)
|
||||
|
||||
@ -200,7 +200,7 @@ __gus_failed: \
|
||||
".previous\n" \
|
||||
EX_TABLE(1b, 3b) \
|
||||
: "=r" (err), "=r" (x) \
|
||||
: "m"UPD_CONSTR (*addr), "i" (-EFAULT), "0" (err))
|
||||
: "m<>" (*addr), "i" (-EFAULT), "0" (err))
|
||||
|
||||
#ifdef __powerpc64__
|
||||
#define __get_user_asm2(x, addr, err) \
|
||||
|
@ -61,27 +61,35 @@ enum perf_event_powerpc_regs {
|
||||
PERF_REG_POWERPC_PMC4,
|
||||
PERF_REG_POWERPC_PMC5,
|
||||
PERF_REG_POWERPC_PMC6,
|
||||
/* Max regs without the extended regs */
|
||||
PERF_REG_POWERPC_SDAR,
|
||||
PERF_REG_POWERPC_SIAR,
|
||||
/* Max mask value for interrupt regs w/o extended regs */
|
||||
PERF_REG_POWERPC_MAX = PERF_REG_POWERPC_MMCRA + 1,
|
||||
/* Max mask value for interrupt regs including extended regs */
|
||||
PERF_REG_EXTENDED_MAX = PERF_REG_POWERPC_SIAR + 1,
|
||||
};
|
||||
|
||||
#define PERF_REG_PMU_MASK ((1ULL << PERF_REG_POWERPC_MAX) - 1)
|
||||
|
||||
/* Exclude MMCR3, SIER2, SIER3 for CPU_FTR_ARCH_300 */
|
||||
#define PERF_EXCLUDE_REG_EXT_300 (7ULL << PERF_REG_POWERPC_MMCR3)
|
||||
|
||||
/*
|
||||
* PERF_REG_EXTENDED_MASK value for CPU_FTR_ARCH_300
|
||||
* includes 9 SPRS from MMCR0 to PMC6 excluding the
|
||||
* unsupported SPRS in PERF_EXCLUDE_REG_EXT_300.
|
||||
* includes 11 SPRS from MMCR0 to SIAR excluding the
|
||||
* unsupported SPRS MMCR3, SIER2 and SIER3.
|
||||
*/
|
||||
#define PERF_REG_PMU_MASK_300 ((0xfffULL << PERF_REG_POWERPC_MMCR0) - PERF_EXCLUDE_REG_EXT_300)
|
||||
#define PERF_REG_PMU_MASK_300 \
|
||||
((1ULL << PERF_REG_POWERPC_MMCR0) | (1ULL << PERF_REG_POWERPC_MMCR1) | \
|
||||
(1ULL << PERF_REG_POWERPC_MMCR2) | (1ULL << PERF_REG_POWERPC_PMC1) | \
|
||||
(1ULL << PERF_REG_POWERPC_PMC2) | (1ULL << PERF_REG_POWERPC_PMC3) | \
|
||||
(1ULL << PERF_REG_POWERPC_PMC4) | (1ULL << PERF_REG_POWERPC_PMC5) | \
|
||||
(1ULL << PERF_REG_POWERPC_PMC6) | (1ULL << PERF_REG_POWERPC_SDAR) | \
|
||||
(1ULL << PERF_REG_POWERPC_SIAR))
|
||||
|
||||
/*
|
||||
* PERF_REG_EXTENDED_MASK value for CPU_FTR_ARCH_31
|
||||
* includes 12 SPRs from MMCR0 to PMC6.
|
||||
* includes 14 SPRs from MMCR0 to SIAR.
|
||||
*/
|
||||
#define PERF_REG_PMU_MASK_31 (0xfffULL << PERF_REG_POWERPC_MMCR0)
|
||||
#define PERF_REG_PMU_MASK_31 \
|
||||
(PERF_REG_PMU_MASK_300 | (1ULL << PERF_REG_POWERPC_MMCR3) | \
|
||||
(1ULL << PERF_REG_POWERPC_SIER2) | (1ULL << PERF_REG_POWERPC_SIER3))
|
||||
|
||||
#define PERF_REG_EXTENDED_MAX (PERF_REG_POWERPC_PMC6 + 1)
|
||||
#endif /* _UAPI_ASM_POWERPC_PERF_REGS_H */
|
||||
|
@ -106,7 +106,7 @@ extra-y += vmlinux.lds
|
||||
|
||||
obj-$(CONFIG_RELOCATABLE) += reloc_$(BITS).o
|
||||
|
||||
obj-$(CONFIG_PPC32) += entry_32.o setup_32.o early_32.o
|
||||
obj-$(CONFIG_PPC32) += entry_32.o setup_32.o early_32.o static_call.o
|
||||
obj-$(CONFIG_PPC64) += dma-iommu.o iommu.o
|
||||
obj-$(CONFIG_KGDB) += kgdb.o
|
||||
obj-$(CONFIG_BOOTX_TEXT) += btext.o
|
||||
|
@ -349,6 +349,7 @@ int fix_alignment(struct pt_regs *regs)
|
||||
if (op.type != CACHEOP + DCBZ)
|
||||
return -EINVAL;
|
||||
PPC_WARN_ALIGNMENT(dcbz, regs);
|
||||
WARN_ON_ONCE(!user_mode(regs));
|
||||
r = emulate_dcbz(op.ea, regs);
|
||||
} else {
|
||||
if (type == LARX || type == STCX)
|
||||
|
@ -589,6 +589,7 @@ EXPORT_SYMBOL(eeh_check_failure);
|
||||
/**
|
||||
* eeh_pci_enable - Enable MMIO or DMA transfers for this slot
|
||||
* @pe: EEH PE
|
||||
* @function: EEH option
|
||||
*
|
||||
* This routine should be called to reenable frozen MMIO or DMA
|
||||
* so that it would work correctly again. It's useful while doing
|
||||
@ -761,8 +762,8 @@ int pcibios_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state stat
|
||||
}
|
||||
|
||||
/**
|
||||
* eeh_set_pe_freset - Check the required reset for the indicated device
|
||||
* @data: EEH device
|
||||
* eeh_set_dev_freset - Check the required reset for the indicated device
|
||||
* @edev: EEH device
|
||||
* @flag: return value
|
||||
*
|
||||
* Each device might have its preferred reset type: fundamental or
|
||||
@ -801,6 +802,7 @@ static void eeh_pe_refreeze_passed(struct eeh_pe *root)
|
||||
/**
|
||||
* eeh_pe_reset_full - Complete a full reset process on the indicated PE
|
||||
* @pe: EEH PE
|
||||
* @include_passed: include passed-through devices?
|
||||
*
|
||||
* This function executes a full reset procedure on a PE, including setting
|
||||
* the appropriate flags, performing a fundamental or hot reset, and then
|
||||
@ -937,6 +939,7 @@ static struct notifier_block eeh_device_nb = {
|
||||
|
||||
/**
|
||||
* eeh_init - System wide EEH initialization
|
||||
* @ops: struct to trace EEH operation callback functions
|
||||
*
|
||||
* It's the platform's job to call this from an arch_initcall().
|
||||
*/
|
||||
@ -1442,6 +1445,7 @@ static int eeh_pe_reenable_devices(struct eeh_pe *pe, bool include_passed)
|
||||
* eeh_pe_reset - Issue PE reset according to specified type
|
||||
* @pe: EEH PE
|
||||
* @option: reset type
|
||||
* @include_passed: include passed-through devices?
|
||||
*
|
||||
* The routine is called to reset the specified PE with the
|
||||
* indicated type, either fundamental reset or hot reset.
|
||||
@ -1513,12 +1517,12 @@ EXPORT_SYMBOL_GPL(eeh_pe_configure);
|
||||
* eeh_pe_inject_err - Injecting the specified PCI error to the indicated PE
|
||||
* @pe: the indicated PE
|
||||
* @type: error type
|
||||
* @function: error function
|
||||
* @func: error function
|
||||
* @addr: address
|
||||
* @mask: address mask
|
||||
*
|
||||
* The routine is called to inject the specified PCI error, which
|
||||
* is determined by @type and @function, to the indicated PE for
|
||||
* is determined by @type and @func, to the indicated PE for
|
||||
* testing purpose.
|
||||
*/
|
||||
int eeh_pe_inject_err(struct eeh_pe *pe, int type, int func,
|
||||
|
@ -31,11 +31,10 @@ int __init check_kvm_guest(void)
|
||||
if (!hyper_node)
|
||||
return 0;
|
||||
|
||||
if (!of_device_is_compatible(hyper_node, "linux,kvm"))
|
||||
return 0;
|
||||
|
||||
static_branch_enable(&kvm_guest);
|
||||
if (of_device_is_compatible(hyper_node, "linux,kvm"))
|
||||
static_branch_enable(&kvm_guest);
|
||||
|
||||
of_node_put(hyper_node);
|
||||
return 0;
|
||||
}
|
||||
core_initcall(check_kvm_guest); // before kvm_guest_init()
|
||||
|
@ -755,7 +755,7 @@ _GLOBAL(mmu_pin_tlb)
|
||||
cmplw r6, r9
|
||||
bdnzt lt, 2b
|
||||
|
||||
4: LOAD_REG_IMMEDIATE(r8, 0xf0 | _PAGE_SPS | _PAGE_SH | _PAGE_PRESENT)
|
||||
4: LOAD_REG_IMMEDIATE(r8, 0xf0 | _PAGE_DIRTY | _PAGE_SPS | _PAGE_SH | _PAGE_PRESENT)
|
||||
2: ori r0, r6, MD_EVALID
|
||||
mtspr SPRN_MD_CTR, r5
|
||||
mtspr SPRN_MD_EPN, r0
|
||||
|
@ -465,12 +465,21 @@ ALT_FTR_SECTION_END_IFSET(CPU_FTR_EMB_HV)
|
||||
bl do_page_fault; \
|
||||
b interrupt_return
|
||||
|
||||
/*
|
||||
* Instruction TLB Error interrupt handlers may call InstructionStorage
|
||||
* directly without clearing ESR, so the ESR at this point may be left over
|
||||
* from a prior interrupt.
|
||||
*
|
||||
* In any case, do_page_fault for BOOK3E does not use ESR and always expects
|
||||
* dsisr to be 0. ESR_DST from a prior store in particular would confuse fault
|
||||
* handling.
|
||||
*/
|
||||
#define INSTRUCTION_STORAGE_EXCEPTION \
|
||||
START_EXCEPTION(InstructionStorage) \
|
||||
NORMAL_EXCEPTION_PROLOG(0x400, INST_STORAGE); \
|
||||
mfspr r5,SPRN_ESR; /* Grab the ESR and save it */ \
|
||||
NORMAL_EXCEPTION_PROLOG(0x400, INST_STORAGE); \
|
||||
li r5,0; /* Store 0 in regs->esr (dsisr) */ \
|
||||
stw r5,_ESR(r11); \
|
||||
stw r12, _DEAR(r11); /* Pass SRR0 as arg2 */ \
|
||||
stw r12, _DEAR(r11); /* Set regs->dear (dar) to SRR0 */ \
|
||||
prepare_transfer_to_handler; \
|
||||
bl do_page_fault; \
|
||||
b interrupt_return
|
||||
|
@ -127,15 +127,6 @@ bool wp_check_constraints(struct pt_regs *regs, struct ppc_inst instr,
|
||||
return false;
|
||||
}
|
||||
|
||||
static int cache_op_size(void)
|
||||
{
|
||||
#ifdef __powerpc64__
|
||||
return ppc64_caches.l1d.block_size;
|
||||
#else
|
||||
return L1_CACHE_BYTES;
|
||||
#endif
|
||||
}
|
||||
|
||||
void wp_get_instr_detail(struct pt_regs *regs, struct ppc_inst *instr,
|
||||
int *type, int *size, unsigned long *ea)
|
||||
{
|
||||
@ -147,14 +138,14 @@ void wp_get_instr_detail(struct pt_regs *regs, struct ppc_inst *instr,
|
||||
analyse_instr(&op, regs, *instr);
|
||||
*type = GETTYPE(op.type);
|
||||
*ea = op.ea;
|
||||
#ifdef __powerpc64__
|
||||
|
||||
if (!(regs->msr & MSR_64BIT))
|
||||
*ea &= 0xffffffffUL;
|
||||
#endif
|
||||
|
||||
|
||||
*size = GETSIZE(op.type);
|
||||
if (*type == CACHEOP) {
|
||||
*size = cache_op_size();
|
||||
*size = l1_dcache_bytes();
|
||||
*ea &= ~(*size - 1);
|
||||
} else if (*type == LOAD_VMX || *type == STORE_VMX) {
|
||||
*ea &= ~(*size - 1);
|
||||
|
@ -266,7 +266,7 @@ static void check_return_regs_valid(struct pt_regs *regs)
|
||||
if (trap_is_scv(regs))
|
||||
return;
|
||||
|
||||
trap = regs->trap;
|
||||
trap = TRAP(regs);
|
||||
// EE in HV mode sets HSRRs like 0xea0
|
||||
if (cpu_has_feature(CPU_FTR_HVMODE) && trap == INTERRUPT_EXTERNAL)
|
||||
trap = 0xea0;
|
||||
|
@ -278,9 +278,6 @@ static int show_cpuinfo(struct seq_file *m, void *v)
|
||||
seq_printf(m, "clock\t\t: %lu.%06luMHz\n",
|
||||
proc_freq / 1000000, proc_freq % 1000000);
|
||||
|
||||
if (ppc_md.show_percpuinfo != NULL)
|
||||
ppc_md.show_percpuinfo(m, cpu_id);
|
||||
|
||||
/* If we are a Freescale core do a simple check so
|
||||
* we dont have to keep adding cases in the future */
|
||||
if (PVR_VER(pvr) & 0x8000) {
|
||||
|
37
arch/powerpc/kernel/static_call.c
Normal file
37
arch/powerpc/kernel/static_call.c
Normal file
@ -0,0 +1,37 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <linux/memory.h>
|
||||
#include <linux/static_call.h>
|
||||
|
||||
#include <asm/code-patching.h>
|
||||
|
||||
void arch_static_call_transform(void *site, void *tramp, void *func, bool tail)
|
||||
{
|
||||
int err;
|
||||
bool is_ret0 = (func == __static_call_return0);
|
||||
unsigned long target = (unsigned long)(is_ret0 ? tramp + PPC_SCT_RET0 : func);
|
||||
bool is_short = is_offset_in_branch_range((long)target - (long)tramp);
|
||||
|
||||
if (!tramp)
|
||||
return;
|
||||
|
||||
mutex_lock(&text_mutex);
|
||||
|
||||
if (func && !is_short) {
|
||||
err = patch_instruction(tramp + PPC_SCT_DATA, ppc_inst(target));
|
||||
if (err)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!func)
|
||||
err = patch_instruction(tramp, ppc_inst(PPC_RAW_BLR()));
|
||||
else if (is_short)
|
||||
err = patch_branch(tramp, target, 0);
|
||||
else
|
||||
err = patch_instruction(tramp, ppc_inst(PPC_RAW_NOP()));
|
||||
out:
|
||||
mutex_unlock(&text_mutex);
|
||||
|
||||
if (err)
|
||||
panic("%s: patching failed %pS at %pS\n", __func__, func, tramp);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(arch_static_call_transform);
|
@ -17,8 +17,3 @@ void do_after_copyback(void)
|
||||
touch_softlockup_watchdog();
|
||||
mb();
|
||||
}
|
||||
|
||||
void _iommu_save(void)
|
||||
{
|
||||
iommu_save();
|
||||
}
|
||||
|
@ -128,7 +128,6 @@ END_FW_FTR_SECTION_IFCLR(FW_FEATURE_LPAR)
|
||||
* stack pointer on the stack like a real stackframe */
|
||||
addi r1,r1,-128
|
||||
|
||||
bl _iommu_save
|
||||
bl swsusp_save
|
||||
|
||||
/* restore LR */
|
||||
|
@ -928,7 +928,8 @@ static int unregister_cpu_online(unsigned int cpu)
|
||||
struct device_attribute *attrs, *pmc_attrs;
|
||||
int i, nattrs;
|
||||
|
||||
BUG_ON(!c->hotpluggable);
|
||||
if (WARN_RATELIMIT(!c->hotpluggable, "cpu %d can't be offlined\n", cpu))
|
||||
return -EBUSY;
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
if (cpu_has_feature(CPU_FTR_SMT))
|
||||
|
@ -631,8 +631,12 @@ void timer_broadcast_interrupt(void)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SUSPEND
|
||||
static void generic_suspend_disable_irqs(void)
|
||||
/* Overrides the weak version in kernel/power/main.c */
|
||||
void arch_suspend_disable_irqs(void)
|
||||
{
|
||||
if (ppc_md.suspend_disable_irqs)
|
||||
ppc_md.suspend_disable_irqs();
|
||||
|
||||
/* Disable the decrementer, so that it doesn't interfere
|
||||
* with suspending.
|
||||
*/
|
||||
@ -642,23 +646,11 @@ static void generic_suspend_disable_irqs(void)
|
||||
set_dec(decrementer_max);
|
||||
}
|
||||
|
||||
static void generic_suspend_enable_irqs(void)
|
||||
{
|
||||
local_irq_enable();
|
||||
}
|
||||
|
||||
/* Overrides the weak version in kernel/power/main.c */
|
||||
void arch_suspend_disable_irqs(void)
|
||||
{
|
||||
if (ppc_md.suspend_disable_irqs)
|
||||
ppc_md.suspend_disable_irqs();
|
||||
generic_suspend_disable_irqs();
|
||||
}
|
||||
|
||||
/* Overrides the weak version in kernel/power/main.c */
|
||||
void arch_suspend_enable_irqs(void)
|
||||
{
|
||||
generic_suspend_enable_irqs();
|
||||
local_irq_enable();
|
||||
|
||||
if (ppc_md.suspend_enable_irqs)
|
||||
ppc_md.suspend_enable_irqs();
|
||||
}
|
||||
|
@ -143,6 +143,12 @@ SECTIONS
|
||||
SOFT_MASK_TABLE(8)
|
||||
RESTART_TABLE(8)
|
||||
|
||||
.opd : AT(ADDR(.opd) - LOAD_OFFSET) {
|
||||
__start_opd = .;
|
||||
KEEP(*(.opd))
|
||||
__end_opd = .;
|
||||
}
|
||||
|
||||
. = ALIGN(8);
|
||||
__stf_entry_barrier_fixup : AT(ADDR(__stf_entry_barrier_fixup) - LOAD_OFFSET) {
|
||||
__start___stf_entry_barrier_fixup = .;
|
||||
@ -339,12 +345,6 @@ SECTIONS
|
||||
*(.branch_lt)
|
||||
}
|
||||
|
||||
.opd : AT(ADDR(.opd) - LOAD_OFFSET) {
|
||||
__start_opd = .;
|
||||
KEEP(*(.opd))
|
||||
__end_opd = .;
|
||||
}
|
||||
|
||||
. = ALIGN(256);
|
||||
.got : AT(ADDR(.got) - LOAD_OFFSET) {
|
||||
__toc_start = .;
|
||||
|
@ -48,19 +48,6 @@ void machine_crash_shutdown(struct pt_regs *regs)
|
||||
default_machine_crash_shutdown(regs);
|
||||
}
|
||||
|
||||
/*
|
||||
* Do what every setup is needed on image and the
|
||||
* reboot code buffer to allow us to avoid allocations
|
||||
* later.
|
||||
*/
|
||||
int machine_kexec_prepare(struct kimage *image)
|
||||
{
|
||||
if (ppc_md.machine_kexec_prepare)
|
||||
return ppc_md.machine_kexec_prepare(image);
|
||||
else
|
||||
return default_machine_kexec_prepare(image);
|
||||
}
|
||||
|
||||
void machine_kexec_cleanup(struct kimage *image)
|
||||
{
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ void default_machine_kexec(struct kimage *image)
|
||||
(*rnk)(page_list, reboot_code_buffer_phys, image->start);
|
||||
}
|
||||
|
||||
int default_machine_kexec_prepare(struct kimage *image)
|
||||
int machine_kexec_prepare(struct kimage *image)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -32,7 +32,7 @@
|
||||
#include <asm/svm.h>
|
||||
#include <asm/ultravisor.h>
|
||||
|
||||
int default_machine_kexec_prepare(struct kimage *image)
|
||||
int machine_kexec_prepare(struct kimage *image)
|
||||
{
|
||||
int i;
|
||||
unsigned long begin, end; /* limits of segment */
|
||||
|
@ -700,6 +700,7 @@ static int update_usable_mem_fdt(void *fdt, struct crash_mem *usable_mem)
|
||||
if (ret) {
|
||||
pr_err("Failed to set linux,usable-memory property for %s node",
|
||||
dn->full_name);
|
||||
of_node_put(dn);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
@ -3726,7 +3726,20 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc)
|
||||
|
||||
kvmppc_set_host_core(pcpu);
|
||||
|
||||
guest_exit_irqoff();
|
||||
context_tracking_guest_exit();
|
||||
if (!vtime_accounting_enabled_this_cpu()) {
|
||||
local_irq_enable();
|
||||
/*
|
||||
* Service IRQs here before vtime_account_guest_exit() so any
|
||||
* ticks that occurred while running the guest are accounted to
|
||||
* the guest. If vtime accounting is enabled, accounting uses
|
||||
* TB rather than ticks, so it can be done without enabling
|
||||
* interrupts here, which has the problem that it accounts
|
||||
* interrupt processing overhead to the host.
|
||||
*/
|
||||
local_irq_disable();
|
||||
}
|
||||
vtime_account_guest_exit();
|
||||
|
||||
local_irq_enable();
|
||||
|
||||
@ -4510,7 +4523,20 @@ int kvmhv_run_single_vcpu(struct kvm_vcpu *vcpu, u64 time_limit,
|
||||
|
||||
kvmppc_set_host_core(pcpu);
|
||||
|
||||
guest_exit_irqoff();
|
||||
context_tracking_guest_exit();
|
||||
if (!vtime_accounting_enabled_this_cpu()) {
|
||||
local_irq_enable();
|
||||
/*
|
||||
* Service IRQs here before vtime_account_guest_exit() so any
|
||||
* ticks that occurred while running the guest are accounted to
|
||||
* the guest. If vtime accounting is enabled, accounting uses
|
||||
* TB rather than ticks, so it can be done without enabling
|
||||
* interrupts here, which has the problem that it accounts
|
||||
* interrupt processing overhead to the host.
|
||||
*/
|
||||
local_irq_disable();
|
||||
}
|
||||
vtime_account_guest_exit();
|
||||
|
||||
local_irq_enable();
|
||||
|
||||
|
@ -207,6 +207,15 @@ long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags,
|
||||
|
||||
if (kvm_is_radix(kvm))
|
||||
return H_FUNCTION;
|
||||
/*
|
||||
* The HPTE gets used by compute_tlbie_rb() to set TLBIE bits, so
|
||||
* these functions should work together -- must ensure a guest can not
|
||||
* cause problems with the TLBIE that KVM executes.
|
||||
*/
|
||||
if ((pteh >> HPTE_V_SSIZE_SHIFT) & 0x2) {
|
||||
/* B=0b1x is a reserved value, disallow it. */
|
||||
return H_PARAMETER;
|
||||
}
|
||||
psize = kvmppc_actual_pgsz(pteh, ptel);
|
||||
if (!psize)
|
||||
return H_PARAMETER;
|
||||
|
@ -1042,7 +1042,21 @@ int kvmppc_handle_exit(struct kvm_vcpu *vcpu, unsigned int exit_nr)
|
||||
}
|
||||
|
||||
trace_kvm_exit(exit_nr, vcpu);
|
||||
guest_exit_irqoff();
|
||||
|
||||
context_tracking_guest_exit();
|
||||
if (!vtime_accounting_enabled_this_cpu()) {
|
||||
local_irq_enable();
|
||||
/*
|
||||
* Service IRQs here before vtime_account_guest_exit() so any
|
||||
* ticks that occurred while running the guest are accounted to
|
||||
* the guest. If vtime accounting is enabled, accounting uses
|
||||
* TB rather than ticks, so it can be done without enabling
|
||||
* interrupts here, which has the problem that it accounts
|
||||
* interrupt processing overhead to the host.
|
||||
*/
|
||||
local_irq_disable();
|
||||
}
|
||||
vtime_account_guest_exit();
|
||||
|
||||
local_irq_enable();
|
||||
|
||||
|
@ -1094,7 +1094,7 @@ static inline u64 sp_to_dp(u32 fprs)
|
||||
|
||||
preempt_disable();
|
||||
enable_kernel_fp();
|
||||
asm ("lfs%U1%X1 0,%1; stfd%U0%X0 0,%0" : "=m"UPD_CONSTR (fprd) : "m"UPD_CONSTR (fprs)
|
||||
asm ("lfs%U1%X1 0,%1; stfd%U0%X0 0,%0" : "=m<>" (fprd) : "m<>" (fprs)
|
||||
: "fr0");
|
||||
preempt_enable();
|
||||
return fprd;
|
||||
@ -1106,7 +1106,7 @@ static inline u32 dp_to_sp(u64 fprd)
|
||||
|
||||
preempt_disable();
|
||||
enable_kernel_fp();
|
||||
asm ("lfd%U1%X1 0,%1; stfs%U0%X0 0,%0" : "=m"UPD_CONSTR (fprs) : "m"UPD_CONSTR (fprd)
|
||||
asm ("lfd%U1%X1 0,%1; stfs%U0%X0 0,%0" : "=m<>" (fprs) : "m<>" (fprd)
|
||||
: "fr0");
|
||||
preempt_enable();
|
||||
return fprs;
|
||||
|
@ -228,6 +228,7 @@ static void do_stf_exit_barrier_fixups(enum stf_barrier_type types)
|
||||
|
||||
static bool stf_exit_reentrant = false;
|
||||
static bool rfi_exit_reentrant = false;
|
||||
static DEFINE_MUTEX(exit_flush_lock);
|
||||
|
||||
static int __do_stf_barrier_fixups(void *data)
|
||||
{
|
||||
@ -253,6 +254,9 @@ void do_stf_barrier_fixups(enum stf_barrier_type types)
|
||||
* low level interrupt exit code before patching. After the patching,
|
||||
* if allowed, then flip the branch to allow fast exits.
|
||||
*/
|
||||
|
||||
// Prevent static key update races with do_rfi_flush_fixups()
|
||||
mutex_lock(&exit_flush_lock);
|
||||
static_branch_enable(&interrupt_exit_not_reentrant);
|
||||
|
||||
stop_machine(__do_stf_barrier_fixups, &types, NULL);
|
||||
@ -264,6 +268,8 @@ void do_stf_barrier_fixups(enum stf_barrier_type types)
|
||||
|
||||
if (stf_exit_reentrant && rfi_exit_reentrant)
|
||||
static_branch_disable(&interrupt_exit_not_reentrant);
|
||||
|
||||
mutex_unlock(&exit_flush_lock);
|
||||
}
|
||||
|
||||
void do_uaccess_flush_fixups(enum l1d_flush_type types)
|
||||
@ -486,6 +492,9 @@ void do_rfi_flush_fixups(enum l1d_flush_type types)
|
||||
* without stop_machine, so this could be achieved with a broadcast
|
||||
* IPI instead, but this matches the stf sequence.
|
||||
*/
|
||||
|
||||
// Prevent static key update races with do_stf_barrier_fixups()
|
||||
mutex_lock(&exit_flush_lock);
|
||||
static_branch_enable(&interrupt_exit_not_reentrant);
|
||||
|
||||
stop_machine(__do_rfi_flush_fixups, &types, NULL);
|
||||
@ -497,6 +506,8 @@ void do_rfi_flush_fixups(enum l1d_flush_type types)
|
||||
|
||||
if (stf_exit_reentrant && rfi_exit_reentrant)
|
||||
static_branch_disable(&interrupt_exit_not_reentrant);
|
||||
|
||||
mutex_unlock(&exit_flush_lock);
|
||||
}
|
||||
|
||||
void do_barrier_nospec_fixups_range(bool enable, void *fixup_start, void *fixup_end)
|
||||
|
@ -302,33 +302,51 @@ static nokprobe_inline void do_byte_reverse(void *ptr, int nb)
|
||||
}
|
||||
}
|
||||
|
||||
static nokprobe_inline int read_mem_aligned(unsigned long *dest,
|
||||
unsigned long ea, int nb,
|
||||
struct pt_regs *regs)
|
||||
static __always_inline int
|
||||
__read_mem_aligned(unsigned long *dest, unsigned long ea, int nb, struct pt_regs *regs)
|
||||
{
|
||||
int err = 0;
|
||||
unsigned long x = 0;
|
||||
|
||||
switch (nb) {
|
||||
case 1:
|
||||
err = __get_user(x, (unsigned char __user *) ea);
|
||||
unsafe_get_user(x, (unsigned char __user *)ea, Efault);
|
||||
break;
|
||||
case 2:
|
||||
err = __get_user(x, (unsigned short __user *) ea);
|
||||
unsafe_get_user(x, (unsigned short __user *)ea, Efault);
|
||||
break;
|
||||
case 4:
|
||||
err = __get_user(x, (unsigned int __user *) ea);
|
||||
unsafe_get_user(x, (unsigned int __user *)ea, Efault);
|
||||
break;
|
||||
#ifdef __powerpc64__
|
||||
case 8:
|
||||
err = __get_user(x, (unsigned long __user *) ea);
|
||||
unsafe_get_user(x, (unsigned long __user *)ea, Efault);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
if (!err)
|
||||
*dest = x;
|
||||
else
|
||||
*dest = x;
|
||||
return 0;
|
||||
|
||||
Efault:
|
||||
regs->dar = ea;
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static nokprobe_inline int
|
||||
read_mem_aligned(unsigned long *dest, unsigned long ea, int nb, struct pt_regs *regs)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (is_kernel_addr(ea))
|
||||
return __read_mem_aligned(dest, ea, nb, regs);
|
||||
|
||||
if (user_read_access_begin((void __user *)ea, nb)) {
|
||||
err = __read_mem_aligned(dest, ea, nb, regs);
|
||||
user_read_access_end();
|
||||
} else {
|
||||
err = -EFAULT;
|
||||
regs->dar = ea;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -336,10 +354,8 @@ static nokprobe_inline int read_mem_aligned(unsigned long *dest,
|
||||
* Copy from userspace to a buffer, using the largest possible
|
||||
* aligned accesses, up to sizeof(long).
|
||||
*/
|
||||
static nokprobe_inline int copy_mem_in(u8 *dest, unsigned long ea, int nb,
|
||||
struct pt_regs *regs)
|
||||
static __always_inline int __copy_mem_in(u8 *dest, unsigned long ea, int nb, struct pt_regs *regs)
|
||||
{
|
||||
int err = 0;
|
||||
int c;
|
||||
|
||||
for (; nb > 0; nb -= c) {
|
||||
@ -348,31 +364,46 @@ static nokprobe_inline int copy_mem_in(u8 *dest, unsigned long ea, int nb,
|
||||
c = max_align(nb);
|
||||
switch (c) {
|
||||
case 1:
|
||||
err = __get_user(*dest, (unsigned char __user *) ea);
|
||||
unsafe_get_user(*dest, (u8 __user *)ea, Efault);
|
||||
break;
|
||||
case 2:
|
||||
err = __get_user(*(u16 *)dest,
|
||||
(unsigned short __user *) ea);
|
||||
unsafe_get_user(*(u16 *)dest, (u16 __user *)ea, Efault);
|
||||
break;
|
||||
case 4:
|
||||
err = __get_user(*(u32 *)dest,
|
||||
(unsigned int __user *) ea);
|
||||
unsafe_get_user(*(u32 *)dest, (u32 __user *)ea, Efault);
|
||||
break;
|
||||
#ifdef __powerpc64__
|
||||
case 8:
|
||||
err = __get_user(*(unsigned long *)dest,
|
||||
(unsigned long __user *) ea);
|
||||
unsafe_get_user(*(u64 *)dest, (u64 __user *)ea, Efault);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
if (err) {
|
||||
regs->dar = ea;
|
||||
return err;
|
||||
}
|
||||
dest += c;
|
||||
ea += c;
|
||||
}
|
||||
return 0;
|
||||
|
||||
Efault:
|
||||
regs->dar = ea;
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static nokprobe_inline int copy_mem_in(u8 *dest, unsigned long ea, int nb, struct pt_regs *regs)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (is_kernel_addr(ea))
|
||||
return __copy_mem_in(dest, ea, nb, regs);
|
||||
|
||||
if (user_read_access_begin((void __user *)ea, nb)) {
|
||||
err = __copy_mem_in(dest, ea, nb, regs);
|
||||
user_read_access_end();
|
||||
} else {
|
||||
err = -EFAULT;
|
||||
regs->dar = ea;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static nokprobe_inline int read_mem_unaligned(unsigned long *dest,
|
||||
@ -410,30 +441,48 @@ static int read_mem(unsigned long *dest, unsigned long ea, int nb,
|
||||
}
|
||||
NOKPROBE_SYMBOL(read_mem);
|
||||
|
||||
static nokprobe_inline int write_mem_aligned(unsigned long val,
|
||||
unsigned long ea, int nb,
|
||||
struct pt_regs *regs)
|
||||
static __always_inline int
|
||||
__write_mem_aligned(unsigned long val, unsigned long ea, int nb, struct pt_regs *regs)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
switch (nb) {
|
||||
case 1:
|
||||
err = __put_user(val, (unsigned char __user *) ea);
|
||||
unsafe_put_user(val, (unsigned char __user *)ea, Efault);
|
||||
break;
|
||||
case 2:
|
||||
err = __put_user(val, (unsigned short __user *) ea);
|
||||
unsafe_put_user(val, (unsigned short __user *)ea, Efault);
|
||||
break;
|
||||
case 4:
|
||||
err = __put_user(val, (unsigned int __user *) ea);
|
||||
unsafe_put_user(val, (unsigned int __user *)ea, Efault);
|
||||
break;
|
||||
#ifdef __powerpc64__
|
||||
case 8:
|
||||
err = __put_user(val, (unsigned long __user *) ea);
|
||||
unsafe_put_user(val, (unsigned long __user *)ea, Efault);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
if (err)
|
||||
return 0;
|
||||
|
||||
Efault:
|
||||
regs->dar = ea;
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static nokprobe_inline int
|
||||
write_mem_aligned(unsigned long val, unsigned long ea, int nb, struct pt_regs *regs)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (is_kernel_addr(ea))
|
||||
return __write_mem_aligned(val, ea, nb, regs);
|
||||
|
||||
if (user_write_access_begin((void __user *)ea, nb)) {
|
||||
err = __write_mem_aligned(val, ea, nb, regs);
|
||||
user_write_access_end();
|
||||
} else {
|
||||
err = -EFAULT;
|
||||
regs->dar = ea;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -441,10 +490,8 @@ static nokprobe_inline int write_mem_aligned(unsigned long val,
|
||||
* Copy from a buffer to userspace, using the largest possible
|
||||
* aligned accesses, up to sizeof(long).
|
||||
*/
|
||||
static nokprobe_inline int copy_mem_out(u8 *dest, unsigned long ea, int nb,
|
||||
struct pt_regs *regs)
|
||||
static nokprobe_inline int __copy_mem_out(u8 *dest, unsigned long ea, int nb, struct pt_regs *regs)
|
||||
{
|
||||
int err = 0;
|
||||
int c;
|
||||
|
||||
for (; nb > 0; nb -= c) {
|
||||
@ -453,31 +500,46 @@ static nokprobe_inline int copy_mem_out(u8 *dest, unsigned long ea, int nb,
|
||||
c = max_align(nb);
|
||||
switch (c) {
|
||||
case 1:
|
||||
err = __put_user(*dest, (unsigned char __user *) ea);
|
||||
unsafe_put_user(*dest, (u8 __user *)ea, Efault);
|
||||
break;
|
||||
case 2:
|
||||
err = __put_user(*(u16 *)dest,
|
||||
(unsigned short __user *) ea);
|
||||
unsafe_put_user(*(u16 *)dest, (u16 __user *)ea, Efault);
|
||||
break;
|
||||
case 4:
|
||||
err = __put_user(*(u32 *)dest,
|
||||
(unsigned int __user *) ea);
|
||||
unsafe_put_user(*(u32 *)dest, (u32 __user *)ea, Efault);
|
||||
break;
|
||||
#ifdef __powerpc64__
|
||||
case 8:
|
||||
err = __put_user(*(unsigned long *)dest,
|
||||
(unsigned long __user *) ea);
|
||||
unsafe_put_user(*(u64 *)dest, (u64 __user *)ea, Efault);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
if (err) {
|
||||
regs->dar = ea;
|
||||
return err;
|
||||
}
|
||||
dest += c;
|
||||
ea += c;
|
||||
}
|
||||
return 0;
|
||||
|
||||
Efault:
|
||||
regs->dar = ea;
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static nokprobe_inline int copy_mem_out(u8 *dest, unsigned long ea, int nb, struct pt_regs *regs)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (is_kernel_addr(ea))
|
||||
return __copy_mem_out(dest, ea, nb, regs);
|
||||
|
||||
if (user_write_access_begin((void __user *)ea, nb)) {
|
||||
err = __copy_mem_out(dest, ea, nb, regs);
|
||||
user_write_access_end();
|
||||
} else {
|
||||
err = -EFAULT;
|
||||
regs->dar = ea;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static nokprobe_inline int write_mem_unaligned(unsigned long val,
|
||||
@ -986,10 +1048,24 @@ static nokprobe_inline int do_vsx_store(struct instruction_op *op,
|
||||
}
|
||||
#endif /* CONFIG_VSX */
|
||||
|
||||
static int __emulate_dcbz(unsigned long ea)
|
||||
{
|
||||
unsigned long i;
|
||||
unsigned long size = l1_dcache_bytes();
|
||||
|
||||
for (i = 0; i < size; i += sizeof(long))
|
||||
unsafe_put_user(0, (unsigned long __user *)(ea + i), Efault);
|
||||
|
||||
return 0;
|
||||
|
||||
Efault:
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
int emulate_dcbz(unsigned long ea, struct pt_regs *regs)
|
||||
{
|
||||
int err;
|
||||
unsigned long i, size;
|
||||
unsigned long size;
|
||||
|
||||
#ifdef __powerpc64__
|
||||
size = ppc64_caches.l1d.block_size;
|
||||
@ -1001,14 +1077,21 @@ int emulate_dcbz(unsigned long ea, struct pt_regs *regs)
|
||||
ea &= ~(size - 1);
|
||||
if (!address_ok(regs, ea, size))
|
||||
return -EFAULT;
|
||||
for (i = 0; i < size; i += sizeof(long)) {
|
||||
err = __put_user(0, (unsigned long __user *) (ea + i));
|
||||
if (err) {
|
||||
regs->dar = ea;
|
||||
return err;
|
||||
}
|
||||
|
||||
if (is_kernel_addr(ea)) {
|
||||
err = __emulate_dcbz(ea);
|
||||
} else if (user_write_access_begin((void __user *)ea, size)) {
|
||||
err = __emulate_dcbz(ea);
|
||||
user_write_access_end();
|
||||
} else {
|
||||
err = -EFAULT;
|
||||
}
|
||||
return 0;
|
||||
|
||||
if (err)
|
||||
regs->dar = ea;
|
||||
|
||||
|
||||
return err;
|
||||
}
|
||||
NOKPROBE_SYMBOL(emulate_dcbz);
|
||||
|
||||
|
@ -1988,7 +1988,7 @@ static void kernel_unmap_linear_page(unsigned long vaddr, unsigned long lmi)
|
||||
mmu_kernel_ssize, 0);
|
||||
}
|
||||
|
||||
void __kernel_map_pages(struct page *page, int numpages, int enable)
|
||||
void hash__kernel_map_pages(struct page *page, int numpages, int enable)
|
||||
{
|
||||
unsigned long flags, vaddr, lmi;
|
||||
int i;
|
||||
|
@ -920,6 +920,13 @@ void __meminit radix__vmemmap_remove_mapping(unsigned long start, unsigned long
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DEBUG_PAGEALLOC
|
||||
void radix__kernel_map_pages(struct page *page, int numpages, int enable)
|
||||
{
|
||||
pr_warn_once("DEBUG_PAGEALLOC not supported in radix mode\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
|
||||
|
||||
unsigned long radix__pmd_hugepage_update(struct mm_struct *mm, unsigned long addr,
|
||||
|
@ -20,8 +20,8 @@
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/rtas.h>
|
||||
#include <asm/kasan.h>
|
||||
#include <asm/sparsemem.h>
|
||||
#include <asm/svm.h>
|
||||
#include <asm/mmzone.h>
|
||||
|
||||
#include <mm/mmu_decl.h>
|
||||
|
||||
@ -256,7 +256,7 @@ void __init mem_init(void)
|
||||
#endif
|
||||
|
||||
high_memory = (void *) __va(max_low_pfn * PAGE_SIZE);
|
||||
set_max_mapnr(max_pfn);
|
||||
set_max_mapnr(max_low_pfn);
|
||||
|
||||
kasan_late_init();
|
||||
|
||||
|
@ -126,7 +126,7 @@ unsigned long mmu_mapin_ram(unsigned long base, unsigned long top);
|
||||
|
||||
#ifdef CONFIG_PPC_FSL_BOOK3E
|
||||
extern unsigned long map_mem_in_cams(unsigned long ram, int max_cam_idx,
|
||||
bool dryrun);
|
||||
bool dryrun, bool init);
|
||||
extern unsigned long calc_cam_sz(unsigned long ram, unsigned long virt,
|
||||
phys_addr_t phys);
|
||||
#ifdef CONFIG_PPC32
|
||||
@ -168,7 +168,7 @@ static inline phys_addr_t v_block_mapped(unsigned long va) { return 0; }
|
||||
static inline unsigned long p_block_mapped(phys_addr_t pa) { return 0; }
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_PPC_BOOK3S_32) || defined(CONFIG_PPC_8xx)
|
||||
#if defined(CONFIG_PPC_BOOK3S_32) || defined(CONFIG_PPC_8xx) || defined(CONFIG_PPC_FSL_BOOK3E)
|
||||
void mmu_mark_initmem_nx(void);
|
||||
void mmu_mark_rodata_ro(void);
|
||||
#else
|
||||
|
@ -7,7 +7,7 @@ obj-$(CONFIG_PPC_BOOK3E_64) += tlb_low_64e.o book3e_pgtable.o
|
||||
obj-$(CONFIG_40x) += 40x.o
|
||||
obj-$(CONFIG_44x) += 44x.o
|
||||
obj-$(CONFIG_PPC_8xx) += 8xx.o
|
||||
obj-$(CONFIG_PPC_FSL_BOOK3E) += fsl_booke.o
|
||||
obj-$(CONFIG_PPC_FSL_BOOK3E) += fsl_book3e.o
|
||||
obj-$(CONFIG_RANDOMIZE_BASE) += kaslr_booke.o
|
||||
ifdef CONFIG_HUGETLB_PAGE
|
||||
obj-$(CONFIG_PPC_FSL_BOOK3E) += book3e_hugetlbpage.o
|
||||
@ -16,4 +16,4 @@ endif
|
||||
# Disable kcov instrumentation on sensitive code
|
||||
# This is necessary for booting with kcov enabled on book3e machines
|
||||
KCOV_INSTRUMENT_tlb.o := n
|
||||
KCOV_INSTRUMENT_fsl_booke.o := n
|
||||
KCOV_INSTRUMENT_fsl_book3e.o := n
|
||||
|
@ -122,15 +122,18 @@ static void settlbcam(int index, unsigned long virt, phys_addr_t phys,
|
||||
TLBCAM[index].MAS2 |= (flags & _PAGE_GUARDED) ? MAS2_G : 0;
|
||||
TLBCAM[index].MAS2 |= (flags & _PAGE_ENDIAN) ? MAS2_E : 0;
|
||||
|
||||
TLBCAM[index].MAS3 = (phys & MAS3_RPN) | MAS3_SX | MAS3_SR;
|
||||
TLBCAM[index].MAS3 |= ((flags & _PAGE_RW) ? MAS3_SW : 0);
|
||||
TLBCAM[index].MAS3 = (phys & MAS3_RPN) | MAS3_SR;
|
||||
TLBCAM[index].MAS3 |= (flags & _PAGE_RW) ? MAS3_SW : 0;
|
||||
if (mmu_has_feature(MMU_FTR_BIG_PHYS))
|
||||
TLBCAM[index].MAS7 = (u64)phys >> 32;
|
||||
|
||||
/* Below is unlikely -- only for large user pages or similar */
|
||||
if (pte_user(__pte(flags))) {
|
||||
TLBCAM[index].MAS3 |= MAS3_UX | MAS3_UR;
|
||||
TLBCAM[index].MAS3 |= ((flags & _PAGE_RW) ? MAS3_UW : 0);
|
||||
TLBCAM[index].MAS3 |= MAS3_UR;
|
||||
TLBCAM[index].MAS3 |= (flags & _PAGE_EXEC) ? MAS3_UX : 0;
|
||||
TLBCAM[index].MAS3 |= (flags & _PAGE_RW) ? MAS3_UW : 0;
|
||||
} else {
|
||||
TLBCAM[index].MAS3 |= (flags & _PAGE_EXEC) ? MAS3_SX : 0;
|
||||
}
|
||||
|
||||
tlbcam_addrs[index].start = virt;
|
||||
@ -165,19 +168,38 @@ unsigned long calc_cam_sz(unsigned long ram, unsigned long virt,
|
||||
|
||||
static unsigned long map_mem_in_cams_addr(phys_addr_t phys, unsigned long virt,
|
||||
unsigned long ram, int max_cam_idx,
|
||||
bool dryrun)
|
||||
bool dryrun, bool init)
|
||||
{
|
||||
int i;
|
||||
unsigned long amount_mapped = 0;
|
||||
unsigned long boundary;
|
||||
|
||||
if (strict_kernel_rwx_enabled())
|
||||
boundary = (unsigned long)(_sinittext - _stext);
|
||||
else
|
||||
boundary = ram;
|
||||
|
||||
/* Calculate CAM values */
|
||||
for (i = 0; ram && i < max_cam_idx; i++) {
|
||||
for (i = 0; boundary && i < max_cam_idx; i++) {
|
||||
unsigned long cam_sz;
|
||||
pgprot_t prot = init ? PAGE_KERNEL_X : PAGE_KERNEL_ROX;
|
||||
|
||||
cam_sz = calc_cam_sz(boundary, virt, phys);
|
||||
if (!dryrun)
|
||||
settlbcam(i, virt, phys, cam_sz, pgprot_val(prot), 0);
|
||||
|
||||
boundary -= cam_sz;
|
||||
amount_mapped += cam_sz;
|
||||
virt += cam_sz;
|
||||
phys += cam_sz;
|
||||
}
|
||||
for (ram -= amount_mapped; ram && i < max_cam_idx; i++) {
|
||||
unsigned long cam_sz;
|
||||
pgprot_t prot = init ? PAGE_KERNEL_X : PAGE_KERNEL;
|
||||
|
||||
cam_sz = calc_cam_sz(ram, virt, phys);
|
||||
if (!dryrun)
|
||||
settlbcam(i, virt, phys, cam_sz,
|
||||
pgprot_val(PAGE_KERNEL_X), 0);
|
||||
settlbcam(i, virt, phys, cam_sz, pgprot_val(prot), 0);
|
||||
|
||||
ram -= cam_sz;
|
||||
amount_mapped += cam_sz;
|
||||
@ -188,8 +210,13 @@ static unsigned long map_mem_in_cams_addr(phys_addr_t phys, unsigned long virt,
|
||||
if (dryrun)
|
||||
return amount_mapped;
|
||||
|
||||
loadcam_multi(0, i, max_cam_idx);
|
||||
tlbcam_index = i;
|
||||
if (init) {
|
||||
loadcam_multi(0, i, max_cam_idx);
|
||||
tlbcam_index = i;
|
||||
} else {
|
||||
loadcam_multi(0, i, 0);
|
||||
WARN_ON(i > tlbcam_index);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
get_paca()->tcd.esel_next = i;
|
||||
@ -200,12 +227,12 @@ static unsigned long map_mem_in_cams_addr(phys_addr_t phys, unsigned long virt,
|
||||
return amount_mapped;
|
||||
}
|
||||
|
||||
unsigned long map_mem_in_cams(unsigned long ram, int max_cam_idx, bool dryrun)
|
||||
unsigned long map_mem_in_cams(unsigned long ram, int max_cam_idx, bool dryrun, bool init)
|
||||
{
|
||||
unsigned long virt = PAGE_OFFSET;
|
||||
phys_addr_t phys = memstart_addr;
|
||||
|
||||
return map_mem_in_cams_addr(phys, virt, ram, max_cam_idx, dryrun);
|
||||
return map_mem_in_cams_addr(phys, virt, ram, max_cam_idx, dryrun, init);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PPC32
|
||||
@ -246,7 +273,7 @@ void __init adjust_total_lowmem(void)
|
||||
ram = min((phys_addr_t)__max_low_memory, (phys_addr_t)total_lowmem);
|
||||
|
||||
i = switch_to_as1();
|
||||
__max_low_memory = map_mem_in_cams(ram, CONFIG_LOWMEM_CAM_NUM, false);
|
||||
__max_low_memory = map_mem_in_cams(ram, CONFIG_LOWMEM_CAM_NUM, false, true);
|
||||
restore_to_as0(i, 0, 0, 1);
|
||||
|
||||
pr_info("Memory CAM mapping: ");
|
||||
@ -258,6 +285,25 @@ void __init adjust_total_lowmem(void)
|
||||
memblock_set_current_limit(memstart_addr + __max_low_memory);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_STRICT_KERNEL_RWX
|
||||
void mmu_mark_rodata_ro(void)
|
||||
{
|
||||
/* Everything is done in mmu_mark_initmem_nx() */
|
||||
}
|
||||
#endif
|
||||
|
||||
void mmu_mark_initmem_nx(void)
|
||||
{
|
||||
unsigned long remapped;
|
||||
|
||||
if (!strict_kernel_rwx_enabled())
|
||||
return;
|
||||
|
||||
remapped = map_mem_in_cams(__max_low_memory, CONFIG_LOWMEM_CAM_NUM, false, false);
|
||||
|
||||
WARN_ON(__max_low_memory != remapped);
|
||||
}
|
||||
|
||||
void setup_initial_memory_limit(phys_addr_t first_memblock_base,
|
||||
phys_addr_t first_memblock_size)
|
||||
{
|
||||
@ -317,11 +363,11 @@ notrace void __init relocate_init(u64 dt_ptr, phys_addr_t start)
|
||||
/* map a 64M area for the second relocation */
|
||||
if (memstart_addr > start)
|
||||
map_mem_in_cams(0x4000000, CONFIG_LOWMEM_CAM_NUM,
|
||||
false);
|
||||
false, true);
|
||||
else
|
||||
map_mem_in_cams_addr(start, PAGE_OFFSET + offset,
|
||||
0x4000000, CONFIG_LOWMEM_CAM_NUM,
|
||||
false);
|
||||
false, true);
|
||||
restore_to_as0(n, offset, __va(dt_ptr), 1);
|
||||
/* We should never reach here */
|
||||
panic("Relocation error");
|
@ -314,7 +314,7 @@ static unsigned long __init kaslr_choose_location(void *dt_ptr, phys_addr_t size
|
||||
pr_warn("KASLR: No safe seed for randomizing the kernel base.\n");
|
||||
|
||||
ram = min_t(phys_addr_t, __max_low_memory, size);
|
||||
ram = map_mem_in_cams(ram, CONFIG_LOWMEM_CAM_NUM, true);
|
||||
ram = map_mem_in_cams(ram, CONFIG_LOWMEM_CAM_NUM, true, false);
|
||||
linear_sz = min_t(unsigned long, ram, SZ_512M);
|
||||
|
||||
/* If the linear size is smaller than 64M, do not randmize */
|
||||
|
@ -185,6 +185,7 @@ EXPORT_PER_CPU_SYMBOL(next_tlbcam_idx);
|
||||
* processor
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_PPC_8xx
|
||||
/*
|
||||
* These are the base non-SMP variants of page and mm flushing
|
||||
*/
|
||||
@ -218,6 +219,7 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
|
||||
mmu_get_tsize(mmu_virtual_psize), 0);
|
||||
}
|
||||
EXPORT_SYMBOL(local_flush_tlb_page);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* And here are the SMP non-local implementations
|
||||
@ -643,7 +645,7 @@ static void early_init_this_mmu(void)
|
||||
|
||||
if (map)
|
||||
linear_map_top = map_mem_in_cams(linear_map_top,
|
||||
num_cams, false);
|
||||
num_cams, true, true);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -764,7 +766,7 @@ void setup_initial_memory_limit(phys_addr_t first_memblock_base,
|
||||
num_cams = (mfspr(SPRN_TLB1CFG) & TLBnCFG_N_ENTRY) / 4;
|
||||
|
||||
linear_sz = map_mem_in_cams(first_memblock_size, num_cams,
|
||||
true);
|
||||
false, true);
|
||||
|
||||
ppc64_rma_size = min_t(u64, linear_sz, 0x40000000);
|
||||
} else
|
||||
|
@ -369,7 +369,7 @@ _GLOBAL(_tlbivax_bcast)
|
||||
* extern void loadcam_entry(unsigned int index)
|
||||
*
|
||||
* Load TLBCAM[index] entry in to the L2 CAM MMU
|
||||
* Must preserve r7, r8, r9, r10 and r11
|
||||
* Must preserve r7, r8, r9, r10, r11, r12
|
||||
*/
|
||||
_GLOBAL(loadcam_entry)
|
||||
mflr r5
|
||||
@ -401,7 +401,7 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_BIG_PHYS)
|
||||
*
|
||||
* r3 = first entry to write
|
||||
* r4 = number of entries to write
|
||||
* r5 = temporary tlb entry
|
||||
* r5 = temporary tlb entry (0 means no switch to AS1)
|
||||
*/
|
||||
_GLOBAL(loadcam_multi)
|
||||
mflr r8
|
||||
@ -409,6 +409,8 @@ _GLOBAL(loadcam_multi)
|
||||
mfmsr r11
|
||||
andi. r11,r11,MSR_IS
|
||||
bne 10f
|
||||
mr. r12, r5
|
||||
beq 10f
|
||||
|
||||
/*
|
||||
* Set up temporary TLB entry that is the same as what we're
|
||||
@ -446,6 +448,8 @@ _GLOBAL(loadcam_multi)
|
||||
/* Don't return to AS=0 if we were in AS=1 at function start */
|
||||
andi. r11,r11,MSR_IS
|
||||
bne 3f
|
||||
cmpwi r12, 0
|
||||
beq 3f
|
||||
|
||||
/* Return to AS=0 and clear the temporary entry */
|
||||
mfmsr r6
|
||||
|
@ -222,7 +222,7 @@ tlb_miss_kernel_bolted:
|
||||
|
||||
tlb_miss_fault_bolted:
|
||||
/* We need to check if it was an instruction miss */
|
||||
andi. r10,r11,_PAGE_EXEC|_PAGE_BAP_SX
|
||||
andi. r10,r11,_PAGE_BAP_UX|_PAGE_BAP_SX
|
||||
bne itlb_miss_fault_bolted
|
||||
dtlb_miss_fault_bolted:
|
||||
tlb_epilog_bolted
|
||||
@ -239,7 +239,7 @@ itlb_miss_fault_bolted:
|
||||
srdi r15,r16,60 /* get region */
|
||||
bne- itlb_miss_fault_bolted
|
||||
|
||||
li r11,_PAGE_PRESENT|_PAGE_EXEC /* Base perm */
|
||||
li r11,_PAGE_PRESENT|_PAGE_BAP_UX /* Base perm */
|
||||
|
||||
/* We do the user/kernel test for the PID here along with the RW test
|
||||
*/
|
||||
@ -614,7 +614,7 @@ itlb_miss_fault_e6500:
|
||||
|
||||
/* We do the user/kernel test for the PID here along with the RW test
|
||||
*/
|
||||
li r11,_PAGE_PRESENT|_PAGE_EXEC /* Base perm */
|
||||
li r11,_PAGE_PRESENT|_PAGE_BAP_UX /* Base perm */
|
||||
oris r11,r11,_PAGE_ACCESSED@h
|
||||
|
||||
cmpldi cr0,r15,0 /* Check for user region */
|
||||
@ -734,7 +734,7 @@ normal_tlb_miss_done:
|
||||
|
||||
normal_tlb_miss_access_fault:
|
||||
/* We need to check if it was an instruction miss */
|
||||
andi. r10,r11,_PAGE_EXEC
|
||||
andi. r10,r11,_PAGE_BAP_UX
|
||||
bne 1f
|
||||
ld r14,EX_TLB_DEAR(r12)
|
||||
ld r15,EX_TLB_ESR(r12)
|
||||
|
@ -271,7 +271,7 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_
|
||||
{
|
||||
pmd_t *pmd = pmd_off(mm, addr);
|
||||
pte_basic_t val;
|
||||
pte_basic_t *entry = &ptep->pte;
|
||||
pte_basic_t *entry = (pte_basic_t *)ptep;
|
||||
int num, i;
|
||||
|
||||
/*
|
||||
|
@ -173,7 +173,7 @@ void mark_rodata_ro(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DEBUG_PAGEALLOC
|
||||
#if defined(CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC) && defined(CONFIG_DEBUG_PAGEALLOC)
|
||||
void __kernel_map_pages(struct page *page, int numpages, int enable)
|
||||
{
|
||||
unsigned long addr = (unsigned long)page_address(page);
|
||||
|
@ -241,8 +241,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
|
||||
fp->jited_len = alloclen;
|
||||
|
||||
bpf_flush_icache(bpf_hdr, (u8 *)bpf_hdr + (bpf_hdr->pages * PAGE_SIZE));
|
||||
bpf_jit_binary_lock_ro(bpf_hdr);
|
||||
if (!fp->is_func || extra_pass) {
|
||||
bpf_jit_binary_lock_ro(bpf_hdr);
|
||||
bpf_prog_fill_jited_linfo(fp, addrs);
|
||||
out_addrs:
|
||||
kfree(addrs);
|
||||
|
@ -90,7 +90,11 @@ static u64 get_ext_regs_value(int idx)
|
||||
return mfspr(SPRN_SIER2);
|
||||
case PERF_REG_POWERPC_SIER3:
|
||||
return mfspr(SPRN_SIER3);
|
||||
case PERF_REG_POWERPC_SDAR:
|
||||
return mfspr(SPRN_SDAR);
|
||||
#endif
|
||||
case PERF_REG_POWERPC_SIAR:
|
||||
return mfspr(SPRN_SIAR);
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
@ -9,10 +9,10 @@
|
||||
/*
|
||||
* Power10 event codes.
|
||||
*/
|
||||
EVENT(PM_RUN_CYC, 0x600f4);
|
||||
EVENT(PM_CYC, 0x600f4);
|
||||
EVENT(PM_DISP_STALL_CYC, 0x100f8);
|
||||
EVENT(PM_EXEC_STALL, 0x30008);
|
||||
EVENT(PM_RUN_INST_CMPL, 0x500fa);
|
||||
EVENT(PM_INST_CMPL, 0x500fa);
|
||||
EVENT(PM_BR_CMPL, 0x4d05e);
|
||||
EVENT(PM_BR_MPRED_CMPL, 0x400f6);
|
||||
EVENT(PM_BR_FIN, 0x2f04a);
|
||||
@ -50,8 +50,8 @@ EVENT(PM_DTLB_MISS, 0x300fc);
|
||||
/* ITLB Reloaded */
|
||||
EVENT(PM_ITLB_MISS, 0x400fc);
|
||||
|
||||
EVENT(PM_RUN_CYC_ALT, 0x0001e);
|
||||
EVENT(PM_RUN_INST_CMPL_ALT, 0x00002);
|
||||
EVENT(PM_CYC_ALT, 0x0001e);
|
||||
EVENT(PM_INST_CMPL_ALT, 0x00002);
|
||||
|
||||
/*
|
||||
* Memory Access Events
|
||||
|
@ -91,8 +91,8 @@ extern u64 PERF_REG_EXTENDED_MASK;
|
||||
|
||||
/* Table of alternatives, sorted by column 0 */
|
||||
static const unsigned int power10_event_alternatives[][MAX_ALT] = {
|
||||
{ PM_RUN_CYC_ALT, PM_RUN_CYC },
|
||||
{ PM_RUN_INST_CMPL_ALT, PM_RUN_INST_CMPL },
|
||||
{ PM_CYC_ALT, PM_CYC },
|
||||
{ PM_INST_CMPL_ALT, PM_INST_CMPL },
|
||||
};
|
||||
|
||||
static int power10_get_alternatives(u64 event, unsigned int flags, u64 alt[])
|
||||
@ -118,8 +118,8 @@ static int power10_check_attr_config(struct perf_event *ev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
GENERIC_EVENT_ATTR(cpu-cycles, PM_RUN_CYC);
|
||||
GENERIC_EVENT_ATTR(instructions, PM_RUN_INST_CMPL);
|
||||
GENERIC_EVENT_ATTR(cpu-cycles, PM_CYC);
|
||||
GENERIC_EVENT_ATTR(instructions, PM_INST_CMPL);
|
||||
GENERIC_EVENT_ATTR(branch-instructions, PM_BR_CMPL);
|
||||
GENERIC_EVENT_ATTR(branch-misses, PM_BR_MPRED_CMPL);
|
||||
GENERIC_EVENT_ATTR(cache-references, PM_LD_REF_L1);
|
||||
@ -148,8 +148,8 @@ CACHE_EVENT_ATTR(dTLB-load-misses, PM_DTLB_MISS);
|
||||
CACHE_EVENT_ATTR(iTLB-load-misses, PM_ITLB_MISS);
|
||||
|
||||
static struct attribute *power10_events_attr_dd1[] = {
|
||||
GENERIC_EVENT_PTR(PM_RUN_CYC),
|
||||
GENERIC_EVENT_PTR(PM_RUN_INST_CMPL),
|
||||
GENERIC_EVENT_PTR(PM_CYC),
|
||||
GENERIC_EVENT_PTR(PM_INST_CMPL),
|
||||
GENERIC_EVENT_PTR(PM_BR_CMPL),
|
||||
GENERIC_EVENT_PTR(PM_BR_MPRED_CMPL),
|
||||
GENERIC_EVENT_PTR(PM_LD_REF_L1),
|
||||
@ -173,8 +173,8 @@ static struct attribute *power10_events_attr_dd1[] = {
|
||||
};
|
||||
|
||||
static struct attribute *power10_events_attr[] = {
|
||||
GENERIC_EVENT_PTR(PM_RUN_CYC),
|
||||
GENERIC_EVENT_PTR(PM_RUN_INST_CMPL),
|
||||
GENERIC_EVENT_PTR(PM_CYC),
|
||||
GENERIC_EVENT_PTR(PM_INST_CMPL),
|
||||
GENERIC_EVENT_PTR(PM_BR_FIN),
|
||||
GENERIC_EVENT_PTR(PM_MPRED_BR_FIN),
|
||||
GENERIC_EVENT_PTR(PM_LD_REF_L1),
|
||||
@ -271,8 +271,8 @@ static const struct attribute_group *power10_pmu_attr_groups[] = {
|
||||
};
|
||||
|
||||
static int power10_generic_events_dd1[] = {
|
||||
[PERF_COUNT_HW_CPU_CYCLES] = PM_RUN_CYC,
|
||||
[PERF_COUNT_HW_INSTRUCTIONS] = PM_RUN_INST_CMPL,
|
||||
[PERF_COUNT_HW_CPU_CYCLES] = PM_CYC,
|
||||
[PERF_COUNT_HW_INSTRUCTIONS] = PM_INST_CMPL,
|
||||
[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = PM_BR_CMPL,
|
||||
[PERF_COUNT_HW_BRANCH_MISSES] = PM_BR_MPRED_CMPL,
|
||||
[PERF_COUNT_HW_CACHE_REFERENCES] = PM_LD_REF_L1,
|
||||
@ -280,8 +280,8 @@ static int power10_generic_events_dd1[] = {
|
||||
};
|
||||
|
||||
static int power10_generic_events[] = {
|
||||
[PERF_COUNT_HW_CPU_CYCLES] = PM_RUN_CYC,
|
||||
[PERF_COUNT_HW_INSTRUCTIONS] = PM_RUN_INST_CMPL,
|
||||
[PERF_COUNT_HW_CPU_CYCLES] = PM_CYC,
|
||||
[PERF_COUNT_HW_INSTRUCTIONS] = PM_INST_CMPL,
|
||||
[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = PM_BR_FIN,
|
||||
[PERF_COUNT_HW_BRANCH_MISSES] = PM_MPRED_BR_FIN,
|
||||
[PERF_COUNT_HW_CACHE_REFERENCES] = PM_LD_REF_L1,
|
||||
@ -548,6 +548,24 @@ static u64 power10_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
|
||||
|
||||
#undef C
|
||||
|
||||
/*
|
||||
* Set the MMCR0[CC56RUN] bit to enable counting for
|
||||
* PMC5 and PMC6 regardless of the state of CTRL[RUN],
|
||||
* so that we can use counters 5 and 6 as PM_INST_CMPL and
|
||||
* PM_CYC.
|
||||
*/
|
||||
static int power10_compute_mmcr(u64 event[], int n_ev,
|
||||
unsigned int hwc[], struct mmcr_regs *mmcr,
|
||||
struct perf_event *pevents[], u32 flags)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = isa207_compute_mmcr(event, n_ev, hwc, mmcr, pevents, flags);
|
||||
if (!ret)
|
||||
mmcr->mmcr0 |= MMCR0_C56RUN;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct power_pmu power10_pmu = {
|
||||
.name = "POWER10",
|
||||
.n_counter = MAX_PMU_COUNTERS,
|
||||
@ -555,7 +573,7 @@ static struct power_pmu power10_pmu = {
|
||||
.test_adder = ISA207_TEST_ADDER,
|
||||
.group_constraint_mask = CNST_CACHE_PMC4_MASK,
|
||||
.group_constraint_val = CNST_CACHE_PMC4_VAL,
|
||||
.compute_mmcr = isa207_compute_mmcr,
|
||||
.compute_mmcr = power10_compute_mmcr,
|
||||
.config_bhrb = power10_config_bhrb,
|
||||
.bhrb_filter_map = power10_bhrb_filter_map,
|
||||
.get_constraint = isa207_get_constraint,
|
||||
|
@ -208,6 +208,7 @@ static void node_irq_request(const char *compat, irq_handler_t errirq_handler)
|
||||
if (irq == NO_IRQ) {
|
||||
pr_err("device tree node %pOFn is missing a interrupt",
|
||||
np);
|
||||
of_node_put(np);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -215,6 +216,7 @@ static void node_irq_request(const char *compat, irq_handler_t errirq_handler)
|
||||
if (rc) {
|
||||
pr_err("fsp_of_probe: request_irq failed: np=%pOF rc=%d",
|
||||
np, rc);
|
||||
of_node_put(np);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -219,7 +219,7 @@ static int board_rev = -1;
|
||||
static int __init ppc47x_get_board_rev(void)
|
||||
{
|
||||
int reg;
|
||||
u8 *fpga;
|
||||
u8 __iomem *fpga;
|
||||
struct device_node *np = NULL;
|
||||
|
||||
if (of_machine_is_compatible("ibm,currituck")) {
|
||||
@ -233,7 +233,7 @@ static int __init ppc47x_get_board_rev(void)
|
||||
if (!np)
|
||||
goto fail;
|
||||
|
||||
fpga = (u8 *) of_iomap(np, 0);
|
||||
fpga = of_iomap(np, 0);
|
||||
of_node_put(np);
|
||||
if (!fpga)
|
||||
goto fail;
|
||||
|
@ -135,11 +135,10 @@ static int mcu_gpiochip_add(struct mcu *mcu)
|
||||
return gpiochip_add_data(gc, mcu);
|
||||
}
|
||||
|
||||
static int mcu_gpiochip_remove(struct mcu *mcu)
|
||||
static void mcu_gpiochip_remove(struct mcu *mcu)
|
||||
{
|
||||
kfree(mcu->gc.label);
|
||||
gpiochip_remove(&mcu->gc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mcu_probe(struct i2c_client *client)
|
||||
@ -198,9 +197,7 @@ static int mcu_remove(struct i2c_client *client)
|
||||
glob_mcu = NULL;
|
||||
}
|
||||
|
||||
ret = mcu_gpiochip_remove(mcu);
|
||||
if (ret)
|
||||
return ret;
|
||||
mcu_gpiochip_remove(mcu);
|
||||
kfree(mcu);
|
||||
return 0;
|
||||
}
|
||||
|
@ -3,7 +3,9 @@
|
||||
# Makefile for the PowerPC 85xx linux kernel.
|
||||
#
|
||||
obj-$(CONFIG_SMP) += smp.o
|
||||
obj-$(CONFIG_FSL_PMC) += mpc85xx_pm_ops.o
|
||||
ifneq ($(CONFIG_FSL_CORENET_RCPM),y)
|
||||
obj-$(CONFIG_SMP) += mpc85xx_pm_ops.o
|
||||
endif
|
||||
|
||||
obj-y += common.o
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
static struct ccsr_guts __iomem *guts;
|
||||
|
||||
#ifdef CONFIG_FSL_PMC
|
||||
static void mpc85xx_irq_mask(int cpu)
|
||||
{
|
||||
|
||||
@ -49,6 +50,7 @@ static void mpc85xx_cpu_up_prepare(int cpu)
|
||||
{
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
static void mpc85xx_freeze_time_base(bool freeze)
|
||||
{
|
||||
@ -76,10 +78,12 @@ static const struct of_device_id mpc85xx_smp_guts_ids[] = {
|
||||
|
||||
static const struct fsl_pm_ops mpc85xx_pm_ops = {
|
||||
.freeze_time_base = mpc85xx_freeze_time_base,
|
||||
#ifdef CONFIG_FSL_PMC
|
||||
.irq_mask = mpc85xx_irq_mask,
|
||||
.irq_unmask = mpc85xx_irq_unmask,
|
||||
.cpu_die = mpc85xx_cpu_die,
|
||||
.cpu_up_prepare = mpc85xx_cpu_up_prepare,
|
||||
#endif
|
||||
};
|
||||
|
||||
int __init mpc85xx_setup_pmc(void)
|
||||
@ -94,9 +98,8 @@ int __init mpc85xx_setup_pmc(void)
|
||||
pr_err("Could not map guts node address\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
qoriq_pm_ops = &mpc85xx_pm_ops;
|
||||
}
|
||||
|
||||
qoriq_pm_ops = &mpc85xx_pm_ops;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -40,7 +40,6 @@ struct epapr_spin_table {
|
||||
u32 pir;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
static u64 timebase;
|
||||
static int tb_req;
|
||||
static int tb_valid;
|
||||
@ -112,6 +111,7 @@ static void mpc85xx_take_timebase(void)
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
static void smp_85xx_cpu_offline_self(void)
|
||||
{
|
||||
unsigned int cpu = smp_processor_id();
|
||||
@ -495,21 +495,21 @@ void __init mpc85xx_smp_init(void)
|
||||
smp_85xx_ops.probe = NULL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
#ifdef CONFIG_FSL_CORENET_RCPM
|
||||
/* Assign a value to qoriq_pm_ops on PPC_E500MC */
|
||||
fsl_rcpm_init();
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FSL_PMC
|
||||
#else
|
||||
/* Assign a value to qoriq_pm_ops on !PPC_E500MC */
|
||||
mpc85xx_setup_pmc();
|
||||
#endif
|
||||
if (qoriq_pm_ops) {
|
||||
smp_85xx_ops.give_timebase = mpc85xx_give_timebase;
|
||||
smp_85xx_ops.take_timebase = mpc85xx_take_timebase;
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
smp_85xx_ops.cpu_offline_self = smp_85xx_cpu_offline_self;
|
||||
smp_85xx_ops.cpu_die = qoriq_cpu_kill;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
smp_ops = &smp_85xx_ops;
|
||||
|
||||
#ifdef CONFIG_KEXEC_CORE
|
||||
|
@ -303,7 +303,7 @@ static int coproc_ioc_tx_win_open(struct file *fp, unsigned long arg)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!cp_inst->coproc->vops && !cp_inst->coproc->vops->open_win) {
|
||||
if (!cp_inst->coproc->vops || !cp_inst->coproc->vops->open_win) {
|
||||
pr_err("VAS API is not registered\n");
|
||||
return -EACCES;
|
||||
}
|
||||
@ -373,7 +373,7 @@ static int coproc_mmap(struct file *fp, struct vm_area_struct *vma)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!cp_inst->coproc->vops && !cp_inst->coproc->vops->paste_addr) {
|
||||
if (!cp_inst->coproc->vops || !cp_inst->coproc->vops->paste_addr) {
|
||||
pr_err("%s(): VAS API is not registered\n", __func__);
|
||||
return -EACCES;
|
||||
}
|
||||
|
@ -27,7 +27,6 @@ extern void pmac_nvram_update(void);
|
||||
extern unsigned char pmac_nvram_read_byte(int addr);
|
||||
extern void pmac_nvram_write_byte(int addr, unsigned char val);
|
||||
extern void pmac_pcibios_after_init(void);
|
||||
extern int of_show_percpuinfo(struct seq_file *m, int i);
|
||||
|
||||
extern void pmac_setup_pci_dma(void);
|
||||
extern void pmac_check_ht_link(void);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user