diff options
253 files changed, 6305 insertions, 3400 deletions
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 5b5f1ba76bba..47ca5cda0eef 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt | |||
@@ -2428,7 +2428,7 @@ | |||
2428 | seconds. Use this parameter to check at some | 2428 | seconds. Use this parameter to check at some |
2429 | other rate. 0 disables periodic checking. | 2429 | other rate. 0 disables periodic checking. |
2430 | 2430 | ||
2431 | memtest= [KNL,X86,ARM] Enable memtest | 2431 | memtest= [KNL,X86,ARM,PPC] Enable memtest |
2432 | Format: <integer> | 2432 | Format: <integer> |
2433 | default : 0 <disable> | 2433 | default : 0 <disable> |
2434 | Specifies the number of memtest passes to be | 2434 | Specifies the number of memtest passes to be |
diff --git a/arch/m68k/mac/misc.c b/arch/m68k/mac/misc.c index 1b083c500b9a..ebb3b6d169ea 100644 --- a/arch/m68k/mac/misc.c +++ b/arch/m68k/mac/misc.c | |||
@@ -37,35 +37,6 @@ | |||
37 | static void (*rom_reset)(void); | 37 | static void (*rom_reset)(void); |
38 | 38 | ||
39 | #ifdef CONFIG_ADB_CUDA | 39 | #ifdef CONFIG_ADB_CUDA |
40 | static time64_t cuda_read_time(void) | ||
41 | { | ||
42 | struct adb_request req; | ||
43 | time64_t time; | ||
44 | |||
45 | if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME) < 0) | ||
46 | return 0; | ||
47 | while (!req.complete) | ||
48 | cuda_poll(); | ||
49 | |||
50 | time = (u32)((req.reply[3] << 24) | (req.reply[4] << 16) | | ||
51 | (req.reply[5] << 8) | req.reply[6]); | ||
52 | |||
53 | return time - RTC_OFFSET; | ||
54 | } | ||
55 | |||
56 | static void cuda_write_time(time64_t time) | ||
57 | { | ||
58 | struct adb_request req; | ||
59 | u32 data = lower_32_bits(time + RTC_OFFSET); | ||
60 | |||
61 | if (cuda_request(&req, NULL, 6, CUDA_PACKET, CUDA_SET_TIME, | ||
62 | (data >> 24) & 0xFF, (data >> 16) & 0xFF, | ||
63 | (data >> 8) & 0xFF, data & 0xFF) < 0) | ||
64 | return; | ||
65 | while (!req.complete) | ||
66 | cuda_poll(); | ||
67 | } | ||
68 | |||
69 | static __u8 cuda_read_pram(int offset) | 40 | static __u8 cuda_read_pram(int offset) |
70 | { | 41 | { |
71 | struct adb_request req; | 42 | struct adb_request req; |
@@ -91,33 +62,6 @@ static void cuda_write_pram(int offset, __u8 data) | |||
91 | #endif /* CONFIG_ADB_CUDA */ | 62 | #endif /* CONFIG_ADB_CUDA */ |
92 | 63 | ||
93 | #ifdef CONFIG_ADB_PMU | 64 | #ifdef CONFIG_ADB_PMU |
94 | static time64_t pmu_read_time(void) | ||
95 | { | ||
96 | struct adb_request req; | ||
97 | time64_t time; | ||
98 | |||
99 | if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0) | ||
100 | return 0; | ||
101 | pmu_wait_complete(&req); | ||
102 | |||
103 | time = (u32)((req.reply[0] << 24) | (req.reply[1] << 16) | | ||
104 | (req.reply[2] << 8) | req.reply[3]); | ||
105 | |||
106 | return time - RTC_OFFSET; | ||
107 | } | ||
108 | |||
109 | static void pmu_write_time(time64_t time) | ||
110 | { | ||
111 | struct adb_request req; | ||
112 | u32 data = lower_32_bits(time + RTC_OFFSET); | ||
113 | |||
114 | if (pmu_request(&req, NULL, 5, PMU_SET_RTC, | ||
115 | (data >> 24) & 0xFF, (data >> 16) & 0xFF, | ||
116 | (data >> 8) & 0xFF, data & 0xFF) < 0) | ||
117 | return; | ||
118 | pmu_wait_complete(&req); | ||
119 | } | ||
120 | |||
121 | static __u8 pmu_read_pram(int offset) | 65 | static __u8 pmu_read_pram(int offset) |
122 | { | 66 | { |
123 | struct adb_request req; | 67 | struct adb_request req; |
@@ -295,13 +239,17 @@ static time64_t via_read_time(void) | |||
295 | * is basically any machine with Mac II-style ADB. | 239 | * is basically any machine with Mac II-style ADB. |
296 | */ | 240 | */ |
297 | 241 | ||
298 | static void via_write_time(time64_t time) | 242 | static void via_set_rtc_time(struct rtc_time *tm) |
299 | { | 243 | { |
300 | union { | 244 | union { |
301 | __u8 cdata[4]; | 245 | __u8 cdata[4]; |
302 | __u32 idata; | 246 | __u32 idata; |
303 | } data; | 247 | } data; |
304 | __u8 temp; | 248 | __u8 temp; |
249 | time64_t time; | ||
250 | |||
251 | time = mktime64(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, | ||
252 | tm->tm_hour, tm->tm_min, tm->tm_sec); | ||
305 | 253 | ||
306 | /* Clear the write protect bit */ | 254 | /* Clear the write protect bit */ |
307 | 255 | ||
@@ -641,12 +589,12 @@ int mac_hwclk(int op, struct rtc_time *t) | |||
641 | #ifdef CONFIG_ADB_CUDA | 589 | #ifdef CONFIG_ADB_CUDA |
642 | case MAC_ADB_EGRET: | 590 | case MAC_ADB_EGRET: |
643 | case MAC_ADB_CUDA: | 591 | case MAC_ADB_CUDA: |
644 | now = cuda_read_time(); | 592 | now = cuda_get_time(); |
645 | break; | 593 | break; |
646 | #endif | 594 | #endif |
647 | #ifdef CONFIG_ADB_PMU | 595 | #ifdef CONFIG_ADB_PMU |
648 | case MAC_ADB_PB2: | 596 | case MAC_ADB_PB2: |
649 | now = pmu_read_time(); | 597 | now = pmu_get_time(); |
650 | break; | 598 | break; |
651 | #endif | 599 | #endif |
652 | default: | 600 | default: |
@@ -665,24 +613,21 @@ int mac_hwclk(int op, struct rtc_time *t) | |||
665 | __func__, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, | 613 | __func__, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, |
666 | t->tm_hour, t->tm_min, t->tm_sec); | 614 | t->tm_hour, t->tm_min, t->tm_sec); |
667 | 615 | ||
668 | now = mktime64(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, | ||
669 | t->tm_hour, t->tm_min, t->tm_sec); | ||
670 | |||
671 | switch (macintosh_config->adb_type) { | 616 | switch (macintosh_config->adb_type) { |
672 | case MAC_ADB_IOP: | 617 | case MAC_ADB_IOP: |
673 | case MAC_ADB_II: | 618 | case MAC_ADB_II: |
674 | case MAC_ADB_PB1: | 619 | case MAC_ADB_PB1: |
675 | via_write_time(now); | 620 | via_set_rtc_time(t); |
676 | break; | 621 | break; |
677 | #ifdef CONFIG_ADB_CUDA | 622 | #ifdef CONFIG_ADB_CUDA |
678 | case MAC_ADB_EGRET: | 623 | case MAC_ADB_EGRET: |
679 | case MAC_ADB_CUDA: | 624 | case MAC_ADB_CUDA: |
680 | cuda_write_time(now); | 625 | cuda_set_rtc_time(t); |
681 | break; | 626 | break; |
682 | #endif | 627 | #endif |
683 | #ifdef CONFIG_ADB_PMU | 628 | #ifdef CONFIG_ADB_PMU |
684 | case MAC_ADB_PB2: | 629 | case MAC_ADB_PB2: |
685 | pmu_write_time(now); | 630 | pmu_set_rtc_time(t); |
686 | break; | 631 | break; |
687 | #endif | 632 | #endif |
688 | default: | 633 | default: |
diff --git a/arch/powerpc/Kbuild b/arch/powerpc/Kbuild new file mode 100644 index 000000000000..1625a06802ca --- /dev/null +++ b/arch/powerpc/Kbuild | |||
@@ -0,0 +1,16 @@ | |||
1 | subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror | ||
2 | |||
3 | obj-y += kernel/ | ||
4 | obj-y += mm/ | ||
5 | obj-y += lib/ | ||
6 | obj-y += sysdev/ | ||
7 | obj-y += platforms/ | ||
8 | obj-y += math-emu/ | ||
9 | obj-y += crypto/ | ||
10 | obj-y += net/ | ||
11 | |||
12 | obj-$(CONFIG_XMON) += xmon/ | ||
13 | obj-$(CONFIG_KVM) += kvm/ | ||
14 | |||
15 | obj-$(CONFIG_PERF_EVENTS) += perf/ | ||
16 | obj-$(CONFIG_KEXEC_FILE) += purgatory/ | ||
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index a80669209155..e84943d24e5c 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
@@ -137,7 +137,7 @@ config PPC | |||
137 | select ARCH_HAS_PMEM_API if PPC64 | 137 | select ARCH_HAS_PMEM_API if PPC64 |
138 | select ARCH_HAS_PTE_SPECIAL | 138 | select ARCH_HAS_PTE_SPECIAL |
139 | select ARCH_HAS_MEMBARRIER_CALLBACKS | 139 | select ARCH_HAS_MEMBARRIER_CALLBACKS |
140 | select ARCH_HAS_SCALED_CPUTIME if VIRT_CPU_ACCOUNTING_NATIVE | 140 | select ARCH_HAS_SCALED_CPUTIME if VIRT_CPU_ACCOUNTING_NATIVE && PPC64 |
141 | select ARCH_HAS_SG_CHAIN | 141 | select ARCH_HAS_SG_CHAIN |
142 | select ARCH_HAS_STRICT_KERNEL_RWX if ((PPC_BOOK3S_64 || PPC32) && !RELOCATABLE && !HIBERNATION) | 142 | select ARCH_HAS_STRICT_KERNEL_RWX if ((PPC_BOOK3S_64 || PPC32) && !RELOCATABLE && !HIBERNATION) |
143 | select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST | 143 | select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST |
@@ -180,6 +180,8 @@ config PPC | |||
180 | select HAVE_ARCH_SECCOMP_FILTER | 180 | select HAVE_ARCH_SECCOMP_FILTER |
181 | select HAVE_ARCH_TRACEHOOK | 181 | select HAVE_ARCH_TRACEHOOK |
182 | select HAVE_CBPF_JIT if !PPC64 | 182 | select HAVE_CBPF_JIT if !PPC64 |
183 | select HAVE_STACKPROTECTOR if PPC64 && $(cc-option,-mstack-protector-guard=tls -mstack-protector-guard-reg=r13) | ||
184 | select HAVE_STACKPROTECTOR if PPC32 && $(cc-option,-mstack-protector-guard=tls -mstack-protector-guard-reg=r2) | ||
183 | select HAVE_CONTEXT_TRACKING if PPC64 | 185 | select HAVE_CONTEXT_TRACKING if PPC64 |
184 | select HAVE_DEBUG_KMEMLEAK | 186 | select HAVE_DEBUG_KMEMLEAK |
185 | select HAVE_DEBUG_STACKOVERFLOW | 187 | select HAVE_DEBUG_STACKOVERFLOW |
@@ -188,6 +190,7 @@ config PPC | |||
188 | select HAVE_EBPF_JIT if PPC64 | 190 | select HAVE_EBPF_JIT if PPC64 |
189 | select HAVE_EFFICIENT_UNALIGNED_ACCESS if !(CPU_LITTLE_ENDIAN && POWER7_CPU) | 191 | select HAVE_EFFICIENT_UNALIGNED_ACCESS if !(CPU_LITTLE_ENDIAN && POWER7_CPU) |
190 | select HAVE_FTRACE_MCOUNT_RECORD | 192 | select HAVE_FTRACE_MCOUNT_RECORD |
193 | select HAVE_FUNCTION_ERROR_INJECTION | ||
191 | select HAVE_FUNCTION_GRAPH_TRACER | 194 | select HAVE_FUNCTION_GRAPH_TRACER |
192 | select HAVE_FUNCTION_TRACER | 195 | select HAVE_FUNCTION_TRACER |
193 | select HAVE_GCC_PLUGINS if GCC_VERSION >= 50200 # plugin support on gcc <= 5.1 is buggy on PPC | 196 | select HAVE_GCC_PLUGINS if GCC_VERSION >= 50200 # plugin support on gcc <= 5.1 is buggy on PPC |
@@ -285,12 +288,10 @@ config ARCH_MAY_HAVE_PC_FDC | |||
285 | 288 | ||
286 | config PPC_UDBG_16550 | 289 | config PPC_UDBG_16550 |
287 | bool | 290 | bool |
288 | default n | ||
289 | 291 | ||
290 | config GENERIC_TBSYNC | 292 | config GENERIC_TBSYNC |
291 | bool | 293 | bool |
292 | default y if PPC32 && SMP | 294 | default y if PPC32 && SMP |
293 | default n | ||
294 | 295 | ||
295 | config AUDIT_ARCH | 296 | config AUDIT_ARCH |
296 | bool | 297 | bool |
@@ -309,13 +310,11 @@ config EPAPR_BOOT | |||
309 | bool | 310 | bool |
310 | help | 311 | help |
311 | Used to allow a board to specify it wants an ePAPR compliant wrapper. | 312 | Used to allow a board to specify it wants an ePAPR compliant wrapper. |
312 | default n | ||
313 | 313 | ||
314 | config DEFAULT_UIMAGE | 314 | config DEFAULT_UIMAGE |
315 | bool | 315 | bool |
316 | help | 316 | help |
317 | Used to allow a board to specify it wants a uImage built by default | 317 | Used to allow a board to specify it wants a uImage built by default |
318 | default n | ||
319 | 318 | ||
320 | config ARCH_HIBERNATION_POSSIBLE | 319 | config ARCH_HIBERNATION_POSSIBLE |
321 | bool | 320 | bool |
@@ -329,11 +328,9 @@ config ARCH_SUSPEND_POSSIBLE | |||
329 | 328 | ||
330 | config PPC_DCR_NATIVE | 329 | config PPC_DCR_NATIVE |
331 | bool | 330 | bool |
332 | default n | ||
333 | 331 | ||
334 | config PPC_DCR_MMIO | 332 | config PPC_DCR_MMIO |
335 | bool | 333 | bool |
336 | default n | ||
337 | 334 | ||
338 | config PPC_DCR | 335 | config PPC_DCR |
339 | bool | 336 | bool |
@@ -344,7 +341,6 @@ config PPC_OF_PLATFORM_PCI | |||
344 | bool | 341 | bool |
345 | depends on PCI | 342 | depends on PCI |
346 | depends on PPC64 # not supported on 32 bits yet | 343 | depends on PPC64 # not supported on 32 bits yet |
347 | default n | ||
348 | 344 | ||
349 | config ARCH_SUPPORTS_DEBUG_PAGEALLOC | 345 | config ARCH_SUPPORTS_DEBUG_PAGEALLOC |
350 | depends on PPC32 || PPC_BOOK3S_64 | 346 | depends on PPC32 || PPC_BOOK3S_64 |
@@ -447,14 +443,12 @@ config PPC_TRANSACTIONAL_MEM | |||
447 | depends on SMP | 443 | depends on SMP |
448 | select ALTIVEC | 444 | select ALTIVEC |
449 | select VSX | 445 | select VSX |
450 | default n | ||
451 | ---help--- | 446 | ---help--- |
452 | Support user-mode Transactional Memory on POWERPC. | 447 | Support user-mode Transactional Memory on POWERPC. |
453 | 448 | ||
454 | config LD_HEAD_STUB_CATCH | 449 | config LD_HEAD_STUB_CATCH |
455 | bool "Reserve 256 bytes to cope with linker stubs in HEAD text" if EXPERT | 450 | bool "Reserve 256 bytes to cope with linker stubs in HEAD text" if EXPERT |
456 | depends on PPC64 | 451 | depends on PPC64 |
457 | default n | ||
458 | help | 452 | help |
459 | Very large kernels can cause linker branch stubs to be generated by | 453 | Very large kernels can cause linker branch stubs to be generated by |
460 | code in head_64.S, which moves the head text sections out of their | 454 | code in head_64.S, which moves the head text sections out of their |
@@ -557,7 +551,6 @@ config RELOCATABLE | |||
557 | config RELOCATABLE_TEST | 551 | config RELOCATABLE_TEST |
558 | bool "Test relocatable kernel" | 552 | bool "Test relocatable kernel" |
559 | depends on (PPC64 && RELOCATABLE) | 553 | depends on (PPC64 && RELOCATABLE) |
560 | default n | ||
561 | help | 554 | help |
562 | This runs the relocatable kernel at the address it was initially | 555 | This runs the relocatable kernel at the address it was initially |
563 | loaded at, which tends to be non-zero and therefore test the | 556 | loaded at, which tends to be non-zero and therefore test the |
@@ -769,7 +762,6 @@ config PPC_SUBPAGE_PROT | |||
769 | 762 | ||
770 | config PPC_COPRO_BASE | 763 | config PPC_COPRO_BASE |
771 | bool | 764 | bool |
772 | default n | ||
773 | 765 | ||
774 | config SCHED_SMT | 766 | config SCHED_SMT |
775 | bool "SMT (Hyperthreading) scheduler support" | 767 | bool "SMT (Hyperthreading) scheduler support" |
@@ -892,7 +884,6 @@ config PPC_INDIRECT_PCI | |||
892 | bool | 884 | bool |
893 | depends on PCI | 885 | depends on PCI |
894 | default y if 40x || 44x | 886 | default y if 40x || 44x |
895 | default n | ||
896 | 887 | ||
897 | config EISA | 888 | config EISA |
898 | bool | 889 | bool |
@@ -989,7 +980,6 @@ source "drivers/pcmcia/Kconfig" | |||
989 | 980 | ||
990 | config HAS_RAPIDIO | 981 | config HAS_RAPIDIO |
991 | bool | 982 | bool |
992 | default n | ||
993 | 983 | ||
994 | config RAPIDIO | 984 | config RAPIDIO |
995 | tristate "RapidIO support" | 985 | tristate "RapidIO support" |
@@ -1012,7 +1002,6 @@ endmenu | |||
1012 | 1002 | ||
1013 | config NONSTATIC_KERNEL | 1003 | config NONSTATIC_KERNEL |
1014 | bool | 1004 | bool |
1015 | default n | ||
1016 | 1005 | ||
1017 | menu "Advanced setup" | 1006 | menu "Advanced setup" |
1018 | depends on PPC32 | 1007 | depends on PPC32 |
diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug index fd63cd914a74..f4961fbcb48d 100644 --- a/arch/powerpc/Kconfig.debug +++ b/arch/powerpc/Kconfig.debug | |||
@@ -2,7 +2,6 @@ | |||
2 | 2 | ||
3 | config PPC_DISABLE_WERROR | 3 | config PPC_DISABLE_WERROR |
4 | bool "Don't build arch/powerpc code with -Werror" | 4 | bool "Don't build arch/powerpc code with -Werror" |
5 | default n | ||
6 | help | 5 | help |
7 | This option tells the compiler NOT to build the code under | 6 | This option tells the compiler NOT to build the code under |
8 | arch/powerpc with the -Werror flag (which means warnings | 7 | arch/powerpc with the -Werror flag (which means warnings |
@@ -56,7 +55,6 @@ config PPC_EMULATED_STATS | |||
56 | config CODE_PATCHING_SELFTEST | 55 | config CODE_PATCHING_SELFTEST |
57 | bool "Run self-tests of the code-patching code" | 56 | bool "Run self-tests of the code-patching code" |
58 | depends on DEBUG_KERNEL | 57 | depends on DEBUG_KERNEL |
59 | default n | ||
60 | 58 | ||
61 | config JUMP_LABEL_FEATURE_CHECKS | 59 | config JUMP_LABEL_FEATURE_CHECKS |
62 | bool "Enable use of jump label for cpu/mmu_has_feature()" | 60 | bool "Enable use of jump label for cpu/mmu_has_feature()" |
@@ -70,7 +68,6 @@ config JUMP_LABEL_FEATURE_CHECKS | |||
70 | config JUMP_LABEL_FEATURE_CHECK_DEBUG | 68 | config JUMP_LABEL_FEATURE_CHECK_DEBUG |
71 | bool "Do extra check on feature fixup calls" | 69 | bool "Do extra check on feature fixup calls" |
72 | depends on DEBUG_KERNEL && JUMP_LABEL_FEATURE_CHECKS | 70 | depends on DEBUG_KERNEL && JUMP_LABEL_FEATURE_CHECKS |
73 | default n | ||
74 | help | 71 | help |
75 | This tries to catch incorrect usage of cpu_has_feature() and | 72 | This tries to catch incorrect usage of cpu_has_feature() and |
76 | mmu_has_feature() in the code. | 73 | mmu_has_feature() in the code. |
@@ -80,16 +77,13 @@ config JUMP_LABEL_FEATURE_CHECK_DEBUG | |||
80 | config FTR_FIXUP_SELFTEST | 77 | config FTR_FIXUP_SELFTEST |
81 | bool "Run self-tests of the feature-fixup code" | 78 | bool "Run self-tests of the feature-fixup code" |
82 | depends on DEBUG_KERNEL | 79 | depends on DEBUG_KERNEL |
83 | default n | ||
84 | 80 | ||
85 | config MSI_BITMAP_SELFTEST | 81 | config MSI_BITMAP_SELFTEST |
86 | bool "Run self-tests of the MSI bitmap code" | 82 | bool "Run self-tests of the MSI bitmap code" |
87 | depends on DEBUG_KERNEL | 83 | depends on DEBUG_KERNEL |
88 | default n | ||
89 | 84 | ||
90 | config PPC_IRQ_SOFT_MASK_DEBUG | 85 | config PPC_IRQ_SOFT_MASK_DEBUG |
91 | bool "Include extra checks for powerpc irq soft masking" | 86 | bool "Include extra checks for powerpc irq soft masking" |
92 | default n | ||
93 | 87 | ||
94 | config XMON | 88 | config XMON |
95 | bool "Include xmon kernel debugger" | 89 | bool "Include xmon kernel debugger" |
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index 42f225f6ec93..17be664dafa2 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile | |||
@@ -112,6 +112,13 @@ KBUILD_LDFLAGS += -m elf$(BITS)$(LDEMULATION) | |||
112 | KBUILD_ARFLAGS += --target=elf$(BITS)-$(GNUTARGET) | 112 | KBUILD_ARFLAGS += --target=elf$(BITS)-$(GNUTARGET) |
113 | endif | 113 | endif |
114 | 114 | ||
115 | cflags-$(CONFIG_STACKPROTECTOR) += -mstack-protector-guard=tls | ||
116 | ifdef CONFIG_PPC64 | ||
117 | cflags-$(CONFIG_STACKPROTECTOR) += -mstack-protector-guard-reg=r13 | ||
118 | else | ||
119 | cflags-$(CONFIG_STACKPROTECTOR) += -mstack-protector-guard-reg=r2 | ||
120 | endif | ||
121 | |||
115 | LDFLAGS_vmlinux-y := -Bstatic | 122 | LDFLAGS_vmlinux-y := -Bstatic |
116 | LDFLAGS_vmlinux-$(CONFIG_RELOCATABLE) := -pie | 123 | LDFLAGS_vmlinux-$(CONFIG_RELOCATABLE) := -pie |
117 | LDFLAGS_vmlinux := $(LDFLAGS_vmlinux-y) | 124 | LDFLAGS_vmlinux := $(LDFLAGS_vmlinux-y) |
@@ -160,8 +167,17 @@ else | |||
160 | CFLAGS-$(CONFIG_GENERIC_CPU) += -mcpu=powerpc64 | 167 | CFLAGS-$(CONFIG_GENERIC_CPU) += -mcpu=powerpc64 |
161 | endif | 168 | endif |
162 | 169 | ||
170 | ifdef CONFIG_FUNCTION_TRACER | ||
171 | CC_FLAGS_FTRACE := -pg | ||
163 | ifdef CONFIG_MPROFILE_KERNEL | 172 | ifdef CONFIG_MPROFILE_KERNEL |
164 | CC_FLAGS_FTRACE := -pg -mprofile-kernel | 173 | CC_FLAGS_FTRACE += -mprofile-kernel |
174 | endif | ||
175 | # Work around gcc code-gen bugs with -pg / -fno-omit-frame-pointer in gcc <= 4.8 | ||
176 | # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=44199 | ||
177 | # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52828 | ||
178 | ifneq ($(cc-name),clang) | ||
179 | CC_FLAGS_FTRACE += $(call cc-ifversion, -lt, 0409, -mno-sched-epilog) | ||
180 | endif | ||
165 | endif | 181 | endif |
166 | 182 | ||
167 | CFLAGS-$(CONFIG_TARGET_CPU_BOOL) += $(call cc-option,-mcpu=$(CONFIG_TARGET_CPU)) | 183 | CFLAGS-$(CONFIG_TARGET_CPU_BOOL) += $(call cc-option,-mcpu=$(CONFIG_TARGET_CPU)) |
@@ -229,16 +245,15 @@ ifdef CONFIG_6xx | |||
229 | KBUILD_CFLAGS += -mcpu=powerpc | 245 | KBUILD_CFLAGS += -mcpu=powerpc |
230 | endif | 246 | endif |
231 | 247 | ||
232 | # Work around a gcc code-gen bug with -fno-omit-frame-pointer. | ||
233 | ifdef CONFIG_FUNCTION_TRACER | ||
234 | KBUILD_CFLAGS += -mno-sched-epilog | ||
235 | endif | ||
236 | |||
237 | cpu-as-$(CONFIG_4xx) += -Wa,-m405 | 248 | cpu-as-$(CONFIG_4xx) += -Wa,-m405 |
238 | cpu-as-$(CONFIG_ALTIVEC) += $(call as-option,-Wa$(comma)-maltivec) | 249 | cpu-as-$(CONFIG_ALTIVEC) += $(call as-option,-Wa$(comma)-maltivec) |
239 | cpu-as-$(CONFIG_E200) += -Wa,-me200 | 250 | cpu-as-$(CONFIG_E200) += -Wa,-me200 |
240 | cpu-as-$(CONFIG_E500) += -Wa,-me500 | 251 | cpu-as-$(CONFIG_E500) += -Wa,-me500 |
241 | cpu-as-$(CONFIG_PPC_BOOK3S_64) += -Wa,-mpower4 | 252 | |
253 | # When using '-many -mpower4' gas will first try and find a matching power4 | ||
254 | # mnemonic and failing that it will allow any valid mnemonic that GAS knows | ||
255 | # about. GCC will pass -many to GAS when assembling, clang does not. | ||
256 | cpu-as-$(CONFIG_PPC_BOOK3S_64) += -Wa,-mpower4 -Wa,-many | ||
242 | cpu-as-$(CONFIG_PPC_E500MC) += $(call as-option,-Wa$(comma)-me500mc) | 257 | cpu-as-$(CONFIG_PPC_E500MC) += $(call as-option,-Wa$(comma)-me500mc) |
243 | 258 | ||
244 | KBUILD_AFLAGS += $(cpu-as-y) | 259 | KBUILD_AFLAGS += $(cpu-as-y) |
@@ -258,18 +273,8 @@ head-$(CONFIG_PPC_FPU) += arch/powerpc/kernel/fpu.o | |||
258 | head-$(CONFIG_ALTIVEC) += arch/powerpc/kernel/vector.o | 273 | head-$(CONFIG_ALTIVEC) += arch/powerpc/kernel/vector.o |
259 | head-$(CONFIG_PPC_OF_BOOT_TRAMPOLINE) += arch/powerpc/kernel/prom_init.o | 274 | head-$(CONFIG_PPC_OF_BOOT_TRAMPOLINE) += arch/powerpc/kernel/prom_init.o |
260 | 275 | ||
261 | core-y += arch/powerpc/kernel/ \ | 276 | # See arch/powerpc/Kbuild for content of core part of the kernel |
262 | arch/powerpc/mm/ \ | 277 | core-y += arch/powerpc/ |
263 | arch/powerpc/lib/ \ | ||
264 | arch/powerpc/sysdev/ \ | ||
265 | arch/powerpc/platforms/ \ | ||
266 | arch/powerpc/math-emu/ \ | ||
267 | arch/powerpc/crypto/ \ | ||
268 | arch/powerpc/net/ | ||
269 | core-$(CONFIG_XMON) += arch/powerpc/xmon/ | ||
270 | core-$(CONFIG_KVM) += arch/powerpc/kvm/ | ||
271 | core-$(CONFIG_PERF_EVENTS) += arch/powerpc/perf/ | ||
272 | core-$(CONFIG_KEXEC_FILE) += arch/powerpc/purgatory/ | ||
273 | 278 | ||
274 | drivers-$(CONFIG_OPROFILE) += arch/powerpc/oprofile/ | 279 | drivers-$(CONFIG_OPROFILE) += arch/powerpc/oprofile/ |
275 | 280 | ||
@@ -397,40 +402,20 @@ archclean: | |||
397 | 402 | ||
398 | archprepare: checkbin | 403 | archprepare: checkbin |
399 | 404 | ||
400 | # Use the file '.tmp_gas_check' for binutils tests, as gas won't output | 405 | ifdef CONFIG_STACKPROTECTOR |
401 | # to stdout and these checks are run even on install targets. | 406 | prepare: stack_protector_prepare |
402 | TOUT := .tmp_gas_check | ||
403 | 407 | ||
404 | # Check gcc and binutils versions: | 408 | stack_protector_prepare: prepare0 |
405 | # - gcc-3.4 and binutils-2.14 are a fatal combination | 409 | ifdef CONFIG_PPC64 |
406 | # - Require gcc 4.0 or above on 64-bit | 410 | $(eval KBUILD_CFLAGS += -mstack-protector-guard-offset=$(shell awk '{if ($$2 == "PACA_CANARY") print $$3;}' include/generated/asm-offsets.h)) |
407 | # - gcc-4.2.0 has issues compiling modules on 64-bit | 411 | else |
412 | $(eval KBUILD_CFLAGS += -mstack-protector-guard-offset=$(shell awk '{if ($$2 == "TASK_CANARY") print $$3;}' include/generated/asm-offsets.h)) | ||
413 | endif | ||
414 | endif | ||
415 | |||
416 | # Check toolchain versions: | ||
417 | # - gcc-4.6 is the minimum kernel-wide version so nothing required. | ||
408 | checkbin: | 418 | checkbin: |
409 | @if test "$(cc-name)" != "clang" \ | ||
410 | && test "$(cc-version)" = "0304" ; then \ | ||
411 | if ! /bin/echo mftb 5 | $(AS) -v -mppc -many -o $(TOUT) >/dev/null 2>&1 ; then \ | ||
412 | echo -n '*** ${VERSION}.${PATCHLEVEL} kernels no longer build '; \ | ||
413 | echo 'correctly with gcc-3.4 and your version of binutils.'; \ | ||
414 | echo '*** Please upgrade your binutils or downgrade your gcc'; \ | ||
415 | false; \ | ||
416 | fi ; \ | ||
417 | fi | ||
418 | @if test "$(cc-name)" != "clang" \ | ||
419 | && test "$(cc-version)" -lt "0400" \ | ||
420 | && test "x${CONFIG_PPC64}" = "xy" ; then \ | ||
421 | echo -n "Sorry, GCC v4.0 or above is required to build " ; \ | ||
422 | echo "the 64-bit powerpc kernel." ; \ | ||
423 | false ; \ | ||
424 | fi | ||
425 | @if test "$(cc-name)" != "clang" \ | ||
426 | && test "$(cc-fullversion)" = "040200" \ | ||
427 | && test "x${CONFIG_MODULES}${CONFIG_PPC64}" = "xyy" ; then \ | ||
428 | echo -n '*** GCC-4.2.0 cannot compile the 64-bit powerpc ' ; \ | ||
429 | echo 'kernel with modules enabled.' ; \ | ||
430 | echo -n '*** Please use a different GCC version or ' ; \ | ||
431 | echo 'disable kernel modules' ; \ | ||
432 | false ; \ | ||
433 | fi | ||
434 | @if test "x${CONFIG_CPU_LITTLE_ENDIAN}" = "xy" \ | 419 | @if test "x${CONFIG_CPU_LITTLE_ENDIAN}" = "xy" \ |
435 | && $(LD) --version | head -1 | grep ' 2\.24$$' >/dev/null ; then \ | 420 | && $(LD) --version | head -1 | grep ' 2\.24$$' >/dev/null ; then \ |
436 | echo -n '*** binutils 2.24 miscompiles weak symbols ' ; \ | 421 | echo -n '*** binutils 2.24 miscompiles weak symbols ' ; \ |
@@ -438,7 +423,3 @@ checkbin: | |||
438 | echo -n '*** Please use a different binutils version.' ; \ | 423 | echo -n '*** Please use a different binutils version.' ; \ |
439 | false ; \ | 424 | false ; \ |
440 | fi | 425 | fi |
441 | |||
442 | |||
443 | CLEAN_FILES += $(TOUT) | ||
444 | |||
diff --git a/arch/powerpc/boot/.gitignore b/arch/powerpc/boot/.gitignore index f92d0530ceb1..32034a0cc554 100644 --- a/arch/powerpc/boot/.gitignore +++ b/arch/powerpc/boot/.gitignore | |||
@@ -44,4 +44,5 @@ fdt_sw.c | |||
44 | fdt_wip.c | 44 | fdt_wip.c |
45 | libfdt.h | 45 | libfdt.h |
46 | libfdt_internal.h | 46 | libfdt_internal.h |
47 | autoconf.h | ||
47 | 48 | ||
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index bca5c23767df..39354365f54a 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile | |||
@@ -32,8 +32,8 @@ else | |||
32 | endif | 32 | endif |
33 | 33 | ||
34 | BOOTCFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \ | 34 | BOOTCFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \ |
35 | -fno-strict-aliasing -Os -msoft-float -pipe \ | 35 | -fno-strict-aliasing -O2 -msoft-float -mno-altivec -mno-vsx \ |
36 | -fomit-frame-pointer -fno-builtin -fPIC -nostdinc \ | 36 | -pipe -fomit-frame-pointer -fno-builtin -fPIC -nostdinc \ |
37 | -D$(compress-y) | 37 | -D$(compress-y) |
38 | 38 | ||
39 | ifdef CONFIG_PPC64_BOOT_WRAPPER | 39 | ifdef CONFIG_PPC64_BOOT_WRAPPER |
@@ -197,9 +197,14 @@ $(obj)/empty.c: | |||
197 | $(obj)/zImage.coff.lds $(obj)/zImage.ps3.lds : $(obj)/%: $(srctree)/$(src)/%.S | 197 | $(obj)/zImage.coff.lds $(obj)/zImage.ps3.lds : $(obj)/%: $(srctree)/$(src)/%.S |
198 | $(Q)cp $< $@ | 198 | $(Q)cp $< $@ |
199 | 199 | ||
200 | $(obj)/serial.c: $(obj)/autoconf.h | ||
201 | |||
202 | $(obj)/autoconf.h: $(obj)/%: $(objtree)/include/generated/% | ||
203 | $(Q)cp $< $@ | ||
204 | |||
200 | clean-files := $(zlib-) $(zlibheader-) $(zliblinuxheader-) \ | 205 | clean-files := $(zlib-) $(zlibheader-) $(zliblinuxheader-) \ |
201 | $(zlib-decomp-) $(libfdt) $(libfdtheader) \ | 206 | $(zlib-decomp-) $(libfdt) $(libfdtheader) \ |
202 | empty.c zImage.coff.lds zImage.ps3.lds zImage.lds | 207 | autoconf.h empty.c zImage.coff.lds zImage.ps3.lds zImage.lds |
203 | 208 | ||
204 | quiet_cmd_bootcc = BOOTCC $@ | 209 | quiet_cmd_bootcc = BOOTCC $@ |
205 | cmd_bootcc = $(BOOTCC) -Wp,-MD,$(depfile) $(BOOTCFLAGS) -c -o $@ $< | 210 | cmd_bootcc = $(BOOTCC) -Wp,-MD,$(depfile) $(BOOTCFLAGS) -c -o $@ $< |
diff --git a/arch/powerpc/boot/crt0.S b/arch/powerpc/boot/crt0.S index dcf2f15e6797..32dfe6d083f3 100644 --- a/arch/powerpc/boot/crt0.S +++ b/arch/powerpc/boot/crt0.S | |||
@@ -47,8 +47,10 @@ p_end: .long _end | |||
47 | p_pstack: .long _platform_stack_top | 47 | p_pstack: .long _platform_stack_top |
48 | #endif | 48 | #endif |
49 | 49 | ||
50 | .weak _zimage_start | ||
51 | .globl _zimage_start | 50 | .globl _zimage_start |
51 | /* Clang appears to require the .weak directive to be after the symbol | ||
52 | * is defined. See https://bugs.llvm.org/show_bug.cgi?id=38921 */ | ||
53 | .weak _zimage_start | ||
52 | _zimage_start: | 54 | _zimage_start: |
53 | .globl _zimage_start_lib | 55 | .globl _zimage_start_lib |
54 | _zimage_start_lib: | 56 | _zimage_start_lib: |
diff --git a/arch/powerpc/boot/opal.c b/arch/powerpc/boot/opal.c index 0272570d02de..dfb199ef5b94 100644 --- a/arch/powerpc/boot/opal.c +++ b/arch/powerpc/boot/opal.c | |||
@@ -13,8 +13,6 @@ | |||
13 | #include <libfdt.h> | 13 | #include <libfdt.h> |
14 | #include "../include/asm/opal-api.h" | 14 | #include "../include/asm/opal-api.h" |
15 | 15 | ||
16 | #ifdef CONFIG_PPC64_BOOT_WRAPPER | ||
17 | |||
18 | /* Global OPAL struct used by opal-call.S */ | 16 | /* Global OPAL struct used by opal-call.S */ |
19 | struct opal { | 17 | struct opal { |
20 | u64 base; | 18 | u64 base; |
@@ -101,9 +99,3 @@ int opal_console_init(void *devp, struct serial_console_data *scdp) | |||
101 | 99 | ||
102 | return 0; | 100 | return 0; |
103 | } | 101 | } |
104 | #else | ||
105 | int opal_console_init(void *devp, struct serial_console_data *scdp) | ||
106 | { | ||
107 | return -1; | ||
108 | } | ||
109 | #endif /* __powerpc64__ */ | ||
diff --git a/arch/powerpc/boot/serial.c b/arch/powerpc/boot/serial.c index 48e3743faedf..f045f8494bf9 100644 --- a/arch/powerpc/boot/serial.c +++ b/arch/powerpc/boot/serial.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include "stdio.h" | 18 | #include "stdio.h" |
19 | #include "io.h" | 19 | #include "io.h" |
20 | #include "ops.h" | 20 | #include "ops.h" |
21 | #include "autoconf.h" | ||
21 | 22 | ||
22 | static int serial_open(void) | 23 | static int serial_open(void) |
23 | { | 24 | { |
diff --git a/arch/powerpc/configs/g5_defconfig b/arch/powerpc/configs/g5_defconfig index 67c39f4acede..f686cc1eac0b 100644 --- a/arch/powerpc/configs/g5_defconfig +++ b/arch/powerpc/configs/g5_defconfig | |||
@@ -262,3 +262,4 @@ CONFIG_CRYPTO_SERPENT=m | |||
262 | CONFIG_CRYPTO_TEA=m | 262 | CONFIG_CRYPTO_TEA=m |
263 | CONFIG_CRYPTO_TWOFISH=m | 263 | CONFIG_CRYPTO_TWOFISH=m |
264 | # CONFIG_CRYPTO_HW is not set | 264 | # CONFIG_CRYPTO_HW is not set |
265 | CONFIG_PRINTK_TIME=y | ||
diff --git a/arch/powerpc/configs/maple_defconfig b/arch/powerpc/configs/maple_defconfig index 59e47ec85336..f71eddafb02f 100644 --- a/arch/powerpc/configs/maple_defconfig +++ b/arch/powerpc/configs/maple_defconfig | |||
@@ -112,3 +112,4 @@ CONFIG_PPC_EARLY_DEBUG=y | |||
112 | CONFIG_CRYPTO_ECB=m | 112 | CONFIG_CRYPTO_ECB=m |
113 | CONFIG_CRYPTO_PCBC=m | 113 | CONFIG_CRYPTO_PCBC=m |
114 | # CONFIG_CRYPTO_HW is not set | 114 | # CONFIG_CRYPTO_HW is not set |
115 | CONFIG_PRINTK_TIME=y | ||
diff --git a/arch/powerpc/configs/powernv_defconfig b/arch/powerpc/configs/powernv_defconfig index 6ab34e60495f..ef2ef98d3f28 100644 --- a/arch/powerpc/configs/powernv_defconfig +++ b/arch/powerpc/configs/powernv_defconfig | |||
@@ -44,6 +44,9 @@ CONFIG_PPC_MEMTRACE=y | |||
44 | # CONFIG_PPC_PSERIES is not set | 44 | # CONFIG_PPC_PSERIES is not set |
45 | # CONFIG_PPC_OF_BOOT_TRAMPOLINE is not set | 45 | # CONFIG_PPC_OF_BOOT_TRAMPOLINE is not set |
46 | CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y | 46 | CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y |
47 | CONFIG_CPU_FREQ_GOV_POWERSAVE=y | ||
48 | CONFIG_CPU_FREQ_GOV_USERSPACE=y | ||
49 | CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y | ||
47 | CONFIG_CPU_IDLE=y | 50 | CONFIG_CPU_IDLE=y |
48 | CONFIG_HZ_100=y | 51 | CONFIG_HZ_100=y |
49 | CONFIG_BINFMT_MISC=m | 52 | CONFIG_BINFMT_MISC=m |
@@ -350,3 +353,4 @@ CONFIG_VIRTUALIZATION=y | |||
350 | CONFIG_KVM_BOOK3S_64=m | 353 | CONFIG_KVM_BOOK3S_64=m |
351 | CONFIG_KVM_BOOK3S_64_HV=m | 354 | CONFIG_KVM_BOOK3S_64_HV=m |
352 | CONFIG_VHOST_NET=m | 355 | CONFIG_VHOST_NET=m |
356 | CONFIG_PRINTK_TIME=y | ||
diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig index 5033e630afea..f2515674a1e2 100644 --- a/arch/powerpc/configs/ppc64_defconfig +++ b/arch/powerpc/configs/ppc64_defconfig | |||
@@ -40,6 +40,9 @@ CONFIG_PS3_LPM=m | |||
40 | CONFIG_PPC_IBM_CELL_BLADE=y | 40 | CONFIG_PPC_IBM_CELL_BLADE=y |
41 | CONFIG_RTAS_FLASH=m | 41 | CONFIG_RTAS_FLASH=m |
42 | CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y | 42 | CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y |
43 | CONFIG_CPU_FREQ_GOV_POWERSAVE=y | ||
44 | CONFIG_CPU_FREQ_GOV_USERSPACE=y | ||
45 | CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y | ||
43 | CONFIG_CPU_FREQ_PMAC64=y | 46 | CONFIG_CPU_FREQ_PMAC64=y |
44 | CONFIG_HZ_100=y | 47 | CONFIG_HZ_100=y |
45 | CONFIG_BINFMT_MISC=m | 48 | CONFIG_BINFMT_MISC=m |
@@ -365,3 +368,4 @@ CONFIG_VIRTUALIZATION=y | |||
365 | CONFIG_KVM_BOOK3S_64=m | 368 | CONFIG_KVM_BOOK3S_64=m |
366 | CONFIG_KVM_BOOK3S_64_HV=m | 369 | CONFIG_KVM_BOOK3S_64_HV=m |
367 | CONFIG_VHOST_NET=m | 370 | CONFIG_VHOST_NET=m |
371 | CONFIG_PRINTK_TIME=y | ||
diff --git a/arch/powerpc/configs/ps3_defconfig b/arch/powerpc/configs/ps3_defconfig index 187e2f7c12c8..cf8d55f67272 100644 --- a/arch/powerpc/configs/ps3_defconfig +++ b/arch/powerpc/configs/ps3_defconfig | |||
@@ -171,3 +171,4 @@ CONFIG_CRYPTO_PCBC=m | |||
171 | CONFIG_CRYPTO_MICHAEL_MIC=m | 171 | CONFIG_CRYPTO_MICHAEL_MIC=m |
172 | CONFIG_CRYPTO_SALSA20=m | 172 | CONFIG_CRYPTO_SALSA20=m |
173 | CONFIG_CRYPTO_LZO=m | 173 | CONFIG_CRYPTO_LZO=m |
174 | CONFIG_PRINTK_TIME=y | ||
diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig index 0dd5cf7b566d..5e09a40cbcbf 100644 --- a/arch/powerpc/configs/pseries_defconfig +++ b/arch/powerpc/configs/pseries_defconfig | |||
@@ -325,3 +325,4 @@ CONFIG_VIRTUALIZATION=y | |||
325 | CONFIG_KVM_BOOK3S_64=m | 325 | CONFIG_KVM_BOOK3S_64=m |
326 | CONFIG_KVM_BOOK3S_64_HV=m | 326 | CONFIG_KVM_BOOK3S_64_HV=m |
327 | CONFIG_VHOST_NET=m | 327 | CONFIG_VHOST_NET=m |
328 | CONFIG_PRINTK_TIME=y | ||
diff --git a/arch/powerpc/configs/skiroot_defconfig b/arch/powerpc/configs/skiroot_defconfig index 6bd5e7261335..cfdd08897a06 100644 --- a/arch/powerpc/configs/skiroot_defconfig +++ b/arch/powerpc/configs/skiroot_defconfig | |||
@@ -3,20 +3,17 @@ CONFIG_ALTIVEC=y | |||
3 | CONFIG_VSX=y | 3 | CONFIG_VSX=y |
4 | CONFIG_NR_CPUS=2048 | 4 | CONFIG_NR_CPUS=2048 |
5 | CONFIG_CPU_LITTLE_ENDIAN=y | 5 | CONFIG_CPU_LITTLE_ENDIAN=y |
6 | CONFIG_KERNEL_XZ=y | ||
6 | # CONFIG_SWAP is not set | 7 | # CONFIG_SWAP is not set |
7 | CONFIG_SYSVIPC=y | 8 | CONFIG_SYSVIPC=y |
8 | CONFIG_POSIX_MQUEUE=y | 9 | CONFIG_POSIX_MQUEUE=y |
9 | # CONFIG_CROSS_MEMORY_ATTACH is not set | 10 | # CONFIG_CROSS_MEMORY_ATTACH is not set |
10 | CONFIG_NO_HZ=y | 11 | CONFIG_NO_HZ=y |
11 | CONFIG_HIGH_RES_TIMERS=y | 12 | CONFIG_HIGH_RES_TIMERS=y |
12 | CONFIG_TASKSTATS=y | 13 | # CONFIG_CPU_ISOLATION is not set |
13 | CONFIG_TASK_DELAY_ACCT=y | ||
14 | CONFIG_TASK_XACCT=y | ||
15 | CONFIG_TASK_IO_ACCOUNTING=y | ||
16 | CONFIG_IKCONFIG=y | 14 | CONFIG_IKCONFIG=y |
17 | CONFIG_IKCONFIG_PROC=y | 15 | CONFIG_IKCONFIG_PROC=y |
18 | CONFIG_LOG_BUF_SHIFT=20 | 16 | CONFIG_LOG_BUF_SHIFT=20 |
19 | CONFIG_RELAY=y | ||
20 | CONFIG_BLK_DEV_INITRD=y | 17 | CONFIG_BLK_DEV_INITRD=y |
21 | # CONFIG_RD_GZIP is not set | 18 | # CONFIG_RD_GZIP is not set |
22 | # CONFIG_RD_BZIP2 is not set | 19 | # CONFIG_RD_BZIP2 is not set |
@@ -24,8 +21,14 @@ CONFIG_BLK_DEV_INITRD=y | |||
24 | # CONFIG_RD_LZO is not set | 21 | # CONFIG_RD_LZO is not set |
25 | # CONFIG_RD_LZ4 is not set | 22 | # CONFIG_RD_LZ4 is not set |
26 | CONFIG_CC_OPTIMIZE_FOR_SIZE=y | 23 | CONFIG_CC_OPTIMIZE_FOR_SIZE=y |
24 | CONFIG_EXPERT=y | ||
25 | # CONFIG_SGETMASK_SYSCALL is not set | ||
26 | # CONFIG_SYSFS_SYSCALL is not set | ||
27 | # CONFIG_SHMEM is not set | ||
28 | # CONFIG_AIO is not set | ||
27 | CONFIG_PERF_EVENTS=y | 29 | CONFIG_PERF_EVENTS=y |
28 | # CONFIG_COMPAT_BRK is not set | 30 | # CONFIG_COMPAT_BRK is not set |
31 | CONFIG_SLAB_FREELIST_HARDENED=y | ||
29 | CONFIG_JUMP_LABEL=y | 32 | CONFIG_JUMP_LABEL=y |
30 | CONFIG_STRICT_KERNEL_RWX=y | 33 | CONFIG_STRICT_KERNEL_RWX=y |
31 | CONFIG_MODULES=y | 34 | CONFIG_MODULES=y |
@@ -35,7 +38,9 @@ CONFIG_MODULE_SIG_FORCE=y | |||
35 | CONFIG_MODULE_SIG_SHA512=y | 38 | CONFIG_MODULE_SIG_SHA512=y |
36 | CONFIG_PARTITION_ADVANCED=y | 39 | CONFIG_PARTITION_ADVANCED=y |
37 | # CONFIG_IOSCHED_DEADLINE is not set | 40 | # CONFIG_IOSCHED_DEADLINE is not set |
41 | # CONFIG_PPC_VAS is not set | ||
38 | # CONFIG_PPC_PSERIES is not set | 42 | # CONFIG_PPC_PSERIES is not set |
43 | # CONFIG_PPC_OF_BOOT_TRAMPOLINE is not set | ||
39 | CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y | 44 | CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y |
40 | CONFIG_CPU_IDLE=y | 45 | CONFIG_CPU_IDLE=y |
41 | CONFIG_HZ_100=y | 46 | CONFIG_HZ_100=y |
@@ -48,8 +53,9 @@ CONFIG_NUMA=y | |||
48 | CONFIG_PPC_64K_PAGES=y | 53 | CONFIG_PPC_64K_PAGES=y |
49 | CONFIG_SCHED_SMT=y | 54 | CONFIG_SCHED_SMT=y |
50 | CONFIG_CMDLINE_BOOL=y | 55 | CONFIG_CMDLINE_BOOL=y |
51 | CONFIG_CMDLINE="console=tty0 console=hvc0 powersave=off" | 56 | CONFIG_CMDLINE="console=tty0 console=hvc0 ipr.fast_reboot=1 quiet" |
52 | # CONFIG_SECCOMP is not set | 57 | # CONFIG_SECCOMP is not set |
58 | # CONFIG_PPC_MEM_KEYS is not set | ||
53 | CONFIG_NET=y | 59 | CONFIG_NET=y |
54 | CONFIG_PACKET=y | 60 | CONFIG_PACKET=y |
55 | CONFIG_UNIX=y | 61 | CONFIG_UNIX=y |
@@ -60,7 +66,6 @@ CONFIG_SYN_COOKIES=y | |||
60 | # CONFIG_INET_XFRM_MODE_TRANSPORT is not set | 66 | # CONFIG_INET_XFRM_MODE_TRANSPORT is not set |
61 | # CONFIG_INET_XFRM_MODE_TUNNEL is not set | 67 | # CONFIG_INET_XFRM_MODE_TUNNEL is not set |
62 | # CONFIG_INET_XFRM_MODE_BEET is not set | 68 | # CONFIG_INET_XFRM_MODE_BEET is not set |
63 | # CONFIG_IPV6 is not set | ||
64 | CONFIG_DNS_RESOLVER=y | 69 | CONFIG_DNS_RESOLVER=y |
65 | # CONFIG_WIRELESS is not set | 70 | # CONFIG_WIRELESS is not set |
66 | CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" | 71 | CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" |
@@ -73,8 +78,10 @@ CONFIG_BLK_DEV_RAM=y | |||
73 | CONFIG_BLK_DEV_RAM_SIZE=65536 | 78 | CONFIG_BLK_DEV_RAM_SIZE=65536 |
74 | CONFIG_VIRTIO_BLK=m | 79 | CONFIG_VIRTIO_BLK=m |
75 | CONFIG_BLK_DEV_NVME=m | 80 | CONFIG_BLK_DEV_NVME=m |
76 | CONFIG_EEPROM_AT24=y | 81 | CONFIG_NVME_MULTIPATH=y |
82 | CONFIG_EEPROM_AT24=m | ||
77 | # CONFIG_CXL is not set | 83 | # CONFIG_CXL is not set |
84 | # CONFIG_OCXL is not set | ||
78 | CONFIG_BLK_DEV_SD=m | 85 | CONFIG_BLK_DEV_SD=m |
79 | CONFIG_BLK_DEV_SR=m | 86 | CONFIG_BLK_DEV_SR=m |
80 | CONFIG_BLK_DEV_SR_VENDOR=y | 87 | CONFIG_BLK_DEV_SR_VENDOR=y |
@@ -85,7 +92,6 @@ CONFIG_SCSI_FC_ATTRS=y | |||
85 | CONFIG_SCSI_CXGB3_ISCSI=m | 92 | CONFIG_SCSI_CXGB3_ISCSI=m |
86 | CONFIG_SCSI_CXGB4_ISCSI=m | 93 | CONFIG_SCSI_CXGB4_ISCSI=m |
87 | CONFIG_SCSI_BNX2_ISCSI=m | 94 | CONFIG_SCSI_BNX2_ISCSI=m |
88 | CONFIG_BE2ISCSI=m | ||
89 | CONFIG_SCSI_AACRAID=m | 95 | CONFIG_SCSI_AACRAID=m |
90 | CONFIG_MEGARAID_NEWGEN=y | 96 | CONFIG_MEGARAID_NEWGEN=y |
91 | CONFIG_MEGARAID_MM=m | 97 | CONFIG_MEGARAID_MM=m |
@@ -102,7 +108,7 @@ CONFIG_SCSI_VIRTIO=m | |||
102 | CONFIG_SCSI_DH=y | 108 | CONFIG_SCSI_DH=y |
103 | CONFIG_SCSI_DH_ALUA=m | 109 | CONFIG_SCSI_DH_ALUA=m |
104 | CONFIG_ATA=y | 110 | CONFIG_ATA=y |
105 | CONFIG_SATA_AHCI=y | 111 | CONFIG_SATA_AHCI=m |
106 | # CONFIG_ATA_SFF is not set | 112 | # CONFIG_ATA_SFF is not set |
107 | CONFIG_MD=y | 113 | CONFIG_MD=y |
108 | CONFIG_BLK_DEV_MD=m | 114 | CONFIG_BLK_DEV_MD=m |
@@ -119,25 +125,72 @@ CONFIG_DM_SNAPSHOT=m | |||
119 | CONFIG_DM_MIRROR=m | 125 | CONFIG_DM_MIRROR=m |
120 | CONFIG_DM_ZERO=m | 126 | CONFIG_DM_ZERO=m |
121 | CONFIG_DM_MULTIPATH=m | 127 | CONFIG_DM_MULTIPATH=m |
128 | # CONFIG_NET_VENDOR_3COM is not set | ||
129 | # CONFIG_NET_VENDOR_ADAPTEC is not set | ||
130 | # CONFIG_NET_VENDOR_AGERE is not set | ||
131 | # CONFIG_NET_VENDOR_ALACRITECH is not set | ||
122 | CONFIG_ACENIC=m | 132 | CONFIG_ACENIC=m |
123 | CONFIG_ACENIC_OMIT_TIGON_I=y | 133 | CONFIG_ACENIC_OMIT_TIGON_I=y |
124 | CONFIG_TIGON3=y | 134 | # CONFIG_NET_VENDOR_AMAZON is not set |
135 | # CONFIG_NET_VENDOR_AMD is not set | ||
136 | # CONFIG_NET_VENDOR_AQUANTIA is not set | ||
137 | # CONFIG_NET_VENDOR_ARC is not set | ||
138 | # CONFIG_NET_VENDOR_ATHEROS is not set | ||
139 | CONFIG_TIGON3=m | ||
125 | CONFIG_BNX2X=m | 140 | CONFIG_BNX2X=m |
126 | CONFIG_CHELSIO_T1=y | 141 | # CONFIG_NET_VENDOR_BROCADE is not set |
142 | # CONFIG_NET_CADENCE is not set | ||
143 | # CONFIG_NET_VENDOR_CAVIUM is not set | ||
144 | CONFIG_CHELSIO_T1=m | ||
145 | # CONFIG_NET_VENDOR_CISCO is not set | ||
146 | # CONFIG_NET_VENDOR_CORTINA is not set | ||
147 | # CONFIG_NET_VENDOR_DEC is not set | ||
148 | # CONFIG_NET_VENDOR_DLINK is not set | ||
127 | CONFIG_BE2NET=m | 149 | CONFIG_BE2NET=m |
128 | CONFIG_S2IO=m | 150 | # CONFIG_NET_VENDOR_EZCHIP is not set |
129 | CONFIG_E100=m | 151 | # CONFIG_NET_VENDOR_HP is not set |
152 | # CONFIG_NET_VENDOR_HUAWEI is not set | ||
130 | CONFIG_E1000=m | 153 | CONFIG_E1000=m |
131 | CONFIG_E1000E=m | 154 | CONFIG_IGB=m |
132 | CONFIG_IXGB=m | 155 | CONFIG_IXGB=m |
133 | CONFIG_IXGBE=m | 156 | CONFIG_IXGBE=m |
157 | CONFIG_I40E=m | ||
158 | CONFIG_S2IO=m | ||
159 | # CONFIG_NET_VENDOR_MARVELL is not set | ||
134 | CONFIG_MLX4_EN=m | 160 | CONFIG_MLX4_EN=m |
161 | # CONFIG_MLX4_CORE_GEN2 is not set | ||
135 | CONFIG_MLX5_CORE=m | 162 | CONFIG_MLX5_CORE=m |
136 | CONFIG_MLX5_CORE_EN=y | 163 | # CONFIG_NET_VENDOR_MICREL is not set |
137 | CONFIG_MYRI10GE=m | 164 | CONFIG_MYRI10GE=m |
165 | # CONFIG_NET_VENDOR_NATSEMI is not set | ||
166 | # CONFIG_NET_VENDOR_NETRONOME is not set | ||
167 | # CONFIG_NET_VENDOR_NI is not set | ||
168 | # CONFIG_NET_VENDOR_NVIDIA is not set | ||
169 | # CONFIG_NET_VENDOR_OKI is not set | ||
170 | # CONFIG_NET_PACKET_ENGINE is not set | ||
138 | CONFIG_QLGE=m | 171 | CONFIG_QLGE=m |
139 | CONFIG_NETXEN_NIC=m | 172 | CONFIG_NETXEN_NIC=m |
173 | # CONFIG_NET_VENDOR_QUALCOMM is not set | ||
174 | # CONFIG_NET_VENDOR_RDC is not set | ||
175 | # CONFIG_NET_VENDOR_REALTEK is not set | ||
176 | # CONFIG_NET_VENDOR_RENESAS is not set | ||
177 | # CONFIG_NET_VENDOR_ROCKER is not set | ||
178 | # CONFIG_NET_VENDOR_SAMSUNG is not set | ||
179 | # CONFIG_NET_VENDOR_SEEQ is not set | ||
140 | CONFIG_SFC=m | 180 | CONFIG_SFC=m |
181 | # CONFIG_NET_VENDOR_SILAN is not set | ||
182 | # CONFIG_NET_VENDOR_SIS is not set | ||
183 | # CONFIG_NET_VENDOR_SMSC is not set | ||
184 | # CONFIG_NET_VENDOR_SOCIONEXT is not set | ||
185 | # CONFIG_NET_VENDOR_STMICRO is not set | ||
186 | # CONFIG_NET_VENDOR_SUN is not set | ||
187 | # CONFIG_NET_VENDOR_SYNOPSYS is not set | ||
188 | # CONFIG_NET_VENDOR_TEHUTI is not set | ||
189 | # CONFIG_NET_VENDOR_TI is not set | ||
190 | # CONFIG_NET_VENDOR_VIA is not set | ||
191 | # CONFIG_NET_VENDOR_WIZNET is not set | ||
192 | # CONFIG_NET_VENDOR_XILINX is not set | ||
193 | CONFIG_PHYLIB=y | ||
141 | # CONFIG_USB_NET_DRIVERS is not set | 194 | # CONFIG_USB_NET_DRIVERS is not set |
142 | # CONFIG_WLAN is not set | 195 | # CONFIG_WLAN is not set |
143 | CONFIG_INPUT_EVDEV=y | 196 | CONFIG_INPUT_EVDEV=y |
@@ -149,39 +202,51 @@ CONFIG_SERIAL_8250_CONSOLE=y | |||
149 | CONFIG_IPMI_HANDLER=y | 202 | CONFIG_IPMI_HANDLER=y |
150 | CONFIG_IPMI_DEVICE_INTERFACE=y | 203 | CONFIG_IPMI_DEVICE_INTERFACE=y |
151 | CONFIG_IPMI_POWERNV=y | 204 | CONFIG_IPMI_POWERNV=y |
205 | CONFIG_IPMI_WATCHDOG=y | ||
152 | CONFIG_HW_RANDOM=y | 206 | CONFIG_HW_RANDOM=y |
207 | CONFIG_TCG_TPM=y | ||
153 | CONFIG_TCG_TIS_I2C_NUVOTON=y | 208 | CONFIG_TCG_TIS_I2C_NUVOTON=y |
209 | CONFIG_I2C=y | ||
154 | # CONFIG_I2C_COMPAT is not set | 210 | # CONFIG_I2C_COMPAT is not set |
155 | CONFIG_I2C_CHARDEV=y | 211 | CONFIG_I2C_CHARDEV=y |
156 | # CONFIG_I2C_HELPER_AUTO is not set | 212 | # CONFIG_I2C_HELPER_AUTO is not set |
157 | CONFIG_DRM=y | 213 | CONFIG_I2C_ALGOBIT=y |
158 | CONFIG_DRM_RADEON=y | 214 | CONFIG_I2C_OPAL=m |
215 | CONFIG_PPS=y | ||
216 | CONFIG_SENSORS_IBMPOWERNV=m | ||
217 | CONFIG_DRM=m | ||
159 | CONFIG_DRM_AST=m | 218 | CONFIG_DRM_AST=m |
219 | CONFIG_FB=y | ||
160 | CONFIG_FIRMWARE_EDID=y | 220 | CONFIG_FIRMWARE_EDID=y |
161 | CONFIG_FB_MODE_HELPERS=y | ||
162 | CONFIG_FB_OF=y | ||
163 | CONFIG_FB_MATROX=y | ||
164 | CONFIG_FB_MATROX_MILLENIUM=y | ||
165 | CONFIG_FB_MATROX_MYSTIQUE=y | ||
166 | CONFIG_FB_MATROX_G=y | ||
167 | # CONFIG_LCD_CLASS_DEVICE is not set | ||
168 | # CONFIG_BACKLIGHT_GENERIC is not set | ||
169 | # CONFIG_VGA_CONSOLE is not set | 221 | # CONFIG_VGA_CONSOLE is not set |
222 | CONFIG_FRAMEBUFFER_CONSOLE=y | ||
170 | CONFIG_LOGO=y | 223 | CONFIG_LOGO=y |
171 | # CONFIG_LOGO_LINUX_MONO is not set | 224 | # CONFIG_LOGO_LINUX_MONO is not set |
172 | # CONFIG_LOGO_LINUX_VGA16 is not set | 225 | # CONFIG_LOGO_LINUX_VGA16 is not set |
226 | CONFIG_HID_GENERIC=m | ||
227 | CONFIG_HID_A4TECH=y | ||
228 | CONFIG_HID_BELKIN=y | ||
229 | CONFIG_HID_CHERRY=y | ||
230 | CONFIG_HID_CHICONY=y | ||
231 | CONFIG_HID_CYPRESS=y | ||
232 | CONFIG_HID_EZKEY=y | ||
233 | CONFIG_HID_ITE=y | ||
234 | CONFIG_HID_KENSINGTON=y | ||
235 | CONFIG_HID_LOGITECH=y | ||
236 | CONFIG_HID_MICROSOFT=y | ||
237 | CONFIG_HID_MONTEREY=y | ||
173 | CONFIG_USB_HIDDEV=y | 238 | CONFIG_USB_HIDDEV=y |
174 | CONFIG_USB=y | 239 | CONFIG_USB=m |
175 | CONFIG_USB_MON=y | 240 | CONFIG_USB_XHCI_HCD=m |
176 | CONFIG_USB_XHCI_HCD=y | 241 | CONFIG_USB_EHCI_HCD=m |
177 | CONFIG_USB_EHCI_HCD=y | ||
178 | # CONFIG_USB_EHCI_HCD_PPC_OF is not set | 242 | # CONFIG_USB_EHCI_HCD_PPC_OF is not set |
179 | CONFIG_USB_OHCI_HCD=y | 243 | CONFIG_USB_OHCI_HCD=m |
180 | CONFIG_USB_STORAGE=y | 244 | CONFIG_USB_STORAGE=m |
181 | CONFIG_RTC_CLASS=y | 245 | CONFIG_RTC_CLASS=y |
246 | CONFIG_RTC_DRV_OPAL=m | ||
182 | CONFIG_RTC_DRV_GENERIC=m | 247 | CONFIG_RTC_DRV_GENERIC=m |
183 | CONFIG_VIRT_DRIVERS=y | 248 | CONFIG_VIRT_DRIVERS=y |
184 | CONFIG_VIRTIO_PCI=y | 249 | CONFIG_VIRTIO_PCI=m |
185 | # CONFIG_IOMMU_SUPPORT is not set | 250 | # CONFIG_IOMMU_SUPPORT is not set |
186 | CONFIG_EXT4_FS=m | 251 | CONFIG_EXT4_FS=m |
187 | CONFIG_EXT4_FS_POSIX_ACL=y | 252 | CONFIG_EXT4_FS_POSIX_ACL=y |
@@ -195,10 +260,9 @@ CONFIG_UDF_FS=m | |||
195 | CONFIG_MSDOS_FS=m | 260 | CONFIG_MSDOS_FS=m |
196 | CONFIG_VFAT_FS=m | 261 | CONFIG_VFAT_FS=m |
197 | CONFIG_PROC_KCORE=y | 262 | CONFIG_PROC_KCORE=y |
198 | CONFIG_TMPFS=y | ||
199 | CONFIG_TMPFS_POSIX_ACL=y | ||
200 | # CONFIG_MISC_FILESYSTEMS is not set | 263 | # CONFIG_MISC_FILESYSTEMS is not set |
201 | # CONFIG_NETWORK_FILESYSTEMS is not set | 264 | # CONFIG_NETWORK_FILESYSTEMS is not set |
265 | CONFIG_NLS=y | ||
202 | CONFIG_NLS_DEFAULT="utf8" | 266 | CONFIG_NLS_DEFAULT="utf8" |
203 | CONFIG_NLS_CODEPAGE_437=y | 267 | CONFIG_NLS_CODEPAGE_437=y |
204 | CONFIG_NLS_ASCII=y | 268 | CONFIG_NLS_ASCII=y |
@@ -207,26 +271,24 @@ CONFIG_NLS_UTF8=y | |||
207 | CONFIG_CRC16=y | 271 | CONFIG_CRC16=y |
208 | CONFIG_CRC_ITU_T=y | 272 | CONFIG_CRC_ITU_T=y |
209 | CONFIG_LIBCRC32C=y | 273 | CONFIG_LIBCRC32C=y |
274 | # CONFIG_XZ_DEC_X86 is not set | ||
275 | # CONFIG_XZ_DEC_IA64 is not set | ||
276 | # CONFIG_XZ_DEC_ARM is not set | ||
277 | # CONFIG_XZ_DEC_ARMTHUMB is not set | ||
278 | # CONFIG_XZ_DEC_SPARC is not set | ||
210 | CONFIG_PRINTK_TIME=y | 279 | CONFIG_PRINTK_TIME=y |
211 | CONFIG_MAGIC_SYSRQ=y | 280 | CONFIG_MAGIC_SYSRQ=y |
212 | CONFIG_DEBUG_KERNEL=y | ||
213 | CONFIG_DEBUG_STACKOVERFLOW=y | 281 | CONFIG_DEBUG_STACKOVERFLOW=y |
214 | CONFIG_SOFTLOCKUP_DETECTOR=y | 282 | CONFIG_SOFTLOCKUP_DETECTOR=y |
283 | CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y | ||
215 | CONFIG_HARDLOCKUP_DETECTOR=y | 284 | CONFIG_HARDLOCKUP_DETECTOR=y |
216 | CONFIG_BOOTPARAM_HARDLOCKUP_PANIC=y | 285 | CONFIG_BOOTPARAM_HARDLOCKUP_PANIC=y |
217 | CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y | ||
218 | CONFIG_WQ_WATCHDOG=y | 286 | CONFIG_WQ_WATCHDOG=y |
219 | CONFIG_SCHEDSTATS=y | 287 | # CONFIG_SCHED_DEBUG is not set |
220 | # CONFIG_FTRACE is not set | 288 | # CONFIG_FTRACE is not set |
289 | # CONFIG_RUNTIME_TESTING_MENU is not set | ||
221 | CONFIG_XMON=y | 290 | CONFIG_XMON=y |
222 | CONFIG_XMON_DEFAULT=y | 291 | CONFIG_XMON_DEFAULT=y |
223 | CONFIG_SECURITY=y | 292 | CONFIG_ENCRYPTED_KEYS=y |
224 | CONFIG_IMA=y | ||
225 | CONFIG_EVM=y | ||
226 | # CONFIG_CRYPTO_ECHAINIV is not set | 293 | # CONFIG_CRYPTO_ECHAINIV is not set |
227 | CONFIG_CRYPTO_ECB=y | ||
228 | CONFIG_CRYPTO_CMAC=y | ||
229 | CONFIG_CRYPTO_MD4=y | ||
230 | CONFIG_CRYPTO_ARC4=y | ||
231 | CONFIG_CRYPTO_DES=y | ||
232 | # CONFIG_CRYPTO_HW is not set | 294 | # CONFIG_CRYPTO_HW is not set |
diff --git a/arch/powerpc/include/asm/accounting.h b/arch/powerpc/include/asm/accounting.h index 3abcf98ed2e0..c607c5d835cc 100644 --- a/arch/powerpc/include/asm/accounting.h +++ b/arch/powerpc/include/asm/accounting.h | |||
@@ -15,8 +15,10 @@ struct cpu_accounting_data { | |||
15 | /* Accumulated cputime values to flush on ticks*/ | 15 | /* Accumulated cputime values to flush on ticks*/ |
16 | unsigned long utime; | 16 | unsigned long utime; |
17 | unsigned long stime; | 17 | unsigned long stime; |
18 | #ifdef CONFIG_ARCH_HAS_SCALED_CPUTIME | ||
18 | unsigned long utime_scaled; | 19 | unsigned long utime_scaled; |
19 | unsigned long stime_scaled; | 20 | unsigned long stime_scaled; |
21 | #endif | ||
20 | unsigned long gtime; | 22 | unsigned long gtime; |
21 | unsigned long hardirq_time; | 23 | unsigned long hardirq_time; |
22 | unsigned long softirq_time; | 24 | unsigned long softirq_time; |
@@ -25,8 +27,10 @@ struct cpu_accounting_data { | |||
25 | /* Internal counters */ | 27 | /* Internal counters */ |
26 | unsigned long starttime; /* TB value snapshot */ | 28 | unsigned long starttime; /* TB value snapshot */ |
27 | unsigned long starttime_user; /* TB value on exit to usermode */ | 29 | unsigned long starttime_user; /* TB value on exit to usermode */ |
30 | #ifdef CONFIG_ARCH_HAS_SCALED_CPUTIME | ||
28 | unsigned long startspurr; /* SPURR value snapshot */ | 31 | unsigned long startspurr; /* SPURR value snapshot */ |
29 | unsigned long utime_sspurr; /* ->user_time when ->startspurr set */ | 32 | unsigned long utime_sspurr; /* ->user_time when ->startspurr set */ |
33 | #endif | ||
30 | }; | 34 | }; |
31 | 35 | ||
32 | #endif | 36 | #endif |
diff --git a/arch/powerpc/include/asm/asm-prototypes.h b/arch/powerpc/include/asm/asm-prototypes.h index c55ba3b4873b..ec691d489656 100644 --- a/arch/powerpc/include/asm/asm-prototypes.h +++ b/arch/powerpc/include/asm/asm-prototypes.h | |||
@@ -63,7 +63,6 @@ void program_check_exception(struct pt_regs *regs); | |||
63 | void alignment_exception(struct pt_regs *regs); | 63 | void alignment_exception(struct pt_regs *regs); |
64 | void slb_miss_bad_addr(struct pt_regs *regs); | 64 | void slb_miss_bad_addr(struct pt_regs *regs); |
65 | void StackOverflow(struct pt_regs *regs); | 65 | void StackOverflow(struct pt_regs *regs); |
66 | void nonrecoverable_exception(struct pt_regs *regs); | ||
67 | void kernel_fp_unavailable_exception(struct pt_regs *regs); | 66 | void kernel_fp_unavailable_exception(struct pt_regs *regs); |
68 | void altivec_unavailable_exception(struct pt_regs *regs); | 67 | void altivec_unavailable_exception(struct pt_regs *regs); |
69 | void vsx_unavailable_exception(struct pt_regs *regs); | 68 | void vsx_unavailable_exception(struct pt_regs *regs); |
@@ -78,6 +77,8 @@ void kernel_bad_stack(struct pt_regs *regs); | |||
78 | void system_reset_exception(struct pt_regs *regs); | 77 | void system_reset_exception(struct pt_regs *regs); |
79 | void machine_check_exception(struct pt_regs *regs); | 78 | void machine_check_exception(struct pt_regs *regs); |
80 | void emulation_assist_interrupt(struct pt_regs *regs); | 79 | void emulation_assist_interrupt(struct pt_regs *regs); |
80 | long do_slb_fault(struct pt_regs *regs, unsigned long ea); | ||
81 | void do_bad_slb_fault(struct pt_regs *regs, unsigned long ea, long err); | ||
81 | 82 | ||
82 | /* signals, syscalls and interrupts */ | 83 | /* signals, syscalls and interrupts */ |
83 | long sys_swapcontext(struct ucontext __user *old_ctx, | 84 | long sys_swapcontext(struct ucontext __user *old_ctx, |
diff --git a/arch/powerpc/include/asm/book3s/32/pgtable.h b/arch/powerpc/include/asm/book3s/32/pgtable.h index 751cf931bb3f..e61dd3ae5bc0 100644 --- a/arch/powerpc/include/asm/book3s/32/pgtable.h +++ b/arch/powerpc/include/asm/book3s/32/pgtable.h | |||
@@ -8,7 +8,97 @@ | |||
8 | #include <asm/book3s/32/hash.h> | 8 | #include <asm/book3s/32/hash.h> |
9 | 9 | ||
10 | /* And here we include common definitions */ | 10 | /* And here we include common definitions */ |
11 | #include <asm/pte-common.h> | 11 | |
12 | #define _PAGE_KERNEL_RO 0 | ||
13 | #define _PAGE_KERNEL_ROX 0 | ||
14 | #define _PAGE_KERNEL_RW (_PAGE_DIRTY | _PAGE_RW) | ||
15 | #define _PAGE_KERNEL_RWX (_PAGE_DIRTY | _PAGE_RW) | ||
16 | |||
17 | #define _PAGE_HPTEFLAGS _PAGE_HASHPTE | ||
18 | |||
19 | #ifndef __ASSEMBLY__ | ||
20 | |||
21 | static inline bool pte_user(pte_t pte) | ||
22 | { | ||
23 | return pte_val(pte) & _PAGE_USER; | ||
24 | } | ||
25 | #endif /* __ASSEMBLY__ */ | ||
26 | |||
27 | /* | ||
28 | * Location of the PFN in the PTE. Most 32-bit platforms use the same | ||
29 | * as _PAGE_SHIFT here (ie, naturally aligned). | ||
30 | * Platform who don't just pre-define the value so we don't override it here. | ||
31 | */ | ||
32 | #define PTE_RPN_SHIFT (PAGE_SHIFT) | ||
33 | |||
34 | /* | ||
35 | * The mask covered by the RPN must be a ULL on 32-bit platforms with | ||
36 | * 64-bit PTEs. | ||
37 | */ | ||
38 | #ifdef CONFIG_PTE_64BIT | ||
39 | #define PTE_RPN_MASK (~((1ULL << PTE_RPN_SHIFT) - 1)) | ||
40 | #else | ||
41 | #define PTE_RPN_MASK (~((1UL << PTE_RPN_SHIFT) - 1)) | ||
42 | #endif | ||
43 | |||
44 | /* | ||
45 | * _PAGE_CHG_MASK masks of bits that are to be preserved across | ||
46 | * pgprot changes. | ||
47 | */ | ||
48 | #define _PAGE_CHG_MASK (PTE_RPN_MASK | _PAGE_HASHPTE | _PAGE_DIRTY | \ | ||
49 | _PAGE_ACCESSED | _PAGE_SPECIAL) | ||
50 | |||
51 | /* | ||
52 | * We define 2 sets of base prot bits, one for basic pages (ie, | ||
53 | * cacheable kernel and user pages) and one for non cacheable | ||
54 | * pages. We always set _PAGE_COHERENT when SMP is enabled or | ||
55 | * the processor might need it for DMA coherency. | ||
56 | */ | ||
57 | #define _PAGE_BASE_NC (_PAGE_PRESENT | _PAGE_ACCESSED) | ||
58 | #define _PAGE_BASE (_PAGE_BASE_NC | _PAGE_COHERENT) | ||
59 | |||
60 | /* | ||
61 | * Permission masks used to generate the __P and __S table. | ||
62 | * | ||
63 | * Note:__pgprot is defined in arch/powerpc/include/asm/page.h | ||
64 | * | ||
65 | * Write permissions imply read permissions for now. | ||
66 | */ | ||
67 | #define PAGE_NONE __pgprot(_PAGE_BASE) | ||
68 | #define PAGE_SHARED __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW) | ||
69 | #define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW) | ||
70 | #define PAGE_COPY __pgprot(_PAGE_BASE | _PAGE_USER) | ||
71 | #define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_USER) | ||
72 | #define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_USER) | ||
73 | #define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_USER) | ||
74 | |||
75 | /* Permission masks used for kernel mappings */ | ||
76 | #define PAGE_KERNEL __pgprot(_PAGE_BASE | _PAGE_KERNEL_RW) | ||
77 | #define PAGE_KERNEL_NC __pgprot(_PAGE_BASE_NC | _PAGE_KERNEL_RW | _PAGE_NO_CACHE) | ||
78 | #define PAGE_KERNEL_NCG __pgprot(_PAGE_BASE_NC | _PAGE_KERNEL_RW | \ | ||
79 | _PAGE_NO_CACHE | _PAGE_GUARDED) | ||
80 | #define PAGE_KERNEL_X __pgprot(_PAGE_BASE | _PAGE_KERNEL_RWX) | ||
81 | #define PAGE_KERNEL_RO __pgprot(_PAGE_BASE | _PAGE_KERNEL_RO) | ||
82 | #define PAGE_KERNEL_ROX __pgprot(_PAGE_BASE | _PAGE_KERNEL_ROX) | ||
83 | |||
84 | /* | ||
85 | * Protection used for kernel text. We want the debuggers to be able to | ||
86 | * set breakpoints anywhere, so don't write protect the kernel text | ||
87 | * on platforms where such control is possible. | ||
88 | */ | ||
89 | #if defined(CONFIG_KGDB) || defined(CONFIG_XMON) || defined(CONFIG_BDI_SWITCH) ||\ | ||
90 | defined(CONFIG_KPROBES) || defined(CONFIG_DYNAMIC_FTRACE) | ||
91 | #define PAGE_KERNEL_TEXT PAGE_KERNEL_X | ||
92 | #else | ||
93 | #define PAGE_KERNEL_TEXT PAGE_KERNEL_ROX | ||
94 | #endif | ||
95 | |||
96 | /* Make modules code happy. We don't set RO yet */ | ||
97 | #define PAGE_KERNEL_EXEC PAGE_KERNEL_X | ||
98 | |||
99 | /* Advertise special mapping type for AGP */ | ||
100 | #define PAGE_AGP (PAGE_KERNEL_NC) | ||
101 | #define HAVE_PAGE_AGP | ||
12 | 102 | ||
13 | #define PTE_INDEX_SIZE PTE_SHIFT | 103 | #define PTE_INDEX_SIZE PTE_SHIFT |
14 | #define PMD_INDEX_SIZE 0 | 104 | #define PMD_INDEX_SIZE 0 |
@@ -219,7 +309,7 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, | |||
219 | static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, | 309 | static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, |
220 | pte_t *ptep) | 310 | pte_t *ptep) |
221 | { | 311 | { |
222 | pte_update(ptep, (_PAGE_RW | _PAGE_HWWRITE), _PAGE_RO); | 312 | pte_update(ptep, _PAGE_RW, 0); |
223 | } | 313 | } |
224 | static inline void huge_ptep_set_wrprotect(struct mm_struct *mm, | 314 | static inline void huge_ptep_set_wrprotect(struct mm_struct *mm, |
225 | unsigned long addr, pte_t *ptep) | 315 | unsigned long addr, pte_t *ptep) |
@@ -234,10 +324,9 @@ static inline void __ptep_set_access_flags(struct vm_area_struct *vma, | |||
234 | int psize) | 324 | int psize) |
235 | { | 325 | { |
236 | unsigned long set = pte_val(entry) & | 326 | unsigned long set = pte_val(entry) & |
237 | (_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW | _PAGE_EXEC); | 327 | (_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW); |
238 | unsigned long clr = ~pte_val(entry) & _PAGE_RO; | ||
239 | 328 | ||
240 | pte_update(ptep, clr, set); | 329 | pte_update(ptep, 0, set); |
241 | 330 | ||
242 | flush_tlb_page(vma, address); | 331 | flush_tlb_page(vma, address); |
243 | } | 332 | } |
@@ -292,7 +381,7 @@ static inline void __ptep_set_access_flags(struct vm_area_struct *vma, | |||
292 | #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) >> 3 }) | 381 | #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) >> 3 }) |
293 | #define __swp_entry_to_pte(x) ((pte_t) { (x).val << 3 }) | 382 | #define __swp_entry_to_pte(x) ((pte_t) { (x).val << 3 }) |
294 | 383 | ||
295 | int map_kernel_page(unsigned long va, phys_addr_t pa, int flags); | 384 | int map_kernel_page(unsigned long va, phys_addr_t pa, pgprot_t prot); |
296 | 385 | ||
297 | /* Generic accessors to PTE bits */ | 386 | /* Generic accessors to PTE bits */ |
298 | static inline int pte_write(pte_t pte) { return !!(pte_val(pte) & _PAGE_RW);} | 387 | static inline int pte_write(pte_t pte) { return !!(pte_val(pte) & _PAGE_RW);} |
@@ -301,13 +390,28 @@ static inline int pte_dirty(pte_t pte) { return !!(pte_val(pte) & _PAGE_DIRTY); | |||
301 | static inline int pte_young(pte_t pte) { return !!(pte_val(pte) & _PAGE_ACCESSED); } | 390 | static inline int pte_young(pte_t pte) { return !!(pte_val(pte) & _PAGE_ACCESSED); } |
302 | static inline int pte_special(pte_t pte) { return !!(pte_val(pte) & _PAGE_SPECIAL); } | 391 | static inline int pte_special(pte_t pte) { return !!(pte_val(pte) & _PAGE_SPECIAL); } |
303 | static inline int pte_none(pte_t pte) { return (pte_val(pte) & ~_PTE_NONE_MASK) == 0; } | 392 | static inline int pte_none(pte_t pte) { return (pte_val(pte) & ~_PTE_NONE_MASK) == 0; } |
304 | static inline pgprot_t pte_pgprot(pte_t pte) { return __pgprot(pte_val(pte) & PAGE_PROT_BITS); } | 393 | static inline bool pte_exec(pte_t pte) { return true; } |
305 | 394 | ||
306 | static inline int pte_present(pte_t pte) | 395 | static inline int pte_present(pte_t pte) |
307 | { | 396 | { |
308 | return pte_val(pte) & _PAGE_PRESENT; | 397 | return pte_val(pte) & _PAGE_PRESENT; |
309 | } | 398 | } |
310 | 399 | ||
400 | static inline bool pte_hw_valid(pte_t pte) | ||
401 | { | ||
402 | return pte_val(pte) & _PAGE_PRESENT; | ||
403 | } | ||
404 | |||
405 | static inline bool pte_hashpte(pte_t pte) | ||
406 | { | ||
407 | return !!(pte_val(pte) & _PAGE_HASHPTE); | ||
408 | } | ||
409 | |||
410 | static inline bool pte_ci(pte_t pte) | ||
411 | { | ||
412 | return !!(pte_val(pte) & _PAGE_NO_CACHE); | ||
413 | } | ||
414 | |||
311 | /* | 415 | /* |
312 | * We only find page table entry in the last level | 416 | * We only find page table entry in the last level |
313 | * Hence no need for other accessors | 417 | * Hence no need for other accessors |
@@ -315,17 +419,14 @@ static inline int pte_present(pte_t pte) | |||
315 | #define pte_access_permitted pte_access_permitted | 419 | #define pte_access_permitted pte_access_permitted |
316 | static inline bool pte_access_permitted(pte_t pte, bool write) | 420 | static inline bool pte_access_permitted(pte_t pte, bool write) |
317 | { | 421 | { |
318 | unsigned long pteval = pte_val(pte); | ||
319 | /* | 422 | /* |
320 | * A read-only access is controlled by _PAGE_USER bit. | 423 | * A read-only access is controlled by _PAGE_USER bit. |
321 | * We have _PAGE_READ set for WRITE and EXECUTE | 424 | * We have _PAGE_READ set for WRITE and EXECUTE |
322 | */ | 425 | */ |
323 | unsigned long need_pte_bits = _PAGE_PRESENT | _PAGE_USER; | 426 | if (!pte_present(pte) || !pte_user(pte) || !pte_read(pte)) |
324 | 427 | return false; | |
325 | if (write) | ||
326 | need_pte_bits |= _PAGE_WRITE; | ||
327 | 428 | ||
328 | if ((pteval & need_pte_bits) != need_pte_bits) | 429 | if (write && !pte_write(pte)) |
329 | return false; | 430 | return false; |
330 | 431 | ||
331 | return true; | 432 | return true; |
@@ -354,6 +455,11 @@ static inline pte_t pte_wrprotect(pte_t pte) | |||
354 | return __pte(pte_val(pte) & ~_PAGE_RW); | 455 | return __pte(pte_val(pte) & ~_PAGE_RW); |
355 | } | 456 | } |
356 | 457 | ||
458 | static inline pte_t pte_exprotect(pte_t pte) | ||
459 | { | ||
460 | return pte; | ||
461 | } | ||
462 | |||
357 | static inline pte_t pte_mkclean(pte_t pte) | 463 | static inline pte_t pte_mkclean(pte_t pte) |
358 | { | 464 | { |
359 | return __pte(pte_val(pte) & ~_PAGE_DIRTY); | 465 | return __pte(pte_val(pte) & ~_PAGE_DIRTY); |
@@ -364,6 +470,16 @@ static inline pte_t pte_mkold(pte_t pte) | |||
364 | return __pte(pte_val(pte) & ~_PAGE_ACCESSED); | 470 | return __pte(pte_val(pte) & ~_PAGE_ACCESSED); |
365 | } | 471 | } |
366 | 472 | ||
473 | static inline pte_t pte_mkexec(pte_t pte) | ||
474 | { | ||
475 | return pte; | ||
476 | } | ||
477 | |||
478 | static inline pte_t pte_mkpte(pte_t pte) | ||
479 | { | ||
480 | return pte; | ||
481 | } | ||
482 | |||
367 | static inline pte_t pte_mkwrite(pte_t pte) | 483 | static inline pte_t pte_mkwrite(pte_t pte) |
368 | { | 484 | { |
369 | return __pte(pte_val(pte) | _PAGE_RW); | 485 | return __pte(pte_val(pte) | _PAGE_RW); |
@@ -389,6 +505,16 @@ static inline pte_t pte_mkhuge(pte_t pte) | |||
389 | return pte; | 505 | return pte; |
390 | } | 506 | } |
391 | 507 | ||
508 | static inline pte_t pte_mkprivileged(pte_t pte) | ||
509 | { | ||
510 | return __pte(pte_val(pte) & ~_PAGE_USER); | ||
511 | } | ||
512 | |||
513 | static inline pte_t pte_mkuser(pte_t pte) | ||
514 | { | ||
515 | return __pte(pte_val(pte) | _PAGE_USER); | ||
516 | } | ||
517 | |||
392 | static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) | 518 | static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) |
393 | { | 519 | { |
394 | return __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot)); | 520 | return __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot)); |
diff --git a/arch/powerpc/include/asm/book3s/64/hash-4k.h b/arch/powerpc/include/asm/book3s/64/hash-4k.h index 9a3798660cef..15bc16b1dc9c 100644 --- a/arch/powerpc/include/asm/book3s/64/hash-4k.h +++ b/arch/powerpc/include/asm/book3s/64/hash-4k.h | |||
@@ -66,7 +66,7 @@ static inline int hash__hugepd_ok(hugepd_t hpd) | |||
66 | * if it is not a pte and have hugepd shift mask | 66 | * if it is not a pte and have hugepd shift mask |
67 | * set, then it is a hugepd directory pointer | 67 | * set, then it is a hugepd directory pointer |
68 | */ | 68 | */ |
69 | if (!(hpdval & _PAGE_PTE) && | 69 | if (!(hpdval & _PAGE_PTE) && (hpdval & _PAGE_PRESENT) && |
70 | ((hpdval & HUGEPD_SHIFT_MASK) != 0)) | 70 | ((hpdval & HUGEPD_SHIFT_MASK) != 0)) |
71 | return true; | 71 | return true; |
72 | return false; | 72 | return false; |
diff --git a/arch/powerpc/include/asm/book3s/64/hash.h b/arch/powerpc/include/asm/book3s/64/hash.h index d52a51b2ce7b..247aff9cc6ba 100644 --- a/arch/powerpc/include/asm/book3s/64/hash.h +++ b/arch/powerpc/include/asm/book3s/64/hash.h | |||
@@ -18,6 +18,11 @@ | |||
18 | #include <asm/book3s/64/hash-4k.h> | 18 | #include <asm/book3s/64/hash-4k.h> |
19 | #endif | 19 | #endif |
20 | 20 | ||
21 | /* Bits to set in a PMD/PUD/PGD entry valid bit*/ | ||
22 | #define HASH_PMD_VAL_BITS (0x8000000000000000UL) | ||
23 | #define HASH_PUD_VAL_BITS (0x8000000000000000UL) | ||
24 | #define HASH_PGD_VAL_BITS (0x8000000000000000UL) | ||
25 | |||
21 | /* | 26 | /* |
22 | * Size of EA range mapped by our pagetables. | 27 | * Size of EA range mapped by our pagetables. |
23 | */ | 28 | */ |
@@ -196,8 +201,7 @@ static inline void hpte_do_hugepage_flush(struct mm_struct *mm, | |||
196 | #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ | 201 | #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ |
197 | 202 | ||
198 | 203 | ||
199 | extern int hash__map_kernel_page(unsigned long ea, unsigned long pa, | 204 | int hash__map_kernel_page(unsigned long ea, unsigned long pa, pgprot_t prot); |
200 | unsigned long flags); | ||
201 | extern int __meminit hash__vmemmap_create_mapping(unsigned long start, | 205 | extern int __meminit hash__vmemmap_create_mapping(unsigned long start, |
202 | unsigned long page_size, | 206 | unsigned long page_size, |
203 | unsigned long phys); | 207 | unsigned long phys); |
diff --git a/arch/powerpc/include/asm/book3s/64/hugetlb.h b/arch/powerpc/include/asm/book3s/64/hugetlb.h index 50888388a359..5b0177733994 100644 --- a/arch/powerpc/include/asm/book3s/64/hugetlb.h +++ b/arch/powerpc/include/asm/book3s/64/hugetlb.h | |||
@@ -39,4 +39,7 @@ static inline bool gigantic_page_supported(void) | |||
39 | } | 39 | } |
40 | #endif | 40 | #endif |
41 | 41 | ||
42 | /* hugepd entry valid bit */ | ||
43 | #define HUGEPD_VAL_BITS (0x8000000000000000UL) | ||
44 | |||
42 | #endif | 45 | #endif |
diff --git a/arch/powerpc/include/asm/book3s/64/mmu-hash.h b/arch/powerpc/include/asm/book3s/64/mmu-hash.h index 66db23e2f4dc..12e522807f9f 100644 --- a/arch/powerpc/include/asm/book3s/64/mmu-hash.h +++ b/arch/powerpc/include/asm/book3s/64/mmu-hash.h | |||
@@ -30,7 +30,7 @@ | |||
30 | * SLB | 30 | * SLB |
31 | */ | 31 | */ |
32 | 32 | ||
33 | #define SLB_NUM_BOLTED 3 | 33 | #define SLB_NUM_BOLTED 2 |
34 | #define SLB_CACHE_ENTRIES 8 | 34 | #define SLB_CACHE_ENTRIES 8 |
35 | #define SLB_MIN_SIZE 32 | 35 | #define SLB_MIN_SIZE 32 |
36 | 36 | ||
@@ -499,6 +499,8 @@ int htab_remove_mapping(unsigned long vstart, unsigned long vend, | |||
499 | extern void pseries_add_gpage(u64 addr, u64 page_size, unsigned long number_of_pages); | 499 | extern void pseries_add_gpage(u64 addr, u64 page_size, unsigned long number_of_pages); |
500 | extern void demote_segment_4k(struct mm_struct *mm, unsigned long addr); | 500 | extern void demote_segment_4k(struct mm_struct *mm, unsigned long addr); |
501 | 501 | ||
502 | extern void hash__setup_new_exec(void); | ||
503 | |||
502 | #ifdef CONFIG_PPC_PSERIES | 504 | #ifdef CONFIG_PPC_PSERIES |
503 | void hpte_init_pseries(void); | 505 | void hpte_init_pseries(void); |
504 | #else | 506 | #else |
@@ -507,11 +509,18 @@ static inline void hpte_init_pseries(void) { } | |||
507 | 509 | ||
508 | extern void hpte_init_native(void); | 510 | extern void hpte_init_native(void); |
509 | 511 | ||
512 | struct slb_entry { | ||
513 | u64 esid; | ||
514 | u64 vsid; | ||
515 | }; | ||
516 | |||
510 | extern void slb_initialize(void); | 517 | extern void slb_initialize(void); |
511 | extern void slb_flush_and_rebolt(void); | 518 | void slb_flush_and_restore_bolted(void); |
512 | void slb_flush_all_realmode(void); | 519 | void slb_flush_all_realmode(void); |
513 | void __slb_restore_bolted_realmode(void); | 520 | void __slb_restore_bolted_realmode(void); |
514 | void slb_restore_bolted_realmode(void); | 521 | void slb_restore_bolted_realmode(void); |
522 | void slb_save_contents(struct slb_entry *slb_ptr); | ||
523 | void slb_dump_contents(struct slb_entry *slb_ptr); | ||
515 | 524 | ||
516 | extern void slb_vmalloc_update(void); | 525 | extern void slb_vmalloc_update(void); |
517 | extern void slb_set_size(u16 size); | 526 | extern void slb_set_size(u16 size); |
@@ -524,13 +533,9 @@ extern void slb_set_size(u16 size); | |||
524 | * from mmu context id and effective segment id of the address. | 533 | * from mmu context id and effective segment id of the address. |
525 | * | 534 | * |
526 | * For user processes max context id is limited to MAX_USER_CONTEXT. | 535 | * For user processes max context id is limited to MAX_USER_CONTEXT. |
527 | 536 | * more details in get_user_context | |
528 | * For kernel space, we use context ids 1-4 to map addresses as below: | 537 | * |
529 | * NOTE: each context only support 64TB now. | 538 | * For kernel space get_kernel_context |
530 | * 0x00001 - [ 0xc000000000000000 - 0xc0003fffffffffff ] | ||
531 | * 0x00002 - [ 0xd000000000000000 - 0xd0003fffffffffff ] | ||
532 | * 0x00003 - [ 0xe000000000000000 - 0xe0003fffffffffff ] | ||
533 | * 0x00004 - [ 0xf000000000000000 - 0xf0003fffffffffff ] | ||
534 | * | 539 | * |
535 | * The proto-VSIDs are then scrambled into real VSIDs with the | 540 | * The proto-VSIDs are then scrambled into real VSIDs with the |
536 | * multiplicative hash: | 541 | * multiplicative hash: |
@@ -571,6 +576,21 @@ extern void slb_set_size(u16 size); | |||
571 | #define ESID_BITS_1T_MASK ((1 << ESID_BITS_1T) - 1) | 576 | #define ESID_BITS_1T_MASK ((1 << ESID_BITS_1T) - 1) |
572 | 577 | ||
573 | /* | 578 | /* |
579 | * Now certain config support MAX_PHYSMEM more than 512TB. Hence we will need | ||
580 | * to use more than one context for linear mapping the kernel. | ||
581 | * For vmalloc and memmap, we use just one context with 512TB. With 64 byte | ||
582 | * struct page size, we need ony 32 TB in memmap for 2PB (51 bits (MAX_PHYSMEM_BITS)). | ||
583 | */ | ||
584 | #if (MAX_PHYSMEM_BITS > MAX_EA_BITS_PER_CONTEXT) | ||
585 | #define MAX_KERNEL_CTX_CNT (1UL << (MAX_PHYSMEM_BITS - MAX_EA_BITS_PER_CONTEXT)) | ||
586 | #else | ||
587 | #define MAX_KERNEL_CTX_CNT 1 | ||
588 | #endif | ||
589 | |||
590 | #define MAX_VMALLOC_CTX_CNT 1 | ||
591 | #define MAX_MEMMAP_CTX_CNT 1 | ||
592 | |||
593 | /* | ||
574 | * 256MB segment | 594 | * 256MB segment |
575 | * The proto-VSID space has 2^(CONTEX_BITS + ESID_BITS) - 1 segments | 595 | * The proto-VSID space has 2^(CONTEX_BITS + ESID_BITS) - 1 segments |
576 | * available for user + kernel mapping. VSID 0 is reserved as invalid, contexts | 596 | * available for user + kernel mapping. VSID 0 is reserved as invalid, contexts |
@@ -580,12 +600,13 @@ extern void slb_set_size(u16 size); | |||
580 | * We also need to avoid the last segment of the last context, because that | 600 | * We also need to avoid the last segment of the last context, because that |
581 | * would give a protovsid of 0x1fffffffff. That will result in a VSID 0 | 601 | * would give a protovsid of 0x1fffffffff. That will result in a VSID 0 |
582 | * because of the modulo operation in vsid scramble. | 602 | * because of the modulo operation in vsid scramble. |
603 | * | ||
604 | * We add one extra context to MIN_USER_CONTEXT so that we can map kernel | ||
605 | * context easily. The +1 is to map the unused 0xe region mapping. | ||
583 | */ | 606 | */ |
584 | #define MAX_USER_CONTEXT ((ASM_CONST(1) << CONTEXT_BITS) - 2) | 607 | #define MAX_USER_CONTEXT ((ASM_CONST(1) << CONTEXT_BITS) - 2) |
585 | #define MIN_USER_CONTEXT (5) | 608 | #define MIN_USER_CONTEXT (MAX_KERNEL_CTX_CNT + MAX_VMALLOC_CTX_CNT + \ |
586 | 609 | MAX_MEMMAP_CTX_CNT + 2) | |
587 | /* Would be nice to use KERNEL_REGION_ID here */ | ||
588 | #define KERNEL_REGION_CONTEXT_OFFSET (0xc - 1) | ||
589 | 610 | ||
590 | /* | 611 | /* |
591 | * For platforms that support on 65bit VA we limit the context bits | 612 | * For platforms that support on 65bit VA we limit the context bits |
@@ -746,6 +767,39 @@ static inline unsigned long get_vsid(unsigned long context, unsigned long ea, | |||
746 | } | 767 | } |
747 | 768 | ||
748 | /* | 769 | /* |
770 | * For kernel space, we use context ids as below | ||
771 | * below. Range is 512TB per context. | ||
772 | * | ||
773 | * 0x00001 - [ 0xc000000000000000 - 0xc001ffffffffffff] | ||
774 | * 0x00002 - [ 0xc002000000000000 - 0xc003ffffffffffff] | ||
775 | * 0x00003 - [ 0xc004000000000000 - 0xc005ffffffffffff] | ||
776 | * 0x00004 - [ 0xc006000000000000 - 0xc007ffffffffffff] | ||
777 | |||
778 | * 0x00005 - [ 0xd000000000000000 - 0xd001ffffffffffff ] | ||
779 | * 0x00006 - Not used - Can map 0xe000000000000000 range. | ||
780 | * 0x00007 - [ 0xf000000000000000 - 0xf001ffffffffffff ] | ||
781 | * | ||
782 | * So we can compute the context from the region (top nibble) by | ||
783 | * subtracting 11, or 0xc - 1. | ||
784 | */ | ||
785 | static inline unsigned long get_kernel_context(unsigned long ea) | ||
786 | { | ||
787 | unsigned long region_id = REGION_ID(ea); | ||
788 | unsigned long ctx; | ||
789 | /* | ||
790 | * For linear mapping we do support multiple context | ||
791 | */ | ||
792 | if (region_id == KERNEL_REGION_ID) { | ||
793 | /* | ||
794 | * We already verified ea to be not beyond the addr limit. | ||
795 | */ | ||
796 | ctx = 1 + ((ea & ~REGION_MASK) >> MAX_EA_BITS_PER_CONTEXT); | ||
797 | } else | ||
798 | ctx = (region_id - 0xc) + MAX_KERNEL_CTX_CNT; | ||
799 | return ctx; | ||
800 | } | ||
801 | |||
802 | /* | ||
749 | * This is only valid for addresses >= PAGE_OFFSET | 803 | * This is only valid for addresses >= PAGE_OFFSET |
750 | */ | 804 | */ |
751 | static inline unsigned long get_kernel_vsid(unsigned long ea, int ssize) | 805 | static inline unsigned long get_kernel_vsid(unsigned long ea, int ssize) |
@@ -755,20 +809,7 @@ static inline unsigned long get_kernel_vsid(unsigned long ea, int ssize) | |||
755 | if (!is_kernel_addr(ea)) | 809 | if (!is_kernel_addr(ea)) |
756 | return 0; | 810 | return 0; |
757 | 811 | ||
758 | /* | 812 | context = get_kernel_context(ea); |
759 | * For kernel space, we use context ids 1-4 to map the address space as | ||
760 | * below: | ||
761 | * | ||
762 | * 0x00001 - [ 0xc000000000000000 - 0xc0003fffffffffff ] | ||
763 | * 0x00002 - [ 0xd000000000000000 - 0xd0003fffffffffff ] | ||
764 | * 0x00003 - [ 0xe000000000000000 - 0xe0003fffffffffff ] | ||
765 | * 0x00004 - [ 0xf000000000000000 - 0xf0003fffffffffff ] | ||
766 | * | ||
767 | * So we can compute the context from the region (top nibble) by | ||
768 | * subtracting 11, or 0xc - 1. | ||
769 | */ | ||
770 | context = (ea >> 60) - KERNEL_REGION_CONTEXT_OFFSET; | ||
771 | |||
772 | return get_vsid(context, ea, ssize); | 813 | return get_vsid(context, ea, ssize); |
773 | } | 814 | } |
774 | 815 | ||
diff --git a/arch/powerpc/include/asm/book3s/64/mmu.h b/arch/powerpc/include/asm/book3s/64/mmu.h index 9c8c669a6b6a..6328857f259f 100644 --- a/arch/powerpc/include/asm/book3s/64/mmu.h +++ b/arch/powerpc/include/asm/book3s/64/mmu.h | |||
@@ -208,7 +208,7 @@ extern void radix_init_pseries(void); | |||
208 | static inline void radix_init_pseries(void) { }; | 208 | static inline void radix_init_pseries(void) { }; |
209 | #endif | 209 | #endif |
210 | 210 | ||
211 | static inline int get_ea_context(mm_context_t *ctx, unsigned long ea) | 211 | static inline int get_user_context(mm_context_t *ctx, unsigned long ea) |
212 | { | 212 | { |
213 | int index = ea >> MAX_EA_BITS_PER_CONTEXT; | 213 | int index = ea >> MAX_EA_BITS_PER_CONTEXT; |
214 | 214 | ||
@@ -223,7 +223,7 @@ static inline int get_ea_context(mm_context_t *ctx, unsigned long ea) | |||
223 | static inline unsigned long get_user_vsid(mm_context_t *ctx, | 223 | static inline unsigned long get_user_vsid(mm_context_t *ctx, |
224 | unsigned long ea, int ssize) | 224 | unsigned long ea, int ssize) |
225 | { | 225 | { |
226 | unsigned long context = get_ea_context(ctx, ea); | 226 | unsigned long context = get_user_context(ctx, ea); |
227 | 227 | ||
228 | return get_vsid(context, ea, ssize); | 228 | return get_vsid(context, ea, ssize); |
229 | } | 229 | } |
diff --git a/arch/powerpc/include/asm/book3s/64/pgtable-64k.h b/arch/powerpc/include/asm/book3s/64/pgtable-64k.h index d7ee249d6890..e3d4dd4ae2fa 100644 --- a/arch/powerpc/include/asm/book3s/64/pgtable-64k.h +++ b/arch/powerpc/include/asm/book3s/64/pgtable-64k.h | |||
@@ -10,6 +10,9 @@ | |||
10 | * | 10 | * |
11 | * Defined in such a way that we can optimize away code block at build time | 11 | * Defined in such a way that we can optimize away code block at build time |
12 | * if CONFIG_HUGETLB_PAGE=n. | 12 | * if CONFIG_HUGETLB_PAGE=n. |
13 | * | ||
14 | * returns true for pmd migration entries, THP, devmap, hugetlb | ||
15 | * But compile time dependent on CONFIG_HUGETLB_PAGE | ||
13 | */ | 16 | */ |
14 | static inline int pmd_huge(pmd_t pmd) | 17 | static inline int pmd_huge(pmd_t pmd) |
15 | { | 18 | { |
diff --git a/arch/powerpc/include/asm/book3s/64/pgtable.h b/arch/powerpc/include/asm/book3s/64/pgtable.h index 2a2486526d1f..cb5dd4078d42 100644 --- a/arch/powerpc/include/asm/book3s/64/pgtable.h +++ b/arch/powerpc/include/asm/book3s/64/pgtable.h | |||
@@ -14,10 +14,6 @@ | |||
14 | */ | 14 | */ |
15 | #define _PAGE_BIT_SWAP_TYPE 0 | 15 | #define _PAGE_BIT_SWAP_TYPE 0 |
16 | 16 | ||
17 | #define _PAGE_NA 0 | ||
18 | #define _PAGE_RO 0 | ||
19 | #define _PAGE_USER 0 | ||
20 | |||
21 | #define _PAGE_EXEC 0x00001 /* execute permission */ | 17 | #define _PAGE_EXEC 0x00001 /* execute permission */ |
22 | #define _PAGE_WRITE 0x00002 /* write access allowed */ | 18 | #define _PAGE_WRITE 0x00002 /* write access allowed */ |
23 | #define _PAGE_READ 0x00004 /* read access allowed */ | 19 | #define _PAGE_READ 0x00004 /* read access allowed */ |
@@ -123,10 +119,6 @@ | |||
123 | #define _PAGE_KERNEL_RWX (_PAGE_PRIVILEGED | _PAGE_DIRTY | \ | 119 | #define _PAGE_KERNEL_RWX (_PAGE_PRIVILEGED | _PAGE_DIRTY | \ |
124 | _PAGE_RW | _PAGE_EXEC) | 120 | _PAGE_RW | _PAGE_EXEC) |
125 | /* | 121 | /* |
126 | * No page size encoding in the linux PTE | ||
127 | */ | ||
128 | #define _PAGE_PSIZE 0 | ||
129 | /* | ||
130 | * _PAGE_CHG_MASK masks of bits that are to be preserved across | 122 | * _PAGE_CHG_MASK masks of bits that are to be preserved across |
131 | * pgprot changes | 123 | * pgprot changes |
132 | */ | 124 | */ |
@@ -137,19 +129,12 @@ | |||
137 | #define H_PTE_PKEY (H_PTE_PKEY_BIT0 | H_PTE_PKEY_BIT1 | H_PTE_PKEY_BIT2 | \ | 129 | #define H_PTE_PKEY (H_PTE_PKEY_BIT0 | H_PTE_PKEY_BIT1 | H_PTE_PKEY_BIT2 | \ |
138 | H_PTE_PKEY_BIT3 | H_PTE_PKEY_BIT4) | 130 | H_PTE_PKEY_BIT3 | H_PTE_PKEY_BIT4) |
139 | /* | 131 | /* |
140 | * Mask of bits returned by pte_pgprot() | ||
141 | */ | ||
142 | #define PAGE_PROT_BITS (_PAGE_SAO | _PAGE_NON_IDEMPOTENT | _PAGE_TOLERANT | \ | ||
143 | H_PAGE_4K_PFN | _PAGE_PRIVILEGED | _PAGE_ACCESSED | \ | ||
144 | _PAGE_READ | _PAGE_WRITE | _PAGE_DIRTY | _PAGE_EXEC | \ | ||
145 | _PAGE_SOFT_DIRTY | H_PTE_PKEY) | ||
146 | /* | ||
147 | * We define 2 sets of base prot bits, one for basic pages (ie, | 132 | * We define 2 sets of base prot bits, one for basic pages (ie, |
148 | * cacheable kernel and user pages) and one for non cacheable | 133 | * cacheable kernel and user pages) and one for non cacheable |
149 | * pages. We always set _PAGE_COHERENT when SMP is enabled or | 134 | * pages. We always set _PAGE_COHERENT when SMP is enabled or |
150 | * the processor might need it for DMA coherency. | 135 | * the processor might need it for DMA coherency. |
151 | */ | 136 | */ |
152 | #define _PAGE_BASE_NC (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_PSIZE) | 137 | #define _PAGE_BASE_NC (_PAGE_PRESENT | _PAGE_ACCESSED) |
153 | #define _PAGE_BASE (_PAGE_BASE_NC) | 138 | #define _PAGE_BASE (_PAGE_BASE_NC) |
154 | 139 | ||
155 | /* Permission masks used to generate the __P and __S table, | 140 | /* Permission masks used to generate the __P and __S table, |
@@ -159,8 +144,6 @@ | |||
159 | * Write permissions imply read permissions for now (we could make write-only | 144 | * Write permissions imply read permissions for now (we could make write-only |
160 | * pages on BookE but we don't bother for now). Execute permission control is | 145 | * pages on BookE but we don't bother for now). Execute permission control is |
161 | * possible on platforms that define _PAGE_EXEC | 146 | * possible on platforms that define _PAGE_EXEC |
162 | * | ||
163 | * Note due to the way vm flags are laid out, the bits are XWR | ||
164 | */ | 147 | */ |
165 | #define PAGE_NONE __pgprot(_PAGE_BASE | _PAGE_PRIVILEGED) | 148 | #define PAGE_NONE __pgprot(_PAGE_BASE | _PAGE_PRIVILEGED) |
166 | #define PAGE_SHARED __pgprot(_PAGE_BASE | _PAGE_RW) | 149 | #define PAGE_SHARED __pgprot(_PAGE_BASE | _PAGE_RW) |
@@ -170,24 +153,6 @@ | |||
170 | #define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_READ) | 153 | #define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_READ) |
171 | #define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_READ | _PAGE_EXEC) | 154 | #define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_READ | _PAGE_EXEC) |
172 | 155 | ||
173 | #define __P000 PAGE_NONE | ||
174 | #define __P001 PAGE_READONLY | ||
175 | #define __P010 PAGE_COPY | ||
176 | #define __P011 PAGE_COPY | ||
177 | #define __P100 PAGE_READONLY_X | ||
178 | #define __P101 PAGE_READONLY_X | ||
179 | #define __P110 PAGE_COPY_X | ||
180 | #define __P111 PAGE_COPY_X | ||
181 | |||
182 | #define __S000 PAGE_NONE | ||
183 | #define __S001 PAGE_READONLY | ||
184 | #define __S010 PAGE_SHARED | ||
185 | #define __S011 PAGE_SHARED | ||
186 | #define __S100 PAGE_READONLY_X | ||
187 | #define __S101 PAGE_READONLY_X | ||
188 | #define __S110 PAGE_SHARED_X | ||
189 | #define __S111 PAGE_SHARED_X | ||
190 | |||
191 | /* Permission masks used for kernel mappings */ | 156 | /* Permission masks used for kernel mappings */ |
192 | #define PAGE_KERNEL __pgprot(_PAGE_BASE | _PAGE_KERNEL_RW) | 157 | #define PAGE_KERNEL __pgprot(_PAGE_BASE | _PAGE_KERNEL_RW) |
193 | #define PAGE_KERNEL_NC __pgprot(_PAGE_BASE_NC | _PAGE_KERNEL_RW | \ | 158 | #define PAGE_KERNEL_NC __pgprot(_PAGE_BASE_NC | _PAGE_KERNEL_RW | \ |
@@ -519,7 +484,11 @@ static inline int pte_special(pte_t pte) | |||
519 | return !!(pte_raw(pte) & cpu_to_be64(_PAGE_SPECIAL)); | 484 | return !!(pte_raw(pte) & cpu_to_be64(_PAGE_SPECIAL)); |
520 | } | 485 | } |
521 | 486 | ||
522 | static inline pgprot_t pte_pgprot(pte_t pte) { return __pgprot(pte_val(pte) & PAGE_PROT_BITS); } | 487 | static inline bool pte_exec(pte_t pte) |
488 | { | ||
489 | return !!(pte_raw(pte) & cpu_to_be64(_PAGE_EXEC)); | ||
490 | } | ||
491 | |||
523 | 492 | ||
524 | #ifdef CONFIG_HAVE_ARCH_SOFT_DIRTY | 493 | #ifdef CONFIG_HAVE_ARCH_SOFT_DIRTY |
525 | static inline bool pte_soft_dirty(pte_t pte) | 494 | static inline bool pte_soft_dirty(pte_t pte) |
@@ -529,12 +498,12 @@ static inline bool pte_soft_dirty(pte_t pte) | |||
529 | 498 | ||
530 | static inline pte_t pte_mksoft_dirty(pte_t pte) | 499 | static inline pte_t pte_mksoft_dirty(pte_t pte) |
531 | { | 500 | { |
532 | return __pte(pte_val(pte) | _PAGE_SOFT_DIRTY); | 501 | return __pte_raw(pte_raw(pte) | cpu_to_be64(_PAGE_SOFT_DIRTY)); |
533 | } | 502 | } |
534 | 503 | ||
535 | static inline pte_t pte_clear_soft_dirty(pte_t pte) | 504 | static inline pte_t pte_clear_soft_dirty(pte_t pte) |
536 | { | 505 | { |
537 | return __pte(pte_val(pte) & ~_PAGE_SOFT_DIRTY); | 506 | return __pte_raw(pte_raw(pte) & cpu_to_be64(~_PAGE_SOFT_DIRTY)); |
538 | } | 507 | } |
539 | #endif /* CONFIG_HAVE_ARCH_SOFT_DIRTY */ | 508 | #endif /* CONFIG_HAVE_ARCH_SOFT_DIRTY */ |
540 | 509 | ||
@@ -555,7 +524,7 @@ static inline pte_t pte_mk_savedwrite(pte_t pte) | |||
555 | */ | 524 | */ |
556 | VM_BUG_ON((pte_raw(pte) & cpu_to_be64(_PAGE_PRESENT | _PAGE_RWX | _PAGE_PRIVILEGED)) != | 525 | VM_BUG_ON((pte_raw(pte) & cpu_to_be64(_PAGE_PRESENT | _PAGE_RWX | _PAGE_PRIVILEGED)) != |
557 | cpu_to_be64(_PAGE_PRESENT | _PAGE_PRIVILEGED)); | 526 | cpu_to_be64(_PAGE_PRESENT | _PAGE_PRIVILEGED)); |
558 | return __pte(pte_val(pte) & ~_PAGE_PRIVILEGED); | 527 | return __pte_raw(pte_raw(pte) & cpu_to_be64(~_PAGE_PRIVILEGED)); |
559 | } | 528 | } |
560 | 529 | ||
561 | #define pte_clear_savedwrite pte_clear_savedwrite | 530 | #define pte_clear_savedwrite pte_clear_savedwrite |
@@ -565,14 +534,14 @@ static inline pte_t pte_clear_savedwrite(pte_t pte) | |||
565 | * Used by KSM subsystem to make a protnone pte readonly. | 534 | * Used by KSM subsystem to make a protnone pte readonly. |
566 | */ | 535 | */ |
567 | VM_BUG_ON(!pte_protnone(pte)); | 536 | VM_BUG_ON(!pte_protnone(pte)); |
568 | return __pte(pte_val(pte) | _PAGE_PRIVILEGED); | 537 | return __pte_raw(pte_raw(pte) | cpu_to_be64(_PAGE_PRIVILEGED)); |
569 | } | 538 | } |
570 | #else | 539 | #else |
571 | #define pte_clear_savedwrite pte_clear_savedwrite | 540 | #define pte_clear_savedwrite pte_clear_savedwrite |
572 | static inline pte_t pte_clear_savedwrite(pte_t pte) | 541 | static inline pte_t pte_clear_savedwrite(pte_t pte) |
573 | { | 542 | { |
574 | VM_WARN_ON(1); | 543 | VM_WARN_ON(1); |
575 | return __pte(pte_val(pte) & ~_PAGE_WRITE); | 544 | return __pte_raw(pte_raw(pte) & cpu_to_be64(~_PAGE_WRITE)); |
576 | } | 545 | } |
577 | #endif /* CONFIG_NUMA_BALANCING */ | 546 | #endif /* CONFIG_NUMA_BALANCING */ |
578 | 547 | ||
@@ -587,6 +556,11 @@ static inline int pte_present(pte_t pte) | |||
587 | return !!(pte_raw(pte) & cpu_to_be64(_PAGE_PRESENT | _PAGE_INVALID)); | 556 | return !!(pte_raw(pte) & cpu_to_be64(_PAGE_PRESENT | _PAGE_INVALID)); |
588 | } | 557 | } |
589 | 558 | ||
559 | static inline bool pte_hw_valid(pte_t pte) | ||
560 | { | ||
561 | return !!(pte_raw(pte) & cpu_to_be64(_PAGE_PRESENT)); | ||
562 | } | ||
563 | |||
590 | #ifdef CONFIG_PPC_MEM_KEYS | 564 | #ifdef CONFIG_PPC_MEM_KEYS |
591 | extern bool arch_pte_access_permitted(u64 pte, bool write, bool execute); | 565 | extern bool arch_pte_access_permitted(u64 pte, bool write, bool execute); |
592 | #else | 566 | #else |
@@ -596,25 +570,22 @@ static inline bool arch_pte_access_permitted(u64 pte, bool write, bool execute) | |||
596 | } | 570 | } |
597 | #endif /* CONFIG_PPC_MEM_KEYS */ | 571 | #endif /* CONFIG_PPC_MEM_KEYS */ |
598 | 572 | ||
573 | static inline bool pte_user(pte_t pte) | ||
574 | { | ||
575 | return !(pte_raw(pte) & cpu_to_be64(_PAGE_PRIVILEGED)); | ||
576 | } | ||
577 | |||
599 | #define pte_access_permitted pte_access_permitted | 578 | #define pte_access_permitted pte_access_permitted |
600 | static inline bool pte_access_permitted(pte_t pte, bool write) | 579 | static inline bool pte_access_permitted(pte_t pte, bool write) |
601 | { | 580 | { |
602 | unsigned long pteval = pte_val(pte); | ||
603 | /* Also check for pte_user */ | ||
604 | unsigned long clear_pte_bits = _PAGE_PRIVILEGED; | ||
605 | /* | 581 | /* |
606 | * _PAGE_READ is needed for any access and will be | 582 | * _PAGE_READ is needed for any access and will be |
607 | * cleared for PROT_NONE | 583 | * cleared for PROT_NONE |
608 | */ | 584 | */ |
609 | unsigned long need_pte_bits = _PAGE_PRESENT | _PAGE_READ; | 585 | if (!pte_present(pte) || !pte_user(pte) || !pte_read(pte)) |
610 | |||
611 | if (write) | ||
612 | need_pte_bits |= _PAGE_WRITE; | ||
613 | |||
614 | if ((pteval & need_pte_bits) != need_pte_bits) | ||
615 | return false; | 586 | return false; |
616 | 587 | ||
617 | if ((pteval & clear_pte_bits) == clear_pte_bits) | 588 | if (write && !pte_write(pte)) |
618 | return false; | 589 | return false; |
619 | 590 | ||
620 | return arch_pte_access_permitted(pte_val(pte), write, 0); | 591 | return arch_pte_access_permitted(pte_val(pte), write, 0); |
@@ -643,17 +614,32 @@ static inline pte_t pte_wrprotect(pte_t pte) | |||
643 | { | 614 | { |
644 | if (unlikely(pte_savedwrite(pte))) | 615 | if (unlikely(pte_savedwrite(pte))) |
645 | return pte_clear_savedwrite(pte); | 616 | return pte_clear_savedwrite(pte); |
646 | return __pte(pte_val(pte) & ~_PAGE_WRITE); | 617 | return __pte_raw(pte_raw(pte) & cpu_to_be64(~_PAGE_WRITE)); |
618 | } | ||
619 | |||
620 | static inline pte_t pte_exprotect(pte_t pte) | ||
621 | { | ||
622 | return __pte_raw(pte_raw(pte) & cpu_to_be64(~_PAGE_EXEC)); | ||
647 | } | 623 | } |
648 | 624 | ||
649 | static inline pte_t pte_mkclean(pte_t pte) | 625 | static inline pte_t pte_mkclean(pte_t pte) |
650 | { | 626 | { |
651 | return __pte(pte_val(pte) & ~_PAGE_DIRTY); | 627 | return __pte_raw(pte_raw(pte) & cpu_to_be64(~_PAGE_DIRTY)); |
652 | } | 628 | } |
653 | 629 | ||
654 | static inline pte_t pte_mkold(pte_t pte) | 630 | static inline pte_t pte_mkold(pte_t pte) |
655 | { | 631 | { |
656 | return __pte(pte_val(pte) & ~_PAGE_ACCESSED); | 632 | return __pte_raw(pte_raw(pte) & cpu_to_be64(~_PAGE_ACCESSED)); |
633 | } | ||
634 | |||
635 | static inline pte_t pte_mkexec(pte_t pte) | ||
636 | { | ||
637 | return __pte_raw(pte_raw(pte) | cpu_to_be64(_PAGE_EXEC)); | ||
638 | } | ||
639 | |||
640 | static inline pte_t pte_mkpte(pte_t pte) | ||
641 | { | ||
642 | return __pte_raw(pte_raw(pte) | cpu_to_be64(_PAGE_PTE)); | ||
657 | } | 643 | } |
658 | 644 | ||
659 | static inline pte_t pte_mkwrite(pte_t pte) | 645 | static inline pte_t pte_mkwrite(pte_t pte) |
@@ -661,22 +647,22 @@ static inline pte_t pte_mkwrite(pte_t pte) | |||
661 | /* | 647 | /* |
662 | * write implies read, hence set both | 648 | * write implies read, hence set both |
663 | */ | 649 | */ |
664 | return __pte(pte_val(pte) | _PAGE_RW); | 650 | return __pte_raw(pte_raw(pte) | cpu_to_be64(_PAGE_RW)); |
665 | } | 651 | } |
666 | 652 | ||
667 | static inline pte_t pte_mkdirty(pte_t pte) | 653 | static inline pte_t pte_mkdirty(pte_t pte) |
668 | { | 654 | { |
669 | return __pte(pte_val(pte) | _PAGE_DIRTY | _PAGE_SOFT_DIRTY); | 655 | return __pte_raw(pte_raw(pte) | cpu_to_be64(_PAGE_DIRTY | _PAGE_SOFT_DIRTY)); |
670 | } | 656 | } |
671 | 657 | ||
672 | static inline pte_t pte_mkyoung(pte_t pte) | 658 | static inline pte_t pte_mkyoung(pte_t pte) |
673 | { | 659 | { |
674 | return __pte(pte_val(pte) | _PAGE_ACCESSED); | 660 | return __pte_raw(pte_raw(pte) | cpu_to_be64(_PAGE_ACCESSED)); |
675 | } | 661 | } |
676 | 662 | ||
677 | static inline pte_t pte_mkspecial(pte_t pte) | 663 | static inline pte_t pte_mkspecial(pte_t pte) |
678 | { | 664 | { |
679 | return __pte(pte_val(pte) | _PAGE_SPECIAL); | 665 | return __pte_raw(pte_raw(pte) | cpu_to_be64(_PAGE_SPECIAL)); |
680 | } | 666 | } |
681 | 667 | ||
682 | static inline pte_t pte_mkhuge(pte_t pte) | 668 | static inline pte_t pte_mkhuge(pte_t pte) |
@@ -686,7 +672,17 @@ static inline pte_t pte_mkhuge(pte_t pte) | |||
686 | 672 | ||
687 | static inline pte_t pte_mkdevmap(pte_t pte) | 673 | static inline pte_t pte_mkdevmap(pte_t pte) |
688 | { | 674 | { |
689 | return __pte(pte_val(pte) | _PAGE_SPECIAL|_PAGE_DEVMAP); | 675 | return __pte_raw(pte_raw(pte) | cpu_to_be64(_PAGE_SPECIAL | _PAGE_DEVMAP)); |
676 | } | ||
677 | |||
678 | static inline pte_t pte_mkprivileged(pte_t pte) | ||
679 | { | ||
680 | return __pte_raw(pte_raw(pte) | cpu_to_be64(_PAGE_PRIVILEGED)); | ||
681 | } | ||
682 | |||
683 | static inline pte_t pte_mkuser(pte_t pte) | ||
684 | { | ||
685 | return __pte_raw(pte_raw(pte) & cpu_to_be64(~_PAGE_PRIVILEGED)); | ||
690 | } | 686 | } |
691 | 687 | ||
692 | /* | 688 | /* |
@@ -705,12 +701,8 @@ static inline int pte_devmap(pte_t pte) | |||
705 | static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) | 701 | static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) |
706 | { | 702 | { |
707 | /* FIXME!! check whether this need to be a conditional */ | 703 | /* FIXME!! check whether this need to be a conditional */ |
708 | return __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot)); | 704 | return __pte_raw((pte_raw(pte) & cpu_to_be64(_PAGE_CHG_MASK)) | |
709 | } | 705 | cpu_to_be64(pgprot_val(newprot))); |
710 | |||
711 | static inline bool pte_user(pte_t pte) | ||
712 | { | ||
713 | return !(pte_raw(pte) & cpu_to_be64(_PAGE_PRIVILEGED)); | ||
714 | } | 706 | } |
715 | 707 | ||
716 | /* Encode and de-code a swap entry */ | 708 | /* Encode and de-code a swap entry */ |
@@ -741,6 +733,8 @@ static inline bool pte_user(pte_t pte) | |||
741 | */ | 733 | */ |
742 | #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val((pte)) & ~_PAGE_PTE }) | 734 | #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val((pte)) & ~_PAGE_PTE }) |
743 | #define __swp_entry_to_pte(x) __pte((x).val | _PAGE_PTE) | 735 | #define __swp_entry_to_pte(x) __pte((x).val | _PAGE_PTE) |
736 | #define __pmd_to_swp_entry(pmd) (__pte_to_swp_entry(pmd_pte(pmd))) | ||
737 | #define __swp_entry_to_pmd(x) (pte_pmd(__swp_entry_to_pte(x))) | ||
744 | 738 | ||
745 | #ifdef CONFIG_MEM_SOFT_DIRTY | 739 | #ifdef CONFIG_MEM_SOFT_DIRTY |
746 | #define _PAGE_SWP_SOFT_DIRTY (1UL << (SWP_TYPE_BITS + _PAGE_BIT_SWAP_TYPE)) | 740 | #define _PAGE_SWP_SOFT_DIRTY (1UL << (SWP_TYPE_BITS + _PAGE_BIT_SWAP_TYPE)) |
@@ -751,7 +745,7 @@ static inline bool pte_user(pte_t pte) | |||
751 | #ifdef CONFIG_HAVE_ARCH_SOFT_DIRTY | 745 | #ifdef CONFIG_HAVE_ARCH_SOFT_DIRTY |
752 | static inline pte_t pte_swp_mksoft_dirty(pte_t pte) | 746 | static inline pte_t pte_swp_mksoft_dirty(pte_t pte) |
753 | { | 747 | { |
754 | return __pte(pte_val(pte) | _PAGE_SWP_SOFT_DIRTY); | 748 | return __pte_raw(pte_raw(pte) | cpu_to_be64(_PAGE_SWP_SOFT_DIRTY)); |
755 | } | 749 | } |
756 | 750 | ||
757 | static inline bool pte_swp_soft_dirty(pte_t pte) | 751 | static inline bool pte_swp_soft_dirty(pte_t pte) |
@@ -761,7 +755,7 @@ static inline bool pte_swp_soft_dirty(pte_t pte) | |||
761 | 755 | ||
762 | static inline pte_t pte_swp_clear_soft_dirty(pte_t pte) | 756 | static inline pte_t pte_swp_clear_soft_dirty(pte_t pte) |
763 | { | 757 | { |
764 | return __pte(pte_val(pte) & ~_PAGE_SWP_SOFT_DIRTY); | 758 | return __pte_raw(pte_raw(pte) & cpu_to_be64(~_PAGE_SWP_SOFT_DIRTY)); |
765 | } | 759 | } |
766 | #endif /* CONFIG_HAVE_ARCH_SOFT_DIRTY */ | 760 | #endif /* CONFIG_HAVE_ARCH_SOFT_DIRTY */ |
767 | 761 | ||
@@ -850,10 +844,10 @@ static inline pgprot_t pgprot_writecombine(pgprot_t prot) | |||
850 | */ | 844 | */ |
851 | static inline bool pte_ci(pte_t pte) | 845 | static inline bool pte_ci(pte_t pte) |
852 | { | 846 | { |
853 | unsigned long pte_v = pte_val(pte); | 847 | __be64 pte_v = pte_raw(pte); |
854 | 848 | ||
855 | if (((pte_v & _PAGE_CACHE_CTL) == _PAGE_TOLERANT) || | 849 | if (((pte_v & cpu_to_be64(_PAGE_CACHE_CTL)) == cpu_to_be64(_PAGE_TOLERANT)) || |
856 | ((pte_v & _PAGE_CACHE_CTL) == _PAGE_NON_IDEMPOTENT)) | 850 | ((pte_v & cpu_to_be64(_PAGE_CACHE_CTL)) == cpu_to_be64(_PAGE_NON_IDEMPOTENT))) |
857 | return true; | 851 | return true; |
858 | return false; | 852 | return false; |
859 | } | 853 | } |
@@ -875,8 +869,16 @@ static inline int pmd_none(pmd_t pmd) | |||
875 | 869 | ||
876 | static inline int pmd_present(pmd_t pmd) | 870 | static inline int pmd_present(pmd_t pmd) |
877 | { | 871 | { |
872 | /* | ||
873 | * A pmd is considerent present if _PAGE_PRESENT is set. | ||
874 | * We also need to consider the pmd present which is marked | ||
875 | * invalid during a split. Hence we look for _PAGE_INVALID | ||
876 | * if we find _PAGE_PRESENT cleared. | ||
877 | */ | ||
878 | if (pmd_raw(pmd) & cpu_to_be64(_PAGE_PRESENT | _PAGE_INVALID)) | ||
879 | return true; | ||
878 | 880 | ||
879 | return !pmd_none(pmd); | 881 | return false; |
880 | } | 882 | } |
881 | 883 | ||
882 | static inline int pmd_bad(pmd_t pmd) | 884 | static inline int pmd_bad(pmd_t pmd) |
@@ -903,7 +905,7 @@ static inline int pud_none(pud_t pud) | |||
903 | 905 | ||
904 | static inline int pud_present(pud_t pud) | 906 | static inline int pud_present(pud_t pud) |
905 | { | 907 | { |
906 | return !pud_none(pud); | 908 | return (pud_raw(pud) & cpu_to_be64(_PAGE_PRESENT)); |
907 | } | 909 | } |
908 | 910 | ||
909 | extern struct page *pud_page(pud_t pud); | 911 | extern struct page *pud_page(pud_t pud); |
@@ -950,7 +952,7 @@ static inline int pgd_none(pgd_t pgd) | |||
950 | 952 | ||
951 | static inline int pgd_present(pgd_t pgd) | 953 | static inline int pgd_present(pgd_t pgd) |
952 | { | 954 | { |
953 | return !pgd_none(pgd); | 955 | return (pgd_raw(pgd) & cpu_to_be64(_PAGE_PRESENT)); |
954 | } | 956 | } |
955 | 957 | ||
956 | static inline pte_t pgd_pte(pgd_t pgd) | 958 | static inline pte_t pgd_pte(pgd_t pgd) |
@@ -1020,17 +1022,16 @@ extern struct page *pgd_page(pgd_t pgd); | |||
1020 | #define pgd_ERROR(e) \ | 1022 | #define pgd_ERROR(e) \ |
1021 | pr_err("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e)) | 1023 | pr_err("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e)) |
1022 | 1024 | ||
1023 | static inline int map_kernel_page(unsigned long ea, unsigned long pa, | 1025 | static inline int map_kernel_page(unsigned long ea, unsigned long pa, pgprot_t prot) |
1024 | unsigned long flags) | ||
1025 | { | 1026 | { |
1026 | if (radix_enabled()) { | 1027 | if (radix_enabled()) { |
1027 | #if defined(CONFIG_PPC_RADIX_MMU) && defined(DEBUG_VM) | 1028 | #if defined(CONFIG_PPC_RADIX_MMU) && defined(DEBUG_VM) |
1028 | unsigned long page_size = 1 << mmu_psize_defs[mmu_io_psize].shift; | 1029 | unsigned long page_size = 1 << mmu_psize_defs[mmu_io_psize].shift; |
1029 | WARN((page_size != PAGE_SIZE), "I/O page size != PAGE_SIZE"); | 1030 | WARN((page_size != PAGE_SIZE), "I/O page size != PAGE_SIZE"); |
1030 | #endif | 1031 | #endif |
1031 | return radix__map_kernel_page(ea, pa, __pgprot(flags), PAGE_SIZE); | 1032 | return radix__map_kernel_page(ea, pa, prot, PAGE_SIZE); |
1032 | } | 1033 | } |
1033 | return hash__map_kernel_page(ea, pa, flags); | 1034 | return hash__map_kernel_page(ea, pa, prot); |
1034 | } | 1035 | } |
1035 | 1036 | ||
1036 | static inline int __meminit vmemmap_create_mapping(unsigned long start, | 1037 | static inline int __meminit vmemmap_create_mapping(unsigned long start, |
@@ -1082,6 +1083,12 @@ static inline pte_t *pmdp_ptep(pmd_t *pmd) | |||
1082 | #define pmd_soft_dirty(pmd) pte_soft_dirty(pmd_pte(pmd)) | 1083 | #define pmd_soft_dirty(pmd) pte_soft_dirty(pmd_pte(pmd)) |
1083 | #define pmd_mksoft_dirty(pmd) pte_pmd(pte_mksoft_dirty(pmd_pte(pmd))) | 1084 | #define pmd_mksoft_dirty(pmd) pte_pmd(pte_mksoft_dirty(pmd_pte(pmd))) |
1084 | #define pmd_clear_soft_dirty(pmd) pte_pmd(pte_clear_soft_dirty(pmd_pte(pmd))) | 1085 | #define pmd_clear_soft_dirty(pmd) pte_pmd(pte_clear_soft_dirty(pmd_pte(pmd))) |
1086 | |||
1087 | #ifdef CONFIG_ARCH_ENABLE_THP_MIGRATION | ||
1088 | #define pmd_swp_mksoft_dirty(pmd) pte_pmd(pte_swp_mksoft_dirty(pmd_pte(pmd))) | ||
1089 | #define pmd_swp_soft_dirty(pmd) pte_swp_soft_dirty(pmd_pte(pmd)) | ||
1090 | #define pmd_swp_clear_soft_dirty(pmd) pte_pmd(pte_swp_clear_soft_dirty(pmd_pte(pmd))) | ||
1091 | #endif | ||
1085 | #endif /* CONFIG_HAVE_ARCH_SOFT_DIRTY */ | 1092 | #endif /* CONFIG_HAVE_ARCH_SOFT_DIRTY */ |
1086 | 1093 | ||
1087 | #ifdef CONFIG_NUMA_BALANCING | 1094 | #ifdef CONFIG_NUMA_BALANCING |
@@ -1127,6 +1134,10 @@ pmd_hugepage_update(struct mm_struct *mm, unsigned long addr, pmd_t *pmdp, | |||
1127 | return hash__pmd_hugepage_update(mm, addr, pmdp, clr, set); | 1134 | return hash__pmd_hugepage_update(mm, addr, pmdp, clr, set); |
1128 | } | 1135 | } |
1129 | 1136 | ||
1137 | /* | ||
1138 | * returns true for pmd migration entries, THP, devmap, hugetlb | ||
1139 | * But compile time dependent on THP config | ||
1140 | */ | ||
1130 | static inline int pmd_large(pmd_t pmd) | 1141 | static inline int pmd_large(pmd_t pmd) |
1131 | { | 1142 | { |
1132 | return !!(pmd_raw(pmd) & cpu_to_be64(_PAGE_PTE)); | 1143 | return !!(pmd_raw(pmd) & cpu_to_be64(_PAGE_PTE)); |
@@ -1161,8 +1172,22 @@ static inline void pmdp_set_wrprotect(struct mm_struct *mm, unsigned long addr, | |||
1161 | pmd_hugepage_update(mm, addr, pmdp, 0, _PAGE_PRIVILEGED); | 1172 | pmd_hugepage_update(mm, addr, pmdp, 0, _PAGE_PRIVILEGED); |
1162 | } | 1173 | } |
1163 | 1174 | ||
1175 | /* | ||
1176 | * Only returns true for a THP. False for pmd migration entry. | ||
1177 | * We also need to return true when we come across a pte that | ||
1178 | * in between a thp split. While splitting THP, we mark the pmd | ||
1179 | * invalid (pmdp_invalidate()) before we set it with pte page | ||
1180 | * address. A pmd_trans_huge() check against a pmd entry during that time | ||
1181 | * should return true. | ||
1182 | * We should not call this on a hugetlb entry. We should check for HugeTLB | ||
1183 | * entry using vma->vm_flags | ||
1184 | * The page table walk rule is explained in Documentation/vm/transhuge.rst | ||
1185 | */ | ||
1164 | static inline int pmd_trans_huge(pmd_t pmd) | 1186 | static inline int pmd_trans_huge(pmd_t pmd) |
1165 | { | 1187 | { |
1188 | if (!pmd_present(pmd)) | ||
1189 | return false; | ||
1190 | |||
1166 | if (radix_enabled()) | 1191 | if (radix_enabled()) |
1167 | return radix__pmd_trans_huge(pmd); | 1192 | return radix__pmd_trans_huge(pmd); |
1168 | return hash__pmd_trans_huge(pmd); | 1193 | return hash__pmd_trans_huge(pmd); |
diff --git a/arch/powerpc/include/asm/cputhreads.h b/arch/powerpc/include/asm/cputhreads.h index d71a90924f3b..deb99fd6e060 100644 --- a/arch/powerpc/include/asm/cputhreads.h +++ b/arch/powerpc/include/asm/cputhreads.h | |||
@@ -23,11 +23,13 @@ | |||
23 | extern int threads_per_core; | 23 | extern int threads_per_core; |
24 | extern int threads_per_subcore; | 24 | extern int threads_per_subcore; |
25 | extern int threads_shift; | 25 | extern int threads_shift; |
26 | extern bool has_big_cores; | ||
26 | extern cpumask_t threads_core_mask; | 27 | extern cpumask_t threads_core_mask; |
27 | #else | 28 | #else |
28 | #define threads_per_core 1 | 29 | #define threads_per_core 1 |
29 | #define threads_per_subcore 1 | 30 | #define threads_per_subcore 1 |
30 | #define threads_shift 0 | 31 | #define threads_shift 0 |
32 | #define has_big_cores 0 | ||
31 | #define threads_core_mask (*get_cpu_mask(0)) | 33 | #define threads_core_mask (*get_cpu_mask(0)) |
32 | #endif | 34 | #endif |
33 | 35 | ||
diff --git a/arch/powerpc/include/asm/cputime.h b/arch/powerpc/include/asm/cputime.h index 133672744b2e..ae73dc8da2d4 100644 --- a/arch/powerpc/include/asm/cputime.h +++ b/arch/powerpc/include/asm/cputime.h | |||
@@ -61,7 +61,6 @@ static inline void arch_vtime_task_switch(struct task_struct *prev) | |||
61 | struct cpu_accounting_data *acct0 = get_accounting(prev); | 61 | struct cpu_accounting_data *acct0 = get_accounting(prev); |
62 | 62 | ||
63 | acct->starttime = acct0->starttime; | 63 | acct->starttime = acct0->starttime; |
64 | acct->startspurr = acct0->startspurr; | ||
65 | } | 64 | } |
66 | #endif | 65 | #endif |
67 | 66 | ||
diff --git a/arch/powerpc/include/asm/drmem.h b/arch/powerpc/include/asm/drmem.h index ce242b9ea8c6..7c1d8e74b25d 100644 --- a/arch/powerpc/include/asm/drmem.h +++ b/arch/powerpc/include/asm/drmem.h | |||
@@ -99,4 +99,9 @@ void __init walk_drmem_lmbs_early(unsigned long node, | |||
99 | void (*func)(struct drmem_lmb *, const __be32 **)); | 99 | void (*func)(struct drmem_lmb *, const __be32 **)); |
100 | #endif | 100 | #endif |
101 | 101 | ||
102 | static inline void invalidate_lmb_associativity_index(struct drmem_lmb *lmb) | ||
103 | { | ||
104 | lmb->aa_index = 0xffffffff; | ||
105 | } | ||
106 | |||
102 | #endif /* _ASM_POWERPC_LMB_H */ | 107 | #endif /* _ASM_POWERPC_LMB_H */ |
diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h index 219637ea69a1..8b596d096ebe 100644 --- a/arch/powerpc/include/asm/eeh.h +++ b/arch/powerpc/include/asm/eeh.h | |||
@@ -43,7 +43,6 @@ struct pci_dn; | |||
43 | #define EEH_VALID_PE_ZERO 0x10 /* PE#0 is valid */ | 43 | #define EEH_VALID_PE_ZERO 0x10 /* PE#0 is valid */ |
44 | #define EEH_ENABLE_IO_FOR_LOG 0x20 /* Enable IO for log */ | 44 | #define EEH_ENABLE_IO_FOR_LOG 0x20 /* Enable IO for log */ |
45 | #define EEH_EARLY_DUMP_LOG 0x40 /* Dump log immediately */ | 45 | #define EEH_EARLY_DUMP_LOG 0x40 /* Dump log immediately */ |
46 | #define EEH_POSTPONED_PROBE 0x80 /* Powernv may postpone device probe */ | ||
47 | 46 | ||
48 | /* | 47 | /* |
49 | * Delay for PE reset, all in ms | 48 | * Delay for PE reset, all in ms |
@@ -99,13 +98,13 @@ struct eeh_pe { | |||
99 | atomic_t pass_dev_cnt; /* Count of passed through devs */ | 98 | atomic_t pass_dev_cnt; /* Count of passed through devs */ |
100 | struct eeh_pe *parent; /* Parent PE */ | 99 | struct eeh_pe *parent; /* Parent PE */ |
101 | void *data; /* PE auxillary data */ | 100 | void *data; /* PE auxillary data */ |
102 | struct list_head child_list; /* Link PE to the child list */ | 101 | struct list_head child_list; /* List of PEs below this PE */ |
103 | struct list_head edevs; /* Link list of EEH devices */ | 102 | struct list_head child; /* Memb. child_list/eeh_phb_pe */ |
104 | struct list_head child; /* Child PEs */ | 103 | struct list_head edevs; /* List of eeh_dev in this PE */ |
105 | }; | 104 | }; |
106 | 105 | ||
107 | #define eeh_pe_for_each_dev(pe, edev, tmp) \ | 106 | #define eeh_pe_for_each_dev(pe, edev, tmp) \ |
108 | list_for_each_entry_safe(edev, tmp, &pe->edevs, list) | 107 | list_for_each_entry_safe(edev, tmp, &pe->edevs, entry) |
109 | 108 | ||
110 | #define eeh_for_each_pe(root, pe) \ | 109 | #define eeh_for_each_pe(root, pe) \ |
111 | for (pe = root; pe; pe = eeh_pe_next(pe, root)) | 110 | for (pe = root; pe; pe = eeh_pe_next(pe, root)) |
@@ -142,13 +141,12 @@ struct eeh_dev { | |||
142 | int aer_cap; /* Saved AER capability */ | 141 | int aer_cap; /* Saved AER capability */ |
143 | int af_cap; /* Saved AF capability */ | 142 | int af_cap; /* Saved AF capability */ |
144 | struct eeh_pe *pe; /* Associated PE */ | 143 | struct eeh_pe *pe; /* Associated PE */ |
145 | struct list_head list; /* Form link list in the PE */ | 144 | struct list_head entry; /* Membership in eeh_pe.edevs */ |
146 | struct list_head rmv_list; /* Record the removed edevs */ | 145 | struct list_head rmv_entry; /* Membership in rmv_list */ |
147 | struct pci_dn *pdn; /* Associated PCI device node */ | 146 | struct pci_dn *pdn; /* Associated PCI device node */ |
148 | struct pci_dev *pdev; /* Associated PCI device */ | 147 | struct pci_dev *pdev; /* Associated PCI device */ |
149 | bool in_error; /* Error flag for edev */ | 148 | bool in_error; /* Error flag for edev */ |
150 | struct pci_dev *physfn; /* Associated SRIOV PF */ | 149 | struct pci_dev *physfn; /* Associated SRIOV PF */ |
151 | struct pci_bus *bus; /* PCI bus for partial hotplug */ | ||
152 | }; | 150 | }; |
153 | 151 | ||
154 | static inline struct pci_dn *eeh_dev_to_pdn(struct eeh_dev *edev) | 152 | static inline struct pci_dn *eeh_dev_to_pdn(struct eeh_dev *edev) |
@@ -207,9 +205,8 @@ struct eeh_ops { | |||
207 | void* (*probe)(struct pci_dn *pdn, void *data); | 205 | void* (*probe)(struct pci_dn *pdn, void *data); |
208 | int (*set_option)(struct eeh_pe *pe, int option); | 206 | int (*set_option)(struct eeh_pe *pe, int option); |
209 | int (*get_pe_addr)(struct eeh_pe *pe); | 207 | int (*get_pe_addr)(struct eeh_pe *pe); |
210 | int (*get_state)(struct eeh_pe *pe, int *state); | 208 | int (*get_state)(struct eeh_pe *pe, int *delay); |
211 | int (*reset)(struct eeh_pe *pe, int option); | 209 | int (*reset)(struct eeh_pe *pe, int option); |
212 | int (*wait_state)(struct eeh_pe *pe, int max_wait); | ||
213 | int (*get_log)(struct eeh_pe *pe, int severity, char *drv_log, unsigned long len); | 210 | int (*get_log)(struct eeh_pe *pe, int severity, char *drv_log, unsigned long len); |
214 | int (*configure_bridge)(struct eeh_pe *pe); | 211 | int (*configure_bridge)(struct eeh_pe *pe); |
215 | int (*err_inject)(struct eeh_pe *pe, int type, int func, | 212 | int (*err_inject)(struct eeh_pe *pe, int type, int func, |
@@ -243,11 +240,7 @@ static inline bool eeh_has_flag(int flag) | |||
243 | 240 | ||
244 | static inline bool eeh_enabled(void) | 241 | static inline bool eeh_enabled(void) |
245 | { | 242 | { |
246 | if (eeh_has_flag(EEH_FORCE_DISABLED) || | 243 | return eeh_has_flag(EEH_ENABLED) && !eeh_has_flag(EEH_FORCE_DISABLED); |
247 | !eeh_has_flag(EEH_ENABLED)) | ||
248 | return false; | ||
249 | |||
250 | return true; | ||
251 | } | 244 | } |
252 | 245 | ||
253 | static inline void eeh_serialize_lock(unsigned long *flags) | 246 | static inline void eeh_serialize_lock(unsigned long *flags) |
@@ -270,6 +263,7 @@ typedef void *(*eeh_edev_traverse_func)(struct eeh_dev *edev, void *flag); | |||
270 | typedef void *(*eeh_pe_traverse_func)(struct eeh_pe *pe, void *flag); | 263 | typedef void *(*eeh_pe_traverse_func)(struct eeh_pe *pe, void *flag); |
271 | void eeh_set_pe_aux_size(int size); | 264 | void eeh_set_pe_aux_size(int size); |
272 | int eeh_phb_pe_create(struct pci_controller *phb); | 265 | int eeh_phb_pe_create(struct pci_controller *phb); |
266 | int eeh_wait_state(struct eeh_pe *pe, int max_wait); | ||
273 | struct eeh_pe *eeh_phb_pe_get(struct pci_controller *phb); | 267 | struct eeh_pe *eeh_phb_pe_get(struct pci_controller *phb); |
274 | struct eeh_pe *eeh_pe_next(struct eeh_pe *pe, struct eeh_pe *root); | 268 | struct eeh_pe *eeh_pe_next(struct eeh_pe *pe, struct eeh_pe *root); |
275 | struct eeh_pe *eeh_pe_get(struct pci_controller *phb, | 269 | struct eeh_pe *eeh_pe_get(struct pci_controller *phb, |
diff --git a/arch/powerpc/include/asm/error-injection.h b/arch/powerpc/include/asm/error-injection.h new file mode 100644 index 000000000000..62fd24739852 --- /dev/null +++ b/arch/powerpc/include/asm/error-injection.h | |||
@@ -0,0 +1,13 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0+ */ | ||
2 | |||
3 | #ifndef _ASM_ERROR_INJECTION_H | ||
4 | #define _ASM_ERROR_INJECTION_H | ||
5 | |||
6 | #include <linux/compiler.h> | ||
7 | #include <linux/linkage.h> | ||
8 | #include <asm/ptrace.h> | ||
9 | #include <asm-generic/error-injection.h> | ||
10 | |||
11 | void override_function_with_return(struct pt_regs *regs); | ||
12 | |||
13 | #endif /* _ASM_ERROR_INJECTION_H */ | ||
diff --git a/arch/powerpc/include/asm/exception-64s.h b/arch/powerpc/include/asm/exception-64s.h index a86feddddad0..3b4767ed3ec5 100644 --- a/arch/powerpc/include/asm/exception-64s.h +++ b/arch/powerpc/include/asm/exception-64s.h | |||
@@ -61,14 +61,6 @@ | |||
61 | #define MAX_MCE_DEPTH 4 | 61 | #define MAX_MCE_DEPTH 4 |
62 | 62 | ||
63 | /* | 63 | /* |
64 | * EX_LR is only used in EXSLB and where it does not overlap with EX_DAR | ||
65 | * EX_CCR similarly with DSISR, but being 4 byte registers there is a hole | ||
66 | * in the save area so it's not necessary to overlap them. Could be used | ||
67 | * for future savings though if another 4 byte register was to be saved. | ||
68 | */ | ||
69 | #define EX_LR EX_DAR | ||
70 | |||
71 | /* | ||
72 | * EX_R3 is only used by the bad_stack handler. bad_stack reloads and | 64 | * EX_R3 is only used by the bad_stack handler. bad_stack reloads and |
73 | * saves DAR from SPRN_DAR, and EX_DAR is not used. So EX_R3 can overlap | 65 | * saves DAR from SPRN_DAR, and EX_DAR is not used. So EX_R3 can overlap |
74 | * with EX_DAR. | 66 | * with EX_DAR. |
@@ -236,11 +228,10 @@ | |||
236 | * PPR save/restore macros used in exceptions_64s.S | 228 | * PPR save/restore macros used in exceptions_64s.S |
237 | * Used for P7 or later processors | 229 | * Used for P7 or later processors |
238 | */ | 230 | */ |
239 | #define SAVE_PPR(area, ra, rb) \ | 231 | #define SAVE_PPR(area, ra) \ |
240 | BEGIN_FTR_SECTION_NESTED(940) \ | 232 | BEGIN_FTR_SECTION_NESTED(940) \ |
241 | ld ra,PACACURRENT(r13); \ | 233 | ld ra,area+EX_PPR(r13); /* Read PPR from paca */ \ |
242 | ld rb,area+EX_PPR(r13); /* Read PPR from paca */ \ | 234 | std ra,_PPR(r1); \ |
243 | std rb,TASKTHREADPPR(ra); \ | ||
244 | END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,CPU_FTR_HAS_PPR,940) | 235 | END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,CPU_FTR_HAS_PPR,940) |
245 | 236 | ||
246 | #define RESTORE_PPR_PACA(area, ra) \ | 237 | #define RESTORE_PPR_PACA(area, ra) \ |
@@ -508,7 +499,7 @@ END_FTR_SECTION_NESTED(ftr,ftr,943) | |||
508 | 3: EXCEPTION_PROLOG_COMMON_1(); \ | 499 | 3: EXCEPTION_PROLOG_COMMON_1(); \ |
509 | beq 4f; /* if from kernel mode */ \ | 500 | beq 4f; /* if from kernel mode */ \ |
510 | ACCOUNT_CPU_USER_ENTRY(r13, r9, r10); \ | 501 | ACCOUNT_CPU_USER_ENTRY(r13, r9, r10); \ |
511 | SAVE_PPR(area, r9, r10); \ | 502 | SAVE_PPR(area, r9); \ |
512 | 4: EXCEPTION_PROLOG_COMMON_2(area) \ | 503 | 4: EXCEPTION_PROLOG_COMMON_2(area) \ |
513 | EXCEPTION_PROLOG_COMMON_3(n) \ | 504 | EXCEPTION_PROLOG_COMMON_3(n) \ |
514 | ACCOUNT_STOLEN_TIME | 505 | ACCOUNT_STOLEN_TIME |
diff --git a/arch/powerpc/include/asm/firmware.h b/arch/powerpc/include/asm/firmware.h index 7a051bd21f87..00bc42d95679 100644 --- a/arch/powerpc/include/asm/firmware.h +++ b/arch/powerpc/include/asm/firmware.h | |||
@@ -52,6 +52,8 @@ | |||
52 | #define FW_FEATURE_PRRN ASM_CONST(0x0000000200000000) | 52 | #define FW_FEATURE_PRRN ASM_CONST(0x0000000200000000) |
53 | #define FW_FEATURE_DRMEM_V2 ASM_CONST(0x0000000400000000) | 53 | #define FW_FEATURE_DRMEM_V2 ASM_CONST(0x0000000400000000) |
54 | #define FW_FEATURE_DRC_INFO ASM_CONST(0x0000000800000000) | 54 | #define FW_FEATURE_DRC_INFO ASM_CONST(0x0000000800000000) |
55 | #define FW_FEATURE_BLOCK_REMOVE ASM_CONST(0x0000001000000000) | ||
56 | #define FW_FEATURE_PAPR_SCM ASM_CONST(0x0000002000000000) | ||
55 | 57 | ||
56 | #ifndef __ASSEMBLY__ | 58 | #ifndef __ASSEMBLY__ |
57 | 59 | ||
@@ -69,7 +71,8 @@ enum { | |||
69 | FW_FEATURE_SET_MODE | FW_FEATURE_BEST_ENERGY | | 71 | FW_FEATURE_SET_MODE | FW_FEATURE_BEST_ENERGY | |
70 | FW_FEATURE_TYPE1_AFFINITY | FW_FEATURE_PRRN | | 72 | FW_FEATURE_TYPE1_AFFINITY | FW_FEATURE_PRRN | |
71 | FW_FEATURE_HPT_RESIZE | FW_FEATURE_DRMEM_V2 | | 73 | FW_FEATURE_HPT_RESIZE | FW_FEATURE_DRMEM_V2 | |
72 | FW_FEATURE_DRC_INFO, | 74 | FW_FEATURE_DRC_INFO | FW_FEATURE_BLOCK_REMOVE | |
75 | FW_FEATURE_PAPR_SCM, | ||
73 | FW_FEATURE_PSERIES_ALWAYS = 0, | 76 | FW_FEATURE_PSERIES_ALWAYS = 0, |
74 | FW_FEATURE_POWERNV_POSSIBLE = FW_FEATURE_OPAL, | 77 | FW_FEATURE_POWERNV_POSSIBLE = FW_FEATURE_OPAL, |
75 | FW_FEATURE_POWERNV_ALWAYS = 0, | 78 | FW_FEATURE_POWERNV_ALWAYS = 0, |
diff --git a/arch/powerpc/include/asm/fixmap.h b/arch/powerpc/include/asm/fixmap.h index 41cc15c14eee..b9fbed84ddca 100644 --- a/arch/powerpc/include/asm/fixmap.h +++ b/arch/powerpc/include/asm/fixmap.h | |||
@@ -72,7 +72,7 @@ enum fixed_addresses { | |||
72 | static inline void __set_fixmap(enum fixed_addresses idx, | 72 | static inline void __set_fixmap(enum fixed_addresses idx, |
73 | phys_addr_t phys, pgprot_t flags) | 73 | phys_addr_t phys, pgprot_t flags) |
74 | { | 74 | { |
75 | map_kernel_page(fix_to_virt(idx), phys, pgprot_val(flags)); | 75 | map_kernel_page(fix_to_virt(idx), phys, flags); |
76 | } | 76 | } |
77 | 77 | ||
78 | #endif /* !__ASSEMBLY__ */ | 78 | #endif /* !__ASSEMBLY__ */ |
diff --git a/arch/powerpc/include/asm/hvcall.h b/arch/powerpc/include/asm/hvcall.h index 45e8789bb770..33a4fc891947 100644 --- a/arch/powerpc/include/asm/hvcall.h +++ b/arch/powerpc/include/asm/hvcall.h | |||
@@ -278,6 +278,7 @@ | |||
278 | #define H_COP 0x304 | 278 | #define H_COP 0x304 |
279 | #define H_GET_MPP_X 0x314 | 279 | #define H_GET_MPP_X 0x314 |
280 | #define H_SET_MODE 0x31C | 280 | #define H_SET_MODE 0x31C |
281 | #define H_BLOCK_REMOVE 0x328 | ||
281 | #define H_CLEAR_HPT 0x358 | 282 | #define H_CLEAR_HPT 0x358 |
282 | #define H_REQUEST_VMC 0x360 | 283 | #define H_REQUEST_VMC 0x360 |
283 | #define H_RESIZE_HPT_PREPARE 0x36C | 284 | #define H_RESIZE_HPT_PREPARE 0x36C |
@@ -295,7 +296,15 @@ | |||
295 | #define H_INT_ESB 0x3C8 | 296 | #define H_INT_ESB 0x3C8 |
296 | #define H_INT_SYNC 0x3CC | 297 | #define H_INT_SYNC 0x3CC |
297 | #define H_INT_RESET 0x3D0 | 298 | #define H_INT_RESET 0x3D0 |
298 | #define MAX_HCALL_OPCODE H_INT_RESET | 299 | #define H_SCM_READ_METADATA 0x3E4 |
300 | #define H_SCM_WRITE_METADATA 0x3E8 | ||
301 | #define H_SCM_BIND_MEM 0x3EC | ||
302 | #define H_SCM_UNBIND_MEM 0x3F0 | ||
303 | #define H_SCM_QUERY_BLOCK_MEM_BINDING 0x3F4 | ||
304 | #define H_SCM_QUERY_LOGICAL_MEM_BINDING 0x3F8 | ||
305 | #define H_SCM_MEM_QUERY 0x3FC | ||
306 | #define H_SCM_BLOCK_CLEAR 0x400 | ||
307 | #define MAX_HCALL_OPCODE H_SCM_BLOCK_CLEAR | ||
299 | 308 | ||
300 | /* H_VIOCTL functions */ | 309 | /* H_VIOCTL functions */ |
301 | #define H_GET_VIOA_DUMP_SIZE 0x01 | 310 | #define H_GET_VIOA_DUMP_SIZE 0x01 |
diff --git a/arch/powerpc/include/asm/io.h b/arch/powerpc/include/asm/io.h index e0331e754568..3ef40b703c4a 100644 --- a/arch/powerpc/include/asm/io.h +++ b/arch/powerpc/include/asm/io.h | |||
@@ -3,6 +3,9 @@ | |||
3 | #ifdef __KERNEL__ | 3 | #ifdef __KERNEL__ |
4 | 4 | ||
5 | #define ARCH_HAS_IOREMAP_WC | 5 | #define ARCH_HAS_IOREMAP_WC |
6 | #ifdef CONFIG_PPC32 | ||
7 | #define ARCH_HAS_IOREMAP_WT | ||
8 | #endif | ||
6 | 9 | ||
7 | /* | 10 | /* |
8 | * This program is free software; you can redistribute it and/or | 11 | * This program is free software; you can redistribute it and/or |
@@ -108,25 +111,6 @@ extern bool isa_io_special; | |||
108 | #define IO_SET_SYNC_FLAG() | 111 | #define IO_SET_SYNC_FLAG() |
109 | #endif | 112 | #endif |
110 | 113 | ||
111 | /* gcc 4.0 and older doesn't have 'Z' constraint */ | ||
112 | #if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ == 0) | ||
113 | #define DEF_MMIO_IN_X(name, size, insn) \ | ||
114 | static inline u##size name(const volatile u##size __iomem *addr) \ | ||
115 | { \ | ||
116 | u##size ret; \ | ||
117 | __asm__ __volatile__("sync;"#insn" %0,0,%1;twi 0,%0,0;isync" \ | ||
118 | : "=r" (ret) : "r" (addr), "m" (*addr) : "memory"); \ | ||
119 | return ret; \ | ||
120 | } | ||
121 | |||
122 | #define DEF_MMIO_OUT_X(name, size, insn) \ | ||
123 | static inline void name(volatile u##size __iomem *addr, u##size val) \ | ||
124 | { \ | ||
125 | __asm__ __volatile__("sync;"#insn" %1,0,%2" \ | ||
126 | : "=m" (*addr) : "r" (val), "r" (addr) : "memory"); \ | ||
127 | IO_SET_SYNC_FLAG(); \ | ||
128 | } | ||
129 | #else /* newer gcc */ | ||
130 | #define DEF_MMIO_IN_X(name, size, insn) \ | 114 | #define DEF_MMIO_IN_X(name, size, insn) \ |
131 | static inline u##size name(const volatile u##size __iomem *addr) \ | 115 | static inline u##size name(const volatile u##size __iomem *addr) \ |
132 | { \ | 116 | { \ |
@@ -143,7 +127,6 @@ static inline void name(volatile u##size __iomem *addr, u##size val) \ | |||
143 | : "=Z" (*addr) : "r" (val) : "memory"); \ | 127 | : "=Z" (*addr) : "r" (val) : "memory"); \ |
144 | IO_SET_SYNC_FLAG(); \ | 128 | IO_SET_SYNC_FLAG(); \ |
145 | } | 129 | } |
146 | #endif | ||
147 | 130 | ||
148 | #define DEF_MMIO_IN_D(name, size, insn) \ | 131 | #define DEF_MMIO_IN_D(name, size, insn) \ |
149 | static inline u##size name(const volatile u##size __iomem *addr) \ | 132 | static inline u##size name(const volatile u##size __iomem *addr) \ |
@@ -746,6 +729,10 @@ static inline void iosync(void) | |||
746 | * | 729 | * |
747 | * * ioremap_wc enables write combining | 730 | * * ioremap_wc enables write combining |
748 | * | 731 | * |
732 | * * ioremap_wt enables write through | ||
733 | * | ||
734 | * * ioremap_coherent maps coherent cached memory | ||
735 | * | ||
749 | * * iounmap undoes such a mapping and can be hooked | 736 | * * iounmap undoes such a mapping and can be hooked |
750 | * | 737 | * |
751 | * * __ioremap_at (and the pending __iounmap_at) are low level functions to | 738 | * * __ioremap_at (and the pending __iounmap_at) are low level functions to |
@@ -767,6 +754,8 @@ extern void __iomem *ioremap(phys_addr_t address, unsigned long size); | |||
767 | extern void __iomem *ioremap_prot(phys_addr_t address, unsigned long size, | 754 | extern void __iomem *ioremap_prot(phys_addr_t address, unsigned long size, |
768 | unsigned long flags); | 755 | unsigned long flags); |
769 | extern void __iomem *ioremap_wc(phys_addr_t address, unsigned long size); | 756 | extern void __iomem *ioremap_wc(phys_addr_t address, unsigned long size); |
757 | void __iomem *ioremap_wt(phys_addr_t address, unsigned long size); | ||
758 | void __iomem *ioremap_coherent(phys_addr_t address, unsigned long size); | ||
770 | #define ioremap_nocache(addr, size) ioremap((addr), (size)) | 759 | #define ioremap_nocache(addr, size) ioremap((addr), (size)) |
771 | #define ioremap_uc(addr, size) ioremap((addr), (size)) | 760 | #define ioremap_uc(addr, size) ioremap((addr), (size)) |
772 | #define ioremap_cache(addr, size) \ | 761 | #define ioremap_cache(addr, size) \ |
@@ -777,12 +766,12 @@ extern void iounmap(volatile void __iomem *addr); | |||
777 | extern void __iomem *__ioremap(phys_addr_t, unsigned long size, | 766 | extern void __iomem *__ioremap(phys_addr_t, unsigned long size, |
778 | unsigned long flags); | 767 | unsigned long flags); |
779 | extern void __iomem *__ioremap_caller(phys_addr_t, unsigned long size, | 768 | extern void __iomem *__ioremap_caller(phys_addr_t, unsigned long size, |
780 | unsigned long flags, void *caller); | 769 | pgprot_t prot, void *caller); |
781 | 770 | ||
782 | extern void __iounmap(volatile void __iomem *addr); | 771 | extern void __iounmap(volatile void __iomem *addr); |
783 | 772 | ||
784 | extern void __iomem * __ioremap_at(phys_addr_t pa, void *ea, | 773 | extern void __iomem * __ioremap_at(phys_addr_t pa, void *ea, |
785 | unsigned long size, unsigned long flags); | 774 | unsigned long size, pgprot_t prot); |
786 | extern void __iounmap_at(void *ea, unsigned long size); | 775 | extern void __iounmap_at(void *ea, unsigned long size); |
787 | 776 | ||
788 | /* | 777 | /* |
diff --git a/arch/powerpc/include/asm/kgdb.h b/arch/powerpc/include/asm/kgdb.h index 9db24e77b9f4..a9e098a3b881 100644 --- a/arch/powerpc/include/asm/kgdb.h +++ b/arch/powerpc/include/asm/kgdb.h | |||
@@ -26,9 +26,12 @@ | |||
26 | #define BREAK_INSTR_SIZE 4 | 26 | #define BREAK_INSTR_SIZE 4 |
27 | #define BUFMAX ((NUMREGBYTES * 2) + 512) | 27 | #define BUFMAX ((NUMREGBYTES * 2) + 512) |
28 | #define OUTBUFMAX ((NUMREGBYTES * 2) + 512) | 28 | #define OUTBUFMAX ((NUMREGBYTES * 2) + 512) |
29 | |||
30 | #define BREAK_INSTR 0x7d821008 /* twge r2, r2 */ | ||
31 | |||
29 | static inline void arch_kgdb_breakpoint(void) | 32 | static inline void arch_kgdb_breakpoint(void) |
30 | { | 33 | { |
31 | asm(".long 0x7d821008"); /* twge r2, r2 */ | 34 | asm(stringify_in_c(.long BREAK_INSTR)); |
32 | } | 35 | } |
33 | #define CACHE_FLUSH_IS_SAFE 1 | 36 | #define CACHE_FLUSH_IS_SAFE 1 |
34 | #define DBG_MAX_REG_NUM 70 | 37 | #define DBG_MAX_REG_NUM 70 |
diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h index a47de82fb8e2..8311869005fa 100644 --- a/arch/powerpc/include/asm/machdep.h +++ b/arch/powerpc/include/asm/machdep.h | |||
@@ -35,7 +35,7 @@ struct machdep_calls { | |||
35 | char *name; | 35 | char *name; |
36 | #ifdef CONFIG_PPC64 | 36 | #ifdef CONFIG_PPC64 |
37 | void __iomem * (*ioremap)(phys_addr_t addr, unsigned long size, | 37 | void __iomem * (*ioremap)(phys_addr_t addr, unsigned long size, |
38 | unsigned long flags, void *caller); | 38 | pgprot_t prot, void *caller); |
39 | void (*iounmap)(volatile void __iomem *token); | 39 | void (*iounmap)(volatile void __iomem *token); |
40 | 40 | ||
41 | #ifdef CONFIG_PM | 41 | #ifdef CONFIG_PM |
@@ -108,6 +108,7 @@ struct machdep_calls { | |||
108 | 108 | ||
109 | /* Early exception handlers called in realmode */ | 109 | /* Early exception handlers called in realmode */ |
110 | int (*hmi_exception_early)(struct pt_regs *regs); | 110 | int (*hmi_exception_early)(struct pt_regs *regs); |
111 | long (*machine_check_early)(struct pt_regs *regs); | ||
111 | 112 | ||
112 | /* Called during machine check exception to retrive fixup address. */ | 113 | /* Called during machine check exception to retrive fixup address. */ |
113 | bool (*mce_check_early_recovery)(struct pt_regs *regs); | 114 | bool (*mce_check_early_recovery)(struct pt_regs *regs); |
diff --git a/arch/powerpc/include/asm/mce.h b/arch/powerpc/include/asm/mce.h index 3a1226e9b465..a8b8903e1844 100644 --- a/arch/powerpc/include/asm/mce.h +++ b/arch/powerpc/include/asm/mce.h | |||
@@ -210,4 +210,7 @@ extern void release_mce_event(void); | |||
210 | extern void machine_check_queue_event(void); | 210 | extern void machine_check_queue_event(void); |
211 | extern void machine_check_print_event_info(struct machine_check_event *evt, | 211 | extern void machine_check_print_event_info(struct machine_check_event *evt, |
212 | bool user_mode); | 212 | bool user_mode); |
213 | #ifdef CONFIG_PPC_BOOK3S_64 | ||
214 | void flush_and_reload_slb(void); | ||
215 | #endif /* CONFIG_PPC_BOOK3S_64 */ | ||
213 | #endif /* __ASM_PPC64_MCE_H__ */ | 216 | #endif /* __ASM_PPC64_MCE_H__ */ |
diff --git a/arch/powerpc/include/asm/mmu.h b/arch/powerpc/include/asm/mmu.h index 13ea441ac531..eb20eb3b8fb0 100644 --- a/arch/powerpc/include/asm/mmu.h +++ b/arch/powerpc/include/asm/mmu.h | |||
@@ -309,6 +309,21 @@ static inline u16 get_mm_addr_key(struct mm_struct *mm, unsigned long address) | |||
309 | */ | 309 | */ |
310 | #define MMU_PAGE_COUNT 16 | 310 | #define MMU_PAGE_COUNT 16 |
311 | 311 | ||
312 | /* | ||
313 | * If we store section details in page->flags we can't increase the MAX_PHYSMEM_BITS | ||
314 | * if we increase SECTIONS_WIDTH we will not store node details in page->flags and | ||
315 | * page_to_nid does a page->section->node lookup | ||
316 | * Hence only increase for VMEMMAP. Further depending on SPARSEMEM_EXTREME reduce | ||
317 | * memory requirements with large number of sections. | ||
318 | * 51 bits is the max physical real address on POWER9 | ||
319 | */ | ||
320 | #if defined(CONFIG_SPARSEMEM_VMEMMAP) && defined(CONFIG_SPARSEMEM_EXTREME) && \ | ||
321 | defined (CONFIG_PPC_64K_PAGES) | ||
322 | #define MAX_PHYSMEM_BITS 51 | ||
323 | #else | ||
324 | #define MAX_PHYSMEM_BITS 46 | ||
325 | #endif | ||
326 | |||
312 | #ifdef CONFIG_PPC_BOOK3S_64 | 327 | #ifdef CONFIG_PPC_BOOK3S_64 |
313 | #include <asm/book3s/64/mmu.h> | 328 | #include <asm/book3s/64/mmu.h> |
314 | #else /* CONFIG_PPC_BOOK3S_64 */ | 329 | #else /* CONFIG_PPC_BOOK3S_64 */ |
diff --git a/arch/powerpc/include/asm/mmu_context.h b/arch/powerpc/include/asm/mmu_context.h index b694d6af1150..0381394a425b 100644 --- a/arch/powerpc/include/asm/mmu_context.h +++ b/arch/powerpc/include/asm/mmu_context.h | |||
@@ -82,7 +82,7 @@ static inline bool need_extra_context(struct mm_struct *mm, unsigned long ea) | |||
82 | { | 82 | { |
83 | int context_id; | 83 | int context_id; |
84 | 84 | ||
85 | context_id = get_ea_context(&mm->context, ea); | 85 | context_id = get_user_context(&mm->context, ea); |
86 | if (!context_id) | 86 | if (!context_id) |
87 | return true; | 87 | return true; |
88 | return false; | 88 | return false; |
diff --git a/arch/powerpc/include/asm/mpic.h b/arch/powerpc/include/asm/mpic.h index fad8ddd697ac..0abf2e7fd222 100644 --- a/arch/powerpc/include/asm/mpic.h +++ b/arch/powerpc/include/asm/mpic.h | |||
@@ -393,7 +393,14 @@ extern struct bus_type mpic_subsys; | |||
393 | #define MPIC_REGSET_TSI108 MPIC_REGSET(1) /* Tsi108/109 PIC */ | 393 | #define MPIC_REGSET_TSI108 MPIC_REGSET(1) /* Tsi108/109 PIC */ |
394 | 394 | ||
395 | /* Get the version of primary MPIC */ | 395 | /* Get the version of primary MPIC */ |
396 | #ifdef CONFIG_MPIC | ||
396 | extern u32 fsl_mpic_primary_get_version(void); | 397 | extern u32 fsl_mpic_primary_get_version(void); |
398 | #else | ||
399 | static inline u32 fsl_mpic_primary_get_version(void) | ||
400 | { | ||
401 | return 0; | ||
402 | } | ||
403 | #endif | ||
397 | 404 | ||
398 | /* Allocate the controller structure and setup the linux irq descs | 405 | /* Allocate the controller structure and setup the linux irq descs |
399 | * for the range if interrupts passed in. No HW initialization is | 406 | * for the range if interrupts passed in. No HW initialization is |
diff --git a/arch/powerpc/include/asm/nohash/32/pgtable.h b/arch/powerpc/include/asm/nohash/32/pgtable.h index a507a65b0866..f7b129a83054 100644 --- a/arch/powerpc/include/asm/nohash/32/pgtable.h +++ b/arch/powerpc/include/asm/nohash/32/pgtable.h | |||
@@ -128,14 +128,65 @@ extern int icache_44x_need_flush; | |||
128 | #include <asm/nohash/32/pte-8xx.h> | 128 | #include <asm/nohash/32/pte-8xx.h> |
129 | #endif | 129 | #endif |
130 | 130 | ||
131 | /* And here we include common definitions */ | 131 | /* |
132 | #include <asm/pte-common.h> | 132 | * Location of the PFN in the PTE. Most 32-bit platforms use the same |
133 | * as _PAGE_SHIFT here (ie, naturally aligned). | ||
134 | * Platform who don't just pre-define the value so we don't override it here. | ||
135 | */ | ||
136 | #ifndef PTE_RPN_SHIFT | ||
137 | #define PTE_RPN_SHIFT (PAGE_SHIFT) | ||
138 | #endif | ||
139 | |||
140 | /* | ||
141 | * The mask covered by the RPN must be a ULL on 32-bit platforms with | ||
142 | * 64-bit PTEs. | ||
143 | */ | ||
144 | #if defined(CONFIG_PPC32) && defined(CONFIG_PTE_64BIT) | ||
145 | #define PTE_RPN_MASK (~((1ULL << PTE_RPN_SHIFT) - 1)) | ||
146 | #else | ||
147 | #define PTE_RPN_MASK (~((1UL << PTE_RPN_SHIFT) - 1)) | ||
148 | #endif | ||
149 | |||
150 | /* | ||
151 | * _PAGE_CHG_MASK masks of bits that are to be preserved across | ||
152 | * pgprot changes. | ||
153 | */ | ||
154 | #define _PAGE_CHG_MASK (PTE_RPN_MASK | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_SPECIAL) | ||
133 | 155 | ||
134 | #ifndef __ASSEMBLY__ | 156 | #ifndef __ASSEMBLY__ |
135 | 157 | ||
136 | #define pte_clear(mm, addr, ptep) \ | 158 | #define pte_clear(mm, addr, ptep) \ |
137 | do { pte_update(ptep, ~0, 0); } while (0) | 159 | do { pte_update(ptep, ~0, 0); } while (0) |
138 | 160 | ||
161 | #ifndef pte_mkwrite | ||
162 | static inline pte_t pte_mkwrite(pte_t pte) | ||
163 | { | ||
164 | return __pte(pte_val(pte) | _PAGE_RW); | ||
165 | } | ||
166 | #endif | ||
167 | |||
168 | static inline pte_t pte_mkdirty(pte_t pte) | ||
169 | { | ||
170 | return __pte(pte_val(pte) | _PAGE_DIRTY); | ||
171 | } | ||
172 | |||
173 | static inline pte_t pte_mkyoung(pte_t pte) | ||
174 | { | ||
175 | return __pte(pte_val(pte) | _PAGE_ACCESSED); | ||
176 | } | ||
177 | |||
178 | #ifndef pte_wrprotect | ||
179 | static inline pte_t pte_wrprotect(pte_t pte) | ||
180 | { | ||
181 | return __pte(pte_val(pte) & ~_PAGE_RW); | ||
182 | } | ||
183 | #endif | ||
184 | |||
185 | static inline pte_t pte_mkexec(pte_t pte) | ||
186 | { | ||
187 | return __pte(pte_val(pte) | _PAGE_EXEC); | ||
188 | } | ||
189 | |||
139 | #define pmd_none(pmd) (!pmd_val(pmd)) | 190 | #define pmd_none(pmd) (!pmd_val(pmd)) |
140 | #define pmd_bad(pmd) (pmd_val(pmd) & _PMD_BAD) | 191 | #define pmd_bad(pmd) (pmd_val(pmd) & _PMD_BAD) |
141 | #define pmd_present(pmd) (pmd_val(pmd) & _PMD_PRESENT_MASK) | 192 | #define pmd_present(pmd) (pmd_val(pmd) & _PMD_PRESENT_MASK) |
@@ -244,7 +295,10 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, | |||
244 | static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, | 295 | static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, |
245 | pte_t *ptep) | 296 | pte_t *ptep) |
246 | { | 297 | { |
247 | pte_update(ptep, (_PAGE_RW | _PAGE_HWWRITE), _PAGE_RO); | 298 | unsigned long clr = ~pte_val(pte_wrprotect(__pte(~0))); |
299 | unsigned long set = pte_val(pte_wrprotect(__pte(0))); | ||
300 | |||
301 | pte_update(ptep, clr, set); | ||
248 | } | 302 | } |
249 | static inline void huge_ptep_set_wrprotect(struct mm_struct *mm, | 303 | static inline void huge_ptep_set_wrprotect(struct mm_struct *mm, |
250 | unsigned long addr, pte_t *ptep) | 304 | unsigned long addr, pte_t *ptep) |
@@ -258,9 +312,10 @@ static inline void __ptep_set_access_flags(struct vm_area_struct *vma, | |||
258 | unsigned long address, | 312 | unsigned long address, |
259 | int psize) | 313 | int psize) |
260 | { | 314 | { |
261 | unsigned long set = pte_val(entry) & | 315 | pte_t pte_set = pte_mkyoung(pte_mkdirty(pte_mkwrite(pte_mkexec(__pte(0))))); |
262 | (_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW | _PAGE_EXEC); | 316 | pte_t pte_clr = pte_mkyoung(pte_mkdirty(pte_mkwrite(pte_mkexec(__pte(~0))))); |
263 | unsigned long clr = ~pte_val(entry) & (_PAGE_RO | _PAGE_NA); | 317 | unsigned long set = pte_val(entry) & pte_val(pte_set); |
318 | unsigned long clr = ~pte_val(entry) & ~pte_val(pte_clr); | ||
264 | 319 | ||
265 | pte_update(ptep, clr, set); | 320 | pte_update(ptep, clr, set); |
266 | 321 | ||
@@ -323,7 +378,7 @@ static inline int pte_young(pte_t pte) | |||
323 | #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) >> 3 }) | 378 | #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) >> 3 }) |
324 | #define __swp_entry_to_pte(x) ((pte_t) { (x).val << 3 }) | 379 | #define __swp_entry_to_pte(x) ((pte_t) { (x).val << 3 }) |
325 | 380 | ||
326 | int map_kernel_page(unsigned long va, phys_addr_t pa, int flags); | 381 | int map_kernel_page(unsigned long va, phys_addr_t pa, pgprot_t prot); |
327 | 382 | ||
328 | #endif /* !__ASSEMBLY__ */ | 383 | #endif /* !__ASSEMBLY__ */ |
329 | 384 | ||
diff --git a/arch/powerpc/include/asm/nohash/32/pte-40x.h b/arch/powerpc/include/asm/nohash/32/pte-40x.h index bb4b3a4b92a0..661f4599f2fc 100644 --- a/arch/powerpc/include/asm/nohash/32/pte-40x.h +++ b/arch/powerpc/include/asm/nohash/32/pte-40x.h | |||
@@ -50,13 +50,56 @@ | |||
50 | #define _PAGE_EXEC 0x200 /* hardware: EX permission */ | 50 | #define _PAGE_EXEC 0x200 /* hardware: EX permission */ |
51 | #define _PAGE_ACCESSED 0x400 /* software: R: page referenced */ | 51 | #define _PAGE_ACCESSED 0x400 /* software: R: page referenced */ |
52 | 52 | ||
53 | /* No page size encoding in the linux PTE */ | ||
54 | #define _PAGE_PSIZE 0 | ||
55 | |||
56 | /* cache related flags non existing on 40x */ | ||
57 | #define _PAGE_COHERENT 0 | ||
58 | |||
59 | #define _PAGE_KERNEL_RO 0 | ||
60 | #define _PAGE_KERNEL_ROX _PAGE_EXEC | ||
61 | #define _PAGE_KERNEL_RW (_PAGE_DIRTY | _PAGE_RW | _PAGE_HWWRITE) | ||
62 | #define _PAGE_KERNEL_RWX (_PAGE_DIRTY | _PAGE_RW | _PAGE_HWWRITE | _PAGE_EXEC) | ||
63 | |||
53 | #define _PMD_PRESENT 0x400 /* PMD points to page of PTEs */ | 64 | #define _PMD_PRESENT 0x400 /* PMD points to page of PTEs */ |
65 | #define _PMD_PRESENT_MASK _PMD_PRESENT | ||
54 | #define _PMD_BAD 0x802 | 66 | #define _PMD_BAD 0x802 |
55 | #define _PMD_SIZE_4M 0x0c0 | 67 | #define _PMD_SIZE_4M 0x0c0 |
56 | #define _PMD_SIZE_16M 0x0e0 | 68 | #define _PMD_SIZE_16M 0x0e0 |
69 | #define _PMD_USER 0 | ||
70 | |||
71 | #define _PTE_NONE_MASK 0 | ||
57 | 72 | ||
58 | /* Until my rework is finished, 40x still needs atomic PTE updates */ | 73 | /* Until my rework is finished, 40x still needs atomic PTE updates */ |
59 | #define PTE_ATOMIC_UPDATES 1 | 74 | #define PTE_ATOMIC_UPDATES 1 |
60 | 75 | ||
76 | #define _PAGE_BASE_NC (_PAGE_PRESENT | _PAGE_ACCESSED) | ||
77 | #define _PAGE_BASE (_PAGE_BASE_NC) | ||
78 | |||
79 | /* Permission masks used to generate the __P and __S table */ | ||
80 | #define PAGE_NONE __pgprot(_PAGE_BASE) | ||
81 | #define PAGE_SHARED __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW) | ||
82 | #define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_EXEC) | ||
83 | #define PAGE_COPY __pgprot(_PAGE_BASE | _PAGE_USER) | ||
84 | #define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC) | ||
85 | #define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_USER) | ||
86 | #define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC) | ||
87 | |||
88 | #ifndef __ASSEMBLY__ | ||
89 | static inline pte_t pte_wrprotect(pte_t pte) | ||
90 | { | ||
91 | return __pte(pte_val(pte) & ~(_PAGE_RW | _PAGE_HWWRITE)); | ||
92 | } | ||
93 | |||
94 | #define pte_wrprotect pte_wrprotect | ||
95 | |||
96 | static inline pte_t pte_mkclean(pte_t pte) | ||
97 | { | ||
98 | return __pte(pte_val(pte) & ~(_PAGE_DIRTY | _PAGE_HWWRITE)); | ||
99 | } | ||
100 | |||
101 | #define pte_mkclean pte_mkclean | ||
102 | #endif | ||
103 | |||
61 | #endif /* __KERNEL__ */ | 104 | #endif /* __KERNEL__ */ |
62 | #endif /* _ASM_POWERPC_NOHASH_32_PTE_40x_H */ | 105 | #endif /* _ASM_POWERPC_NOHASH_32_PTE_40x_H */ |
diff --git a/arch/powerpc/include/asm/nohash/32/pte-44x.h b/arch/powerpc/include/asm/nohash/32/pte-44x.h index f812c0272364..78bc304f750e 100644 --- a/arch/powerpc/include/asm/nohash/32/pte-44x.h +++ b/arch/powerpc/include/asm/nohash/32/pte-44x.h | |||
@@ -85,14 +85,44 @@ | |||
85 | #define _PAGE_NO_CACHE 0x00000400 /* H: I bit */ | 85 | #define _PAGE_NO_CACHE 0x00000400 /* H: I bit */ |
86 | #define _PAGE_WRITETHRU 0x00000800 /* H: W bit */ | 86 | #define _PAGE_WRITETHRU 0x00000800 /* H: W bit */ |
87 | 87 | ||
88 | /* No page size encoding in the linux PTE */ | ||
89 | #define _PAGE_PSIZE 0 | ||
90 | |||
91 | #define _PAGE_KERNEL_RO 0 | ||
92 | #define _PAGE_KERNEL_ROX _PAGE_EXEC | ||
93 | #define _PAGE_KERNEL_RW (_PAGE_DIRTY | _PAGE_RW) | ||
94 | #define _PAGE_KERNEL_RWX (_PAGE_DIRTY | _PAGE_RW | _PAGE_EXEC) | ||
95 | |||
88 | /* TODO: Add large page lowmem mapping support */ | 96 | /* TODO: Add large page lowmem mapping support */ |
89 | #define _PMD_PRESENT 0 | 97 | #define _PMD_PRESENT 0 |
90 | #define _PMD_PRESENT_MASK (PAGE_MASK) | 98 | #define _PMD_PRESENT_MASK (PAGE_MASK) |
91 | #define _PMD_BAD (~PAGE_MASK) | 99 | #define _PMD_BAD (~PAGE_MASK) |
100 | #define _PMD_USER 0 | ||
92 | 101 | ||
93 | /* ERPN in a PTE never gets cleared, ignore it */ | 102 | /* ERPN in a PTE never gets cleared, ignore it */ |
94 | #define _PTE_NONE_MASK 0xffffffff00000000ULL | 103 | #define _PTE_NONE_MASK 0xffffffff00000000ULL |
95 | 104 | ||
105 | /* | ||
106 | * We define 2 sets of base prot bits, one for basic pages (ie, | ||
107 | * cacheable kernel and user pages) and one for non cacheable | ||
108 | * pages. We always set _PAGE_COHERENT when SMP is enabled or | ||
109 | * the processor might need it for DMA coherency. | ||
110 | */ | ||
111 | #define _PAGE_BASE_NC (_PAGE_PRESENT | _PAGE_ACCESSED) | ||
112 | #if defined(CONFIG_SMP) | ||
113 | #define _PAGE_BASE (_PAGE_BASE_NC | _PAGE_COHERENT) | ||
114 | #else | ||
115 | #define _PAGE_BASE (_PAGE_BASE_NC) | ||
116 | #endif | ||
117 | |||
118 | /* Permission masks used to generate the __P and __S table */ | ||
119 | #define PAGE_NONE __pgprot(_PAGE_BASE) | ||
120 | #define PAGE_SHARED __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW) | ||
121 | #define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_EXEC) | ||
122 | #define PAGE_COPY __pgprot(_PAGE_BASE | _PAGE_USER) | ||
123 | #define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC) | ||
124 | #define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_USER) | ||
125 | #define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC) | ||
96 | 126 | ||
97 | #endif /* __KERNEL__ */ | 127 | #endif /* __KERNEL__ */ |
98 | #endif /* _ASM_POWERPC_NOHASH_32_PTE_44x_H */ | 128 | #endif /* _ASM_POWERPC_NOHASH_32_PTE_44x_H */ |
diff --git a/arch/powerpc/include/asm/nohash/32/pte-8xx.h b/arch/powerpc/include/asm/nohash/32/pte-8xx.h index f04cb46ae8a1..6bfe041ef59d 100644 --- a/arch/powerpc/include/asm/nohash/32/pte-8xx.h +++ b/arch/powerpc/include/asm/nohash/32/pte-8xx.h | |||
@@ -29,10 +29,10 @@ | |||
29 | */ | 29 | */ |
30 | 30 | ||
31 | /* Definitions for 8xx embedded chips. */ | 31 | /* Definitions for 8xx embedded chips. */ |
32 | #define _PAGE_PRESENT 0x0001 /* Page is valid */ | 32 | #define _PAGE_PRESENT 0x0001 /* V: Page is valid */ |
33 | #define _PAGE_NO_CACHE 0x0002 /* I: cache inhibit */ | 33 | #define _PAGE_NO_CACHE 0x0002 /* CI: cache inhibit */ |
34 | #define _PAGE_PRIVILEGED 0x0004 /* No ASID (context) compare */ | 34 | #define _PAGE_SH 0x0004 /* SH: No ASID (context) compare */ |
35 | #define _PAGE_HUGE 0x0008 /* SPS: Small Page Size (1 if 16k, 512k or 8M)*/ | 35 | #define _PAGE_SPS 0x0008 /* SPS: Small Page Size (1 if 16k, 512k or 8M)*/ |
36 | #define _PAGE_DIRTY 0x0100 /* C: page changed */ | 36 | #define _PAGE_DIRTY 0x0100 /* C: page changed */ |
37 | 37 | ||
38 | /* These 4 software bits must be masked out when the L2 entry is loaded | 38 | /* These 4 software bits must be masked out when the L2 entry is loaded |
@@ -46,18 +46,95 @@ | |||
46 | #define _PAGE_NA 0x0200 /* Supervisor NA, User no access */ | 46 | #define _PAGE_NA 0x0200 /* Supervisor NA, User no access */ |
47 | #define _PAGE_RO 0x0600 /* Supervisor RO, User no access */ | 47 | #define _PAGE_RO 0x0600 /* Supervisor RO, User no access */ |
48 | 48 | ||
49 | /* cache related flags non existing on 8xx */ | ||
50 | #define _PAGE_COHERENT 0 | ||
51 | #define _PAGE_WRITETHRU 0 | ||
52 | |||
53 | #define _PAGE_KERNEL_RO (_PAGE_SH | _PAGE_RO) | ||
54 | #define _PAGE_KERNEL_ROX (_PAGE_SH | _PAGE_RO | _PAGE_EXEC) | ||
55 | #define _PAGE_KERNEL_RW (_PAGE_SH | _PAGE_DIRTY) | ||
56 | #define _PAGE_KERNEL_RWX (_PAGE_SH | _PAGE_DIRTY | _PAGE_EXEC) | ||
57 | |||
49 | #define _PMD_PRESENT 0x0001 | 58 | #define _PMD_PRESENT 0x0001 |
59 | #define _PMD_PRESENT_MASK _PMD_PRESENT | ||
50 | #define _PMD_BAD 0x0fd0 | 60 | #define _PMD_BAD 0x0fd0 |
51 | #define _PMD_PAGE_MASK 0x000c | 61 | #define _PMD_PAGE_MASK 0x000c |
52 | #define _PMD_PAGE_8M 0x000c | 62 | #define _PMD_PAGE_8M 0x000c |
53 | #define _PMD_PAGE_512K 0x0004 | 63 | #define _PMD_PAGE_512K 0x0004 |
54 | #define _PMD_USER 0x0020 /* APG 1 */ | 64 | #define _PMD_USER 0x0020 /* APG 1 */ |
55 | 65 | ||
66 | #define _PTE_NONE_MASK 0 | ||
67 | |||
56 | /* Until my rework is finished, 8xx still needs atomic PTE updates */ | 68 | /* Until my rework is finished, 8xx still needs atomic PTE updates */ |
57 | #define PTE_ATOMIC_UPDATES 1 | 69 | #define PTE_ATOMIC_UPDATES 1 |
58 | 70 | ||
59 | #ifdef CONFIG_PPC_16K_PAGES | 71 | #ifdef CONFIG_PPC_16K_PAGES |
60 | #define _PAGE_PSIZE _PAGE_HUGE | 72 | #define _PAGE_PSIZE _PAGE_SPS |
73 | #else | ||
74 | #define _PAGE_PSIZE 0 | ||
75 | #endif | ||
76 | |||
77 | #define _PAGE_BASE_NC (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_PSIZE) | ||
78 | #define _PAGE_BASE (_PAGE_BASE_NC) | ||
79 | |||
80 | /* Permission masks used to generate the __P and __S table */ | ||
81 | #define PAGE_NONE __pgprot(_PAGE_BASE | _PAGE_NA) | ||
82 | #define PAGE_SHARED __pgprot(_PAGE_BASE) | ||
83 | #define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_EXEC) | ||
84 | #define PAGE_COPY __pgprot(_PAGE_BASE | _PAGE_RO) | ||
85 | #define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_RO | _PAGE_EXEC) | ||
86 | #define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_RO) | ||
87 | #define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_RO | _PAGE_EXEC) | ||
88 | |||
89 | #ifndef __ASSEMBLY__ | ||
90 | static inline pte_t pte_wrprotect(pte_t pte) | ||
91 | { | ||
92 | return __pte(pte_val(pte) | _PAGE_RO); | ||
93 | } | ||
94 | |||
95 | #define pte_wrprotect pte_wrprotect | ||
96 | |||
97 | static inline int pte_write(pte_t pte) | ||
98 | { | ||
99 | return !(pte_val(pte) & _PAGE_RO); | ||
100 | } | ||
101 | |||
102 | #define pte_write pte_write | ||
103 | |||
104 | static inline pte_t pte_mkwrite(pte_t pte) | ||
105 | { | ||
106 | return __pte(pte_val(pte) & ~_PAGE_RO); | ||
107 | } | ||
108 | |||
109 | #define pte_mkwrite pte_mkwrite | ||
110 | |||
111 | static inline bool pte_user(pte_t pte) | ||
112 | { | ||
113 | return !(pte_val(pte) & _PAGE_SH); | ||
114 | } | ||
115 | |||
116 | #define pte_user pte_user | ||
117 | |||
118 | static inline pte_t pte_mkprivileged(pte_t pte) | ||
119 | { | ||
120 | return __pte(pte_val(pte) | _PAGE_SH); | ||
121 | } | ||
122 | |||
123 | #define pte_mkprivileged pte_mkprivileged | ||
124 | |||
125 | static inline pte_t pte_mkuser(pte_t pte) | ||
126 | { | ||
127 | return __pte(pte_val(pte) & ~_PAGE_SH); | ||
128 | } | ||
129 | |||
130 | #define pte_mkuser pte_mkuser | ||
131 | |||
132 | static inline pte_t pte_mkhuge(pte_t pte) | ||
133 | { | ||
134 | return __pte(pte_val(pte) | _PAGE_SPS); | ||
135 | } | ||
136 | |||
137 | #define pte_mkhuge pte_mkhuge | ||
61 | #endif | 138 | #endif |
62 | 139 | ||
63 | #endif /* __KERNEL__ */ | 140 | #endif /* __KERNEL__ */ |
diff --git a/arch/powerpc/include/asm/nohash/32/pte-fsl-booke.h b/arch/powerpc/include/asm/nohash/32/pte-fsl-booke.h index d1ee24e9e137..0fc1bd42bb3e 100644 --- a/arch/powerpc/include/asm/nohash/32/pte-fsl-booke.h +++ b/arch/powerpc/include/asm/nohash/32/pte-fsl-booke.h | |||
@@ -31,11 +31,44 @@ | |||
31 | #define _PAGE_WRITETHRU 0x00400 /* H: W bit */ | 31 | #define _PAGE_WRITETHRU 0x00400 /* H: W bit */ |
32 | #define _PAGE_SPECIAL 0x00800 /* S: Special page */ | 32 | #define _PAGE_SPECIAL 0x00800 /* S: Special page */ |
33 | 33 | ||
34 | #define _PAGE_KERNEL_RO 0 | ||
35 | #define _PAGE_KERNEL_ROX _PAGE_EXEC | ||
36 | #define _PAGE_KERNEL_RW (_PAGE_DIRTY | _PAGE_RW) | ||
37 | #define _PAGE_KERNEL_RWX (_PAGE_DIRTY | _PAGE_RW | _PAGE_EXEC) | ||
38 | |||
39 | /* No page size encoding in the linux PTE */ | ||
40 | #define _PAGE_PSIZE 0 | ||
41 | |||
34 | #define _PMD_PRESENT 0 | 42 | #define _PMD_PRESENT 0 |
35 | #define _PMD_PRESENT_MASK (PAGE_MASK) | 43 | #define _PMD_PRESENT_MASK (PAGE_MASK) |
36 | #define _PMD_BAD (~PAGE_MASK) | 44 | #define _PMD_BAD (~PAGE_MASK) |
45 | #define _PMD_USER 0 | ||
46 | |||
47 | #define _PTE_NONE_MASK 0 | ||
37 | 48 | ||
38 | #define PTE_WIMGE_SHIFT (6) | 49 | #define PTE_WIMGE_SHIFT (6) |
39 | 50 | ||
51 | /* | ||
52 | * We define 2 sets of base prot bits, one for basic pages (ie, | ||
53 | * cacheable kernel and user pages) and one for non cacheable | ||
54 | * pages. We always set _PAGE_COHERENT when SMP is enabled or | ||
55 | * the processor might need it for DMA coherency. | ||
56 | */ | ||
57 | #define _PAGE_BASE_NC (_PAGE_PRESENT | _PAGE_ACCESSED) | ||
58 | #if defined(CONFIG_SMP) || defined(CONFIG_PPC_E500MC) | ||
59 | #define _PAGE_BASE (_PAGE_BASE_NC | _PAGE_COHERENT) | ||
60 | #else | ||
61 | #define _PAGE_BASE (_PAGE_BASE_NC) | ||
62 | #endif | ||
63 | |||
64 | /* Permission masks used to generate the __P and __S table */ | ||
65 | #define PAGE_NONE __pgprot(_PAGE_BASE) | ||
66 | #define PAGE_SHARED __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW) | ||
67 | #define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_EXEC) | ||
68 | #define PAGE_COPY __pgprot(_PAGE_BASE | _PAGE_USER) | ||
69 | #define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC) | ||
70 | #define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_USER) | ||
71 | #define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC) | ||
72 | |||
40 | #endif /* __KERNEL__ */ | 73 | #endif /* __KERNEL__ */ |
41 | #endif /* _ASM_POWERPC_NOHASH_32_PTE_FSL_BOOKE_H */ | 74 | #endif /* _ASM_POWERPC_NOHASH_32_PTE_FSL_BOOKE_H */ |
diff --git a/arch/powerpc/include/asm/nohash/64/pgtable.h b/arch/powerpc/include/asm/nohash/64/pgtable.h index 7cd6809f4d33..dc6bb9da3f23 100644 --- a/arch/powerpc/include/asm/nohash/64/pgtable.h +++ b/arch/powerpc/include/asm/nohash/64/pgtable.h | |||
@@ -89,11 +89,47 @@ | |||
89 | * Include the PTE bits definitions | 89 | * Include the PTE bits definitions |
90 | */ | 90 | */ |
91 | #include <asm/nohash/pte-book3e.h> | 91 | #include <asm/nohash/pte-book3e.h> |
92 | #include <asm/pte-common.h> | 92 | |
93 | #define _PAGE_SAO 0 | ||
94 | |||
95 | #define PTE_RPN_MASK (~((1UL << PTE_RPN_SHIFT) - 1)) | ||
96 | |||
97 | /* | ||
98 | * _PAGE_CHG_MASK masks of bits that are to be preserved across | ||
99 | * pgprot changes. | ||
100 | */ | ||
101 | #define _PAGE_CHG_MASK (PTE_RPN_MASK | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_SPECIAL) | ||
102 | |||
103 | #define H_PAGE_4K_PFN 0 | ||
93 | 104 | ||
94 | #ifndef __ASSEMBLY__ | 105 | #ifndef __ASSEMBLY__ |
95 | /* pte_clear moved to later in this file */ | 106 | /* pte_clear moved to later in this file */ |
96 | 107 | ||
108 | static inline pte_t pte_mkwrite(pte_t pte) | ||
109 | { | ||
110 | return __pte(pte_val(pte) | _PAGE_RW); | ||
111 | } | ||
112 | |||
113 | static inline pte_t pte_mkdirty(pte_t pte) | ||
114 | { | ||
115 | return __pte(pte_val(pte) | _PAGE_DIRTY); | ||
116 | } | ||
117 | |||
118 | static inline pte_t pte_mkyoung(pte_t pte) | ||
119 | { | ||
120 | return __pte(pte_val(pte) | _PAGE_ACCESSED); | ||
121 | } | ||
122 | |||
123 | static inline pte_t pte_wrprotect(pte_t pte) | ||
124 | { | ||
125 | return __pte(pte_val(pte) & ~_PAGE_RW); | ||
126 | } | ||
127 | |||
128 | static inline pte_t pte_mkexec(pte_t pte) | ||
129 | { | ||
130 | return __pte(pte_val(pte) | _PAGE_EXEC); | ||
131 | } | ||
132 | |||
97 | #define PMD_BAD_BITS (PTE_TABLE_SIZE-1) | 133 | #define PMD_BAD_BITS (PTE_TABLE_SIZE-1) |
98 | #define PUD_BAD_BITS (PMD_TABLE_SIZE-1) | 134 | #define PUD_BAD_BITS (PMD_TABLE_SIZE-1) |
99 | 135 | ||
@@ -327,8 +363,7 @@ static inline void __ptep_set_access_flags(struct vm_area_struct *vma, | |||
327 | #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val((pte)) }) | 363 | #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val((pte)) }) |
328 | #define __swp_entry_to_pte(x) __pte((x).val) | 364 | #define __swp_entry_to_pte(x) __pte((x).val) |
329 | 365 | ||
330 | extern int map_kernel_page(unsigned long ea, unsigned long pa, | 366 | int map_kernel_page(unsigned long ea, unsigned long pa, pgprot_t prot); |
331 | unsigned long flags); | ||
332 | extern int __meminit vmemmap_create_mapping(unsigned long start, | 367 | extern int __meminit vmemmap_create_mapping(unsigned long start, |
333 | unsigned long page_size, | 368 | unsigned long page_size, |
334 | unsigned long phys); | 369 | unsigned long phys); |
diff --git a/arch/powerpc/include/asm/nohash/pgtable.h b/arch/powerpc/include/asm/nohash/pgtable.h index b321c82b3624..70ff23974b59 100644 --- a/arch/powerpc/include/asm/nohash/pgtable.h +++ b/arch/powerpc/include/asm/nohash/pgtable.h | |||
@@ -8,18 +8,50 @@ | |||
8 | #include <asm/nohash/32/pgtable.h> | 8 | #include <asm/nohash/32/pgtable.h> |
9 | #endif | 9 | #endif |
10 | 10 | ||
11 | /* Permission masks used for kernel mappings */ | ||
12 | #define PAGE_KERNEL __pgprot(_PAGE_BASE | _PAGE_KERNEL_RW) | ||
13 | #define PAGE_KERNEL_NC __pgprot(_PAGE_BASE_NC | _PAGE_KERNEL_RW | _PAGE_NO_CACHE) | ||
14 | #define PAGE_KERNEL_NCG __pgprot(_PAGE_BASE_NC | _PAGE_KERNEL_RW | \ | ||
15 | _PAGE_NO_CACHE | _PAGE_GUARDED) | ||
16 | #define PAGE_KERNEL_X __pgprot(_PAGE_BASE | _PAGE_KERNEL_RWX) | ||
17 | #define PAGE_KERNEL_RO __pgprot(_PAGE_BASE | _PAGE_KERNEL_RO) | ||
18 | #define PAGE_KERNEL_ROX __pgprot(_PAGE_BASE | _PAGE_KERNEL_ROX) | ||
19 | |||
20 | /* | ||
21 | * Protection used for kernel text. We want the debuggers to be able to | ||
22 | * set breakpoints anywhere, so don't write protect the kernel text | ||
23 | * on platforms where such control is possible. | ||
24 | */ | ||
25 | #if defined(CONFIG_KGDB) || defined(CONFIG_XMON) || defined(CONFIG_BDI_SWITCH) ||\ | ||
26 | defined(CONFIG_KPROBES) || defined(CONFIG_DYNAMIC_FTRACE) | ||
27 | #define PAGE_KERNEL_TEXT PAGE_KERNEL_X | ||
28 | #else | ||
29 | #define PAGE_KERNEL_TEXT PAGE_KERNEL_ROX | ||
30 | #endif | ||
31 | |||
32 | /* Make modules code happy. We don't set RO yet */ | ||
33 | #define PAGE_KERNEL_EXEC PAGE_KERNEL_X | ||
34 | |||
35 | /* Advertise special mapping type for AGP */ | ||
36 | #define PAGE_AGP (PAGE_KERNEL_NC) | ||
37 | #define HAVE_PAGE_AGP | ||
38 | |||
11 | #ifndef __ASSEMBLY__ | 39 | #ifndef __ASSEMBLY__ |
12 | 40 | ||
13 | /* Generic accessors to PTE bits */ | 41 | /* Generic accessors to PTE bits */ |
42 | #ifndef pte_write | ||
14 | static inline int pte_write(pte_t pte) | 43 | static inline int pte_write(pte_t pte) |
15 | { | 44 | { |
16 | return (pte_val(pte) & (_PAGE_RW | _PAGE_RO)) != _PAGE_RO; | 45 | return pte_val(pte) & _PAGE_RW; |
17 | } | 46 | } |
47 | #endif | ||
18 | static inline int pte_read(pte_t pte) { return 1; } | 48 | static inline int pte_read(pte_t pte) { return 1; } |
19 | static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; } | 49 | static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; } |
20 | static inline int pte_special(pte_t pte) { return pte_val(pte) & _PAGE_SPECIAL; } | 50 | static inline int pte_special(pte_t pte) { return pte_val(pte) & _PAGE_SPECIAL; } |
21 | static inline int pte_none(pte_t pte) { return (pte_val(pte) & ~_PTE_NONE_MASK) == 0; } | 51 | static inline int pte_none(pte_t pte) { return (pte_val(pte) & ~_PTE_NONE_MASK) == 0; } |
22 | static inline pgprot_t pte_pgprot(pte_t pte) { return __pgprot(pte_val(pte) & PAGE_PROT_BITS); } | 52 | static inline bool pte_hashpte(pte_t pte) { return false; } |
53 | static inline bool pte_ci(pte_t pte) { return pte_val(pte) & _PAGE_NO_CACHE; } | ||
54 | static inline bool pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_EXEC; } | ||
23 | 55 | ||
24 | #ifdef CONFIG_NUMA_BALANCING | 56 | #ifdef CONFIG_NUMA_BALANCING |
25 | /* | 57 | /* |
@@ -29,8 +61,7 @@ static inline pgprot_t pte_pgprot(pte_t pte) { return __pgprot(pte_val(pte) & PA | |||
29 | */ | 61 | */ |
30 | static inline int pte_protnone(pte_t pte) | 62 | static inline int pte_protnone(pte_t pte) |
31 | { | 63 | { |
32 | return (pte_val(pte) & | 64 | return pte_present(pte) && !pte_user(pte); |
33 | (_PAGE_PRESENT | _PAGE_USER)) == _PAGE_PRESENT; | ||
34 | } | 65 | } |
35 | 66 | ||
36 | static inline int pmd_protnone(pmd_t pmd) | 67 | static inline int pmd_protnone(pmd_t pmd) |
@@ -44,6 +75,23 @@ static inline int pte_present(pte_t pte) | |||
44 | return pte_val(pte) & _PAGE_PRESENT; | 75 | return pte_val(pte) & _PAGE_PRESENT; |
45 | } | 76 | } |
46 | 77 | ||
78 | static inline bool pte_hw_valid(pte_t pte) | ||
79 | { | ||
80 | return pte_val(pte) & _PAGE_PRESENT; | ||
81 | } | ||
82 | |||
83 | /* | ||
84 | * Don't just check for any non zero bits in __PAGE_USER, since for book3e | ||
85 | * and PTE_64BIT, PAGE_KERNEL_X contains _PAGE_BAP_SR which is also in | ||
86 | * _PAGE_USER. Need to explicitly match _PAGE_BAP_UR bit in that case too. | ||
87 | */ | ||
88 | #ifndef pte_user | ||
89 | static inline bool pte_user(pte_t pte) | ||
90 | { | ||
91 | return (pte_val(pte) & _PAGE_USER) == _PAGE_USER; | ||
92 | } | ||
93 | #endif | ||
94 | |||
47 | /* | 95 | /* |
48 | * We only find page table entry in the last level | 96 | * We only find page table entry in the last level |
49 | * Hence no need for other accessors | 97 | * Hence no need for other accessors |
@@ -77,53 +125,53 @@ static inline unsigned long pte_pfn(pte_t pte) { | |||
77 | return pte_val(pte) >> PTE_RPN_SHIFT; } | 125 | return pte_val(pte) >> PTE_RPN_SHIFT; } |
78 | 126 | ||
79 | /* Generic modifiers for PTE bits */ | 127 | /* Generic modifiers for PTE bits */ |
80 | static inline pte_t pte_wrprotect(pte_t pte) | 128 | static inline pte_t pte_exprotect(pte_t pte) |
81 | { | 129 | { |
82 | pte_basic_t ptev; | 130 | return __pte(pte_val(pte) & ~_PAGE_EXEC); |
83 | |||
84 | ptev = pte_val(pte) & ~(_PAGE_RW | _PAGE_HWWRITE); | ||
85 | ptev |= _PAGE_RO; | ||
86 | return __pte(ptev); | ||
87 | } | 131 | } |
88 | 132 | ||
133 | #ifndef pte_mkclean | ||
89 | static inline pte_t pte_mkclean(pte_t pte) | 134 | static inline pte_t pte_mkclean(pte_t pte) |
90 | { | 135 | { |
91 | return __pte(pte_val(pte) & ~(_PAGE_DIRTY | _PAGE_HWWRITE)); | 136 | return __pte(pte_val(pte) & ~_PAGE_DIRTY); |
92 | } | 137 | } |
138 | #endif | ||
93 | 139 | ||
94 | static inline pte_t pte_mkold(pte_t pte) | 140 | static inline pte_t pte_mkold(pte_t pte) |
95 | { | 141 | { |
96 | return __pte(pte_val(pte) & ~_PAGE_ACCESSED); | 142 | return __pte(pte_val(pte) & ~_PAGE_ACCESSED); |
97 | } | 143 | } |
98 | 144 | ||
99 | static inline pte_t pte_mkwrite(pte_t pte) | 145 | static inline pte_t pte_mkpte(pte_t pte) |
100 | { | 146 | { |
101 | pte_basic_t ptev; | 147 | return pte; |
102 | |||
103 | ptev = pte_val(pte) & ~_PAGE_RO; | ||
104 | ptev |= _PAGE_RW; | ||
105 | return __pte(ptev); | ||
106 | } | 148 | } |
107 | 149 | ||
108 | static inline pte_t pte_mkdirty(pte_t pte) | 150 | static inline pte_t pte_mkspecial(pte_t pte) |
109 | { | 151 | { |
110 | return __pte(pte_val(pte) | _PAGE_DIRTY); | 152 | return __pte(pte_val(pte) | _PAGE_SPECIAL); |
111 | } | 153 | } |
112 | 154 | ||
113 | static inline pte_t pte_mkyoung(pte_t pte) | 155 | #ifndef pte_mkhuge |
156 | static inline pte_t pte_mkhuge(pte_t pte) | ||
114 | { | 157 | { |
115 | return __pte(pte_val(pte) | _PAGE_ACCESSED); | 158 | return __pte(pte_val(pte)); |
116 | } | 159 | } |
160 | #endif | ||
117 | 161 | ||
118 | static inline pte_t pte_mkspecial(pte_t pte) | 162 | #ifndef pte_mkprivileged |
163 | static inline pte_t pte_mkprivileged(pte_t pte) | ||
119 | { | 164 | { |
120 | return __pte(pte_val(pte) | _PAGE_SPECIAL); | 165 | return __pte(pte_val(pte) & ~_PAGE_USER); |
121 | } | 166 | } |
167 | #endif | ||
122 | 168 | ||
123 | static inline pte_t pte_mkhuge(pte_t pte) | 169 | #ifndef pte_mkuser |
170 | static inline pte_t pte_mkuser(pte_t pte) | ||
124 | { | 171 | { |
125 | return __pte(pte_val(pte) | _PAGE_HUGE); | 172 | return __pte(pte_val(pte) | _PAGE_USER); |
126 | } | 173 | } |
174 | #endif | ||
127 | 175 | ||
128 | static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) | 176 | static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) |
129 | { | 177 | { |
@@ -197,6 +245,8 @@ extern int ptep_set_access_flags(struct vm_area_struct *vma, unsigned long addre | |||
197 | #if _PAGE_WRITETHRU != 0 | 245 | #if _PAGE_WRITETHRU != 0 |
198 | #define pgprot_cached_wthru(prot) (__pgprot((pgprot_val(prot) & ~_PAGE_CACHE_CTL) | \ | 246 | #define pgprot_cached_wthru(prot) (__pgprot((pgprot_val(prot) & ~_PAGE_CACHE_CTL) | \ |
199 | _PAGE_COHERENT | _PAGE_WRITETHRU)) | 247 | _PAGE_COHERENT | _PAGE_WRITETHRU)) |
248 | #else | ||
249 | #define pgprot_cached_wthru(prot) pgprot_noncached(prot) | ||
200 | #endif | 250 | #endif |
201 | 251 | ||
202 | #define pgprot_cached_noncoherent(prot) \ | 252 | #define pgprot_cached_noncoherent(prot) \ |
diff --git a/arch/powerpc/include/asm/nohash/pte-book3e.h b/arch/powerpc/include/asm/nohash/pte-book3e.h index 12730b81cd98..dd40d200f274 100644 --- a/arch/powerpc/include/asm/nohash/pte-book3e.h +++ b/arch/powerpc/include/asm/nohash/pte-book3e.h | |||
@@ -77,7 +77,48 @@ | |||
77 | #define _PMD_PRESENT 0 | 77 | #define _PMD_PRESENT 0 |
78 | #define _PMD_PRESENT_MASK (PAGE_MASK) | 78 | #define _PMD_PRESENT_MASK (PAGE_MASK) |
79 | #define _PMD_BAD (~PAGE_MASK) | 79 | #define _PMD_BAD (~PAGE_MASK) |
80 | #define _PMD_USER 0 | ||
81 | #else | ||
82 | #define _PTE_NONE_MASK 0 | ||
83 | #endif | ||
84 | |||
85 | /* | ||
86 | * We define 2 sets of base prot bits, one for basic pages (ie, | ||
87 | * cacheable kernel and user pages) and one for non cacheable | ||
88 | * pages. We always set _PAGE_COHERENT when SMP is enabled or | ||
89 | * the processor might need it for DMA coherency. | ||
90 | */ | ||
91 | #define _PAGE_BASE_NC (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_PSIZE) | ||
92 | #if defined(CONFIG_SMP) | ||
93 | #define _PAGE_BASE (_PAGE_BASE_NC | _PAGE_COHERENT) | ||
94 | #else | ||
95 | #define _PAGE_BASE (_PAGE_BASE_NC) | ||
80 | #endif | 96 | #endif |
81 | 97 | ||
98 | /* Permission masks used to generate the __P and __S table */ | ||
99 | #define PAGE_NONE __pgprot(_PAGE_BASE) | ||
100 | #define PAGE_SHARED __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW) | ||
101 | #define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_EXEC) | ||
102 | #define PAGE_COPY __pgprot(_PAGE_BASE | _PAGE_USER) | ||
103 | #define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC) | ||
104 | #define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_USER) | ||
105 | #define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC) | ||
106 | |||
107 | #ifndef __ASSEMBLY__ | ||
108 | static inline pte_t pte_mkprivileged(pte_t pte) | ||
109 | { | ||
110 | return __pte((pte_val(pte) & ~_PAGE_USER) | _PAGE_PRIVILEGED); | ||
111 | } | ||
112 | |||
113 | #define pte_mkprivileged pte_mkprivileged | ||
114 | |||
115 | static inline pte_t pte_mkuser(pte_t pte) | ||
116 | { | ||
117 | return __pte((pte_val(pte) & ~_PAGE_PRIVILEGED) | _PAGE_USER); | ||
118 | } | ||
119 | |||
120 | #define pte_mkuser pte_mkuser | ||
121 | #endif /* __ASSEMBLY__ */ | ||
122 | |||
82 | #endif /* __KERNEL__ */ | 123 | #endif /* __KERNEL__ */ |
83 | #endif /* _ASM_POWERPC_NOHASH_PTE_BOOK3E_H */ | 124 | #endif /* _ASM_POWERPC_NOHASH_PTE_BOOK3E_H */ |
diff --git a/arch/powerpc/include/asm/opal-api.h b/arch/powerpc/include/asm/opal-api.h index 8365353330b4..870fb7b239ea 100644 --- a/arch/powerpc/include/asm/opal-api.h +++ b/arch/powerpc/include/asm/opal-api.h | |||
@@ -1050,6 +1050,7 @@ enum OpalSysCooling { | |||
1050 | enum { | 1050 | enum { |
1051 | OPAL_REBOOT_NORMAL = 0, | 1051 | OPAL_REBOOT_NORMAL = 0, |
1052 | OPAL_REBOOT_PLATFORM_ERROR = 1, | 1052 | OPAL_REBOOT_PLATFORM_ERROR = 1, |
1053 | OPAL_REBOOT_FULL_IPL = 2, | ||
1053 | }; | 1054 | }; |
1054 | 1055 | ||
1055 | /* Argument to OPAL_PCI_TCE_KILL */ | 1056 | /* Argument to OPAL_PCI_TCE_KILL */ |
diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h index ad4f16164619..e843bc5d1a0f 100644 --- a/arch/powerpc/include/asm/paca.h +++ b/arch/powerpc/include/asm/paca.h | |||
@@ -113,7 +113,13 @@ struct paca_struct { | |||
113 | * on the linear mapping */ | 113 | * on the linear mapping */ |
114 | /* SLB related definitions */ | 114 | /* SLB related definitions */ |
115 | u16 vmalloc_sllp; | 115 | u16 vmalloc_sllp; |
116 | u16 slb_cache_ptr; | 116 | u8 slb_cache_ptr; |
117 | u8 stab_rr; /* stab/slb round-robin counter */ | ||
118 | #ifdef CONFIG_DEBUG_VM | ||
119 | u8 in_kernel_slb_handler; | ||
120 | #endif | ||
121 | u32 slb_used_bitmap; /* Bitmaps for first 32 SLB entries. */ | ||
122 | u32 slb_kern_bitmap; | ||
117 | u32 slb_cache[SLB_CACHE_ENTRIES]; | 123 | u32 slb_cache[SLB_CACHE_ENTRIES]; |
118 | #endif /* CONFIG_PPC_BOOK3S_64 */ | 124 | #endif /* CONFIG_PPC_BOOK3S_64 */ |
119 | 125 | ||
@@ -160,7 +166,6 @@ struct paca_struct { | |||
160 | */ | 166 | */ |
161 | struct task_struct *__current; /* Pointer to current */ | 167 | struct task_struct *__current; /* Pointer to current */ |
162 | u64 kstack; /* Saved Kernel stack addr */ | 168 | u64 kstack; /* Saved Kernel stack addr */ |
163 | u64 stab_rr; /* stab/slb round-robin counter */ | ||
164 | u64 saved_r1; /* r1 save for RTAS calls or PM or EE=0 */ | 169 | u64 saved_r1; /* r1 save for RTAS calls or PM or EE=0 */ |
165 | u64 saved_msr; /* MSR saved here by enter_rtas */ | 170 | u64 saved_msr; /* MSR saved here by enter_rtas */ |
166 | u16 trap_save; /* Used when bad stack is encountered */ | 171 | u16 trap_save; /* Used when bad stack is encountered */ |
@@ -250,6 +255,15 @@ struct paca_struct { | |||
250 | #ifdef CONFIG_PPC_PSERIES | 255 | #ifdef CONFIG_PPC_PSERIES |
251 | u8 *mce_data_buf; /* buffer to hold per cpu rtas errlog */ | 256 | u8 *mce_data_buf; /* buffer to hold per cpu rtas errlog */ |
252 | #endif /* CONFIG_PPC_PSERIES */ | 257 | #endif /* CONFIG_PPC_PSERIES */ |
258 | |||
259 | #ifdef CONFIG_PPC_BOOK3S_64 | ||
260 | /* Capture SLB related old contents in MCE handler. */ | ||
261 | struct slb_entry *mce_faulty_slbs; | ||
262 | u16 slb_save_cache_ptr; | ||
263 | #endif /* CONFIG_PPC_BOOK3S_64 */ | ||
264 | #ifdef CONFIG_STACKPROTECTOR | ||
265 | unsigned long canary; | ||
266 | #endif | ||
253 | } ____cacheline_aligned; | 267 | } ____cacheline_aligned; |
254 | 268 | ||
255 | extern void copy_mm_to_paca(struct mm_struct *mm); | 269 | extern void copy_mm_to_paca(struct mm_struct *mm); |
diff --git a/arch/powerpc/include/asm/pgtable.h b/arch/powerpc/include/asm/pgtable.h index 14c79a7dc855..9679b7519a35 100644 --- a/arch/powerpc/include/asm/pgtable.h +++ b/arch/powerpc/include/asm/pgtable.h | |||
@@ -20,6 +20,25 @@ struct mm_struct; | |||
20 | #include <asm/nohash/pgtable.h> | 20 | #include <asm/nohash/pgtable.h> |
21 | #endif /* !CONFIG_PPC_BOOK3S */ | 21 | #endif /* !CONFIG_PPC_BOOK3S */ |
22 | 22 | ||
23 | /* Note due to the way vm flags are laid out, the bits are XWR */ | ||
24 | #define __P000 PAGE_NONE | ||
25 | #define __P001 PAGE_READONLY | ||
26 | #define __P010 PAGE_COPY | ||
27 | #define __P011 PAGE_COPY | ||
28 | #define __P100 PAGE_READONLY_X | ||
29 | #define __P101 PAGE_READONLY_X | ||
30 | #define __P110 PAGE_COPY_X | ||
31 | #define __P111 PAGE_COPY_X | ||
32 | |||
33 | #define __S000 PAGE_NONE | ||
34 | #define __S001 PAGE_READONLY | ||
35 | #define __S010 PAGE_SHARED | ||
36 | #define __S011 PAGE_SHARED | ||
37 | #define __S100 PAGE_READONLY_X | ||
38 | #define __S101 PAGE_READONLY_X | ||
39 | #define __S110 PAGE_SHARED_X | ||
40 | #define __S111 PAGE_SHARED_X | ||
41 | |||
23 | #ifndef __ASSEMBLY__ | 42 | #ifndef __ASSEMBLY__ |
24 | 43 | ||
25 | #include <asm/tlbflush.h> | 44 | #include <asm/tlbflush.h> |
@@ -27,6 +46,16 @@ struct mm_struct; | |||
27 | /* Keep these as a macros to avoid include dependency mess */ | 46 | /* Keep these as a macros to avoid include dependency mess */ |
28 | #define pte_page(x) pfn_to_page(pte_pfn(x)) | 47 | #define pte_page(x) pfn_to_page(pte_pfn(x)) |
29 | #define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot)) | 48 | #define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot)) |
49 | /* | ||
50 | * Select all bits except the pfn | ||
51 | */ | ||
52 | static inline pgprot_t pte_pgprot(pte_t pte) | ||
53 | { | ||
54 | unsigned long pte_flags; | ||
55 | |||
56 | pte_flags = pte_val(pte) & ~PTE_RPN_MASK; | ||
57 | return __pgprot(pte_flags); | ||
58 | } | ||
30 | 59 | ||
31 | /* | 60 | /* |
32 | * ZERO_PAGE is a global shared page that is always zero: used | 61 | * ZERO_PAGE is a global shared page that is always zero: used |
diff --git a/arch/powerpc/include/asm/ppc-pci.h b/arch/powerpc/include/asm/ppc-pci.h index 726288048652..f67da277d652 100644 --- a/arch/powerpc/include/asm/ppc-pci.h +++ b/arch/powerpc/include/asm/ppc-pci.h | |||
@@ -58,6 +58,7 @@ void eeh_save_bars(struct eeh_dev *edev); | |||
58 | int rtas_write_config(struct pci_dn *, int where, int size, u32 val); | 58 | int rtas_write_config(struct pci_dn *, int where, int size, u32 val); |
59 | int rtas_read_config(struct pci_dn *, int where, int size, u32 *val); | 59 | int rtas_read_config(struct pci_dn *, int where, int size, u32 *val); |
60 | void eeh_pe_state_mark(struct eeh_pe *pe, int state); | 60 | void eeh_pe_state_mark(struct eeh_pe *pe, int state); |
61 | void eeh_pe_mark_isolated(struct eeh_pe *pe); | ||
61 | void eeh_pe_state_clear(struct eeh_pe *pe, int state); | 62 | void eeh_pe_state_clear(struct eeh_pe *pe, int state); |
62 | void eeh_pe_state_mark_with_cfg(struct eeh_pe *pe, int state); | 63 | void eeh_pe_state_mark_with_cfg(struct eeh_pe *pe, int state); |
63 | void eeh_pe_dev_mode_mark(struct eeh_pe *pe, int mode); | 64 | void eeh_pe_dev_mode_mark(struct eeh_pe *pe, int mode); |
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h index 52fadded5c1e..7d04d60a39c9 100644 --- a/arch/powerpc/include/asm/processor.h +++ b/arch/powerpc/include/asm/processor.h | |||
@@ -32,9 +32,9 @@ | |||
32 | /* Default SMT priority is set to 3. Use 11- 13bits to save priority. */ | 32 | /* Default SMT priority is set to 3. Use 11- 13bits to save priority. */ |
33 | #define PPR_PRIORITY 3 | 33 | #define PPR_PRIORITY 3 |
34 | #ifdef __ASSEMBLY__ | 34 | #ifdef __ASSEMBLY__ |
35 | #define INIT_PPR (PPR_PRIORITY << 50) | 35 | #define DEFAULT_PPR (PPR_PRIORITY << 50) |
36 | #else | 36 | #else |
37 | #define INIT_PPR ((u64)PPR_PRIORITY << 50) | 37 | #define DEFAULT_PPR ((u64)PPR_PRIORITY << 50) |
38 | #endif /* __ASSEMBLY__ */ | 38 | #endif /* __ASSEMBLY__ */ |
39 | #endif /* CONFIG_PPC64 */ | 39 | #endif /* CONFIG_PPC64 */ |
40 | 40 | ||
@@ -273,6 +273,7 @@ struct thread_struct { | |||
273 | #endif /* CONFIG_HAVE_HW_BREAKPOINT */ | 273 | #endif /* CONFIG_HAVE_HW_BREAKPOINT */ |
274 | struct arch_hw_breakpoint hw_brk; /* info on the hardware breakpoint */ | 274 | struct arch_hw_breakpoint hw_brk; /* info on the hardware breakpoint */ |
275 | unsigned long trap_nr; /* last trap # on this thread */ | 275 | unsigned long trap_nr; /* last trap # on this thread */ |
276 | u8 load_slb; /* Ages out SLB preload cache entries */ | ||
276 | u8 load_fp; | 277 | u8 load_fp; |
277 | #ifdef CONFIG_ALTIVEC | 278 | #ifdef CONFIG_ALTIVEC |
278 | u8 load_vec; | 279 | u8 load_vec; |
@@ -341,7 +342,6 @@ struct thread_struct { | |||
341 | * onwards. | 342 | * onwards. |
342 | */ | 343 | */ |
343 | int dscr_inherit; | 344 | int dscr_inherit; |
344 | unsigned long ppr; /* used to save/restore SMT priority */ | ||
345 | unsigned long tidr; | 345 | unsigned long tidr; |
346 | #endif | 346 | #endif |
347 | #ifdef CONFIG_PPC_BOOK3S_64 | 347 | #ifdef CONFIG_PPC_BOOK3S_64 |
@@ -389,7 +389,6 @@ struct thread_struct { | |||
389 | .regs = (struct pt_regs *)INIT_SP - 1, /* XXX bogus, I think */ \ | 389 | .regs = (struct pt_regs *)INIT_SP - 1, /* XXX bogus, I think */ \ |
390 | .addr_limit = KERNEL_DS, \ | 390 | .addr_limit = KERNEL_DS, \ |
391 | .fpexc_mode = 0, \ | 391 | .fpexc_mode = 0, \ |
392 | .ppr = INIT_PPR, \ | ||
393 | .fscr = FSCR_TAR | FSCR_EBB \ | 392 | .fscr = FSCR_TAR | FSCR_EBB \ |
394 | } | 393 | } |
395 | #endif | 394 | #endif |
diff --git a/arch/powerpc/include/asm/pte-common.h b/arch/powerpc/include/asm/pte-common.h deleted file mode 100644 index bef56141a549..000000000000 --- a/arch/powerpc/include/asm/pte-common.h +++ /dev/null | |||
@@ -1,219 +0,0 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
2 | /* Included from asm/pgtable-*.h only ! */ | ||
3 | |||
4 | /* | ||
5 | * Some bits are only used on some cpu families... Make sure that all | ||
6 | * the undefined gets a sensible default | ||
7 | */ | ||
8 | #ifndef _PAGE_HASHPTE | ||
9 | #define _PAGE_HASHPTE 0 | ||
10 | #endif | ||
11 | #ifndef _PAGE_HWWRITE | ||
12 | #define _PAGE_HWWRITE 0 | ||
13 | #endif | ||
14 | #ifndef _PAGE_EXEC | ||
15 | #define _PAGE_EXEC 0 | ||
16 | #endif | ||
17 | #ifndef _PAGE_ENDIAN | ||
18 | #define _PAGE_ENDIAN 0 | ||
19 | #endif | ||
20 | #ifndef _PAGE_COHERENT | ||
21 | #define _PAGE_COHERENT 0 | ||
22 | #endif | ||
23 | #ifndef _PAGE_WRITETHRU | ||
24 | #define _PAGE_WRITETHRU 0 | ||
25 | #endif | ||
26 | #ifndef _PAGE_4K_PFN | ||
27 | #define _PAGE_4K_PFN 0 | ||
28 | #endif | ||
29 | #ifndef _PAGE_SAO | ||
30 | #define _PAGE_SAO 0 | ||
31 | #endif | ||
32 | #ifndef _PAGE_PSIZE | ||
33 | #define _PAGE_PSIZE 0 | ||
34 | #endif | ||
35 | /* _PAGE_RO and _PAGE_RW shall not be defined at the same time */ | ||
36 | #ifndef _PAGE_RO | ||
37 | #define _PAGE_RO 0 | ||
38 | #else | ||
39 | #define _PAGE_RW 0 | ||
40 | #endif | ||
41 | |||
42 | #ifndef _PAGE_PTE | ||
43 | #define _PAGE_PTE 0 | ||
44 | #endif | ||
45 | /* At least one of _PAGE_PRIVILEGED or _PAGE_USER must be defined */ | ||
46 | #ifndef _PAGE_PRIVILEGED | ||
47 | #define _PAGE_PRIVILEGED 0 | ||
48 | #else | ||
49 | #ifndef _PAGE_USER | ||
50 | #define _PAGE_USER 0 | ||
51 | #endif | ||
52 | #endif | ||
53 | #ifndef _PAGE_NA | ||
54 | #define _PAGE_NA 0 | ||
55 | #endif | ||
56 | #ifndef _PAGE_HUGE | ||
57 | #define _PAGE_HUGE 0 | ||
58 | #endif | ||
59 | |||
60 | #ifndef _PMD_PRESENT_MASK | ||
61 | #define _PMD_PRESENT_MASK _PMD_PRESENT | ||
62 | #endif | ||
63 | #ifndef _PMD_USER | ||
64 | #define _PMD_USER 0 | ||
65 | #endif | ||
66 | #ifndef _PAGE_KERNEL_RO | ||
67 | #define _PAGE_KERNEL_RO (_PAGE_PRIVILEGED | _PAGE_RO) | ||
68 | #endif | ||
69 | #ifndef _PAGE_KERNEL_ROX | ||
70 | #define _PAGE_KERNEL_ROX (_PAGE_PRIVILEGED | _PAGE_RO | _PAGE_EXEC) | ||
71 | #endif | ||
72 | #ifndef _PAGE_KERNEL_RW | ||
73 | #define _PAGE_KERNEL_RW (_PAGE_PRIVILEGED | _PAGE_DIRTY | _PAGE_RW | \ | ||
74 | _PAGE_HWWRITE) | ||
75 | #endif | ||
76 | #ifndef _PAGE_KERNEL_RWX | ||
77 | #define _PAGE_KERNEL_RWX (_PAGE_PRIVILEGED | _PAGE_DIRTY | _PAGE_RW | \ | ||
78 | _PAGE_HWWRITE | _PAGE_EXEC) | ||
79 | #endif | ||
80 | #ifndef _PAGE_HPTEFLAGS | ||
81 | #define _PAGE_HPTEFLAGS _PAGE_HASHPTE | ||
82 | #endif | ||
83 | #ifndef _PTE_NONE_MASK | ||
84 | #define _PTE_NONE_MASK _PAGE_HPTEFLAGS | ||
85 | #endif | ||
86 | |||
87 | #ifndef __ASSEMBLY__ | ||
88 | |||
89 | /* | ||
90 | * Don't just check for any non zero bits in __PAGE_USER, since for book3e | ||
91 | * and PTE_64BIT, PAGE_KERNEL_X contains _PAGE_BAP_SR which is also in | ||
92 | * _PAGE_USER. Need to explicitly match _PAGE_BAP_UR bit in that case too. | ||
93 | */ | ||
94 | static inline bool pte_user(pte_t pte) | ||
95 | { | ||
96 | return (pte_val(pte) & (_PAGE_USER | _PAGE_PRIVILEGED)) == _PAGE_USER; | ||
97 | } | ||
98 | #endif /* __ASSEMBLY__ */ | ||
99 | |||
100 | /* Location of the PFN in the PTE. Most 32-bit platforms use the same | ||
101 | * as _PAGE_SHIFT here (ie, naturally aligned). | ||
102 | * Platform who don't just pre-define the value so we don't override it here | ||
103 | */ | ||
104 | #ifndef PTE_RPN_SHIFT | ||
105 | #define PTE_RPN_SHIFT (PAGE_SHIFT) | ||
106 | #endif | ||
107 | |||
108 | /* The mask covered by the RPN must be a ULL on 32-bit platforms with | ||
109 | * 64-bit PTEs | ||
110 | */ | ||
111 | #if defined(CONFIG_PPC32) && defined(CONFIG_PTE_64BIT) | ||
112 | #define PTE_RPN_MASK (~((1ULL<<PTE_RPN_SHIFT)-1)) | ||
113 | #else | ||
114 | #define PTE_RPN_MASK (~((1UL<<PTE_RPN_SHIFT)-1)) | ||
115 | #endif | ||
116 | |||
117 | /* _PAGE_CHG_MASK masks of bits that are to be preserved across | ||
118 | * pgprot changes | ||
119 | */ | ||
120 | #define _PAGE_CHG_MASK (PTE_RPN_MASK | _PAGE_HPTEFLAGS | _PAGE_DIRTY | \ | ||
121 | _PAGE_ACCESSED | _PAGE_SPECIAL) | ||
122 | |||
123 | /* Mask of bits returned by pte_pgprot() */ | ||
124 | #define PAGE_PROT_BITS (_PAGE_GUARDED | _PAGE_COHERENT | _PAGE_NO_CACHE | \ | ||
125 | _PAGE_WRITETHRU | _PAGE_ENDIAN | _PAGE_4K_PFN | \ | ||
126 | _PAGE_USER | _PAGE_ACCESSED | _PAGE_RO | _PAGE_NA | \ | ||
127 | _PAGE_PRIVILEGED | \ | ||
128 | _PAGE_RW | _PAGE_HWWRITE | _PAGE_DIRTY | _PAGE_EXEC) | ||
129 | |||
130 | /* | ||
131 | * We define 2 sets of base prot bits, one for basic pages (ie, | ||
132 | * cacheable kernel and user pages) and one for non cacheable | ||
133 | * pages. We always set _PAGE_COHERENT when SMP is enabled or | ||
134 | * the processor might need it for DMA coherency. | ||
135 | */ | ||
136 | #define _PAGE_BASE_NC (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_PSIZE) | ||
137 | #if defined(CONFIG_SMP) || defined(CONFIG_PPC_STD_MMU) || \ | ||
138 | defined(CONFIG_PPC_E500MC) | ||
139 | #define _PAGE_BASE (_PAGE_BASE_NC | _PAGE_COHERENT) | ||
140 | #else | ||
141 | #define _PAGE_BASE (_PAGE_BASE_NC) | ||
142 | #endif | ||
143 | |||
144 | /* Permission masks used to generate the __P and __S table, | ||
145 | * | ||
146 | * Note:__pgprot is defined in arch/powerpc/include/asm/page.h | ||
147 | * | ||
148 | * Write permissions imply read permissions for now (we could make write-only | ||
149 | * pages on BookE but we don't bother for now). Execute permission control is | ||
150 | * possible on platforms that define _PAGE_EXEC | ||
151 | * | ||
152 | * Note due to the way vm flags are laid out, the bits are XWR | ||
153 | */ | ||
154 | #define PAGE_NONE __pgprot(_PAGE_BASE | _PAGE_NA) | ||
155 | #define PAGE_SHARED __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW) | ||
156 | #define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | \ | ||
157 | _PAGE_EXEC) | ||
158 | #define PAGE_COPY __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RO) | ||
159 | #define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RO | \ | ||
160 | _PAGE_EXEC) | ||
161 | #define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RO) | ||
162 | #define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RO | \ | ||
163 | _PAGE_EXEC) | ||
164 | |||
165 | #define __P000 PAGE_NONE | ||
166 | #define __P001 PAGE_READONLY | ||
167 | #define __P010 PAGE_COPY | ||
168 | #define __P011 PAGE_COPY | ||
169 | #define __P100 PAGE_READONLY_X | ||
170 | #define __P101 PAGE_READONLY_X | ||
171 | #define __P110 PAGE_COPY_X | ||
172 | #define __P111 PAGE_COPY_X | ||
173 | |||
174 | #define __S000 PAGE_NONE | ||
175 | #define __S001 PAGE_READONLY | ||
176 | #define __S010 PAGE_SHARED | ||
177 | #define __S011 PAGE_SHARED | ||
178 | #define __S100 PAGE_READONLY_X | ||
179 | #define __S101 PAGE_READONLY_X | ||
180 | #define __S110 PAGE_SHARED_X | ||
181 | #define __S111 PAGE_SHARED_X | ||
182 | |||
183 | /* Permission masks used for kernel mappings */ | ||
184 | #define PAGE_KERNEL __pgprot(_PAGE_BASE | _PAGE_KERNEL_RW) | ||
185 | #define PAGE_KERNEL_NC __pgprot(_PAGE_BASE_NC | _PAGE_KERNEL_RW | \ | ||
186 | _PAGE_NO_CACHE) | ||
187 | #define PAGE_KERNEL_NCG __pgprot(_PAGE_BASE_NC | _PAGE_KERNEL_RW | \ | ||
188 | _PAGE_NO_CACHE | _PAGE_GUARDED) | ||
189 | #define PAGE_KERNEL_X __pgprot(_PAGE_BASE | _PAGE_KERNEL_RWX) | ||
190 | #define PAGE_KERNEL_RO __pgprot(_PAGE_BASE | _PAGE_KERNEL_RO) | ||
191 | #define PAGE_KERNEL_ROX __pgprot(_PAGE_BASE | _PAGE_KERNEL_ROX) | ||
192 | |||
193 | /* Protection used for kernel text. We want the debuggers to be able to | ||
194 | * set breakpoints anywhere, so don't write protect the kernel text | ||
195 | * on platforms where such control is possible. | ||
196 | */ | ||
197 | #if defined(CONFIG_KGDB) || defined(CONFIG_XMON) || defined(CONFIG_BDI_SWITCH) ||\ | ||
198 | defined(CONFIG_KPROBES) || defined(CONFIG_DYNAMIC_FTRACE) | ||
199 | #define PAGE_KERNEL_TEXT PAGE_KERNEL_X | ||
200 | #else | ||
201 | #define PAGE_KERNEL_TEXT PAGE_KERNEL_ROX | ||
202 | #endif | ||
203 | |||
204 | /* Make modules code happy. We don't set RO yet */ | ||
205 | #define PAGE_KERNEL_EXEC PAGE_KERNEL_X | ||
206 | |||
207 | /* Advertise special mapping type for AGP */ | ||
208 | #define PAGE_AGP (PAGE_KERNEL_NC) | ||
209 | #define HAVE_PAGE_AGP | ||
210 | |||
211 | #ifndef _PAGE_READ | ||
212 | /* if not defined, we should not find _PAGE_WRITE too */ | ||
213 | #define _PAGE_READ 0 | ||
214 | #define _PAGE_WRITE _PAGE_RW | ||
215 | #endif | ||
216 | |||
217 | #ifndef H_PAGE_4K_PFN | ||
218 | #define H_PAGE_4K_PFN 0 | ||
219 | #endif | ||
diff --git a/arch/powerpc/include/asm/ptrace.h b/arch/powerpc/include/asm/ptrace.h index 5b480e1d5909..f73886a1a7f5 100644 --- a/arch/powerpc/include/asm/ptrace.h +++ b/arch/powerpc/include/asm/ptrace.h | |||
@@ -26,6 +26,37 @@ | |||
26 | #include <uapi/asm/ptrace.h> | 26 | #include <uapi/asm/ptrace.h> |
27 | #include <asm/asm-const.h> | 27 | #include <asm/asm-const.h> |
28 | 28 | ||
29 | #ifndef __ASSEMBLY__ | ||
30 | struct pt_regs | ||
31 | { | ||
32 | union { | ||
33 | struct user_pt_regs user_regs; | ||
34 | struct { | ||
35 | unsigned long gpr[32]; | ||
36 | unsigned long nip; | ||
37 | unsigned long msr; | ||
38 | unsigned long orig_gpr3; | ||
39 | unsigned long ctr; | ||
40 | unsigned long link; | ||
41 | unsigned long xer; | ||
42 | unsigned long ccr; | ||
43 | #ifdef CONFIG_PPC64 | ||
44 | unsigned long softe; | ||
45 | #else | ||
46 | unsigned long mq; | ||
47 | #endif | ||
48 | unsigned long trap; | ||
49 | unsigned long dar; | ||
50 | unsigned long dsisr; | ||
51 | unsigned long result; | ||
52 | }; | ||
53 | }; | ||
54 | |||
55 | #ifdef CONFIG_PPC64 | ||
56 | unsigned long ppr; | ||
57 | #endif | ||
58 | }; | ||
59 | #endif | ||
29 | 60 | ||
30 | #ifdef __powerpc64__ | 61 | #ifdef __powerpc64__ |
31 | 62 | ||
@@ -102,6 +133,11 @@ static inline long regs_return_value(struct pt_regs *regs) | |||
102 | return -regs->gpr[3]; | 133 | return -regs->gpr[3]; |
103 | } | 134 | } |
104 | 135 | ||
136 | static inline void regs_set_return_value(struct pt_regs *regs, unsigned long rc) | ||
137 | { | ||
138 | regs->gpr[3] = rc; | ||
139 | } | ||
140 | |||
105 | #ifdef __powerpc64__ | 141 | #ifdef __powerpc64__ |
106 | #define user_mode(regs) ((((regs)->msr) >> MSR_PR_LG) & 0x1) | 142 | #define user_mode(regs) ((((regs)->msr) >> MSR_PR_LG) & 0x1) |
107 | #else | 143 | #else |
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h index c90698972f42..de52c3166ba4 100644 --- a/arch/powerpc/include/asm/reg.h +++ b/arch/powerpc/include/asm/reg.h | |||
@@ -118,11 +118,16 @@ | |||
118 | #define MSR_TS_S __MASK(MSR_TS_S_LG) /* Transaction Suspended */ | 118 | #define MSR_TS_S __MASK(MSR_TS_S_LG) /* Transaction Suspended */ |
119 | #define MSR_TS_T __MASK(MSR_TS_T_LG) /* Transaction Transactional */ | 119 | #define MSR_TS_T __MASK(MSR_TS_T_LG) /* Transaction Transactional */ |
120 | #define MSR_TS_MASK (MSR_TS_T | MSR_TS_S) /* Transaction State bits */ | 120 | #define MSR_TS_MASK (MSR_TS_T | MSR_TS_S) /* Transaction State bits */ |
121 | #define MSR_TM_ACTIVE(x) (((x) & MSR_TS_MASK) != 0) /* Transaction active? */ | ||
122 | #define MSR_TM_RESV(x) (((x) & MSR_TS_MASK) == MSR_TS_MASK) /* Reserved */ | 121 | #define MSR_TM_RESV(x) (((x) & MSR_TS_MASK) == MSR_TS_MASK) /* Reserved */ |
123 | #define MSR_TM_TRANSACTIONAL(x) (((x) & MSR_TS_MASK) == MSR_TS_T) | 122 | #define MSR_TM_TRANSACTIONAL(x) (((x) & MSR_TS_MASK) == MSR_TS_T) |
124 | #define MSR_TM_SUSPENDED(x) (((x) & MSR_TS_MASK) == MSR_TS_S) | 123 | #define MSR_TM_SUSPENDED(x) (((x) & MSR_TS_MASK) == MSR_TS_S) |
125 | 124 | ||
125 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | ||
126 | #define MSR_TM_ACTIVE(x) (((x) & MSR_TS_MASK) != 0) /* Transaction active? */ | ||
127 | #else | ||
128 | #define MSR_TM_ACTIVE(x) 0 | ||
129 | #endif | ||
130 | |||
126 | #if defined(CONFIG_PPC_BOOK3S_64) | 131 | #if defined(CONFIG_PPC_BOOK3S_64) |
127 | #define MSR_64BIT MSR_SF | 132 | #define MSR_64BIT MSR_SF |
128 | 133 | ||
diff --git a/arch/powerpc/include/asm/rtas.h b/arch/powerpc/include/asm/rtas.h index 71e393c46a49..bb38dd67d47d 100644 --- a/arch/powerpc/include/asm/rtas.h +++ b/arch/powerpc/include/asm/rtas.h | |||
@@ -125,6 +125,7 @@ struct rtas_suspend_me_data { | |||
125 | #define RTAS_TYPE_INFO 0xE2 | 125 | #define RTAS_TYPE_INFO 0xE2 |
126 | #define RTAS_TYPE_DEALLOC 0xE3 | 126 | #define RTAS_TYPE_DEALLOC 0xE3 |
127 | #define RTAS_TYPE_DUMP 0xE4 | 127 | #define RTAS_TYPE_DUMP 0xE4 |
128 | #define RTAS_TYPE_HOTPLUG 0xE5 | ||
128 | /* I don't add PowerMGM events right now, this is a different topic */ | 129 | /* I don't add PowerMGM events right now, this is a different topic */ |
129 | #define RTAS_TYPE_PMGM_POWER_SW_ON 0x60 | 130 | #define RTAS_TYPE_PMGM_POWER_SW_ON 0x60 |
130 | #define RTAS_TYPE_PMGM_POWER_SW_OFF 0x61 | 131 | #define RTAS_TYPE_PMGM_POWER_SW_OFF 0x61 |
@@ -185,11 +186,23 @@ static inline uint8_t rtas_error_disposition(const struct rtas_error_log *elog) | |||
185 | return (elog->byte1 & 0x18) >> 3; | 186 | return (elog->byte1 & 0x18) >> 3; |
186 | } | 187 | } |
187 | 188 | ||
189 | static inline | ||
190 | void rtas_set_disposition_recovered(struct rtas_error_log *elog) | ||
191 | { | ||
192 | elog->byte1 &= ~0x18; | ||
193 | elog->byte1 |= (RTAS_DISP_FULLY_RECOVERED << 3); | ||
194 | } | ||
195 | |||
188 | static inline uint8_t rtas_error_extended(const struct rtas_error_log *elog) | 196 | static inline uint8_t rtas_error_extended(const struct rtas_error_log *elog) |
189 | { | 197 | { |
190 | return (elog->byte1 & 0x04) >> 2; | 198 | return (elog->byte1 & 0x04) >> 2; |
191 | } | 199 | } |
192 | 200 | ||
201 | static inline uint8_t rtas_error_initiator(const struct rtas_error_log *elog) | ||
202 | { | ||
203 | return (elog->byte2 & 0xf0) >> 4; | ||
204 | } | ||
205 | |||
193 | #define rtas_error_type(x) ((x)->byte3) | 206 | #define rtas_error_type(x) ((x)->byte3) |
194 | 207 | ||
195 | static inline | 208 | static inline |
@@ -275,6 +288,7 @@ inline uint32_t rtas_ext_event_company_id(struct rtas_ext_event_log_v6 *ext_log) | |||
275 | #define PSERIES_ELOG_SECT_ID_CALL_HOME (('C' << 8) | 'H') | 288 | #define PSERIES_ELOG_SECT_ID_CALL_HOME (('C' << 8) | 'H') |
276 | #define PSERIES_ELOG_SECT_ID_USER_DEF (('U' << 8) | 'D') | 289 | #define PSERIES_ELOG_SECT_ID_USER_DEF (('U' << 8) | 'D') |
277 | #define PSERIES_ELOG_SECT_ID_HOTPLUG (('H' << 8) | 'P') | 290 | #define PSERIES_ELOG_SECT_ID_HOTPLUG (('H' << 8) | 'P') |
291 | #define PSERIES_ELOG_SECT_ID_MCE (('M' << 8) | 'C') | ||
278 | 292 | ||
279 | /* Vendor specific Platform Event Log Format, Version 6, section header */ | 293 | /* Vendor specific Platform Event Log Format, Version 6, section header */ |
280 | struct pseries_errorlog { | 294 | struct pseries_errorlog { |
@@ -316,6 +330,7 @@ struct pseries_hp_errorlog { | |||
316 | #define PSERIES_HP_ELOG_RESOURCE_MEM 2 | 330 | #define PSERIES_HP_ELOG_RESOURCE_MEM 2 |
317 | #define PSERIES_HP_ELOG_RESOURCE_SLOT 3 | 331 | #define PSERIES_HP_ELOG_RESOURCE_SLOT 3 |
318 | #define PSERIES_HP_ELOG_RESOURCE_PHB 4 | 332 | #define PSERIES_HP_ELOG_RESOURCE_PHB 4 |
333 | #define PSERIES_HP_ELOG_RESOURCE_PMEM 6 | ||
319 | 334 | ||
320 | #define PSERIES_HP_ELOG_ACTION_ADD 1 | 335 | #define PSERIES_HP_ELOG_ACTION_ADD 1 |
321 | #define PSERIES_HP_ELOG_ACTION_REMOVE 2 | 336 | #define PSERIES_HP_ELOG_ACTION_REMOVE 2 |
diff --git a/arch/powerpc/include/asm/slice.h b/arch/powerpc/include/asm/slice.h index e40406cf5628..a595461c9cb0 100644 --- a/arch/powerpc/include/asm/slice.h +++ b/arch/powerpc/include/asm/slice.h | |||
@@ -32,6 +32,7 @@ void slice_set_range_psize(struct mm_struct *mm, unsigned long start, | |||
32 | unsigned long len, unsigned int psize); | 32 | unsigned long len, unsigned int psize); |
33 | 33 | ||
34 | void slice_init_new_context_exec(struct mm_struct *mm); | 34 | void slice_init_new_context_exec(struct mm_struct *mm); |
35 | void slice_setup_new_exec(void); | ||
35 | 36 | ||
36 | #endif /* __ASSEMBLY__ */ | 37 | #endif /* __ASSEMBLY__ */ |
37 | 38 | ||
diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h index 95b66a0c639b..41695745032c 100644 --- a/arch/powerpc/include/asm/smp.h +++ b/arch/powerpc/include/asm/smp.h | |||
@@ -100,6 +100,7 @@ static inline void set_hard_smp_processor_id(int cpu, int phys) | |||
100 | DECLARE_PER_CPU(cpumask_var_t, cpu_sibling_map); | 100 | DECLARE_PER_CPU(cpumask_var_t, cpu_sibling_map); |
101 | DECLARE_PER_CPU(cpumask_var_t, cpu_l2_cache_map); | 101 | DECLARE_PER_CPU(cpumask_var_t, cpu_l2_cache_map); |
102 | DECLARE_PER_CPU(cpumask_var_t, cpu_core_map); | 102 | DECLARE_PER_CPU(cpumask_var_t, cpu_core_map); |
103 | DECLARE_PER_CPU(cpumask_var_t, cpu_smallcore_map); | ||
103 | 104 | ||
104 | static inline struct cpumask *cpu_sibling_mask(int cpu) | 105 | static inline struct cpumask *cpu_sibling_mask(int cpu) |
105 | { | 106 | { |
@@ -116,6 +117,11 @@ static inline struct cpumask *cpu_l2_cache_mask(int cpu) | |||
116 | return per_cpu(cpu_l2_cache_map, cpu); | 117 | return per_cpu(cpu_l2_cache_map, cpu); |
117 | } | 118 | } |
118 | 119 | ||
120 | static inline struct cpumask *cpu_smallcore_mask(int cpu) | ||
121 | { | ||
122 | return per_cpu(cpu_smallcore_map, cpu); | ||
123 | } | ||
124 | |||
119 | extern int cpu_to_core_id(int cpu); | 125 | extern int cpu_to_core_id(int cpu); |
120 | 126 | ||
121 | /* Since OpenPIC has only 4 IPIs, we use slightly different message numbers. | 127 | /* Since OpenPIC has only 4 IPIs, we use slightly different message numbers. |
@@ -166,6 +172,11 @@ static inline const struct cpumask *cpu_sibling_mask(int cpu) | |||
166 | return cpumask_of(cpu); | 172 | return cpumask_of(cpu); |
167 | } | 173 | } |
168 | 174 | ||
175 | static inline const struct cpumask *cpu_smallcore_mask(int cpu) | ||
176 | { | ||
177 | return cpumask_of(cpu); | ||
178 | } | ||
179 | |||
169 | #endif /* CONFIG_SMP */ | 180 | #endif /* CONFIG_SMP */ |
170 | 181 | ||
171 | #ifdef CONFIG_PPC64 | 182 | #ifdef CONFIG_PPC64 |
diff --git a/arch/powerpc/include/asm/sparsemem.h b/arch/powerpc/include/asm/sparsemem.h index 28f5dae25db6..68da49320592 100644 --- a/arch/powerpc/include/asm/sparsemem.h +++ b/arch/powerpc/include/asm/sparsemem.h | |||
@@ -9,17 +9,6 @@ | |||
9 | * MAX_PHYSMEM_BITS 2^N: how much memory we can have in that space | 9 | * MAX_PHYSMEM_BITS 2^N: how much memory we can have in that space |
10 | */ | 10 | */ |
11 | #define SECTION_SIZE_BITS 24 | 11 | #define SECTION_SIZE_BITS 24 |
12 | /* | ||
13 | * If we store section details in page->flags we can't increase the MAX_PHYSMEM_BITS | ||
14 | * if we increase SECTIONS_WIDTH we will not store node details in page->flags and | ||
15 | * page_to_nid does a page->section->node lookup | ||
16 | * Hence only increase for VMEMMAP. | ||
17 | */ | ||
18 | #ifdef CONFIG_SPARSEMEM_VMEMMAP | ||
19 | #define MAX_PHYSMEM_BITS 47 | ||
20 | #else | ||
21 | #define MAX_PHYSMEM_BITS 46 | ||
22 | #endif | ||
23 | 12 | ||
24 | #endif /* CONFIG_SPARSEMEM */ | 13 | #endif /* CONFIG_SPARSEMEM */ |
25 | 14 | ||
diff --git a/arch/powerpc/include/asm/stackprotector.h b/arch/powerpc/include/asm/stackprotector.h new file mode 100644 index 000000000000..1c8460e23583 --- /dev/null +++ b/arch/powerpc/include/asm/stackprotector.h | |||
@@ -0,0 +1,38 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
2 | /* | ||
3 | * GCC stack protector support. | ||
4 | * | ||
5 | */ | ||
6 | |||
7 | #ifndef _ASM_STACKPROTECTOR_H | ||
8 | #define _ASM_STACKPROTECTOR_H | ||
9 | |||
10 | #include <linux/random.h> | ||
11 | #include <linux/version.h> | ||
12 | #include <asm/reg.h> | ||
13 | #include <asm/current.h> | ||
14 | #include <asm/paca.h> | ||
15 | |||
16 | /* | ||
17 | * Initialize the stackprotector canary value. | ||
18 | * | ||
19 | * NOTE: this must only be called from functions that never return, | ||
20 | * and it must always be inlined. | ||
21 | */ | ||
22 | static __always_inline void boot_init_stack_canary(void) | ||
23 | { | ||
24 | unsigned long canary; | ||
25 | |||
26 | /* Try to get a semi random initial value. */ | ||
27 | canary = get_random_canary(); | ||
28 | canary ^= mftb(); | ||
29 | canary ^= LINUX_VERSION_CODE; | ||
30 | canary &= CANARY_MASK; | ||
31 | |||
32 | current->stack_canary = canary; | ||
33 | #ifdef CONFIG_PPC64 | ||
34 | get_paca()->canary = canary; | ||
35 | #endif | ||
36 | } | ||
37 | |||
38 | #endif /* _ASM_STACKPROTECTOR_H */ | ||
diff --git a/arch/powerpc/include/asm/thread_info.h b/arch/powerpc/include/asm/thread_info.h index 3c0002044bc9..544cac0474cb 100644 --- a/arch/powerpc/include/asm/thread_info.h +++ b/arch/powerpc/include/asm/thread_info.h | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <asm/page.h> | 29 | #include <asm/page.h> |
30 | #include <asm/accounting.h> | 30 | #include <asm/accounting.h> |
31 | 31 | ||
32 | #define SLB_PRELOAD_NR 16U | ||
32 | /* | 33 | /* |
33 | * low level task data. | 34 | * low level task data. |
34 | */ | 35 | */ |
@@ -44,6 +45,10 @@ struct thread_info { | |||
44 | #if defined(CONFIG_VIRT_CPU_ACCOUNTING_NATIVE) && defined(CONFIG_PPC32) | 45 | #if defined(CONFIG_VIRT_CPU_ACCOUNTING_NATIVE) && defined(CONFIG_PPC32) |
45 | struct cpu_accounting_data accounting; | 46 | struct cpu_accounting_data accounting; |
46 | #endif | 47 | #endif |
48 | unsigned char slb_preload_nr; | ||
49 | unsigned char slb_preload_tail; | ||
50 | u32 slb_preload_esid[SLB_PRELOAD_NR]; | ||
51 | |||
47 | /* low level flags - has atomic operations done on it */ | 52 | /* low level flags - has atomic operations done on it */ |
48 | unsigned long flags ____cacheline_aligned_in_smp; | 53 | unsigned long flags ____cacheline_aligned_in_smp; |
49 | }; | 54 | }; |
@@ -72,6 +77,12 @@ static inline struct thread_info *current_thread_info(void) | |||
72 | } | 77 | } |
73 | 78 | ||
74 | extern int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src); | 79 | extern int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src); |
80 | |||
81 | #ifdef CONFIG_PPC_BOOK3S_64 | ||
82 | void arch_setup_new_exec(void); | ||
83 | #define arch_setup_new_exec arch_setup_new_exec | ||
84 | #endif | ||
85 | |||
75 | #endif /* __ASSEMBLY__ */ | 86 | #endif /* __ASSEMBLY__ */ |
76 | 87 | ||
77 | /* | 88 | /* |
@@ -81,7 +92,7 @@ extern int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src | |||
81 | #define TIF_SIGPENDING 1 /* signal pending */ | 92 | #define TIF_SIGPENDING 1 /* signal pending */ |
82 | #define TIF_NEED_RESCHED 2 /* rescheduling necessary */ | 93 | #define TIF_NEED_RESCHED 2 /* rescheduling necessary */ |
83 | #define TIF_FSCHECK 3 /* Check FS is USER_DS on return */ | 94 | #define TIF_FSCHECK 3 /* Check FS is USER_DS on return */ |
84 | #define TIF_32BIT 4 /* 32 bit binary */ | 95 | #define TIF_SYSCALL_EMU 4 /* syscall emulation active */ |
85 | #define TIF_RESTORE_TM 5 /* need to restore TM FP/VEC/VSX */ | 96 | #define TIF_RESTORE_TM 5 /* need to restore TM FP/VEC/VSX */ |
86 | #define TIF_PATCH_PENDING 6 /* pending live patching update */ | 97 | #define TIF_PATCH_PENDING 6 /* pending live patching update */ |
87 | #define TIF_SYSCALL_AUDIT 7 /* syscall auditing active */ | 98 | #define TIF_SYSCALL_AUDIT 7 /* syscall auditing active */ |
@@ -100,6 +111,7 @@ extern int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src | |||
100 | #define TIF_ELF2ABI 18 /* function descriptors must die! */ | 111 | #define TIF_ELF2ABI 18 /* function descriptors must die! */ |
101 | #endif | 112 | #endif |
102 | #define TIF_POLLING_NRFLAG 19 /* true if poll_idle() is polling TIF_NEED_RESCHED */ | 113 | #define TIF_POLLING_NRFLAG 19 /* true if poll_idle() is polling TIF_NEED_RESCHED */ |
114 | #define TIF_32BIT 20 /* 32 bit binary */ | ||
103 | 115 | ||
104 | /* as above, but as bit values */ | 116 | /* as above, but as bit values */ |
105 | #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) | 117 | #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) |
@@ -120,9 +132,10 @@ extern int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src | |||
120 | #define _TIF_EMULATE_STACK_STORE (1<<TIF_EMULATE_STACK_STORE) | 132 | #define _TIF_EMULATE_STACK_STORE (1<<TIF_EMULATE_STACK_STORE) |
121 | #define _TIF_NOHZ (1<<TIF_NOHZ) | 133 | #define _TIF_NOHZ (1<<TIF_NOHZ) |
122 | #define _TIF_FSCHECK (1<<TIF_FSCHECK) | 134 | #define _TIF_FSCHECK (1<<TIF_FSCHECK) |
135 | #define _TIF_SYSCALL_EMU (1<<TIF_SYSCALL_EMU) | ||
123 | #define _TIF_SYSCALL_DOTRACE (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \ | 136 | #define _TIF_SYSCALL_DOTRACE (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \ |
124 | _TIF_SECCOMP | _TIF_SYSCALL_TRACEPOINT | \ | 137 | _TIF_SECCOMP | _TIF_SYSCALL_TRACEPOINT | \ |
125 | _TIF_NOHZ) | 138 | _TIF_NOHZ | _TIF_SYSCALL_EMU) |
126 | 139 | ||
127 | #define _TIF_USER_WORK_MASK (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \ | 140 | #define _TIF_USER_WORK_MASK (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \ |
128 | _TIF_NOTIFY_RESUME | _TIF_UPROBE | \ | 141 | _TIF_NOTIFY_RESUME | _TIF_UPROBE | \ |
diff --git a/arch/powerpc/include/asm/trace.h b/arch/powerpc/include/asm/trace.h index d018e8602694..58ef8c43a89d 100644 --- a/arch/powerpc/include/asm/trace.h +++ b/arch/powerpc/include/asm/trace.h | |||
@@ -201,6 +201,21 @@ TRACE_EVENT(tlbie, | |||
201 | __entry->r) | 201 | __entry->r) |
202 | ); | 202 | ); |
203 | 203 | ||
204 | TRACE_EVENT(tlbia, | ||
205 | |||
206 | TP_PROTO(unsigned long id), | ||
207 | TP_ARGS(id), | ||
208 | TP_STRUCT__entry( | ||
209 | __field(unsigned long, id) | ||
210 | ), | ||
211 | |||
212 | TP_fast_assign( | ||
213 | __entry->id = id; | ||
214 | ), | ||
215 | |||
216 | TP_printk("ctx.id=0x%lx", __entry->id) | ||
217 | ); | ||
218 | |||
204 | #endif /* _TRACE_POWERPC_H */ | 219 | #endif /* _TRACE_POWERPC_H */ |
205 | 220 | ||
206 | #undef TRACE_INCLUDE_PATH | 221 | #undef TRACE_INCLUDE_PATH |
diff --git a/arch/powerpc/include/asm/uaccess.h b/arch/powerpc/include/asm/uaccess.h index bac225bb7f64..15bea9a0f260 100644 --- a/arch/powerpc/include/asm/uaccess.h +++ b/arch/powerpc/include/asm/uaccess.h | |||
@@ -260,7 +260,7 @@ do { \ | |||
260 | ({ \ | 260 | ({ \ |
261 | long __gu_err; \ | 261 | long __gu_err; \ |
262 | __long_type(*(ptr)) __gu_val; \ | 262 | __long_type(*(ptr)) __gu_val; \ |
263 | const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ | 263 | __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ |
264 | __chk_user_ptr(ptr); \ | 264 | __chk_user_ptr(ptr); \ |
265 | if (!is_kernel_addr((unsigned long)__gu_addr)) \ | 265 | if (!is_kernel_addr((unsigned long)__gu_addr)) \ |
266 | might_fault(); \ | 266 | might_fault(); \ |
@@ -274,7 +274,7 @@ do { \ | |||
274 | ({ \ | 274 | ({ \ |
275 | long __gu_err = -EFAULT; \ | 275 | long __gu_err = -EFAULT; \ |
276 | __long_type(*(ptr)) __gu_val = 0; \ | 276 | __long_type(*(ptr)) __gu_val = 0; \ |
277 | const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ | 277 | __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ |
278 | might_fault(); \ | 278 | might_fault(); \ |
279 | if (access_ok(VERIFY_READ, __gu_addr, (size))) { \ | 279 | if (access_ok(VERIFY_READ, __gu_addr, (size))) { \ |
280 | barrier_nospec(); \ | 280 | barrier_nospec(); \ |
@@ -288,7 +288,7 @@ do { \ | |||
288 | ({ \ | 288 | ({ \ |
289 | long __gu_err; \ | 289 | long __gu_err; \ |
290 | __long_type(*(ptr)) __gu_val; \ | 290 | __long_type(*(ptr)) __gu_val; \ |
291 | const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ | 291 | __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ |
292 | __chk_user_ptr(ptr); \ | 292 | __chk_user_ptr(ptr); \ |
293 | barrier_nospec(); \ | 293 | barrier_nospec(); \ |
294 | __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ | 294 | __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ |
diff --git a/arch/powerpc/include/asm/user.h b/arch/powerpc/include/asm/user.h index 5c0e082eae7b..99443b8594e7 100644 --- a/arch/powerpc/include/asm/user.h +++ b/arch/powerpc/include/asm/user.h | |||
@@ -31,7 +31,7 @@ | |||
31 | * to write an integer number of pages. | 31 | * to write an integer number of pages. |
32 | */ | 32 | */ |
33 | struct user { | 33 | struct user { |
34 | struct pt_regs regs; /* entire machine state */ | 34 | struct user_pt_regs regs; /* entire machine state */ |
35 | size_t u_tsize; /* text size (pages) */ | 35 | size_t u_tsize; /* text size (pages) */ |
36 | size_t u_dsize; /* data size (pages) */ | 36 | size_t u_dsize; /* data size (pages) */ |
37 | size_t u_ssize; /* stack size (pages) */ | 37 | size_t u_ssize; /* stack size (pages) */ |
diff --git a/arch/powerpc/include/uapi/asm/ptrace.h b/arch/powerpc/include/uapi/asm/ptrace.h index 5e3edc2a7634..f5f1ccc740fc 100644 --- a/arch/powerpc/include/uapi/asm/ptrace.h +++ b/arch/powerpc/include/uapi/asm/ptrace.h | |||
@@ -29,7 +29,12 @@ | |||
29 | 29 | ||
30 | #ifndef __ASSEMBLY__ | 30 | #ifndef __ASSEMBLY__ |
31 | 31 | ||
32 | struct pt_regs { | 32 | #ifdef __KERNEL__ |
33 | struct user_pt_regs | ||
34 | #else | ||
35 | struct pt_regs | ||
36 | #endif | ||
37 | { | ||
33 | unsigned long gpr[32]; | 38 | unsigned long gpr[32]; |
34 | unsigned long nip; | 39 | unsigned long nip; |
35 | unsigned long msr; | 40 | unsigned long msr; |
@@ -160,6 +165,10 @@ struct pt_regs { | |||
160 | #define PTRACE_GETVSRREGS 0x1b | 165 | #define PTRACE_GETVSRREGS 0x1b |
161 | #define PTRACE_SETVSRREGS 0x1c | 166 | #define PTRACE_SETVSRREGS 0x1c |
162 | 167 | ||
168 | /* Syscall emulation defines */ | ||
169 | #define PTRACE_SYSEMU 0x1d | ||
170 | #define PTRACE_SYSEMU_SINGLESTEP 0x1e | ||
171 | |||
163 | /* | 172 | /* |
164 | * Get or set a debug register. The first 16 are DABR registers and the | 173 | * Get or set a debug register. The first 16 are DABR registers and the |
165 | * second 16 are IABR registers. | 174 | * second 16 are IABR registers. |
diff --git a/arch/powerpc/include/uapi/asm/sigcontext.h b/arch/powerpc/include/uapi/asm/sigcontext.h index 2fbe485acdb4..630aeda56d59 100644 --- a/arch/powerpc/include/uapi/asm/sigcontext.h +++ b/arch/powerpc/include/uapi/asm/sigcontext.h | |||
@@ -22,7 +22,11 @@ struct sigcontext { | |||
22 | #endif | 22 | #endif |
23 | unsigned long handler; | 23 | unsigned long handler; |
24 | unsigned long oldmask; | 24 | unsigned long oldmask; |
25 | struct pt_regs __user *regs; | 25 | #ifdef __KERNEL__ |
26 | struct user_pt_regs __user *regs; | ||
27 | #else | ||
28 | struct pt_regs *regs; | ||
29 | #endif | ||
26 | #ifdef __powerpc64__ | 30 | #ifdef __powerpc64__ |
27 | elf_gregset_t gp_regs; | 31 | elf_gregset_t gp_regs; |
28 | elf_fpregset_t fp_regs; | 32 | elf_fpregset_t fp_regs; |
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 3b66f2c19c84..53d4b8d5b54d 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile | |||
@@ -5,7 +5,8 @@ | |||
5 | 5 | ||
6 | CFLAGS_ptrace.o += -DUTS_MACHINE='"$(UTS_MACHINE)"' | 6 | CFLAGS_ptrace.o += -DUTS_MACHINE='"$(UTS_MACHINE)"' |
7 | 7 | ||
8 | subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror | 8 | # Disable clang warning for using setjmp without setjmp.h header |
9 | CFLAGS_crash.o += $(call cc-disable-warning, builtin-requires-header) | ||
9 | 10 | ||
10 | ifdef CONFIG_PPC64 | 11 | ifdef CONFIG_PPC64 |
11 | CFLAGS_prom_init.o += $(NO_MINIMAL_TOC) | 12 | CFLAGS_prom_init.o += $(NO_MINIMAL_TOC) |
@@ -20,12 +21,14 @@ CFLAGS_prom_init.o += $(DISABLE_LATENT_ENTROPY_PLUGIN) | |||
20 | CFLAGS_btext.o += $(DISABLE_LATENT_ENTROPY_PLUGIN) | 21 | CFLAGS_btext.o += $(DISABLE_LATENT_ENTROPY_PLUGIN) |
21 | CFLAGS_prom.o += $(DISABLE_LATENT_ENTROPY_PLUGIN) | 22 | CFLAGS_prom.o += $(DISABLE_LATENT_ENTROPY_PLUGIN) |
22 | 23 | ||
24 | CFLAGS_prom_init.o += $(call cc-option, -fno-stack-protector) | ||
25 | |||
23 | ifdef CONFIG_FUNCTION_TRACER | 26 | ifdef CONFIG_FUNCTION_TRACER |
24 | # Do not trace early boot code | 27 | # Do not trace early boot code |
25 | CFLAGS_REMOVE_cputable.o = -mno-sched-epilog $(CC_FLAGS_FTRACE) | 28 | CFLAGS_REMOVE_cputable.o = $(CC_FLAGS_FTRACE) |
26 | CFLAGS_REMOVE_prom_init.o = -mno-sched-epilog $(CC_FLAGS_FTRACE) | 29 | CFLAGS_REMOVE_prom_init.o = $(CC_FLAGS_FTRACE) |
27 | CFLAGS_REMOVE_btext.o = -mno-sched-epilog $(CC_FLAGS_FTRACE) | 30 | CFLAGS_REMOVE_btext.o = $(CC_FLAGS_FTRACE) |
28 | CFLAGS_REMOVE_prom.o = -mno-sched-epilog $(CC_FLAGS_FTRACE) | 31 | CFLAGS_REMOVE_prom.o = $(CC_FLAGS_FTRACE) |
29 | endif | 32 | endif |
30 | 33 | ||
31 | obj-y := cputable.o ptrace.o syscalls.o \ | 34 | obj-y := cputable.o ptrace.o syscalls.o \ |
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index d68b9ef38328..9ffc72ded73a 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c | |||
@@ -79,11 +79,16 @@ int main(void) | |||
79 | { | 79 | { |
80 | OFFSET(THREAD, task_struct, thread); | 80 | OFFSET(THREAD, task_struct, thread); |
81 | OFFSET(MM, task_struct, mm); | 81 | OFFSET(MM, task_struct, mm); |
82 | #ifdef CONFIG_STACKPROTECTOR | ||
83 | OFFSET(TASK_CANARY, task_struct, stack_canary); | ||
84 | #ifdef CONFIG_PPC64 | ||
85 | OFFSET(PACA_CANARY, paca_struct, canary); | ||
86 | #endif | ||
87 | #endif | ||
82 | OFFSET(MMCONTEXTID, mm_struct, context.id); | 88 | OFFSET(MMCONTEXTID, mm_struct, context.id); |
83 | #ifdef CONFIG_PPC64 | 89 | #ifdef CONFIG_PPC64 |
84 | DEFINE(SIGSEGV, SIGSEGV); | 90 | DEFINE(SIGSEGV, SIGSEGV); |
85 | DEFINE(NMI_MASK, NMI_MASK); | 91 | DEFINE(NMI_MASK, NMI_MASK); |
86 | OFFSET(TASKTHREADPPR, task_struct, thread.ppr); | ||
87 | #else | 92 | #else |
88 | OFFSET(THREAD_INFO, task_struct, stack); | 93 | OFFSET(THREAD_INFO, task_struct, stack); |
89 | DEFINE(THREAD_INFO_GAP, _ALIGN_UP(sizeof(struct thread_info), 16)); | 94 | DEFINE(THREAD_INFO_GAP, _ALIGN_UP(sizeof(struct thread_info), 16)); |
@@ -173,7 +178,6 @@ int main(void) | |||
173 | OFFSET(PACAKSAVE, paca_struct, kstack); | 178 | OFFSET(PACAKSAVE, paca_struct, kstack); |
174 | OFFSET(PACACURRENT, paca_struct, __current); | 179 | OFFSET(PACACURRENT, paca_struct, __current); |
175 | OFFSET(PACASAVEDMSR, paca_struct, saved_msr); | 180 | OFFSET(PACASAVEDMSR, paca_struct, saved_msr); |
176 | OFFSET(PACASTABRR, paca_struct, stab_rr); | ||
177 | OFFSET(PACAR1, paca_struct, saved_r1); | 181 | OFFSET(PACAR1, paca_struct, saved_r1); |
178 | OFFSET(PACATOC, paca_struct, kernel_toc); | 182 | OFFSET(PACATOC, paca_struct, kernel_toc); |
179 | OFFSET(PACAKBASE, paca_struct, kernelbase); | 183 | OFFSET(PACAKBASE, paca_struct, kernelbase); |
@@ -212,6 +216,7 @@ int main(void) | |||
212 | #ifdef CONFIG_PPC_BOOK3S_64 | 216 | #ifdef CONFIG_PPC_BOOK3S_64 |
213 | OFFSET(PACASLBCACHE, paca_struct, slb_cache); | 217 | OFFSET(PACASLBCACHE, paca_struct, slb_cache); |
214 | OFFSET(PACASLBCACHEPTR, paca_struct, slb_cache_ptr); | 218 | OFFSET(PACASLBCACHEPTR, paca_struct, slb_cache_ptr); |
219 | OFFSET(PACASTABRR, paca_struct, stab_rr); | ||
215 | OFFSET(PACAVMALLOCSLLP, paca_struct, vmalloc_sllp); | 220 | OFFSET(PACAVMALLOCSLLP, paca_struct, vmalloc_sllp); |
216 | #ifdef CONFIG_PPC_MM_SLICES | 221 | #ifdef CONFIG_PPC_MM_SLICES |
217 | OFFSET(MMUPSIZESLLP, mmu_psize_def, sllp); | 222 | OFFSET(MMUPSIZESLLP, mmu_psize_def, sllp); |
@@ -274,11 +279,6 @@ int main(void) | |||
274 | /* Interrupt register frame */ | 279 | /* Interrupt register frame */ |
275 | DEFINE(INT_FRAME_SIZE, STACK_INT_FRAME_SIZE); | 280 | DEFINE(INT_FRAME_SIZE, STACK_INT_FRAME_SIZE); |
276 | DEFINE(SWITCH_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs)); | 281 | DEFINE(SWITCH_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs)); |
277 | #ifdef CONFIG_PPC64 | ||
278 | /* Create extra stack space for SRR0 and SRR1 when calling prom/rtas. */ | ||
279 | DEFINE(PROM_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 16); | ||
280 | DEFINE(RTAS_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 16); | ||
281 | #endif /* CONFIG_PPC64 */ | ||
282 | STACK_PT_REGS_OFFSET(GPR0, gpr[0]); | 282 | STACK_PT_REGS_OFFSET(GPR0, gpr[0]); |
283 | STACK_PT_REGS_OFFSET(GPR1, gpr[1]); | 283 | STACK_PT_REGS_OFFSET(GPR1, gpr[1]); |
284 | STACK_PT_REGS_OFFSET(GPR2, gpr[2]); | 284 | STACK_PT_REGS_OFFSET(GPR2, gpr[2]); |
@@ -322,10 +322,7 @@ int main(void) | |||
322 | STACK_PT_REGS_OFFSET(_ESR, dsisr); | 322 | STACK_PT_REGS_OFFSET(_ESR, dsisr); |
323 | #else /* CONFIG_PPC64 */ | 323 | #else /* CONFIG_PPC64 */ |
324 | STACK_PT_REGS_OFFSET(SOFTE, softe); | 324 | STACK_PT_REGS_OFFSET(SOFTE, softe); |
325 | 325 | STACK_PT_REGS_OFFSET(_PPR, ppr); | |
326 | /* These _only_ to be used with {PROM,RTAS}_FRAME_SIZE!!! */ | ||
327 | DEFINE(_SRR0, STACK_FRAME_OVERHEAD+sizeof(struct pt_regs)); | ||
328 | DEFINE(_SRR1, STACK_FRAME_OVERHEAD+sizeof(struct pt_regs)+8); | ||
329 | #endif /* CONFIG_PPC64 */ | 326 | #endif /* CONFIG_PPC64 */ |
330 | 327 | ||
331 | #if defined(CONFIG_PPC32) | 328 | #if defined(CONFIG_PPC32) |
diff --git a/arch/powerpc/kernel/btext.c b/arch/powerpc/kernel/btext.c index b2072d5bbf2b..b4241ed1456e 100644 --- a/arch/powerpc/kernel/btext.c +++ b/arch/powerpc/kernel/btext.c | |||
@@ -163,7 +163,7 @@ void btext_map(void) | |||
163 | offset = ((unsigned long) dispDeviceBase) - base; | 163 | offset = ((unsigned long) dispDeviceBase) - base; |
164 | size = dispDeviceRowBytes * dispDeviceRect[3] + offset | 164 | size = dispDeviceRowBytes * dispDeviceRect[3] + offset |
165 | + dispDeviceRect[0]; | 165 | + dispDeviceRect[0]; |
166 | vbase = __ioremap(base, size, pgprot_val(pgprot_noncached_wc(__pgprot(0)))); | 166 | vbase = ioremap_wc(base, size); |
167 | if (!vbase) | 167 | if (!vbase) |
168 | return; | 168 | return; |
169 | logicalDisplayBase = vbase + offset; | 169 | logicalDisplayBase = vbase + offset; |
diff --git a/arch/powerpc/kernel/cacheinfo.c b/arch/powerpc/kernel/cacheinfo.c index a8f20e5928e1..be57bd07596d 100644 --- a/arch/powerpc/kernel/cacheinfo.c +++ b/arch/powerpc/kernel/cacheinfo.c | |||
@@ -20,6 +20,8 @@ | |||
20 | #include <linux/percpu.h> | 20 | #include <linux/percpu.h> |
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
22 | #include <asm/prom.h> | 22 | #include <asm/prom.h> |
23 | #include <asm/cputhreads.h> | ||
24 | #include <asm/smp.h> | ||
23 | 25 | ||
24 | #include "cacheinfo.h" | 26 | #include "cacheinfo.h" |
25 | 27 | ||
@@ -627,17 +629,48 @@ static ssize_t level_show(struct kobject *k, struct kobj_attribute *attr, char * | |||
627 | static struct kobj_attribute cache_level_attr = | 629 | static struct kobj_attribute cache_level_attr = |
628 | __ATTR(level, 0444, level_show, NULL); | 630 | __ATTR(level, 0444, level_show, NULL); |
629 | 631 | ||
632 | static unsigned int index_dir_to_cpu(struct cache_index_dir *index) | ||
633 | { | ||
634 | struct kobject *index_dir_kobj = &index->kobj; | ||
635 | struct kobject *cache_dir_kobj = index_dir_kobj->parent; | ||
636 | struct kobject *cpu_dev_kobj = cache_dir_kobj->parent; | ||
637 | struct device *dev = kobj_to_dev(cpu_dev_kobj); | ||
638 | |||
639 | return dev->id; | ||
640 | } | ||
641 | |||
642 | /* | ||
643 | * On big-core systems, each core has two groups of CPUs each of which | ||
644 | * has its own L1-cache. The thread-siblings which share l1-cache with | ||
645 | * @cpu can be obtained via cpu_smallcore_mask(). | ||
646 | */ | ||
647 | static const struct cpumask *get_big_core_shared_cpu_map(int cpu, struct cache *cache) | ||
648 | { | ||
649 | if (cache->level == 1) | ||
650 | return cpu_smallcore_mask(cpu); | ||
651 | |||
652 | return &cache->shared_cpu_map; | ||
653 | } | ||
654 | |||
630 | static ssize_t shared_cpu_map_show(struct kobject *k, struct kobj_attribute *attr, char *buf) | 655 | static ssize_t shared_cpu_map_show(struct kobject *k, struct kobj_attribute *attr, char *buf) |
631 | { | 656 | { |
632 | struct cache_index_dir *index; | 657 | struct cache_index_dir *index; |
633 | struct cache *cache; | 658 | struct cache *cache; |
634 | int ret; | 659 | const struct cpumask *mask; |
660 | int ret, cpu; | ||
635 | 661 | ||
636 | index = kobj_to_cache_index_dir(k); | 662 | index = kobj_to_cache_index_dir(k); |
637 | cache = index->cache; | 663 | cache = index->cache; |
638 | 664 | ||
665 | if (has_big_cores) { | ||
666 | cpu = index_dir_to_cpu(index); | ||
667 | mask = get_big_core_shared_cpu_map(cpu, cache); | ||
668 | } else { | ||
669 | mask = &cache->shared_cpu_map; | ||
670 | } | ||
671 | |||
639 | ret = scnprintf(buf, PAGE_SIZE - 1, "%*pb\n", | 672 | ret = scnprintf(buf, PAGE_SIZE - 1, "%*pb\n", |
640 | cpumask_pr_args(&cache->shared_cpu_map)); | 673 | cpumask_pr_args(mask)); |
641 | buf[ret++] = '\n'; | 674 | buf[ret++] = '\n'; |
642 | buf[ret] = '\0'; | 675 | buf[ret] = '\0'; |
643 | return ret; | 676 | return ret; |
diff --git a/arch/powerpc/kernel/crash_dump.c b/arch/powerpc/kernel/crash_dump.c index d10ad258d41a..bbdc4706c159 100644 --- a/arch/powerpc/kernel/crash_dump.c +++ b/arch/powerpc/kernel/crash_dump.c | |||
@@ -110,7 +110,7 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf, | |||
110 | vaddr = __va(paddr); | 110 | vaddr = __va(paddr); |
111 | csize = copy_oldmem_vaddr(vaddr, buf, csize, offset, userbuf); | 111 | csize = copy_oldmem_vaddr(vaddr, buf, csize, offset, userbuf); |
112 | } else { | 112 | } else { |
113 | vaddr = __ioremap(paddr, PAGE_SIZE, 0); | 113 | vaddr = ioremap_cache(paddr, PAGE_SIZE); |
114 | csize = copy_oldmem_vaddr(vaddr, buf, csize, offset, userbuf); | 114 | csize = copy_oldmem_vaddr(vaddr, buf, csize, offset, userbuf); |
115 | iounmap(vaddr); | 115 | iounmap(vaddr); |
116 | } | 116 | } |
diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c index 6ebba3e48b01..6cae6b56ffd6 100644 --- a/arch/powerpc/kernel/eeh.c +++ b/arch/powerpc/kernel/eeh.c | |||
@@ -169,6 +169,11 @@ static size_t eeh_dump_dev_log(struct eeh_dev *edev, char *buf, size_t len) | |||
169 | int n = 0, l = 0; | 169 | int n = 0, l = 0; |
170 | char buffer[128]; | 170 | char buffer[128]; |
171 | 171 | ||
172 | if (!pdn) { | ||
173 | pr_warn("EEH: Note: No error log for absent device.\n"); | ||
174 | return 0; | ||
175 | } | ||
176 | |||
172 | n += scnprintf(buf+n, len-n, "%04x:%02x:%02x.%01x\n", | 177 | n += scnprintf(buf+n, len-n, "%04x:%02x:%02x.%01x\n", |
173 | pdn->phb->global_number, pdn->busno, | 178 | pdn->phb->global_number, pdn->busno, |
174 | PCI_SLOT(pdn->devfn), PCI_FUNC(pdn->devfn)); | 179 | PCI_SLOT(pdn->devfn), PCI_FUNC(pdn->devfn)); |
@@ -399,7 +404,7 @@ static int eeh_phb_check_failure(struct eeh_pe *pe) | |||
399 | } | 404 | } |
400 | 405 | ||
401 | /* Isolate the PHB and send event */ | 406 | /* Isolate the PHB and send event */ |
402 | eeh_pe_state_mark(phb_pe, EEH_PE_ISOLATED); | 407 | eeh_pe_mark_isolated(phb_pe); |
403 | eeh_serialize_unlock(flags); | 408 | eeh_serialize_unlock(flags); |
404 | 409 | ||
405 | pr_err("EEH: PHB#%x failure detected, location: %s\n", | 410 | pr_err("EEH: PHB#%x failure detected, location: %s\n", |
@@ -558,7 +563,7 @@ int eeh_dev_check_failure(struct eeh_dev *edev) | |||
558 | * with other functions on this device, and functions under | 563 | * with other functions on this device, and functions under |
559 | * bridges. | 564 | * bridges. |
560 | */ | 565 | */ |
561 | eeh_pe_state_mark(pe, EEH_PE_ISOLATED); | 566 | eeh_pe_mark_isolated(pe); |
562 | eeh_serialize_unlock(flags); | 567 | eeh_serialize_unlock(flags); |
563 | 568 | ||
564 | /* Most EEH events are due to device driver bugs. Having | 569 | /* Most EEH events are due to device driver bugs. Having |
@@ -676,7 +681,7 @@ int eeh_pci_enable(struct eeh_pe *pe, int function) | |||
676 | 681 | ||
677 | /* Check if the request is finished successfully */ | 682 | /* Check if the request is finished successfully */ |
678 | if (active_flag) { | 683 | if (active_flag) { |
679 | rc = eeh_ops->wait_state(pe, PCI_BUS_RESET_WAIT_MSEC); | 684 | rc = eeh_wait_state(pe, PCI_BUS_RESET_WAIT_MSEC); |
680 | if (rc < 0) | 685 | if (rc < 0) |
681 | return rc; | 686 | return rc; |
682 | 687 | ||
@@ -825,7 +830,8 @@ int pcibios_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state stat | |||
825 | eeh_pe_state_clear(pe, EEH_PE_ISOLATED); | 830 | eeh_pe_state_clear(pe, EEH_PE_ISOLATED); |
826 | break; | 831 | break; |
827 | case pcie_hot_reset: | 832 | case pcie_hot_reset: |
828 | eeh_pe_state_mark_with_cfg(pe, EEH_PE_ISOLATED); | 833 | eeh_pe_mark_isolated(pe); |
834 | eeh_pe_state_clear(pe, EEH_PE_CFG_BLOCKED); | ||
829 | eeh_ops->set_option(pe, EEH_OPT_FREEZE_PE); | 835 | eeh_ops->set_option(pe, EEH_OPT_FREEZE_PE); |
830 | eeh_pe_dev_traverse(pe, eeh_disable_and_save_dev_state, dev); | 836 | eeh_pe_dev_traverse(pe, eeh_disable_and_save_dev_state, dev); |
831 | if (!(pe->type & EEH_PE_VF)) | 837 | if (!(pe->type & EEH_PE_VF)) |
@@ -833,7 +839,8 @@ int pcibios_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state stat | |||
833 | eeh_ops->reset(pe, EEH_RESET_HOT); | 839 | eeh_ops->reset(pe, EEH_RESET_HOT); |
834 | break; | 840 | break; |
835 | case pcie_warm_reset: | 841 | case pcie_warm_reset: |
836 | eeh_pe_state_mark_with_cfg(pe, EEH_PE_ISOLATED); | 842 | eeh_pe_mark_isolated(pe); |
843 | eeh_pe_state_clear(pe, EEH_PE_CFG_BLOCKED); | ||
837 | eeh_ops->set_option(pe, EEH_OPT_FREEZE_PE); | 844 | eeh_ops->set_option(pe, EEH_OPT_FREEZE_PE); |
838 | eeh_pe_dev_traverse(pe, eeh_disable_and_save_dev_state, dev); | 845 | eeh_pe_dev_traverse(pe, eeh_disable_and_save_dev_state, dev); |
839 | if (!(pe->type & EEH_PE_VF)) | 846 | if (!(pe->type & EEH_PE_VF)) |
@@ -913,16 +920,15 @@ int eeh_pe_reset_full(struct eeh_pe *pe) | |||
913 | break; | 920 | break; |
914 | 921 | ||
915 | /* Wait until the PE is in a functioning state */ | 922 | /* Wait until the PE is in a functioning state */ |
916 | state = eeh_ops->wait_state(pe, PCI_BUS_RESET_WAIT_MSEC); | 923 | state = eeh_wait_state(pe, PCI_BUS_RESET_WAIT_MSEC); |
917 | if (eeh_state_active(state)) | ||
918 | break; | ||
919 | |||
920 | if (state < 0) { | 924 | if (state < 0) { |
921 | pr_warn("%s: Unrecoverable slot failure on PHB#%x-PE#%x", | 925 | pr_warn("%s: Unrecoverable slot failure on PHB#%x-PE#%x", |
922 | __func__, pe->phb->global_number, pe->addr); | 926 | __func__, pe->phb->global_number, pe->addr); |
923 | ret = -ENOTRECOVERABLE; | 927 | ret = -ENOTRECOVERABLE; |
924 | break; | 928 | break; |
925 | } | 929 | } |
930 | if (eeh_state_active(state)) | ||
931 | break; | ||
926 | 932 | ||
927 | /* Set error in case this is our last attempt */ | 933 | /* Set error in case this is our last attempt */ |
928 | ret = -EIO; | 934 | ret = -EIO; |
@@ -1036,6 +1042,11 @@ void eeh_probe_devices(void) | |||
1036 | pdn = hose->pci_data; | 1042 | pdn = hose->pci_data; |
1037 | traverse_pci_dn(pdn, eeh_ops->probe, NULL); | 1043 | traverse_pci_dn(pdn, eeh_ops->probe, NULL); |
1038 | } | 1044 | } |
1045 | if (eeh_enabled()) | ||
1046 | pr_info("EEH: PCI Enhanced I/O Error Handling Enabled\n"); | ||
1047 | else | ||
1048 | pr_info("EEH: No capable adapters found\n"); | ||
1049 | |||
1039 | } | 1050 | } |
1040 | 1051 | ||
1041 | /** | 1052 | /** |
@@ -1079,18 +1090,7 @@ static int eeh_init(void) | |||
1079 | eeh_dev_phb_init_dynamic(hose); | 1090 | eeh_dev_phb_init_dynamic(hose); |
1080 | 1091 | ||
1081 | /* Initialize EEH event */ | 1092 | /* Initialize EEH event */ |
1082 | ret = eeh_event_init(); | 1093 | return eeh_event_init(); |
1083 | if (ret) | ||
1084 | return ret; | ||
1085 | |||
1086 | eeh_probe_devices(); | ||
1087 | |||
1088 | if (eeh_enabled()) | ||
1089 | pr_info("EEH: PCI Enhanced I/O Error Handling Enabled\n"); | ||
1090 | else if (!eeh_has_flag(EEH_POSTPONED_PROBE)) | ||
1091 | pr_info("EEH: No capable adapters found\n"); | ||
1092 | |||
1093 | return ret; | ||
1094 | } | 1094 | } |
1095 | 1095 | ||
1096 | core_initcall_sync(eeh_init); | 1096 | core_initcall_sync(eeh_init); |
diff --git a/arch/powerpc/kernel/eeh_dev.c b/arch/powerpc/kernel/eeh_dev.c index a34e6912c15e..d8c90f3284b5 100644 --- a/arch/powerpc/kernel/eeh_dev.c +++ b/arch/powerpc/kernel/eeh_dev.c | |||
@@ -60,8 +60,6 @@ struct eeh_dev *eeh_dev_init(struct pci_dn *pdn) | |||
60 | /* Associate EEH device with OF node */ | 60 | /* Associate EEH device with OF node */ |
61 | pdn->edev = edev; | 61 | pdn->edev = edev; |
62 | edev->pdn = pdn; | 62 | edev->pdn = pdn; |
63 | INIT_LIST_HEAD(&edev->list); | ||
64 | INIT_LIST_HEAD(&edev->rmv_list); | ||
65 | 63 | ||
66 | return edev; | 64 | return edev; |
67 | } | 65 | } |
diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c index 67619b4b3f96..9446248eb6b8 100644 --- a/arch/powerpc/kernel/eeh_driver.c +++ b/arch/powerpc/kernel/eeh_driver.c | |||
@@ -35,8 +35,8 @@ | |||
35 | #include <asm/rtas.h> | 35 | #include <asm/rtas.h> |
36 | 36 | ||
37 | struct eeh_rmv_data { | 37 | struct eeh_rmv_data { |
38 | struct list_head edev_list; | 38 | struct list_head removed_vf_list; |
39 | int removed; | 39 | int removed_dev_count; |
40 | }; | 40 | }; |
41 | 41 | ||
42 | static int eeh_result_priority(enum pci_ers_result result) | 42 | static int eeh_result_priority(enum pci_ers_result result) |
@@ -281,6 +281,10 @@ static void eeh_pe_report_edev(struct eeh_dev *edev, eeh_report_fn fn, | |||
281 | struct pci_driver *driver; | 281 | struct pci_driver *driver; |
282 | enum pci_ers_result new_result; | 282 | enum pci_ers_result new_result; |
283 | 283 | ||
284 | if (!edev->pdev) { | ||
285 | eeh_edev_info(edev, "no device"); | ||
286 | return; | ||
287 | } | ||
284 | device_lock(&edev->pdev->dev); | 288 | device_lock(&edev->pdev->dev); |
285 | if (eeh_edev_actionable(edev)) { | 289 | if (eeh_edev_actionable(edev)) { |
286 | driver = eeh_pcid_get(edev->pdev); | 290 | driver = eeh_pcid_get(edev->pdev); |
@@ -400,7 +404,7 @@ static void *eeh_dev_restore_state(struct eeh_dev *edev, void *userdata) | |||
400 | * EEH device is created. | 404 | * EEH device is created. |
401 | */ | 405 | */ |
402 | if (edev->pe && (edev->pe->state & EEH_PE_CFG_RESTRICTED)) { | 406 | if (edev->pe && (edev->pe->state & EEH_PE_CFG_RESTRICTED)) { |
403 | if (list_is_last(&edev->list, &edev->pe->edevs)) | 407 | if (list_is_last(&edev->entry, &edev->pe->edevs)) |
404 | eeh_pe_restore_bars(edev->pe); | 408 | eeh_pe_restore_bars(edev->pe); |
405 | 409 | ||
406 | return NULL; | 410 | return NULL; |
@@ -465,10 +469,9 @@ static enum pci_ers_result eeh_report_failure(struct eeh_dev *edev, | |||
465 | return rc; | 469 | return rc; |
466 | } | 470 | } |
467 | 471 | ||
468 | static void *eeh_add_virt_device(void *data, void *userdata) | 472 | static void *eeh_add_virt_device(struct eeh_dev *edev) |
469 | { | 473 | { |
470 | struct pci_driver *driver; | 474 | struct pci_driver *driver; |
471 | struct eeh_dev *edev = (struct eeh_dev *)data; | ||
472 | struct pci_dev *dev = eeh_dev_to_pci_dev(edev); | 475 | struct pci_dev *dev = eeh_dev_to_pci_dev(edev); |
473 | struct pci_dn *pdn = eeh_dev_to_pdn(edev); | 476 | struct pci_dn *pdn = eeh_dev_to_pdn(edev); |
474 | 477 | ||
@@ -499,7 +502,6 @@ static void *eeh_rmv_device(struct eeh_dev *edev, void *userdata) | |||
499 | struct pci_driver *driver; | 502 | struct pci_driver *driver; |
500 | struct pci_dev *dev = eeh_dev_to_pci_dev(edev); | 503 | struct pci_dev *dev = eeh_dev_to_pci_dev(edev); |
501 | struct eeh_rmv_data *rmv_data = (struct eeh_rmv_data *)userdata; | 504 | struct eeh_rmv_data *rmv_data = (struct eeh_rmv_data *)userdata; |
502 | int *removed = rmv_data ? &rmv_data->removed : NULL; | ||
503 | 505 | ||
504 | /* | 506 | /* |
505 | * Actually, we should remove the PCI bridges as well. | 507 | * Actually, we should remove the PCI bridges as well. |
@@ -521,7 +523,7 @@ static void *eeh_rmv_device(struct eeh_dev *edev, void *userdata) | |||
521 | if (eeh_dev_removed(edev)) | 523 | if (eeh_dev_removed(edev)) |
522 | return NULL; | 524 | return NULL; |
523 | 525 | ||
524 | if (removed) { | 526 | if (rmv_data) { |
525 | if (eeh_pe_passed(edev->pe)) | 527 | if (eeh_pe_passed(edev->pe)) |
526 | return NULL; | 528 | return NULL; |
527 | driver = eeh_pcid_get(dev); | 529 | driver = eeh_pcid_get(dev); |
@@ -539,10 +541,9 @@ static void *eeh_rmv_device(struct eeh_dev *edev, void *userdata) | |||
539 | /* Remove it from PCI subsystem */ | 541 | /* Remove it from PCI subsystem */ |
540 | pr_debug("EEH: Removing %s without EEH sensitive driver\n", | 542 | pr_debug("EEH: Removing %s without EEH sensitive driver\n", |
541 | pci_name(dev)); | 543 | pci_name(dev)); |
542 | edev->bus = dev->bus; | ||
543 | edev->mode |= EEH_DEV_DISCONNECTED; | 544 | edev->mode |= EEH_DEV_DISCONNECTED; |
544 | if (removed) | 545 | if (rmv_data) |
545 | (*removed)++; | 546 | rmv_data->removed_dev_count++; |
546 | 547 | ||
547 | if (edev->physfn) { | 548 | if (edev->physfn) { |
548 | #ifdef CONFIG_PCI_IOV | 549 | #ifdef CONFIG_PCI_IOV |
@@ -558,7 +559,7 @@ static void *eeh_rmv_device(struct eeh_dev *edev, void *userdata) | |||
558 | pdn->pe_number = IODA_INVALID_PE; | 559 | pdn->pe_number = IODA_INVALID_PE; |
559 | #endif | 560 | #endif |
560 | if (rmv_data) | 561 | if (rmv_data) |
561 | list_add(&edev->rmv_list, &rmv_data->edev_list); | 562 | list_add(&edev->rmv_entry, &rmv_data->removed_vf_list); |
562 | } else { | 563 | } else { |
563 | pci_lock_rescan_remove(); | 564 | pci_lock_rescan_remove(); |
564 | pci_stop_and_remove_bus_device(dev); | 565 | pci_stop_and_remove_bus_device(dev); |
@@ -727,7 +728,7 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus, | |||
727 | * the device up before the scripts have taken it down, | 728 | * the device up before the scripts have taken it down, |
728 | * potentially weird things happen. | 729 | * potentially weird things happen. |
729 | */ | 730 | */ |
730 | if (!driver_eeh_aware || rmv_data->removed) { | 731 | if (!driver_eeh_aware || rmv_data->removed_dev_count) { |
731 | pr_info("EEH: Sleep 5s ahead of %s hotplug\n", | 732 | pr_info("EEH: Sleep 5s ahead of %s hotplug\n", |
732 | (driver_eeh_aware ? "partial" : "complete")); | 733 | (driver_eeh_aware ? "partial" : "complete")); |
733 | ssleep(5); | 734 | ssleep(5); |
@@ -737,10 +738,10 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus, | |||
737 | * PE. We should disconnect it so the binding can be | 738 | * PE. We should disconnect it so the binding can be |
738 | * rebuilt when adding PCI devices. | 739 | * rebuilt when adding PCI devices. |
739 | */ | 740 | */ |
740 | edev = list_first_entry(&pe->edevs, struct eeh_dev, list); | 741 | edev = list_first_entry(&pe->edevs, struct eeh_dev, entry); |
741 | eeh_pe_traverse(pe, eeh_pe_detach_dev, NULL); | 742 | eeh_pe_traverse(pe, eeh_pe_detach_dev, NULL); |
742 | if (pe->type & EEH_PE_VF) { | 743 | if (pe->type & EEH_PE_VF) { |
743 | eeh_add_virt_device(edev, NULL); | 744 | eeh_add_virt_device(edev); |
744 | } else { | 745 | } else { |
745 | if (!driver_eeh_aware) | 746 | if (!driver_eeh_aware) |
746 | eeh_pe_state_clear(pe, EEH_PE_PRI_BUS); | 747 | eeh_pe_state_clear(pe, EEH_PE_PRI_BUS); |
@@ -789,7 +790,8 @@ void eeh_handle_normal_event(struct eeh_pe *pe) | |||
789 | struct eeh_pe *tmp_pe; | 790 | struct eeh_pe *tmp_pe; |
790 | int rc = 0; | 791 | int rc = 0; |
791 | enum pci_ers_result result = PCI_ERS_RESULT_NONE; | 792 | enum pci_ers_result result = PCI_ERS_RESULT_NONE; |
792 | struct eeh_rmv_data rmv_data = {LIST_HEAD_INIT(rmv_data.edev_list), 0}; | 793 | struct eeh_rmv_data rmv_data = |
794 | {LIST_HEAD_INIT(rmv_data.removed_vf_list), 0}; | ||
793 | 795 | ||
794 | bus = eeh_pe_bus_get(pe); | 796 | bus = eeh_pe_bus_get(pe); |
795 | if (!bus) { | 797 | if (!bus) { |
@@ -806,10 +808,8 @@ void eeh_handle_normal_event(struct eeh_pe *pe) | |||
806 | pr_err("EEH: PHB#%x-PE#%x has failed %d times in the last hour and has been permanently disabled.\n", | 808 | pr_err("EEH: PHB#%x-PE#%x has failed %d times in the last hour and has been permanently disabled.\n", |
807 | pe->phb->global_number, pe->addr, | 809 | pe->phb->global_number, pe->addr, |
808 | pe->freeze_count); | 810 | pe->freeze_count); |
809 | goto hard_fail; | 811 | result = PCI_ERS_RESULT_DISCONNECT; |
810 | } | 812 | } |
811 | pr_warn("EEH: This PCI device has failed %d times in the last hour and will be permanently disabled after %d failures.\n", | ||
812 | pe->freeze_count, eeh_max_freezes); | ||
813 | 813 | ||
814 | /* Walk the various device drivers attached to this slot through | 814 | /* Walk the various device drivers attached to this slot through |
815 | * a reset sequence, giving each an opportunity to do what it needs | 815 | * a reset sequence, giving each an opportunity to do what it needs |
@@ -821,31 +821,39 @@ void eeh_handle_normal_event(struct eeh_pe *pe) | |||
821 | * the error. Override the result if necessary to have partially | 821 | * the error. Override the result if necessary to have partially |
822 | * hotplug for this case. | 822 | * hotplug for this case. |
823 | */ | 823 | */ |
824 | pr_info("EEH: Notify device drivers to shutdown\n"); | 824 | if (result != PCI_ERS_RESULT_DISCONNECT) { |
825 | eeh_set_channel_state(pe, pci_channel_io_frozen); | 825 | pr_warn("EEH: This PCI device has failed %d times in the last hour and will be permanently disabled after %d failures.\n", |
826 | eeh_set_irq_state(pe, false); | 826 | pe->freeze_count, eeh_max_freezes); |
827 | eeh_pe_report("error_detected(IO frozen)", pe, eeh_report_error, | 827 | pr_info("EEH: Notify device drivers to shutdown\n"); |
828 | &result); | 828 | eeh_set_channel_state(pe, pci_channel_io_frozen); |
829 | if ((pe->type & EEH_PE_PHB) && | 829 | eeh_set_irq_state(pe, false); |
830 | result != PCI_ERS_RESULT_NONE && | 830 | eeh_pe_report("error_detected(IO frozen)", pe, |
831 | result != PCI_ERS_RESULT_NEED_RESET) | 831 | eeh_report_error, &result); |
832 | result = PCI_ERS_RESULT_NEED_RESET; | 832 | if ((pe->type & EEH_PE_PHB) && |
833 | result != PCI_ERS_RESULT_NONE && | ||
834 | result != PCI_ERS_RESULT_NEED_RESET) | ||
835 | result = PCI_ERS_RESULT_NEED_RESET; | ||
836 | } | ||
833 | 837 | ||
834 | /* Get the current PCI slot state. This can take a long time, | 838 | /* Get the current PCI slot state. This can take a long time, |
835 | * sometimes over 300 seconds for certain systems. | 839 | * sometimes over 300 seconds for certain systems. |
836 | */ | 840 | */ |
837 | rc = eeh_ops->wait_state(pe, MAX_WAIT_FOR_RECOVERY*1000); | 841 | if (result != PCI_ERS_RESULT_DISCONNECT) { |
838 | if (rc < 0 || rc == EEH_STATE_NOT_SUPPORT) { | 842 | rc = eeh_wait_state(pe, MAX_WAIT_FOR_RECOVERY*1000); |
839 | pr_warn("EEH: Permanent failure\n"); | 843 | if (rc < 0 || rc == EEH_STATE_NOT_SUPPORT) { |
840 | goto hard_fail; | 844 | pr_warn("EEH: Permanent failure\n"); |
845 | result = PCI_ERS_RESULT_DISCONNECT; | ||
846 | } | ||
841 | } | 847 | } |
842 | 848 | ||
843 | /* Since rtas may enable MMIO when posting the error log, | 849 | /* Since rtas may enable MMIO when posting the error log, |
844 | * don't post the error log until after all dev drivers | 850 | * don't post the error log until after all dev drivers |
845 | * have been informed. | 851 | * have been informed. |
846 | */ | 852 | */ |
847 | pr_info("EEH: Collect temporary log\n"); | 853 | if (result != PCI_ERS_RESULT_DISCONNECT) { |
848 | eeh_slot_error_detail(pe, EEH_LOG_TEMP); | 854 | pr_info("EEH: Collect temporary log\n"); |
855 | eeh_slot_error_detail(pe, EEH_LOG_TEMP); | ||
856 | } | ||
849 | 857 | ||
850 | /* If all device drivers were EEH-unaware, then shut | 858 | /* If all device drivers were EEH-unaware, then shut |
851 | * down all of the device drivers, and hope they | 859 | * down all of the device drivers, and hope they |
@@ -857,7 +865,7 @@ void eeh_handle_normal_event(struct eeh_pe *pe) | |||
857 | if (rc) { | 865 | if (rc) { |
858 | pr_warn("%s: Unable to reset, err=%d\n", | 866 | pr_warn("%s: Unable to reset, err=%d\n", |
859 | __func__, rc); | 867 | __func__, rc); |
860 | goto hard_fail; | 868 | result = PCI_ERS_RESULT_DISCONNECT; |
861 | } | 869 | } |
862 | } | 870 | } |
863 | 871 | ||
@@ -866,9 +874,9 @@ void eeh_handle_normal_event(struct eeh_pe *pe) | |||
866 | pr_info("EEH: Enable I/O for affected devices\n"); | 874 | pr_info("EEH: Enable I/O for affected devices\n"); |
867 | rc = eeh_pci_enable(pe, EEH_OPT_THAW_MMIO); | 875 | rc = eeh_pci_enable(pe, EEH_OPT_THAW_MMIO); |
868 | 876 | ||
869 | if (rc < 0) | 877 | if (rc < 0) { |
870 | goto hard_fail; | 878 | result = PCI_ERS_RESULT_DISCONNECT; |
871 | if (rc) { | 879 | } else if (rc) { |
872 | result = PCI_ERS_RESULT_NEED_RESET; | 880 | result = PCI_ERS_RESULT_NEED_RESET; |
873 | } else { | 881 | } else { |
874 | pr_info("EEH: Notify device drivers to resume I/O\n"); | 882 | pr_info("EEH: Notify device drivers to resume I/O\n"); |
@@ -882,9 +890,9 @@ void eeh_handle_normal_event(struct eeh_pe *pe) | |||
882 | pr_info("EEH: Enabled DMA for affected devices\n"); | 890 | pr_info("EEH: Enabled DMA for affected devices\n"); |
883 | rc = eeh_pci_enable(pe, EEH_OPT_THAW_DMA); | 891 | rc = eeh_pci_enable(pe, EEH_OPT_THAW_DMA); |
884 | 892 | ||
885 | if (rc < 0) | 893 | if (rc < 0) { |
886 | goto hard_fail; | 894 | result = PCI_ERS_RESULT_DISCONNECT; |
887 | if (rc) { | 895 | } else if (rc) { |
888 | result = PCI_ERS_RESULT_NEED_RESET; | 896 | result = PCI_ERS_RESULT_NEED_RESET; |
889 | } else { | 897 | } else { |
890 | /* | 898 | /* |
@@ -897,12 +905,6 @@ void eeh_handle_normal_event(struct eeh_pe *pe) | |||
897 | } | 905 | } |
898 | } | 906 | } |
899 | 907 | ||
900 | /* If any device has a hard failure, then shut off everything. */ | ||
901 | if (result == PCI_ERS_RESULT_DISCONNECT) { | ||
902 | pr_warn("EEH: Device driver gave up\n"); | ||
903 | goto hard_fail; | ||
904 | } | ||
905 | |||
906 | /* If any device called out for a reset, then reset the slot */ | 908 | /* If any device called out for a reset, then reset the slot */ |
907 | if (result == PCI_ERS_RESULT_NEED_RESET) { | 909 | if (result == PCI_ERS_RESULT_NEED_RESET) { |
908 | pr_info("EEH: Reset without hotplug activity\n"); | 910 | pr_info("EEH: Reset without hotplug activity\n"); |
@@ -910,88 +912,81 @@ void eeh_handle_normal_event(struct eeh_pe *pe) | |||
910 | if (rc) { | 912 | if (rc) { |
911 | pr_warn("%s: Cannot reset, err=%d\n", | 913 | pr_warn("%s: Cannot reset, err=%d\n", |
912 | __func__, rc); | 914 | __func__, rc); |
913 | goto hard_fail; | 915 | result = PCI_ERS_RESULT_DISCONNECT; |
916 | } else { | ||
917 | result = PCI_ERS_RESULT_NONE; | ||
918 | eeh_set_channel_state(pe, pci_channel_io_normal); | ||
919 | eeh_set_irq_state(pe, true); | ||
920 | eeh_pe_report("slot_reset", pe, eeh_report_reset, | ||
921 | &result); | ||
914 | } | 922 | } |
915 | |||
916 | pr_info("EEH: Notify device drivers " | ||
917 | "the completion of reset\n"); | ||
918 | result = PCI_ERS_RESULT_NONE; | ||
919 | eeh_set_channel_state(pe, pci_channel_io_normal); | ||
920 | eeh_set_irq_state(pe, true); | ||
921 | eeh_pe_report("slot_reset", pe, eeh_report_reset, &result); | ||
922 | } | ||
923 | |||
924 | /* All devices should claim they have recovered by now. */ | ||
925 | if ((result != PCI_ERS_RESULT_RECOVERED) && | ||
926 | (result != PCI_ERS_RESULT_NONE)) { | ||
927 | pr_warn("EEH: Not recovered\n"); | ||
928 | goto hard_fail; | ||
929 | } | ||
930 | |||
931 | /* | ||
932 | * For those hot removed VFs, we should add back them after PF get | ||
933 | * recovered properly. | ||
934 | */ | ||
935 | list_for_each_entry_safe(edev, tmp, &rmv_data.edev_list, rmv_list) { | ||
936 | eeh_add_virt_device(edev, NULL); | ||
937 | list_del(&edev->rmv_list); | ||
938 | } | 923 | } |
939 | 924 | ||
940 | /* Tell all device drivers that they can resume operations */ | 925 | if ((result == PCI_ERS_RESULT_RECOVERED) || |
941 | pr_info("EEH: Notify device driver to resume\n"); | 926 | (result == PCI_ERS_RESULT_NONE)) { |
942 | eeh_set_channel_state(pe, pci_channel_io_normal); | 927 | /* |
943 | eeh_set_irq_state(pe, true); | 928 | * For those hot removed VFs, we should add back them after PF |
944 | eeh_pe_report("resume", pe, eeh_report_resume, NULL); | 929 | * get recovered properly. |
945 | eeh_for_each_pe(pe, tmp_pe) { | 930 | */ |
946 | eeh_pe_for_each_dev(tmp_pe, edev, tmp) { | 931 | list_for_each_entry_safe(edev, tmp, &rmv_data.removed_vf_list, |
947 | edev->mode &= ~EEH_DEV_NO_HANDLER; | 932 | rmv_entry) { |
948 | edev->in_error = false; | 933 | eeh_add_virt_device(edev); |
934 | list_del(&edev->rmv_entry); | ||
949 | } | 935 | } |
950 | } | ||
951 | 936 | ||
952 | pr_info("EEH: Recovery successful.\n"); | 937 | /* Tell all device drivers that they can resume operations */ |
953 | goto final; | 938 | pr_info("EEH: Notify device driver to resume\n"); |
939 | eeh_set_channel_state(pe, pci_channel_io_normal); | ||
940 | eeh_set_irq_state(pe, true); | ||
941 | eeh_pe_report("resume", pe, eeh_report_resume, NULL); | ||
942 | eeh_for_each_pe(pe, tmp_pe) { | ||
943 | eeh_pe_for_each_dev(tmp_pe, edev, tmp) { | ||
944 | edev->mode &= ~EEH_DEV_NO_HANDLER; | ||
945 | edev->in_error = false; | ||
946 | } | ||
947 | } | ||
954 | 948 | ||
955 | hard_fail: | 949 | pr_info("EEH: Recovery successful.\n"); |
956 | /* | 950 | } else { |
957 | * About 90% of all real-life EEH failures in the field | 951 | /* |
958 | * are due to poorly seated PCI cards. Only 10% or so are | 952 | * About 90% of all real-life EEH failures in the field |
959 | * due to actual, failed cards. | 953 | * are due to poorly seated PCI cards. Only 10% or so are |
960 | */ | 954 | * due to actual, failed cards. |
961 | pr_err("EEH: Unable to recover from failure from PHB#%x-PE#%x.\n" | 955 | */ |
962 | "Please try reseating or replacing it\n", | 956 | pr_err("EEH: Unable to recover from failure from PHB#%x-PE#%x.\n" |
963 | pe->phb->global_number, pe->addr); | 957 | "Please try reseating or replacing it\n", |
958 | pe->phb->global_number, pe->addr); | ||
964 | 959 | ||
965 | eeh_slot_error_detail(pe, EEH_LOG_PERM); | 960 | eeh_slot_error_detail(pe, EEH_LOG_PERM); |
966 | 961 | ||
967 | /* Notify all devices that they're about to go down. */ | 962 | /* Notify all devices that they're about to go down. */ |
968 | eeh_set_channel_state(pe, pci_channel_io_perm_failure); | 963 | eeh_set_channel_state(pe, pci_channel_io_perm_failure); |
969 | eeh_set_irq_state(pe, false); | 964 | eeh_set_irq_state(pe, false); |
970 | eeh_pe_report("error_detected(permanent failure)", pe, | 965 | eeh_pe_report("error_detected(permanent failure)", pe, |
971 | eeh_report_failure, NULL); | 966 | eeh_report_failure, NULL); |
972 | 967 | ||
973 | /* Mark the PE to be removed permanently */ | 968 | /* Mark the PE to be removed permanently */ |
974 | eeh_pe_state_mark(pe, EEH_PE_REMOVED); | 969 | eeh_pe_state_mark(pe, EEH_PE_REMOVED); |
975 | 970 | ||
976 | /* | 971 | /* |
977 | * Shut down the device drivers for good. We mark | 972 | * Shut down the device drivers for good. We mark |
978 | * all removed devices correctly to avoid access | 973 | * all removed devices correctly to avoid access |
979 | * the their PCI config any more. | 974 | * the their PCI config any more. |
980 | */ | 975 | */ |
981 | if (pe->type & EEH_PE_VF) { | 976 | if (pe->type & EEH_PE_VF) { |
982 | eeh_pe_dev_traverse(pe, eeh_rmv_device, NULL); | 977 | eeh_pe_dev_traverse(pe, eeh_rmv_device, NULL); |
983 | eeh_pe_dev_mode_mark(pe, EEH_DEV_REMOVED); | 978 | eeh_pe_dev_mode_mark(pe, EEH_DEV_REMOVED); |
984 | } else { | 979 | } else { |
985 | eeh_pe_state_clear(pe, EEH_PE_PRI_BUS); | 980 | eeh_pe_state_clear(pe, EEH_PE_PRI_BUS); |
986 | eeh_pe_dev_mode_mark(pe, EEH_DEV_REMOVED); | 981 | eeh_pe_dev_mode_mark(pe, EEH_DEV_REMOVED); |
987 | 982 | ||
988 | pci_lock_rescan_remove(); | 983 | pci_lock_rescan_remove(); |
989 | pci_hp_remove_devices(bus); | 984 | pci_hp_remove_devices(bus); |
990 | pci_unlock_rescan_remove(); | 985 | pci_unlock_rescan_remove(); |
991 | /* The passed PE should no longer be used */ | 986 | /* The passed PE should no longer be used */ |
992 | return; | 987 | return; |
988 | } | ||
993 | } | 989 | } |
994 | final: | ||
995 | eeh_pe_state_clear(pe, EEH_PE_RECOVERING); | 990 | eeh_pe_state_clear(pe, EEH_PE_RECOVERING); |
996 | } | 991 | } |
997 | 992 | ||
@@ -1026,7 +1021,7 @@ void eeh_handle_special_event(void) | |||
1026 | phb_pe = eeh_phb_pe_get(hose); | 1021 | phb_pe = eeh_phb_pe_get(hose); |
1027 | if (!phb_pe) continue; | 1022 | if (!phb_pe) continue; |
1028 | 1023 | ||
1029 | eeh_pe_state_mark(phb_pe, EEH_PE_ISOLATED); | 1024 | eeh_pe_mark_isolated(phb_pe); |
1030 | } | 1025 | } |
1031 | 1026 | ||
1032 | eeh_serialize_unlock(flags); | 1027 | eeh_serialize_unlock(flags); |
@@ -1041,11 +1036,9 @@ void eeh_handle_special_event(void) | |||
1041 | /* Purge all events of the PHB */ | 1036 | /* Purge all events of the PHB */ |
1042 | eeh_remove_event(pe, true); | 1037 | eeh_remove_event(pe, true); |
1043 | 1038 | ||
1044 | if (rc == EEH_NEXT_ERR_DEAD_PHB) | 1039 | if (rc != EEH_NEXT_ERR_DEAD_PHB) |
1045 | eeh_pe_state_mark(pe, EEH_PE_ISOLATED); | 1040 | eeh_pe_state_mark(pe, EEH_PE_RECOVERING); |
1046 | else | 1041 | eeh_pe_mark_isolated(pe); |
1047 | eeh_pe_state_mark(pe, | ||
1048 | EEH_PE_ISOLATED | EEH_PE_RECOVERING); | ||
1049 | 1042 | ||
1050 | eeh_serialize_unlock(flags); | 1043 | eeh_serialize_unlock(flags); |
1051 | 1044 | ||
diff --git a/arch/powerpc/kernel/eeh_pe.c b/arch/powerpc/kernel/eeh_pe.c index 1b238ecc553e..6fa2032e0594 100644 --- a/arch/powerpc/kernel/eeh_pe.c +++ b/arch/powerpc/kernel/eeh_pe.c | |||
@@ -75,7 +75,6 @@ static struct eeh_pe *eeh_pe_alloc(struct pci_controller *phb, int type) | |||
75 | pe->type = type; | 75 | pe->type = type; |
76 | pe->phb = phb; | 76 | pe->phb = phb; |
77 | INIT_LIST_HEAD(&pe->child_list); | 77 | INIT_LIST_HEAD(&pe->child_list); |
78 | INIT_LIST_HEAD(&pe->child); | ||
79 | INIT_LIST_HEAD(&pe->edevs); | 78 | INIT_LIST_HEAD(&pe->edevs); |
80 | 79 | ||
81 | pe->data = (void *)pe + ALIGN(sizeof(struct eeh_pe), | 80 | pe->data = (void *)pe + ALIGN(sizeof(struct eeh_pe), |
@@ -110,6 +109,57 @@ int eeh_phb_pe_create(struct pci_controller *phb) | |||
110 | } | 109 | } |
111 | 110 | ||
112 | /** | 111 | /** |
112 | * eeh_wait_state - Wait for PE state | ||
113 | * @pe: EEH PE | ||
114 | * @max_wait: maximal period in millisecond | ||
115 | * | ||
116 | * Wait for the state of associated PE. It might take some time | ||
117 | * to retrieve the PE's state. | ||
118 | */ | ||
119 | int eeh_wait_state(struct eeh_pe *pe, int max_wait) | ||
120 | { | ||
121 | int ret; | ||
122 | int mwait; | ||
123 | |||
124 | /* | ||
125 | * According to PAPR, the state of PE might be temporarily | ||
126 | * unavailable. Under the circumstance, we have to wait | ||
127 | * for indicated time determined by firmware. The maximal | ||
128 | * wait time is 5 minutes, which is acquired from the original | ||
129 | * EEH implementation. Also, the original implementation | ||
130 | * also defined the minimal wait time as 1 second. | ||
131 | */ | ||
132 | #define EEH_STATE_MIN_WAIT_TIME (1000) | ||
133 | #define EEH_STATE_MAX_WAIT_TIME (300 * 1000) | ||
134 | |||
135 | while (1) { | ||
136 | ret = eeh_ops->get_state(pe, &mwait); | ||
137 | |||
138 | if (ret != EEH_STATE_UNAVAILABLE) | ||
139 | return ret; | ||
140 | |||
141 | if (max_wait <= 0) { | ||
142 | pr_warn("%s: Timeout when getting PE's state (%d)\n", | ||
143 | __func__, max_wait); | ||
144 | return EEH_STATE_NOT_SUPPORT; | ||
145 | } | ||
146 | |||
147 | if (mwait < EEH_STATE_MIN_WAIT_TIME) { | ||
148 | pr_warn("%s: Firmware returned bad wait value %d\n", | ||
149 | __func__, mwait); | ||
150 | mwait = EEH_STATE_MIN_WAIT_TIME; | ||
151 | } else if (mwait > EEH_STATE_MAX_WAIT_TIME) { | ||
152 | pr_warn("%s: Firmware returned too long wait value %d\n", | ||
153 | __func__, mwait); | ||
154 | mwait = EEH_STATE_MAX_WAIT_TIME; | ||
155 | } | ||
156 | |||
157 | msleep(min(mwait, max_wait)); | ||
158 | max_wait -= mwait; | ||
159 | } | ||
160 | } | ||
161 | |||
162 | /** | ||
113 | * eeh_phb_pe_get - Retrieve PHB PE based on the given PHB | 163 | * eeh_phb_pe_get - Retrieve PHB PE based on the given PHB |
114 | * @phb: PCI controller | 164 | * @phb: PCI controller |
115 | * | 165 | * |
@@ -360,7 +410,7 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev) | |||
360 | edev->pe = pe; | 410 | edev->pe = pe; |
361 | 411 | ||
362 | /* Put the edev to PE */ | 412 | /* Put the edev to PE */ |
363 | list_add_tail(&edev->list, &pe->edevs); | 413 | list_add_tail(&edev->entry, &pe->edevs); |
364 | pr_debug("EEH: Add %04x:%02x:%02x.%01x to Bus PE#%x\n", | 414 | pr_debug("EEH: Add %04x:%02x:%02x.%01x to Bus PE#%x\n", |
365 | pdn->phb->global_number, | 415 | pdn->phb->global_number, |
366 | pdn->busno, | 416 | pdn->busno, |
@@ -369,7 +419,7 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev) | |||
369 | pe->addr); | 419 | pe->addr); |
370 | return 0; | 420 | return 0; |
371 | } else if (pe && (pe->type & EEH_PE_INVALID)) { | 421 | } else if (pe && (pe->type & EEH_PE_INVALID)) { |
372 | list_add_tail(&edev->list, &pe->edevs); | 422 | list_add_tail(&edev->entry, &pe->edevs); |
373 | edev->pe = pe; | 423 | edev->pe = pe; |
374 | /* | 424 | /* |
375 | * We're running to here because of PCI hotplug caused by | 425 | * We're running to here because of PCI hotplug caused by |
@@ -379,7 +429,7 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev) | |||
379 | while (parent) { | 429 | while (parent) { |
380 | if (!(parent->type & EEH_PE_INVALID)) | 430 | if (!(parent->type & EEH_PE_INVALID)) |
381 | break; | 431 | break; |
382 | parent->type &= ~(EEH_PE_INVALID | EEH_PE_KEEP); | 432 | parent->type &= ~EEH_PE_INVALID; |
383 | parent = parent->parent; | 433 | parent = parent->parent; |
384 | } | 434 | } |
385 | 435 | ||
@@ -429,7 +479,7 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev) | |||
429 | * link the EEH device accordingly. | 479 | * link the EEH device accordingly. |
430 | */ | 480 | */ |
431 | list_add_tail(&pe->child, &parent->child_list); | 481 | list_add_tail(&pe->child, &parent->child_list); |
432 | list_add_tail(&edev->list, &pe->edevs); | 482 | list_add_tail(&edev->entry, &pe->edevs); |
433 | edev->pe = pe; | 483 | edev->pe = pe; |
434 | pr_debug("EEH: Add %04x:%02x:%02x.%01x to " | 484 | pr_debug("EEH: Add %04x:%02x:%02x.%01x to " |
435 | "Device PE#%x, Parent PE#%x\n", | 485 | "Device PE#%x, Parent PE#%x\n", |
@@ -457,7 +507,8 @@ int eeh_rmv_from_parent_pe(struct eeh_dev *edev) | |||
457 | int cnt; | 507 | int cnt; |
458 | struct pci_dn *pdn = eeh_dev_to_pdn(edev); | 508 | struct pci_dn *pdn = eeh_dev_to_pdn(edev); |
459 | 509 | ||
460 | if (!edev->pe) { | 510 | pe = eeh_dev_to_pe(edev); |
511 | if (!pe) { | ||
461 | pr_debug("%s: No PE found for device %04x:%02x:%02x.%01x\n", | 512 | pr_debug("%s: No PE found for device %04x:%02x:%02x.%01x\n", |
462 | __func__, pdn->phb->global_number, | 513 | __func__, pdn->phb->global_number, |
463 | pdn->busno, | 514 | pdn->busno, |
@@ -467,9 +518,8 @@ int eeh_rmv_from_parent_pe(struct eeh_dev *edev) | |||
467 | } | 518 | } |
468 | 519 | ||
469 | /* Remove the EEH device */ | 520 | /* Remove the EEH device */ |
470 | pe = eeh_dev_to_pe(edev); | ||
471 | edev->pe = NULL; | 521 | edev->pe = NULL; |
472 | list_del(&edev->list); | 522 | list_del(&edev->entry); |
473 | 523 | ||
474 | /* | 524 | /* |
475 | * Check if the parent PE includes any EEH devices. | 525 | * Check if the parent PE includes any EEH devices. |
@@ -541,56 +591,50 @@ void eeh_pe_update_time_stamp(struct eeh_pe *pe) | |||
541 | } | 591 | } |
542 | 592 | ||
543 | /** | 593 | /** |
544 | * __eeh_pe_state_mark - Mark the state for the PE | 594 | * eeh_pe_state_mark - Mark specified state for PE and its associated device |
545 | * @data: EEH PE | 595 | * @pe: EEH PE |
546 | * @flag: state | ||
547 | * | 596 | * |
548 | * The function is used to mark the indicated state for the given | 597 | * EEH error affects the current PE and its child PEs. The function |
549 | * PE. Also, the associated PCI devices will be put into IO frozen | 598 | * is used to mark appropriate state for the affected PEs and the |
550 | * state as well. | 599 | * associated devices. |
551 | */ | 600 | */ |
552 | static void *__eeh_pe_state_mark(struct eeh_pe *pe, void *flag) | 601 | void eeh_pe_state_mark(struct eeh_pe *root, int state) |
553 | { | 602 | { |
554 | int state = *((int *)flag); | 603 | struct eeh_pe *pe; |
555 | struct eeh_dev *edev, *tmp; | ||
556 | struct pci_dev *pdev; | ||
557 | |||
558 | /* Keep the state of permanently removed PE intact */ | ||
559 | if (pe->state & EEH_PE_REMOVED) | ||
560 | return NULL; | ||
561 | |||
562 | pe->state |= state; | ||
563 | |||
564 | /* Offline PCI devices if applicable */ | ||
565 | if (!(state & EEH_PE_ISOLATED)) | ||
566 | return NULL; | ||
567 | |||
568 | eeh_pe_for_each_dev(pe, edev, tmp) { | ||
569 | pdev = eeh_dev_to_pci_dev(edev); | ||
570 | if (pdev) | ||
571 | pdev->error_state = pci_channel_io_frozen; | ||
572 | } | ||
573 | |||
574 | /* Block PCI config access if required */ | ||
575 | if (pe->state & EEH_PE_CFG_RESTRICTED) | ||
576 | pe->state |= EEH_PE_CFG_BLOCKED; | ||
577 | 604 | ||
578 | return NULL; | 605 | eeh_for_each_pe(root, pe) |
606 | if (!(pe->state & EEH_PE_REMOVED)) | ||
607 | pe->state |= state; | ||
579 | } | 608 | } |
609 | EXPORT_SYMBOL_GPL(eeh_pe_state_mark); | ||
580 | 610 | ||
581 | /** | 611 | /** |
582 | * eeh_pe_state_mark - Mark specified state for PE and its associated device | 612 | * eeh_pe_mark_isolated |
583 | * @pe: EEH PE | 613 | * @pe: EEH PE |
584 | * | 614 | * |
585 | * EEH error affects the current PE and its child PEs. The function | 615 | * Record that a PE has been isolated by marking the PE and it's children as |
586 | * is used to mark appropriate state for the affected PEs and the | 616 | * EEH_PE_ISOLATED (and EEH_PE_CFG_BLOCKED, if required) and their PCI devices |
587 | * associated devices. | 617 | * as pci_channel_io_frozen. |
588 | */ | 618 | */ |
589 | void eeh_pe_state_mark(struct eeh_pe *pe, int state) | 619 | void eeh_pe_mark_isolated(struct eeh_pe *root) |
590 | { | 620 | { |
591 | eeh_pe_traverse(pe, __eeh_pe_state_mark, &state); | 621 | struct eeh_pe *pe; |
622 | struct eeh_dev *edev; | ||
623 | struct pci_dev *pdev; | ||
624 | |||
625 | eeh_pe_state_mark(root, EEH_PE_ISOLATED); | ||
626 | eeh_for_each_pe(root, pe) { | ||
627 | list_for_each_entry(edev, &pe->edevs, entry) { | ||
628 | pdev = eeh_dev_to_pci_dev(edev); | ||
629 | if (pdev) | ||
630 | pdev->error_state = pci_channel_io_frozen; | ||
631 | } | ||
632 | /* Block PCI config access if required */ | ||
633 | if (pe->state & EEH_PE_CFG_RESTRICTED) | ||
634 | pe->state |= EEH_PE_CFG_BLOCKED; | ||
635 | } | ||
592 | } | 636 | } |
593 | EXPORT_SYMBOL_GPL(eeh_pe_state_mark); | 637 | EXPORT_SYMBOL_GPL(eeh_pe_mark_isolated); |
594 | 638 | ||
595 | static void *__eeh_pe_dev_mode_mark(struct eeh_dev *edev, void *flag) | 639 | static void *__eeh_pe_dev_mode_mark(struct eeh_dev *edev, void *flag) |
596 | { | 640 | { |
@@ -671,28 +715,6 @@ void eeh_pe_state_clear(struct eeh_pe *pe, int state) | |||
671 | eeh_pe_traverse(pe, __eeh_pe_state_clear, &state); | 715 | eeh_pe_traverse(pe, __eeh_pe_state_clear, &state); |
672 | } | 716 | } |
673 | 717 | ||
674 | /** | ||
675 | * eeh_pe_state_mark_with_cfg - Mark PE state with unblocked config space | ||
676 | * @pe: PE | ||
677 | * @state: PE state to be set | ||
678 | * | ||
679 | * Set specified flag to PE and its child PEs. The PCI config space | ||
680 | * of some PEs is blocked automatically when EEH_PE_ISOLATED is set, | ||
681 | * which isn't needed in some situations. The function allows to set | ||
682 | * the specified flag to indicated PEs without blocking their PCI | ||
683 | * config space. | ||
684 | */ | ||
685 | void eeh_pe_state_mark_with_cfg(struct eeh_pe *pe, int state) | ||
686 | { | ||
687 | eeh_pe_traverse(pe, __eeh_pe_state_mark, &state); | ||
688 | if (!(state & EEH_PE_ISOLATED)) | ||
689 | return; | ||
690 | |||
691 | /* Clear EEH_PE_CFG_BLOCKED, which might be set just now */ | ||
692 | state = EEH_PE_CFG_BLOCKED; | ||
693 | eeh_pe_traverse(pe, __eeh_pe_state_clear, &state); | ||
694 | } | ||
695 | |||
696 | /* | 718 | /* |
697 | * Some PCI bridges (e.g. PLX bridges) have primary/secondary | 719 | * Some PCI bridges (e.g. PLX bridges) have primary/secondary |
698 | * buses assigned explicitly by firmware, and we probably have | 720 | * buses assigned explicitly by firmware, and we probably have |
@@ -945,7 +967,7 @@ struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe) | |||
945 | return pe->bus; | 967 | return pe->bus; |
946 | 968 | ||
947 | /* Retrieve the parent PCI bus of first (top) PCI device */ | 969 | /* Retrieve the parent PCI bus of first (top) PCI device */ |
948 | edev = list_first_entry_or_null(&pe->edevs, struct eeh_dev, list); | 970 | edev = list_first_entry_or_null(&pe->edevs, struct eeh_dev, entry); |
949 | pdev = eeh_dev_to_pci_dev(edev); | 971 | pdev = eeh_dev_to_pci_dev(edev); |
950 | if (pdev) | 972 | if (pdev) |
951 | return pdev->bus; | 973 | return pdev->bus; |
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S index e58c3f467db5..77decded1175 100644 --- a/arch/powerpc/kernel/entry_32.S +++ b/arch/powerpc/kernel/entry_32.S | |||
@@ -794,7 +794,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_601) | |||
794 | lis r10,MSR_KERNEL@h | 794 | lis r10,MSR_KERNEL@h |
795 | ori r10,r10,MSR_KERNEL@l | 795 | ori r10,r10,MSR_KERNEL@l |
796 | bl transfer_to_handler_full | 796 | bl transfer_to_handler_full |
797 | .long nonrecoverable_exception | 797 | .long unrecoverable_exception |
798 | .long ret_from_except | 798 | .long ret_from_except |
799 | #endif | 799 | #endif |
800 | 800 | ||
@@ -1297,7 +1297,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_601) | |||
1297 | rlwinm r3,r3,0,0,30 | 1297 | rlwinm r3,r3,0,0,30 |
1298 | stw r3,_TRAP(r1) | 1298 | stw r3,_TRAP(r1) |
1299 | 4: addi r3,r1,STACK_FRAME_OVERHEAD | 1299 | 4: addi r3,r1,STACK_FRAME_OVERHEAD |
1300 | bl nonrecoverable_exception | 1300 | bl unrecoverable_exception |
1301 | /* shouldn't return */ | 1301 | /* shouldn't return */ |
1302 | b 4b | 1302 | b 4b |
1303 | 1303 | ||
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 2206912ea4f0..7b1693adff2a 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S | |||
@@ -171,7 +171,7 @@ system_call: /* label this so stack traces look sane */ | |||
171 | * based on caller's run-mode / personality. | 171 | * based on caller's run-mode / personality. |
172 | */ | 172 | */ |
173 | ld r11,SYS_CALL_TABLE@toc(2) | 173 | ld r11,SYS_CALL_TABLE@toc(2) |
174 | andi. r10,r10,_TIF_32BIT | 174 | andis. r10,r10,_TIF_32BIT@h |
175 | beq 15f | 175 | beq 15f |
176 | addi r11,r11,8 /* use 32-bit syscall entries */ | 176 | addi r11,r11,8 /* use 32-bit syscall entries */ |
177 | clrldi r3,r3,32 | 177 | clrldi r3,r3,32 |
@@ -386,10 +386,9 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR) | |||
386 | 386 | ||
387 | 4: /* Anything else left to do? */ | 387 | 4: /* Anything else left to do? */ |
388 | BEGIN_FTR_SECTION | 388 | BEGIN_FTR_SECTION |
389 | lis r3,INIT_PPR@highest /* Set thread.ppr = 3 */ | 389 | lis r3,DEFAULT_PPR@highest /* Set default PPR */ |
390 | ld r10,PACACURRENT(r13) | ||
391 | sldi r3,r3,32 /* bits 11-13 are used for ppr */ | 390 | sldi r3,r3,32 /* bits 11-13 are used for ppr */ |
392 | std r3,TASKTHREADPPR(r10) | 391 | std r3,_PPR(r1) |
393 | END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR) | 392 | END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR) |
394 | 393 | ||
395 | andi. r0,r9,(_TIF_SYSCALL_DOTRACE|_TIF_SINGLESTEP) | 394 | andi. r0,r9,(_TIF_SYSCALL_DOTRACE|_TIF_SINGLESTEP) |
@@ -624,6 +623,10 @@ _GLOBAL(_switch) | |||
624 | 623 | ||
625 | addi r6,r4,-THREAD /* Convert THREAD to 'current' */ | 624 | addi r6,r4,-THREAD /* Convert THREAD to 'current' */ |
626 | std r6,PACACURRENT(r13) /* Set new 'current' */ | 625 | std r6,PACACURRENT(r13) /* Set new 'current' */ |
626 | #if defined(CONFIG_STACKPROTECTOR) | ||
627 | ld r6, TASK_CANARY(r6) | ||
628 | std r6, PACA_CANARY(r13) | ||
629 | #endif | ||
627 | 630 | ||
628 | ld r8,KSP(r4) /* new stack pointer */ | 631 | ld r8,KSP(r4) /* new stack pointer */ |
629 | #ifdef CONFIG_PPC_BOOK3S_64 | 632 | #ifdef CONFIG_PPC_BOOK3S_64 |
@@ -672,7 +675,9 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT) | |||
672 | 675 | ||
673 | isync | 676 | isync |
674 | slbie r6 | 677 | slbie r6 |
678 | BEGIN_FTR_SECTION | ||
675 | slbie r6 /* Workaround POWER5 < DD2.1 issue */ | 679 | slbie r6 /* Workaround POWER5 < DD2.1 issue */ |
680 | END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S) | ||
676 | slbmte r7,r0 | 681 | slbmte r7,r0 |
677 | isync | 682 | isync |
678 | 2: | 683 | 2: |
@@ -936,12 +941,6 @@ fast_exception_return: | |||
936 | andi. r0,r3,MSR_RI | 941 | andi. r0,r3,MSR_RI |
937 | beq- .Lunrecov_restore | 942 | beq- .Lunrecov_restore |
938 | 943 | ||
939 | /* Load PPR from thread struct before we clear MSR:RI */ | ||
940 | BEGIN_FTR_SECTION | ||
941 | ld r2,PACACURRENT(r13) | ||
942 | ld r2,TASKTHREADPPR(r2) | ||
943 | END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR) | ||
944 | |||
945 | /* | 944 | /* |
946 | * Clear RI before restoring r13. If we are returning to | 945 | * Clear RI before restoring r13. If we are returning to |
947 | * userspace and we take an exception after restoring r13, | 946 | * userspace and we take an exception after restoring r13, |
@@ -962,7 +961,9 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR) | |||
962 | andi. r0,r3,MSR_PR | 961 | andi. r0,r3,MSR_PR |
963 | beq 1f | 962 | beq 1f |
964 | BEGIN_FTR_SECTION | 963 | BEGIN_FTR_SECTION |
965 | mtspr SPRN_PPR,r2 /* Restore PPR */ | 964 | /* Restore PPR */ |
965 | ld r2,_PPR(r1) | ||
966 | mtspr SPRN_PPR,r2 | ||
966 | END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR) | 967 | END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR) |
967 | ACCOUNT_CPU_USER_EXIT(r13, r2, r4) | 968 | ACCOUNT_CPU_USER_EXIT(r13, r2, r4) |
968 | REST_GPR(13, r1) | 969 | REST_GPR(13, r1) |
@@ -1118,7 +1119,7 @@ _ASM_NOKPROBE_SYMBOL(fast_exception_return); | |||
1118 | _GLOBAL(enter_rtas) | 1119 | _GLOBAL(enter_rtas) |
1119 | mflr r0 | 1120 | mflr r0 |
1120 | std r0,16(r1) | 1121 | std r0,16(r1) |
1121 | stdu r1,-RTAS_FRAME_SIZE(r1) /* Save SP and create stack space. */ | 1122 | stdu r1,-SWITCH_FRAME_SIZE(r1) /* Save SP and create stack space. */ |
1122 | 1123 | ||
1123 | /* Because RTAS is running in 32b mode, it clobbers the high order half | 1124 | /* Because RTAS is running in 32b mode, it clobbers the high order half |
1124 | * of all registers that it saves. We therefore save those registers | 1125 | * of all registers that it saves. We therefore save those registers |
@@ -1250,7 +1251,7 @@ rtas_restore_regs: | |||
1250 | ld r8,_DSISR(r1) | 1251 | ld r8,_DSISR(r1) |
1251 | mtdsisr r8 | 1252 | mtdsisr r8 |
1252 | 1253 | ||
1253 | addi r1,r1,RTAS_FRAME_SIZE /* Unstack our frame */ | 1254 | addi r1,r1,SWITCH_FRAME_SIZE /* Unstack our frame */ |
1254 | ld r0,16(r1) /* get return address */ | 1255 | ld r0,16(r1) /* get return address */ |
1255 | 1256 | ||
1256 | mtlr r0 | 1257 | mtlr r0 |
@@ -1261,7 +1262,7 @@ rtas_restore_regs: | |||
1261 | _GLOBAL(enter_prom) | 1262 | _GLOBAL(enter_prom) |
1262 | mflr r0 | 1263 | mflr r0 |
1263 | std r0,16(r1) | 1264 | std r0,16(r1) |
1264 | stdu r1,-PROM_FRAME_SIZE(r1) /* Save SP and create stack space */ | 1265 | stdu r1,-SWITCH_FRAME_SIZE(r1) /* Save SP and create stack space */ |
1265 | 1266 | ||
1266 | /* Because PROM is running in 32b mode, it clobbers the high order half | 1267 | /* Because PROM is running in 32b mode, it clobbers the high order half |
1267 | * of all registers that it saves. We therefore save those registers | 1268 | * of all registers that it saves. We therefore save those registers |
@@ -1318,8 +1319,8 @@ _GLOBAL(enter_prom) | |||
1318 | REST_10GPRS(22, r1) | 1319 | REST_10GPRS(22, r1) |
1319 | ld r4,_CCR(r1) | 1320 | ld r4,_CCR(r1) |
1320 | mtcr r4 | 1321 | mtcr r4 |
1321 | 1322 | ||
1322 | addi r1,r1,PROM_FRAME_SIZE | 1323 | addi r1,r1,SWITCH_FRAME_SIZE |
1323 | ld r0,16(r1) | 1324 | ld r0,16(r1) |
1324 | mtlr r0 | 1325 | mtlr r0 |
1325 | blr | 1326 | blr |
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S index 2d8fc8c9da7a..89d32bb79d5e 100644 --- a/arch/powerpc/kernel/exceptions-64s.S +++ b/arch/powerpc/kernel/exceptions-64s.S | |||
@@ -244,14 +244,13 @@ EXC_REAL_BEGIN(machine_check, 0x200, 0x100) | |||
244 | SET_SCRATCH0(r13) /* save r13 */ | 244 | SET_SCRATCH0(r13) /* save r13 */ |
245 | EXCEPTION_PROLOG_0(PACA_EXMC) | 245 | EXCEPTION_PROLOG_0(PACA_EXMC) |
246 | BEGIN_FTR_SECTION | 246 | BEGIN_FTR_SECTION |
247 | b machine_check_powernv_early | 247 | b machine_check_common_early |
248 | FTR_SECTION_ELSE | 248 | FTR_SECTION_ELSE |
249 | b machine_check_pSeries_0 | 249 | b machine_check_pSeries_0 |
250 | ALT_FTR_SECTION_END_IFSET(CPU_FTR_HVMODE) | 250 | ALT_FTR_SECTION_END_IFSET(CPU_FTR_HVMODE) |
251 | EXC_REAL_END(machine_check, 0x200, 0x100) | 251 | EXC_REAL_END(machine_check, 0x200, 0x100) |
252 | EXC_VIRT_NONE(0x4200, 0x100) | 252 | EXC_VIRT_NONE(0x4200, 0x100) |
253 | TRAMP_REAL_BEGIN(machine_check_powernv_early) | 253 | TRAMP_REAL_BEGIN(machine_check_common_early) |
254 | BEGIN_FTR_SECTION | ||
255 | EXCEPTION_PROLOG_1(PACA_EXMC, NOTEST, 0x200) | 254 | EXCEPTION_PROLOG_1(PACA_EXMC, NOTEST, 0x200) |
256 | /* | 255 | /* |
257 | * Register contents: | 256 | * Register contents: |
@@ -305,7 +304,9 @@ BEGIN_FTR_SECTION | |||
305 | /* Save r9 through r13 from EXMC save area to stack frame. */ | 304 | /* Save r9 through r13 from EXMC save area to stack frame. */ |
306 | EXCEPTION_PROLOG_COMMON_2(PACA_EXMC) | 305 | EXCEPTION_PROLOG_COMMON_2(PACA_EXMC) |
307 | mfmsr r11 /* get MSR value */ | 306 | mfmsr r11 /* get MSR value */ |
307 | BEGIN_FTR_SECTION | ||
308 | ori r11,r11,MSR_ME /* turn on ME bit */ | 308 | ori r11,r11,MSR_ME /* turn on ME bit */ |
309 | END_FTR_SECTION_IFSET(CPU_FTR_HVMODE) | ||
309 | ori r11,r11,MSR_RI /* turn on RI bit */ | 310 | ori r11,r11,MSR_RI /* turn on RI bit */ |
310 | LOAD_HANDLER(r12, machine_check_handle_early) | 311 | LOAD_HANDLER(r12, machine_check_handle_early) |
311 | 1: mtspr SPRN_SRR0,r12 | 312 | 1: mtspr SPRN_SRR0,r12 |
@@ -324,13 +325,15 @@ BEGIN_FTR_SECTION | |||
324 | andc r11,r11,r10 /* Turn off MSR_ME */ | 325 | andc r11,r11,r10 /* Turn off MSR_ME */ |
325 | b 1b | 326 | b 1b |
326 | b . /* prevent speculative execution */ | 327 | b . /* prevent speculative execution */ |
327 | END_FTR_SECTION_IFSET(CPU_FTR_HVMODE) | ||
328 | 328 | ||
329 | TRAMP_REAL_BEGIN(machine_check_pSeries) | 329 | TRAMP_REAL_BEGIN(machine_check_pSeries) |
330 | .globl machine_check_fwnmi | 330 | .globl machine_check_fwnmi |
331 | machine_check_fwnmi: | 331 | machine_check_fwnmi: |
332 | SET_SCRATCH0(r13) /* save r13 */ | 332 | SET_SCRATCH0(r13) /* save r13 */ |
333 | EXCEPTION_PROLOG_0(PACA_EXMC) | 333 | EXCEPTION_PROLOG_0(PACA_EXMC) |
334 | BEGIN_FTR_SECTION | ||
335 | b machine_check_common_early | ||
336 | END_FTR_SECTION_IFCLR(CPU_FTR_HVMODE) | ||
334 | machine_check_pSeries_0: | 337 | machine_check_pSeries_0: |
335 | EXCEPTION_PROLOG_1(PACA_EXMC, KVMTEST_PR, 0x200) | 338 | EXCEPTION_PROLOG_1(PACA_EXMC, KVMTEST_PR, 0x200) |
336 | /* | 339 | /* |
@@ -440,6 +443,9 @@ EXC_COMMON_BEGIN(machine_check_handle_early) | |||
440 | bl machine_check_early | 443 | bl machine_check_early |
441 | std r3,RESULT(r1) /* Save result */ | 444 | std r3,RESULT(r1) /* Save result */ |
442 | ld r12,_MSR(r1) | 445 | ld r12,_MSR(r1) |
446 | BEGIN_FTR_SECTION | ||
447 | b 4f | ||
448 | END_FTR_SECTION_IFCLR(CPU_FTR_HVMODE) | ||
443 | 449 | ||
444 | #ifdef CONFIG_PPC_P7_NAP | 450 | #ifdef CONFIG_PPC_P7_NAP |
445 | /* | 451 | /* |
@@ -463,11 +469,12 @@ EXC_COMMON_BEGIN(machine_check_handle_early) | |||
463 | */ | 469 | */ |
464 | rldicl. r11,r12,4,63 /* See if MC hit while in HV mode. */ | 470 | rldicl. r11,r12,4,63 /* See if MC hit while in HV mode. */ |
465 | beq 5f | 471 | beq 5f |
466 | andi. r11,r12,MSR_PR /* See if coming from user. */ | 472 | 4: andi. r11,r12,MSR_PR /* See if coming from user. */ |
467 | bne 9f /* continue in V mode if we are. */ | 473 | bne 9f /* continue in V mode if we are. */ |
468 | 474 | ||
469 | 5: | 475 | 5: |
470 | #ifdef CONFIG_KVM_BOOK3S_64_HANDLER | 476 | #ifdef CONFIG_KVM_BOOK3S_64_HANDLER |
477 | BEGIN_FTR_SECTION | ||
471 | /* | 478 | /* |
472 | * We are coming from kernel context. Check if we are coming from | 479 | * We are coming from kernel context. Check if we are coming from |
473 | * guest. if yes, then we can continue. We will fall through | 480 | * guest. if yes, then we can continue. We will fall through |
@@ -476,6 +483,7 @@ EXC_COMMON_BEGIN(machine_check_handle_early) | |||
476 | lbz r11,HSTATE_IN_GUEST(r13) | 483 | lbz r11,HSTATE_IN_GUEST(r13) |
477 | cmpwi r11,0 /* Check if coming from guest */ | 484 | cmpwi r11,0 /* Check if coming from guest */ |
478 | bne 9f /* continue if we are. */ | 485 | bne 9f /* continue if we are. */ |
486 | END_FTR_SECTION_IFSET(CPU_FTR_HVMODE) | ||
479 | #endif | 487 | #endif |
480 | /* | 488 | /* |
481 | * At this point we are not sure about what context we come from. | 489 | * At this point we are not sure about what context we come from. |
@@ -510,6 +518,7 @@ EXC_COMMON_BEGIN(machine_check_handle_early) | |||
510 | cmpdi r3,0 /* see if we handled MCE successfully */ | 518 | cmpdi r3,0 /* see if we handled MCE successfully */ |
511 | 519 | ||
512 | beq 1b /* if !handled then panic */ | 520 | beq 1b /* if !handled then panic */ |
521 | BEGIN_FTR_SECTION | ||
513 | /* | 522 | /* |
514 | * Return from MC interrupt. | 523 | * Return from MC interrupt. |
515 | * Queue up the MCE event so that we can log it later, while | 524 | * Queue up the MCE event so that we can log it later, while |
@@ -518,10 +527,24 @@ EXC_COMMON_BEGIN(machine_check_handle_early) | |||
518 | bl machine_check_queue_event | 527 | bl machine_check_queue_event |
519 | MACHINE_CHECK_HANDLER_WINDUP | 528 | MACHINE_CHECK_HANDLER_WINDUP |
520 | RFI_TO_USER_OR_KERNEL | 529 | RFI_TO_USER_OR_KERNEL |
530 | FTR_SECTION_ELSE | ||
531 | /* | ||
532 | * pSeries: Return from MC interrupt. Before that stay on emergency | ||
533 | * stack and call machine_check_exception to log the MCE event. | ||
534 | */ | ||
535 | LOAD_HANDLER(r10,mce_return) | ||
536 | mtspr SPRN_SRR0,r10 | ||
537 | ld r10,PACAKMSR(r13) | ||
538 | mtspr SPRN_SRR1,r10 | ||
539 | RFI_TO_KERNEL | ||
540 | b . | ||
541 | ALT_FTR_SECTION_END_IFSET(CPU_FTR_HVMODE) | ||
521 | 9: | 542 | 9: |
522 | /* Deliver the machine check to host kernel in V mode. */ | 543 | /* Deliver the machine check to host kernel in V mode. */ |
523 | MACHINE_CHECK_HANDLER_WINDUP | 544 | MACHINE_CHECK_HANDLER_WINDUP |
524 | b machine_check_pSeries | 545 | SET_SCRATCH0(r13) /* save r13 */ |
546 | EXCEPTION_PROLOG_0(PACA_EXMC) | ||
547 | b machine_check_pSeries_0 | ||
525 | 548 | ||
526 | EXC_COMMON_BEGIN(unrecover_mce) | 549 | EXC_COMMON_BEGIN(unrecover_mce) |
527 | /* Invoke machine_check_exception to print MCE event and panic. */ | 550 | /* Invoke machine_check_exception to print MCE event and panic. */ |
@@ -535,6 +558,13 @@ EXC_COMMON_BEGIN(unrecover_mce) | |||
535 | bl unrecoverable_exception | 558 | bl unrecoverable_exception |
536 | b 1b | 559 | b 1b |
537 | 560 | ||
561 | EXC_COMMON_BEGIN(mce_return) | ||
562 | /* Invoke machine_check_exception to print MCE event and return. */ | ||
563 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
564 | bl machine_check_exception | ||
565 | MACHINE_CHECK_HANDLER_WINDUP | ||
566 | RFI_TO_KERNEL | ||
567 | b . | ||
538 | 568 | ||
539 | EXC_REAL(data_access, 0x300, 0x80) | 569 | EXC_REAL(data_access, 0x300, 0x80) |
540 | EXC_VIRT(data_access, 0x4300, 0x80, 0x300) | 570 | EXC_VIRT(data_access, 0x4300, 0x80, 0x300) |
@@ -566,28 +596,36 @@ ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_TYPE_RADIX) | |||
566 | 596 | ||
567 | 597 | ||
568 | EXC_REAL_BEGIN(data_access_slb, 0x380, 0x80) | 598 | EXC_REAL_BEGIN(data_access_slb, 0x380, 0x80) |
569 | SET_SCRATCH0(r13) | 599 | EXCEPTION_PROLOG(PACA_EXSLB, data_access_slb_common, EXC_STD, KVMTEST_PR, 0x380); |
570 | EXCEPTION_PROLOG_0(PACA_EXSLB) | ||
571 | EXCEPTION_PROLOG_1(PACA_EXSLB, KVMTEST_PR, 0x380) | ||
572 | mr r12,r3 /* save r3 */ | ||
573 | mfspr r3,SPRN_DAR | ||
574 | mfspr r11,SPRN_SRR1 | ||
575 | crset 4*cr6+eq | ||
576 | BRANCH_TO_COMMON(r10, slb_miss_common) | ||
577 | EXC_REAL_END(data_access_slb, 0x380, 0x80) | 600 | EXC_REAL_END(data_access_slb, 0x380, 0x80) |
578 | 601 | ||
579 | EXC_VIRT_BEGIN(data_access_slb, 0x4380, 0x80) | 602 | EXC_VIRT_BEGIN(data_access_slb, 0x4380, 0x80) |
580 | SET_SCRATCH0(r13) | 603 | EXCEPTION_RELON_PROLOG(PACA_EXSLB, data_access_slb_common, EXC_STD, NOTEST, 0x380); |
581 | EXCEPTION_PROLOG_0(PACA_EXSLB) | ||
582 | EXCEPTION_PROLOG_1(PACA_EXSLB, NOTEST, 0x380) | ||
583 | mr r12,r3 /* save r3 */ | ||
584 | mfspr r3,SPRN_DAR | ||
585 | mfspr r11,SPRN_SRR1 | ||
586 | crset 4*cr6+eq | ||
587 | BRANCH_TO_COMMON(r10, slb_miss_common) | ||
588 | EXC_VIRT_END(data_access_slb, 0x4380, 0x80) | 604 | EXC_VIRT_END(data_access_slb, 0x4380, 0x80) |
605 | |||
589 | TRAMP_KVM_SKIP(PACA_EXSLB, 0x380) | 606 | TRAMP_KVM_SKIP(PACA_EXSLB, 0x380) |
590 | 607 | ||
608 | EXC_COMMON_BEGIN(data_access_slb_common) | ||
609 | mfspr r10,SPRN_DAR | ||
610 | std r10,PACA_EXSLB+EX_DAR(r13) | ||
611 | EXCEPTION_PROLOG_COMMON(0x380, PACA_EXSLB) | ||
612 | ld r4,PACA_EXSLB+EX_DAR(r13) | ||
613 | std r4,_DAR(r1) | ||
614 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
615 | bl do_slb_fault | ||
616 | cmpdi r3,0 | ||
617 | bne- 1f | ||
618 | b fast_exception_return | ||
619 | 1: /* Error case */ | ||
620 | std r3,RESULT(r1) | ||
621 | bl save_nvgprs | ||
622 | RECONCILE_IRQ_STATE(r10, r11) | ||
623 | ld r4,_DAR(r1) | ||
624 | ld r5,RESULT(r1) | ||
625 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
626 | bl do_bad_slb_fault | ||
627 | b ret_from_except | ||
628 | |||
591 | 629 | ||
592 | EXC_REAL(instruction_access, 0x400, 0x80) | 630 | EXC_REAL(instruction_access, 0x400, 0x80) |
593 | EXC_VIRT(instruction_access, 0x4400, 0x80, 0x400) | 631 | EXC_VIRT(instruction_access, 0x4400, 0x80, 0x400) |
@@ -610,160 +648,34 @@ ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_TYPE_RADIX) | |||
610 | 648 | ||
611 | 649 | ||
612 | EXC_REAL_BEGIN(instruction_access_slb, 0x480, 0x80) | 650 | EXC_REAL_BEGIN(instruction_access_slb, 0x480, 0x80) |
613 | SET_SCRATCH0(r13) | 651 | EXCEPTION_PROLOG(PACA_EXSLB, instruction_access_slb_common, EXC_STD, KVMTEST_PR, 0x480); |
614 | EXCEPTION_PROLOG_0(PACA_EXSLB) | ||
615 | EXCEPTION_PROLOG_1(PACA_EXSLB, KVMTEST_PR, 0x480) | ||
616 | mr r12,r3 /* save r3 */ | ||
617 | mfspr r3,SPRN_SRR0 /* SRR0 is faulting address */ | ||
618 | mfspr r11,SPRN_SRR1 | ||
619 | crclr 4*cr6+eq | ||
620 | BRANCH_TO_COMMON(r10, slb_miss_common) | ||
621 | EXC_REAL_END(instruction_access_slb, 0x480, 0x80) | 652 | EXC_REAL_END(instruction_access_slb, 0x480, 0x80) |
622 | 653 | ||
623 | EXC_VIRT_BEGIN(instruction_access_slb, 0x4480, 0x80) | 654 | EXC_VIRT_BEGIN(instruction_access_slb, 0x4480, 0x80) |
624 | SET_SCRATCH0(r13) | 655 | EXCEPTION_RELON_PROLOG(PACA_EXSLB, instruction_access_slb_common, EXC_STD, NOTEST, 0x480); |
625 | EXCEPTION_PROLOG_0(PACA_EXSLB) | ||
626 | EXCEPTION_PROLOG_1(PACA_EXSLB, NOTEST, 0x480) | ||
627 | mr r12,r3 /* save r3 */ | ||
628 | mfspr r3,SPRN_SRR0 /* SRR0 is faulting address */ | ||
629 | mfspr r11,SPRN_SRR1 | ||
630 | crclr 4*cr6+eq | ||
631 | BRANCH_TO_COMMON(r10, slb_miss_common) | ||
632 | EXC_VIRT_END(instruction_access_slb, 0x4480, 0x80) | 656 | EXC_VIRT_END(instruction_access_slb, 0x4480, 0x80) |
633 | TRAMP_KVM(PACA_EXSLB, 0x480) | ||
634 | |||
635 | |||
636 | /* | ||
637 | * This handler is used by the 0x380 and 0x480 SLB miss interrupts, as well as | ||
638 | * the virtual mode 0x4380 and 0x4480 interrupts if AIL is enabled. | ||
639 | */ | ||
640 | EXC_COMMON_BEGIN(slb_miss_common) | ||
641 | /* | ||
642 | * r13 points to the PACA, r9 contains the saved CR, | ||
643 | * r12 contains the saved r3, | ||
644 | * r11 contain the saved SRR1, SRR0 is still ready for return | ||
645 | * r3 has the faulting address | ||
646 | * r9 - r13 are saved in paca->exslb. | ||
647 | * cr6.eq is set for a D-SLB miss, clear for a I-SLB miss | ||
648 | * We assume we aren't going to take any exceptions during this | ||
649 | * procedure. | ||
650 | */ | ||
651 | mflr r10 | ||
652 | stw r9,PACA_EXSLB+EX_CCR(r13) /* save CR in exc. frame */ | ||
653 | std r10,PACA_EXSLB+EX_LR(r13) /* save LR */ | ||
654 | |||
655 | andi. r9,r11,MSR_PR // Check for exception from userspace | ||
656 | cmpdi cr4,r9,MSR_PR // And save the result in CR4 for later | ||
657 | |||
658 | /* | ||
659 | * Test MSR_RI before calling slb_allocate_realmode, because the | ||
660 | * MSR in r11 gets clobbered. However we still want to allocate | ||
661 | * SLB in case MSR_RI=0, to minimise the risk of getting stuck in | ||
662 | * recursive SLB faults. So use cr5 for this, which is preserved. | ||
663 | */ | ||
664 | andi. r11,r11,MSR_RI /* check for unrecoverable exception */ | ||
665 | cmpdi cr5,r11,MSR_RI | ||
666 | |||
667 | crset 4*cr0+eq | ||
668 | #ifdef CONFIG_PPC_BOOK3S_64 | ||
669 | BEGIN_MMU_FTR_SECTION | ||
670 | bl slb_allocate | ||
671 | END_MMU_FTR_SECTION_IFCLR(MMU_FTR_TYPE_RADIX) | ||
672 | #endif | ||
673 | |||
674 | ld r10,PACA_EXSLB+EX_LR(r13) | ||
675 | lwz r9,PACA_EXSLB+EX_CCR(r13) /* get saved CR */ | ||
676 | mtlr r10 | ||
677 | |||
678 | /* | ||
679 | * Large address, check whether we have to allocate new contexts. | ||
680 | */ | ||
681 | beq- 8f | ||
682 | 657 | ||
683 | bne- cr5,2f /* if unrecoverable exception, oops */ | 658 | TRAMP_KVM(PACA_EXSLB, 0x480) |
684 | |||
685 | /* All done -- return from exception. */ | ||
686 | |||
687 | bne cr4,1f /* returning to kernel */ | ||
688 | |||
689 | mtcrf 0x80,r9 | ||
690 | mtcrf 0x08,r9 /* MSR[PR] indication is in cr4 */ | ||
691 | mtcrf 0x04,r9 /* MSR[RI] indication is in cr5 */ | ||
692 | mtcrf 0x02,r9 /* I/D indication is in cr6 */ | ||
693 | mtcrf 0x01,r9 /* slb_allocate uses cr0 and cr7 */ | ||
694 | |||
695 | RESTORE_CTR(r9, PACA_EXSLB) | ||
696 | RESTORE_PPR_PACA(PACA_EXSLB, r9) | ||
697 | mr r3,r12 | ||
698 | ld r9,PACA_EXSLB+EX_R9(r13) | ||
699 | ld r10,PACA_EXSLB+EX_R10(r13) | ||
700 | ld r11,PACA_EXSLB+EX_R11(r13) | ||
701 | ld r12,PACA_EXSLB+EX_R12(r13) | ||
702 | ld r13,PACA_EXSLB+EX_R13(r13) | ||
703 | RFI_TO_USER | ||
704 | b . /* prevent speculative execution */ | ||
705 | 1: | ||
706 | mtcrf 0x80,r9 | ||
707 | mtcrf 0x08,r9 /* MSR[PR] indication is in cr4 */ | ||
708 | mtcrf 0x04,r9 /* MSR[RI] indication is in cr5 */ | ||
709 | mtcrf 0x02,r9 /* I/D indication is in cr6 */ | ||
710 | mtcrf 0x01,r9 /* slb_allocate uses cr0 and cr7 */ | ||
711 | |||
712 | RESTORE_CTR(r9, PACA_EXSLB) | ||
713 | RESTORE_PPR_PACA(PACA_EXSLB, r9) | ||
714 | mr r3,r12 | ||
715 | ld r9,PACA_EXSLB+EX_R9(r13) | ||
716 | ld r10,PACA_EXSLB+EX_R10(r13) | ||
717 | ld r11,PACA_EXSLB+EX_R11(r13) | ||
718 | ld r12,PACA_EXSLB+EX_R12(r13) | ||
719 | ld r13,PACA_EXSLB+EX_R13(r13) | ||
720 | RFI_TO_KERNEL | ||
721 | b . /* prevent speculative execution */ | ||
722 | |||
723 | |||
724 | 2: std r3,PACA_EXSLB+EX_DAR(r13) | ||
725 | mr r3,r12 | ||
726 | mfspr r11,SPRN_SRR0 | ||
727 | mfspr r12,SPRN_SRR1 | ||
728 | LOAD_HANDLER(r10,unrecov_slb) | ||
729 | mtspr SPRN_SRR0,r10 | ||
730 | ld r10,PACAKMSR(r13) | ||
731 | mtspr SPRN_SRR1,r10 | ||
732 | RFI_TO_KERNEL | ||
733 | b . | ||
734 | |||
735 | 8: std r3,PACA_EXSLB+EX_DAR(r13) | ||
736 | mr r3,r12 | ||
737 | mfspr r11,SPRN_SRR0 | ||
738 | mfspr r12,SPRN_SRR1 | ||
739 | LOAD_HANDLER(r10, large_addr_slb) | ||
740 | mtspr SPRN_SRR0,r10 | ||
741 | ld r10,PACAKMSR(r13) | ||
742 | mtspr SPRN_SRR1,r10 | ||
743 | RFI_TO_KERNEL | ||
744 | b . | ||
745 | 659 | ||
746 | EXC_COMMON_BEGIN(unrecov_slb) | 660 | EXC_COMMON_BEGIN(instruction_access_slb_common) |
747 | EXCEPTION_PROLOG_COMMON(0x4100, PACA_EXSLB) | 661 | EXCEPTION_PROLOG_COMMON(0x480, PACA_EXSLB) |
748 | RECONCILE_IRQ_STATE(r10, r11) | 662 | ld r4,_NIP(r1) |
663 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
664 | bl do_slb_fault | ||
665 | cmpdi r3,0 | ||
666 | bne- 1f | ||
667 | b fast_exception_return | ||
668 | 1: /* Error case */ | ||
669 | std r3,RESULT(r1) | ||
749 | bl save_nvgprs | 670 | bl save_nvgprs |
750 | 1: addi r3,r1,STACK_FRAME_OVERHEAD | ||
751 | bl unrecoverable_exception | ||
752 | b 1b | ||
753 | |||
754 | EXC_COMMON_BEGIN(large_addr_slb) | ||
755 | EXCEPTION_PROLOG_COMMON(0x380, PACA_EXSLB) | ||
756 | RECONCILE_IRQ_STATE(r10, r11) | 671 | RECONCILE_IRQ_STATE(r10, r11) |
757 | ld r3, PACA_EXSLB+EX_DAR(r13) | 672 | ld r4,_NIP(r1) |
758 | std r3, _DAR(r1) | 673 | ld r5,RESULT(r1) |
759 | beq cr6, 2f | 674 | addi r3,r1,STACK_FRAME_OVERHEAD |
760 | li r10, 0x481 /* fix trap number for I-SLB miss */ | 675 | bl do_bad_slb_fault |
761 | std r10, _TRAP(r1) | ||
762 | 2: bl save_nvgprs | ||
763 | addi r3, r1, STACK_FRAME_OVERHEAD | ||
764 | bl slb_miss_large_addr | ||
765 | b ret_from_except | 676 | b ret_from_except |
766 | 677 | ||
678 | |||
767 | EXC_REAL_BEGIN(hardware_interrupt, 0x500, 0x100) | 679 | EXC_REAL_BEGIN(hardware_interrupt, 0x500, 0x100) |
768 | .globl hardware_interrupt_hv; | 680 | .globl hardware_interrupt_hv; |
769 | hardware_interrupt_hv: | 681 | hardware_interrupt_hv: |
diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c index a711d22339ea..761b28b1427d 100644 --- a/arch/powerpc/kernel/fadump.c +++ b/arch/powerpc/kernel/fadump.c | |||
@@ -1444,8 +1444,8 @@ static ssize_t fadump_register_store(struct kobject *kobj, | |||
1444 | break; | 1444 | break; |
1445 | case 1: | 1445 | case 1: |
1446 | if (fw_dump.dump_registered == 1) { | 1446 | if (fw_dump.dump_registered == 1) { |
1447 | ret = -EEXIST; | 1447 | /* Un-register Firmware-assisted dump */ |
1448 | goto unlock_out; | 1448 | fadump_unregister_dump(&fdm); |
1449 | } | 1449 | } |
1450 | /* Register Firmware-assisted dump */ | 1450 | /* Register Firmware-assisted dump */ |
1451 | ret = register_fadump(); | 1451 | ret = register_fadump(); |
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S index 6582f824d620..134a573a9f2d 100644 --- a/arch/powerpc/kernel/head_8xx.S +++ b/arch/powerpc/kernel/head_8xx.S | |||
@@ -642,7 +642,7 @@ DTLBMissIMMR: | |||
642 | mtspr SPRN_MD_TWC, r10 | 642 | mtspr SPRN_MD_TWC, r10 |
643 | mfspr r10, SPRN_IMMR /* Get current IMMR */ | 643 | mfspr r10, SPRN_IMMR /* Get current IMMR */ |
644 | rlwinm r10, r10, 0, 0xfff80000 /* Get 512 kbytes boundary */ | 644 | rlwinm r10, r10, 0, 0xfff80000 /* Get 512 kbytes boundary */ |
645 | ori r10, r10, 0xf0 | MD_SPS16K | _PAGE_PRIVILEGED | _PAGE_DIRTY | \ | 645 | ori r10, r10, 0xf0 | MD_SPS16K | _PAGE_SH | _PAGE_DIRTY | \ |
646 | _PAGE_PRESENT | _PAGE_NO_CACHE | 646 | _PAGE_PRESENT | _PAGE_NO_CACHE |
647 | mtspr SPRN_MD_RPN, r10 /* Update TLB entry */ | 647 | mtspr SPRN_MD_RPN, r10 /* Update TLB entry */ |
648 | 648 | ||
@@ -660,7 +660,7 @@ DTLBMissLinear: | |||
660 | li r11, MD_PS8MEG | MD_SVALID | M_APG2 | 660 | li r11, MD_PS8MEG | MD_SVALID | M_APG2 |
661 | mtspr SPRN_MD_TWC, r11 | 661 | mtspr SPRN_MD_TWC, r11 |
662 | rlwinm r10, r10, 0, 0x0f800000 /* 8xx supports max 256Mb RAM */ | 662 | rlwinm r10, r10, 0, 0x0f800000 /* 8xx supports max 256Mb RAM */ |
663 | ori r10, r10, 0xf0 | MD_SPS16K | _PAGE_PRIVILEGED | _PAGE_DIRTY | \ | 663 | ori r10, r10, 0xf0 | MD_SPS16K | _PAGE_SH | _PAGE_DIRTY | \ |
664 | _PAGE_PRESENT | 664 | _PAGE_PRESENT |
665 | mtspr SPRN_MD_RPN, r10 /* Update TLB entry */ | 665 | mtspr SPRN_MD_RPN, r10 /* Update TLB entry */ |
666 | 666 | ||
@@ -679,7 +679,7 @@ ITLBMissLinear: | |||
679 | li r11, MI_PS8MEG | MI_SVALID | M_APG2 | 679 | li r11, MI_PS8MEG | MI_SVALID | M_APG2 |
680 | mtspr SPRN_MI_TWC, r11 | 680 | mtspr SPRN_MI_TWC, r11 |
681 | rlwinm r10, r10, 0, 0x0f800000 /* 8xx supports max 256Mb RAM */ | 681 | rlwinm r10, r10, 0, 0x0f800000 /* 8xx supports max 256Mb RAM */ |
682 | ori r10, r10, 0xf0 | MI_SPS16K | _PAGE_PRIVILEGED | _PAGE_DIRTY | \ | 682 | ori r10, r10, 0xf0 | MI_SPS16K | _PAGE_SH | _PAGE_DIRTY | \ |
683 | _PAGE_PRESENT | 683 | _PAGE_PRESENT |
684 | mtspr SPRN_MI_RPN, r10 /* Update TLB entry */ | 684 | mtspr SPRN_MI_RPN, r10 /* Update TLB entry */ |
685 | 685 | ||
diff --git a/arch/powerpc/kernel/io-workarounds.c b/arch/powerpc/kernel/io-workarounds.c index aa9f1b8261db..7e89d02a84e1 100644 --- a/arch/powerpc/kernel/io-workarounds.c +++ b/arch/powerpc/kernel/io-workarounds.c | |||
@@ -153,10 +153,10 @@ static const struct ppc_pci_io iowa_pci_io = { | |||
153 | 153 | ||
154 | #ifdef CONFIG_PPC_INDIRECT_MMIO | 154 | #ifdef CONFIG_PPC_INDIRECT_MMIO |
155 | static void __iomem *iowa_ioremap(phys_addr_t addr, unsigned long size, | 155 | static void __iomem *iowa_ioremap(phys_addr_t addr, unsigned long size, |
156 | unsigned long flags, void *caller) | 156 | pgprot_t prot, void *caller) |
157 | { | 157 | { |
158 | struct iowa_bus *bus; | 158 | struct iowa_bus *bus; |
159 | void __iomem *res = __ioremap_caller(addr, size, flags, caller); | 159 | void __iomem *res = __ioremap_caller(addr, size, prot, caller); |
160 | int busno; | 160 | int busno; |
161 | 161 | ||
162 | bus = iowa_pci_find(0, (unsigned long)addr); | 162 | bus = iowa_pci_find(0, (unsigned long)addr); |
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index 19b4c628f3be..f0dc680e659a 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c | |||
@@ -785,9 +785,9 @@ dma_addr_t iommu_map_page(struct device *dev, struct iommu_table *tbl, | |||
785 | 785 | ||
786 | vaddr = page_address(page) + offset; | 786 | vaddr = page_address(page) + offset; |
787 | uaddr = (unsigned long)vaddr; | 787 | uaddr = (unsigned long)vaddr; |
788 | npages = iommu_num_pages(uaddr, size, IOMMU_PAGE_SIZE(tbl)); | ||
789 | 788 | ||
790 | if (tbl) { | 789 | if (tbl) { |
790 | npages = iommu_num_pages(uaddr, size, IOMMU_PAGE_SIZE(tbl)); | ||
791 | align = 0; | 791 | align = 0; |
792 | if (tbl->it_page_shift < PAGE_SHIFT && size >= PAGE_SIZE && | 792 | if (tbl->it_page_shift < PAGE_SHIFT && size >= PAGE_SIZE && |
793 | ((unsigned long)vaddr & ~PAGE_MASK) == 0) | 793 | ((unsigned long)vaddr & ~PAGE_MASK) == 0) |
diff --git a/arch/powerpc/kernel/isa-bridge.c b/arch/powerpc/kernel/isa-bridge.c index 1df6c74aa731..fda3ae48480c 100644 --- a/arch/powerpc/kernel/isa-bridge.c +++ b/arch/powerpc/kernel/isa-bridge.c | |||
@@ -110,14 +110,14 @@ static void pci_process_ISA_OF_ranges(struct device_node *isa_node, | |||
110 | size = 0x10000; | 110 | size = 0x10000; |
111 | 111 | ||
112 | __ioremap_at(phb_io_base_phys, (void *)ISA_IO_BASE, | 112 | __ioremap_at(phb_io_base_phys, (void *)ISA_IO_BASE, |
113 | size, pgprot_val(pgprot_noncached(__pgprot(0)))); | 113 | size, pgprot_noncached(PAGE_KERNEL)); |
114 | return; | 114 | return; |
115 | 115 | ||
116 | inval_range: | 116 | inval_range: |
117 | printk(KERN_ERR "no ISA IO ranges or unexpected isa range, " | 117 | printk(KERN_ERR "no ISA IO ranges or unexpected isa range, " |
118 | "mapping 64k\n"); | 118 | "mapping 64k\n"); |
119 | __ioremap_at(phb_io_base_phys, (void *)ISA_IO_BASE, | 119 | __ioremap_at(phb_io_base_phys, (void *)ISA_IO_BASE, |
120 | 0x10000, pgprot_val(pgprot_noncached(__pgprot(0)))); | 120 | 0x10000, pgprot_noncached(PAGE_KERNEL)); |
121 | } | 121 | } |
122 | 122 | ||
123 | 123 | ||
@@ -253,7 +253,7 @@ void __init isa_bridge_init_non_pci(struct device_node *np) | |||
253 | */ | 253 | */ |
254 | isa_io_base = ISA_IO_BASE; | 254 | isa_io_base = ISA_IO_BASE; |
255 | __ioremap_at(pbase, (void *)ISA_IO_BASE, | 255 | __ioremap_at(pbase, (void *)ISA_IO_BASE, |
256 | size, pgprot_val(pgprot_noncached(__pgprot(0)))); | 256 | size, pgprot_noncached(PAGE_KERNEL)); |
257 | 257 | ||
258 | pr_debug("ISA: Non-PCI bridge is %pOF\n", np); | 258 | pr_debug("ISA: Non-PCI bridge is %pOF\n", np); |
259 | } | 259 | } |
diff --git a/arch/powerpc/kernel/kgdb.c b/arch/powerpc/kernel/kgdb.c index 35e240a0a408..59c578f865aa 100644 --- a/arch/powerpc/kernel/kgdb.c +++ b/arch/powerpc/kernel/kgdb.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <asm/processor.h> | 24 | #include <asm/processor.h> |
25 | #include <asm/machdep.h> | 25 | #include <asm/machdep.h> |
26 | #include <asm/debug.h> | 26 | #include <asm/debug.h> |
27 | #include <asm/code-patching.h> | ||
27 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
28 | 29 | ||
29 | /* | 30 | /* |
@@ -144,7 +145,7 @@ static int kgdb_handle_breakpoint(struct pt_regs *regs) | |||
144 | if (kgdb_handle_exception(1, SIGTRAP, 0, regs) != 0) | 145 | if (kgdb_handle_exception(1, SIGTRAP, 0, regs) != 0) |
145 | return 0; | 146 | return 0; |
146 | 147 | ||
147 | if (*(u32 *) (regs->nip) == *(u32 *) (&arch_kgdb_ops.gdb_bpt_instr)) | 148 | if (*(u32 *)regs->nip == BREAK_INSTR) |
148 | regs->nip += BREAK_INSTR_SIZE; | 149 | regs->nip += BREAK_INSTR_SIZE; |
149 | 150 | ||
150 | return 1; | 151 | return 1; |
@@ -441,16 +442,42 @@ int kgdb_arch_handle_exception(int vector, int signo, int err_code, | |||
441 | return -1; | 442 | return -1; |
442 | } | 443 | } |
443 | 444 | ||
445 | int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt) | ||
446 | { | ||
447 | int err; | ||
448 | unsigned int instr; | ||
449 | unsigned int *addr = (unsigned int *)bpt->bpt_addr; | ||
450 | |||
451 | err = probe_kernel_address(addr, instr); | ||
452 | if (err) | ||
453 | return err; | ||
454 | |||
455 | err = patch_instruction(addr, BREAK_INSTR); | ||
456 | if (err) | ||
457 | return -EFAULT; | ||
458 | |||
459 | *(unsigned int *)bpt->saved_instr = instr; | ||
460 | |||
461 | return 0; | ||
462 | } | ||
463 | |||
464 | int kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt) | ||
465 | { | ||
466 | int err; | ||
467 | unsigned int instr = *(unsigned int *)bpt->saved_instr; | ||
468 | unsigned int *addr = (unsigned int *)bpt->bpt_addr; | ||
469 | |||
470 | err = patch_instruction(addr, instr); | ||
471 | if (err) | ||
472 | return -EFAULT; | ||
473 | |||
474 | return 0; | ||
475 | } | ||
476 | |||
444 | /* | 477 | /* |
445 | * Global data | 478 | * Global data |
446 | */ | 479 | */ |
447 | struct kgdb_arch arch_kgdb_ops = { | 480 | struct kgdb_arch arch_kgdb_ops; |
448 | #ifdef __LITTLE_ENDIAN__ | ||
449 | .gdb_bpt_instr = {0x08, 0x10, 0x82, 0x7d}, | ||
450 | #else | ||
451 | .gdb_bpt_instr = {0x7d, 0x82, 0x10, 0x08}, | ||
452 | #endif | ||
453 | }; | ||
454 | 481 | ||
455 | static int kgdb_not_implemented(struct pt_regs *regs) | 482 | static int kgdb_not_implemented(struct pt_regs *regs) |
456 | { | 483 | { |
diff --git a/arch/powerpc/kernel/mce.c b/arch/powerpc/kernel/mce.c index efdd16a79075..bd933a75f0bc 100644 --- a/arch/powerpc/kernel/mce.c +++ b/arch/powerpc/kernel/mce.c | |||
@@ -488,10 +488,11 @@ long machine_check_early(struct pt_regs *regs) | |||
488 | { | 488 | { |
489 | long handled = 0; | 489 | long handled = 0; |
490 | 490 | ||
491 | __this_cpu_inc(irq_stat.mce_exceptions); | 491 | /* |
492 | 492 | * See if platform is capable of handling machine check. | |
493 | if (cur_cpu_spec && cur_cpu_spec->machine_check_early) | 493 | */ |
494 | handled = cur_cpu_spec->machine_check_early(regs); | 494 | if (ppc_md.machine_check_early) |
495 | handled = ppc_md.machine_check_early(regs); | ||
495 | return handled; | 496 | return handled; |
496 | } | 497 | } |
497 | 498 | ||
diff --git a/arch/powerpc/kernel/mce_power.c b/arch/powerpc/kernel/mce_power.c index 3497c8329c1d..6b800eec31f2 100644 --- a/arch/powerpc/kernel/mce_power.c +++ b/arch/powerpc/kernel/mce_power.c | |||
@@ -60,7 +60,7 @@ static unsigned long addr_to_pfn(struct pt_regs *regs, unsigned long addr) | |||
60 | 60 | ||
61 | /* flush SLBs and reload */ | 61 | /* flush SLBs and reload */ |
62 | #ifdef CONFIG_PPC_BOOK3S_64 | 62 | #ifdef CONFIG_PPC_BOOK3S_64 |
63 | static void flush_and_reload_slb(void) | 63 | void flush_and_reload_slb(void) |
64 | { | 64 | { |
65 | /* Invalidate all SLBs */ | 65 | /* Invalidate all SLBs */ |
66 | slb_flush_all_realmode(); | 66 | slb_flush_all_realmode(); |
@@ -89,6 +89,13 @@ static void flush_and_reload_slb(void) | |||
89 | 89 | ||
90 | static void flush_erat(void) | 90 | static void flush_erat(void) |
91 | { | 91 | { |
92 | #ifdef CONFIG_PPC_BOOK3S_64 | ||
93 | if (!early_cpu_has_feature(CPU_FTR_ARCH_300)) { | ||
94 | flush_and_reload_slb(); | ||
95 | return; | ||
96 | } | ||
97 | #endif | ||
98 | /* PPC_INVALIDATE_ERAT can only be used on ISA v3 and newer */ | ||
92 | asm volatile(PPC_INVALIDATE_ERAT : : :"memory"); | 99 | asm volatile(PPC_INVALIDATE_ERAT : : :"memory"); |
93 | } | 100 | } |
94 | 101 | ||
diff --git a/arch/powerpc/kernel/module.c b/arch/powerpc/kernel/module.c index 77371c9ef3d8..2d861a36662e 100644 --- a/arch/powerpc/kernel/module.c +++ b/arch/powerpc/kernel/module.c | |||
@@ -74,6 +74,14 @@ int module_finalize(const Elf_Ehdr *hdr, | |||
74 | (void *)sect->sh_addr + sect->sh_size); | 74 | (void *)sect->sh_addr + sect->sh_size); |
75 | #endif /* CONFIG_PPC64 */ | 75 | #endif /* CONFIG_PPC64 */ |
76 | 76 | ||
77 | #ifdef PPC64_ELF_ABI_v1 | ||
78 | sect = find_section(hdr, sechdrs, ".opd"); | ||
79 | if (sect != NULL) { | ||
80 | me->arch.start_opd = sect->sh_addr; | ||
81 | me->arch.end_opd = sect->sh_addr + sect->sh_size; | ||
82 | } | ||
83 | #endif /* PPC64_ELF_ABI_v1 */ | ||
84 | |||
77 | #ifdef CONFIG_PPC_BARRIER_NOSPEC | 85 | #ifdef CONFIG_PPC_BARRIER_NOSPEC |
78 | sect = find_section(hdr, sechdrs, "__spec_barrier_fixup"); | 86 | sect = find_section(hdr, sechdrs, "__spec_barrier_fixup"); |
79 | if (sect != NULL) | 87 | if (sect != NULL) |
diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c index b8d61e019d06..8661eea78503 100644 --- a/arch/powerpc/kernel/module_64.c +++ b/arch/powerpc/kernel/module_64.c | |||
@@ -360,11 +360,6 @@ int module_frob_arch_sections(Elf64_Ehdr *hdr, | |||
360 | else if (strcmp(secstrings+sechdrs[i].sh_name,"__versions")==0) | 360 | else if (strcmp(secstrings+sechdrs[i].sh_name,"__versions")==0) |
361 | dedotify_versions((void *)hdr + sechdrs[i].sh_offset, | 361 | dedotify_versions((void *)hdr + sechdrs[i].sh_offset, |
362 | sechdrs[i].sh_size); | 362 | sechdrs[i].sh_size); |
363 | else if (!strcmp(secstrings + sechdrs[i].sh_name, ".opd")) { | ||
364 | me->arch.start_opd = sechdrs[i].sh_addr; | ||
365 | me->arch.end_opd = sechdrs[i].sh_addr + | ||
366 | sechdrs[i].sh_size; | ||
367 | } | ||
368 | 363 | ||
369 | /* We don't handle .init for the moment: rename to _init */ | 364 | /* We don't handle .init for the moment: rename to _init */ |
370 | while ((p = strstr(secstrings + sechdrs[i].sh_name, ".init"))) | 365 | while ((p = strstr(secstrings + sechdrs[i].sh_name, ".init"))) |
@@ -685,7 +680,14 @@ int apply_relocate_add(Elf64_Shdr *sechdrs, | |||
685 | 680 | ||
686 | case R_PPC64_REL32: | 681 | case R_PPC64_REL32: |
687 | /* 32 bits relative (used by relative exception tables) */ | 682 | /* 32 bits relative (used by relative exception tables) */ |
688 | *(u32 *)location = value - (unsigned long)location; | 683 | /* Convert value to relative */ |
684 | value -= (unsigned long)location; | ||
685 | if (value + 0x80000000 > 0xffffffff) { | ||
686 | pr_err("%s: REL32 %li out of range!\n", | ||
687 | me->name, (long int)value); | ||
688 | return -ENOEXEC; | ||
689 | } | ||
690 | *(u32 *)location = value; | ||
689 | break; | 691 | break; |
690 | 692 | ||
691 | case R_PPC64_TOCSAVE: | 693 | case R_PPC64_TOCSAVE: |
diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c index d63b488d34d7..4da8ed576229 100644 --- a/arch/powerpc/kernel/pci_32.c +++ b/arch/powerpc/kernel/pci_32.c | |||
@@ -17,7 +17,6 @@ | |||
17 | #include <linux/of.h> | 17 | #include <linux/of.h> |
18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
19 | #include <linux/export.h> | 19 | #include <linux/export.h> |
20 | #include <linux/syscalls.h> | ||
21 | 20 | ||
22 | #include <asm/processor.h> | 21 | #include <asm/processor.h> |
23 | #include <asm/io.h> | 22 | #include <asm/io.h> |
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index dff28f903512..9d8c10d55407 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c | |||
@@ -159,7 +159,7 @@ static int pcibios_map_phb_io_space(struct pci_controller *hose) | |||
159 | 159 | ||
160 | /* Establish the mapping */ | 160 | /* Establish the mapping */ |
161 | if (__ioremap_at(phys_page, area->addr, size_page, | 161 | if (__ioremap_at(phys_page, area->addr, size_page, |
162 | pgprot_val(pgprot_noncached(__pgprot(0)))) == NULL) | 162 | pgprot_noncached(PAGE_KERNEL)) == NULL) |
163 | return -ENOMEM; | 163 | return -ENOMEM; |
164 | 164 | ||
165 | /* Fixup hose IO resource */ | 165 | /* Fixup hose IO resource */ |
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 5d983d8bac27..4d5322cfad25 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c | |||
@@ -43,6 +43,7 @@ | |||
43 | #include <linux/uaccess.h> | 43 | #include <linux/uaccess.h> |
44 | #include <linux/elf-randomize.h> | 44 | #include <linux/elf-randomize.h> |
45 | #include <linux/pkeys.h> | 45 | #include <linux/pkeys.h> |
46 | #include <linux/seq_buf.h> | ||
46 | 47 | ||
47 | #include <asm/pgtable.h> | 48 | #include <asm/pgtable.h> |
48 | #include <asm/io.h> | 49 | #include <asm/io.h> |
@@ -65,6 +66,7 @@ | |||
65 | #include <asm/livepatch.h> | 66 | #include <asm/livepatch.h> |
66 | #include <asm/cpu_has_feature.h> | 67 | #include <asm/cpu_has_feature.h> |
67 | #include <asm/asm-prototypes.h> | 68 | #include <asm/asm-prototypes.h> |
69 | #include <asm/stacktrace.h> | ||
68 | 70 | ||
69 | #include <linux/kprobes.h> | 71 | #include <linux/kprobes.h> |
70 | #include <linux/kdebug.h> | 72 | #include <linux/kdebug.h> |
@@ -102,24 +104,18 @@ static void check_if_tm_restore_required(struct task_struct *tsk) | |||
102 | } | 104 | } |
103 | } | 105 | } |
104 | 106 | ||
105 | static inline bool msr_tm_active(unsigned long msr) | ||
106 | { | ||
107 | return MSR_TM_ACTIVE(msr); | ||
108 | } | ||
109 | |||
110 | static bool tm_active_with_fp(struct task_struct *tsk) | 107 | static bool tm_active_with_fp(struct task_struct *tsk) |
111 | { | 108 | { |
112 | return msr_tm_active(tsk->thread.regs->msr) && | 109 | return MSR_TM_ACTIVE(tsk->thread.regs->msr) && |
113 | (tsk->thread.ckpt_regs.msr & MSR_FP); | 110 | (tsk->thread.ckpt_regs.msr & MSR_FP); |
114 | } | 111 | } |
115 | 112 | ||
116 | static bool tm_active_with_altivec(struct task_struct *tsk) | 113 | static bool tm_active_with_altivec(struct task_struct *tsk) |
117 | { | 114 | { |
118 | return msr_tm_active(tsk->thread.regs->msr) && | 115 | return MSR_TM_ACTIVE(tsk->thread.regs->msr) && |
119 | (tsk->thread.ckpt_regs.msr & MSR_VEC); | 116 | (tsk->thread.ckpt_regs.msr & MSR_VEC); |
120 | } | 117 | } |
121 | #else | 118 | #else |
122 | static inline bool msr_tm_active(unsigned long msr) { return false; } | ||
123 | static inline void check_if_tm_restore_required(struct task_struct *tsk) { } | 119 | static inline void check_if_tm_restore_required(struct task_struct *tsk) { } |
124 | static inline bool tm_active_with_fp(struct task_struct *tsk) { return false; } | 120 | static inline bool tm_active_with_fp(struct task_struct *tsk) { return false; } |
125 | static inline bool tm_active_with_altivec(struct task_struct *tsk) { return false; } | 121 | static inline bool tm_active_with_altivec(struct task_struct *tsk) { return false; } |
@@ -247,7 +243,8 @@ void enable_kernel_fp(void) | |||
247 | * giveup as this would save to the 'live' structure not the | 243 | * giveup as this would save to the 'live' structure not the |
248 | * checkpointed structure. | 244 | * checkpointed structure. |
249 | */ | 245 | */ |
250 | if(!msr_tm_active(cpumsr) && msr_tm_active(current->thread.regs->msr)) | 246 | if (!MSR_TM_ACTIVE(cpumsr) && |
247 | MSR_TM_ACTIVE(current->thread.regs->msr)) | ||
251 | return; | 248 | return; |
252 | __giveup_fpu(current); | 249 | __giveup_fpu(current); |
253 | } | 250 | } |
@@ -311,7 +308,8 @@ void enable_kernel_altivec(void) | |||
311 | * giveup as this would save to the 'live' structure not the | 308 | * giveup as this would save to the 'live' structure not the |
312 | * checkpointed structure. | 309 | * checkpointed structure. |
313 | */ | 310 | */ |
314 | if(!msr_tm_active(cpumsr) && msr_tm_active(current->thread.regs->msr)) | 311 | if (!MSR_TM_ACTIVE(cpumsr) && |
312 | MSR_TM_ACTIVE(current->thread.regs->msr)) | ||
315 | return; | 313 | return; |
316 | __giveup_altivec(current); | 314 | __giveup_altivec(current); |
317 | } | 315 | } |
@@ -397,7 +395,8 @@ void enable_kernel_vsx(void) | |||
397 | * giveup as this would save to the 'live' structure not the | 395 | * giveup as this would save to the 'live' structure not the |
398 | * checkpointed structure. | 396 | * checkpointed structure. |
399 | */ | 397 | */ |
400 | if(!msr_tm_active(cpumsr) && msr_tm_active(current->thread.regs->msr)) | 398 | if (!MSR_TM_ACTIVE(cpumsr) && |
399 | MSR_TM_ACTIVE(current->thread.regs->msr)) | ||
401 | return; | 400 | return; |
402 | __giveup_vsx(current); | 401 | __giveup_vsx(current); |
403 | } | 402 | } |
@@ -530,7 +529,7 @@ void restore_math(struct pt_regs *regs) | |||
530 | { | 529 | { |
531 | unsigned long msr; | 530 | unsigned long msr; |
532 | 531 | ||
533 | if (!msr_tm_active(regs->msr) && | 532 | if (!MSR_TM_ACTIVE(regs->msr) && |
534 | !current->thread.load_fp && !loadvec(current->thread)) | 533 | !current->thread.load_fp && !loadvec(current->thread)) |
535 | return; | 534 | return; |
536 | 535 | ||
@@ -1252,17 +1251,16 @@ struct task_struct *__switch_to(struct task_struct *prev, | |||
1252 | return last; | 1251 | return last; |
1253 | } | 1252 | } |
1254 | 1253 | ||
1255 | static int instructions_to_print = 16; | 1254 | #define NR_INSN_TO_PRINT 16 |
1256 | 1255 | ||
1257 | static void show_instructions(struct pt_regs *regs) | 1256 | static void show_instructions(struct pt_regs *regs) |
1258 | { | 1257 | { |
1259 | int i; | 1258 | int i; |
1260 | unsigned long pc = regs->nip - (instructions_to_print * 3 / 4 * | 1259 | unsigned long pc = regs->nip - (NR_INSN_TO_PRINT * 3 / 4 * sizeof(int)); |
1261 | sizeof(int)); | ||
1262 | 1260 | ||
1263 | printk("Instruction dump:"); | 1261 | printk("Instruction dump:"); |
1264 | 1262 | ||
1265 | for (i = 0; i < instructions_to_print; i++) { | 1263 | for (i = 0; i < NR_INSN_TO_PRINT; i++) { |
1266 | int instr; | 1264 | int instr; |
1267 | 1265 | ||
1268 | if (!(i % 8)) | 1266 | if (!(i % 8)) |
@@ -1277,7 +1275,7 @@ static void show_instructions(struct pt_regs *regs) | |||
1277 | #endif | 1275 | #endif |
1278 | 1276 | ||
1279 | if (!__kernel_text_address(pc) || | 1277 | if (!__kernel_text_address(pc) || |
1280 | probe_kernel_address((unsigned int __user *)pc, instr)) { | 1278 | probe_kernel_address((const void *)pc, instr)) { |
1281 | pr_cont("XXXXXXXX "); | 1279 | pr_cont("XXXXXXXX "); |
1282 | } else { | 1280 | } else { |
1283 | if (regs->nip == pc) | 1281 | if (regs->nip == pc) |
@@ -1295,43 +1293,43 @@ static void show_instructions(struct pt_regs *regs) | |||
1295 | void show_user_instructions(struct pt_regs *regs) | 1293 | void show_user_instructions(struct pt_regs *regs) |
1296 | { | 1294 | { |
1297 | unsigned long pc; | 1295 | unsigned long pc; |
1298 | int i; | 1296 | int n = NR_INSN_TO_PRINT; |
1297 | struct seq_buf s; | ||
1298 | char buf[96]; /* enough for 8 times 9 + 2 chars */ | ||
1299 | 1299 | ||
1300 | pc = regs->nip - (instructions_to_print * 3 / 4 * sizeof(int)); | 1300 | pc = regs->nip - (NR_INSN_TO_PRINT * 3 / 4 * sizeof(int)); |
1301 | 1301 | ||
1302 | /* | 1302 | /* |
1303 | * Make sure the NIP points at userspace, not kernel text/data or | 1303 | * Make sure the NIP points at userspace, not kernel text/data or |
1304 | * elsewhere. | 1304 | * elsewhere. |
1305 | */ | 1305 | */ |
1306 | if (!__access_ok(pc, instructions_to_print * sizeof(int), USER_DS)) { | 1306 | if (!__access_ok(pc, NR_INSN_TO_PRINT * sizeof(int), USER_DS)) { |
1307 | pr_info("%s[%d]: Bad NIP, not dumping instructions.\n", | 1307 | pr_info("%s[%d]: Bad NIP, not dumping instructions.\n", |
1308 | current->comm, current->pid); | 1308 | current->comm, current->pid); |
1309 | return; | 1309 | return; |
1310 | } | 1310 | } |
1311 | 1311 | ||
1312 | pr_info("%s[%d]: code: ", current->comm, current->pid); | 1312 | seq_buf_init(&s, buf, sizeof(buf)); |
1313 | 1313 | ||
1314 | for (i = 0; i < instructions_to_print; i++) { | 1314 | while (n) { |
1315 | int instr; | 1315 | int i; |
1316 | 1316 | ||
1317 | if (!(i % 8) && (i > 0)) { | 1317 | seq_buf_clear(&s); |
1318 | pr_cont("\n"); | ||
1319 | pr_info("%s[%d]: code: ", current->comm, current->pid); | ||
1320 | } | ||
1321 | 1318 | ||
1322 | if (probe_kernel_address((unsigned int __user *)pc, instr)) { | 1319 | for (i = 0; i < 8 && n; i++, n--, pc += sizeof(int)) { |
1323 | pr_cont("XXXXXXXX "); | 1320 | int instr; |
1324 | } else { | 1321 | |
1325 | if (regs->nip == pc) | 1322 | if (probe_kernel_address((const void *)pc, instr)) { |
1326 | pr_cont("<%08x> ", instr); | 1323 | seq_buf_printf(&s, "XXXXXXXX "); |
1327 | else | 1324 | continue; |
1328 | pr_cont("%08x ", instr); | 1325 | } |
1326 | seq_buf_printf(&s, regs->nip == pc ? "<%08x> " : "%08x ", instr); | ||
1329 | } | 1327 | } |
1330 | 1328 | ||
1331 | pc += sizeof(int); | 1329 | if (!seq_buf_has_overflowed(&s)) |
1330 | pr_info("%s[%d]: code: %s\n", current->comm, | ||
1331 | current->pid, s.buffer); | ||
1332 | } | 1332 | } |
1333 | |||
1334 | pr_cont("\n"); | ||
1335 | } | 1333 | } |
1336 | 1334 | ||
1337 | struct regbit { | 1335 | struct regbit { |
@@ -1485,6 +1483,15 @@ void flush_thread(void) | |||
1485 | #endif /* CONFIG_HAVE_HW_BREAKPOINT */ | 1483 | #endif /* CONFIG_HAVE_HW_BREAKPOINT */ |
1486 | } | 1484 | } |
1487 | 1485 | ||
1486 | #ifdef CONFIG_PPC_BOOK3S_64 | ||
1487 | void arch_setup_new_exec(void) | ||
1488 | { | ||
1489 | if (radix_enabled()) | ||
1490 | return; | ||
1491 | hash__setup_new_exec(); | ||
1492 | } | ||
1493 | #endif | ||
1494 | |||
1488 | int set_thread_uses_vas(void) | 1495 | int set_thread_uses_vas(void) |
1489 | { | 1496 | { |
1490 | #ifdef CONFIG_PPC_BOOK3S_64 | 1497 | #ifdef CONFIG_PPC_BOOK3S_64 |
@@ -1705,7 +1712,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, | |||
1705 | p->thread.dscr = mfspr(SPRN_DSCR); | 1712 | p->thread.dscr = mfspr(SPRN_DSCR); |
1706 | } | 1713 | } |
1707 | if (cpu_has_feature(CPU_FTR_HAS_PPR)) | 1714 | if (cpu_has_feature(CPU_FTR_HAS_PPR)) |
1708 | p->thread.ppr = INIT_PPR; | 1715 | childregs->ppr = DEFAULT_PPR; |
1709 | 1716 | ||
1710 | p->thread.tidr = 0; | 1717 | p->thread.tidr = 0; |
1711 | #endif | 1718 | #endif |
@@ -1713,6 +1720,8 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, | |||
1713 | return 0; | 1720 | return 0; |
1714 | } | 1721 | } |
1715 | 1722 | ||
1723 | void preload_new_slb_context(unsigned long start, unsigned long sp); | ||
1724 | |||
1716 | /* | 1725 | /* |
1717 | * Set up a thread for executing a new program | 1726 | * Set up a thread for executing a new program |
1718 | */ | 1727 | */ |
@@ -1720,6 +1729,10 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp) | |||
1720 | { | 1729 | { |
1721 | #ifdef CONFIG_PPC64 | 1730 | #ifdef CONFIG_PPC64 |
1722 | unsigned long load_addr = regs->gpr[2]; /* saved by ELF_PLAT_INIT */ | 1731 | unsigned long load_addr = regs->gpr[2]; /* saved by ELF_PLAT_INIT */ |
1732 | |||
1733 | #ifdef CONFIG_PPC_BOOK3S_64 | ||
1734 | preload_new_slb_context(start, sp); | ||
1735 | #endif | ||
1723 | #endif | 1736 | #endif |
1724 | 1737 | ||
1725 | /* | 1738 | /* |
@@ -1810,6 +1823,7 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp) | |||
1810 | #ifdef CONFIG_VSX | 1823 | #ifdef CONFIG_VSX |
1811 | current->thread.used_vsr = 0; | 1824 | current->thread.used_vsr = 0; |
1812 | #endif | 1825 | #endif |
1826 | current->thread.load_slb = 0; | ||
1813 | current->thread.load_fp = 0; | 1827 | current->thread.load_fp = 0; |
1814 | memset(¤t->thread.fp_state, 0, sizeof(current->thread.fp_state)); | 1828 | memset(¤t->thread.fp_state, 0, sizeof(current->thread.fp_state)); |
1815 | current->thread.fp_save_area = NULL; | 1829 | current->thread.fp_save_area = NULL; |
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index 9b38a2e5dd35..f33ff4163a51 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c | |||
@@ -43,11 +43,13 @@ | |||
43 | #include <asm/btext.h> | 43 | #include <asm/btext.h> |
44 | #include <asm/sections.h> | 44 | #include <asm/sections.h> |
45 | #include <asm/machdep.h> | 45 | #include <asm/machdep.h> |
46 | #include <asm/opal.h> | ||
47 | #include <asm/asm-prototypes.h> | 46 | #include <asm/asm-prototypes.h> |
48 | 47 | ||
49 | #include <linux/linux_logo.h> | 48 | #include <linux/linux_logo.h> |
50 | 49 | ||
50 | /* All of prom_init bss lives here */ | ||
51 | #define __prombss __section(.bss.prominit) | ||
52 | |||
51 | /* | 53 | /* |
52 | * Eventually bump that one up | 54 | * Eventually bump that one up |
53 | */ | 55 | */ |
@@ -87,7 +89,7 @@ | |||
87 | #define OF_WORKAROUNDS 0 | 89 | #define OF_WORKAROUNDS 0 |
88 | #else | 90 | #else |
89 | #define OF_WORKAROUNDS of_workarounds | 91 | #define OF_WORKAROUNDS of_workarounds |
90 | int of_workarounds; | 92 | static int of_workarounds __prombss; |
91 | #endif | 93 | #endif |
92 | 94 | ||
93 | #define OF_WA_CLAIM 1 /* do phys/virt claim separately, then map */ | 95 | #define OF_WA_CLAIM 1 /* do phys/virt claim separately, then map */ |
@@ -148,29 +150,31 @@ extern void copy_and_flush(unsigned long dest, unsigned long src, | |||
148 | unsigned long size, unsigned long offset); | 150 | unsigned long size, unsigned long offset); |
149 | 151 | ||
150 | /* prom structure */ | 152 | /* prom structure */ |
151 | static struct prom_t __initdata prom; | 153 | static struct prom_t __prombss prom; |
152 | 154 | ||
153 | static unsigned long prom_entry __initdata; | 155 | static unsigned long __prombss prom_entry; |
154 | 156 | ||
155 | #define PROM_SCRATCH_SIZE 256 | 157 | #define PROM_SCRATCH_SIZE 256 |
156 | 158 | ||
157 | static char __initdata of_stdout_device[256]; | 159 | static char __prombss of_stdout_device[256]; |
158 | static char __initdata prom_scratch[PROM_SCRATCH_SIZE]; | 160 | static char __prombss prom_scratch[PROM_SCRATCH_SIZE]; |
159 | 161 | ||
160 | static unsigned long __initdata dt_header_start; | 162 | static unsigned long __prombss dt_header_start; |
161 | static unsigned long __initdata dt_struct_start, dt_struct_end; | 163 | static unsigned long __prombss dt_struct_start, dt_struct_end; |
162 | static unsigned long __initdata dt_string_start, dt_string_end; | 164 | static unsigned long __prombss dt_string_start, dt_string_end; |
163 | 165 | ||
164 | static unsigned long __initdata prom_initrd_start, prom_initrd_end; | 166 | static unsigned long __prombss prom_initrd_start, prom_initrd_end; |
165 | 167 | ||
166 | #ifdef CONFIG_PPC64 | 168 | #ifdef CONFIG_PPC64 |
167 | static int __initdata prom_iommu_force_on; | 169 | static int __prombss prom_iommu_force_on; |
168 | static int __initdata prom_iommu_off; | 170 | static int __prombss prom_iommu_off; |
169 | static unsigned long __initdata prom_tce_alloc_start; | 171 | static unsigned long __prombss prom_tce_alloc_start; |
170 | static unsigned long __initdata prom_tce_alloc_end; | 172 | static unsigned long __prombss prom_tce_alloc_end; |
171 | #endif | 173 | #endif |
172 | 174 | ||
173 | static bool prom_radix_disable __initdata = !IS_ENABLED(CONFIG_PPC_RADIX_MMU_DEFAULT); | 175 | #ifdef CONFIG_PPC_PSERIES |
176 | static bool __prombss prom_radix_disable; | ||
177 | #endif | ||
174 | 178 | ||
175 | struct platform_support { | 179 | struct platform_support { |
176 | bool hash_mmu; | 180 | bool hash_mmu; |
@@ -188,26 +192,25 @@ struct platform_support { | |||
188 | #define PLATFORM_LPAR 0x0001 | 192 | #define PLATFORM_LPAR 0x0001 |
189 | #define PLATFORM_POWERMAC 0x0400 | 193 | #define PLATFORM_POWERMAC 0x0400 |
190 | #define PLATFORM_GENERIC 0x0500 | 194 | #define PLATFORM_GENERIC 0x0500 |
191 | #define PLATFORM_OPAL 0x0600 | ||
192 | 195 | ||
193 | static int __initdata of_platform; | 196 | static int __prombss of_platform; |
194 | 197 | ||
195 | static char __initdata prom_cmd_line[COMMAND_LINE_SIZE]; | 198 | static char __prombss prom_cmd_line[COMMAND_LINE_SIZE]; |
196 | 199 | ||
197 | static unsigned long __initdata prom_memory_limit; | 200 | static unsigned long __prombss prom_memory_limit; |
198 | 201 | ||
199 | static unsigned long __initdata alloc_top; | 202 | static unsigned long __prombss alloc_top; |
200 | static unsigned long __initdata alloc_top_high; | 203 | static unsigned long __prombss alloc_top_high; |
201 | static unsigned long __initdata alloc_bottom; | 204 | static unsigned long __prombss alloc_bottom; |
202 | static unsigned long __initdata rmo_top; | 205 | static unsigned long __prombss rmo_top; |
203 | static unsigned long __initdata ram_top; | 206 | static unsigned long __prombss ram_top; |
204 | 207 | ||
205 | static struct mem_map_entry __initdata mem_reserve_map[MEM_RESERVE_MAP_SIZE]; | 208 | static struct mem_map_entry __prombss mem_reserve_map[MEM_RESERVE_MAP_SIZE]; |
206 | static int __initdata mem_reserve_cnt; | 209 | static int __prombss mem_reserve_cnt; |
207 | 210 | ||
208 | static cell_t __initdata regbuf[1024]; | 211 | static cell_t __prombss regbuf[1024]; |
209 | 212 | ||
210 | static bool rtas_has_query_cpu_stopped; | 213 | static bool __prombss rtas_has_query_cpu_stopped; |
211 | 214 | ||
212 | 215 | ||
213 | /* | 216 | /* |
@@ -522,8 +525,8 @@ static void add_string(char **str, const char *q) | |||
522 | 525 | ||
523 | static char *tohex(unsigned int x) | 526 | static char *tohex(unsigned int x) |
524 | { | 527 | { |
525 | static char digits[] = "0123456789abcdef"; | 528 | static const char digits[] __initconst = "0123456789abcdef"; |
526 | static char result[9]; | 529 | static char result[9] __prombss; |
527 | int i; | 530 | int i; |
528 | 531 | ||
529 | result[8] = 0; | 532 | result[8] = 0; |
@@ -664,6 +667,8 @@ static void __init early_cmdline_parse(void) | |||
664 | #endif | 667 | #endif |
665 | } | 668 | } |
666 | 669 | ||
670 | #ifdef CONFIG_PPC_PSERIES | ||
671 | prom_radix_disable = !IS_ENABLED(CONFIG_PPC_RADIX_MMU_DEFAULT); | ||
667 | opt = strstr(prom_cmd_line, "disable_radix"); | 672 | opt = strstr(prom_cmd_line, "disable_radix"); |
668 | if (opt) { | 673 | if (opt) { |
669 | opt += 13; | 674 | opt += 13; |
@@ -679,9 +684,10 @@ static void __init early_cmdline_parse(void) | |||
679 | } | 684 | } |
680 | if (prom_radix_disable) | 685 | if (prom_radix_disable) |
681 | prom_debug("Radix disabled from cmdline\n"); | 686 | prom_debug("Radix disabled from cmdline\n"); |
687 | #endif /* CONFIG_PPC_PSERIES */ | ||
682 | } | 688 | } |
683 | 689 | ||
684 | #if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV) | 690 | #ifdef CONFIG_PPC_PSERIES |
685 | /* | 691 | /* |
686 | * The architecture vector has an array of PVR mask/value pairs, | 692 | * The architecture vector has an array of PVR mask/value pairs, |
687 | * followed by # option vectors - 1, followed by the option vectors. | 693 | * followed by # option vectors - 1, followed by the option vectors. |
@@ -782,7 +788,7 @@ struct ibm_arch_vec { | |||
782 | struct option_vector6 vec6; | 788 | struct option_vector6 vec6; |
783 | } __packed; | 789 | } __packed; |
784 | 790 | ||
785 | struct ibm_arch_vec __cacheline_aligned ibm_architecture_vec = { | 791 | static const struct ibm_arch_vec ibm_architecture_vec_template __initconst = { |
786 | .pvrs = { | 792 | .pvrs = { |
787 | { | 793 | { |
788 | .mask = cpu_to_be32(0xfffe0000), /* POWER5/POWER5+ */ | 794 | .mask = cpu_to_be32(0xfffe0000), /* POWER5/POWER5+ */ |
@@ -920,9 +926,11 @@ struct ibm_arch_vec __cacheline_aligned ibm_architecture_vec = { | |||
920 | }, | 926 | }, |
921 | }; | 927 | }; |
922 | 928 | ||
929 | static struct ibm_arch_vec __prombss ibm_architecture_vec ____cacheline_aligned; | ||
930 | |||
923 | /* Old method - ELF header with PT_NOTE sections only works on BE */ | 931 | /* Old method - ELF header with PT_NOTE sections only works on BE */ |
924 | #ifdef __BIG_ENDIAN__ | 932 | #ifdef __BIG_ENDIAN__ |
925 | static struct fake_elf { | 933 | static const struct fake_elf { |
926 | Elf32_Ehdr elfhdr; | 934 | Elf32_Ehdr elfhdr; |
927 | Elf32_Phdr phdr[2]; | 935 | Elf32_Phdr phdr[2]; |
928 | struct chrpnote { | 936 | struct chrpnote { |
@@ -955,7 +963,7 @@ static struct fake_elf { | |||
955 | u32 ignore_me; | 963 | u32 ignore_me; |
956 | } rpadesc; | 964 | } rpadesc; |
957 | } rpanote; | 965 | } rpanote; |
958 | } fake_elf = { | 966 | } fake_elf __initconst = { |
959 | .elfhdr = { | 967 | .elfhdr = { |
960 | .e_ident = { 0x7f, 'E', 'L', 'F', | 968 | .e_ident = { 0x7f, 'E', 'L', 'F', |
961 | ELFCLASS32, ELFDATA2MSB, EV_CURRENT }, | 969 | ELFCLASS32, ELFDATA2MSB, EV_CURRENT }, |
@@ -1129,14 +1137,21 @@ static void __init prom_check_platform_support(void) | |||
1129 | }; | 1137 | }; |
1130 | int prop_len = prom_getproplen(prom.chosen, | 1138 | int prop_len = prom_getproplen(prom.chosen, |
1131 | "ibm,arch-vec-5-platform-support"); | 1139 | "ibm,arch-vec-5-platform-support"); |
1140 | |||
1141 | /* First copy the architecture vec template */ | ||
1142 | ibm_architecture_vec = ibm_architecture_vec_template; | ||
1143 | |||
1132 | if (prop_len > 1) { | 1144 | if (prop_len > 1) { |
1133 | int i; | 1145 | int i; |
1134 | u8 vec[prop_len]; | 1146 | u8 vec[8]; |
1135 | prom_debug("Found ibm,arch-vec-5-platform-support, len: %d\n", | 1147 | prom_debug("Found ibm,arch-vec-5-platform-support, len: %d\n", |
1136 | prop_len); | 1148 | prop_len); |
1149 | if (prop_len > sizeof(vec)) | ||
1150 | prom_printf("WARNING: ibm,arch-vec-5-platform-support longer than expected (len: %d)\n", | ||
1151 | prop_len); | ||
1137 | prom_getprop(prom.chosen, "ibm,arch-vec-5-platform-support", | 1152 | prom_getprop(prom.chosen, "ibm,arch-vec-5-platform-support", |
1138 | &vec, sizeof(vec)); | 1153 | &vec, sizeof(vec)); |
1139 | for (i = 0; i < prop_len; i += 2) { | 1154 | for (i = 0; i < sizeof(vec); i += 2) { |
1140 | prom_debug("%d: index = 0x%x val = 0x%x\n", i / 2 | 1155 | prom_debug("%d: index = 0x%x val = 0x%x\n", i / 2 |
1141 | , vec[i] | 1156 | , vec[i] |
1142 | , vec[i + 1]); | 1157 | , vec[i + 1]); |
@@ -1225,7 +1240,7 @@ static void __init prom_send_capabilities(void) | |||
1225 | } | 1240 | } |
1226 | #endif /* __BIG_ENDIAN__ */ | 1241 | #endif /* __BIG_ENDIAN__ */ |
1227 | } | 1242 | } |
1228 | #endif /* #if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV) */ | 1243 | #endif /* CONFIG_PPC_PSERIES */ |
1229 | 1244 | ||
1230 | /* | 1245 | /* |
1231 | * Memory allocation strategy... our layout is normally: | 1246 | * Memory allocation strategy... our layout is normally: |
@@ -1562,88 +1577,6 @@ static void __init prom_close_stdin(void) | |||
1562 | } | 1577 | } |
1563 | } | 1578 | } |
1564 | 1579 | ||
1565 | #ifdef CONFIG_PPC_POWERNV | ||
1566 | |||
1567 | #ifdef CONFIG_PPC_EARLY_DEBUG_OPAL | ||
1568 | static u64 __initdata prom_opal_base; | ||
1569 | static u64 __initdata prom_opal_entry; | ||
1570 | #endif | ||
1571 | |||
1572 | /* | ||
1573 | * Allocate room for and instantiate OPAL | ||
1574 | */ | ||
1575 | static void __init prom_instantiate_opal(void) | ||
1576 | { | ||
1577 | phandle opal_node; | ||
1578 | ihandle opal_inst; | ||
1579 | u64 base, entry; | ||
1580 | u64 size = 0, align = 0x10000; | ||
1581 | __be64 val64; | ||
1582 | u32 rets[2]; | ||
1583 | |||
1584 | prom_debug("prom_instantiate_opal: start...\n"); | ||
1585 | |||
1586 | opal_node = call_prom("finddevice", 1, 1, ADDR("/ibm,opal")); | ||
1587 | prom_debug("opal_node: %x\n", opal_node); | ||
1588 | if (!PHANDLE_VALID(opal_node)) | ||
1589 | return; | ||
1590 | |||
1591 | val64 = 0; | ||
1592 | prom_getprop(opal_node, "opal-runtime-size", &val64, sizeof(val64)); | ||
1593 | size = be64_to_cpu(val64); | ||
1594 | if (size == 0) | ||
1595 | return; | ||
1596 | val64 = 0; | ||
1597 | prom_getprop(opal_node, "opal-runtime-alignment", &val64,sizeof(val64)); | ||
1598 | align = be64_to_cpu(val64); | ||
1599 | |||
1600 | base = alloc_down(size, align, 0); | ||
1601 | if (base == 0) { | ||
1602 | prom_printf("OPAL allocation failed !\n"); | ||
1603 | return; | ||
1604 | } | ||
1605 | |||
1606 | opal_inst = call_prom("open", 1, 1, ADDR("/ibm,opal")); | ||
1607 | if (!IHANDLE_VALID(opal_inst)) { | ||
1608 | prom_printf("opening opal package failed (%x)\n", opal_inst); | ||
1609 | return; | ||
1610 | } | ||
1611 | |||
1612 | prom_printf("instantiating opal at 0x%llx...", base); | ||
1613 | |||
1614 | if (call_prom_ret("call-method", 4, 3, rets, | ||
1615 | ADDR("load-opal-runtime"), | ||
1616 | opal_inst, | ||
1617 | base >> 32, base & 0xffffffff) != 0 | ||
1618 | || (rets[0] == 0 && rets[1] == 0)) { | ||
1619 | prom_printf(" failed\n"); | ||
1620 | return; | ||
1621 | } | ||
1622 | entry = (((u64)rets[0]) << 32) | rets[1]; | ||
1623 | |||
1624 | prom_printf(" done\n"); | ||
1625 | |||
1626 | reserve_mem(base, size); | ||
1627 | |||
1628 | prom_debug("opal base = 0x%llx\n", base); | ||
1629 | prom_debug("opal align = 0x%llx\n", align); | ||
1630 | prom_debug("opal entry = 0x%llx\n", entry); | ||
1631 | prom_debug("opal size = 0x%llx\n", size); | ||
1632 | |||
1633 | prom_setprop(opal_node, "/ibm,opal", "opal-base-address", | ||
1634 | &base, sizeof(base)); | ||
1635 | prom_setprop(opal_node, "/ibm,opal", "opal-entry-address", | ||
1636 | &entry, sizeof(entry)); | ||
1637 | |||
1638 | #ifdef CONFIG_PPC_EARLY_DEBUG_OPAL | ||
1639 | prom_opal_base = base; | ||
1640 | prom_opal_entry = entry; | ||
1641 | #endif | ||
1642 | prom_debug("prom_instantiate_opal: end...\n"); | ||
1643 | } | ||
1644 | |||
1645 | #endif /* CONFIG_PPC_POWERNV */ | ||
1646 | |||
1647 | /* | 1580 | /* |
1648 | * Allocate room for and instantiate RTAS | 1581 | * Allocate room for and instantiate RTAS |
1649 | */ | 1582 | */ |
@@ -2150,10 +2083,6 @@ static int __init prom_find_machine_type(void) | |||
2150 | } | 2083 | } |
2151 | } | 2084 | } |
2152 | #ifdef CONFIG_PPC64 | 2085 | #ifdef CONFIG_PPC64 |
2153 | /* Try to detect OPAL */ | ||
2154 | if (PHANDLE_VALID(call_prom("finddevice", 1, 1, ADDR("/ibm,opal")))) | ||
2155 | return PLATFORM_OPAL; | ||
2156 | |||
2157 | /* Try to figure out if it's an IBM pSeries or any other | 2086 | /* Try to figure out if it's an IBM pSeries or any other |
2158 | * PAPR compliant platform. We assume it is if : | 2087 | * PAPR compliant platform. We assume it is if : |
2159 | * - /device_type is "chrp" (please, do NOT use that for future | 2088 | * - /device_type is "chrp" (please, do NOT use that for future |
@@ -2202,7 +2131,7 @@ static void __init prom_check_displays(void) | |||
2202 | ihandle ih; | 2131 | ihandle ih; |
2203 | int i; | 2132 | int i; |
2204 | 2133 | ||
2205 | static unsigned char default_colors[] = { | 2134 | static const unsigned char default_colors[] __initconst = { |
2206 | 0x00, 0x00, 0x00, | 2135 | 0x00, 0x00, 0x00, |
2207 | 0x00, 0x00, 0xaa, | 2136 | 0x00, 0x00, 0xaa, |
2208 | 0x00, 0xaa, 0x00, | 2137 | 0x00, 0xaa, 0x00, |
@@ -2398,7 +2327,7 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start, | |||
2398 | char *namep, *prev_name, *sstart, *p, *ep, *lp, *path; | 2327 | char *namep, *prev_name, *sstart, *p, *ep, *lp, *path; |
2399 | unsigned long soff; | 2328 | unsigned long soff; |
2400 | unsigned char *valp; | 2329 | unsigned char *valp; |
2401 | static char pname[MAX_PROPERTY_NAME]; | 2330 | static char pname[MAX_PROPERTY_NAME] __prombss; |
2402 | int l, room, has_phandle = 0; | 2331 | int l, room, has_phandle = 0; |
2403 | 2332 | ||
2404 | dt_push_token(OF_DT_BEGIN_NODE, mem_start, mem_end); | 2333 | dt_push_token(OF_DT_BEGIN_NODE, mem_start, mem_end); |
@@ -2481,14 +2410,11 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start, | |||
2481 | has_phandle = 1; | 2410 | has_phandle = 1; |
2482 | } | 2411 | } |
2483 | 2412 | ||
2484 | /* Add a "linux,phandle" property if no "phandle" property already | 2413 | /* Add a "phandle" property if none already exist */ |
2485 | * existed (can happen with OPAL) | ||
2486 | */ | ||
2487 | if (!has_phandle) { | 2414 | if (!has_phandle) { |
2488 | soff = dt_find_string("linux,phandle"); | 2415 | soff = dt_find_string("phandle"); |
2489 | if (soff == 0) | 2416 | if (soff == 0) |
2490 | prom_printf("WARNING: Can't find string index for" | 2417 | prom_printf("WARNING: Can't find string index for <phandle> node %s\n", path); |
2491 | " <linux-phandle> node %s\n", path); | ||
2492 | else { | 2418 | else { |
2493 | dt_push_token(OF_DT_PROP, mem_start, mem_end); | 2419 | dt_push_token(OF_DT_PROP, mem_start, mem_end); |
2494 | dt_push_token(4, mem_start, mem_end); | 2420 | dt_push_token(4, mem_start, mem_end); |
@@ -2548,9 +2474,9 @@ static void __init flatten_device_tree(void) | |||
2548 | dt_string_start = mem_start; | 2474 | dt_string_start = mem_start; |
2549 | mem_start += 4; /* hole */ | 2475 | mem_start += 4; /* hole */ |
2550 | 2476 | ||
2551 | /* Add "linux,phandle" in there, we'll need it */ | 2477 | /* Add "phandle" in there, we'll need it */ |
2552 | namep = make_room(&mem_start, &mem_end, 16, 1); | 2478 | namep = make_room(&mem_start, &mem_end, 16, 1); |
2553 | strcpy(namep, "linux,phandle"); | 2479 | strcpy(namep, "phandle"); |
2554 | mem_start = (unsigned long)namep + strlen(namep) + 1; | 2480 | mem_start = (unsigned long)namep + strlen(namep) + 1; |
2555 | 2481 | ||
2556 | /* Build string array */ | 2482 | /* Build string array */ |
@@ -3172,7 +3098,7 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, | |||
3172 | */ | 3098 | */ |
3173 | early_cmdline_parse(); | 3099 | early_cmdline_parse(); |
3174 | 3100 | ||
3175 | #if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV) | 3101 | #ifdef CONFIG_PPC_PSERIES |
3176 | /* | 3102 | /* |
3177 | * On pSeries, inform the firmware about our capabilities | 3103 | * On pSeries, inform the firmware about our capabilities |
3178 | */ | 3104 | */ |
@@ -3216,15 +3142,9 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, | |||
3216 | * On non-powermacs, try to instantiate RTAS. PowerMacs don't | 3142 | * On non-powermacs, try to instantiate RTAS. PowerMacs don't |
3217 | * have a usable RTAS implementation. | 3143 | * have a usable RTAS implementation. |
3218 | */ | 3144 | */ |
3219 | if (of_platform != PLATFORM_POWERMAC && | 3145 | if (of_platform != PLATFORM_POWERMAC) |
3220 | of_platform != PLATFORM_OPAL) | ||
3221 | prom_instantiate_rtas(); | 3146 | prom_instantiate_rtas(); |
3222 | 3147 | ||
3223 | #ifdef CONFIG_PPC_POWERNV | ||
3224 | if (of_platform == PLATFORM_OPAL) | ||
3225 | prom_instantiate_opal(); | ||
3226 | #endif /* CONFIG_PPC_POWERNV */ | ||
3227 | |||
3228 | #ifdef CONFIG_PPC64 | 3148 | #ifdef CONFIG_PPC64 |
3229 | /* instantiate sml */ | 3149 | /* instantiate sml */ |
3230 | prom_instantiate_sml(); | 3150 | prom_instantiate_sml(); |
@@ -3237,8 +3157,7 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, | |||
3237 | * | 3157 | * |
3238 | * (This must be done after instanciating RTAS) | 3158 | * (This must be done after instanciating RTAS) |
3239 | */ | 3159 | */ |
3240 | if (of_platform != PLATFORM_POWERMAC && | 3160 | if (of_platform != PLATFORM_POWERMAC) |
3241 | of_platform != PLATFORM_OPAL) | ||
3242 | prom_hold_cpus(); | 3161 | prom_hold_cpus(); |
3243 | 3162 | ||
3244 | /* | 3163 | /* |
@@ -3282,11 +3201,9 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, | |||
3282 | /* | 3201 | /* |
3283 | * in case stdin is USB and still active on IBM machines... | 3202 | * in case stdin is USB and still active on IBM machines... |
3284 | * Unfortunately quiesce crashes on some powermacs if we have | 3203 | * Unfortunately quiesce crashes on some powermacs if we have |
3285 | * closed stdin already (in particular the powerbook 101). It | 3204 | * closed stdin already (in particular the powerbook 101). |
3286 | * appears that the OPAL version of OFW doesn't like it either. | ||
3287 | */ | 3205 | */ |
3288 | if (of_platform != PLATFORM_POWERMAC && | 3206 | if (of_platform != PLATFORM_POWERMAC) |
3289 | of_platform != PLATFORM_OPAL) | ||
3290 | prom_close_stdin(); | 3207 | prom_close_stdin(); |
3291 | 3208 | ||
3292 | /* | 3209 | /* |
@@ -3304,10 +3221,8 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, | |||
3304 | hdr = dt_header_start; | 3221 | hdr = dt_header_start; |
3305 | 3222 | ||
3306 | /* Don't print anything after quiesce under OPAL, it crashes OFW */ | 3223 | /* Don't print anything after quiesce under OPAL, it crashes OFW */ |
3307 | if (of_platform != PLATFORM_OPAL) { | 3224 | prom_printf("Booting Linux via __start() @ 0x%lx ...\n", kbase); |
3308 | prom_printf("Booting Linux via __start() @ 0x%lx ...\n", kbase); | 3225 | prom_debug("->dt_header_start=0x%lx\n", hdr); |
3309 | prom_debug("->dt_header_start=0x%lx\n", hdr); | ||
3310 | } | ||
3311 | 3226 | ||
3312 | #ifdef CONFIG_PPC32 | 3227 | #ifdef CONFIG_PPC32 |
3313 | reloc_got2(-offset); | 3228 | reloc_got2(-offset); |
@@ -3315,13 +3230,7 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, | |||
3315 | unreloc_toc(); | 3230 | unreloc_toc(); |
3316 | #endif | 3231 | #endif |
3317 | 3232 | ||
3318 | #ifdef CONFIG_PPC_EARLY_DEBUG_OPAL | ||
3319 | /* OPAL early debug gets the OPAL base & entry in r8 and r9 */ | ||
3320 | __start(hdr, kbase, 0, 0, 0, | ||
3321 | prom_opal_base, prom_opal_entry); | ||
3322 | #else | ||
3323 | __start(hdr, kbase, 0, 0, 0, 0, 0); | 3233 | __start(hdr, kbase, 0, 0, 0, 0, 0); |
3324 | #endif | ||
3325 | 3234 | ||
3326 | return 0; | 3235 | return 0; |
3327 | } | 3236 | } |
diff --git a/arch/powerpc/kernel/prom_init_check.sh b/arch/powerpc/kernel/prom_init_check.sh index acb6b9226352..667df97d2595 100644 --- a/arch/powerpc/kernel/prom_init_check.sh +++ b/arch/powerpc/kernel/prom_init_check.sh | |||
@@ -28,6 +28,18 @@ OBJ="$2" | |||
28 | 28 | ||
29 | ERROR=0 | 29 | ERROR=0 |
30 | 30 | ||
31 | function check_section() | ||
32 | { | ||
33 | file=$1 | ||
34 | section=$2 | ||
35 | size=$(objdump -h -j $section $file 2>/dev/null | awk "\$2 == \"$section\" {print \$3}") | ||
36 | size=${size:-0} | ||
37 | if [ $size -ne 0 ]; then | ||
38 | ERROR=1 | ||
39 | echo "Error: Section $section not empty in prom_init.c" >&2 | ||
40 | fi | ||
41 | } | ||
42 | |||
31 | for UNDEF in $($NM -u $OBJ | awk '{print $2}') | 43 | for UNDEF in $($NM -u $OBJ | awk '{print $2}') |
32 | do | 44 | do |
33 | # On 64-bit nm gives us the function descriptors, which have | 45 | # On 64-bit nm gives us the function descriptors, which have |
@@ -66,4 +78,8 @@ do | |||
66 | fi | 78 | fi |
67 | done | 79 | done |
68 | 80 | ||
81 | check_section $OBJ .data | ||
82 | check_section $OBJ .bss | ||
83 | check_section $OBJ .init.data | ||
84 | |||
69 | exit $ERROR | 85 | exit $ERROR |
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index 9667666eb18e..afb819f4ca68 100644 --- a/arch/powerpc/kernel/ptrace.c +++ b/arch/powerpc/kernel/ptrace.c | |||
@@ -297,7 +297,7 @@ int ptrace_get_reg(struct task_struct *task, int regno, unsigned long *data) | |||
297 | } | 297 | } |
298 | #endif | 298 | #endif |
299 | 299 | ||
300 | if (regno < (sizeof(struct pt_regs) / sizeof(unsigned long))) { | 300 | if (regno < (sizeof(struct user_pt_regs) / sizeof(unsigned long))) { |
301 | *data = ((unsigned long *)task->thread.regs)[regno]; | 301 | *data = ((unsigned long *)task->thread.regs)[regno]; |
302 | return 0; | 302 | return 0; |
303 | } | 303 | } |
@@ -360,10 +360,10 @@ static int gpr_get(struct task_struct *target, const struct user_regset *regset, | |||
360 | ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, | 360 | ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, |
361 | &target->thread.regs->orig_gpr3, | 361 | &target->thread.regs->orig_gpr3, |
362 | offsetof(struct pt_regs, orig_gpr3), | 362 | offsetof(struct pt_regs, orig_gpr3), |
363 | sizeof(struct pt_regs)); | 363 | sizeof(struct user_pt_regs)); |
364 | if (!ret) | 364 | if (!ret) |
365 | ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, | 365 | ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, |
366 | sizeof(struct pt_regs), -1); | 366 | sizeof(struct user_pt_regs), -1); |
367 | 367 | ||
368 | return ret; | 368 | return ret; |
369 | } | 369 | } |
@@ -853,10 +853,10 @@ static int tm_cgpr_get(struct task_struct *target, | |||
853 | ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, | 853 | ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, |
854 | &target->thread.ckpt_regs.orig_gpr3, | 854 | &target->thread.ckpt_regs.orig_gpr3, |
855 | offsetof(struct pt_regs, orig_gpr3), | 855 | offsetof(struct pt_regs, orig_gpr3), |
856 | sizeof(struct pt_regs)); | 856 | sizeof(struct user_pt_regs)); |
857 | if (!ret) | 857 | if (!ret) |
858 | ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, | 858 | ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, |
859 | sizeof(struct pt_regs), -1); | 859 | sizeof(struct user_pt_regs), -1); |
860 | 860 | ||
861 | return ret; | 861 | return ret; |
862 | } | 862 | } |
@@ -1609,7 +1609,7 @@ static int ppr_get(struct task_struct *target, | |||
1609 | void *kbuf, void __user *ubuf) | 1609 | void *kbuf, void __user *ubuf) |
1610 | { | 1610 | { |
1611 | return user_regset_copyout(&pos, &count, &kbuf, &ubuf, | 1611 | return user_regset_copyout(&pos, &count, &kbuf, &ubuf, |
1612 | &target->thread.ppr, 0, sizeof(u64)); | 1612 | &target->thread.regs->ppr, 0, sizeof(u64)); |
1613 | } | 1613 | } |
1614 | 1614 | ||
1615 | static int ppr_set(struct task_struct *target, | 1615 | static int ppr_set(struct task_struct *target, |
@@ -1618,7 +1618,7 @@ static int ppr_set(struct task_struct *target, | |||
1618 | const void *kbuf, const void __user *ubuf) | 1618 | const void *kbuf, const void __user *ubuf) |
1619 | { | 1619 | { |
1620 | return user_regset_copyin(&pos, &count, &kbuf, &ubuf, | 1620 | return user_regset_copyin(&pos, &count, &kbuf, &ubuf, |
1621 | &target->thread.ppr, 0, sizeof(u64)); | 1621 | &target->thread.regs->ppr, 0, sizeof(u64)); |
1622 | } | 1622 | } |
1623 | 1623 | ||
1624 | static int dscr_get(struct task_struct *target, | 1624 | static int dscr_get(struct task_struct *target, |
@@ -2508,6 +2508,7 @@ void ptrace_disable(struct task_struct *child) | |||
2508 | { | 2508 | { |
2509 | /* make sure the single step bit is not set. */ | 2509 | /* make sure the single step bit is not set. */ |
2510 | user_disable_single_step(child); | 2510 | user_disable_single_step(child); |
2511 | clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); | ||
2511 | } | 2512 | } |
2512 | 2513 | ||
2513 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS | 2514 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS |
@@ -3130,7 +3131,7 @@ long arch_ptrace(struct task_struct *child, long request, | |||
3130 | case PTRACE_GETREGS: /* Get all pt_regs from the child. */ | 3131 | case PTRACE_GETREGS: /* Get all pt_regs from the child. */ |
3131 | return copy_regset_to_user(child, &user_ppc_native_view, | 3132 | return copy_regset_to_user(child, &user_ppc_native_view, |
3132 | REGSET_GPR, | 3133 | REGSET_GPR, |
3133 | 0, sizeof(struct pt_regs), | 3134 | 0, sizeof(struct user_pt_regs), |
3134 | datavp); | 3135 | datavp); |
3135 | 3136 | ||
3136 | #ifdef CONFIG_PPC64 | 3137 | #ifdef CONFIG_PPC64 |
@@ -3139,7 +3140,7 @@ long arch_ptrace(struct task_struct *child, long request, | |||
3139 | case PTRACE_SETREGS: /* Set all gp regs in the child. */ | 3140 | case PTRACE_SETREGS: /* Set all gp regs in the child. */ |
3140 | return copy_regset_from_user(child, &user_ppc_native_view, | 3141 | return copy_regset_from_user(child, &user_ppc_native_view, |
3141 | REGSET_GPR, | 3142 | REGSET_GPR, |
3142 | 0, sizeof(struct pt_regs), | 3143 | 0, sizeof(struct user_pt_regs), |
3143 | datavp); | 3144 | datavp); |
3144 | 3145 | ||
3145 | case PTRACE_GETFPREGS: /* Get the child FPU state (FPR0...31 + FPSCR) */ | 3146 | case PTRACE_GETFPREGS: /* Get the child FPU state (FPR0...31 + FPSCR) */ |
@@ -3264,6 +3265,16 @@ long do_syscall_trace_enter(struct pt_regs *regs) | |||
3264 | { | 3265 | { |
3265 | user_exit(); | 3266 | user_exit(); |
3266 | 3267 | ||
3268 | if (test_thread_flag(TIF_SYSCALL_EMU)) { | ||
3269 | ptrace_report_syscall(regs); | ||
3270 | /* | ||
3271 | * Returning -1 will skip the syscall execution. We want to | ||
3272 | * avoid clobbering any register also, thus, not 'gotoing' | ||
3273 | * skip label. | ||
3274 | */ | ||
3275 | return -1; | ||
3276 | } | ||
3277 | |||
3267 | /* | 3278 | /* |
3268 | * The tracer may decide to abort the syscall, if so tracehook | 3279 | * The tracer may decide to abort the syscall, if so tracehook |
3269 | * will return !0. Note that the tracer may also just change | 3280 | * will return !0. Note that the tracer may also just change |
@@ -3324,3 +3335,42 @@ void do_syscall_trace_leave(struct pt_regs *regs) | |||
3324 | 3335 | ||
3325 | user_enter(); | 3336 | user_enter(); |
3326 | } | 3337 | } |
3338 | |||
3339 | void __init pt_regs_check(void) | ||
3340 | { | ||
3341 | BUILD_BUG_ON(offsetof(struct pt_regs, gpr) != | ||
3342 | offsetof(struct user_pt_regs, gpr)); | ||
3343 | BUILD_BUG_ON(offsetof(struct pt_regs, nip) != | ||
3344 | offsetof(struct user_pt_regs, nip)); | ||
3345 | BUILD_BUG_ON(offsetof(struct pt_regs, msr) != | ||
3346 | offsetof(struct user_pt_regs, msr)); | ||
3347 | BUILD_BUG_ON(offsetof(struct pt_regs, msr) != | ||
3348 | offsetof(struct user_pt_regs, msr)); | ||
3349 | BUILD_BUG_ON(offsetof(struct pt_regs, orig_gpr3) != | ||
3350 | offsetof(struct user_pt_regs, orig_gpr3)); | ||
3351 | BUILD_BUG_ON(offsetof(struct pt_regs, ctr) != | ||
3352 | offsetof(struct user_pt_regs, ctr)); | ||
3353 | BUILD_BUG_ON(offsetof(struct pt_regs, link) != | ||
3354 | offsetof(struct user_pt_regs, link)); | ||
3355 | BUILD_BUG_ON(offsetof(struct pt_regs, xer) != | ||
3356 | offsetof(struct user_pt_regs, xer)); | ||
3357 | BUILD_BUG_ON(offsetof(struct pt_regs, ccr) != | ||
3358 | offsetof(struct user_pt_regs, ccr)); | ||
3359 | #ifdef __powerpc64__ | ||
3360 | BUILD_BUG_ON(offsetof(struct pt_regs, softe) != | ||
3361 | offsetof(struct user_pt_regs, softe)); | ||
3362 | #else | ||
3363 | BUILD_BUG_ON(offsetof(struct pt_regs, mq) != | ||
3364 | offsetof(struct user_pt_regs, mq)); | ||
3365 | #endif | ||
3366 | BUILD_BUG_ON(offsetof(struct pt_regs, trap) != | ||
3367 | offsetof(struct user_pt_regs, trap)); | ||
3368 | BUILD_BUG_ON(offsetof(struct pt_regs, dar) != | ||
3369 | offsetof(struct user_pt_regs, dar)); | ||
3370 | BUILD_BUG_ON(offsetof(struct pt_regs, dsisr) != | ||
3371 | offsetof(struct user_pt_regs, dsisr)); | ||
3372 | BUILD_BUG_ON(offsetof(struct pt_regs, result) != | ||
3373 | offsetof(struct user_pt_regs, result)); | ||
3374 | |||
3375 | BUILD_BUG_ON(sizeof(struct user_pt_regs) > sizeof(struct pt_regs)); | ||
3376 | } | ||
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 8afd146bc9c7..de35bd8f047f 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c | |||
@@ -981,7 +981,15 @@ int rtas_ibm_suspend_me(u64 handle) | |||
981 | goto out; | 981 | goto out; |
982 | } | 982 | } |
983 | 983 | ||
984 | stop_topology_update(); | 984 | cpu_hotplug_disable(); |
985 | |||
986 | /* Check if we raced with a CPU-Offline Operation */ | ||
987 | if (unlikely(!cpumask_equal(cpu_present_mask, cpu_online_mask))) { | ||
988 | pr_err("%s: Raced against a concurrent CPU-Offline\n", | ||
989 | __func__); | ||
990 | atomic_set(&data.error, -EBUSY); | ||
991 | goto out_hotplug_enable; | ||
992 | } | ||
985 | 993 | ||
986 | /* Call function on all CPUs. One of us will make the | 994 | /* Call function on all CPUs. One of us will make the |
987 | * rtas call | 995 | * rtas call |
@@ -994,7 +1002,8 @@ int rtas_ibm_suspend_me(u64 handle) | |||
994 | if (atomic_read(&data.error) != 0) | 1002 | if (atomic_read(&data.error) != 0) |
995 | printk(KERN_ERR "Error doing global join\n"); | 1003 | printk(KERN_ERR "Error doing global join\n"); |
996 | 1004 | ||
997 | start_topology_update(); | 1005 | out_hotplug_enable: |
1006 | cpu_hotplug_enable(); | ||
998 | 1007 | ||
999 | /* Take down CPUs not online prior to suspend */ | 1008 | /* Take down CPUs not online prior to suspend */ |
1000 | cpuret = rtas_offline_cpus_mask(offline_mask); | 1009 | cpuret = rtas_offline_cpus_mask(offline_mask); |
diff --git a/arch/powerpc/kernel/rtasd.c b/arch/powerpc/kernel/rtasd.c index 44d66c33d59d..38cadae4ca4f 100644 --- a/arch/powerpc/kernel/rtasd.c +++ b/arch/powerpc/kernel/rtasd.c | |||
@@ -91,6 +91,8 @@ static char *rtas_event_type(int type) | |||
91 | return "Dump Notification Event"; | 91 | return "Dump Notification Event"; |
92 | case RTAS_TYPE_PRRN: | 92 | case RTAS_TYPE_PRRN: |
93 | return "Platform Resource Reassignment Event"; | 93 | return "Platform Resource Reassignment Event"; |
94 | case RTAS_TYPE_HOTPLUG: | ||
95 | return "Hotplug Event"; | ||
94 | } | 96 | } |
95 | 97 | ||
96 | return rtas_type[0]; | 98 | return rtas_type[0]; |
@@ -150,8 +152,10 @@ static void printk_log_rtas(char *buf, int len) | |||
150 | } else { | 152 | } else { |
151 | struct rtas_error_log *errlog = (struct rtas_error_log *)buf; | 153 | struct rtas_error_log *errlog = (struct rtas_error_log *)buf; |
152 | 154 | ||
153 | printk(RTAS_DEBUG "event: %d, Type: %s, Severity: %d\n", | 155 | printk(RTAS_DEBUG "event: %d, Type: %s (%d), Severity: %d\n", |
154 | error_log_cnt, rtas_event_type(rtas_error_type(errlog)), | 156 | error_log_cnt, |
157 | rtas_event_type(rtas_error_type(errlog)), | ||
158 | rtas_error_type(errlog), | ||
155 | rtas_error_severity(errlog)); | 159 | rtas_error_severity(errlog)); |
156 | } | 160 | } |
157 | } | 161 | } |
@@ -274,27 +278,16 @@ void pSeries_log_error(char *buf, unsigned int err_type, int fatal) | |||
274 | } | 278 | } |
275 | 279 | ||
276 | #ifdef CONFIG_PPC_PSERIES | 280 | #ifdef CONFIG_PPC_PSERIES |
277 | static s32 prrn_update_scope; | 281 | static void handle_prrn_event(s32 scope) |
278 | |||
279 | static void prrn_work_fn(struct work_struct *work) | ||
280 | { | 282 | { |
281 | /* | 283 | /* |
282 | * For PRRN, we must pass the negative of the scope value in | 284 | * For PRRN, we must pass the negative of the scope value in |
283 | * the RTAS event. | 285 | * the RTAS event. |
284 | */ | 286 | */ |
285 | pseries_devicetree_update(-prrn_update_scope); | 287 | pseries_devicetree_update(-scope); |
286 | numa_update_cpu_topology(false); | 288 | numa_update_cpu_topology(false); |
287 | } | 289 | } |
288 | 290 | ||
289 | static DECLARE_WORK(prrn_work, prrn_work_fn); | ||
290 | |||
291 | static void prrn_schedule_update(u32 scope) | ||
292 | { | ||
293 | flush_work(&prrn_work); | ||
294 | prrn_update_scope = scope; | ||
295 | schedule_work(&prrn_work); | ||
296 | } | ||
297 | |||
298 | static void handle_rtas_event(const struct rtas_error_log *log) | 291 | static void handle_rtas_event(const struct rtas_error_log *log) |
299 | { | 292 | { |
300 | if (rtas_error_type(log) != RTAS_TYPE_PRRN || !prrn_is_enabled()) | 293 | if (rtas_error_type(log) != RTAS_TYPE_PRRN || !prrn_is_enabled()) |
@@ -303,7 +296,7 @@ static void handle_rtas_event(const struct rtas_error_log *log) | |||
303 | /* For PRRN Events the extended log length is used to denote | 296 | /* For PRRN Events the extended log length is used to denote |
304 | * the scope for calling rtas update-nodes. | 297 | * the scope for calling rtas update-nodes. |
305 | */ | 298 | */ |
306 | prrn_schedule_update(rtas_error_extended_log_length(log)); | 299 | handle_prrn_event(rtas_error_extended_log_length(log)); |
307 | } | 300 | } |
308 | 301 | ||
309 | #else | 302 | #else |
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index 93fa0c99681e..9ca9db707bcb 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/serial_8250.h> | 33 | #include <linux/serial_8250.h> |
34 | #include <linux/percpu.h> | 34 | #include <linux/percpu.h> |
35 | #include <linux/memblock.h> | 35 | #include <linux/memblock.h> |
36 | #include <linux/bootmem.h> | ||
36 | #include <linux/of_platform.h> | 37 | #include <linux/of_platform.h> |
37 | #include <linux/hugetlb.h> | 38 | #include <linux/hugetlb.h> |
38 | #include <asm/debugfs.h> | 39 | #include <asm/debugfs.h> |
@@ -966,6 +967,8 @@ void __init setup_arch(char **cmdline_p) | |||
966 | 967 | ||
967 | initmem_init(); | 968 | initmem_init(); |
968 | 969 | ||
970 | early_memtest(min_low_pfn << PAGE_SHIFT, max_low_pfn << PAGE_SHIFT); | ||
971 | |||
969 | #ifdef CONFIG_DUMMY_CONSOLE | 972 | #ifdef CONFIG_DUMMY_CONSOLE |
970 | conswitchp = &dummy_con; | 973 | conswitchp = &dummy_con; |
971 | #endif | 974 | #endif |
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 6a501b25dd85..faf00222b324 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c | |||
@@ -243,13 +243,19 @@ static void cpu_ready_for_interrupts(void) | |||
243 | } | 243 | } |
244 | 244 | ||
245 | /* | 245 | /* |
246 | * Fixup HFSCR:TM based on CPU features. The bit is set by our | 246 | * Set HFSCR:TM based on CPU features: |
247 | * early asm init because at that point we haven't updated our | 247 | * In the special case of TM no suspend (P9N DD2.1), Linux is |
248 | * CPU features from firmware and device-tree. Here we have, | 248 | * told TM is off via the dt-ftrs but told to (partially) use |
249 | * so let's do it. | 249 | * it via OPAL_REINIT_CPUS_TM_SUSPEND_DISABLED. So HFSCR[TM] |
250 | * will be off from dt-ftrs but we need to turn it on for the | ||
251 | * no suspend case. | ||
250 | */ | 252 | */ |
251 | if (cpu_has_feature(CPU_FTR_HVMODE) && !cpu_has_feature(CPU_FTR_TM_COMP)) | 253 | if (cpu_has_feature(CPU_FTR_HVMODE)) { |
252 | mtspr(SPRN_HFSCR, mfspr(SPRN_HFSCR) & ~HFSCR_TM); | 254 | if (cpu_has_feature(CPU_FTR_TM_COMP)) |
255 | mtspr(SPRN_HFSCR, mfspr(SPRN_HFSCR) | HFSCR_TM); | ||
256 | else | ||
257 | mtspr(SPRN_HFSCR, mfspr(SPRN_HFSCR) & ~HFSCR_TM); | ||
258 | } | ||
253 | 259 | ||
254 | /* Set IR and DR in PACA MSR */ | 260 | /* Set IR and DR in PACA MSR */ |
255 | get_paca()->kernel_msr = MSR_KERNEL; | 261 | get_paca()->kernel_msr = MSR_KERNEL; |
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 61c1fadbc644..3f15edf25a0d 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c | |||
@@ -34,6 +34,8 @@ | |||
34 | #include <linux/topology.h> | 34 | #include <linux/topology.h> |
35 | #include <linux/profile.h> | 35 | #include <linux/profile.h> |
36 | #include <linux/processor.h> | 36 | #include <linux/processor.h> |
37 | #include <linux/random.h> | ||
38 | #include <linux/stackprotector.h> | ||
37 | 39 | ||
38 | #include <asm/ptrace.h> | 40 | #include <asm/ptrace.h> |
39 | #include <linux/atomic.h> | 41 | #include <linux/atomic.h> |
@@ -74,14 +76,32 @@ static DEFINE_PER_CPU(int, cpu_state) = { 0 }; | |||
74 | #endif | 76 | #endif |
75 | 77 | ||
76 | struct thread_info *secondary_ti; | 78 | struct thread_info *secondary_ti; |
79 | bool has_big_cores; | ||
77 | 80 | ||
78 | DEFINE_PER_CPU(cpumask_var_t, cpu_sibling_map); | 81 | DEFINE_PER_CPU(cpumask_var_t, cpu_sibling_map); |
82 | DEFINE_PER_CPU(cpumask_var_t, cpu_smallcore_map); | ||
79 | DEFINE_PER_CPU(cpumask_var_t, cpu_l2_cache_map); | 83 | DEFINE_PER_CPU(cpumask_var_t, cpu_l2_cache_map); |
80 | DEFINE_PER_CPU(cpumask_var_t, cpu_core_map); | 84 | DEFINE_PER_CPU(cpumask_var_t, cpu_core_map); |
81 | 85 | ||
82 | EXPORT_PER_CPU_SYMBOL(cpu_sibling_map); | 86 | EXPORT_PER_CPU_SYMBOL(cpu_sibling_map); |
83 | EXPORT_PER_CPU_SYMBOL(cpu_l2_cache_map); | 87 | EXPORT_PER_CPU_SYMBOL(cpu_l2_cache_map); |
84 | EXPORT_PER_CPU_SYMBOL(cpu_core_map); | 88 | EXPORT_PER_CPU_SYMBOL(cpu_core_map); |
89 | EXPORT_SYMBOL_GPL(has_big_cores); | ||
90 | |||
91 | #define MAX_THREAD_LIST_SIZE 8 | ||
92 | #define THREAD_GROUP_SHARE_L1 1 | ||
93 | struct thread_groups { | ||
94 | unsigned int property; | ||
95 | unsigned int nr_groups; | ||
96 | unsigned int threads_per_group; | ||
97 | unsigned int thread_list[MAX_THREAD_LIST_SIZE]; | ||
98 | }; | ||
99 | |||
100 | /* | ||
101 | * On big-cores system, cpu_l1_cache_map for each CPU corresponds to | ||
102 | * the set its siblings that share the L1-cache. | ||
103 | */ | ||
104 | DEFINE_PER_CPU(cpumask_var_t, cpu_l1_cache_map); | ||
85 | 105 | ||
86 | /* SMP operations for this machine */ | 106 | /* SMP operations for this machine */ |
87 | struct smp_ops_t *smp_ops; | 107 | struct smp_ops_t *smp_ops; |
@@ -674,6 +694,185 @@ static void set_cpus_unrelated(int i, int j, | |||
674 | } | 694 | } |
675 | #endif | 695 | #endif |
676 | 696 | ||
697 | /* | ||
698 | * parse_thread_groups: Parses the "ibm,thread-groups" device tree | ||
699 | * property for the CPU device node @dn and stores | ||
700 | * the parsed output in the thread_groups | ||
701 | * structure @tg if the ibm,thread-groups[0] | ||
702 | * matches @property. | ||
703 | * | ||
704 | * @dn: The device node of the CPU device. | ||
705 | * @tg: Pointer to a thread group structure into which the parsed | ||
706 | * output of "ibm,thread-groups" is stored. | ||
707 | * @property: The property of the thread-group that the caller is | ||
708 | * interested in. | ||
709 | * | ||
710 | * ibm,thread-groups[0..N-1] array defines which group of threads in | ||
711 | * the CPU-device node can be grouped together based on the property. | ||
712 | * | ||
713 | * ibm,thread-groups[0] tells us the property based on which the | ||
714 | * threads are being grouped together. If this value is 1, it implies | ||
715 | * that the threads in the same group share L1, translation cache. | ||
716 | * | ||
717 | * ibm,thread-groups[1] tells us how many such thread groups exist. | ||
718 | * | ||
719 | * ibm,thread-groups[2] tells us the number of threads in each such | ||
720 | * group. | ||
721 | * | ||
722 | * ibm,thread-groups[3..N-1] is the list of threads identified by | ||
723 | * "ibm,ppc-interrupt-server#s" arranged as per their membership in | ||
724 | * the grouping. | ||
725 | * | ||
726 | * Example: If ibm,thread-groups = [1,2,4,5,6,7,8,9,10,11,12] it | ||
727 | * implies that there are 2 groups of 4 threads each, where each group | ||
728 | * of threads share L1, translation cache. | ||
729 | * | ||
730 | * The "ibm,ppc-interrupt-server#s" of the first group is {5,6,7,8} | ||
731 | * and the "ibm,ppc-interrupt-server#s" of the second group is {9, 10, | ||
732 | * 11, 12} structure | ||
733 | * | ||
734 | * Returns 0 on success, -EINVAL if the property does not exist, | ||
735 | * -ENODATA if property does not have a value, and -EOVERFLOW if the | ||
736 | * property data isn't large enough. | ||
737 | */ | ||
738 | static int parse_thread_groups(struct device_node *dn, | ||
739 | struct thread_groups *tg, | ||
740 | unsigned int property) | ||
741 | { | ||
742 | int i; | ||
743 | u32 thread_group_array[3 + MAX_THREAD_LIST_SIZE]; | ||
744 | u32 *thread_list; | ||
745 | size_t total_threads; | ||
746 | int ret; | ||
747 | |||
748 | ret = of_property_read_u32_array(dn, "ibm,thread-groups", | ||
749 | thread_group_array, 3); | ||
750 | if (ret) | ||
751 | return ret; | ||
752 | |||
753 | tg->property = thread_group_array[0]; | ||
754 | tg->nr_groups = thread_group_array[1]; | ||
755 | tg->threads_per_group = thread_group_array[2]; | ||
756 | if (tg->property != property || | ||
757 | tg->nr_groups < 1 || | ||
758 | tg->threads_per_group < 1) | ||
759 | return -ENODATA; | ||
760 | |||
761 | total_threads = tg->nr_groups * tg->threads_per_group; | ||
762 | |||
763 | ret = of_property_read_u32_array(dn, "ibm,thread-groups", | ||
764 | thread_group_array, | ||
765 | 3 + total_threads); | ||
766 | if (ret) | ||
767 | return ret; | ||
768 | |||
769 | thread_list = &thread_group_array[3]; | ||
770 | |||
771 | for (i = 0 ; i < total_threads; i++) | ||
772 | tg->thread_list[i] = thread_list[i]; | ||
773 | |||
774 | return 0; | ||
775 | } | ||
776 | |||
777 | /* | ||
778 | * get_cpu_thread_group_start : Searches the thread group in tg->thread_list | ||
779 | * that @cpu belongs to. | ||
780 | * | ||
781 | * @cpu : The logical CPU whose thread group is being searched. | ||
782 | * @tg : The thread-group structure of the CPU node which @cpu belongs | ||
783 | * to. | ||
784 | * | ||
785 | * Returns the index to tg->thread_list that points to the the start | ||
786 | * of the thread_group that @cpu belongs to. | ||
787 | * | ||
788 | * Returns -1 if cpu doesn't belong to any of the groups pointed to by | ||
789 | * tg->thread_list. | ||
790 | */ | ||
791 | static int get_cpu_thread_group_start(int cpu, struct thread_groups *tg) | ||
792 | { | ||
793 | int hw_cpu_id = get_hard_smp_processor_id(cpu); | ||
794 | int i, j; | ||
795 | |||
796 | for (i = 0; i < tg->nr_groups; i++) { | ||
797 | int group_start = i * tg->threads_per_group; | ||
798 | |||
799 | for (j = 0; j < tg->threads_per_group; j++) { | ||
800 | int idx = group_start + j; | ||
801 | |||
802 | if (tg->thread_list[idx] == hw_cpu_id) | ||
803 | return group_start; | ||
804 | } | ||
805 | } | ||
806 | |||
807 | return -1; | ||
808 | } | ||
809 | |||
810 | static int init_cpu_l1_cache_map(int cpu) | ||
811 | |||
812 | { | ||
813 | struct device_node *dn = of_get_cpu_node(cpu, NULL); | ||
814 | struct thread_groups tg = {.property = 0, | ||
815 | .nr_groups = 0, | ||
816 | .threads_per_group = 0}; | ||
817 | int first_thread = cpu_first_thread_sibling(cpu); | ||
818 | int i, cpu_group_start = -1, err = 0; | ||
819 | |||
820 | if (!dn) | ||
821 | return -ENODATA; | ||
822 | |||
823 | err = parse_thread_groups(dn, &tg, THREAD_GROUP_SHARE_L1); | ||
824 | if (err) | ||
825 | goto out; | ||
826 | |||
827 | zalloc_cpumask_var_node(&per_cpu(cpu_l1_cache_map, cpu), | ||
828 | GFP_KERNEL, | ||
829 | cpu_to_node(cpu)); | ||
830 | |||
831 | cpu_group_start = get_cpu_thread_group_start(cpu, &tg); | ||
832 | |||
833 | if (unlikely(cpu_group_start == -1)) { | ||
834 | WARN_ON_ONCE(1); | ||
835 | err = -ENODATA; | ||
836 | goto out; | ||
837 | } | ||
838 | |||
839 | for (i = first_thread; i < first_thread + threads_per_core; i++) { | ||
840 | int i_group_start = get_cpu_thread_group_start(i, &tg); | ||
841 | |||
842 | if (unlikely(i_group_start == -1)) { | ||
843 | WARN_ON_ONCE(1); | ||
844 | err = -ENODATA; | ||
845 | goto out; | ||
846 | } | ||
847 | |||
848 | if (i_group_start == cpu_group_start) | ||
849 | cpumask_set_cpu(i, per_cpu(cpu_l1_cache_map, cpu)); | ||
850 | } | ||
851 | |||
852 | out: | ||
853 | of_node_put(dn); | ||
854 | return err; | ||
855 | } | ||
856 | |||
857 | static int init_big_cores(void) | ||
858 | { | ||
859 | int cpu; | ||
860 | |||
861 | for_each_possible_cpu(cpu) { | ||
862 | int err = init_cpu_l1_cache_map(cpu); | ||
863 | |||
864 | if (err) | ||
865 | return err; | ||
866 | |||
867 | zalloc_cpumask_var_node(&per_cpu(cpu_smallcore_map, cpu), | ||
868 | GFP_KERNEL, | ||
869 | cpu_to_node(cpu)); | ||
870 | } | ||
871 | |||
872 | has_big_cores = true; | ||
873 | return 0; | ||
874 | } | ||
875 | |||
677 | void __init smp_prepare_cpus(unsigned int max_cpus) | 876 | void __init smp_prepare_cpus(unsigned int max_cpus) |
678 | { | 877 | { |
679 | unsigned int cpu; | 878 | unsigned int cpu; |
@@ -712,6 +911,12 @@ void __init smp_prepare_cpus(unsigned int max_cpus) | |||
712 | cpumask_set_cpu(boot_cpuid, cpu_l2_cache_mask(boot_cpuid)); | 911 | cpumask_set_cpu(boot_cpuid, cpu_l2_cache_mask(boot_cpuid)); |
713 | cpumask_set_cpu(boot_cpuid, cpu_core_mask(boot_cpuid)); | 912 | cpumask_set_cpu(boot_cpuid, cpu_core_mask(boot_cpuid)); |
714 | 913 | ||
914 | init_big_cores(); | ||
915 | if (has_big_cores) { | ||
916 | cpumask_set_cpu(boot_cpuid, | ||
917 | cpu_smallcore_mask(boot_cpuid)); | ||
918 | } | ||
919 | |||
715 | if (smp_ops && smp_ops->probe) | 920 | if (smp_ops && smp_ops->probe) |
716 | smp_ops->probe(); | 921 | smp_ops->probe(); |
717 | } | 922 | } |
@@ -995,10 +1200,28 @@ static void remove_cpu_from_masks(int cpu) | |||
995 | set_cpus_unrelated(cpu, i, cpu_core_mask); | 1200 | set_cpus_unrelated(cpu, i, cpu_core_mask); |
996 | set_cpus_unrelated(cpu, i, cpu_l2_cache_mask); | 1201 | set_cpus_unrelated(cpu, i, cpu_l2_cache_mask); |
997 | set_cpus_unrelated(cpu, i, cpu_sibling_mask); | 1202 | set_cpus_unrelated(cpu, i, cpu_sibling_mask); |
1203 | if (has_big_cores) | ||
1204 | set_cpus_unrelated(cpu, i, cpu_smallcore_mask); | ||
998 | } | 1205 | } |
999 | } | 1206 | } |
1000 | #endif | 1207 | #endif |
1001 | 1208 | ||
1209 | static inline void add_cpu_to_smallcore_masks(int cpu) | ||
1210 | { | ||
1211 | struct cpumask *this_l1_cache_map = per_cpu(cpu_l1_cache_map, cpu); | ||
1212 | int i, first_thread = cpu_first_thread_sibling(cpu); | ||
1213 | |||
1214 | if (!has_big_cores) | ||
1215 | return; | ||
1216 | |||
1217 | cpumask_set_cpu(cpu, cpu_smallcore_mask(cpu)); | ||
1218 | |||
1219 | for (i = first_thread; i < first_thread + threads_per_core; i++) { | ||
1220 | if (cpu_online(i) && cpumask_test_cpu(i, this_l1_cache_map)) | ||
1221 | set_cpus_related(i, cpu, cpu_smallcore_mask); | ||
1222 | } | ||
1223 | } | ||
1224 | |||
1002 | static void add_cpu_to_masks(int cpu) | 1225 | static void add_cpu_to_masks(int cpu) |
1003 | { | 1226 | { |
1004 | int first_thread = cpu_first_thread_sibling(cpu); | 1227 | int first_thread = cpu_first_thread_sibling(cpu); |
@@ -1015,6 +1238,7 @@ static void add_cpu_to_masks(int cpu) | |||
1015 | if (cpu_online(i)) | 1238 | if (cpu_online(i)) |
1016 | set_cpus_related(i, cpu, cpu_sibling_mask); | 1239 | set_cpus_related(i, cpu, cpu_sibling_mask); |
1017 | 1240 | ||
1241 | add_cpu_to_smallcore_masks(cpu); | ||
1018 | /* | 1242 | /* |
1019 | * Copy the thread sibling mask into the cache sibling mask | 1243 | * Copy the thread sibling mask into the cache sibling mask |
1020 | * and mark any CPUs that share an L2 with this CPU. | 1244 | * and mark any CPUs that share an L2 with this CPU. |
@@ -1044,6 +1268,7 @@ static bool shared_caches; | |||
1044 | void start_secondary(void *unused) | 1268 | void start_secondary(void *unused) |
1045 | { | 1269 | { |
1046 | unsigned int cpu = smp_processor_id(); | 1270 | unsigned int cpu = smp_processor_id(); |
1271 | struct cpumask *(*sibling_mask)(int) = cpu_sibling_mask; | ||
1047 | 1272 | ||
1048 | mmgrab(&init_mm); | 1273 | mmgrab(&init_mm); |
1049 | current->active_mm = &init_mm; | 1274 | current->active_mm = &init_mm; |
@@ -1069,11 +1294,13 @@ void start_secondary(void *unused) | |||
1069 | /* Update topology CPU masks */ | 1294 | /* Update topology CPU masks */ |
1070 | add_cpu_to_masks(cpu); | 1295 | add_cpu_to_masks(cpu); |
1071 | 1296 | ||
1297 | if (has_big_cores) | ||
1298 | sibling_mask = cpu_smallcore_mask; | ||
1072 | /* | 1299 | /* |
1073 | * Check for any shared caches. Note that this must be done on a | 1300 | * Check for any shared caches. Note that this must be done on a |
1074 | * per-core basis because one core in the pair might be disabled. | 1301 | * per-core basis because one core in the pair might be disabled. |
1075 | */ | 1302 | */ |
1076 | if (!cpumask_equal(cpu_l2_cache_mask(cpu), cpu_sibling_mask(cpu))) | 1303 | if (!cpumask_equal(cpu_l2_cache_mask(cpu), sibling_mask(cpu))) |
1077 | shared_caches = true; | 1304 | shared_caches = true; |
1078 | 1305 | ||
1079 | set_numa_node(numa_cpu_lookup_table[cpu]); | 1306 | set_numa_node(numa_cpu_lookup_table[cpu]); |
@@ -1083,6 +1310,8 @@ void start_secondary(void *unused) | |||
1083 | notify_cpu_starting(cpu); | 1310 | notify_cpu_starting(cpu); |
1084 | set_cpu_online(cpu, true); | 1311 | set_cpu_online(cpu, true); |
1085 | 1312 | ||
1313 | boot_init_stack_canary(); | ||
1314 | |||
1086 | local_irq_enable(); | 1315 | local_irq_enable(); |
1087 | 1316 | ||
1088 | /* We can enable ftrace for secondary cpus now */ | 1317 | /* We can enable ftrace for secondary cpus now */ |
@@ -1140,6 +1369,13 @@ static const struct cpumask *shared_cache_mask(int cpu) | |||
1140 | return cpu_l2_cache_mask(cpu); | 1369 | return cpu_l2_cache_mask(cpu); |
1141 | } | 1370 | } |
1142 | 1371 | ||
1372 | #ifdef CONFIG_SCHED_SMT | ||
1373 | static const struct cpumask *smallcore_smt_mask(int cpu) | ||
1374 | { | ||
1375 | return cpu_smallcore_mask(cpu); | ||
1376 | } | ||
1377 | #endif | ||
1378 | |||
1143 | static struct sched_domain_topology_level power9_topology[] = { | 1379 | static struct sched_domain_topology_level power9_topology[] = { |
1144 | #ifdef CONFIG_SCHED_SMT | 1380 | #ifdef CONFIG_SCHED_SMT |
1145 | { cpu_smt_mask, powerpc_smt_flags, SD_INIT_NAME(SMT) }, | 1381 | { cpu_smt_mask, powerpc_smt_flags, SD_INIT_NAME(SMT) }, |
@@ -1167,6 +1403,13 @@ void __init smp_cpus_done(unsigned int max_cpus) | |||
1167 | shared_proc_topology_init(); | 1403 | shared_proc_topology_init(); |
1168 | dump_numa_cpu_topology(); | 1404 | dump_numa_cpu_topology(); |
1169 | 1405 | ||
1406 | #ifdef CONFIG_SCHED_SMT | ||
1407 | if (has_big_cores) { | ||
1408 | pr_info("Using small cores at SMT level\n"); | ||
1409 | power9_topology[0].mask = smallcore_smt_mask; | ||
1410 | powerpc_topology[0].mask = smallcore_smt_mask; | ||
1411 | } | ||
1412 | #endif | ||
1170 | /* | 1413 | /* |
1171 | * If any CPU detects that it's sharing a cache with another CPU then | 1414 | * If any CPU detects that it's sharing a cache with another CPU then |
1172 | * use the deeper topology that is aware of this sharing. | 1415 | * use the deeper topology that is aware of this sharing. |
diff --git a/arch/powerpc/kernel/swsusp_asm64.S b/arch/powerpc/kernel/swsusp_asm64.S index f83bf6f72cb0..185216becb8b 100644 --- a/arch/powerpc/kernel/swsusp_asm64.S +++ b/arch/powerpc/kernel/swsusp_asm64.S | |||
@@ -262,7 +262,7 @@ END_FW_FTR_SECTION_IFCLR(FW_FEATURE_LPAR) | |||
262 | 262 | ||
263 | addi r1,r1,-128 | 263 | addi r1,r1,-128 |
264 | #ifdef CONFIG_PPC_BOOK3S_64 | 264 | #ifdef CONFIG_PPC_BOOK3S_64 |
265 | bl slb_flush_and_rebolt | 265 | bl slb_flush_and_restore_bolted |
266 | #endif | 266 | #endif |
267 | bl do_after_copyback | 267 | bl do_after_copyback |
268 | addi r1,r1,128 | 268 | addi r1,r1,128 |
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 70f145e02487..3646affae963 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c | |||
@@ -111,6 +111,7 @@ struct clock_event_device decrementer_clockevent = { | |||
111 | .rating = 200, | 111 | .rating = 200, |
112 | .irq = 0, | 112 | .irq = 0, |
113 | .set_next_event = decrementer_set_next_event, | 113 | .set_next_event = decrementer_set_next_event, |
114 | .set_state_oneshot_stopped = decrementer_shutdown, | ||
114 | .set_state_shutdown = decrementer_shutdown, | 115 | .set_state_shutdown = decrementer_shutdown, |
115 | .tick_resume = decrementer_shutdown, | 116 | .tick_resume = decrementer_shutdown, |
116 | .features = CLOCK_EVT_FEAT_ONESHOT | | 117 | .features = CLOCK_EVT_FEAT_ONESHOT | |
@@ -175,7 +176,7 @@ static void calc_cputime_factors(void) | |||
175 | * Read the SPURR on systems that have it, otherwise the PURR, | 176 | * Read the SPURR on systems that have it, otherwise the PURR, |
176 | * or if that doesn't exist return the timebase value passed in. | 177 | * or if that doesn't exist return the timebase value passed in. |
177 | */ | 178 | */ |
178 | static unsigned long read_spurr(unsigned long tb) | 179 | static inline unsigned long read_spurr(unsigned long tb) |
179 | { | 180 | { |
180 | if (cpu_has_feature(CPU_FTR_SPURR)) | 181 | if (cpu_has_feature(CPU_FTR_SPURR)) |
181 | return mfspr(SPRN_SPURR); | 182 | return mfspr(SPRN_SPURR); |
@@ -281,26 +282,17 @@ static inline u64 calculate_stolen_time(u64 stop_tb) | |||
281 | * Account time for a transition between system, hard irq | 282 | * Account time for a transition between system, hard irq |
282 | * or soft irq state. | 283 | * or soft irq state. |
283 | */ | 284 | */ |
284 | static unsigned long vtime_delta(struct task_struct *tsk, | 285 | static unsigned long vtime_delta_scaled(struct cpu_accounting_data *acct, |
285 | unsigned long *stime_scaled, | 286 | unsigned long now, unsigned long stime) |
286 | unsigned long *steal_time) | ||
287 | { | 287 | { |
288 | unsigned long now, nowscaled, deltascaled; | 288 | unsigned long stime_scaled = 0; |
289 | unsigned long stime; | 289 | #ifdef CONFIG_ARCH_HAS_SCALED_CPUTIME |
290 | unsigned long nowscaled, deltascaled; | ||
290 | unsigned long utime, utime_scaled; | 291 | unsigned long utime, utime_scaled; |
291 | struct cpu_accounting_data *acct = get_accounting(tsk); | ||
292 | 292 | ||
293 | WARN_ON_ONCE(!irqs_disabled()); | ||
294 | |||
295 | now = mftb(); | ||
296 | nowscaled = read_spurr(now); | 293 | nowscaled = read_spurr(now); |
297 | stime = now - acct->starttime; | ||
298 | acct->starttime = now; | ||
299 | deltascaled = nowscaled - acct->startspurr; | 294 | deltascaled = nowscaled - acct->startspurr; |
300 | acct->startspurr = nowscaled; | 295 | acct->startspurr = nowscaled; |
301 | |||
302 | *steal_time = calculate_stolen_time(now); | ||
303 | |||
304 | utime = acct->utime - acct->utime_sspurr; | 296 | utime = acct->utime - acct->utime_sspurr; |
305 | acct->utime_sspurr = acct->utime; | 297 | acct->utime_sspurr = acct->utime; |
306 | 298 | ||
@@ -314,17 +306,38 @@ static unsigned long vtime_delta(struct task_struct *tsk, | |||
314 | * the user ticks get saved up in paca->user_time_scaled to be | 306 | * the user ticks get saved up in paca->user_time_scaled to be |
315 | * used by account_process_tick. | 307 | * used by account_process_tick. |
316 | */ | 308 | */ |
317 | *stime_scaled = stime; | 309 | stime_scaled = stime; |
318 | utime_scaled = utime; | 310 | utime_scaled = utime; |
319 | if (deltascaled != stime + utime) { | 311 | if (deltascaled != stime + utime) { |
320 | if (utime) { | 312 | if (utime) { |
321 | *stime_scaled = deltascaled * stime / (stime + utime); | 313 | stime_scaled = deltascaled * stime / (stime + utime); |
322 | utime_scaled = deltascaled - *stime_scaled; | 314 | utime_scaled = deltascaled - stime_scaled; |
323 | } else { | 315 | } else { |
324 | *stime_scaled = deltascaled; | 316 | stime_scaled = deltascaled; |
325 | } | 317 | } |
326 | } | 318 | } |
327 | acct->utime_scaled += utime_scaled; | 319 | acct->utime_scaled += utime_scaled; |
320 | #endif | ||
321 | |||
322 | return stime_scaled; | ||
323 | } | ||
324 | |||
325 | static unsigned long vtime_delta(struct task_struct *tsk, | ||
326 | unsigned long *stime_scaled, | ||
327 | unsigned long *steal_time) | ||
328 | { | ||
329 | unsigned long now, stime; | ||
330 | struct cpu_accounting_data *acct = get_accounting(tsk); | ||
331 | |||
332 | WARN_ON_ONCE(!irqs_disabled()); | ||
333 | |||
334 | now = mftb(); | ||
335 | stime = now - acct->starttime; | ||
336 | acct->starttime = now; | ||
337 | |||
338 | *stime_scaled = vtime_delta_scaled(acct, now, stime); | ||
339 | |||
340 | *steal_time = calculate_stolen_time(now); | ||
328 | 341 | ||
329 | return stime; | 342 | return stime; |
330 | } | 343 | } |
@@ -341,7 +354,9 @@ void vtime_account_system(struct task_struct *tsk) | |||
341 | 354 | ||
342 | if ((tsk->flags & PF_VCPU) && !irq_count()) { | 355 | if ((tsk->flags & PF_VCPU) && !irq_count()) { |
343 | acct->gtime += stime; | 356 | acct->gtime += stime; |
357 | #ifdef CONFIG_ARCH_HAS_SCALED_CPUTIME | ||
344 | acct->utime_scaled += stime_scaled; | 358 | acct->utime_scaled += stime_scaled; |
359 | #endif | ||
345 | } else { | 360 | } else { |
346 | if (hardirq_count()) | 361 | if (hardirq_count()) |
347 | acct->hardirq_time += stime; | 362 | acct->hardirq_time += stime; |
@@ -350,7 +365,9 @@ void vtime_account_system(struct task_struct *tsk) | |||
350 | else | 365 | else |
351 | acct->stime += stime; | 366 | acct->stime += stime; |
352 | 367 | ||
368 | #ifdef CONFIG_ARCH_HAS_SCALED_CPUTIME | ||
353 | acct->stime_scaled += stime_scaled; | 369 | acct->stime_scaled += stime_scaled; |
370 | #endif | ||
354 | } | 371 | } |
355 | } | 372 | } |
356 | EXPORT_SYMBOL_GPL(vtime_account_system); | 373 | EXPORT_SYMBOL_GPL(vtime_account_system); |
@@ -364,6 +381,21 @@ void vtime_account_idle(struct task_struct *tsk) | |||
364 | acct->idle_time += stime + steal_time; | 381 | acct->idle_time += stime + steal_time; |
365 | } | 382 | } |
366 | 383 | ||
384 | static void vtime_flush_scaled(struct task_struct *tsk, | ||
385 | struct cpu_accounting_data *acct) | ||
386 | { | ||
387 | #ifdef CONFIG_ARCH_HAS_SCALED_CPUTIME | ||
388 | if (acct->utime_scaled) | ||
389 | tsk->utimescaled += cputime_to_nsecs(acct->utime_scaled); | ||
390 | if (acct->stime_scaled) | ||
391 | tsk->stimescaled += cputime_to_nsecs(acct->stime_scaled); | ||
392 | |||
393 | acct->utime_scaled = 0; | ||
394 | acct->utime_sspurr = 0; | ||
395 | acct->stime_scaled = 0; | ||
396 | #endif | ||
397 | } | ||
398 | |||
367 | /* | 399 | /* |
368 | * Account the whole cputime accumulated in the paca | 400 | * Account the whole cputime accumulated in the paca |
369 | * Must be called with interrupts disabled. | 401 | * Must be called with interrupts disabled. |
@@ -378,14 +410,13 @@ void vtime_flush(struct task_struct *tsk) | |||
378 | if (acct->utime) | 410 | if (acct->utime) |
379 | account_user_time(tsk, cputime_to_nsecs(acct->utime)); | 411 | account_user_time(tsk, cputime_to_nsecs(acct->utime)); |
380 | 412 | ||
381 | if (acct->utime_scaled) | ||
382 | tsk->utimescaled += cputime_to_nsecs(acct->utime_scaled); | ||
383 | |||
384 | if (acct->gtime) | 413 | if (acct->gtime) |
385 | account_guest_time(tsk, cputime_to_nsecs(acct->gtime)); | 414 | account_guest_time(tsk, cputime_to_nsecs(acct->gtime)); |
386 | 415 | ||
387 | if (acct->steal_time) | 416 | if (IS_ENABLED(CONFIG_PPC_SPLPAR) && acct->steal_time) { |
388 | account_steal_time(cputime_to_nsecs(acct->steal_time)); | 417 | account_steal_time(cputime_to_nsecs(acct->steal_time)); |
418 | acct->steal_time = 0; | ||
419 | } | ||
389 | 420 | ||
390 | if (acct->idle_time) | 421 | if (acct->idle_time) |
391 | account_idle_time(cputime_to_nsecs(acct->idle_time)); | 422 | account_idle_time(cputime_to_nsecs(acct->idle_time)); |
@@ -393,8 +424,6 @@ void vtime_flush(struct task_struct *tsk) | |||
393 | if (acct->stime) | 424 | if (acct->stime) |
394 | account_system_index_time(tsk, cputime_to_nsecs(acct->stime), | 425 | account_system_index_time(tsk, cputime_to_nsecs(acct->stime), |
395 | CPUTIME_SYSTEM); | 426 | CPUTIME_SYSTEM); |
396 | if (acct->stime_scaled) | ||
397 | tsk->stimescaled += cputime_to_nsecs(acct->stime_scaled); | ||
398 | 427 | ||
399 | if (acct->hardirq_time) | 428 | if (acct->hardirq_time) |
400 | account_system_index_time(tsk, cputime_to_nsecs(acct->hardirq_time), | 429 | account_system_index_time(tsk, cputime_to_nsecs(acct->hardirq_time), |
@@ -403,14 +432,12 @@ void vtime_flush(struct task_struct *tsk) | |||
403 | account_system_index_time(tsk, cputime_to_nsecs(acct->softirq_time), | 432 | account_system_index_time(tsk, cputime_to_nsecs(acct->softirq_time), |
404 | CPUTIME_SOFTIRQ); | 433 | CPUTIME_SOFTIRQ); |
405 | 434 | ||
435 | vtime_flush_scaled(tsk, acct); | ||
436 | |||
406 | acct->utime = 0; | 437 | acct->utime = 0; |
407 | acct->utime_scaled = 0; | ||
408 | acct->utime_sspurr = 0; | ||
409 | acct->gtime = 0; | 438 | acct->gtime = 0; |
410 | acct->steal_time = 0; | ||
411 | acct->idle_time = 0; | 439 | acct->idle_time = 0; |
412 | acct->stime = 0; | 440 | acct->stime = 0; |
413 | acct->stime_scaled = 0; | ||
414 | acct->hardirq_time = 0; | 441 | acct->hardirq_time = 0; |
415 | acct->softirq_time = 0; | 442 | acct->softirq_time = 0; |
416 | } | 443 | } |
@@ -984,10 +1011,14 @@ static void register_decrementer_clockevent(int cpu) | |||
984 | *dec = decrementer_clockevent; | 1011 | *dec = decrementer_clockevent; |
985 | dec->cpumask = cpumask_of(cpu); | 1012 | dec->cpumask = cpumask_of(cpu); |
986 | 1013 | ||
1014 | clockevents_config_and_register(dec, ppc_tb_freq, 2, decrementer_max); | ||
1015 | |||
987 | printk_once(KERN_DEBUG "clockevent: %s mult[%x] shift[%d] cpu[%d]\n", | 1016 | printk_once(KERN_DEBUG "clockevent: %s mult[%x] shift[%d] cpu[%d]\n", |
988 | dec->name, dec->mult, dec->shift, cpu); | 1017 | dec->name, dec->mult, dec->shift, cpu); |
989 | 1018 | ||
990 | clockevents_register_device(dec); | 1019 | /* Set values for KVM, see kvm_emulate_dec() */ |
1020 | decrementer_clockevent.mult = dec->mult; | ||
1021 | decrementer_clockevent.shift = dec->shift; | ||
991 | } | 1022 | } |
992 | 1023 | ||
993 | static void enable_large_decrementer(void) | 1024 | static void enable_large_decrementer(void) |
@@ -1035,18 +1066,7 @@ static void __init set_decrementer_max(void) | |||
1035 | 1066 | ||
1036 | static void __init init_decrementer_clockevent(void) | 1067 | static void __init init_decrementer_clockevent(void) |
1037 | { | 1068 | { |
1038 | int cpu = smp_processor_id(); | 1069 | register_decrementer_clockevent(smp_processor_id()); |
1039 | |||
1040 | clockevents_calc_mult_shift(&decrementer_clockevent, ppc_tb_freq, 4); | ||
1041 | |||
1042 | decrementer_clockevent.max_delta_ns = | ||
1043 | clockevent_delta2ns(decrementer_max, &decrementer_clockevent); | ||
1044 | decrementer_clockevent.max_delta_ticks = decrementer_max; | ||
1045 | decrementer_clockevent.min_delta_ns = | ||
1046 | clockevent_delta2ns(2, &decrementer_clockevent); | ||
1047 | decrementer_clockevent.min_delta_ticks = 2; | ||
1048 | |||
1049 | register_decrementer_clockevent(cpu); | ||
1050 | } | 1070 | } |
1051 | 1071 | ||
1052 | void secondary_cpu_time_init(void) | 1072 | void secondary_cpu_time_init(void) |
diff --git a/arch/powerpc/kernel/tm.S b/arch/powerpc/kernel/tm.S index 7716374786bd..9fabdce255cd 100644 --- a/arch/powerpc/kernel/tm.S +++ b/arch/powerpc/kernel/tm.S | |||
@@ -92,13 +92,14 @@ _GLOBAL(tm_abort) | |||
92 | blr | 92 | blr |
93 | EXPORT_SYMBOL_GPL(tm_abort); | 93 | EXPORT_SYMBOL_GPL(tm_abort); |
94 | 94 | ||
95 | /* void tm_reclaim(struct thread_struct *thread, | 95 | /* |
96 | * void tm_reclaim(struct thread_struct *thread, | ||
96 | * uint8_t cause) | 97 | * uint8_t cause) |
97 | * | 98 | * |
98 | * - Performs a full reclaim. This destroys outstanding | 99 | * - Performs a full reclaim. This destroys outstanding |
99 | * transactions and updates thread->regs.tm_ckpt_* with the | 100 | * transactions and updates thread.ckpt_regs, thread.ckfp_state and |
100 | * original checkpointed state. Note that thread->regs is | 101 | * thread.ckvr_state with the original checkpointed state. Note that |
101 | * unchanged. | 102 | * thread->regs is unchanged. |
102 | * | 103 | * |
103 | * Purpose is to both abort transactions of, and preserve the state of, | 104 | * Purpose is to both abort transactions of, and preserve the state of, |
104 | * a transactions at a context switch. We preserve/restore both sets of process | 105 | * a transactions at a context switch. We preserve/restore both sets of process |
@@ -163,15 +164,16 @@ _GLOBAL(tm_reclaim) | |||
163 | */ | 164 | */ |
164 | TRECLAIM(R4) /* Cause in r4 */ | 165 | TRECLAIM(R4) /* Cause in r4 */ |
165 | 166 | ||
166 | /* ******************** GPRs ******************** */ | 167 | /* |
167 | /* Stash the checkpointed r13 away in the scratch SPR and get the real | 168 | * ******************** GPRs ******************** |
168 | * paca | 169 | * Stash the checkpointed r13 in the scratch SPR and get the real paca. |
169 | */ | 170 | */ |
170 | SET_SCRATCH0(r13) | 171 | SET_SCRATCH0(r13) |
171 | GET_PACA(r13) | 172 | GET_PACA(r13) |
172 | 173 | ||
173 | /* Stash the checkpointed r1 away in paca tm_scratch and get the real | 174 | /* |
174 | * stack pointer back | 175 | * Stash the checkpointed r1 away in paca->tm_scratch and get the real |
176 | * stack pointer back into r1. | ||
175 | */ | 177 | */ |
176 | std r1, PACATMSCRATCH(r13) | 178 | std r1, PACATMSCRATCH(r13) |
177 | ld r1, PACAR1(r13) | 179 | ld r1, PACAR1(r13) |
@@ -209,14 +211,15 @@ _GLOBAL(tm_reclaim) | |||
209 | 211 | ||
210 | addi r7, r12, PT_CKPT_REGS /* Thread's ckpt_regs */ | 212 | addi r7, r12, PT_CKPT_REGS /* Thread's ckpt_regs */ |
211 | 213 | ||
212 | /* Make r7 look like an exception frame so that we | 214 | /* |
213 | * can use the neat GPRx(n) macros. r7 is NOT a pt_regs ptr! | 215 | * Make r7 look like an exception frame so that we can use the neat |
216 | * GPRx(n) macros. r7 is NOT a pt_regs ptr! | ||
214 | */ | 217 | */ |
215 | subi r7, r7, STACK_FRAME_OVERHEAD | 218 | subi r7, r7, STACK_FRAME_OVERHEAD |
216 | 219 | ||
217 | /* Sync the userland GPRs 2-12, 14-31 to thread->regs: */ | 220 | /* Sync the userland GPRs 2-12, 14-31 to thread->regs: */ |
218 | SAVE_GPR(0, r7) /* user r0 */ | 221 | SAVE_GPR(0, r7) /* user r0 */ |
219 | SAVE_GPR(2, r7) /* user r2 */ | 222 | SAVE_GPR(2, r7) /* user r2 */ |
220 | SAVE_4GPRS(3, r7) /* user r3-r6 */ | 223 | SAVE_4GPRS(3, r7) /* user r3-r6 */ |
221 | SAVE_GPR(8, r7) /* user r8 */ | 224 | SAVE_GPR(8, r7) /* user r8 */ |
222 | SAVE_GPR(9, r7) /* user r9 */ | 225 | SAVE_GPR(9, r7) /* user r9 */ |
@@ -237,7 +240,8 @@ _GLOBAL(tm_reclaim) | |||
237 | /* ******************** NIP ******************** */ | 240 | /* ******************** NIP ******************** */ |
238 | mfspr r3, SPRN_TFHAR | 241 | mfspr r3, SPRN_TFHAR |
239 | std r3, _NIP(r7) /* Returns to failhandler */ | 242 | std r3, _NIP(r7) /* Returns to failhandler */ |
240 | /* The checkpointed NIP is ignored when rescheduling/rechkpting, | 243 | /* |
244 | * The checkpointed NIP is ignored when rescheduling/rechkpting, | ||
241 | * but is used in signal return to 'wind back' to the abort handler. | 245 | * but is used in signal return to 'wind back' to the abort handler. |
242 | */ | 246 | */ |
243 | 247 | ||
@@ -260,12 +264,13 @@ _GLOBAL(tm_reclaim) | |||
260 | std r3, THREAD_TM_TAR(r12) | 264 | std r3, THREAD_TM_TAR(r12) |
261 | std r4, THREAD_TM_DSCR(r12) | 265 | std r4, THREAD_TM_DSCR(r12) |
262 | 266 | ||
263 | /* MSR and flags: We don't change CRs, and we don't need to alter | 267 | /* |
264 | * MSR. | 268 | * MSR and flags: We don't change CRs, and we don't need to alter MSR. |
265 | */ | 269 | */ |
266 | 270 | ||
267 | 271 | ||
268 | /* ******************** FPR/VR/VSRs ************ | 272 | /* |
273 | * ******************** FPR/VR/VSRs ************ | ||
269 | * After reclaiming, capture the checkpointed FPRs/VRs. | 274 | * After reclaiming, capture the checkpointed FPRs/VRs. |
270 | * | 275 | * |
271 | * We enabled VEC/FP/VSX in the msr above, so we can execute these | 276 | * We enabled VEC/FP/VSX in the msr above, so we can execute these |
@@ -275,7 +280,7 @@ _GLOBAL(tm_reclaim) | |||
275 | 280 | ||
276 | /* Altivec (VEC/VMX/VR)*/ | 281 | /* Altivec (VEC/VMX/VR)*/ |
277 | addi r7, r3, THREAD_CKVRSTATE | 282 | addi r7, r3, THREAD_CKVRSTATE |
278 | SAVE_32VRS(0, r6, r7) /* r6 scratch, r7 transact vr state */ | 283 | SAVE_32VRS(0, r6, r7) /* r6 scratch, r7 ckvr_state */ |
279 | mfvscr v0 | 284 | mfvscr v0 |
280 | li r6, VRSTATE_VSCR | 285 | li r6, VRSTATE_VSCR |
281 | stvx v0, r7, r6 | 286 | stvx v0, r7, r6 |
@@ -286,12 +291,13 @@ _GLOBAL(tm_reclaim) | |||
286 | 291 | ||
287 | /* Floating Point (FP) */ | 292 | /* Floating Point (FP) */ |
288 | addi r7, r3, THREAD_CKFPSTATE | 293 | addi r7, r3, THREAD_CKFPSTATE |
289 | SAVE_32FPRS_VSRS(0, R6, R7) /* r6 scratch, r7 transact fp state */ | 294 | SAVE_32FPRS_VSRS(0, R6, R7) /* r6 scratch, r7 ckfp_state */ |
290 | mffs fr0 | 295 | mffs fr0 |
291 | stfd fr0,FPSTATE_FPSCR(r7) | 296 | stfd fr0,FPSTATE_FPSCR(r7) |
292 | 297 | ||
293 | 298 | ||
294 | /* TM regs, incl TEXASR -- these live in thread_struct. Note they've | 299 | /* |
300 | * TM regs, incl TEXASR -- these live in thread_struct. Note they've | ||
295 | * been updated by the treclaim, to explain to userland the failure | 301 | * been updated by the treclaim, to explain to userland the failure |
296 | * cause (aborted). | 302 | * cause (aborted). |
297 | */ | 303 | */ |
@@ -327,7 +333,7 @@ _GLOBAL(tm_reclaim) | |||
327 | blr | 333 | blr |
328 | 334 | ||
329 | 335 | ||
330 | /* | 336 | /* |
331 | * void __tm_recheckpoint(struct thread_struct *thread) | 337 | * void __tm_recheckpoint(struct thread_struct *thread) |
332 | * - Restore the checkpointed register state saved by tm_reclaim | 338 | * - Restore the checkpointed register state saved by tm_reclaim |
333 | * when we switch_to a process. | 339 | * when we switch_to a process. |
@@ -343,7 +349,8 @@ _GLOBAL(__tm_recheckpoint) | |||
343 | std r2, STK_GOT(r1) | 349 | std r2, STK_GOT(r1) |
344 | stdu r1, -TM_FRAME_SIZE(r1) | 350 | stdu r1, -TM_FRAME_SIZE(r1) |
345 | 351 | ||
346 | /* We've a struct pt_regs at [r1+STACK_FRAME_OVERHEAD]. | 352 | /* |
353 | * We've a struct pt_regs at [r1+STACK_FRAME_OVERHEAD]. | ||
347 | * This is used for backing up the NVGPRs: | 354 | * This is used for backing up the NVGPRs: |
348 | */ | 355 | */ |
349 | SAVE_NVGPRS(r1) | 356 | SAVE_NVGPRS(r1) |
@@ -352,8 +359,9 @@ _GLOBAL(__tm_recheckpoint) | |||
352 | 359 | ||
353 | addi r7, r3, PT_CKPT_REGS /* Thread's ckpt_regs */ | 360 | addi r7, r3, PT_CKPT_REGS /* Thread's ckpt_regs */ |
354 | 361 | ||
355 | /* Make r7 look like an exception frame so that we | 362 | /* |
356 | * can use the neat GPRx(n) macros. r7 is now NOT a pt_regs ptr! | 363 | * Make r7 look like an exception frame so that we can use the neat |
364 | * GPRx(n) macros. r7 is now NOT a pt_regs ptr! | ||
357 | */ | 365 | */ |
358 | subi r7, r7, STACK_FRAME_OVERHEAD | 366 | subi r7, r7, STACK_FRAME_OVERHEAD |
359 | 367 | ||
@@ -421,14 +429,15 @@ restore_gprs: | |||
421 | 429 | ||
422 | REST_NVGPRS(r7) /* GPR14-31 */ | 430 | REST_NVGPRS(r7) /* GPR14-31 */ |
423 | 431 | ||
424 | /* Load up PPR and DSCR here so we don't run with user values for long | 432 | /* Load up PPR and DSCR here so we don't run with user values for long */ |
425 | */ | ||
426 | mtspr SPRN_DSCR, r5 | 433 | mtspr SPRN_DSCR, r5 |
427 | mtspr SPRN_PPR, r6 | 434 | mtspr SPRN_PPR, r6 |
428 | 435 | ||
429 | /* Do final sanity check on TEXASR to make sure FS is set. Do this | 436 | /* |
437 | * Do final sanity check on TEXASR to make sure FS is set. Do this | ||
430 | * here before we load up the userspace r1 so any bugs we hit will get | 438 | * here before we load up the userspace r1 so any bugs we hit will get |
431 | * a call chain */ | 439 | * a call chain. |
440 | */ | ||
432 | mfspr r5, SPRN_TEXASR | 441 | mfspr r5, SPRN_TEXASR |
433 | srdi r5, r5, 16 | 442 | srdi r5, r5, 16 |
434 | li r6, (TEXASR_FS)@h | 443 | li r6, (TEXASR_FS)@h |
@@ -436,8 +445,9 @@ restore_gprs: | |||
436 | 1: tdeqi r6, 0 | 445 | 1: tdeqi r6, 0 |
437 | EMIT_BUG_ENTRY 1b,__FILE__,__LINE__,0 | 446 | EMIT_BUG_ENTRY 1b,__FILE__,__LINE__,0 |
438 | 447 | ||
439 | /* Do final sanity check on MSR to make sure we are not transactional | 448 | /* |
440 | * or suspended | 449 | * Do final sanity check on MSR to make sure we are not transactional |
450 | * or suspended. | ||
441 | */ | 451 | */ |
442 | mfmsr r6 | 452 | mfmsr r6 |
443 | li r5, (MSR_TS_MASK)@higher | 453 | li r5, (MSR_TS_MASK)@higher |
@@ -453,8 +463,8 @@ restore_gprs: | |||
453 | REST_GPR(6, r7) | 463 | REST_GPR(6, r7) |
454 | 464 | ||
455 | /* | 465 | /* |
456 | * Store r1 and r5 on the stack so that we can access them | 466 | * Store r1 and r5 on the stack so that we can access them after we |
457 | * after we clear MSR RI. | 467 | * clear MSR RI. |
458 | */ | 468 | */ |
459 | 469 | ||
460 | REST_GPR(5, r7) | 470 | REST_GPR(5, r7) |
@@ -484,7 +494,8 @@ restore_gprs: | |||
484 | 494 | ||
485 | HMT_MEDIUM | 495 | HMT_MEDIUM |
486 | 496 | ||
487 | /* Our transactional state has now changed. | 497 | /* |
498 | * Our transactional state has now changed. | ||
488 | * | 499 | * |
489 | * Now just get out of here. Transactional (current) state will be | 500 | * Now just get out of here. Transactional (current) state will be |
490 | * updated once restore is called on the return path in the _switch-ed | 501 | * updated once restore is called on the return path in the _switch-ed |
diff --git a/arch/powerpc/kernel/trace/Makefile b/arch/powerpc/kernel/trace/Makefile index d22d8bafb643..b1725ad3e13d 100644 --- a/arch/powerpc/kernel/trace/Makefile +++ b/arch/powerpc/kernel/trace/Makefile | |||
@@ -3,11 +3,9 @@ | |||
3 | # Makefile for the powerpc trace subsystem | 3 | # Makefile for the powerpc trace subsystem |
4 | # | 4 | # |
5 | 5 | ||
6 | subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror | ||
7 | |||
8 | ifdef CONFIG_FUNCTION_TRACER | 6 | ifdef CONFIG_FUNCTION_TRACER |
9 | # do not trace tracer code | 7 | # do not trace tracer code |
10 | CFLAGS_REMOVE_ftrace.o = -mno-sched-epilog $(CC_FLAGS_FTRACE) | 8 | CFLAGS_REMOVE_ftrace.o = $(CC_FLAGS_FTRACE) |
11 | endif | 9 | endif |
12 | 10 | ||
13 | obj32-$(CONFIG_FUNCTION_TRACER) += ftrace_32.o | 11 | obj32-$(CONFIG_FUNCTION_TRACER) += ftrace_32.o |
diff --git a/arch/powerpc/kernel/trace/ftrace.c b/arch/powerpc/kernel/trace/ftrace.c index 4bfbb54dee51..4bf051d3e21e 100644 --- a/arch/powerpc/kernel/trace/ftrace.c +++ b/arch/powerpc/kernel/trace/ftrace.c | |||
@@ -30,6 +30,16 @@ | |||
30 | 30 | ||
31 | 31 | ||
32 | #ifdef CONFIG_DYNAMIC_FTRACE | 32 | #ifdef CONFIG_DYNAMIC_FTRACE |
33 | |||
34 | /* | ||
35 | * We generally only have a single long_branch tramp and at most 2 or 3 plt | ||
36 | * tramps generated. But, we don't use the plt tramps currently. We also allot | ||
37 | * 2 tramps after .text and .init.text. So, we only end up with around 3 usable | ||
38 | * tramps in total. Set aside 8 just to be sure. | ||
39 | */ | ||
40 | #define NUM_FTRACE_TRAMPS 8 | ||
41 | static unsigned long ftrace_tramps[NUM_FTRACE_TRAMPS]; | ||
42 | |||
33 | static unsigned int | 43 | static unsigned int |
34 | ftrace_call_replace(unsigned long ip, unsigned long addr, int link) | 44 | ftrace_call_replace(unsigned long ip, unsigned long addr, int link) |
35 | { | 45 | { |
@@ -85,13 +95,16 @@ static int test_24bit_addr(unsigned long ip, unsigned long addr) | |||
85 | return create_branch((unsigned int *)ip, addr, 0); | 95 | return create_branch((unsigned int *)ip, addr, 0); |
86 | } | 96 | } |
87 | 97 | ||
88 | #ifdef CONFIG_MODULES | ||
89 | |||
90 | static int is_bl_op(unsigned int op) | 98 | static int is_bl_op(unsigned int op) |
91 | { | 99 | { |
92 | return (op & 0xfc000003) == 0x48000001; | 100 | return (op & 0xfc000003) == 0x48000001; |
93 | } | 101 | } |
94 | 102 | ||
103 | static int is_b_op(unsigned int op) | ||
104 | { | ||
105 | return (op & 0xfc000003) == 0x48000000; | ||
106 | } | ||
107 | |||
95 | static unsigned long find_bl_target(unsigned long ip, unsigned int op) | 108 | static unsigned long find_bl_target(unsigned long ip, unsigned int op) |
96 | { | 109 | { |
97 | static int offset; | 110 | static int offset; |
@@ -104,6 +117,7 @@ static unsigned long find_bl_target(unsigned long ip, unsigned int op) | |||
104 | return ip + (long)offset; | 117 | return ip + (long)offset; |
105 | } | 118 | } |
106 | 119 | ||
120 | #ifdef CONFIG_MODULES | ||
107 | #ifdef CONFIG_PPC64 | 121 | #ifdef CONFIG_PPC64 |
108 | static int | 122 | static int |
109 | __ftrace_make_nop(struct module *mod, | 123 | __ftrace_make_nop(struct module *mod, |
@@ -270,6 +284,146 @@ __ftrace_make_nop(struct module *mod, | |||
270 | #endif /* PPC64 */ | 284 | #endif /* PPC64 */ |
271 | #endif /* CONFIG_MODULES */ | 285 | #endif /* CONFIG_MODULES */ |
272 | 286 | ||
287 | static unsigned long find_ftrace_tramp(unsigned long ip) | ||
288 | { | ||
289 | int i; | ||
290 | |||
291 | /* | ||
292 | * We have the compiler generated long_branch tramps at the end | ||
293 | * and we prefer those | ||
294 | */ | ||
295 | for (i = NUM_FTRACE_TRAMPS - 1; i >= 0; i--) | ||
296 | if (!ftrace_tramps[i]) | ||
297 | continue; | ||
298 | else if (create_branch((void *)ip, ftrace_tramps[i], 0)) | ||
299 | return ftrace_tramps[i]; | ||
300 | |||
301 | return 0; | ||
302 | } | ||
303 | |||
304 | static int add_ftrace_tramp(unsigned long tramp) | ||
305 | { | ||
306 | int i; | ||
307 | |||
308 | for (i = 0; i < NUM_FTRACE_TRAMPS; i++) | ||
309 | if (!ftrace_tramps[i]) { | ||
310 | ftrace_tramps[i] = tramp; | ||
311 | return 0; | ||
312 | } | ||
313 | |||
314 | return -1; | ||
315 | } | ||
316 | |||
317 | /* | ||
318 | * If this is a compiler generated long_branch trampoline (essentially, a | ||
319 | * trampoline that has a branch to _mcount()), we re-write the branch to | ||
320 | * instead go to ftrace_[regs_]caller() and note down the location of this | ||
321 | * trampoline. | ||
322 | */ | ||
323 | static int setup_mcount_compiler_tramp(unsigned long tramp) | ||
324 | { | ||
325 | int i, op; | ||
326 | unsigned long ptr; | ||
327 | static unsigned long ftrace_plt_tramps[NUM_FTRACE_TRAMPS]; | ||
328 | |||
329 | /* Is this a known long jump tramp? */ | ||
330 | for (i = 0; i < NUM_FTRACE_TRAMPS; i++) | ||
331 | if (!ftrace_tramps[i]) | ||
332 | break; | ||
333 | else if (ftrace_tramps[i] == tramp) | ||
334 | return 0; | ||
335 | |||
336 | /* Is this a known plt tramp? */ | ||
337 | for (i = 0; i < NUM_FTRACE_TRAMPS; i++) | ||
338 | if (!ftrace_plt_tramps[i]) | ||
339 | break; | ||
340 | else if (ftrace_plt_tramps[i] == tramp) | ||
341 | return -1; | ||
342 | |||
343 | /* New trampoline -- read where this goes */ | ||
344 | if (probe_kernel_read(&op, (void *)tramp, sizeof(int))) { | ||
345 | pr_debug("Fetching opcode failed.\n"); | ||
346 | return -1; | ||
347 | } | ||
348 | |||
349 | /* Is this a 24 bit branch? */ | ||
350 | if (!is_b_op(op)) { | ||
351 | pr_debug("Trampoline is not a long branch tramp.\n"); | ||
352 | return -1; | ||
353 | } | ||
354 | |||
355 | /* lets find where the pointer goes */ | ||
356 | ptr = find_bl_target(tramp, op); | ||
357 | |||
358 | if (ptr != ppc_global_function_entry((void *)_mcount)) { | ||
359 | pr_debug("Trampoline target %p is not _mcount\n", (void *)ptr); | ||
360 | return -1; | ||
361 | } | ||
362 | |||
363 | /* Let's re-write the tramp to go to ftrace_[regs_]caller */ | ||
364 | #ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS | ||
365 | ptr = ppc_global_function_entry((void *)ftrace_regs_caller); | ||
366 | #else | ||
367 | ptr = ppc_global_function_entry((void *)ftrace_caller); | ||
368 | #endif | ||
369 | if (!create_branch((void *)tramp, ptr, 0)) { | ||
370 | pr_debug("%ps is not reachable from existing mcount tramp\n", | ||
371 | (void *)ptr); | ||
372 | return -1; | ||
373 | } | ||
374 | |||
375 | if (patch_branch((unsigned int *)tramp, ptr, 0)) { | ||
376 | pr_debug("REL24 out of range!\n"); | ||
377 | return -1; | ||
378 | } | ||
379 | |||
380 | if (add_ftrace_tramp(tramp)) { | ||
381 | pr_debug("No tramp locations left\n"); | ||
382 | return -1; | ||
383 | } | ||
384 | |||
385 | return 0; | ||
386 | } | ||
387 | |||
388 | static int __ftrace_make_nop_kernel(struct dyn_ftrace *rec, unsigned long addr) | ||
389 | { | ||
390 | unsigned long tramp, ip = rec->ip; | ||
391 | unsigned int op; | ||
392 | |||
393 | /* Read where this goes */ | ||
394 | if (probe_kernel_read(&op, (void *)ip, sizeof(int))) { | ||
395 | pr_err("Fetching opcode failed.\n"); | ||
396 | return -EFAULT; | ||
397 | } | ||
398 | |||
399 | /* Make sure that that this is still a 24bit jump */ | ||
400 | if (!is_bl_op(op)) { | ||
401 | pr_err("Not expected bl: opcode is %x\n", op); | ||
402 | return -EINVAL; | ||
403 | } | ||
404 | |||
405 | /* Let's find where the pointer goes */ | ||
406 | tramp = find_bl_target(ip, op); | ||
407 | |||
408 | pr_devel("ip:%lx jumps to %lx", ip, tramp); | ||
409 | |||
410 | if (setup_mcount_compiler_tramp(tramp)) { | ||
411 | /* Are other trampolines reachable? */ | ||
412 | if (!find_ftrace_tramp(ip)) { | ||
413 | pr_err("No ftrace trampolines reachable from %ps\n", | ||
414 | (void *)ip); | ||
415 | return -EINVAL; | ||
416 | } | ||
417 | } | ||
418 | |||
419 | if (patch_instruction((unsigned int *)ip, PPC_INST_NOP)) { | ||
420 | pr_err("Patching NOP failed.\n"); | ||
421 | return -EPERM; | ||
422 | } | ||
423 | |||
424 | return 0; | ||
425 | } | ||
426 | |||
273 | int ftrace_make_nop(struct module *mod, | 427 | int ftrace_make_nop(struct module *mod, |
274 | struct dyn_ftrace *rec, unsigned long addr) | 428 | struct dyn_ftrace *rec, unsigned long addr) |
275 | { | 429 | { |
@@ -286,7 +440,8 @@ int ftrace_make_nop(struct module *mod, | |||
286 | old = ftrace_call_replace(ip, addr, 1); | 440 | old = ftrace_call_replace(ip, addr, 1); |
287 | new = PPC_INST_NOP; | 441 | new = PPC_INST_NOP; |
288 | return ftrace_modify_code(ip, old, new); | 442 | return ftrace_modify_code(ip, old, new); |
289 | } | 443 | } else if (core_kernel_text(ip)) |
444 | return __ftrace_make_nop_kernel(rec, addr); | ||
290 | 445 | ||
291 | #ifdef CONFIG_MODULES | 446 | #ifdef CONFIG_MODULES |
292 | /* | 447 | /* |
@@ -456,6 +611,53 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) | |||
456 | #endif /* CONFIG_PPC64 */ | 611 | #endif /* CONFIG_PPC64 */ |
457 | #endif /* CONFIG_MODULES */ | 612 | #endif /* CONFIG_MODULES */ |
458 | 613 | ||
614 | static int __ftrace_make_call_kernel(struct dyn_ftrace *rec, unsigned long addr) | ||
615 | { | ||
616 | unsigned int op; | ||
617 | void *ip = (void *)rec->ip; | ||
618 | unsigned long tramp, entry, ptr; | ||
619 | |||
620 | /* Make sure we're being asked to patch branch to a known ftrace addr */ | ||
621 | entry = ppc_global_function_entry((void *)ftrace_caller); | ||
622 | ptr = ppc_global_function_entry((void *)addr); | ||
623 | |||
624 | if (ptr != entry) { | ||
625 | #ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS | ||
626 | entry = ppc_global_function_entry((void *)ftrace_regs_caller); | ||
627 | if (ptr != entry) { | ||
628 | #endif | ||
629 | pr_err("Unknown ftrace addr to patch: %ps\n", (void *)ptr); | ||
630 | return -EINVAL; | ||
631 | #ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS | ||
632 | } | ||
633 | #endif | ||
634 | } | ||
635 | |||
636 | /* Make sure we have a nop */ | ||
637 | if (probe_kernel_read(&op, ip, sizeof(op))) { | ||
638 | pr_err("Unable to read ftrace location %p\n", ip); | ||
639 | return -EFAULT; | ||
640 | } | ||
641 | |||
642 | if (op != PPC_INST_NOP) { | ||
643 | pr_err("Unexpected call sequence at %p: %x\n", ip, op); | ||
644 | return -EINVAL; | ||
645 | } | ||
646 | |||
647 | tramp = find_ftrace_tramp((unsigned long)ip); | ||
648 | if (!tramp) { | ||
649 | pr_err("No ftrace trampolines reachable from %ps\n", ip); | ||
650 | return -EINVAL; | ||
651 | } | ||
652 | |||
653 | if (patch_branch(ip, tramp, BRANCH_SET_LINK)) { | ||
654 | pr_err("Error patching branch to ftrace tramp!\n"); | ||
655 | return -EINVAL; | ||
656 | } | ||
657 | |||
658 | return 0; | ||
659 | } | ||
660 | |||
459 | int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) | 661 | int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) |
460 | { | 662 | { |
461 | unsigned long ip = rec->ip; | 663 | unsigned long ip = rec->ip; |
@@ -471,7 +673,8 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) | |||
471 | old = PPC_INST_NOP; | 673 | old = PPC_INST_NOP; |
472 | new = ftrace_call_replace(ip, addr, 1); | 674 | new = ftrace_call_replace(ip, addr, 1); |
473 | return ftrace_modify_code(ip, old, new); | 675 | return ftrace_modify_code(ip, old, new); |
474 | } | 676 | } else if (core_kernel_text(ip)) |
677 | return __ftrace_make_call_kernel(rec, addr); | ||
475 | 678 | ||
476 | #ifdef CONFIG_MODULES | 679 | #ifdef CONFIG_MODULES |
477 | /* | 680 | /* |
@@ -603,6 +806,12 @@ int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr, | |||
603 | old = ftrace_call_replace(ip, old_addr, 1); | 806 | old = ftrace_call_replace(ip, old_addr, 1); |
604 | new = ftrace_call_replace(ip, addr, 1); | 807 | new = ftrace_call_replace(ip, addr, 1); |
605 | return ftrace_modify_code(ip, old, new); | 808 | return ftrace_modify_code(ip, old, new); |
809 | } else if (core_kernel_text(ip)) { | ||
810 | /* | ||
811 | * We always patch out of range locations to go to the regs | ||
812 | * variant, so there is nothing to do here | ||
813 | */ | ||
814 | return 0; | ||
606 | } | 815 | } |
607 | 816 | ||
608 | #ifdef CONFIG_MODULES | 817 | #ifdef CONFIG_MODULES |
@@ -654,10 +863,54 @@ void arch_ftrace_update_code(int command) | |||
654 | ftrace_modify_all_code(command); | 863 | ftrace_modify_all_code(command); |
655 | } | 864 | } |
656 | 865 | ||
866 | #ifdef CONFIG_PPC64 | ||
867 | #define PACATOC offsetof(struct paca_struct, kernel_toc) | ||
868 | |||
869 | #define PPC_LO(v) ((v) & 0xffff) | ||
870 | #define PPC_HI(v) (((v) >> 16) & 0xffff) | ||
871 | #define PPC_HA(v) PPC_HI ((v) + 0x8000) | ||
872 | |||
873 | extern unsigned int ftrace_tramp_text[], ftrace_tramp_init[]; | ||
874 | |||
875 | int __init ftrace_dyn_arch_init(void) | ||
876 | { | ||
877 | int i; | ||
878 | unsigned int *tramp[] = { ftrace_tramp_text, ftrace_tramp_init }; | ||
879 | u32 stub_insns[] = { | ||
880 | 0xe98d0000 | PACATOC, /* ld r12,PACATOC(r13) */ | ||
881 | 0x3d8c0000, /* addis r12,r12,<high> */ | ||
882 | 0x398c0000, /* addi r12,r12,<low> */ | ||
883 | 0x7d8903a6, /* mtctr r12 */ | ||
884 | 0x4e800420, /* bctr */ | ||
885 | }; | ||
886 | #ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS | ||
887 | unsigned long addr = ppc_global_function_entry((void *)ftrace_regs_caller); | ||
888 | #else | ||
889 | unsigned long addr = ppc_global_function_entry((void *)ftrace_caller); | ||
890 | #endif | ||
891 | long reladdr = addr - kernel_toc_addr(); | ||
892 | |||
893 | if (reladdr > 0x7FFFFFFF || reladdr < -(0x80000000L)) { | ||
894 | pr_err("Address of %ps out of range of kernel_toc.\n", | ||
895 | (void *)addr); | ||
896 | return -1; | ||
897 | } | ||
898 | |||
899 | for (i = 0; i < 2; i++) { | ||
900 | memcpy(tramp[i], stub_insns, sizeof(stub_insns)); | ||
901 | tramp[i][1] |= PPC_HA(reladdr); | ||
902 | tramp[i][2] |= PPC_LO(reladdr); | ||
903 | add_ftrace_tramp((unsigned long)tramp[i]); | ||
904 | } | ||
905 | |||
906 | return 0; | ||
907 | } | ||
908 | #else | ||
657 | int __init ftrace_dyn_arch_init(void) | 909 | int __init ftrace_dyn_arch_init(void) |
658 | { | 910 | { |
659 | return 0; | 911 | return 0; |
660 | } | 912 | } |
913 | #endif | ||
661 | #endif /* CONFIG_DYNAMIC_FTRACE */ | 914 | #endif /* CONFIG_DYNAMIC_FTRACE */ |
662 | 915 | ||
663 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | 916 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER |
diff --git a/arch/powerpc/kernel/trace/ftrace_64.S b/arch/powerpc/kernel/trace/ftrace_64.S index e25f77c10a72..1782af2d1496 100644 --- a/arch/powerpc/kernel/trace/ftrace_64.S +++ b/arch/powerpc/kernel/trace/ftrace_64.S | |||
@@ -14,6 +14,18 @@ | |||
14 | #include <asm/ppc-opcode.h> | 14 | #include <asm/ppc-opcode.h> |
15 | #include <asm/export.h> | 15 | #include <asm/export.h> |
16 | 16 | ||
17 | .pushsection ".tramp.ftrace.text","aw",@progbits; | ||
18 | .globl ftrace_tramp_text | ||
19 | ftrace_tramp_text: | ||
20 | .space 64 | ||
21 | .popsection | ||
22 | |||
23 | .pushsection ".tramp.ftrace.init","aw",@progbits; | ||
24 | .globl ftrace_tramp_init | ||
25 | ftrace_tramp_init: | ||
26 | .space 64 | ||
27 | .popsection | ||
28 | |||
17 | _GLOBAL(mcount) | 29 | _GLOBAL(mcount) |
18 | _GLOBAL(_mcount) | 30 | _GLOBAL(_mcount) |
19 | EXPORT_SYMBOL(_mcount) | 31 | EXPORT_SYMBOL(_mcount) |
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index ab1bd06d7c44..9a86572db1ef 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c | |||
@@ -247,8 +247,6 @@ static void oops_end(unsigned long flags, struct pt_regs *regs, | |||
247 | mdelay(MSEC_PER_SEC); | 247 | mdelay(MSEC_PER_SEC); |
248 | } | 248 | } |
249 | 249 | ||
250 | if (in_interrupt()) | ||
251 | panic("Fatal exception in interrupt"); | ||
252 | if (panic_on_oops) | 250 | if (panic_on_oops) |
253 | panic("Fatal exception"); | 251 | panic("Fatal exception"); |
254 | do_exit(signr); | 252 | do_exit(signr); |
@@ -535,10 +533,10 @@ int machine_check_e500mc(struct pt_regs *regs) | |||
535 | printk("Caused by (from MCSR=%lx): ", reason); | 533 | printk("Caused by (from MCSR=%lx): ", reason); |
536 | 534 | ||
537 | if (reason & MCSR_MCP) | 535 | if (reason & MCSR_MCP) |
538 | printk("Machine Check Signal\n"); | 536 | pr_cont("Machine Check Signal\n"); |
539 | 537 | ||
540 | if (reason & MCSR_ICPERR) { | 538 | if (reason & MCSR_ICPERR) { |
541 | printk("Instruction Cache Parity Error\n"); | 539 | pr_cont("Instruction Cache Parity Error\n"); |
542 | 540 | ||
543 | /* | 541 | /* |
544 | * This is recoverable by invalidating the i-cache. | 542 | * This is recoverable by invalidating the i-cache. |
@@ -556,7 +554,7 @@ int machine_check_e500mc(struct pt_regs *regs) | |||
556 | } | 554 | } |
557 | 555 | ||
558 | if (reason & MCSR_DCPERR_MC) { | 556 | if (reason & MCSR_DCPERR_MC) { |
559 | printk("Data Cache Parity Error\n"); | 557 | pr_cont("Data Cache Parity Error\n"); |
560 | 558 | ||
561 | /* | 559 | /* |
562 | * In write shadow mode we auto-recover from the error, but it | 560 | * In write shadow mode we auto-recover from the error, but it |
@@ -575,38 +573,38 @@ int machine_check_e500mc(struct pt_regs *regs) | |||
575 | } | 573 | } |
576 | 574 | ||
577 | if (reason & MCSR_L2MMU_MHIT) { | 575 | if (reason & MCSR_L2MMU_MHIT) { |
578 | printk("Hit on multiple TLB entries\n"); | 576 | pr_cont("Hit on multiple TLB entries\n"); |
579 | recoverable = 0; | 577 | recoverable = 0; |
580 | } | 578 | } |
581 | 579 | ||
582 | if (reason & MCSR_NMI) | 580 | if (reason & MCSR_NMI) |
583 | printk("Non-maskable interrupt\n"); | 581 | pr_cont("Non-maskable interrupt\n"); |
584 | 582 | ||
585 | if (reason & MCSR_IF) { | 583 | if (reason & MCSR_IF) { |
586 | printk("Instruction Fetch Error Report\n"); | 584 | pr_cont("Instruction Fetch Error Report\n"); |
587 | recoverable = 0; | 585 | recoverable = 0; |
588 | } | 586 | } |
589 | 587 | ||
590 | if (reason & MCSR_LD) { | 588 | if (reason & MCSR_LD) { |
591 | printk("Load Error Report\n"); | 589 | pr_cont("Load Error Report\n"); |
592 | recoverable = 0; | 590 | recoverable = 0; |
593 | } | 591 | } |
594 | 592 | ||
595 | if (reason & MCSR_ST) { | 593 | if (reason & MCSR_ST) { |
596 | printk("Store Error Report\n"); | 594 | pr_cont("Store Error Report\n"); |
597 | recoverable = 0; | 595 | recoverable = 0; |
598 | } | 596 | } |
599 | 597 | ||
600 | if (reason & MCSR_LDG) { | 598 | if (reason & MCSR_LDG) { |
601 | printk("Guarded Load Error Report\n"); | 599 | pr_cont("Guarded Load Error Report\n"); |
602 | recoverable = 0; | 600 | recoverable = 0; |
603 | } | 601 | } |
604 | 602 | ||
605 | if (reason & MCSR_TLBSYNC) | 603 | if (reason & MCSR_TLBSYNC) |
606 | printk("Simultaneous tlbsync operations\n"); | 604 | pr_cont("Simultaneous tlbsync operations\n"); |
607 | 605 | ||
608 | if (reason & MCSR_BSL2_ERR) { | 606 | if (reason & MCSR_BSL2_ERR) { |
609 | printk("Level 2 Cache Error\n"); | 607 | pr_cont("Level 2 Cache Error\n"); |
610 | recoverable = 0; | 608 | recoverable = 0; |
611 | } | 609 | } |
612 | 610 | ||
@@ -616,7 +614,7 @@ int machine_check_e500mc(struct pt_regs *regs) | |||
616 | addr = mfspr(SPRN_MCAR); | 614 | addr = mfspr(SPRN_MCAR); |
617 | addr |= (u64)mfspr(SPRN_MCARU) << 32; | 615 | addr |= (u64)mfspr(SPRN_MCARU) << 32; |
618 | 616 | ||
619 | printk("Machine Check %s Address: %#llx\n", | 617 | pr_cont("Machine Check %s Address: %#llx\n", |
620 | reason & MCSR_MEA ? "Effective" : "Physical", addr); | 618 | reason & MCSR_MEA ? "Effective" : "Physical", addr); |
621 | } | 619 | } |
622 | 620 | ||
@@ -640,29 +638,29 @@ int machine_check_e500(struct pt_regs *regs) | |||
640 | printk("Caused by (from MCSR=%lx): ", reason); | 638 | printk("Caused by (from MCSR=%lx): ", reason); |
641 | 639 | ||
642 | if (reason & MCSR_MCP) | 640 | if (reason & MCSR_MCP) |
643 | printk("Machine Check Signal\n"); | 641 | pr_cont("Machine Check Signal\n"); |
644 | if (reason & MCSR_ICPERR) | 642 | if (reason & MCSR_ICPERR) |
645 | printk("Instruction Cache Parity Error\n"); | 643 | pr_cont("Instruction Cache Parity Error\n"); |
646 | if (reason & MCSR_DCP_PERR) | 644 | if (reason & MCSR_DCP_PERR) |
647 | printk("Data Cache Push Parity Error\n"); | 645 | pr_cont("Data Cache Push Parity Error\n"); |
648 | if (reason & MCSR_DCPERR) | 646 | if (reason & MCSR_DCPERR) |
649 | printk("Data Cache Parity Error\n"); | 647 | pr_cont("Data Cache Parity Error\n"); |
650 | if (reason & MCSR_BUS_IAERR) | 648 | if (reason & MCSR_BUS_IAERR) |
651 | printk("Bus - Instruction Address Error\n"); | 649 | pr_cont("Bus - Instruction Address Error\n"); |
652 | if (reason & MCSR_BUS_RAERR) | 650 | if (reason & MCSR_BUS_RAERR) |
653 | printk("Bus - Read Address Error\n"); | 651 | pr_cont("Bus - Read Address Error\n"); |
654 | if (reason & MCSR_BUS_WAERR) | 652 | if (reason & MCSR_BUS_WAERR) |
655 | printk("Bus - Write Address Error\n"); | 653 | pr_cont("Bus - Write Address Error\n"); |
656 | if (reason & MCSR_BUS_IBERR) | 654 | if (reason & MCSR_BUS_IBERR) |
657 | printk("Bus - Instruction Data Error\n"); | 655 | pr_cont("Bus - Instruction Data Error\n"); |
658 | if (reason & MCSR_BUS_RBERR) | 656 | if (reason & MCSR_BUS_RBERR) |
659 | printk("Bus - Read Data Bus Error\n"); | 657 | pr_cont("Bus - Read Data Bus Error\n"); |
660 | if (reason & MCSR_BUS_WBERR) | 658 | if (reason & MCSR_BUS_WBERR) |
661 | printk("Bus - Write Data Bus Error\n"); | 659 | pr_cont("Bus - Write Data Bus Error\n"); |
662 | if (reason & MCSR_BUS_IPERR) | 660 | if (reason & MCSR_BUS_IPERR) |
663 | printk("Bus - Instruction Parity Error\n"); | 661 | pr_cont("Bus - Instruction Parity Error\n"); |
664 | if (reason & MCSR_BUS_RPERR) | 662 | if (reason & MCSR_BUS_RPERR) |
665 | printk("Bus - Read Parity Error\n"); | 663 | pr_cont("Bus - Read Parity Error\n"); |
666 | 664 | ||
667 | return 0; | 665 | return 0; |
668 | } | 666 | } |
@@ -680,19 +678,19 @@ int machine_check_e200(struct pt_regs *regs) | |||
680 | printk("Caused by (from MCSR=%lx): ", reason); | 678 | printk("Caused by (from MCSR=%lx): ", reason); |
681 | 679 | ||
682 | if (reason & MCSR_MCP) | 680 | if (reason & MCSR_MCP) |
683 | printk("Machine Check Signal\n"); | 681 | pr_cont("Machine Check Signal\n"); |
684 | if (reason & MCSR_CP_PERR) | 682 | if (reason & MCSR_CP_PERR) |
685 | printk("Cache Push Parity Error\n"); | 683 | pr_cont("Cache Push Parity Error\n"); |
686 | if (reason & MCSR_CPERR) | 684 | if (reason & MCSR_CPERR) |
687 | printk("Cache Parity Error\n"); | 685 | pr_cont("Cache Parity Error\n"); |
688 | if (reason & MCSR_EXCP_ERR) | 686 | if (reason & MCSR_EXCP_ERR) |
689 | printk("ISI, ITLB, or Bus Error on first instruction fetch for an exception handler\n"); | 687 | pr_cont("ISI, ITLB, or Bus Error on first instruction fetch for an exception handler\n"); |
690 | if (reason & MCSR_BUS_IRERR) | 688 | if (reason & MCSR_BUS_IRERR) |
691 | printk("Bus - Read Bus Error on instruction fetch\n"); | 689 | pr_cont("Bus - Read Bus Error on instruction fetch\n"); |
692 | if (reason & MCSR_BUS_DRERR) | 690 | if (reason & MCSR_BUS_DRERR) |
693 | printk("Bus - Read Bus Error on data load\n"); | 691 | pr_cont("Bus - Read Bus Error on data load\n"); |
694 | if (reason & MCSR_BUS_WRERR) | 692 | if (reason & MCSR_BUS_WRERR) |
695 | printk("Bus - Write Bus Error on buffered store or cache line push\n"); | 693 | pr_cont("Bus - Write Bus Error on buffered store or cache line push\n"); |
696 | 694 | ||
697 | return 0; | 695 | return 0; |
698 | } | 696 | } |
@@ -705,30 +703,30 @@ int machine_check_generic(struct pt_regs *regs) | |||
705 | printk("Caused by (from SRR1=%lx): ", reason); | 703 | printk("Caused by (from SRR1=%lx): ", reason); |
706 | switch (reason & 0x601F0000) { | 704 | switch (reason & 0x601F0000) { |
707 | case 0x80000: | 705 | case 0x80000: |
708 | printk("Machine check signal\n"); | 706 | pr_cont("Machine check signal\n"); |
709 | break; | 707 | break; |
710 | case 0: /* for 601 */ | 708 | case 0: /* for 601 */ |
711 | case 0x40000: | 709 | case 0x40000: |
712 | case 0x140000: /* 7450 MSS error and TEA */ | 710 | case 0x140000: /* 7450 MSS error and TEA */ |
713 | printk("Transfer error ack signal\n"); | 711 | pr_cont("Transfer error ack signal\n"); |
714 | break; | 712 | break; |
715 | case 0x20000: | 713 | case 0x20000: |
716 | printk("Data parity error signal\n"); | 714 | pr_cont("Data parity error signal\n"); |
717 | break; | 715 | break; |
718 | case 0x10000: | 716 | case 0x10000: |
719 | printk("Address parity error signal\n"); | 717 | pr_cont("Address parity error signal\n"); |
720 | break; | 718 | break; |
721 | case 0x20000000: | 719 | case 0x20000000: |
722 | printk("L1 Data Cache error\n"); | 720 | pr_cont("L1 Data Cache error\n"); |
723 | break; | 721 | break; |
724 | case 0x40000000: | 722 | case 0x40000000: |
725 | printk("L1 Instruction Cache error\n"); | 723 | pr_cont("L1 Instruction Cache error\n"); |
726 | break; | 724 | break; |
727 | case 0x00100000: | 725 | case 0x00100000: |
728 | printk("L2 data cache parity error\n"); | 726 | pr_cont("L2 data cache parity error\n"); |
729 | break; | 727 | break; |
730 | default: | 728 | default: |
731 | printk("Unknown values in msr\n"); | 729 | pr_cont("Unknown values in msr\n"); |
732 | } | 730 | } |
733 | return 0; | 731 | return 0; |
734 | } | 732 | } |
@@ -741,9 +739,7 @@ void machine_check_exception(struct pt_regs *regs) | |||
741 | if (!nested) | 739 | if (!nested) |
742 | nmi_enter(); | 740 | nmi_enter(); |
743 | 741 | ||
744 | /* 64s accounts the mce in machine_check_early when in HVMODE */ | 742 | __this_cpu_inc(irq_stat.mce_exceptions); |
745 | if (!IS_ENABLED(CONFIG_PPC_BOOK3S_64) || !cpu_has_feature(CPU_FTR_HVMODE)) | ||
746 | __this_cpu_inc(irq_stat.mce_exceptions); | ||
747 | 743 | ||
748 | add_taint(TAINT_MACHINE_CHECK, LOCKDEP_NOW_UNRELIABLE); | 744 | add_taint(TAINT_MACHINE_CHECK, LOCKDEP_NOW_UNRELIABLE); |
749 | 745 | ||
@@ -767,12 +763,17 @@ void machine_check_exception(struct pt_regs *regs) | |||
767 | if (check_io_access(regs)) | 763 | if (check_io_access(regs)) |
768 | goto bail; | 764 | goto bail; |
769 | 765 | ||
770 | die("Machine check", regs, SIGBUS); | ||
771 | |||
772 | /* Must die if the interrupt is not recoverable */ | 766 | /* Must die if the interrupt is not recoverable */ |
773 | if (!(regs->msr & MSR_RI)) | 767 | if (!(regs->msr & MSR_RI)) |
774 | nmi_panic(regs, "Unrecoverable Machine check"); | 768 | nmi_panic(regs, "Unrecoverable Machine check"); |
775 | 769 | ||
770 | if (!nested) | ||
771 | nmi_exit(); | ||
772 | |||
773 | die("Machine check", regs, SIGBUS); | ||
774 | |||
775 | return; | ||
776 | |||
776 | bail: | 777 | bail: |
777 | if (!nested) | 778 | if (!nested) |
778 | nmi_exit(); | 779 | nmi_exit(); |
@@ -1433,7 +1434,7 @@ void program_check_exception(struct pt_regs *regs) | |||
1433 | goto bail; | 1434 | goto bail; |
1434 | } else { | 1435 | } else { |
1435 | printk(KERN_EMERG "Unexpected TM Bad Thing exception " | 1436 | printk(KERN_EMERG "Unexpected TM Bad Thing exception " |
1436 | "at %lx (msr 0x%x)\n", regs->nip, reason); | 1437 | "at %lx (msr 0x%lx)\n", regs->nip, regs->msr); |
1437 | die("Unrecoverable exception", regs, SIGABRT); | 1438 | die("Unrecoverable exception", regs, SIGABRT); |
1438 | } | 1439 | } |
1439 | } | 1440 | } |
@@ -1547,14 +1548,6 @@ void StackOverflow(struct pt_regs *regs) | |||
1547 | panic("kernel stack overflow"); | 1548 | panic("kernel stack overflow"); |
1548 | } | 1549 | } |
1549 | 1550 | ||
1550 | void nonrecoverable_exception(struct pt_regs *regs) | ||
1551 | { | ||
1552 | printk(KERN_ERR "Non-recoverable exception at PC=%lx MSR=%lx\n", | ||
1553 | regs->nip, regs->msr); | ||
1554 | debugger(regs); | ||
1555 | die("nonrecoverable exception", regs, SIGKILL); | ||
1556 | } | ||
1557 | |||
1558 | void kernel_fp_unavailable_exception(struct pt_regs *regs) | 1551 | void kernel_fp_unavailable_exception(struct pt_regs *regs) |
1559 | { | 1552 | { |
1560 | enum ctx_state prev_state = exception_enter(); | 1553 | enum ctx_state prev_state = exception_enter(); |
@@ -1750,16 +1743,20 @@ void fp_unavailable_tm(struct pt_regs *regs) | |||
1750 | * checkpointed FP registers need to be loaded. | 1743 | * checkpointed FP registers need to be loaded. |
1751 | */ | 1744 | */ |
1752 | tm_reclaim_current(TM_CAUSE_FAC_UNAV); | 1745 | tm_reclaim_current(TM_CAUSE_FAC_UNAV); |
1753 | /* Reclaim didn't save out any FPRs to transact_fprs. */ | 1746 | |
1747 | /* | ||
1748 | * Reclaim initially saved out bogus (lazy) FPRs to ckfp_state, and | ||
1749 | * then it was overwrite by the thr->fp_state by tm_reclaim_thread(). | ||
1750 | * | ||
1751 | * At this point, ck{fp,vr}_state contains the exact values we want to | ||
1752 | * recheckpoint. | ||
1753 | */ | ||
1754 | 1754 | ||
1755 | /* Enable FP for the task: */ | 1755 | /* Enable FP for the task: */ |
1756 | current->thread.load_fp = 1; | 1756 | current->thread.load_fp = 1; |
1757 | 1757 | ||
1758 | /* This loads and recheckpoints the FP registers from | 1758 | /* |
1759 | * thread.fpr[]. They will remain in registers after the | 1759 | * Recheckpoint all the checkpointed ckpt, ck{fp, vr}_state registers. |
1760 | * checkpoint so we don't need to reload them after. | ||
1761 | * If VMX is in use, the VRs now hold checkpointed values, | ||
1762 | * so we don't want to load the VRs from the thread_struct. | ||
1763 | */ | 1760 | */ |
1764 | tm_recheckpoint(¤t->thread); | 1761 | tm_recheckpoint(¤t->thread); |
1765 | } | 1762 | } |
@@ -2086,8 +2083,8 @@ void SPEFloatingPointRoundException(struct pt_regs *regs) | |||
2086 | */ | 2083 | */ |
2087 | void unrecoverable_exception(struct pt_regs *regs) | 2084 | void unrecoverable_exception(struct pt_regs *regs) |
2088 | { | 2085 | { |
2089 | printk(KERN_EMERG "Unrecoverable exception %lx at %lx\n", | 2086 | pr_emerg("Unrecoverable exception %lx at %lx (msr=%lx)\n", |
2090 | regs->trap, regs->nip); | 2087 | regs->trap, regs->nip, regs->msr); |
2091 | die("Unrecoverable exception", regs, SIGABRT); | 2088 | die("Unrecoverable exception", regs, SIGABRT); |
2092 | } | 2089 | } |
2093 | NOKPROBE_SYMBOL(unrecoverable_exception); | 2090 | NOKPROBE_SYMBOL(unrecoverable_exception); |
diff --git a/arch/powerpc/kernel/vdso32/datapage.S b/arch/powerpc/kernel/vdso32/datapage.S index 3745113fcc65..2a7eb5452aba 100644 --- a/arch/powerpc/kernel/vdso32/datapage.S +++ b/arch/powerpc/kernel/vdso32/datapage.S | |||
@@ -37,6 +37,7 @@ data_page_branch: | |||
37 | mtlr r0 | 37 | mtlr r0 |
38 | addi r3, r3, __kernel_datapage_offset-data_page_branch | 38 | addi r3, r3, __kernel_datapage_offset-data_page_branch |
39 | lwz r0,0(r3) | 39 | lwz r0,0(r3) |
40 | .cfi_restore lr | ||
40 | add r3,r0,r3 | 41 | add r3,r0,r3 |
41 | blr | 42 | blr |
42 | .cfi_endproc | 43 | .cfi_endproc |
diff --git a/arch/powerpc/kernel/vdso32/gettimeofday.S b/arch/powerpc/kernel/vdso32/gettimeofday.S index 769c2624e0a6..1e0bc5955a40 100644 --- a/arch/powerpc/kernel/vdso32/gettimeofday.S +++ b/arch/powerpc/kernel/vdso32/gettimeofday.S | |||
@@ -139,6 +139,7 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime) | |||
139 | */ | 139 | */ |
140 | 99: | 140 | 99: |
141 | li r0,__NR_clock_gettime | 141 | li r0,__NR_clock_gettime |
142 | .cfi_restore lr | ||
142 | sc | 143 | sc |
143 | blr | 144 | blr |
144 | .cfi_endproc | 145 | .cfi_endproc |
diff --git a/arch/powerpc/kernel/vdso64/datapage.S b/arch/powerpc/kernel/vdso64/datapage.S index abf17feffe40..bf9668691511 100644 --- a/arch/powerpc/kernel/vdso64/datapage.S +++ b/arch/powerpc/kernel/vdso64/datapage.S | |||
@@ -37,6 +37,7 @@ data_page_branch: | |||
37 | mtlr r0 | 37 | mtlr r0 |
38 | addi r3, r3, __kernel_datapage_offset-data_page_branch | 38 | addi r3, r3, __kernel_datapage_offset-data_page_branch |
39 | lwz r0,0(r3) | 39 | lwz r0,0(r3) |
40 | .cfi_restore lr | ||
40 | add r3,r0,r3 | 41 | add r3,r0,r3 |
41 | blr | 42 | blr |
42 | .cfi_endproc | 43 | .cfi_endproc |
diff --git a/arch/powerpc/kernel/vdso64/gettimeofday.S b/arch/powerpc/kernel/vdso64/gettimeofday.S index c002adcc694c..a4ed9edfd5f0 100644 --- a/arch/powerpc/kernel/vdso64/gettimeofday.S +++ b/arch/powerpc/kernel/vdso64/gettimeofday.S | |||
@@ -169,6 +169,7 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime) | |||
169 | */ | 169 | */ |
170 | 99: | 170 | 99: |
171 | li r0,__NR_clock_gettime | 171 | li r0,__NR_clock_gettime |
172 | .cfi_restore lr | ||
172 | sc | 173 | sc |
173 | blr | 174 | blr |
174 | .cfi_endproc | 175 | .cfi_endproc |
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S index 105a976323aa..434581bcd5b4 100644 --- a/arch/powerpc/kernel/vmlinux.lds.S +++ b/arch/powerpc/kernel/vmlinux.lds.S | |||
@@ -4,6 +4,9 @@ | |||
4 | #else | 4 | #else |
5 | #define PROVIDE32(x) PROVIDE(x) | 5 | #define PROVIDE32(x) PROVIDE(x) |
6 | #endif | 6 | #endif |
7 | |||
8 | #define BSS_FIRST_SECTIONS *(.bss.prominit) | ||
9 | |||
7 | #include <asm/page.h> | 10 | #include <asm/page.h> |
8 | #include <asm-generic/vmlinux.lds.h> | 11 | #include <asm-generic/vmlinux.lds.h> |
9 | #include <asm/cache.h> | 12 | #include <asm/cache.h> |
@@ -99,6 +102,9 @@ SECTIONS | |||
99 | #endif | 102 | #endif |
100 | /* careful! __ftr_alt_* sections need to be close to .text */ | 103 | /* careful! __ftr_alt_* sections need to be close to .text */ |
101 | *(.text.hot TEXT_MAIN .text.fixup .text.unlikely .fixup __ftr_alt_* .ref.text); | 104 | *(.text.hot TEXT_MAIN .text.fixup .text.unlikely .fixup __ftr_alt_* .ref.text); |
105 | #ifdef CONFIG_PPC64 | ||
106 | *(.tramp.ftrace.text); | ||
107 | #endif | ||
102 | SCHED_TEXT | 108 | SCHED_TEXT |
103 | CPUIDLE_TEXT | 109 | CPUIDLE_TEXT |
104 | LOCK_TEXT | 110 | LOCK_TEXT |
@@ -181,7 +187,15 @@ SECTIONS | |||
181 | */ | 187 | */ |
182 | . = ALIGN(STRICT_ALIGN_SIZE); | 188 | . = ALIGN(STRICT_ALIGN_SIZE); |
183 | __init_begin = .; | 189 | __init_begin = .; |
184 | INIT_TEXT_SECTION(PAGE_SIZE) :kernel | 190 | . = ALIGN(PAGE_SIZE); |
191 | .init.text : AT(ADDR(.init.text) - LOAD_OFFSET) { | ||
192 | _sinittext = .; | ||
193 | INIT_TEXT | ||
194 | _einittext = .; | ||
195 | #ifdef CONFIG_PPC64 | ||
196 | *(.tramp.ftrace.init); | ||
197 | #endif | ||
198 | } :kernel | ||
185 | 199 | ||
186 | /* .exit.text is discarded at runtime, not link time, | 200 | /* .exit.text is discarded at runtime, not link time, |
187 | * to deal with references from __bug_table | 201 | * to deal with references from __bug_table |
diff --git a/arch/powerpc/kvm/Makefile b/arch/powerpc/kvm/Makefile index e814f40ab836..64f1135e7732 100644 --- a/arch/powerpc/kvm/Makefile +++ b/arch/powerpc/kvm/Makefile | |||
@@ -3,8 +3,6 @@ | |||
3 | # Makefile for Kernel-based Virtual Machine module | 3 | # Makefile for Kernel-based Virtual Machine module |
4 | # | 4 | # |
5 | 5 | ||
6 | subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror | ||
7 | |||
8 | ccflags-y := -Ivirt/kvm -Iarch/powerpc/kvm | 6 | ccflags-y := -Ivirt/kvm -Iarch/powerpc/kvm |
9 | KVM := ../../../virt/kvm | 7 | KVM := ../../../virt/kvm |
10 | 8 | ||
diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile index 670286808928..3bf9fc6fd36c 100644 --- a/arch/powerpc/lib/Makefile +++ b/arch/powerpc/lib/Makefile | |||
@@ -3,8 +3,6 @@ | |||
3 | # Makefile for ppc-specific library files.. | 3 | # Makefile for ppc-specific library files.. |
4 | # | 4 | # |
5 | 5 | ||
6 | subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror | ||
7 | |||
8 | ccflags-$(CONFIG_PPC64) := $(NO_MINIMAL_TOC) | 6 | ccflags-$(CONFIG_PPC64) := $(NO_MINIMAL_TOC) |
9 | 7 | ||
10 | CFLAGS_REMOVE_code-patching.o = $(CC_FLAGS_FTRACE) | 8 | CFLAGS_REMOVE_code-patching.o = $(CC_FLAGS_FTRACE) |
@@ -14,6 +12,8 @@ obj-y += string.o alloc.o code-patching.o feature-fixups.o | |||
14 | 12 | ||
15 | obj-$(CONFIG_PPC32) += div64.o copy_32.o crtsavres.o strlen_32.o | 13 | obj-$(CONFIG_PPC32) += div64.o copy_32.o crtsavres.o strlen_32.o |
16 | 14 | ||
15 | obj-$(CONFIG_FUNCTION_ERROR_INJECTION) += error-inject.o | ||
16 | |||
17 | # See corresponding test in arch/powerpc/Makefile | 17 | # See corresponding test in arch/powerpc/Makefile |
18 | # 64-bit linker creates .sfpr on demand for final link (vmlinux), | 18 | # 64-bit linker creates .sfpr on demand for final link (vmlinux), |
19 | # so it is only needed for modules, and only for older linkers which | 19 | # so it is only needed for modules, and only for older linkers which |
diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c index 5ffee298745f..89502cbccb1b 100644 --- a/arch/powerpc/lib/code-patching.c +++ b/arch/powerpc/lib/code-patching.c | |||
@@ -98,8 +98,7 @@ static int map_patch_area(void *addr, unsigned long text_poke_addr) | |||
98 | else | 98 | else |
99 | pfn = __pa_symbol(addr) >> PAGE_SHIFT; | 99 | pfn = __pa_symbol(addr) >> PAGE_SHIFT; |
100 | 100 | ||
101 | err = map_kernel_page(text_poke_addr, (pfn << PAGE_SHIFT), | 101 | err = map_kernel_page(text_poke_addr, (pfn << PAGE_SHIFT), PAGE_KERNEL); |
102 | pgprot_val(PAGE_KERNEL)); | ||
103 | 102 | ||
104 | pr_devel("Mapped addr %lx with pfn %lx:%d\n", text_poke_addr, pfn, err); | 103 | pr_devel("Mapped addr %lx with pfn %lx:%d\n", text_poke_addr, pfn, err); |
105 | if (err) | 104 | if (err) |
diff --git a/arch/powerpc/lib/error-inject.c b/arch/powerpc/lib/error-inject.c new file mode 100644 index 000000000000..407b992fb02f --- /dev/null +++ b/arch/powerpc/lib/error-inject.c | |||
@@ -0,0 +1,16 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0+ | ||
2 | |||
3 | #include <linux/error-injection.h> | ||
4 | #include <linux/kprobes.h> | ||
5 | #include <linux/uaccess.h> | ||
6 | |||
7 | void override_function_with_return(struct pt_regs *regs) | ||
8 | { | ||
9 | /* | ||
10 | * Emulate 'blr'. 'regs' represents the state on entry of a predefined | ||
11 | * function in the kernel/module, captured on a kprobe. We don't need | ||
12 | * to worry about 32-bit userspace on a 64-bit kernel. | ||
13 | */ | ||
14 | regs->nip = regs->link; | ||
15 | } | ||
16 | NOKPROBE_SYMBOL(override_function_with_return); | ||
diff --git a/arch/powerpc/lib/mem_64.S b/arch/powerpc/lib/mem_64.S index ec531de99996..3c3be02f33b7 100644 --- a/arch/powerpc/lib/mem_64.S +++ b/arch/powerpc/lib/mem_64.S | |||
@@ -40,7 +40,7 @@ _GLOBAL(memset) | |||
40 | .Lms: PPC_MTOCRF(1,r0) | 40 | .Lms: PPC_MTOCRF(1,r0) |
41 | mr r6,r3 | 41 | mr r6,r3 |
42 | blt cr1,8f | 42 | blt cr1,8f |
43 | beq+ 3f /* if already 8-byte aligned */ | 43 | beq 3f /* if already 8-byte aligned */ |
44 | subf r5,r0,r5 | 44 | subf r5,r0,r5 |
45 | bf 31,1f | 45 | bf 31,1f |
46 | stb r4,0(r6) | 46 | stb r4,0(r6) |
@@ -85,7 +85,7 @@ _GLOBAL(memset) | |||
85 | addi r6,r6,8 | 85 | addi r6,r6,8 |
86 | 8: cmpwi r5,0 | 86 | 8: cmpwi r5,0 |
87 | PPC_MTOCRF(1,r5) | 87 | PPC_MTOCRF(1,r5) |
88 | beqlr+ | 88 | beqlr |
89 | bf 29,9f | 89 | bf 29,9f |
90 | stw r4,0(r6) | 90 | stw r4,0(r6) |
91 | addi r6,r6,4 | 91 | addi r6,r6,4 |
diff --git a/arch/powerpc/mm/8xx_mmu.c b/arch/powerpc/mm/8xx_mmu.c index cf77d755246d..36484a2ef915 100644 --- a/arch/powerpc/mm/8xx_mmu.c +++ b/arch/powerpc/mm/8xx_mmu.c | |||
@@ -67,7 +67,7 @@ void __init MMU_init_hw(void) | |||
67 | /* PIN up to the 3 first 8Mb after IMMR in DTLB table */ | 67 | /* PIN up to the 3 first 8Mb after IMMR in DTLB table */ |
68 | #ifdef CONFIG_PIN_TLB_DATA | 68 | #ifdef CONFIG_PIN_TLB_DATA |
69 | unsigned long ctr = mfspr(SPRN_MD_CTR) & 0xfe000000; | 69 | unsigned long ctr = mfspr(SPRN_MD_CTR) & 0xfe000000; |
70 | unsigned long flags = 0xf0 | MD_SPS16K | _PAGE_PRIVILEGED | _PAGE_DIRTY; | 70 | unsigned long flags = 0xf0 | MD_SPS16K | _PAGE_SH | _PAGE_DIRTY; |
71 | #ifdef CONFIG_PIN_TLB_IMMR | 71 | #ifdef CONFIG_PIN_TLB_IMMR |
72 | int i = 29; | 72 | int i = 29; |
73 | #else | 73 | #else |
@@ -91,11 +91,10 @@ static void __init mmu_mapin_immr(void) | |||
91 | { | 91 | { |
92 | unsigned long p = PHYS_IMMR_BASE; | 92 | unsigned long p = PHYS_IMMR_BASE; |
93 | unsigned long v = VIRT_IMMR_BASE; | 93 | unsigned long v = VIRT_IMMR_BASE; |
94 | unsigned long f = pgprot_val(PAGE_KERNEL_NCG); | ||
95 | int offset; | 94 | int offset; |
96 | 95 | ||
97 | for (offset = 0; offset < IMMR_SIZE; offset += PAGE_SIZE) | 96 | for (offset = 0; offset < IMMR_SIZE; offset += PAGE_SIZE) |
98 | map_kernel_page(v + offset, p + offset, f); | 97 | map_kernel_page(v + offset, p + offset, PAGE_KERNEL_NCG); |
99 | } | 98 | } |
100 | 99 | ||
101 | /* Address of instructions to patch */ | 100 | /* Address of instructions to patch */ |
diff --git a/arch/powerpc/mm/Makefile b/arch/powerpc/mm/Makefile index cdf6a9960046..ca96e7be4d0e 100644 --- a/arch/powerpc/mm/Makefile +++ b/arch/powerpc/mm/Makefile | |||
@@ -3,10 +3,10 @@ | |||
3 | # Makefile for the linux ppc-specific parts of the memory manager. | 3 | # Makefile for the linux ppc-specific parts of the memory manager. |
4 | # | 4 | # |
5 | 5 | ||
6 | subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror | ||
7 | |||
8 | ccflags-$(CONFIG_PPC64) := $(NO_MINIMAL_TOC) | 6 | ccflags-$(CONFIG_PPC64) := $(NO_MINIMAL_TOC) |
9 | 7 | ||
8 | CFLAGS_REMOVE_slb.o = $(CC_FLAGS_FTRACE) | ||
9 | |||
10 | obj-y := fault.o mem.o pgtable.o mmap.o \ | 10 | obj-y := fault.o mem.o pgtable.o mmap.o \ |
11 | init_$(BITS).o pgtable_$(BITS).o \ | 11 | init_$(BITS).o pgtable_$(BITS).o \ |
12 | init-common.o mmu_context.o drmem.o | 12 | init-common.o mmu_context.o drmem.o |
@@ -15,7 +15,7 @@ obj-$(CONFIG_PPC_MMU_NOHASH) += mmu_context_nohash.o tlb_nohash.o \ | |||
15 | obj-$(CONFIG_PPC_BOOK3E) += tlb_low_$(BITS)e.o | 15 | obj-$(CONFIG_PPC_BOOK3E) += tlb_low_$(BITS)e.o |
16 | hash64-$(CONFIG_PPC_NATIVE) := hash_native_64.o | 16 | hash64-$(CONFIG_PPC_NATIVE) := hash_native_64.o |
17 | obj-$(CONFIG_PPC_BOOK3E_64) += pgtable-book3e.o | 17 | obj-$(CONFIG_PPC_BOOK3E_64) += pgtable-book3e.o |
18 | obj-$(CONFIG_PPC_BOOK3S_64) += pgtable-hash64.o hash_utils_64.o slb_low.o slb.o $(hash64-y) mmu_context_book3s64.o pgtable-book3s64.o | 18 | obj-$(CONFIG_PPC_BOOK3S_64) += pgtable-hash64.o hash_utils_64.o slb.o $(hash64-y) mmu_context_book3s64.o pgtable-book3s64.o |
19 | obj-$(CONFIG_PPC_RADIX_MMU) += pgtable-radix.o tlb-radix.o | 19 | obj-$(CONFIG_PPC_RADIX_MMU) += pgtable-radix.o tlb-radix.o |
20 | obj-$(CONFIG_PPC_STD_MMU_32) += ppc_mmu_32.o hash_low_32.o mmu_context_hash32.o | 20 | obj-$(CONFIG_PPC_STD_MMU_32) += ppc_mmu_32.o hash_low_32.o mmu_context_hash32.o |
21 | obj-$(CONFIG_PPC_STD_MMU) += tlb_hash$(BITS).o | 21 | obj-$(CONFIG_PPC_STD_MMU) += tlb_hash$(BITS).o |
@@ -43,5 +43,12 @@ obj-$(CONFIG_HIGHMEM) += highmem.o | |||
43 | obj-$(CONFIG_PPC_COPRO_BASE) += copro_fault.o | 43 | obj-$(CONFIG_PPC_COPRO_BASE) += copro_fault.o |
44 | obj-$(CONFIG_SPAPR_TCE_IOMMU) += mmu_context_iommu.o | 44 | obj-$(CONFIG_SPAPR_TCE_IOMMU) += mmu_context_iommu.o |
45 | obj-$(CONFIG_PPC_PTDUMP) += dump_linuxpagetables.o | 45 | obj-$(CONFIG_PPC_PTDUMP) += dump_linuxpagetables.o |
46 | ifdef CONFIG_PPC_PTDUMP | ||
47 | obj-$(CONFIG_4xx) += dump_linuxpagetables-generic.o | ||
48 | obj-$(CONFIG_PPC_8xx) += dump_linuxpagetables-8xx.o | ||
49 | obj-$(CONFIG_PPC_BOOK3E_MMU) += dump_linuxpagetables-generic.o | ||
50 | obj-$(CONFIG_PPC_BOOK3S_32) += dump_linuxpagetables-generic.o | ||
51 | obj-$(CONFIG_PPC_BOOK3S_64) += dump_linuxpagetables-book3s64.o | ||
52 | endif | ||
46 | obj-$(CONFIG_PPC_HTDUMP) += dump_hashpagetable.o | 53 | obj-$(CONFIG_PPC_HTDUMP) += dump_hashpagetable.o |
47 | obj-$(CONFIG_PPC_MEM_KEYS) += pkeys.o | 54 | obj-$(CONFIG_PPC_MEM_KEYS) += pkeys.o |
diff --git a/arch/powerpc/mm/dma-noncoherent.c b/arch/powerpc/mm/dma-noncoherent.c index 382528475433..b6e7b5952ab5 100644 --- a/arch/powerpc/mm/dma-noncoherent.c +++ b/arch/powerpc/mm/dma-noncoherent.c | |||
@@ -228,7 +228,7 @@ __dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t | |||
228 | do { | 228 | do { |
229 | SetPageReserved(page); | 229 | SetPageReserved(page); |
230 | map_kernel_page(vaddr, page_to_phys(page), | 230 | map_kernel_page(vaddr, page_to_phys(page), |
231 | pgprot_val(pgprot_noncached(PAGE_KERNEL))); | 231 | pgprot_noncached(PAGE_KERNEL)); |
232 | page++; | 232 | page++; |
233 | vaddr += PAGE_SIZE; | 233 | vaddr += PAGE_SIZE; |
234 | } while (size -= PAGE_SIZE); | 234 | } while (size -= PAGE_SIZE); |
diff --git a/arch/powerpc/mm/dump_linuxpagetables-8xx.c b/arch/powerpc/mm/dump_linuxpagetables-8xx.c new file mode 100644 index 000000000000..ab9e3f24db2f --- /dev/null +++ b/arch/powerpc/mm/dump_linuxpagetables-8xx.c | |||
@@ -0,0 +1,82 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /* | ||
3 | * From split of dump_linuxpagetables.c | ||
4 | * Copyright 2016, Rashmica Gupta, IBM Corp. | ||
5 | * | ||
6 | */ | ||
7 | #include <linux/kernel.h> | ||
8 | #include <asm/pgtable.h> | ||
9 | |||
10 | #include "dump_linuxpagetables.h" | ||
11 | |||
12 | static const struct flag_info flag_array[] = { | ||
13 | { | ||
14 | .mask = _PAGE_SH, | ||
15 | .val = 0, | ||
16 | .set = "user", | ||
17 | .clear = " ", | ||
18 | }, { | ||
19 | .mask = _PAGE_RO | _PAGE_NA, | ||
20 | .val = 0, | ||
21 | .set = "rw", | ||
22 | }, { | ||
23 | .mask = _PAGE_RO | _PAGE_NA, | ||
24 | .val = _PAGE_RO, | ||
25 | .set = "r ", | ||
26 | }, { | ||
27 | .mask = _PAGE_RO | _PAGE_NA, | ||
28 | .val = _PAGE_NA, | ||
29 | .set = " ", | ||
30 | }, { | ||
31 | .mask = _PAGE_EXEC, | ||
32 | .val = _PAGE_EXEC, | ||
33 | .set = " X ", | ||
34 | .clear = " ", | ||
35 | }, { | ||
36 | .mask = _PAGE_PRESENT, | ||
37 | .val = _PAGE_PRESENT, | ||
38 | .set = "present", | ||
39 | .clear = " ", | ||
40 | }, { | ||
41 | .mask = _PAGE_GUARDED, | ||
42 | .val = _PAGE_GUARDED, | ||
43 | .set = "guarded", | ||
44 | .clear = " ", | ||
45 | }, { | ||
46 | .mask = _PAGE_DIRTY, | ||
47 | .val = _PAGE_DIRTY, | ||
48 | .set = "dirty", | ||
49 | .clear = " ", | ||
50 | }, { | ||
51 | .mask = _PAGE_ACCESSED, | ||
52 | .val = _PAGE_ACCESSED, | ||
53 | .set = "accessed", | ||
54 | .clear = " ", | ||
55 | }, { | ||
56 | .mask = _PAGE_NO_CACHE, | ||
57 | .val = _PAGE_NO_CACHE, | ||
58 | .set = "no cache", | ||
59 | .clear = " ", | ||
60 | }, { | ||
61 | .mask = _PAGE_SPECIAL, | ||
62 | .val = _PAGE_SPECIAL, | ||
63 | .set = "special", | ||
64 | } | ||
65 | }; | ||
66 | |||
67 | struct pgtable_level pg_level[5] = { | ||
68 | { | ||
69 | }, { /* pgd */ | ||
70 | .flag = flag_array, | ||
71 | .num = ARRAY_SIZE(flag_array), | ||
72 | }, { /* pud */ | ||
73 | .flag = flag_array, | ||
74 | .num = ARRAY_SIZE(flag_array), | ||
75 | }, { /* pmd */ | ||
76 | .flag = flag_array, | ||
77 | .num = ARRAY_SIZE(flag_array), | ||
78 | }, { /* pte */ | ||
79 | .flag = flag_array, | ||
80 | .num = ARRAY_SIZE(flag_array), | ||
81 | }, | ||
82 | }; | ||
diff --git a/arch/powerpc/mm/dump_linuxpagetables-book3s64.c b/arch/powerpc/mm/dump_linuxpagetables-book3s64.c new file mode 100644 index 000000000000..ed6fcf78256e --- /dev/null +++ b/arch/powerpc/mm/dump_linuxpagetables-book3s64.c | |||
@@ -0,0 +1,120 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /* | ||
3 | * From split of dump_linuxpagetables.c | ||
4 | * Copyright 2016, Rashmica Gupta, IBM Corp. | ||
5 | * | ||
6 | */ | ||
7 | #include <linux/kernel.h> | ||
8 | #include <asm/pgtable.h> | ||
9 | |||
10 | #include "dump_linuxpagetables.h" | ||
11 | |||
12 | static const struct flag_info flag_array[] = { | ||
13 | { | ||
14 | .mask = _PAGE_PRIVILEGED, | ||
15 | .val = 0, | ||
16 | .set = "user", | ||
17 | .clear = " ", | ||
18 | }, { | ||
19 | .mask = _PAGE_READ, | ||
20 | .val = _PAGE_READ, | ||
21 | .set = "r", | ||
22 | .clear = " ", | ||
23 | }, { | ||
24 | .mask = _PAGE_WRITE, | ||
25 | .val = _PAGE_WRITE, | ||
26 | .set = "w", | ||
27 | .clear = " ", | ||
28 | }, { | ||
29 | .mask = _PAGE_EXEC, | ||
30 | .val = _PAGE_EXEC, | ||
31 | .set = " X ", | ||
32 | .clear = " ", | ||
33 | }, { | ||
34 | .mask = _PAGE_PTE, | ||
35 | .val = _PAGE_PTE, | ||
36 | .set = "pte", | ||
37 | .clear = " ", | ||
38 | }, { | ||
39 | .mask = _PAGE_PRESENT, | ||
40 | .val = _PAGE_PRESENT, | ||
41 | .set = "valid", | ||
42 | .clear = " ", | ||
43 | }, { | ||
44 | .mask = _PAGE_PRESENT | _PAGE_INVALID, | ||
45 | .val = 0, | ||
46 | .set = " ", | ||
47 | .clear = "present", | ||
48 | }, { | ||
49 | .mask = H_PAGE_HASHPTE, | ||
50 | .val = H_PAGE_HASHPTE, | ||
51 | .set = "hpte", | ||
52 | .clear = " ", | ||
53 | }, { | ||
54 | .mask = _PAGE_DIRTY, | ||
55 | .val = _PAGE_DIRTY, | ||
56 | .set = "dirty", | ||
57 | .clear = " ", | ||
58 | }, { | ||
59 | .mask = _PAGE_ACCESSED, | ||
60 | .val = _PAGE_ACCESSED, | ||
61 | .set = "accessed", | ||
62 | .clear = " ", | ||
63 | }, { | ||
64 | .mask = _PAGE_NON_IDEMPOTENT, | ||
65 | .val = _PAGE_NON_IDEMPOTENT, | ||
66 | .set = "non-idempotent", | ||
67 | .clear = " ", | ||
68 | }, { | ||
69 | .mask = _PAGE_TOLERANT, | ||
70 | .val = _PAGE_TOLERANT, | ||
71 | .set = "tolerant", | ||
72 | .clear = " ", | ||
73 | }, { | ||
74 | .mask = H_PAGE_BUSY, | ||
75 | .val = H_PAGE_BUSY, | ||
76 | .set = "busy", | ||
77 | }, { | ||
78 | #ifdef CONFIG_PPC_64K_PAGES | ||
79 | .mask = H_PAGE_COMBO, | ||
80 | .val = H_PAGE_COMBO, | ||
81 | .set = "combo", | ||
82 | }, { | ||
83 | .mask = H_PAGE_4K_PFN, | ||
84 | .val = H_PAGE_4K_PFN, | ||
85 | .set = "4K_pfn", | ||
86 | }, { | ||
87 | #else /* CONFIG_PPC_64K_PAGES */ | ||
88 | .mask = H_PAGE_F_GIX, | ||
89 | .val = H_PAGE_F_GIX, | ||
90 | .set = "f_gix", | ||
91 | .is_val = true, | ||
92 | .shift = H_PAGE_F_GIX_SHIFT, | ||
93 | }, { | ||
94 | .mask = H_PAGE_F_SECOND, | ||
95 | .val = H_PAGE_F_SECOND, | ||
96 | .set = "f_second", | ||
97 | }, { | ||
98 | #endif /* CONFIG_PPC_64K_PAGES */ | ||
99 | .mask = _PAGE_SPECIAL, | ||
100 | .val = _PAGE_SPECIAL, | ||
101 | .set = "special", | ||
102 | } | ||
103 | }; | ||
104 | |||
105 | struct pgtable_level pg_level[5] = { | ||
106 | { | ||
107 | }, { /* pgd */ | ||
108 | .flag = flag_array, | ||
109 | .num = ARRAY_SIZE(flag_array), | ||
110 | }, { /* pud */ | ||
111 | .flag = flag_array, | ||
112 | .num = ARRAY_SIZE(flag_array), | ||
113 | }, { /* pmd */ | ||
114 | .flag = flag_array, | ||
115 | .num = ARRAY_SIZE(flag_array), | ||
116 | }, { /* pte */ | ||
117 | .flag = flag_array, | ||
118 | .num = ARRAY_SIZE(flag_array), | ||
119 | }, | ||
120 | }; | ||
diff --git a/arch/powerpc/mm/dump_linuxpagetables-generic.c b/arch/powerpc/mm/dump_linuxpagetables-generic.c new file mode 100644 index 000000000000..1e3829ec1348 --- /dev/null +++ b/arch/powerpc/mm/dump_linuxpagetables-generic.c | |||
@@ -0,0 +1,82 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /* | ||
3 | * From split of dump_linuxpagetables.c | ||
4 | * Copyright 2016, Rashmica Gupta, IBM Corp. | ||
5 | * | ||
6 | */ | ||
7 | #include <linux/kernel.h> | ||
8 | #include <asm/pgtable.h> | ||
9 | |||
10 | #include "dump_linuxpagetables.h" | ||
11 | |||
12 | static const struct flag_info flag_array[] = { | ||
13 | { | ||
14 | .mask = _PAGE_USER, | ||
15 | .val = _PAGE_USER, | ||
16 | .set = "user", | ||
17 | .clear = " ", | ||
18 | }, { | ||
19 | .mask = _PAGE_RW, | ||
20 | .val = _PAGE_RW, | ||
21 | .set = "rw", | ||
22 | .clear = "r ", | ||
23 | }, { | ||
24 | #ifndef CONFIG_PPC_BOOK3S_32 | ||
25 | .mask = _PAGE_EXEC, | ||
26 | .val = _PAGE_EXEC, | ||
27 | .set = " X ", | ||
28 | .clear = " ", | ||
29 | }, { | ||
30 | #endif | ||
31 | .mask = _PAGE_PRESENT, | ||
32 | .val = _PAGE_PRESENT, | ||
33 | .set = "present", | ||
34 | .clear = " ", | ||
35 | }, { | ||
36 | .mask = _PAGE_GUARDED, | ||
37 | .val = _PAGE_GUARDED, | ||
38 | .set = "guarded", | ||
39 | .clear = " ", | ||
40 | }, { | ||
41 | .mask = _PAGE_DIRTY, | ||
42 | .val = _PAGE_DIRTY, | ||
43 | .set = "dirty", | ||
44 | .clear = " ", | ||
45 | }, { | ||
46 | .mask = _PAGE_ACCESSED, | ||
47 | .val = _PAGE_ACCESSED, | ||
48 | .set = "accessed", | ||
49 | .clear = " ", | ||
50 | }, { | ||
51 | .mask = _PAGE_WRITETHRU, | ||
52 | .val = _PAGE_WRITETHRU, | ||
53 | .set = "write through", | ||
54 | .clear = " ", | ||
55 | }, { | ||
56 | .mask = _PAGE_NO_CACHE, | ||
57 | .val = _PAGE_NO_CACHE, | ||
58 | .set = "no cache", | ||
59 | .clear = " ", | ||
60 | }, { | ||
61 | .mask = _PAGE_SPECIAL, | ||
62 | .val = _PAGE_SPECIAL, | ||
63 | .set = "special", | ||
64 | } | ||
65 | }; | ||
66 | |||
67 | struct pgtable_level pg_level[5] = { | ||
68 | { | ||
69 | }, { /* pgd */ | ||
70 | .flag = flag_array, | ||
71 | .num = ARRAY_SIZE(flag_array), | ||
72 | }, { /* pud */ | ||
73 | .flag = flag_array, | ||
74 | .num = ARRAY_SIZE(flag_array), | ||
75 | }, { /* pmd */ | ||
76 | .flag = flag_array, | ||
77 | .num = ARRAY_SIZE(flag_array), | ||
78 | }, { /* pte */ | ||
79 | .flag = flag_array, | ||
80 | .num = ARRAY_SIZE(flag_array), | ||
81 | }, | ||
82 | }; | ||
diff --git a/arch/powerpc/mm/dump_linuxpagetables.c b/arch/powerpc/mm/dump_linuxpagetables.c index 876e2a3c79f2..2b74f8adf4d0 100644 --- a/arch/powerpc/mm/dump_linuxpagetables.c +++ b/arch/powerpc/mm/dump_linuxpagetables.c | |||
@@ -27,6 +27,8 @@ | |||
27 | #include <asm/page.h> | 27 | #include <asm/page.h> |
28 | #include <asm/pgalloc.h> | 28 | #include <asm/pgalloc.h> |
29 | 29 | ||
30 | #include "dump_linuxpagetables.h" | ||
31 | |||
30 | #ifdef CONFIG_PPC32 | 32 | #ifdef CONFIG_PPC32 |
31 | #define KERN_VIRT_START 0 | 33 | #define KERN_VIRT_START 0 |
32 | #endif | 34 | #endif |
@@ -101,159 +103,6 @@ static struct addr_marker address_markers[] = { | |||
101 | { -1, NULL }, | 103 | { -1, NULL }, |
102 | }; | 104 | }; |
103 | 105 | ||
104 | struct flag_info { | ||
105 | u64 mask; | ||
106 | u64 val; | ||
107 | const char *set; | ||
108 | const char *clear; | ||
109 | bool is_val; | ||
110 | int shift; | ||
111 | }; | ||
112 | |||
113 | static const struct flag_info flag_array[] = { | ||
114 | { | ||
115 | .mask = _PAGE_USER | _PAGE_PRIVILEGED, | ||
116 | .val = _PAGE_USER, | ||
117 | .set = "user", | ||
118 | .clear = " ", | ||
119 | }, { | ||
120 | .mask = _PAGE_RW | _PAGE_RO | _PAGE_NA, | ||
121 | .val = _PAGE_RW, | ||
122 | .set = "rw", | ||
123 | }, { | ||
124 | .mask = _PAGE_RW | _PAGE_RO | _PAGE_NA, | ||
125 | .val = _PAGE_RO, | ||
126 | .set = "ro", | ||
127 | }, { | ||
128 | #if _PAGE_NA != 0 | ||
129 | .mask = _PAGE_RW | _PAGE_RO | _PAGE_NA, | ||
130 | .val = _PAGE_RO, | ||
131 | .set = "na", | ||
132 | }, { | ||
133 | #endif | ||
134 | .mask = _PAGE_EXEC, | ||
135 | .val = _PAGE_EXEC, | ||
136 | .set = " X ", | ||
137 | .clear = " ", | ||
138 | }, { | ||
139 | .mask = _PAGE_PTE, | ||
140 | .val = _PAGE_PTE, | ||
141 | .set = "pte", | ||
142 | .clear = " ", | ||
143 | }, { | ||
144 | .mask = _PAGE_PRESENT, | ||
145 | .val = _PAGE_PRESENT, | ||
146 | .set = "present", | ||
147 | .clear = " ", | ||
148 | }, { | ||
149 | #ifdef CONFIG_PPC_BOOK3S_64 | ||
150 | .mask = H_PAGE_HASHPTE, | ||
151 | .val = H_PAGE_HASHPTE, | ||
152 | #else | ||
153 | .mask = _PAGE_HASHPTE, | ||
154 | .val = _PAGE_HASHPTE, | ||
155 | #endif | ||
156 | .set = "hpte", | ||
157 | .clear = " ", | ||
158 | }, { | ||
159 | #ifndef CONFIG_PPC_BOOK3S_64 | ||
160 | .mask = _PAGE_GUARDED, | ||
161 | .val = _PAGE_GUARDED, | ||
162 | .set = "guarded", | ||
163 | .clear = " ", | ||
164 | }, { | ||
165 | #endif | ||
166 | .mask = _PAGE_DIRTY, | ||
167 | .val = _PAGE_DIRTY, | ||
168 | .set = "dirty", | ||
169 | .clear = " ", | ||
170 | }, { | ||
171 | .mask = _PAGE_ACCESSED, | ||
172 | .val = _PAGE_ACCESSED, | ||
173 | .set = "accessed", | ||
174 | .clear = " ", | ||
175 | }, { | ||
176 | #ifndef CONFIG_PPC_BOOK3S_64 | ||
177 | .mask = _PAGE_WRITETHRU, | ||
178 | .val = _PAGE_WRITETHRU, | ||
179 | .set = "write through", | ||
180 | .clear = " ", | ||
181 | }, { | ||
182 | #endif | ||
183 | #ifndef CONFIG_PPC_BOOK3S_64 | ||
184 | .mask = _PAGE_NO_CACHE, | ||
185 | .val = _PAGE_NO_CACHE, | ||
186 | .set = "no cache", | ||
187 | .clear = " ", | ||
188 | }, { | ||
189 | #else | ||
190 | .mask = _PAGE_NON_IDEMPOTENT, | ||
191 | .val = _PAGE_NON_IDEMPOTENT, | ||
192 | .set = "non-idempotent", | ||
193 | .clear = " ", | ||
194 | }, { | ||
195 | .mask = _PAGE_TOLERANT, | ||
196 | .val = _PAGE_TOLERANT, | ||
197 | .set = "tolerant", | ||
198 | .clear = " ", | ||
199 | }, { | ||
200 | #endif | ||
201 | #ifdef CONFIG_PPC_BOOK3S_64 | ||
202 | .mask = H_PAGE_BUSY, | ||
203 | .val = H_PAGE_BUSY, | ||
204 | .set = "busy", | ||
205 | }, { | ||
206 | #ifdef CONFIG_PPC_64K_PAGES | ||
207 | .mask = H_PAGE_COMBO, | ||
208 | .val = H_PAGE_COMBO, | ||
209 | .set = "combo", | ||
210 | }, { | ||
211 | .mask = H_PAGE_4K_PFN, | ||
212 | .val = H_PAGE_4K_PFN, | ||
213 | .set = "4K_pfn", | ||
214 | }, { | ||
215 | #else /* CONFIG_PPC_64K_PAGES */ | ||
216 | .mask = H_PAGE_F_GIX, | ||
217 | .val = H_PAGE_F_GIX, | ||
218 | .set = "f_gix", | ||
219 | .is_val = true, | ||
220 | .shift = H_PAGE_F_GIX_SHIFT, | ||
221 | }, { | ||
222 | .mask = H_PAGE_F_SECOND, | ||
223 | .val = H_PAGE_F_SECOND, | ||
224 | .set = "f_second", | ||
225 | }, { | ||
226 | #endif /* CONFIG_PPC_64K_PAGES */ | ||
227 | #endif | ||
228 | .mask = _PAGE_SPECIAL, | ||
229 | .val = _PAGE_SPECIAL, | ||
230 | .set = "special", | ||
231 | } | ||
232 | }; | ||
233 | |||
234 | struct pgtable_level { | ||
235 | const struct flag_info *flag; | ||
236 | size_t num; | ||
237 | u64 mask; | ||
238 | }; | ||
239 | |||
240 | static struct pgtable_level pg_level[] = { | ||
241 | { | ||
242 | }, { /* pgd */ | ||
243 | .flag = flag_array, | ||
244 | .num = ARRAY_SIZE(flag_array), | ||
245 | }, { /* pud */ | ||
246 | .flag = flag_array, | ||
247 | .num = ARRAY_SIZE(flag_array), | ||
248 | }, { /* pmd */ | ||
249 | .flag = flag_array, | ||
250 | .num = ARRAY_SIZE(flag_array), | ||
251 | }, { /* pte */ | ||
252 | .flag = flag_array, | ||
253 | .num = ARRAY_SIZE(flag_array), | ||
254 | }, | ||
255 | }; | ||
256 | |||
257 | static void dump_flag_info(struct pg_state *st, const struct flag_info | 106 | static void dump_flag_info(struct pg_state *st, const struct flag_info |
258 | *flag, u64 pte, int num) | 107 | *flag, u64 pte, int num) |
259 | { | 108 | { |
@@ -418,12 +267,13 @@ static void walk_pagetables(struct pg_state *st) | |||
418 | unsigned int i; | 267 | unsigned int i; |
419 | unsigned long addr; | 268 | unsigned long addr; |
420 | 269 | ||
270 | addr = st->start_address; | ||
271 | |||
421 | /* | 272 | /* |
422 | * Traverse the linux pagetable structure and dump pages that are in | 273 | * Traverse the linux pagetable structure and dump pages that are in |
423 | * the hash pagetable. | 274 | * the hash pagetable. |
424 | */ | 275 | */ |
425 | for (i = 0; i < PTRS_PER_PGD; i++, pgd++) { | 276 | for (i = 0; i < PTRS_PER_PGD; i++, pgd++, addr += PGDIR_SIZE) { |
426 | addr = KERN_VIRT_START + i * PGDIR_SIZE; | ||
427 | if (!pgd_none(*pgd) && !pgd_huge(*pgd)) | 277 | if (!pgd_none(*pgd) && !pgd_huge(*pgd)) |
428 | /* pgd exists */ | 278 | /* pgd exists */ |
429 | walk_pud(st, pgd, addr); | 279 | walk_pud(st, pgd, addr); |
@@ -472,9 +322,14 @@ static int ptdump_show(struct seq_file *m, void *v) | |||
472 | { | 322 | { |
473 | struct pg_state st = { | 323 | struct pg_state st = { |
474 | .seq = m, | 324 | .seq = m, |
475 | .start_address = KERN_VIRT_START, | ||
476 | .marker = address_markers, | 325 | .marker = address_markers, |
477 | }; | 326 | }; |
327 | |||
328 | if (radix_enabled()) | ||
329 | st.start_address = PAGE_OFFSET; | ||
330 | else | ||
331 | st.start_address = KERN_VIRT_START; | ||
332 | |||
478 | /* Traverse kernel page tables */ | 333 | /* Traverse kernel page tables */ |
479 | walk_pagetables(&st); | 334 | walk_pagetables(&st); |
480 | note_page(&st, 0, 0, 0); | 335 | note_page(&st, 0, 0, 0); |
diff --git a/arch/powerpc/mm/dump_linuxpagetables.h b/arch/powerpc/mm/dump_linuxpagetables.h new file mode 100644 index 000000000000..5d513636de73 --- /dev/null +++ b/arch/powerpc/mm/dump_linuxpagetables.h | |||
@@ -0,0 +1,19 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
2 | #include <linux/types.h> | ||
3 | |||
4 | struct flag_info { | ||
5 | u64 mask; | ||
6 | u64 val; | ||
7 | const char *set; | ||
8 | const char *clear; | ||
9 | bool is_val; | ||
10 | int shift; | ||
11 | }; | ||
12 | |||
13 | struct pgtable_level { | ||
14 | const struct flag_info *flag; | ||
15 | size_t num; | ||
16 | u64 mask; | ||
17 | }; | ||
18 | |||
19 | extern struct pgtable_level pg_level[5]; | ||
diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c index 729f02df8290..aaa28fd918fe 100644 --- a/arch/powerpc/mm/hash_native_64.c +++ b/arch/powerpc/mm/hash_native_64.c | |||
@@ -115,6 +115,8 @@ static void tlbiel_all_isa300(unsigned int num_sets, unsigned int is) | |||
115 | tlbiel_hash_set_isa300(0, is, 0, 2, 1); | 115 | tlbiel_hash_set_isa300(0, is, 0, 2, 1); |
116 | 116 | ||
117 | asm volatile("ptesync": : :"memory"); | 117 | asm volatile("ptesync": : :"memory"); |
118 | |||
119 | asm volatile(PPC_INVALIDATE_ERAT "; isync" : : :"memory"); | ||
118 | } | 120 | } |
119 | 121 | ||
120 | void hash__tlbiel_all(unsigned int action) | 122 | void hash__tlbiel_all(unsigned int action) |
@@ -140,8 +142,6 @@ void hash__tlbiel_all(unsigned int action) | |||
140 | tlbiel_all_isa206(POWER7_TLB_SETS, is); | 142 | tlbiel_all_isa206(POWER7_TLB_SETS, is); |
141 | else | 143 | else |
142 | WARN(1, "%s called on pre-POWER7 CPU\n", __func__); | 144 | WARN(1, "%s called on pre-POWER7 CPU\n", __func__); |
143 | |||
144 | asm volatile(PPC_INVALIDATE_ERAT "; isync" : : :"memory"); | ||
145 | } | 145 | } |
146 | 146 | ||
147 | static inline unsigned long ___tlbie(unsigned long vpn, int psize, | 147 | static inline unsigned long ___tlbie(unsigned long vpn, int psize, |
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index f23a89d8e4ce..0cc7fbc3bd1c 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c | |||
@@ -1001,9 +1001,9 @@ void __init hash__early_init_mmu(void) | |||
1001 | * 4k use hugepd format, so for hash set then to | 1001 | * 4k use hugepd format, so for hash set then to |
1002 | * zero | 1002 | * zero |
1003 | */ | 1003 | */ |
1004 | __pmd_val_bits = 0; | 1004 | __pmd_val_bits = HASH_PMD_VAL_BITS; |
1005 | __pud_val_bits = 0; | 1005 | __pud_val_bits = HASH_PUD_VAL_BITS; |
1006 | __pgd_val_bits = 0; | 1006 | __pgd_val_bits = HASH_PGD_VAL_BITS; |
1007 | 1007 | ||
1008 | __kernel_virt_start = H_KERN_VIRT_START; | 1008 | __kernel_virt_start = H_KERN_VIRT_START; |
1009 | __kernel_virt_size = H_KERN_VIRT_SIZE; | 1009 | __kernel_virt_size = H_KERN_VIRT_SIZE; |
@@ -1125,7 +1125,7 @@ void demote_segment_4k(struct mm_struct *mm, unsigned long addr) | |||
1125 | if ((get_paca_psize(addr) != MMU_PAGE_4K) && (current->mm == mm)) { | 1125 | if ((get_paca_psize(addr) != MMU_PAGE_4K) && (current->mm == mm)) { |
1126 | 1126 | ||
1127 | copy_mm_to_paca(mm); | 1127 | copy_mm_to_paca(mm); |
1128 | slb_flush_and_rebolt(); | 1128 | slb_flush_and_restore_bolted(); |
1129 | } | 1129 | } |
1130 | } | 1130 | } |
1131 | #endif /* CONFIG_PPC_64K_PAGES */ | 1131 | #endif /* CONFIG_PPC_64K_PAGES */ |
@@ -1197,7 +1197,7 @@ static void check_paca_psize(unsigned long ea, struct mm_struct *mm, | |||
1197 | if (user_region) { | 1197 | if (user_region) { |
1198 | if (psize != get_paca_psize(ea)) { | 1198 | if (psize != get_paca_psize(ea)) { |
1199 | copy_mm_to_paca(mm); | 1199 | copy_mm_to_paca(mm); |
1200 | slb_flush_and_rebolt(); | 1200 | slb_flush_and_restore_bolted(); |
1201 | } | 1201 | } |
1202 | } else if (get_paca()->vmalloc_sllp != | 1202 | } else if (get_paca()->vmalloc_sllp != |
1203 | mmu_psize_defs[mmu_vmalloc_psize].sllp) { | 1203 | mmu_psize_defs[mmu_vmalloc_psize].sllp) { |
@@ -1482,7 +1482,7 @@ static bool should_hash_preload(struct mm_struct *mm, unsigned long ea) | |||
1482 | #endif | 1482 | #endif |
1483 | 1483 | ||
1484 | void hash_preload(struct mm_struct *mm, unsigned long ea, | 1484 | void hash_preload(struct mm_struct *mm, unsigned long ea, |
1485 | unsigned long access, unsigned long trap) | 1485 | bool is_exec, unsigned long trap) |
1486 | { | 1486 | { |
1487 | int hugepage_shift; | 1487 | int hugepage_shift; |
1488 | unsigned long vsid; | 1488 | unsigned long vsid; |
@@ -1490,6 +1490,7 @@ void hash_preload(struct mm_struct *mm, unsigned long ea, | |||
1490 | pte_t *ptep; | 1490 | pte_t *ptep; |
1491 | unsigned long flags; | 1491 | unsigned long flags; |
1492 | int rc, ssize, update_flags = 0; | 1492 | int rc, ssize, update_flags = 0; |
1493 | unsigned long access = _PAGE_PRESENT | _PAGE_READ | (is_exec ? _PAGE_EXEC : 0); | ||
1493 | 1494 | ||
1494 | BUG_ON(REGION_ID(ea) != USER_REGION_ID); | 1495 | BUG_ON(REGION_ID(ea) != USER_REGION_ID); |
1495 | 1496 | ||
diff --git a/arch/powerpc/mm/hugepage-hash64.c b/arch/powerpc/mm/hugepage-hash64.c index 01f213d2bcb9..dfbc3b32f09b 100644 --- a/arch/powerpc/mm/hugepage-hash64.c +++ b/arch/powerpc/mm/hugepage-hash64.c | |||
@@ -51,6 +51,12 @@ int __hash_page_thp(unsigned long ea, unsigned long access, unsigned long vsid, | |||
51 | new_pmd |= _PAGE_DIRTY; | 51 | new_pmd |= _PAGE_DIRTY; |
52 | } while (!pmd_xchg(pmdp, __pmd(old_pmd), __pmd(new_pmd))); | 52 | } while (!pmd_xchg(pmdp, __pmd(old_pmd), __pmd(new_pmd))); |
53 | 53 | ||
54 | /* | ||
55 | * Make sure this is thp or devmap entry | ||
56 | */ | ||
57 | if (!(old_pmd & (H_PAGE_THP_HUGE | _PAGE_DEVMAP))) | ||
58 | return 0; | ||
59 | |||
54 | rflags = htab_convert_pte_flags(new_pmd); | 60 | rflags = htab_convert_pte_flags(new_pmd); |
55 | 61 | ||
56 | #if 0 | 62 | #if 0 |
diff --git a/arch/powerpc/mm/hugetlbpage-hash64.c b/arch/powerpc/mm/hugetlbpage-hash64.c index b320f5097a06..2e6a8f9345d3 100644 --- a/arch/powerpc/mm/hugetlbpage-hash64.c +++ b/arch/powerpc/mm/hugetlbpage-hash64.c | |||
@@ -62,6 +62,10 @@ int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid, | |||
62 | new_pte |= _PAGE_DIRTY; | 62 | new_pte |= _PAGE_DIRTY; |
63 | } while(!pte_xchg(ptep, __pte(old_pte), __pte(new_pte))); | 63 | } while(!pte_xchg(ptep, __pte(old_pte), __pte(new_pte))); |
64 | 64 | ||
65 | /* Make sure this is a hugetlb entry */ | ||
66 | if (old_pte & (H_PAGE_THP_HUGE | _PAGE_DEVMAP)) | ||
67 | return 0; | ||
68 | |||
65 | rflags = htab_convert_pte_flags(new_pte); | 69 | rflags = htab_convert_pte_flags(new_pte); |
66 | if (unlikely(mmu_psize == MMU_PAGE_16G)) | 70 | if (unlikely(mmu_psize == MMU_PAGE_16G)) |
67 | offset = PTRS_PER_PUD; | 71 | offset = PTRS_PER_PUD; |
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c index e87f9ef9115b..a7226ed9cae6 100644 --- a/arch/powerpc/mm/hugetlbpage.c +++ b/arch/powerpc/mm/hugetlbpage.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/moduleparam.h> | 19 | #include <linux/moduleparam.h> |
20 | #include <linux/swap.h> | 20 | #include <linux/swap.h> |
21 | #include <linux/swapops.h> | 21 | #include <linux/swapops.h> |
22 | #include <linux/kmemleak.h> | ||
22 | #include <asm/pgtable.h> | 23 | #include <asm/pgtable.h> |
23 | #include <asm/pgalloc.h> | 24 | #include <asm/pgalloc.h> |
24 | #include <asm/tlb.h> | 25 | #include <asm/tlb.h> |
@@ -95,7 +96,7 @@ static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp, | |||
95 | break; | 96 | break; |
96 | else { | 97 | else { |
97 | #ifdef CONFIG_PPC_BOOK3S_64 | 98 | #ifdef CONFIG_PPC_BOOK3S_64 |
98 | *hpdp = __hugepd(__pa(new) | | 99 | *hpdp = __hugepd(__pa(new) | HUGEPD_VAL_BITS | |
99 | (shift_to_mmu_psize(pshift) << 2)); | 100 | (shift_to_mmu_psize(pshift) << 2)); |
100 | #elif defined(CONFIG_PPC_8xx) | 101 | #elif defined(CONFIG_PPC_8xx) |
101 | *hpdp = __hugepd(__pa(new) | _PMD_USER | | 102 | *hpdp = __hugepd(__pa(new) | _PMD_USER | |
@@ -112,6 +113,8 @@ static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp, | |||
112 | for (i = i - 1 ; i >= 0; i--, hpdp--) | 113 | for (i = i - 1 ; i >= 0; i--, hpdp--) |
113 | *hpdp = __hugepd(0); | 114 | *hpdp = __hugepd(0); |
114 | kmem_cache_free(cachep, new); | 115 | kmem_cache_free(cachep, new); |
116 | } else { | ||
117 | kmemleak_ignore(new); | ||
115 | } | 118 | } |
116 | spin_unlock(ptl); | 119 | spin_unlock(ptl); |
117 | return 0; | 120 | return 0; |
@@ -837,8 +840,12 @@ pte_t *__find_linux_pte(pgd_t *pgdir, unsigned long ea, | |||
837 | ret_pte = (pte_t *) pmdp; | 840 | ret_pte = (pte_t *) pmdp; |
838 | goto out; | 841 | goto out; |
839 | } | 842 | } |
840 | 843 | /* | |
841 | if (pmd_huge(pmd)) { | 844 | * pmd_large check below will handle the swap pmd pte |
845 | * we need to do both the check because they are config | ||
846 | * dependent. | ||
847 | */ | ||
848 | if (pmd_huge(pmd) || pmd_large(pmd)) { | ||
842 | ret_pte = (pte_t *) pmdp; | 849 | ret_pte = (pte_t *) pmdp; |
843 | goto out; | 850 | goto out; |
844 | } else if (is_hugepd(__hugepd(pmd_val(pmd)))) | 851 | } else if (is_hugepd(__hugepd(pmd_val(pmd)))) |
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 04ccb274a620..dd949d6649a2 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c | |||
@@ -309,11 +309,11 @@ void __init paging_init(void) | |||
309 | unsigned long end = __fix_to_virt(FIX_HOLE); | 309 | unsigned long end = __fix_to_virt(FIX_HOLE); |
310 | 310 | ||
311 | for (; v < end; v += PAGE_SIZE) | 311 | for (; v < end; v += PAGE_SIZE) |
312 | map_kernel_page(v, 0, 0); /* XXX gross */ | 312 | map_kernel_page(v, 0, __pgprot(0)); /* XXX gross */ |
313 | #endif | 313 | #endif |
314 | 314 | ||
315 | #ifdef CONFIG_HIGHMEM | 315 | #ifdef CONFIG_HIGHMEM |
316 | map_kernel_page(PKMAP_BASE, 0, 0); /* XXX gross */ | 316 | map_kernel_page(PKMAP_BASE, 0, __pgprot(0)); /* XXX gross */ |
317 | pkmap_page_table = virt_to_kpte(PKMAP_BASE); | 317 | pkmap_page_table = virt_to_kpte(PKMAP_BASE); |
318 | 318 | ||
319 | kmap_pte = virt_to_kpte(__fix_to_virt(FIX_KMAP_BEGIN)); | 319 | kmap_pte = virt_to_kpte(__fix_to_virt(FIX_KMAP_BEGIN)); |
@@ -509,7 +509,8 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, | |||
509 | * We don't need to worry about _PAGE_PRESENT here because we are | 509 | * We don't need to worry about _PAGE_PRESENT here because we are |
510 | * called with either mm->page_table_lock held or ptl lock held | 510 | * called with either mm->page_table_lock held or ptl lock held |
511 | */ | 511 | */ |
512 | unsigned long access, trap; | 512 | unsigned long trap; |
513 | bool is_exec; | ||
513 | 514 | ||
514 | if (radix_enabled()) { | 515 | if (radix_enabled()) { |
515 | prefetch((void *)address); | 516 | prefetch((void *)address); |
@@ -531,16 +532,16 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, | |||
531 | trap = current->thread.regs ? TRAP(current->thread.regs) : 0UL; | 532 | trap = current->thread.regs ? TRAP(current->thread.regs) : 0UL; |
532 | switch (trap) { | 533 | switch (trap) { |
533 | case 0x300: | 534 | case 0x300: |
534 | access = 0UL; | 535 | is_exec = false; |
535 | break; | 536 | break; |
536 | case 0x400: | 537 | case 0x400: |
537 | access = _PAGE_EXEC; | 538 | is_exec = true; |
538 | break; | 539 | break; |
539 | default: | 540 | default: |
540 | return; | 541 | return; |
541 | } | 542 | } |
542 | 543 | ||
543 | hash_preload(vma->vm_mm, address, access, trap); | 544 | hash_preload(vma->vm_mm, address, is_exec, trap); |
544 | #endif /* CONFIG_PPC_STD_MMU */ | 545 | #endif /* CONFIG_PPC_STD_MMU */ |
545 | #if (defined(CONFIG_PPC_BOOK3E_64) || defined(CONFIG_PPC_FSL_BOOK3E)) \ | 546 | #if (defined(CONFIG_PPC_BOOK3E_64) || defined(CONFIG_PPC_FSL_BOOK3E)) \ |
546 | && defined(CONFIG_HUGETLB_PAGE) | 547 | && defined(CONFIG_HUGETLB_PAGE) |
diff --git a/arch/powerpc/mm/mmu_context_book3s64.c b/arch/powerpc/mm/mmu_context_book3s64.c index dbd8f762140b..510f103d7813 100644 --- a/arch/powerpc/mm/mmu_context_book3s64.c +++ b/arch/powerpc/mm/mmu_context_book3s64.c | |||
@@ -53,6 +53,8 @@ int hash__alloc_context_id(void) | |||
53 | } | 53 | } |
54 | EXPORT_SYMBOL_GPL(hash__alloc_context_id); | 54 | EXPORT_SYMBOL_GPL(hash__alloc_context_id); |
55 | 55 | ||
56 | void slb_setup_new_exec(void); | ||
57 | |||
56 | static int hash__init_new_context(struct mm_struct *mm) | 58 | static int hash__init_new_context(struct mm_struct *mm) |
57 | { | 59 | { |
58 | int index; | 60 | int index; |
@@ -84,6 +86,13 @@ static int hash__init_new_context(struct mm_struct *mm) | |||
84 | return index; | 86 | return index; |
85 | } | 87 | } |
86 | 88 | ||
89 | void hash__setup_new_exec(void) | ||
90 | { | ||
91 | slice_setup_new_exec(); | ||
92 | |||
93 | slb_setup_new_exec(); | ||
94 | } | ||
95 | |||
87 | static int radix__init_new_context(struct mm_struct *mm) | 96 | static int radix__init_new_context(struct mm_struct *mm) |
88 | { | 97 | { |
89 | unsigned long rts_field; | 98 | unsigned long rts_field; |
diff --git a/arch/powerpc/mm/mmu_decl.h b/arch/powerpc/mm/mmu_decl.h index e5d779eed181..8574fbbc45e0 100644 --- a/arch/powerpc/mm/mmu_decl.h +++ b/arch/powerpc/mm/mmu_decl.h | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <asm/mmu.h> | 22 | #include <asm/mmu.h> |
23 | 23 | ||
24 | #ifdef CONFIG_PPC_MMU_NOHASH | 24 | #ifdef CONFIG_PPC_MMU_NOHASH |
25 | #include <asm/trace.h> | ||
25 | 26 | ||
26 | /* | 27 | /* |
27 | * On 40x and 8xx, we directly inline tlbia and tlbivax | 28 | * On 40x and 8xx, we directly inline tlbia and tlbivax |
@@ -30,10 +31,12 @@ | |||
30 | static inline void _tlbil_all(void) | 31 | static inline void _tlbil_all(void) |
31 | { | 32 | { |
32 | asm volatile ("sync; tlbia; isync" : : : "memory"); | 33 | asm volatile ("sync; tlbia; isync" : : : "memory"); |
34 | trace_tlbia(MMU_NO_CONTEXT); | ||
33 | } | 35 | } |
34 | static inline void _tlbil_pid(unsigned int pid) | 36 | static inline void _tlbil_pid(unsigned int pid) |
35 | { | 37 | { |
36 | asm volatile ("sync; tlbia; isync" : : : "memory"); | 38 | asm volatile ("sync; tlbia; isync" : : : "memory"); |
39 | trace_tlbia(pid); | ||
37 | } | 40 | } |
38 | #define _tlbil_pid_noind(pid) _tlbil_pid(pid) | 41 | #define _tlbil_pid_noind(pid) _tlbil_pid(pid) |
39 | 42 | ||
@@ -55,6 +58,7 @@ static inline void _tlbil_va(unsigned long address, unsigned int pid, | |||
55 | unsigned int tsize, unsigned int ind) | 58 | unsigned int tsize, unsigned int ind) |
56 | { | 59 | { |
57 | asm volatile ("tlbie %0; sync" : : "r" (address) : "memory"); | 60 | asm volatile ("tlbie %0; sync" : : "r" (address) : "memory"); |
61 | trace_tlbie(0, 0, address, pid, 0, 0, 0); | ||
58 | } | 62 | } |
59 | #elif defined(CONFIG_PPC_BOOK3E) | 63 | #elif defined(CONFIG_PPC_BOOK3E) |
60 | extern void _tlbil_va(unsigned long address, unsigned int pid, | 64 | extern void _tlbil_va(unsigned long address, unsigned int pid, |
@@ -82,7 +86,7 @@ static inline void _tlbivax_bcast(unsigned long address, unsigned int pid, | |||
82 | #else /* CONFIG_PPC_MMU_NOHASH */ | 86 | #else /* CONFIG_PPC_MMU_NOHASH */ |
83 | 87 | ||
84 | extern void hash_preload(struct mm_struct *mm, unsigned long ea, | 88 | extern void hash_preload(struct mm_struct *mm, unsigned long ea, |
85 | unsigned long access, unsigned long trap); | 89 | bool is_exec, unsigned long trap); |
86 | 90 | ||
87 | 91 | ||
88 | extern void _tlbie(unsigned long address); | 92 | extern void _tlbie(unsigned long address); |
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index 055b211b7126..693ae1c1acba 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c | |||
@@ -1521,6 +1521,10 @@ int start_topology_update(void) | |||
1521 | } | 1521 | } |
1522 | } | 1522 | } |
1523 | 1523 | ||
1524 | pr_info("Starting topology update%s%s\n", | ||
1525 | (prrn_enabled ? " prrn_enabled" : ""), | ||
1526 | (vphn_enabled ? " vphn_enabled" : "")); | ||
1527 | |||
1524 | return rc; | 1528 | return rc; |
1525 | } | 1529 | } |
1526 | 1530 | ||
@@ -1542,6 +1546,8 @@ int stop_topology_update(void) | |||
1542 | rc = del_timer_sync(&topology_timer); | 1546 | rc = del_timer_sync(&topology_timer); |
1543 | } | 1547 | } |
1544 | 1548 | ||
1549 | pr_info("Stopping topology update\n"); | ||
1550 | |||
1545 | return rc; | 1551 | return rc; |
1546 | } | 1552 | } |
1547 | 1553 | ||
diff --git a/arch/powerpc/mm/pgtable-book3e.c b/arch/powerpc/mm/pgtable-book3e.c index a2298930f990..e0ccf36714b2 100644 --- a/arch/powerpc/mm/pgtable-book3e.c +++ b/arch/powerpc/mm/pgtable-book3e.c | |||
@@ -42,7 +42,7 @@ int __meminit vmemmap_create_mapping(unsigned long start, | |||
42 | * thus must have the low bits clear | 42 | * thus must have the low bits clear |
43 | */ | 43 | */ |
44 | for (i = 0; i < page_size; i += PAGE_SIZE) | 44 | for (i = 0; i < page_size; i += PAGE_SIZE) |
45 | BUG_ON(map_kernel_page(start + i, phys, flags)); | 45 | BUG_ON(map_kernel_page(start + i, phys, __pgprot(flags))); |
46 | 46 | ||
47 | return 0; | 47 | return 0; |
48 | } | 48 | } |
@@ -70,7 +70,7 @@ static __ref void *early_alloc_pgtable(unsigned long size) | |||
70 | * map_kernel_page adds an entry to the ioremap page table | 70 | * map_kernel_page adds an entry to the ioremap page table |
71 | * and adds an entry to the HPT, possibly bolting it | 71 | * and adds an entry to the HPT, possibly bolting it |
72 | */ | 72 | */ |
73 | int map_kernel_page(unsigned long ea, unsigned long pa, unsigned long flags) | 73 | int map_kernel_page(unsigned long ea, unsigned long pa, pgprot_t prot) |
74 | { | 74 | { |
75 | pgd_t *pgdp; | 75 | pgd_t *pgdp; |
76 | pud_t *pudp; | 76 | pud_t *pudp; |
@@ -89,8 +89,6 @@ int map_kernel_page(unsigned long ea, unsigned long pa, unsigned long flags) | |||
89 | ptep = pte_alloc_kernel(pmdp, ea); | 89 | ptep = pte_alloc_kernel(pmdp, ea); |
90 | if (!ptep) | 90 | if (!ptep) |
91 | return -ENOMEM; | 91 | return -ENOMEM; |
92 | set_pte_at(&init_mm, ea, ptep, pfn_pte(pa >> PAGE_SHIFT, | ||
93 | __pgprot(flags))); | ||
94 | } else { | 92 | } else { |
95 | pgdp = pgd_offset_k(ea); | 93 | pgdp = pgd_offset_k(ea); |
96 | #ifndef __PAGETABLE_PUD_FOLDED | 94 | #ifndef __PAGETABLE_PUD_FOLDED |
@@ -113,9 +111,8 @@ int map_kernel_page(unsigned long ea, unsigned long pa, unsigned long flags) | |||
113 | pmd_populate_kernel(&init_mm, pmdp, ptep); | 111 | pmd_populate_kernel(&init_mm, pmdp, ptep); |
114 | } | 112 | } |
115 | ptep = pte_offset_kernel(pmdp, ea); | 113 | ptep = pte_offset_kernel(pmdp, ea); |
116 | set_pte_at(&init_mm, ea, ptep, pfn_pte(pa >> PAGE_SHIFT, | ||
117 | __pgprot(flags))); | ||
118 | } | 114 | } |
115 | set_pte_at(&init_mm, ea, ptep, pfn_pte(pa >> PAGE_SHIFT, prot)); | ||
119 | 116 | ||
120 | smp_wmb(); | 117 | smp_wmb(); |
121 | return 0; | 118 | return 0; |
diff --git a/arch/powerpc/mm/pgtable-book3s64.c b/arch/powerpc/mm/pgtable-book3s64.c index 01d7c0f7c4f0..9f93c9f985c5 100644 --- a/arch/powerpc/mm/pgtable-book3s64.c +++ b/arch/powerpc/mm/pgtable-book3s64.c | |||
@@ -69,9 +69,14 @@ void set_pmd_at(struct mm_struct *mm, unsigned long addr, | |||
69 | pmd_t *pmdp, pmd_t pmd) | 69 | pmd_t *pmdp, pmd_t pmd) |
70 | { | 70 | { |
71 | #ifdef CONFIG_DEBUG_VM | 71 | #ifdef CONFIG_DEBUG_VM |
72 | WARN_ON(pte_present(pmd_pte(*pmdp)) && !pte_protnone(pmd_pte(*pmdp))); | 72 | /* |
73 | * Make sure hardware valid bit is not set. We don't do | ||
74 | * tlb flush for this update. | ||
75 | */ | ||
76 | |||
77 | WARN_ON(pte_hw_valid(pmd_pte(*pmdp)) && !pte_protnone(pmd_pte(*pmdp))); | ||
73 | assert_spin_locked(pmd_lockptr(mm, pmdp)); | 78 | assert_spin_locked(pmd_lockptr(mm, pmdp)); |
74 | WARN_ON(!(pmd_trans_huge(pmd) || pmd_devmap(pmd))); | 79 | WARN_ON(!(pmd_large(pmd) || pmd_devmap(pmd))); |
75 | #endif | 80 | #endif |
76 | trace_hugepage_set_pmd(addr, pmd_val(pmd)); | 81 | trace_hugepage_set_pmd(addr, pmd_val(pmd)); |
77 | return set_pte_at(mm, addr, pmdp_ptep(pmdp), pmd_pte(pmd)); | 82 | return set_pte_at(mm, addr, pmdp_ptep(pmdp), pmd_pte(pmd)); |
@@ -106,7 +111,7 @@ pmd_t pmdp_invalidate(struct vm_area_struct *vma, unsigned long address, | |||
106 | { | 111 | { |
107 | unsigned long old_pmd; | 112 | unsigned long old_pmd; |
108 | 113 | ||
109 | old_pmd = pmd_hugepage_update(vma->vm_mm, address, pmdp, _PAGE_PRESENT, 0); | 114 | old_pmd = pmd_hugepage_update(vma->vm_mm, address, pmdp, _PAGE_PRESENT, _PAGE_INVALID); |
110 | flush_pmd_tlb_range(vma, address, address + HPAGE_PMD_SIZE); | 115 | flush_pmd_tlb_range(vma, address, address + HPAGE_PMD_SIZE); |
111 | /* | 116 | /* |
112 | * This ensures that generic code that rely on IRQ disabling | 117 | * This ensures that generic code that rely on IRQ disabling |
diff --git a/arch/powerpc/mm/pgtable-hash64.c b/arch/powerpc/mm/pgtable-hash64.c index 692bfc9e372c..c08d49046a96 100644 --- a/arch/powerpc/mm/pgtable-hash64.c +++ b/arch/powerpc/mm/pgtable-hash64.c | |||
@@ -142,7 +142,7 @@ void hash__vmemmap_remove_mapping(unsigned long start, | |||
142 | * map_kernel_page adds an entry to the ioremap page table | 142 | * map_kernel_page adds an entry to the ioremap page table |
143 | * and adds an entry to the HPT, possibly bolting it | 143 | * and adds an entry to the HPT, possibly bolting it |
144 | */ | 144 | */ |
145 | int hash__map_kernel_page(unsigned long ea, unsigned long pa, unsigned long flags) | 145 | int hash__map_kernel_page(unsigned long ea, unsigned long pa, pgprot_t prot) |
146 | { | 146 | { |
147 | pgd_t *pgdp; | 147 | pgd_t *pgdp; |
148 | pud_t *pudp; | 148 | pud_t *pudp; |
@@ -161,8 +161,7 @@ int hash__map_kernel_page(unsigned long ea, unsigned long pa, unsigned long flag | |||
161 | ptep = pte_alloc_kernel(pmdp, ea); | 161 | ptep = pte_alloc_kernel(pmdp, ea); |
162 | if (!ptep) | 162 | if (!ptep) |
163 | return -ENOMEM; | 163 | return -ENOMEM; |
164 | set_pte_at(&init_mm, ea, ptep, pfn_pte(pa >> PAGE_SHIFT, | 164 | set_pte_at(&init_mm, ea, ptep, pfn_pte(pa >> PAGE_SHIFT, prot)); |
165 | __pgprot(flags))); | ||
166 | } else { | 165 | } else { |
167 | /* | 166 | /* |
168 | * If the mm subsystem is not fully up, we cannot create a | 167 | * If the mm subsystem is not fully up, we cannot create a |
@@ -170,7 +169,7 @@ int hash__map_kernel_page(unsigned long ea, unsigned long pa, unsigned long flag | |||
170 | * entry in the hardware page table. | 169 | * entry in the hardware page table. |
171 | * | 170 | * |
172 | */ | 171 | */ |
173 | if (htab_bolt_mapping(ea, ea + PAGE_SIZE, pa, flags, | 172 | if (htab_bolt_mapping(ea, ea + PAGE_SIZE, pa, pgprot_val(prot), |
174 | mmu_io_psize, mmu_kernel_ssize)) { | 173 | mmu_io_psize, mmu_kernel_ssize)) { |
175 | printk(KERN_ERR "Failed to do bolted mapping IO " | 174 | printk(KERN_ERR "Failed to do bolted mapping IO " |
176 | "memory at %016lx !\n", pa); | 175 | "memory at %016lx !\n", pa); |
diff --git a/arch/powerpc/mm/pgtable-radix.c b/arch/powerpc/mm/pgtable-radix.c index c879979faa73..931156069a81 100644 --- a/arch/powerpc/mm/pgtable-radix.c +++ b/arch/powerpc/mm/pgtable-radix.c | |||
@@ -241,9 +241,8 @@ void radix__mark_initmem_nx(void) | |||
241 | } | 241 | } |
242 | #endif /* CONFIG_STRICT_KERNEL_RWX */ | 242 | #endif /* CONFIG_STRICT_KERNEL_RWX */ |
243 | 243 | ||
244 | static inline void __meminit print_mapping(unsigned long start, | 244 | static inline void __meminit |
245 | unsigned long end, | 245 | print_mapping(unsigned long start, unsigned long end, unsigned long size, bool exec) |
246 | unsigned long size) | ||
247 | { | 246 | { |
248 | char buf[10]; | 247 | char buf[10]; |
249 | 248 | ||
@@ -252,7 +251,17 @@ static inline void __meminit print_mapping(unsigned long start, | |||
252 | 251 | ||
253 | string_get_size(size, 1, STRING_UNITS_2, buf, sizeof(buf)); | 252 | string_get_size(size, 1, STRING_UNITS_2, buf, sizeof(buf)); |
254 | 253 | ||
255 | pr_info("Mapped 0x%016lx-0x%016lx with %s pages\n", start, end, buf); | 254 | pr_info("Mapped 0x%016lx-0x%016lx with %s pages%s\n", start, end, buf, |
255 | exec ? " (exec)" : ""); | ||
256 | } | ||
257 | |||
258 | static unsigned long next_boundary(unsigned long addr, unsigned long end) | ||
259 | { | ||
260 | #ifdef CONFIG_STRICT_KERNEL_RWX | ||
261 | if (addr < __pa_symbol(__init_begin)) | ||
262 | return __pa_symbol(__init_begin); | ||
263 | #endif | ||
264 | return end; | ||
256 | } | 265 | } |
257 | 266 | ||
258 | static int __meminit create_physical_mapping(unsigned long start, | 267 | static int __meminit create_physical_mapping(unsigned long start, |
@@ -260,13 +269,8 @@ static int __meminit create_physical_mapping(unsigned long start, | |||
260 | int nid) | 269 | int nid) |
261 | { | 270 | { |
262 | unsigned long vaddr, addr, mapping_size = 0; | 271 | unsigned long vaddr, addr, mapping_size = 0; |
272 | bool prev_exec, exec = false; | ||
263 | pgprot_t prot; | 273 | pgprot_t prot; |
264 | unsigned long max_mapping_size; | ||
265 | #ifdef CONFIG_STRICT_KERNEL_RWX | ||
266 | int split_text_mapping = 1; | ||
267 | #else | ||
268 | int split_text_mapping = 0; | ||
269 | #endif | ||
270 | int psize; | 274 | int psize; |
271 | 275 | ||
272 | start = _ALIGN_UP(start, PAGE_SIZE); | 276 | start = _ALIGN_UP(start, PAGE_SIZE); |
@@ -274,14 +278,12 @@ static int __meminit create_physical_mapping(unsigned long start, | |||
274 | unsigned long gap, previous_size; | 278 | unsigned long gap, previous_size; |
275 | int rc; | 279 | int rc; |
276 | 280 | ||
277 | gap = end - addr; | 281 | gap = next_boundary(addr, end) - addr; |
278 | previous_size = mapping_size; | 282 | previous_size = mapping_size; |
279 | max_mapping_size = PUD_SIZE; | 283 | prev_exec = exec; |
280 | 284 | ||
281 | retry: | ||
282 | if (IS_ALIGNED(addr, PUD_SIZE) && gap >= PUD_SIZE && | 285 | if (IS_ALIGNED(addr, PUD_SIZE) && gap >= PUD_SIZE && |
283 | mmu_psize_defs[MMU_PAGE_1G].shift && | 286 | mmu_psize_defs[MMU_PAGE_1G].shift) { |
284 | PUD_SIZE <= max_mapping_size) { | ||
285 | mapping_size = PUD_SIZE; | 287 | mapping_size = PUD_SIZE; |
286 | psize = MMU_PAGE_1G; | 288 | psize = MMU_PAGE_1G; |
287 | } else if (IS_ALIGNED(addr, PMD_SIZE) && gap >= PMD_SIZE && | 289 | } else if (IS_ALIGNED(addr, PMD_SIZE) && gap >= PMD_SIZE && |
@@ -293,32 +295,21 @@ retry: | |||
293 | psize = mmu_virtual_psize; | 295 | psize = mmu_virtual_psize; |
294 | } | 296 | } |
295 | 297 | ||
296 | if (split_text_mapping && (mapping_size == PUD_SIZE) && | ||
297 | (addr <= __pa_symbol(__init_begin)) && | ||
298 | (addr + mapping_size) >= __pa_symbol(_stext)) { | ||
299 | max_mapping_size = PMD_SIZE; | ||
300 | goto retry; | ||
301 | } | ||
302 | |||
303 | if (split_text_mapping && (mapping_size == PMD_SIZE) && | ||
304 | (addr <= __pa_symbol(__init_begin)) && | ||
305 | (addr + mapping_size) >= __pa_symbol(_stext)) { | ||
306 | mapping_size = PAGE_SIZE; | ||
307 | psize = mmu_virtual_psize; | ||
308 | } | ||
309 | |||
310 | if (mapping_size != previous_size) { | ||
311 | print_mapping(start, addr, previous_size); | ||
312 | start = addr; | ||
313 | } | ||
314 | |||
315 | vaddr = (unsigned long)__va(addr); | 298 | vaddr = (unsigned long)__va(addr); |
316 | 299 | ||
317 | if (overlaps_kernel_text(vaddr, vaddr + mapping_size) || | 300 | if (overlaps_kernel_text(vaddr, vaddr + mapping_size) || |
318 | overlaps_interrupt_vector_text(vaddr, vaddr + mapping_size)) | 301 | overlaps_interrupt_vector_text(vaddr, vaddr + mapping_size)) { |
319 | prot = PAGE_KERNEL_X; | 302 | prot = PAGE_KERNEL_X; |
320 | else | 303 | exec = true; |
304 | } else { | ||
321 | prot = PAGE_KERNEL; | 305 | prot = PAGE_KERNEL; |
306 | exec = false; | ||
307 | } | ||
308 | |||
309 | if (mapping_size != previous_size || exec != prev_exec) { | ||
310 | print_mapping(start, addr, previous_size, prev_exec); | ||
311 | start = addr; | ||
312 | } | ||
322 | 313 | ||
323 | rc = __map_kernel_page(vaddr, addr, prot, mapping_size, nid, start, end); | 314 | rc = __map_kernel_page(vaddr, addr, prot, mapping_size, nid, start, end); |
324 | if (rc) | 315 | if (rc) |
@@ -327,7 +318,7 @@ retry: | |||
327 | update_page_count(psize, 1); | 318 | update_page_count(psize, 1); |
328 | } | 319 | } |
329 | 320 | ||
330 | print_mapping(start, addr, mapping_size); | 321 | print_mapping(start, addr, mapping_size, exec); |
331 | return 0; | 322 | return 0; |
332 | } | 323 | } |
333 | 324 | ||
diff --git a/arch/powerpc/mm/pgtable.c b/arch/powerpc/mm/pgtable.c index d71c7777669c..010e1c616cb2 100644 --- a/arch/powerpc/mm/pgtable.c +++ b/arch/powerpc/mm/pgtable.c | |||
@@ -44,20 +44,13 @@ static inline int is_exec_fault(void) | |||
44 | static inline int pte_looks_normal(pte_t pte) | 44 | static inline int pte_looks_normal(pte_t pte) |
45 | { | 45 | { |
46 | 46 | ||
47 | #if defined(CONFIG_PPC_BOOK3S_64) | 47 | if (pte_present(pte) && !pte_special(pte)) { |
48 | if ((pte_val(pte) & (_PAGE_PRESENT | _PAGE_SPECIAL)) == _PAGE_PRESENT) { | ||
49 | if (pte_ci(pte)) | 48 | if (pte_ci(pte)) |
50 | return 0; | 49 | return 0; |
51 | if (pte_user(pte)) | 50 | if (pte_user(pte)) |
52 | return 1; | 51 | return 1; |
53 | } | 52 | } |
54 | return 0; | 53 | return 0; |
55 | #else | ||
56 | return (pte_val(pte) & | ||
57 | (_PAGE_PRESENT | _PAGE_SPECIAL | _PAGE_NO_CACHE | _PAGE_USER | | ||
58 | _PAGE_PRIVILEGED)) == | ||
59 | (_PAGE_PRESENT | _PAGE_USER); | ||
60 | #endif | ||
61 | } | 54 | } |
62 | 55 | ||
63 | static struct page *maybe_pte_to_page(pte_t pte) | 56 | static struct page *maybe_pte_to_page(pte_t pte) |
@@ -73,7 +66,7 @@ static struct page *maybe_pte_to_page(pte_t pte) | |||
73 | return page; | 66 | return page; |
74 | } | 67 | } |
75 | 68 | ||
76 | #if defined(CONFIG_PPC_STD_MMU) || _PAGE_EXEC == 0 | 69 | #ifdef CONFIG_PPC_BOOK3S |
77 | 70 | ||
78 | /* Server-style MMU handles coherency when hashing if HW exec permission | 71 | /* Server-style MMU handles coherency when hashing if HW exec permission |
79 | * is supposed per page (currently 64-bit only). If not, then, we always | 72 | * is supposed per page (currently 64-bit only). If not, then, we always |
@@ -106,7 +99,7 @@ static pte_t set_access_flags_filter(pte_t pte, struct vm_area_struct *vma, | |||
106 | return pte; | 99 | return pte; |
107 | } | 100 | } |
108 | 101 | ||
109 | #else /* defined(CONFIG_PPC_STD_MMU) || _PAGE_EXEC == 0 */ | 102 | #else /* CONFIG_PPC_BOOK3S */ |
110 | 103 | ||
111 | /* Embedded type MMU with HW exec support. This is a bit more complicated | 104 | /* Embedded type MMU with HW exec support. This is a bit more complicated |
112 | * as we don't have two bits to spare for _PAGE_EXEC and _PAGE_HWEXEC so | 105 | * as we don't have two bits to spare for _PAGE_EXEC and _PAGE_HWEXEC so |
@@ -117,7 +110,7 @@ static pte_t set_pte_filter(pte_t pte) | |||
117 | struct page *pg; | 110 | struct page *pg; |
118 | 111 | ||
119 | /* No exec permission in the first place, move on */ | 112 | /* No exec permission in the first place, move on */ |
120 | if (!(pte_val(pte) & _PAGE_EXEC) || !pte_looks_normal(pte)) | 113 | if (!pte_exec(pte) || !pte_looks_normal(pte)) |
121 | return pte; | 114 | return pte; |
122 | 115 | ||
123 | /* If you set _PAGE_EXEC on weird pages you're on your own */ | 116 | /* If you set _PAGE_EXEC on weird pages you're on your own */ |
@@ -137,7 +130,7 @@ static pte_t set_pte_filter(pte_t pte) | |||
137 | } | 130 | } |
138 | 131 | ||
139 | /* Else, we filter out _PAGE_EXEC */ | 132 | /* Else, we filter out _PAGE_EXEC */ |
140 | return __pte(pte_val(pte) & ~_PAGE_EXEC); | 133 | return pte_exprotect(pte); |
141 | } | 134 | } |
142 | 135 | ||
143 | static pte_t set_access_flags_filter(pte_t pte, struct vm_area_struct *vma, | 136 | static pte_t set_access_flags_filter(pte_t pte, struct vm_area_struct *vma, |
@@ -150,7 +143,7 @@ static pte_t set_access_flags_filter(pte_t pte, struct vm_area_struct *vma, | |||
150 | * if necessary. Also if _PAGE_EXEC is already set, same deal, | 143 | * if necessary. Also if _PAGE_EXEC is already set, same deal, |
151 | * we just bail out | 144 | * we just bail out |
152 | */ | 145 | */ |
153 | if (dirty || (pte_val(pte) & _PAGE_EXEC) || !is_exec_fault()) | 146 | if (dirty || pte_exec(pte) || !is_exec_fault()) |
154 | return pte; | 147 | return pte; |
155 | 148 | ||
156 | #ifdef CONFIG_DEBUG_VM | 149 | #ifdef CONFIG_DEBUG_VM |
@@ -176,10 +169,10 @@ static pte_t set_access_flags_filter(pte_t pte, struct vm_area_struct *vma, | |||
176 | set_bit(PG_arch_1, &pg->flags); | 169 | set_bit(PG_arch_1, &pg->flags); |
177 | 170 | ||
178 | bail: | 171 | bail: |
179 | return __pte(pte_val(pte) | _PAGE_EXEC); | 172 | return pte_mkexec(pte); |
180 | } | 173 | } |
181 | 174 | ||
182 | #endif /* !(defined(CONFIG_PPC_STD_MMU) || _PAGE_EXEC == 0) */ | 175 | #endif /* CONFIG_PPC_BOOK3S */ |
183 | 176 | ||
184 | /* | 177 | /* |
185 | * set_pte stores a linux PTE into the linux page table. | 178 | * set_pte stores a linux PTE into the linux page table. |
@@ -188,14 +181,13 @@ void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, | |||
188 | pte_t pte) | 181 | pte_t pte) |
189 | { | 182 | { |
190 | /* | 183 | /* |
191 | * When handling numa faults, we already have the pte marked | 184 | * Make sure hardware valid bit is not set. We don't do |
192 | * _PAGE_PRESENT, but we can be sure that it is not in hpte. | 185 | * tlb flush for this update. |
193 | * Hence we can use set_pte_at for them. | ||
194 | */ | 186 | */ |
195 | VM_WARN_ON(pte_present(*ptep) && !pte_protnone(*ptep)); | 187 | VM_WARN_ON(pte_hw_valid(*ptep) && !pte_protnone(*ptep)); |
196 | 188 | ||
197 | /* Add the pte bit when trying to set a pte */ | 189 | /* Add the pte bit when trying to set a pte */ |
198 | pte = __pte(pte_val(pte) | _PAGE_PTE); | 190 | pte = pte_mkpte(pte); |
199 | 191 | ||
200 | /* Note: mm->context.id might not yet have been assigned as | 192 | /* Note: mm->context.id might not yet have been assigned as |
201 | * this context might not have been activated yet when this | 193 | * this context might not have been activated yet when this |
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c index 120a49bfb9c6..5877f5aa8f5d 100644 --- a/arch/powerpc/mm/pgtable_32.c +++ b/arch/powerpc/mm/pgtable_32.c | |||
@@ -76,56 +76,69 @@ pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address) | |||
76 | void __iomem * | 76 | void __iomem * |
77 | ioremap(phys_addr_t addr, unsigned long size) | 77 | ioremap(phys_addr_t addr, unsigned long size) |
78 | { | 78 | { |
79 | return __ioremap_caller(addr, size, _PAGE_NO_CACHE | _PAGE_GUARDED, | 79 | pgprot_t prot = pgprot_noncached(PAGE_KERNEL); |
80 | __builtin_return_address(0)); | 80 | |
81 | return __ioremap_caller(addr, size, prot, __builtin_return_address(0)); | ||
81 | } | 82 | } |
82 | EXPORT_SYMBOL(ioremap); | 83 | EXPORT_SYMBOL(ioremap); |
83 | 84 | ||
84 | void __iomem * | 85 | void __iomem * |
85 | ioremap_wc(phys_addr_t addr, unsigned long size) | 86 | ioremap_wc(phys_addr_t addr, unsigned long size) |
86 | { | 87 | { |
87 | return __ioremap_caller(addr, size, _PAGE_NO_CACHE, | 88 | pgprot_t prot = pgprot_noncached_wc(PAGE_KERNEL); |
88 | __builtin_return_address(0)); | 89 | |
90 | return __ioremap_caller(addr, size, prot, __builtin_return_address(0)); | ||
89 | } | 91 | } |
90 | EXPORT_SYMBOL(ioremap_wc); | 92 | EXPORT_SYMBOL(ioremap_wc); |
91 | 93 | ||
92 | void __iomem * | 94 | void __iomem * |
95 | ioremap_wt(phys_addr_t addr, unsigned long size) | ||
96 | { | ||
97 | pgprot_t prot = pgprot_cached_wthru(PAGE_KERNEL); | ||
98 | |||
99 | return __ioremap_caller(addr, size, prot, __builtin_return_address(0)); | ||
100 | } | ||
101 | EXPORT_SYMBOL(ioremap_wt); | ||
102 | |||
103 | void __iomem * | ||
104 | ioremap_coherent(phys_addr_t addr, unsigned long size) | ||
105 | { | ||
106 | pgprot_t prot = pgprot_cached(PAGE_KERNEL); | ||
107 | |||
108 | return __ioremap_caller(addr, size, prot, __builtin_return_address(0)); | ||
109 | } | ||
110 | EXPORT_SYMBOL(ioremap_coherent); | ||
111 | |||
112 | void __iomem * | ||
93 | ioremap_prot(phys_addr_t addr, unsigned long size, unsigned long flags) | 113 | ioremap_prot(phys_addr_t addr, unsigned long size, unsigned long flags) |
94 | { | 114 | { |
115 | pte_t pte = __pte(flags); | ||
116 | |||
95 | /* writeable implies dirty for kernel addresses */ | 117 | /* writeable implies dirty for kernel addresses */ |
96 | if ((flags & (_PAGE_RW | _PAGE_RO)) != _PAGE_RO) | 118 | if (pte_write(pte)) |
97 | flags |= _PAGE_DIRTY | _PAGE_HWWRITE; | 119 | pte = pte_mkdirty(pte); |
98 | 120 | ||
99 | /* we don't want to let _PAGE_USER and _PAGE_EXEC leak out */ | 121 | /* we don't want to let _PAGE_USER and _PAGE_EXEC leak out */ |
100 | flags &= ~(_PAGE_USER | _PAGE_EXEC); | 122 | pte = pte_exprotect(pte); |
101 | flags |= _PAGE_PRIVILEGED; | 123 | pte = pte_mkprivileged(pte); |
102 | 124 | ||
103 | return __ioremap_caller(addr, size, flags, __builtin_return_address(0)); | 125 | return __ioremap_caller(addr, size, pte_pgprot(pte), __builtin_return_address(0)); |
104 | } | 126 | } |
105 | EXPORT_SYMBOL(ioremap_prot); | 127 | EXPORT_SYMBOL(ioremap_prot); |
106 | 128 | ||
107 | void __iomem * | 129 | void __iomem * |
108 | __ioremap(phys_addr_t addr, unsigned long size, unsigned long flags) | 130 | __ioremap(phys_addr_t addr, unsigned long size, unsigned long flags) |
109 | { | 131 | { |
110 | return __ioremap_caller(addr, size, flags, __builtin_return_address(0)); | 132 | return __ioremap_caller(addr, size, __pgprot(flags), __builtin_return_address(0)); |
111 | } | 133 | } |
112 | 134 | ||
113 | void __iomem * | 135 | void __iomem * |
114 | __ioremap_caller(phys_addr_t addr, unsigned long size, unsigned long flags, | 136 | __ioremap_caller(phys_addr_t addr, unsigned long size, pgprot_t prot, void *caller) |
115 | void *caller) | ||
116 | { | 137 | { |
117 | unsigned long v, i; | 138 | unsigned long v, i; |
118 | phys_addr_t p; | 139 | phys_addr_t p; |
119 | int err; | 140 | int err; |
120 | 141 | ||
121 | /* Make sure we have the base flags */ | ||
122 | if ((flags & _PAGE_PRESENT) == 0) | ||
123 | flags |= pgprot_val(PAGE_KERNEL); | ||
124 | |||
125 | /* Non-cacheable page cannot be coherent */ | ||
126 | if (flags & _PAGE_NO_CACHE) | ||
127 | flags &= ~_PAGE_COHERENT; | ||
128 | |||
129 | /* | 142 | /* |
130 | * Choose an address to map it to. | 143 | * Choose an address to map it to. |
131 | * Once the vmalloc system is running, we use it. | 144 | * Once the vmalloc system is running, we use it. |
@@ -183,7 +196,7 @@ __ioremap_caller(phys_addr_t addr, unsigned long size, unsigned long flags, | |||
183 | 196 | ||
184 | err = 0; | 197 | err = 0; |
185 | for (i = 0; i < size && err == 0; i += PAGE_SIZE) | 198 | for (i = 0; i < size && err == 0; i += PAGE_SIZE) |
186 | err = map_kernel_page(v+i, p+i, flags); | 199 | err = map_kernel_page(v + i, p + i, prot); |
187 | if (err) { | 200 | if (err) { |
188 | if (slab_is_available()) | 201 | if (slab_is_available()) |
189 | vunmap((void *)v); | 202 | vunmap((void *)v); |
@@ -209,7 +222,7 @@ void iounmap(volatile void __iomem *addr) | |||
209 | } | 222 | } |
210 | EXPORT_SYMBOL(iounmap); | 223 | EXPORT_SYMBOL(iounmap); |
211 | 224 | ||
212 | int map_kernel_page(unsigned long va, phys_addr_t pa, int flags) | 225 | int map_kernel_page(unsigned long va, phys_addr_t pa, pgprot_t prot) |
213 | { | 226 | { |
214 | pmd_t *pd; | 227 | pmd_t *pd; |
215 | pte_t *pg; | 228 | pte_t *pg; |
@@ -224,10 +237,8 @@ int map_kernel_page(unsigned long va, phys_addr_t pa, int flags) | |||
224 | /* The PTE should never be already set nor present in the | 237 | /* The PTE should never be already set nor present in the |
225 | * hash table | 238 | * hash table |
226 | */ | 239 | */ |
227 | BUG_ON((pte_val(*pg) & (_PAGE_PRESENT | _PAGE_HASHPTE)) && | 240 | BUG_ON((pte_present(*pg) | pte_hashpte(*pg)) && pgprot_val(prot)); |
228 | flags); | 241 | set_pte_at(&init_mm, va, pg, pfn_pte(pa >> PAGE_SHIFT, prot)); |
229 | set_pte_at(&init_mm, va, pg, pfn_pte(pa >> PAGE_SHIFT, | ||
230 | __pgprot(flags))); | ||
231 | } | 242 | } |
232 | smp_wmb(); | 243 | smp_wmb(); |
233 | return err; | 244 | return err; |
@@ -238,7 +249,7 @@ int map_kernel_page(unsigned long va, phys_addr_t pa, int flags) | |||
238 | */ | 249 | */ |
239 | static void __init __mapin_ram_chunk(unsigned long offset, unsigned long top) | 250 | static void __init __mapin_ram_chunk(unsigned long offset, unsigned long top) |
240 | { | 251 | { |
241 | unsigned long v, s, f; | 252 | unsigned long v, s; |
242 | phys_addr_t p; | 253 | phys_addr_t p; |
243 | int ktext; | 254 | int ktext; |
244 | 255 | ||
@@ -248,11 +259,10 @@ static void __init __mapin_ram_chunk(unsigned long offset, unsigned long top) | |||
248 | for (; s < top; s += PAGE_SIZE) { | 259 | for (; s < top; s += PAGE_SIZE) { |
249 | ktext = ((char *)v >= _stext && (char *)v < etext) || | 260 | ktext = ((char *)v >= _stext && (char *)v < etext) || |
250 | ((char *)v >= _sinittext && (char *)v < _einittext); | 261 | ((char *)v >= _sinittext && (char *)v < _einittext); |
251 | f = ktext ? pgprot_val(PAGE_KERNEL_TEXT) : pgprot_val(PAGE_KERNEL); | 262 | map_kernel_page(v, p, ktext ? PAGE_KERNEL_TEXT : PAGE_KERNEL); |
252 | map_kernel_page(v, p, f); | ||
253 | #ifdef CONFIG_PPC_STD_MMU_32 | 263 | #ifdef CONFIG_PPC_STD_MMU_32 |
254 | if (ktext) | 264 | if (ktext) |
255 | hash_preload(&init_mm, v, 0, 0x300); | 265 | hash_preload(&init_mm, v, false, 0x300); |
256 | #endif | 266 | #endif |
257 | v += PAGE_SIZE; | 267 | v += PAGE_SIZE; |
258 | p += PAGE_SIZE; | 268 | p += PAGE_SIZE; |
diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c index 53e9eeecd5d4..fb1375c07e8c 100644 --- a/arch/powerpc/mm/pgtable_64.c +++ b/arch/powerpc/mm/pgtable_64.c | |||
@@ -113,17 +113,12 @@ unsigned long ioremap_bot = IOREMAP_BASE; | |||
113 | * __ioremap_at - Low level function to establish the page tables | 113 | * __ioremap_at - Low level function to establish the page tables |
114 | * for an IO mapping | 114 | * for an IO mapping |
115 | */ | 115 | */ |
116 | void __iomem * __ioremap_at(phys_addr_t pa, void *ea, unsigned long size, | 116 | void __iomem *__ioremap_at(phys_addr_t pa, void *ea, unsigned long size, pgprot_t prot) |
117 | unsigned long flags) | ||
118 | { | 117 | { |
119 | unsigned long i; | 118 | unsigned long i; |
120 | 119 | ||
121 | /* Make sure we have the base flags */ | ||
122 | if ((flags & _PAGE_PRESENT) == 0) | ||
123 | flags |= pgprot_val(PAGE_KERNEL); | ||
124 | |||
125 | /* We don't support the 4K PFN hack with ioremap */ | 120 | /* We don't support the 4K PFN hack with ioremap */ |
126 | if (flags & H_PAGE_4K_PFN) | 121 | if (pgprot_val(prot) & H_PAGE_4K_PFN) |
127 | return NULL; | 122 | return NULL; |
128 | 123 | ||
129 | WARN_ON(pa & ~PAGE_MASK); | 124 | WARN_ON(pa & ~PAGE_MASK); |
@@ -131,7 +126,7 @@ void __iomem * __ioremap_at(phys_addr_t pa, void *ea, unsigned long size, | |||
131 | WARN_ON(size & ~PAGE_MASK); | 126 | WARN_ON(size & ~PAGE_MASK); |
132 | 127 | ||
133 | for (i = 0; i < size; i += PAGE_SIZE) | 128 | for (i = 0; i < size; i += PAGE_SIZE) |
134 | if (map_kernel_page((unsigned long)ea+i, pa+i, flags)) | 129 | if (map_kernel_page((unsigned long)ea + i, pa + i, prot)) |
135 | return NULL; | 130 | return NULL; |
136 | 131 | ||
137 | return (void __iomem *)ea; | 132 | return (void __iomem *)ea; |
@@ -152,7 +147,7 @@ void __iounmap_at(void *ea, unsigned long size) | |||
152 | } | 147 | } |
153 | 148 | ||
154 | void __iomem * __ioremap_caller(phys_addr_t addr, unsigned long size, | 149 | void __iomem * __ioremap_caller(phys_addr_t addr, unsigned long size, |
155 | unsigned long flags, void *caller) | 150 | pgprot_t prot, void *caller) |
156 | { | 151 | { |
157 | phys_addr_t paligned; | 152 | phys_addr_t paligned; |
158 | void __iomem *ret; | 153 | void __iomem *ret; |
@@ -182,11 +177,11 @@ void __iomem * __ioremap_caller(phys_addr_t addr, unsigned long size, | |||
182 | return NULL; | 177 | return NULL; |
183 | 178 | ||
184 | area->phys_addr = paligned; | 179 | area->phys_addr = paligned; |
185 | ret = __ioremap_at(paligned, area->addr, size, flags); | 180 | ret = __ioremap_at(paligned, area->addr, size, prot); |
186 | if (!ret) | 181 | if (!ret) |
187 | vunmap(area->addr); | 182 | vunmap(area->addr); |
188 | } else { | 183 | } else { |
189 | ret = __ioremap_at(paligned, (void *)ioremap_bot, size, flags); | 184 | ret = __ioremap_at(paligned, (void *)ioremap_bot, size, prot); |
190 | if (ret) | 185 | if (ret) |
191 | ioremap_bot += size; | 186 | ioremap_bot += size; |
192 | } | 187 | } |
@@ -199,49 +194,59 @@ void __iomem * __ioremap_caller(phys_addr_t addr, unsigned long size, | |||
199 | void __iomem * __ioremap(phys_addr_t addr, unsigned long size, | 194 | void __iomem * __ioremap(phys_addr_t addr, unsigned long size, |
200 | unsigned long flags) | 195 | unsigned long flags) |
201 | { | 196 | { |
202 | return __ioremap_caller(addr, size, flags, __builtin_return_address(0)); | 197 | return __ioremap_caller(addr, size, __pgprot(flags), __builtin_return_address(0)); |
203 | } | 198 | } |
204 | 199 | ||
205 | void __iomem * ioremap(phys_addr_t addr, unsigned long size) | 200 | void __iomem * ioremap(phys_addr_t addr, unsigned long size) |
206 | { | 201 | { |
207 | unsigned long flags = pgprot_val(pgprot_noncached(__pgprot(0))); | 202 | pgprot_t prot = pgprot_noncached(PAGE_KERNEL); |
208 | void *caller = __builtin_return_address(0); | 203 | void *caller = __builtin_return_address(0); |
209 | 204 | ||
210 | if (ppc_md.ioremap) | 205 | if (ppc_md.ioremap) |
211 | return ppc_md.ioremap(addr, size, flags, caller); | 206 | return ppc_md.ioremap(addr, size, prot, caller); |
212 | return __ioremap_caller(addr, size, flags, caller); | 207 | return __ioremap_caller(addr, size, prot, caller); |
213 | } | 208 | } |
214 | 209 | ||
215 | void __iomem * ioremap_wc(phys_addr_t addr, unsigned long size) | 210 | void __iomem * ioremap_wc(phys_addr_t addr, unsigned long size) |
216 | { | 211 | { |
217 | unsigned long flags = pgprot_val(pgprot_noncached_wc(__pgprot(0))); | 212 | pgprot_t prot = pgprot_noncached_wc(PAGE_KERNEL); |
213 | void *caller = __builtin_return_address(0); | ||
214 | |||
215 | if (ppc_md.ioremap) | ||
216 | return ppc_md.ioremap(addr, size, prot, caller); | ||
217 | return __ioremap_caller(addr, size, prot, caller); | ||
218 | } | ||
219 | |||
220 | void __iomem *ioremap_coherent(phys_addr_t addr, unsigned long size) | ||
221 | { | ||
222 | pgprot_t prot = pgprot_cached(PAGE_KERNEL); | ||
218 | void *caller = __builtin_return_address(0); | 223 | void *caller = __builtin_return_address(0); |
219 | 224 | ||
220 | if (ppc_md.ioremap) | 225 | if (ppc_md.ioremap) |
221 | return ppc_md.ioremap(addr, size, flags, caller); | 226 | return ppc_md.ioremap(addr, size, prot, caller); |
222 | return __ioremap_caller(addr, size, flags, caller); | 227 | return __ioremap_caller(addr, size, prot, caller); |
223 | } | 228 | } |
224 | 229 | ||
225 | void __iomem * ioremap_prot(phys_addr_t addr, unsigned long size, | 230 | void __iomem * ioremap_prot(phys_addr_t addr, unsigned long size, |
226 | unsigned long flags) | 231 | unsigned long flags) |
227 | { | 232 | { |
233 | pte_t pte = __pte(flags); | ||
228 | void *caller = __builtin_return_address(0); | 234 | void *caller = __builtin_return_address(0); |
229 | 235 | ||
230 | /* writeable implies dirty for kernel addresses */ | 236 | /* writeable implies dirty for kernel addresses */ |
231 | if (flags & _PAGE_WRITE) | 237 | if (pte_write(pte)) |
232 | flags |= _PAGE_DIRTY; | 238 | pte = pte_mkdirty(pte); |
233 | 239 | ||
234 | /* we don't want to let _PAGE_EXEC leak out */ | 240 | /* we don't want to let _PAGE_EXEC leak out */ |
235 | flags &= ~_PAGE_EXEC; | 241 | pte = pte_exprotect(pte); |
236 | /* | 242 | /* |
237 | * Force kernel mapping. | 243 | * Force kernel mapping. |
238 | */ | 244 | */ |
239 | flags &= ~_PAGE_USER; | 245 | pte = pte_mkprivileged(pte); |
240 | flags |= _PAGE_PRIVILEGED; | ||
241 | 246 | ||
242 | if (ppc_md.ioremap) | 247 | if (ppc_md.ioremap) |
243 | return ppc_md.ioremap(addr, size, flags, caller); | 248 | return ppc_md.ioremap(addr, size, pte_pgprot(pte), caller); |
244 | return __ioremap_caller(addr, size, flags, caller); | 249 | return __ioremap_caller(addr, size, pte_pgprot(pte), caller); |
245 | } | 250 | } |
246 | 251 | ||
247 | 252 | ||
@@ -306,7 +311,7 @@ struct page *pud_page(pud_t pud) | |||
306 | */ | 311 | */ |
307 | struct page *pmd_page(pmd_t pmd) | 312 | struct page *pmd_page(pmd_t pmd) |
308 | { | 313 | { |
309 | if (pmd_trans_huge(pmd) || pmd_huge(pmd) || pmd_devmap(pmd)) | 314 | if (pmd_large(pmd) || pmd_huge(pmd) || pmd_devmap(pmd)) |
310 | return pte_page(pmd_pte(pmd)); | 315 | return pte_page(pmd_pte(pmd)); |
311 | return virt_to_page(pmd_page_vaddr(pmd)); | 316 | return virt_to_page(pmd_page_vaddr(pmd)); |
312 | } | 317 | } |
diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c index bea6c544e38f..38a793bfca37 100644 --- a/arch/powerpc/mm/ppc_mmu_32.c +++ b/arch/powerpc/mm/ppc_mmu_32.c | |||
@@ -163,7 +163,7 @@ void __init setbat(int index, unsigned long virt, phys_addr_t phys, | |||
163 | * Preload a translation in the hash table | 163 | * Preload a translation in the hash table |
164 | */ | 164 | */ |
165 | void hash_preload(struct mm_struct *mm, unsigned long ea, | 165 | void hash_preload(struct mm_struct *mm, unsigned long ea, |
166 | unsigned long access, unsigned long trap) | 166 | bool is_exec, unsigned long trap) |
167 | { | 167 | { |
168 | pmd_t *pmd; | 168 | pmd_t *pmd; |
169 | 169 | ||
diff --git a/arch/powerpc/mm/slb.c b/arch/powerpc/mm/slb.c index 9f574e59d178..c3fdf2969d9f 100644 --- a/arch/powerpc/mm/slb.c +++ b/arch/powerpc/mm/slb.c | |||
@@ -14,6 +14,7 @@ | |||
14 | * 2 of the License, or (at your option) any later version. | 14 | * 2 of the License, or (at your option) any later version. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <asm/asm-prototypes.h> | ||
17 | #include <asm/pgtable.h> | 18 | #include <asm/pgtable.h> |
18 | #include <asm/mmu.h> | 19 | #include <asm/mmu.h> |
19 | #include <asm/mmu_context.h> | 20 | #include <asm/mmu_context.h> |
@@ -30,11 +31,10 @@ | |||
30 | 31 | ||
31 | enum slb_index { | 32 | enum slb_index { |
32 | LINEAR_INDEX = 0, /* Kernel linear map (0xc000000000000000) */ | 33 | LINEAR_INDEX = 0, /* Kernel linear map (0xc000000000000000) */ |
33 | VMALLOC_INDEX = 1, /* Kernel virtual map (0xd000000000000000) */ | 34 | KSTACK_INDEX = 1, /* Kernel stack map */ |
34 | KSTACK_INDEX = 2, /* Kernel stack map */ | ||
35 | }; | 35 | }; |
36 | 36 | ||
37 | extern void slb_allocate(unsigned long ea); | 37 | static long slb_allocate_user(struct mm_struct *mm, unsigned long ea); |
38 | 38 | ||
39 | #define slb_esid_mask(ssize) \ | 39 | #define slb_esid_mask(ssize) \ |
40 | (((ssize) == MMU_SEGSIZE_256M)? ESID_MASK: ESID_MASK_1T) | 40 | (((ssize) == MMU_SEGSIZE_256M)? ESID_MASK: ESID_MASK_1T) |
@@ -45,13 +45,43 @@ static inline unsigned long mk_esid_data(unsigned long ea, int ssize, | |||
45 | return (ea & slb_esid_mask(ssize)) | SLB_ESID_V | index; | 45 | return (ea & slb_esid_mask(ssize)) | SLB_ESID_V | index; |
46 | } | 46 | } |
47 | 47 | ||
48 | static inline unsigned long mk_vsid_data(unsigned long ea, int ssize, | 48 | static inline unsigned long __mk_vsid_data(unsigned long vsid, int ssize, |
49 | unsigned long flags) | 49 | unsigned long flags) |
50 | { | 50 | { |
51 | return (get_kernel_vsid(ea, ssize) << slb_vsid_shift(ssize)) | flags | | 51 | return (vsid << slb_vsid_shift(ssize)) | flags | |
52 | ((unsigned long) ssize << SLB_VSID_SSIZE_SHIFT); | 52 | ((unsigned long) ssize << SLB_VSID_SSIZE_SHIFT); |
53 | } | 53 | } |
54 | 54 | ||
55 | static inline unsigned long mk_vsid_data(unsigned long ea, int ssize, | ||
56 | unsigned long flags) | ||
57 | { | ||
58 | return __mk_vsid_data(get_kernel_vsid(ea, ssize), ssize, flags); | ||
59 | } | ||
60 | |||
61 | static void assert_slb_exists(unsigned long ea) | ||
62 | { | ||
63 | #ifdef CONFIG_DEBUG_VM | ||
64 | unsigned long tmp; | ||
65 | |||
66 | WARN_ON_ONCE(mfmsr() & MSR_EE); | ||
67 | |||
68 | asm volatile("slbfee. %0, %1" : "=r"(tmp) : "r"(ea) : "cr0"); | ||
69 | WARN_ON(tmp == 0); | ||
70 | #endif | ||
71 | } | ||
72 | |||
73 | static void assert_slb_notexists(unsigned long ea) | ||
74 | { | ||
75 | #ifdef CONFIG_DEBUG_VM | ||
76 | unsigned long tmp; | ||
77 | |||
78 | WARN_ON_ONCE(mfmsr() & MSR_EE); | ||
79 | |||
80 | asm volatile("slbfee. %0, %1" : "=r"(tmp) : "r"(ea) : "cr0"); | ||
81 | WARN_ON(tmp != 0); | ||
82 | #endif | ||
83 | } | ||
84 | |||
55 | static inline void slb_shadow_update(unsigned long ea, int ssize, | 85 | static inline void slb_shadow_update(unsigned long ea, int ssize, |
56 | unsigned long flags, | 86 | unsigned long flags, |
57 | enum slb_index index) | 87 | enum slb_index index) |
@@ -84,6 +114,7 @@ static inline void create_shadowed_slbe(unsigned long ea, int ssize, | |||
84 | */ | 114 | */ |
85 | slb_shadow_update(ea, ssize, flags, index); | 115 | slb_shadow_update(ea, ssize, flags, index); |
86 | 116 | ||
117 | assert_slb_notexists(ea); | ||
87 | asm volatile("slbmte %0,%1" : | 118 | asm volatile("slbmte %0,%1" : |
88 | : "r" (mk_vsid_data(ea, ssize, flags)), | 119 | : "r" (mk_vsid_data(ea, ssize, flags)), |
89 | "r" (mk_esid_data(ea, ssize, index)) | 120 | "r" (mk_esid_data(ea, ssize, index)) |
@@ -105,17 +136,20 @@ void __slb_restore_bolted_realmode(void) | |||
105 | : "r" (be64_to_cpu(p->save_area[index].vsid)), | 136 | : "r" (be64_to_cpu(p->save_area[index].vsid)), |
106 | "r" (be64_to_cpu(p->save_area[index].esid))); | 137 | "r" (be64_to_cpu(p->save_area[index].esid))); |
107 | } | 138 | } |
139 | |||
140 | assert_slb_exists(local_paca->kstack); | ||
108 | } | 141 | } |
109 | 142 | ||
110 | /* | 143 | /* |
111 | * Insert the bolted entries into an empty SLB. | 144 | * Insert the bolted entries into an empty SLB. |
112 | * This is not the same as rebolt because the bolted segments are not | ||
113 | * changed, just loaded from the shadow area. | ||
114 | */ | 145 | */ |
115 | void slb_restore_bolted_realmode(void) | 146 | void slb_restore_bolted_realmode(void) |
116 | { | 147 | { |
117 | __slb_restore_bolted_realmode(); | 148 | __slb_restore_bolted_realmode(); |
118 | get_paca()->slb_cache_ptr = 0; | 149 | get_paca()->slb_cache_ptr = 0; |
150 | |||
151 | get_paca()->slb_kern_bitmap = (1U << SLB_NUM_BOLTED) - 1; | ||
152 | get_paca()->slb_used_bitmap = get_paca()->slb_kern_bitmap; | ||
119 | } | 153 | } |
120 | 154 | ||
121 | /* | 155 | /* |
@@ -123,113 +157,262 @@ void slb_restore_bolted_realmode(void) | |||
123 | */ | 157 | */ |
124 | void slb_flush_all_realmode(void) | 158 | void slb_flush_all_realmode(void) |
125 | { | 159 | { |
126 | /* | ||
127 | * This flushes all SLB entries including 0, so it must be realmode. | ||
128 | */ | ||
129 | asm volatile("slbmte %0,%0; slbia" : : "r" (0)); | 160 | asm volatile("slbmte %0,%0; slbia" : : "r" (0)); |
130 | } | 161 | } |
131 | 162 | ||
132 | static void __slb_flush_and_rebolt(void) | 163 | /* |
164 | * This flushes non-bolted entries, it can be run in virtual mode. Must | ||
165 | * be called with interrupts disabled. | ||
166 | */ | ||
167 | void slb_flush_and_restore_bolted(void) | ||
133 | { | 168 | { |
134 | /* If you change this make sure you change SLB_NUM_BOLTED | 169 | struct slb_shadow *p = get_slb_shadow(); |
135 | * and PR KVM appropriately too. */ | ||
136 | unsigned long linear_llp, vmalloc_llp, lflags, vflags; | ||
137 | unsigned long ksp_esid_data, ksp_vsid_data; | ||
138 | 170 | ||
139 | linear_llp = mmu_psize_defs[mmu_linear_psize].sllp; | 171 | BUILD_BUG_ON(SLB_NUM_BOLTED != 2); |
140 | vmalloc_llp = mmu_psize_defs[mmu_vmalloc_psize].sllp; | ||
141 | lflags = SLB_VSID_KERNEL | linear_llp; | ||
142 | vflags = SLB_VSID_KERNEL | vmalloc_llp; | ||
143 | 172 | ||
144 | ksp_esid_data = mk_esid_data(get_paca()->kstack, mmu_kernel_ssize, KSTACK_INDEX); | 173 | WARN_ON(!irqs_disabled()); |
145 | if ((ksp_esid_data & ~0xfffffffUL) <= PAGE_OFFSET) { | 174 | |
146 | ksp_esid_data &= ~SLB_ESID_V; | 175 | /* |
147 | ksp_vsid_data = 0; | 176 | * We can't take a PMU exception in the following code, so hard |
148 | slb_shadow_clear(KSTACK_INDEX); | 177 | * disable interrupts. |
149 | } else { | 178 | */ |
150 | /* Update stack entry; others don't change */ | 179 | hard_irq_disable(); |
151 | slb_shadow_update(get_paca()->kstack, mmu_kernel_ssize, lflags, KSTACK_INDEX); | ||
152 | ksp_vsid_data = | ||
153 | be64_to_cpu(get_slb_shadow()->save_area[KSTACK_INDEX].vsid); | ||
154 | } | ||
155 | 180 | ||
156 | /* We need to do this all in asm, so we're sure we don't touch | ||
157 | * the stack between the slbia and rebolting it. */ | ||
158 | asm volatile("isync\n" | 181 | asm volatile("isync\n" |
159 | "slbia\n" | 182 | "slbia\n" |
160 | /* Slot 1 - first VMALLOC segment */ | 183 | "slbmte %0, %1\n" |
161 | "slbmte %0,%1\n" | 184 | "isync\n" |
162 | /* Slot 2 - kernel stack */ | 185 | :: "r" (be64_to_cpu(p->save_area[KSTACK_INDEX].vsid)), |
163 | "slbmte %2,%3\n" | 186 | "r" (be64_to_cpu(p->save_area[KSTACK_INDEX].esid)) |
164 | "isync" | ||
165 | :: "r"(mk_vsid_data(VMALLOC_START, mmu_kernel_ssize, vflags)), | ||
166 | "r"(mk_esid_data(VMALLOC_START, mmu_kernel_ssize, VMALLOC_INDEX)), | ||
167 | "r"(ksp_vsid_data), | ||
168 | "r"(ksp_esid_data) | ||
169 | : "memory"); | 187 | : "memory"); |
188 | assert_slb_exists(get_paca()->kstack); | ||
189 | |||
190 | get_paca()->slb_cache_ptr = 0; | ||
191 | |||
192 | get_paca()->slb_kern_bitmap = (1U << SLB_NUM_BOLTED) - 1; | ||
193 | get_paca()->slb_used_bitmap = get_paca()->slb_kern_bitmap; | ||
170 | } | 194 | } |
171 | 195 | ||
172 | void slb_flush_and_rebolt(void) | 196 | void slb_save_contents(struct slb_entry *slb_ptr) |
173 | { | 197 | { |
198 | int i; | ||
199 | unsigned long e, v; | ||
174 | 200 | ||
175 | WARN_ON(!irqs_disabled()); | 201 | /* Save slb_cache_ptr value. */ |
202 | get_paca()->slb_save_cache_ptr = get_paca()->slb_cache_ptr; | ||
203 | |||
204 | if (!slb_ptr) | ||
205 | return; | ||
206 | |||
207 | for (i = 0; i < mmu_slb_size; i++) { | ||
208 | asm volatile("slbmfee %0,%1" : "=r" (e) : "r" (i)); | ||
209 | asm volatile("slbmfev %0,%1" : "=r" (v) : "r" (i)); | ||
210 | slb_ptr->esid = e; | ||
211 | slb_ptr->vsid = v; | ||
212 | slb_ptr++; | ||
213 | } | ||
214 | } | ||
215 | |||
216 | void slb_dump_contents(struct slb_entry *slb_ptr) | ||
217 | { | ||
218 | int i, n; | ||
219 | unsigned long e, v; | ||
220 | unsigned long llp; | ||
221 | |||
222 | if (!slb_ptr) | ||
223 | return; | ||
224 | |||
225 | pr_err("SLB contents of cpu 0x%x\n", smp_processor_id()); | ||
226 | pr_err("Last SLB entry inserted at slot %d\n", get_paca()->stab_rr); | ||
227 | |||
228 | for (i = 0; i < mmu_slb_size; i++) { | ||
229 | e = slb_ptr->esid; | ||
230 | v = slb_ptr->vsid; | ||
231 | slb_ptr++; | ||
232 | |||
233 | if (!e && !v) | ||
234 | continue; | ||
235 | |||
236 | pr_err("%02d %016lx %016lx\n", i, e, v); | ||
237 | |||
238 | if (!(e & SLB_ESID_V)) { | ||
239 | pr_err("\n"); | ||
240 | continue; | ||
241 | } | ||
242 | llp = v & SLB_VSID_LLP; | ||
243 | if (v & SLB_VSID_B_1T) { | ||
244 | pr_err(" 1T ESID=%9lx VSID=%13lx LLP:%3lx\n", | ||
245 | GET_ESID_1T(e), | ||
246 | (v & ~SLB_VSID_B) >> SLB_VSID_SHIFT_1T, llp); | ||
247 | } else { | ||
248 | pr_err(" 256M ESID=%9lx VSID=%13lx LLP:%3lx\n", | ||
249 | GET_ESID(e), | ||
250 | (v & ~SLB_VSID_B) >> SLB_VSID_SHIFT, llp); | ||
251 | } | ||
252 | } | ||
253 | pr_err("----------------------------------\n"); | ||
254 | |||
255 | /* Dump slb cache entires as well. */ | ||
256 | pr_err("SLB cache ptr value = %d\n", get_paca()->slb_save_cache_ptr); | ||
257 | pr_err("Valid SLB cache entries:\n"); | ||
258 | n = min_t(int, get_paca()->slb_save_cache_ptr, SLB_CACHE_ENTRIES); | ||
259 | for (i = 0; i < n; i++) | ||
260 | pr_err("%02d EA[0-35]=%9x\n", i, get_paca()->slb_cache[i]); | ||
261 | pr_err("Rest of SLB cache entries:\n"); | ||
262 | for (i = n; i < SLB_CACHE_ENTRIES; i++) | ||
263 | pr_err("%02d EA[0-35]=%9x\n", i, get_paca()->slb_cache[i]); | ||
264 | } | ||
176 | 265 | ||
266 | void slb_vmalloc_update(void) | ||
267 | { | ||
177 | /* | 268 | /* |
178 | * We can't take a PMU exception in the following code, so hard | 269 | * vmalloc is not bolted, so just have to flush non-bolted. |
179 | * disable interrupts. | ||
180 | */ | 270 | */ |
181 | hard_irq_disable(); | 271 | slb_flush_and_restore_bolted(); |
272 | } | ||
182 | 273 | ||
183 | __slb_flush_and_rebolt(); | 274 | static bool preload_hit(struct thread_info *ti, unsigned long esid) |
184 | get_paca()->slb_cache_ptr = 0; | 275 | { |
276 | unsigned char i; | ||
277 | |||
278 | for (i = 0; i < ti->slb_preload_nr; i++) { | ||
279 | unsigned char idx; | ||
280 | |||
281 | idx = (ti->slb_preload_tail + i) % SLB_PRELOAD_NR; | ||
282 | if (esid == ti->slb_preload_esid[idx]) | ||
283 | return true; | ||
284 | } | ||
285 | return false; | ||
185 | } | 286 | } |
186 | 287 | ||
187 | void slb_vmalloc_update(void) | 288 | static bool preload_add(struct thread_info *ti, unsigned long ea) |
188 | { | 289 | { |
189 | unsigned long vflags; | 290 | unsigned char idx; |
291 | unsigned long esid; | ||
292 | |||
293 | if (mmu_has_feature(MMU_FTR_1T_SEGMENT)) { | ||
294 | /* EAs are stored >> 28 so 256MB segments don't need clearing */ | ||
295 | if (ea & ESID_MASK_1T) | ||
296 | ea &= ESID_MASK_1T; | ||
297 | } | ||
298 | |||
299 | esid = ea >> SID_SHIFT; | ||
190 | 300 | ||
191 | vflags = SLB_VSID_KERNEL | mmu_psize_defs[mmu_vmalloc_psize].sllp; | 301 | if (preload_hit(ti, esid)) |
192 | slb_shadow_update(VMALLOC_START, mmu_kernel_ssize, vflags, VMALLOC_INDEX); | 302 | return false; |
193 | slb_flush_and_rebolt(); | 303 | |
304 | idx = (ti->slb_preload_tail + ti->slb_preload_nr) % SLB_PRELOAD_NR; | ||
305 | ti->slb_preload_esid[idx] = esid; | ||
306 | if (ti->slb_preload_nr == SLB_PRELOAD_NR) | ||
307 | ti->slb_preload_tail = (ti->slb_preload_tail + 1) % SLB_PRELOAD_NR; | ||
308 | else | ||
309 | ti->slb_preload_nr++; | ||
310 | |||
311 | return true; | ||
194 | } | 312 | } |
195 | 313 | ||
196 | /* Helper function to compare esids. There are four cases to handle. | 314 | static void preload_age(struct thread_info *ti) |
197 | * 1. The system is not 1T segment size capable. Use the GET_ESID compare. | ||
198 | * 2. The system is 1T capable, both addresses are < 1T, use the GET_ESID compare. | ||
199 | * 3. The system is 1T capable, only one of the two addresses is > 1T. This is not a match. | ||
200 | * 4. The system is 1T capable, both addresses are > 1T, use the GET_ESID_1T macro to compare. | ||
201 | */ | ||
202 | static inline int esids_match(unsigned long addr1, unsigned long addr2) | ||
203 | { | 315 | { |
204 | int esid_1t_count; | 316 | if (!ti->slb_preload_nr) |
317 | return; | ||
318 | ti->slb_preload_nr--; | ||
319 | ti->slb_preload_tail = (ti->slb_preload_tail + 1) % SLB_PRELOAD_NR; | ||
320 | } | ||
205 | 321 | ||
206 | /* System is not 1T segment size capable. */ | 322 | void slb_setup_new_exec(void) |
207 | if (!mmu_has_feature(MMU_FTR_1T_SEGMENT)) | 323 | { |
208 | return (GET_ESID(addr1) == GET_ESID(addr2)); | 324 | struct thread_info *ti = current_thread_info(); |
325 | struct mm_struct *mm = current->mm; | ||
326 | unsigned long exec = 0x10000000; | ||
209 | 327 | ||
210 | esid_1t_count = (((addr1 >> SID_SHIFT_1T) != 0) + | 328 | WARN_ON(irqs_disabled()); |
211 | ((addr2 >> SID_SHIFT_1T) != 0)); | ||
212 | 329 | ||
213 | /* both addresses are < 1T */ | 330 | /* |
214 | if (esid_1t_count == 0) | 331 | * preload cache can only be used to determine whether a SLB |
215 | return (GET_ESID(addr1) == GET_ESID(addr2)); | 332 | * entry exists if it does not start to overflow. |
333 | */ | ||
334 | if (ti->slb_preload_nr + 2 > SLB_PRELOAD_NR) | ||
335 | return; | ||
216 | 336 | ||
217 | /* One address < 1T, the other > 1T. Not a match */ | 337 | hard_irq_disable(); |
218 | if (esid_1t_count == 1) | ||
219 | return 0; | ||
220 | 338 | ||
221 | /* Both addresses are > 1T. */ | 339 | /* |
222 | return (GET_ESID_1T(addr1) == GET_ESID_1T(addr2)); | 340 | * We have no good place to clear the slb preload cache on exec, |
341 | * flush_thread is about the earliest arch hook but that happens | ||
342 | * after we switch to the mm and have aleady preloaded the SLBEs. | ||
343 | * | ||
344 | * For the most part that's probably okay to use entries from the | ||
345 | * previous exec, they will age out if unused. It may turn out to | ||
346 | * be an advantage to clear the cache before switching to it, | ||
347 | * however. | ||
348 | */ | ||
349 | |||
350 | /* | ||
351 | * preload some userspace segments into the SLB. | ||
352 | * Almost all 32 and 64bit PowerPC executables are linked at | ||
353 | * 0x10000000 so it makes sense to preload this segment. | ||
354 | */ | ||
355 | if (!is_kernel_addr(exec)) { | ||
356 | if (preload_add(ti, exec)) | ||
357 | slb_allocate_user(mm, exec); | ||
358 | } | ||
359 | |||
360 | /* Libraries and mmaps. */ | ||
361 | if (!is_kernel_addr(mm->mmap_base)) { | ||
362 | if (preload_add(ti, mm->mmap_base)) | ||
363 | slb_allocate_user(mm, mm->mmap_base); | ||
364 | } | ||
365 | |||
366 | /* see switch_slb */ | ||
367 | asm volatile("isync" : : : "memory"); | ||
368 | |||
369 | local_irq_enable(); | ||
223 | } | 370 | } |
224 | 371 | ||
372 | void preload_new_slb_context(unsigned long start, unsigned long sp) | ||
373 | { | ||
374 | struct thread_info *ti = current_thread_info(); | ||
375 | struct mm_struct *mm = current->mm; | ||
376 | unsigned long heap = mm->start_brk; | ||
377 | |||
378 | WARN_ON(irqs_disabled()); | ||
379 | |||
380 | /* see above */ | ||
381 | if (ti->slb_preload_nr + 3 > SLB_PRELOAD_NR) | ||
382 | return; | ||
383 | |||
384 | hard_irq_disable(); | ||
385 | |||
386 | /* Userspace entry address. */ | ||
387 | if (!is_kernel_addr(start)) { | ||
388 | if (preload_add(ti, start)) | ||
389 | slb_allocate_user(mm, start); | ||
390 | } | ||
391 | |||
392 | /* Top of stack, grows down. */ | ||
393 | if (!is_kernel_addr(sp)) { | ||
394 | if (preload_add(ti, sp)) | ||
395 | slb_allocate_user(mm, sp); | ||
396 | } | ||
397 | |||
398 | /* Bottom of heap, grows up. */ | ||
399 | if (heap && !is_kernel_addr(heap)) { | ||
400 | if (preload_add(ti, heap)) | ||
401 | slb_allocate_user(mm, heap); | ||
402 | } | ||
403 | |||
404 | /* see switch_slb */ | ||
405 | asm volatile("isync" : : : "memory"); | ||
406 | |||
407 | local_irq_enable(); | ||
408 | } | ||
409 | |||
410 | |||
225 | /* Flush all user entries from the segment table of the current processor. */ | 411 | /* Flush all user entries from the segment table of the current processor. */ |
226 | void switch_slb(struct task_struct *tsk, struct mm_struct *mm) | 412 | void switch_slb(struct task_struct *tsk, struct mm_struct *mm) |
227 | { | 413 | { |
228 | unsigned long offset; | 414 | struct thread_info *ti = task_thread_info(tsk); |
229 | unsigned long slbie_data = 0; | 415 | unsigned char i; |
230 | unsigned long pc = KSTK_EIP(tsk); | ||
231 | unsigned long stack = KSTK_ESP(tsk); | ||
232 | unsigned long exec_base; | ||
233 | 416 | ||
234 | /* | 417 | /* |
235 | * We need interrupts hard-disabled here, not just soft-disabled, | 418 | * We need interrupts hard-disabled here, not just soft-disabled, |
@@ -238,91 +421,107 @@ void switch_slb(struct task_struct *tsk, struct mm_struct *mm) | |||
238 | * which would update the slb_cache/slb_cache_ptr fields in the PACA. | 421 | * which would update the slb_cache/slb_cache_ptr fields in the PACA. |
239 | */ | 422 | */ |
240 | hard_irq_disable(); | 423 | hard_irq_disable(); |
241 | offset = get_paca()->slb_cache_ptr; | 424 | asm volatile("isync" : : : "memory"); |
242 | if (!mmu_has_feature(MMU_FTR_NO_SLBIE_B) && | 425 | if (cpu_has_feature(CPU_FTR_ARCH_300)) { |
243 | offset <= SLB_CACHE_ENTRIES) { | 426 | /* |
244 | int i; | 427 | * SLBIA IH=3 invalidates all Class=1 SLBEs and their |
245 | asm volatile("isync" : : : "memory"); | 428 | * associated lookaside structures, which matches what |
246 | for (i = 0; i < offset; i++) { | 429 | * switch_slb wants. So ARCH_300 does not use the slb |
247 | slbie_data = (unsigned long)get_paca()->slb_cache[i] | 430 | * cache. |
248 | << SID_SHIFT; /* EA */ | 431 | */ |
249 | slbie_data |= user_segment_size(slbie_data) | 432 | asm volatile(PPC_SLBIA(3)); |
250 | << SLBIE_SSIZE_SHIFT; | ||
251 | slbie_data |= SLBIE_C; /* C set for user addresses */ | ||
252 | asm volatile("slbie %0" : : "r" (slbie_data)); | ||
253 | } | ||
254 | asm volatile("isync" : : : "memory"); | ||
255 | } else { | 433 | } else { |
256 | __slb_flush_and_rebolt(); | 434 | unsigned long offset = get_paca()->slb_cache_ptr; |
257 | } | 435 | |
436 | if (!mmu_has_feature(MMU_FTR_NO_SLBIE_B) && | ||
437 | offset <= SLB_CACHE_ENTRIES) { | ||
438 | unsigned long slbie_data = 0; | ||
439 | |||
440 | for (i = 0; i < offset; i++) { | ||
441 | unsigned long ea; | ||
442 | |||
443 | ea = (unsigned long) | ||
444 | get_paca()->slb_cache[i] << SID_SHIFT; | ||
445 | /* | ||
446 | * Could assert_slb_exists here, but hypervisor | ||
447 | * or machine check could have come in and | ||
448 | * removed the entry at this point. | ||
449 | */ | ||
450 | |||
451 | slbie_data = ea; | ||
452 | slbie_data |= user_segment_size(slbie_data) | ||
453 | << SLBIE_SSIZE_SHIFT; | ||
454 | slbie_data |= SLBIE_C; /* user slbs have C=1 */ | ||
455 | asm volatile("slbie %0" : : "r" (slbie_data)); | ||
456 | } | ||
457 | |||
458 | /* Workaround POWER5 < DD2.1 issue */ | ||
459 | if (!cpu_has_feature(CPU_FTR_ARCH_207S) && offset == 1) | ||
460 | asm volatile("slbie %0" : : "r" (slbie_data)); | ||
461 | |||
462 | } else { | ||
463 | struct slb_shadow *p = get_slb_shadow(); | ||
464 | unsigned long ksp_esid_data = | ||
465 | be64_to_cpu(p->save_area[KSTACK_INDEX].esid); | ||
466 | unsigned long ksp_vsid_data = | ||
467 | be64_to_cpu(p->save_area[KSTACK_INDEX].vsid); | ||
468 | |||
469 | asm volatile(PPC_SLBIA(1) "\n" | ||
470 | "slbmte %0,%1\n" | ||
471 | "isync" | ||
472 | :: "r"(ksp_vsid_data), | ||
473 | "r"(ksp_esid_data)); | ||
474 | |||
475 | get_paca()->slb_kern_bitmap = (1U << SLB_NUM_BOLTED) - 1; | ||
476 | } | ||
258 | 477 | ||
259 | /* Workaround POWER5 < DD2.1 issue */ | 478 | get_paca()->slb_cache_ptr = 0; |
260 | if (offset == 1 || offset > SLB_CACHE_ENTRIES) | 479 | } |
261 | asm volatile("slbie %0" : : "r" (slbie_data)); | 480 | get_paca()->slb_used_bitmap = get_paca()->slb_kern_bitmap; |
262 | 481 | ||
263 | get_paca()->slb_cache_ptr = 0; | ||
264 | copy_mm_to_paca(mm); | 482 | copy_mm_to_paca(mm); |
265 | 483 | ||
266 | /* | 484 | /* |
267 | * preload some userspace segments into the SLB. | 485 | * We gradually age out SLBs after a number of context switches to |
268 | * Almost all 32 and 64bit PowerPC executables are linked at | 486 | * reduce reload overhead of unused entries (like we do with FP/VEC |
269 | * 0x10000000 so it makes sense to preload this segment. | 487 | * reload). Each time we wrap 256 switches, take an entry out of the |
488 | * SLB preload cache. | ||
270 | */ | 489 | */ |
271 | exec_base = 0x10000000; | 490 | tsk->thread.load_slb++; |
272 | 491 | if (!tsk->thread.load_slb) { | |
273 | if (is_kernel_addr(pc) || is_kernel_addr(stack) || | 492 | unsigned long pc = KSTK_EIP(tsk); |
274 | is_kernel_addr(exec_base)) | ||
275 | return; | ||
276 | 493 | ||
277 | slb_allocate(pc); | 494 | preload_age(ti); |
495 | preload_add(ti, pc); | ||
496 | } | ||
278 | 497 | ||
279 | if (!esids_match(pc, stack)) | 498 | for (i = 0; i < ti->slb_preload_nr; i++) { |
280 | slb_allocate(stack); | 499 | unsigned char idx; |
500 | unsigned long ea; | ||
281 | 501 | ||
282 | if (!esids_match(pc, exec_base) && | 502 | idx = (ti->slb_preload_tail + i) % SLB_PRELOAD_NR; |
283 | !esids_match(stack, exec_base)) | 503 | ea = (unsigned long)ti->slb_preload_esid[idx] << SID_SHIFT; |
284 | slb_allocate(exec_base); | ||
285 | } | ||
286 | 504 | ||
287 | static inline void patch_slb_encoding(unsigned int *insn_addr, | 505 | slb_allocate_user(mm, ea); |
288 | unsigned int immed) | 506 | } |
289 | { | ||
290 | 507 | ||
291 | /* | 508 | /* |
292 | * This function patches either an li or a cmpldi instruction with | 509 | * Synchronize slbmte preloads with possible subsequent user memory |
293 | * a new immediate value. This relies on the fact that both li | 510 | * address accesses by the kernel (user mode won't happen until |
294 | * (which is actually addi) and cmpldi both take a 16-bit immediate | 511 | * rfid, which is safe). |
295 | * value, and it is situated in the same location in the instruction, | ||
296 | * ie. bits 16-31 (Big endian bit order) or the lower 16 bits. | ||
297 | * The signedness of the immediate operand differs between the two | ||
298 | * instructions however this code is only ever patching a small value, | ||
299 | * much less than 1 << 15, so we can get away with it. | ||
300 | * To patch the value we read the existing instruction, clear the | ||
301 | * immediate value, and or in our new value, then write the instruction | ||
302 | * back. | ||
303 | */ | 512 | */ |
304 | unsigned int insn = (*insn_addr & 0xffff0000) | immed; | 513 | asm volatile("isync" : : : "memory"); |
305 | patch_instruction(insn_addr, insn); | ||
306 | } | 514 | } |
307 | 515 | ||
308 | extern u32 slb_miss_kernel_load_linear[]; | ||
309 | extern u32 slb_miss_kernel_load_io[]; | ||
310 | extern u32 slb_compare_rr_to_size[]; | ||
311 | extern u32 slb_miss_kernel_load_vmemmap[]; | ||
312 | |||
313 | void slb_set_size(u16 size) | 516 | void slb_set_size(u16 size) |
314 | { | 517 | { |
315 | if (mmu_slb_size == size) | ||
316 | return; | ||
317 | |||
318 | mmu_slb_size = size; | 518 | mmu_slb_size = size; |
319 | patch_slb_encoding(slb_compare_rr_to_size, mmu_slb_size); | ||
320 | } | 519 | } |
321 | 520 | ||
322 | void slb_initialize(void) | 521 | void slb_initialize(void) |
323 | { | 522 | { |
324 | unsigned long linear_llp, vmalloc_llp, io_llp; | 523 | unsigned long linear_llp, vmalloc_llp, io_llp; |
325 | unsigned long lflags, vflags; | 524 | unsigned long lflags; |
326 | static int slb_encoding_inited; | 525 | static int slb_encoding_inited; |
327 | #ifdef CONFIG_SPARSEMEM_VMEMMAP | 526 | #ifdef CONFIG_SPARSEMEM_VMEMMAP |
328 | unsigned long vmemmap_llp; | 527 | unsigned long vmemmap_llp; |
@@ -338,34 +537,24 @@ void slb_initialize(void) | |||
338 | #endif | 537 | #endif |
339 | if (!slb_encoding_inited) { | 538 | if (!slb_encoding_inited) { |
340 | slb_encoding_inited = 1; | 539 | slb_encoding_inited = 1; |
341 | patch_slb_encoding(slb_miss_kernel_load_linear, | ||
342 | SLB_VSID_KERNEL | linear_llp); | ||
343 | patch_slb_encoding(slb_miss_kernel_load_io, | ||
344 | SLB_VSID_KERNEL | io_llp); | ||
345 | patch_slb_encoding(slb_compare_rr_to_size, | ||
346 | mmu_slb_size); | ||
347 | |||
348 | pr_devel("SLB: linear LLP = %04lx\n", linear_llp); | 540 | pr_devel("SLB: linear LLP = %04lx\n", linear_llp); |
349 | pr_devel("SLB: io LLP = %04lx\n", io_llp); | 541 | pr_devel("SLB: io LLP = %04lx\n", io_llp); |
350 | |||
351 | #ifdef CONFIG_SPARSEMEM_VMEMMAP | 542 | #ifdef CONFIG_SPARSEMEM_VMEMMAP |
352 | patch_slb_encoding(slb_miss_kernel_load_vmemmap, | ||
353 | SLB_VSID_KERNEL | vmemmap_llp); | ||
354 | pr_devel("SLB: vmemmap LLP = %04lx\n", vmemmap_llp); | 543 | pr_devel("SLB: vmemmap LLP = %04lx\n", vmemmap_llp); |
355 | #endif | 544 | #endif |
356 | } | 545 | } |
357 | 546 | ||
358 | get_paca()->stab_rr = SLB_NUM_BOLTED; | 547 | get_paca()->stab_rr = SLB_NUM_BOLTED - 1; |
548 | get_paca()->slb_kern_bitmap = (1U << SLB_NUM_BOLTED) - 1; | ||
549 | get_paca()->slb_used_bitmap = get_paca()->slb_kern_bitmap; | ||
359 | 550 | ||
360 | lflags = SLB_VSID_KERNEL | linear_llp; | 551 | lflags = SLB_VSID_KERNEL | linear_llp; |
361 | vflags = SLB_VSID_KERNEL | vmalloc_llp; | ||
362 | 552 | ||
363 | /* Invalidate the entire SLB (even entry 0) & all the ERATS */ | 553 | /* Invalidate the entire SLB (even entry 0) & all the ERATS */ |
364 | asm volatile("isync":::"memory"); | 554 | asm volatile("isync":::"memory"); |
365 | asm volatile("slbmte %0,%0"::"r" (0) : "memory"); | 555 | asm volatile("slbmte %0,%0"::"r" (0) : "memory"); |
366 | asm volatile("isync; slbia; isync":::"memory"); | 556 | asm volatile("isync; slbia; isync":::"memory"); |
367 | create_shadowed_slbe(PAGE_OFFSET, mmu_kernel_ssize, lflags, LINEAR_INDEX); | 557 | create_shadowed_slbe(PAGE_OFFSET, mmu_kernel_ssize, lflags, LINEAR_INDEX); |
368 | create_shadowed_slbe(VMALLOC_START, mmu_kernel_ssize, vflags, VMALLOC_INDEX); | ||
369 | 558 | ||
370 | /* For the boot cpu, we're running on the stack in init_thread_union, | 559 | /* For the boot cpu, we're running on the stack in init_thread_union, |
371 | * which is in the first segment of the linear mapping, and also | 560 | * which is in the first segment of the linear mapping, and also |
@@ -381,122 +570,259 @@ void slb_initialize(void) | |||
381 | asm volatile("isync":::"memory"); | 570 | asm volatile("isync":::"memory"); |
382 | } | 571 | } |
383 | 572 | ||
384 | static void insert_slb_entry(unsigned long vsid, unsigned long ea, | 573 | static void slb_cache_update(unsigned long esid_data) |
385 | int bpsize, int ssize) | ||
386 | { | 574 | { |
387 | unsigned long flags, vsid_data, esid_data; | ||
388 | enum slb_index index; | ||
389 | int slb_cache_index; | 575 | int slb_cache_index; |
390 | 576 | ||
391 | /* | 577 | if (cpu_has_feature(CPU_FTR_ARCH_300)) |
392 | * We are irq disabled, hence should be safe to access PACA. | 578 | return; /* ISAv3.0B and later does not use slb_cache */ |
393 | */ | ||
394 | VM_WARN_ON(!irqs_disabled()); | ||
395 | |||
396 | /* | ||
397 | * We can't take a PMU exception in the following code, so hard | ||
398 | * disable interrupts. | ||
399 | */ | ||
400 | hard_irq_disable(); | ||
401 | |||
402 | index = get_paca()->stab_rr; | ||
403 | |||
404 | /* | ||
405 | * simple round-robin replacement of slb starting at SLB_NUM_BOLTED. | ||
406 | */ | ||
407 | if (index < (mmu_slb_size - 1)) | ||
408 | index++; | ||
409 | else | ||
410 | index = SLB_NUM_BOLTED; | ||
411 | |||
412 | get_paca()->stab_rr = index; | ||
413 | |||
414 | flags = SLB_VSID_USER | mmu_psize_defs[bpsize].sllp; | ||
415 | vsid_data = (vsid << slb_vsid_shift(ssize)) | flags | | ||
416 | ((unsigned long) ssize << SLB_VSID_SSIZE_SHIFT); | ||
417 | esid_data = mk_esid_data(ea, ssize, index); | ||
418 | |||
419 | /* | ||
420 | * No need for an isync before or after this slbmte. The exception | ||
421 | * we enter with and the rfid we exit with are context synchronizing. | ||
422 | * Also we only handle user segments here. | ||
423 | */ | ||
424 | asm volatile("slbmte %0, %1" : : "r" (vsid_data), "r" (esid_data) | ||
425 | : "memory"); | ||
426 | 579 | ||
427 | /* | 580 | /* |
428 | * Now update slb cache entries | 581 | * Now update slb cache entries |
429 | */ | 582 | */ |
430 | slb_cache_index = get_paca()->slb_cache_ptr; | 583 | slb_cache_index = local_paca->slb_cache_ptr; |
431 | if (slb_cache_index < SLB_CACHE_ENTRIES) { | 584 | if (slb_cache_index < SLB_CACHE_ENTRIES) { |
432 | /* | 585 | /* |
433 | * We have space in slb cache for optimized switch_slb(). | 586 | * We have space in slb cache for optimized switch_slb(). |
434 | * Top 36 bits from esid_data as per ISA | 587 | * Top 36 bits from esid_data as per ISA |
435 | */ | 588 | */ |
436 | get_paca()->slb_cache[slb_cache_index++] = esid_data >> 28; | 589 | local_paca->slb_cache[slb_cache_index++] = esid_data >> 28; |
437 | get_paca()->slb_cache_ptr++; | 590 | local_paca->slb_cache_ptr++; |
438 | } else { | 591 | } else { |
439 | /* | 592 | /* |
440 | * Our cache is full and the current cache content strictly | 593 | * Our cache is full and the current cache content strictly |
441 | * doesn't indicate the active SLB conents. Bump the ptr | 594 | * doesn't indicate the active SLB conents. Bump the ptr |
442 | * so that switch_slb() will ignore the cache. | 595 | * so that switch_slb() will ignore the cache. |
443 | */ | 596 | */ |
444 | get_paca()->slb_cache_ptr = SLB_CACHE_ENTRIES + 1; | 597 | local_paca->slb_cache_ptr = SLB_CACHE_ENTRIES + 1; |
445 | } | 598 | } |
446 | } | 599 | } |
447 | 600 | ||
448 | static void handle_multi_context_slb_miss(int context_id, unsigned long ea) | 601 | static enum slb_index alloc_slb_index(bool kernel) |
449 | { | 602 | { |
450 | struct mm_struct *mm = current->mm; | 603 | enum slb_index index; |
451 | unsigned long vsid; | ||
452 | int bpsize; | ||
453 | 604 | ||
454 | /* | 605 | /* |
455 | * We are always above 1TB, hence use high user segment size. | 606 | * The allocation bitmaps can become out of synch with the SLB |
607 | * when the _switch code does slbie when bolting a new stack | ||
608 | * segment and it must not be anywhere else in the SLB. This leaves | ||
609 | * a kernel allocated entry that is unused in the SLB. With very | ||
610 | * large systems or small segment sizes, the bitmaps could slowly | ||
611 | * fill with these entries. They will eventually be cleared out | ||
612 | * by the round robin allocator in that case, so it's probably not | ||
613 | * worth accounting for. | ||
456 | */ | 614 | */ |
457 | vsid = get_vsid(context_id, ea, mmu_highuser_ssize); | 615 | |
458 | bpsize = get_slice_psize(mm, ea); | 616 | /* |
459 | insert_slb_entry(vsid, ea, bpsize, mmu_highuser_ssize); | 617 | * SLBs beyond 32 entries are allocated with stab_rr only |
618 | * POWER7/8/9 have 32 SLB entries, this could be expanded if a | ||
619 | * future CPU has more. | ||
620 | */ | ||
621 | if (local_paca->slb_used_bitmap != U32_MAX) { | ||
622 | index = ffz(local_paca->slb_used_bitmap); | ||
623 | local_paca->slb_used_bitmap |= 1U << index; | ||
624 | if (kernel) | ||
625 | local_paca->slb_kern_bitmap |= 1U << index; | ||
626 | } else { | ||
627 | /* round-robin replacement of slb starting at SLB_NUM_BOLTED. */ | ||
628 | index = local_paca->stab_rr; | ||
629 | if (index < (mmu_slb_size - 1)) | ||
630 | index++; | ||
631 | else | ||
632 | index = SLB_NUM_BOLTED; | ||
633 | local_paca->stab_rr = index; | ||
634 | if (index < 32) { | ||
635 | if (kernel) | ||
636 | local_paca->slb_kern_bitmap |= 1U << index; | ||
637 | else | ||
638 | local_paca->slb_kern_bitmap &= ~(1U << index); | ||
639 | } | ||
640 | } | ||
641 | BUG_ON(index < SLB_NUM_BOLTED); | ||
642 | |||
643 | return index; | ||
460 | } | 644 | } |
461 | 645 | ||
462 | void slb_miss_large_addr(struct pt_regs *regs) | 646 | static long slb_insert_entry(unsigned long ea, unsigned long context, |
647 | unsigned long flags, int ssize, bool kernel) | ||
463 | { | 648 | { |
464 | enum ctx_state prev_state = exception_enter(); | 649 | unsigned long vsid; |
465 | unsigned long ea = regs->dar; | 650 | unsigned long vsid_data, esid_data; |
466 | int context; | 651 | enum slb_index index; |
467 | 652 | ||
468 | if (REGION_ID(ea) != USER_REGION_ID) | 653 | vsid = get_vsid(context, ea, ssize); |
469 | goto slb_bad_addr; | 654 | if (!vsid) |
655 | return -EFAULT; | ||
470 | 656 | ||
471 | /* | 657 | /* |
472 | * Are we beyound what the page table layout supports ? | 658 | * There must not be a kernel SLB fault in alloc_slb_index or before |
659 | * slbmte here or the allocation bitmaps could get out of whack with | ||
660 | * the SLB. | ||
661 | * | ||
662 | * User SLB faults or preloads take this path which might get inlined | ||
663 | * into the caller, so add compiler barriers here to ensure unsafe | ||
664 | * memory accesses do not come between. | ||
473 | */ | 665 | */ |
474 | if ((ea & ~REGION_MASK) >= H_PGTABLE_RANGE) | 666 | barrier(); |
475 | goto slb_bad_addr; | ||
476 | 667 | ||
477 | /* Lower address should have been handled by asm code */ | 668 | index = alloc_slb_index(kernel); |
478 | if (ea < (1UL << MAX_EA_BITS_PER_CONTEXT)) | 669 | |
479 | goto slb_bad_addr; | 670 | vsid_data = __mk_vsid_data(vsid, ssize, flags); |
671 | esid_data = mk_esid_data(ea, ssize, index); | ||
672 | |||
673 | /* | ||
674 | * No need for an isync before or after this slbmte. The exception | ||
675 | * we enter with and the rfid we exit with are context synchronizing. | ||
676 | * User preloads should add isync afterwards in case the kernel | ||
677 | * accesses user memory before it returns to userspace with rfid. | ||
678 | */ | ||
679 | assert_slb_notexists(ea); | ||
680 | asm volatile("slbmte %0, %1" : : "r" (vsid_data), "r" (esid_data)); | ||
681 | |||
682 | barrier(); | ||
683 | |||
684 | if (!kernel) | ||
685 | slb_cache_update(esid_data); | ||
686 | |||
687 | return 0; | ||
688 | } | ||
689 | |||
690 | static long slb_allocate_kernel(unsigned long ea, unsigned long id) | ||
691 | { | ||
692 | unsigned long context; | ||
693 | unsigned long flags; | ||
694 | int ssize; | ||
695 | |||
696 | if (id == KERNEL_REGION_ID) { | ||
697 | |||
698 | /* We only support upto MAX_PHYSMEM_BITS */ | ||
699 | if ((ea & ~REGION_MASK) > (1UL << MAX_PHYSMEM_BITS)) | ||
700 | return -EFAULT; | ||
701 | |||
702 | flags = SLB_VSID_KERNEL | mmu_psize_defs[mmu_linear_psize].sllp; | ||
703 | |||
704 | #ifdef CONFIG_SPARSEMEM_VMEMMAP | ||
705 | } else if (id == VMEMMAP_REGION_ID) { | ||
706 | |||
707 | if ((ea & ~REGION_MASK) >= (1ULL << MAX_EA_BITS_PER_CONTEXT)) | ||
708 | return -EFAULT; | ||
709 | |||
710 | flags = SLB_VSID_KERNEL | mmu_psize_defs[mmu_vmemmap_psize].sllp; | ||
711 | #endif | ||
712 | } else if (id == VMALLOC_REGION_ID) { | ||
713 | |||
714 | if ((ea & ~REGION_MASK) >= (1ULL << MAX_EA_BITS_PER_CONTEXT)) | ||
715 | return -EFAULT; | ||
716 | |||
717 | if (ea < H_VMALLOC_END) | ||
718 | flags = get_paca()->vmalloc_sllp; | ||
719 | else | ||
720 | flags = SLB_VSID_KERNEL | mmu_psize_defs[mmu_io_psize].sllp; | ||
721 | } else { | ||
722 | return -EFAULT; | ||
723 | } | ||
724 | |||
725 | ssize = MMU_SEGSIZE_1T; | ||
726 | if (!mmu_has_feature(MMU_FTR_1T_SEGMENT)) | ||
727 | ssize = MMU_SEGSIZE_256M; | ||
728 | |||
729 | context = get_kernel_context(ea); | ||
730 | return slb_insert_entry(ea, context, flags, ssize, true); | ||
731 | } | ||
732 | |||
733 | static long slb_allocate_user(struct mm_struct *mm, unsigned long ea) | ||
734 | { | ||
735 | unsigned long context; | ||
736 | unsigned long flags; | ||
737 | int bpsize; | ||
738 | int ssize; | ||
480 | 739 | ||
481 | /* | 740 | /* |
482 | * consider this as bad access if we take a SLB miss | 741 | * consider this as bad access if we take a SLB miss |
483 | * on an address above addr limit. | 742 | * on an address above addr limit. |
484 | */ | 743 | */ |
485 | if (ea >= current->mm->context.slb_addr_limit) | 744 | if (ea >= mm->context.slb_addr_limit) |
486 | goto slb_bad_addr; | 745 | return -EFAULT; |
487 | 746 | ||
488 | context = get_ea_context(¤t->mm->context, ea); | 747 | context = get_user_context(&mm->context, ea); |
489 | if (!context) | 748 | if (!context) |
490 | goto slb_bad_addr; | 749 | return -EFAULT; |
750 | |||
751 | if (unlikely(ea >= H_PGTABLE_RANGE)) { | ||
752 | WARN_ON(1); | ||
753 | return -EFAULT; | ||
754 | } | ||
491 | 755 | ||
492 | handle_multi_context_slb_miss(context, ea); | 756 | ssize = user_segment_size(ea); |
493 | exception_exit(prev_state); | ||
494 | return; | ||
495 | 757 | ||
496 | slb_bad_addr: | 758 | bpsize = get_slice_psize(mm, ea); |
497 | if (user_mode(regs)) | 759 | flags = SLB_VSID_USER | mmu_psize_defs[bpsize].sllp; |
498 | _exception(SIGSEGV, regs, SEGV_BNDERR, ea); | 760 | |
499 | else | 761 | return slb_insert_entry(ea, context, flags, ssize, false); |
500 | bad_page_fault(regs, ea, SIGSEGV); | 762 | } |
501 | exception_exit(prev_state); | 763 | |
764 | long do_slb_fault(struct pt_regs *regs, unsigned long ea) | ||
765 | { | ||
766 | unsigned long id = REGION_ID(ea); | ||
767 | |||
768 | /* IRQs are not reconciled here, so can't check irqs_disabled */ | ||
769 | VM_WARN_ON(mfmsr() & MSR_EE); | ||
770 | |||
771 | if (unlikely(!(regs->msr & MSR_RI))) | ||
772 | return -EINVAL; | ||
773 | |||
774 | /* | ||
775 | * SLB kernel faults must be very careful not to touch anything | ||
776 | * that is not bolted. E.g., PACA and global variables are okay, | ||
777 | * mm->context stuff is not. | ||
778 | * | ||
779 | * SLB user faults can access all of kernel memory, but must be | ||
780 | * careful not to touch things like IRQ state because it is not | ||
781 | * "reconciled" here. The difficulty is that we must use | ||
782 | * fast_exception_return to return from kernel SLB faults without | ||
783 | * looking at possible non-bolted memory. We could test user vs | ||
784 | * kernel faults in the interrupt handler asm and do a full fault, | ||
785 | * reconcile, ret_from_except for user faults which would make them | ||
786 | * first class kernel code. But for performance it's probably nicer | ||
787 | * if they go via fast_exception_return too. | ||
788 | */ | ||
789 | if (id >= KERNEL_REGION_ID) { | ||
790 | long err; | ||
791 | #ifdef CONFIG_DEBUG_VM | ||
792 | /* Catch recursive kernel SLB faults. */ | ||
793 | BUG_ON(local_paca->in_kernel_slb_handler); | ||
794 | local_paca->in_kernel_slb_handler = 1; | ||
795 | #endif | ||
796 | err = slb_allocate_kernel(ea, id); | ||
797 | #ifdef CONFIG_DEBUG_VM | ||
798 | local_paca->in_kernel_slb_handler = 0; | ||
799 | #endif | ||
800 | return err; | ||
801 | } else { | ||
802 | struct mm_struct *mm = current->mm; | ||
803 | long err; | ||
804 | |||
805 | if (unlikely(!mm)) | ||
806 | return -EFAULT; | ||
807 | |||
808 | err = slb_allocate_user(mm, ea); | ||
809 | if (!err) | ||
810 | preload_add(current_thread_info(), ea); | ||
811 | |||
812 | return err; | ||
813 | } | ||
814 | } | ||
815 | |||
816 | void do_bad_slb_fault(struct pt_regs *regs, unsigned long ea, long err) | ||
817 | { | ||
818 | if (err == -EFAULT) { | ||
819 | if (user_mode(regs)) | ||
820 | _exception(SIGSEGV, regs, SEGV_BNDERR, ea); | ||
821 | else | ||
822 | bad_page_fault(regs, ea, SIGSEGV); | ||
823 | } else if (err == -EINVAL) { | ||
824 | unrecoverable_exception(regs); | ||
825 | } else { | ||
826 | BUG(); | ||
827 | } | ||
502 | } | 828 | } |
diff --git a/arch/powerpc/mm/slb_low.S b/arch/powerpc/mm/slb_low.S deleted file mode 100644 index 4ac5057ad439..000000000000 --- a/arch/powerpc/mm/slb_low.S +++ /dev/null | |||
@@ -1,335 +0,0 @@ | |||
1 | /* | ||
2 | * Low-level SLB routines | ||
3 | * | ||
4 | * Copyright (C) 2004 David Gibson <dwg@au.ibm.com>, IBM | ||
5 | * | ||
6 | * Based on earlier C version: | ||
7 | * Dave Engebretsen and Mike Corrigan {engebret|mikejc}@us.ibm.com | ||
8 | * Copyright (c) 2001 Dave Engebretsen | ||
9 | * Copyright (C) 2002 Anton Blanchard <anton@au.ibm.com>, IBM | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or | ||
12 | * modify it under the terms of the GNU General Public License | ||
13 | * as published by the Free Software Foundation; either version | ||
14 | * 2 of the License, or (at your option) any later version. | ||
15 | */ | ||
16 | |||
17 | #include <asm/processor.h> | ||
18 | #include <asm/ppc_asm.h> | ||
19 | #include <asm/asm-offsets.h> | ||
20 | #include <asm/cputable.h> | ||
21 | #include <asm/page.h> | ||
22 | #include <asm/mmu.h> | ||
23 | #include <asm/pgtable.h> | ||
24 | #include <asm/firmware.h> | ||
25 | #include <asm/feature-fixups.h> | ||
26 | |||
27 | /* | ||
28 | * This macro generates asm code to compute the VSID scramble | ||
29 | * function. Used in slb_allocate() and do_stab_bolted. The function | ||
30 | * computed is: (protovsid*VSID_MULTIPLIER) % VSID_MODULUS | ||
31 | * | ||
32 | * rt = register containing the proto-VSID and into which the | ||
33 | * VSID will be stored | ||
34 | * rx = scratch register (clobbered) | ||
35 | * rf = flags | ||
36 | * | ||
37 | * - rt and rx must be different registers | ||
38 | * - The answer will end up in the low VSID_BITS bits of rt. The higher | ||
39 | * bits may contain other garbage, so you may need to mask the | ||
40 | * result. | ||
41 | */ | ||
42 | #define ASM_VSID_SCRAMBLE(rt, rx, rf, size) \ | ||
43 | lis rx,VSID_MULTIPLIER_##size@h; \ | ||
44 | ori rx,rx,VSID_MULTIPLIER_##size@l; \ | ||
45 | mulld rt,rt,rx; /* rt = rt * MULTIPLIER */ \ | ||
46 | /* \ | ||
47 | * powermac get slb fault before feature fixup, so make 65 bit part \ | ||
48 | * the default part of feature fixup \ | ||
49 | */ \ | ||
50 | BEGIN_MMU_FTR_SECTION \ | ||
51 | srdi rx,rt,VSID_BITS_65_##size; \ | ||
52 | clrldi rt,rt,(64-VSID_BITS_65_##size); \ | ||
53 | add rt,rt,rx; \ | ||
54 | addi rx,rt,1; \ | ||
55 | srdi rx,rx,VSID_BITS_65_##size; \ | ||
56 | add rt,rt,rx; \ | ||
57 | rldimi rf,rt,SLB_VSID_SHIFT_##size,(64 - (SLB_VSID_SHIFT_##size + VSID_BITS_65_##size)); \ | ||
58 | MMU_FTR_SECTION_ELSE \ | ||
59 | srdi rx,rt,VSID_BITS_##size; \ | ||
60 | clrldi rt,rt,(64-VSID_BITS_##size); \ | ||
61 | add rt,rt,rx; /* add high and low bits */ \ | ||
62 | addi rx,rt,1; \ | ||
63 | srdi rx,rx,VSID_BITS_##size; /* extract 2^VSID_BITS bit */ \ | ||
64 | add rt,rt,rx; \ | ||
65 | rldimi rf,rt,SLB_VSID_SHIFT_##size,(64 - (SLB_VSID_SHIFT_##size + VSID_BITS_##size)); \ | ||
66 | ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_68_BIT_VA) | ||
67 | |||
68 | |||
69 | /* void slb_allocate(unsigned long ea); | ||
70 | * | ||
71 | * Create an SLB entry for the given EA (user or kernel). | ||
72 | * r3 = faulting address, r13 = PACA | ||
73 | * r9, r10, r11 are clobbered by this function | ||
74 | * r3 is preserved. | ||
75 | * No other registers are examined or changed. | ||
76 | */ | ||
77 | _GLOBAL(slb_allocate) | ||
78 | /* | ||
79 | * Check if the address falls within the range of the first context, or | ||
80 | * if we may need to handle multi context. For the first context we | ||
81 | * allocate the slb entry via the fast path below. For large address we | ||
82 | * branch out to C-code and see if additional contexts have been | ||
83 | * allocated. | ||
84 | * The test here is: | ||
85 | * (ea & ~REGION_MASK) >= (1ull << MAX_EA_BITS_PER_CONTEXT) | ||
86 | */ | ||
87 | rldicr. r9,r3,4,(63 - MAX_EA_BITS_PER_CONTEXT - 4) | ||
88 | bne- 8f | ||
89 | |||
90 | srdi r9,r3,60 /* get region */ | ||
91 | srdi r10,r3,SID_SHIFT /* get esid */ | ||
92 | cmpldi cr7,r9,0xc /* cmp PAGE_OFFSET for later use */ | ||
93 | |||
94 | /* r3 = address, r10 = esid, cr7 = <> PAGE_OFFSET */ | ||
95 | blt cr7,0f /* user or kernel? */ | ||
96 | |||
97 | /* Check if hitting the linear mapping or some other kernel space | ||
98 | */ | ||
99 | bne cr7,1f | ||
100 | |||
101 | /* Linear mapping encoding bits, the "li" instruction below will | ||
102 | * be patched by the kernel at boot | ||
103 | */ | ||
104 | .globl slb_miss_kernel_load_linear | ||
105 | slb_miss_kernel_load_linear: | ||
106 | li r11,0 | ||
107 | /* | ||
108 | * context = (ea >> 60) - (0xc - 1) | ||
109 | * r9 = region id. | ||
110 | */ | ||
111 | subi r9,r9,KERNEL_REGION_CONTEXT_OFFSET | ||
112 | |||
113 | BEGIN_FTR_SECTION | ||
114 | b .Lslb_finish_load | ||
115 | END_MMU_FTR_SECTION_IFCLR(MMU_FTR_1T_SEGMENT) | ||
116 | b .Lslb_finish_load_1T | ||
117 | |||
118 | 1: | ||
119 | #ifdef CONFIG_SPARSEMEM_VMEMMAP | ||
120 | cmpldi cr0,r9,0xf | ||
121 | bne 1f | ||
122 | /* Check virtual memmap region. To be patched at kernel boot */ | ||
123 | .globl slb_miss_kernel_load_vmemmap | ||
124 | slb_miss_kernel_load_vmemmap: | ||
125 | li r11,0 | ||
126 | b 6f | ||
127 | 1: | ||
128 | #endif /* CONFIG_SPARSEMEM_VMEMMAP */ | ||
129 | |||
130 | /* | ||
131 | * r10 contains the ESID, which is the original faulting EA shifted | ||
132 | * right by 28 bits. We need to compare that with (H_VMALLOC_END >> 28) | ||
133 | * which is 0xd00038000. That can't be used as an immediate, even if we | ||
134 | * ignored the 0xd, so we have to load it into a register, and we only | ||
135 | * have one register free. So we must load all of (H_VMALLOC_END >> 28) | ||
136 | * into a register and compare ESID against that. | ||
137 | */ | ||
138 | lis r11,(H_VMALLOC_END >> 32)@h // r11 = 0xffffffffd0000000 | ||
139 | ori r11,r11,(H_VMALLOC_END >> 32)@l // r11 = 0xffffffffd0003800 | ||
140 | // Rotate left 4, then mask with 0xffffffff0 | ||
141 | rldic r11,r11,4,28 // r11 = 0xd00038000 | ||
142 | cmpld r10,r11 // if r10 >= r11 | ||
143 | bge 5f // goto io_mapping | ||
144 | |||
145 | /* | ||
146 | * vmalloc mapping gets the encoding from the PACA as the mapping | ||
147 | * can be demoted from 64K -> 4K dynamically on some machines. | ||
148 | */ | ||
149 | lhz r11,PACAVMALLOCSLLP(r13) | ||
150 | b 6f | ||
151 | 5: | ||
152 | /* IO mapping */ | ||
153 | .globl slb_miss_kernel_load_io | ||
154 | slb_miss_kernel_load_io: | ||
155 | li r11,0 | ||
156 | 6: | ||
157 | /* | ||
158 | * context = (ea >> 60) - (0xc - 1) | ||
159 | * r9 = region id. | ||
160 | */ | ||
161 | subi r9,r9,KERNEL_REGION_CONTEXT_OFFSET | ||
162 | |||
163 | BEGIN_FTR_SECTION | ||
164 | b .Lslb_finish_load | ||
165 | END_MMU_FTR_SECTION_IFCLR(MMU_FTR_1T_SEGMENT) | ||
166 | b .Lslb_finish_load_1T | ||
167 | |||
168 | 0: /* | ||
169 | * For userspace addresses, make sure this is region 0. | ||
170 | */ | ||
171 | cmpdi r9, 0 | ||
172 | bne- 8f | ||
173 | /* | ||
174 | * user space make sure we are within the allowed limit | ||
175 | */ | ||
176 | ld r11,PACA_SLB_ADDR_LIMIT(r13) | ||
177 | cmpld r3,r11 | ||
178 | bge- 8f | ||
179 | |||
180 | /* when using slices, we extract the psize off the slice bitmaps | ||
181 | * and then we need to get the sllp encoding off the mmu_psize_defs | ||
182 | * array. | ||
183 | * | ||
184 | * XXX This is a bit inefficient especially for the normal case, | ||
185 | * so we should try to implement a fast path for the standard page | ||
186 | * size using the old sllp value so we avoid the array. We cannot | ||
187 | * really do dynamic patching unfortunately as processes might flip | ||
188 | * between 4k and 64k standard page size | ||
189 | */ | ||
190 | #ifdef CONFIG_PPC_MM_SLICES | ||
191 | /* r10 have esid */ | ||
192 | cmpldi r10,16 | ||
193 | /* below SLICE_LOW_TOP */ | ||
194 | blt 5f | ||
195 | /* | ||
196 | * Handle hpsizes, | ||
197 | * r9 is get_paca()->context.high_slices_psize[index], r11 is mask_index | ||
198 | */ | ||
199 | srdi r11,r10,(SLICE_HIGH_SHIFT - SLICE_LOW_SHIFT + 1) /* index */ | ||
200 | addi r9,r11,PACAHIGHSLICEPSIZE | ||
201 | lbzx r9,r13,r9 /* r9 is hpsizes[r11] */ | ||
202 | /* r11 = (r10 >> (SLICE_HIGH_SHIFT - SLICE_LOW_SHIFT)) & 0x1 */ | ||
203 | rldicl r11,r10,(64 - (SLICE_HIGH_SHIFT - SLICE_LOW_SHIFT)),63 | ||
204 | b 6f | ||
205 | |||
206 | 5: | ||
207 | /* | ||
208 | * Handle lpsizes | ||
209 | * r9 is get_paca()->context.low_slices_psize[index], r11 is mask_index | ||
210 | */ | ||
211 | srdi r11,r10,1 /* index */ | ||
212 | addi r9,r11,PACALOWSLICESPSIZE | ||
213 | lbzx r9,r13,r9 /* r9 is lpsizes[r11] */ | ||
214 | rldicl r11,r10,0,63 /* r11 = r10 & 0x1 */ | ||
215 | 6: | ||
216 | sldi r11,r11,2 /* index * 4 */ | ||
217 | /* Extract the psize and multiply to get an array offset */ | ||
218 | srd r9,r9,r11 | ||
219 | andi. r9,r9,0xf | ||
220 | mulli r9,r9,MMUPSIZEDEFSIZE | ||
221 | |||
222 | /* Now get to the array and obtain the sllp | ||
223 | */ | ||
224 | ld r11,PACATOC(r13) | ||
225 | ld r11,mmu_psize_defs@got(r11) | ||
226 | add r11,r11,r9 | ||
227 | ld r11,MMUPSIZESLLP(r11) | ||
228 | ori r11,r11,SLB_VSID_USER | ||
229 | #else | ||
230 | /* paca context sllp already contains the SLB_VSID_USER bits */ | ||
231 | lhz r11,PACACONTEXTSLLP(r13) | ||
232 | #endif /* CONFIG_PPC_MM_SLICES */ | ||
233 | |||
234 | ld r9,PACACONTEXTID(r13) | ||
235 | BEGIN_FTR_SECTION | ||
236 | cmpldi r10,0x1000 | ||
237 | bge .Lslb_finish_load_1T | ||
238 | END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT) | ||
239 | b .Lslb_finish_load | ||
240 | |||
241 | 8: /* invalid EA - return an error indication */ | ||
242 | crset 4*cr0+eq /* indicate failure */ | ||
243 | blr | ||
244 | |||
245 | /* | ||
246 | * Finish loading of an SLB entry and return | ||
247 | * | ||
248 | * r3 = EA, r9 = context, r10 = ESID, r11 = flags, clobbers r9, cr7 = <> PAGE_OFFSET | ||
249 | */ | ||
250 | .Lslb_finish_load: | ||
251 | rldimi r10,r9,ESID_BITS,0 | ||
252 | ASM_VSID_SCRAMBLE(r10,r9,r11,256M) | ||
253 | /* r3 = EA, r11 = VSID data */ | ||
254 | /* | ||
255 | * Find a slot, round robin. Previously we tried to find a | ||
256 | * free slot first but that took too long. Unfortunately we | ||
257 | * dont have any LRU information to help us choose a slot. | ||
258 | */ | ||
259 | |||
260 | mr r9,r3 | ||
261 | |||
262 | /* slb_finish_load_1T continues here. r9=EA with non-ESID bits clear */ | ||
263 | 7: ld r10,PACASTABRR(r13) | ||
264 | addi r10,r10,1 | ||
265 | /* This gets soft patched on boot. */ | ||
266 | .globl slb_compare_rr_to_size | ||
267 | slb_compare_rr_to_size: | ||
268 | cmpldi r10,0 | ||
269 | |||
270 | blt+ 4f | ||
271 | li r10,SLB_NUM_BOLTED | ||
272 | |||
273 | 4: | ||
274 | std r10,PACASTABRR(r13) | ||
275 | |||
276 | 3: | ||
277 | rldimi r9,r10,0,36 /* r9 = EA[0:35] | entry */ | ||
278 | oris r10,r9,SLB_ESID_V@h /* r10 = r9 | SLB_ESID_V */ | ||
279 | |||
280 | /* r9 = ESID data, r11 = VSID data */ | ||
281 | |||
282 | /* | ||
283 | * No need for an isync before or after this slbmte. The exception | ||
284 | * we enter with and the rfid we exit with are context synchronizing. | ||
285 | */ | ||
286 | slbmte r11,r10 | ||
287 | |||
288 | /* we're done for kernel addresses */ | ||
289 | crclr 4*cr0+eq /* set result to "success" */ | ||
290 | bgelr cr7 | ||
291 | |||
292 | /* Update the slb cache */ | ||
293 | lhz r9,PACASLBCACHEPTR(r13) /* offset = paca->slb_cache_ptr */ | ||
294 | cmpldi r9,SLB_CACHE_ENTRIES | ||
295 | bge 1f | ||
296 | |||
297 | /* still room in the slb cache */ | ||
298 | sldi r11,r9,2 /* r11 = offset * sizeof(u32) */ | ||
299 | srdi r10,r10,28 /* get the 36 bits of the ESID */ | ||
300 | add r11,r11,r13 /* r11 = (u32 *)paca + offset */ | ||
301 | stw r10,PACASLBCACHE(r11) /* paca->slb_cache[offset] = esid */ | ||
302 | addi r9,r9,1 /* offset++ */ | ||
303 | b 2f | ||
304 | 1: /* offset >= SLB_CACHE_ENTRIES */ | ||
305 | li r9,SLB_CACHE_ENTRIES+1 | ||
306 | 2: | ||
307 | sth r9,PACASLBCACHEPTR(r13) /* paca->slb_cache_ptr = offset */ | ||
308 | crclr 4*cr0+eq /* set result to "success" */ | ||
309 | blr | ||
310 | |||
311 | /* | ||
312 | * Finish loading of a 1T SLB entry (for the kernel linear mapping) and return. | ||
313 | * | ||
314 | * r3 = EA, r9 = context, r10 = ESID(256MB), r11 = flags, clobbers r9 | ||
315 | */ | ||
316 | .Lslb_finish_load_1T: | ||
317 | srdi r10,r10,(SID_SHIFT_1T - SID_SHIFT) /* get 1T ESID */ | ||
318 | rldimi r10,r9,ESID_BITS_1T,0 | ||
319 | ASM_VSID_SCRAMBLE(r10,r9,r11,1T) | ||
320 | |||
321 | li r10,MMU_SEGSIZE_1T | ||
322 | rldimi r11,r10,SLB_VSID_SSIZE_SHIFT,0 /* insert segment size */ | ||
323 | |||
324 | /* r3 = EA, r11 = VSID data */ | ||
325 | clrrdi r9,r3,SID_SHIFT_1T /* clear out non-ESID bits */ | ||
326 | b 7b | ||
327 | |||
328 | |||
329 | _ASM_NOKPROBE_SYMBOL(slb_allocate) | ||
330 | _ASM_NOKPROBE_SYMBOL(slb_miss_kernel_load_linear) | ||
331 | _ASM_NOKPROBE_SYMBOL(slb_miss_kernel_load_io) | ||
332 | _ASM_NOKPROBE_SYMBOL(slb_compare_rr_to_size) | ||
333 | #ifdef CONFIG_SPARSEMEM_VMEMMAP | ||
334 | _ASM_NOKPROBE_SYMBOL(slb_miss_kernel_load_vmemmap) | ||
335 | #endif | ||
diff --git a/arch/powerpc/mm/slice.c b/arch/powerpc/mm/slice.c index 205fe557ca10..06898c13901d 100644 --- a/arch/powerpc/mm/slice.c +++ b/arch/powerpc/mm/slice.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/spinlock.h> | 31 | #include <linux/spinlock.h> |
32 | #include <linux/export.h> | 32 | #include <linux/export.h> |
33 | #include <linux/hugetlb.h> | 33 | #include <linux/hugetlb.h> |
34 | #include <linux/sched/mm.h> | ||
34 | #include <asm/mman.h> | 35 | #include <asm/mman.h> |
35 | #include <asm/mmu.h> | 36 | #include <asm/mmu.h> |
36 | #include <asm/copro.h> | 37 | #include <asm/copro.h> |
@@ -61,6 +62,13 @@ static void slice_print_mask(const char *label, const struct slice_mask *mask) { | |||
61 | 62 | ||
62 | #endif | 63 | #endif |
63 | 64 | ||
65 | static inline bool slice_addr_is_low(unsigned long addr) | ||
66 | { | ||
67 | u64 tmp = (u64)addr; | ||
68 | |||
69 | return tmp < SLICE_LOW_TOP; | ||
70 | } | ||
71 | |||
64 | static void slice_range_to_mask(unsigned long start, unsigned long len, | 72 | static void slice_range_to_mask(unsigned long start, unsigned long len, |
65 | struct slice_mask *ret) | 73 | struct slice_mask *ret) |
66 | { | 74 | { |
@@ -70,7 +78,7 @@ static void slice_range_to_mask(unsigned long start, unsigned long len, | |||
70 | if (SLICE_NUM_HIGH) | 78 | if (SLICE_NUM_HIGH) |
71 | bitmap_zero(ret->high_slices, SLICE_NUM_HIGH); | 79 | bitmap_zero(ret->high_slices, SLICE_NUM_HIGH); |
72 | 80 | ||
73 | if (start < SLICE_LOW_TOP) { | 81 | if (slice_addr_is_low(start)) { |
74 | unsigned long mend = min(end, | 82 | unsigned long mend = min(end, |
75 | (unsigned long)(SLICE_LOW_TOP - 1)); | 83 | (unsigned long)(SLICE_LOW_TOP - 1)); |
76 | 84 | ||
@@ -78,7 +86,7 @@ static void slice_range_to_mask(unsigned long start, unsigned long len, | |||
78 | - (1u << GET_LOW_SLICE_INDEX(start)); | 86 | - (1u << GET_LOW_SLICE_INDEX(start)); |
79 | } | 87 | } |
80 | 88 | ||
81 | if ((start + len) > SLICE_LOW_TOP) { | 89 | if (SLICE_NUM_HIGH && !slice_addr_is_low(end)) { |
82 | unsigned long start_index = GET_HIGH_SLICE_INDEX(start); | 90 | unsigned long start_index = GET_HIGH_SLICE_INDEX(start); |
83 | unsigned long align_end = ALIGN(end, (1UL << SLICE_HIGH_SHIFT)); | 91 | unsigned long align_end = ALIGN(end, (1UL << SLICE_HIGH_SHIFT)); |
84 | unsigned long count = GET_HIGH_SLICE_INDEX(align_end) - start_index; | 92 | unsigned long count = GET_HIGH_SLICE_INDEX(align_end) - start_index; |
@@ -133,7 +141,7 @@ static void slice_mask_for_free(struct mm_struct *mm, struct slice_mask *ret, | |||
133 | if (!slice_low_has_vma(mm, i)) | 141 | if (!slice_low_has_vma(mm, i)) |
134 | ret->low_slices |= 1u << i; | 142 | ret->low_slices |= 1u << i; |
135 | 143 | ||
136 | if (high_limit <= SLICE_LOW_TOP) | 144 | if (slice_addr_is_low(high_limit - 1)) |
137 | return; | 145 | return; |
138 | 146 | ||
139 | for (i = 0; i < GET_HIGH_SLICE_INDEX(high_limit); i++) | 147 | for (i = 0; i < GET_HIGH_SLICE_INDEX(high_limit); i++) |
@@ -182,7 +190,7 @@ static bool slice_check_range_fits(struct mm_struct *mm, | |||
182 | unsigned long end = start + len - 1; | 190 | unsigned long end = start + len - 1; |
183 | u64 low_slices = 0; | 191 | u64 low_slices = 0; |
184 | 192 | ||
185 | if (start < SLICE_LOW_TOP) { | 193 | if (slice_addr_is_low(start)) { |
186 | unsigned long mend = min(end, | 194 | unsigned long mend = min(end, |
187 | (unsigned long)(SLICE_LOW_TOP - 1)); | 195 | (unsigned long)(SLICE_LOW_TOP - 1)); |
188 | 196 | ||
@@ -192,7 +200,7 @@ static bool slice_check_range_fits(struct mm_struct *mm, | |||
192 | if ((low_slices & available->low_slices) != low_slices) | 200 | if ((low_slices & available->low_slices) != low_slices) |
193 | return false; | 201 | return false; |
194 | 202 | ||
195 | if (SLICE_NUM_HIGH && ((start + len) > SLICE_LOW_TOP)) { | 203 | if (SLICE_NUM_HIGH && !slice_addr_is_low(end)) { |
196 | unsigned long start_index = GET_HIGH_SLICE_INDEX(start); | 204 | unsigned long start_index = GET_HIGH_SLICE_INDEX(start); |
197 | unsigned long align_end = ALIGN(end, (1UL << SLICE_HIGH_SHIFT)); | 205 | unsigned long align_end = ALIGN(end, (1UL << SLICE_HIGH_SHIFT)); |
198 | unsigned long count = GET_HIGH_SLICE_INDEX(align_end) - start_index; | 206 | unsigned long count = GET_HIGH_SLICE_INDEX(align_end) - start_index; |
@@ -219,7 +227,7 @@ static void slice_flush_segments(void *parm) | |||
219 | copy_mm_to_paca(current->active_mm); | 227 | copy_mm_to_paca(current->active_mm); |
220 | 228 | ||
221 | local_irq_save(flags); | 229 | local_irq_save(flags); |
222 | slb_flush_and_rebolt(); | 230 | slb_flush_and_restore_bolted(); |
223 | local_irq_restore(flags); | 231 | local_irq_restore(flags); |
224 | #endif | 232 | #endif |
225 | } | 233 | } |
@@ -303,7 +311,7 @@ static bool slice_scan_available(unsigned long addr, | |||
303 | int end, unsigned long *boundary_addr) | 311 | int end, unsigned long *boundary_addr) |
304 | { | 312 | { |
305 | unsigned long slice; | 313 | unsigned long slice; |
306 | if (addr < SLICE_LOW_TOP) { | 314 | if (slice_addr_is_low(addr)) { |
307 | slice = GET_LOW_SLICE_INDEX(addr); | 315 | slice = GET_LOW_SLICE_INDEX(addr); |
308 | *boundary_addr = (slice + end) << SLICE_LOW_SHIFT; | 316 | *boundary_addr = (slice + end) << SLICE_LOW_SHIFT; |
309 | return !!(available->low_slices & (1u << slice)); | 317 | return !!(available->low_slices & (1u << slice)); |
@@ -706,7 +714,7 @@ unsigned int get_slice_psize(struct mm_struct *mm, unsigned long addr) | |||
706 | 714 | ||
707 | VM_BUG_ON(radix_enabled()); | 715 | VM_BUG_ON(radix_enabled()); |
708 | 716 | ||
709 | if (addr < SLICE_LOW_TOP) { | 717 | if (slice_addr_is_low(addr)) { |
710 | psizes = mm->context.low_slices_psize; | 718 | psizes = mm->context.low_slices_psize; |
711 | index = GET_LOW_SLICE_INDEX(addr); | 719 | index = GET_LOW_SLICE_INDEX(addr); |
712 | } else { | 720 | } else { |
@@ -757,6 +765,20 @@ void slice_init_new_context_exec(struct mm_struct *mm) | |||
757 | bitmap_fill(mask->high_slices, SLICE_NUM_HIGH); | 765 | bitmap_fill(mask->high_slices, SLICE_NUM_HIGH); |
758 | } | 766 | } |
759 | 767 | ||
768 | #ifdef CONFIG_PPC_BOOK3S_64 | ||
769 | void slice_setup_new_exec(void) | ||
770 | { | ||
771 | struct mm_struct *mm = current->mm; | ||
772 | |||
773 | slice_dbg("slice_setup_new_exec(mm=%p)\n", mm); | ||
774 | |||
775 | if (!is_32bit_task()) | ||
776 | return; | ||
777 | |||
778 | mm->context.slb_addr_limit = DEFAULT_MAP_WINDOW; | ||
779 | } | ||
780 | #endif | ||
781 | |||
760 | void slice_set_range_psize(struct mm_struct *mm, unsigned long start, | 782 | void slice_set_range_psize(struct mm_struct *mm, unsigned long start, |
761 | unsigned long len, unsigned int psize) | 783 | unsigned long len, unsigned int psize) |
762 | { | 784 | { |
diff --git a/arch/powerpc/mm/tlb-radix.c b/arch/powerpc/mm/tlb-radix.c index 4c4dfc473800..6a23b9ebd2a1 100644 --- a/arch/powerpc/mm/tlb-radix.c +++ b/arch/powerpc/mm/tlb-radix.c | |||
@@ -366,6 +366,7 @@ static inline void _tlbiel_lpid_guest(unsigned long lpid, unsigned long ric) | |||
366 | __tlbiel_lpid_guest(lpid, set, RIC_FLUSH_TLB); | 366 | __tlbiel_lpid_guest(lpid, set, RIC_FLUSH_TLB); |
367 | 367 | ||
368 | asm volatile("ptesync": : :"memory"); | 368 | asm volatile("ptesync": : :"memory"); |
369 | asm volatile(PPC_INVALIDATE_ERAT : : :"memory"); | ||
369 | } | 370 | } |
370 | 371 | ||
371 | 372 | ||
@@ -1016,7 +1017,6 @@ void radix__flush_tlb_collapsed_pmd(struct mm_struct *mm, unsigned long addr) | |||
1016 | goto local; | 1017 | goto local; |
1017 | } | 1018 | } |
1018 | _tlbie_va_range(addr, end, pid, PAGE_SIZE, mmu_virtual_psize, true); | 1019 | _tlbie_va_range(addr, end, pid, PAGE_SIZE, mmu_virtual_psize, true); |
1019 | goto local; | ||
1020 | } else { | 1020 | } else { |
1021 | local: | 1021 | local: |
1022 | _tlbiel_va_range(addr, end, pid, PAGE_SIZE, mmu_virtual_psize, true); | 1022 | _tlbiel_va_range(addr, end, pid, PAGE_SIZE, mmu_virtual_psize, true); |
diff --git a/arch/powerpc/mm/tlb_nohash.c b/arch/powerpc/mm/tlb_nohash.c index 15fe5f0c8665..ae5d568e267f 100644 --- a/arch/powerpc/mm/tlb_nohash.c +++ b/arch/powerpc/mm/tlb_nohash.c | |||
@@ -503,6 +503,9 @@ static void setup_page_sizes(void) | |||
503 | for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) { | 503 | for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) { |
504 | struct mmu_psize_def *def = &mmu_psize_defs[psize]; | 504 | struct mmu_psize_def *def = &mmu_psize_defs[psize]; |
505 | 505 | ||
506 | if (!def->shift) | ||
507 | continue; | ||
508 | |||
506 | if (tlb1ps & (1U << (def->shift - 10))) { | 509 | if (tlb1ps & (1U << (def->shift - 10))) { |
507 | def->flags |= MMU_PAGE_SIZE_DIRECT; | 510 | def->flags |= MMU_PAGE_SIZE_DIRECT; |
508 | 511 | ||
diff --git a/arch/powerpc/oprofile/Makefile b/arch/powerpc/oprofile/Makefile index 7a7834c39f64..8d26d7416481 100644 --- a/arch/powerpc/oprofile/Makefile +++ b/arch/powerpc/oprofile/Makefile | |||
@@ -1,5 +1,4 @@ | |||
1 | # SPDX-License-Identifier: GPL-2.0 | 1 | # SPDX-License-Identifier: GPL-2.0 |
2 | subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror | ||
3 | 2 | ||
4 | ccflags-$(CONFIG_PPC64) := $(NO_MINIMAL_TOC) | 3 | ccflags-$(CONFIG_PPC64) := $(NO_MINIMAL_TOC) |
5 | 4 | ||
diff --git a/arch/powerpc/perf/Makefile b/arch/powerpc/perf/Makefile index 82986d2acd9b..ab26df5bacb9 100644 --- a/arch/powerpc/perf/Makefile +++ b/arch/powerpc/perf/Makefile | |||
@@ -1,5 +1,4 @@ | |||
1 | # SPDX-License-Identifier: GPL-2.0 | 1 | # SPDX-License-Identifier: GPL-2.0 |
2 | subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror | ||
3 | 2 | ||
4 | obj-$(CONFIG_PERF_EVENTS) += callchain.o perf_regs.o | 3 | obj-$(CONFIG_PERF_EVENTS) += callchain.o perf_regs.o |
5 | 4 | ||
diff --git a/arch/powerpc/perf/imc-pmu.c b/arch/powerpc/perf/imc-pmu.c index 1fafc32b12a0..6954636b16d1 100644 --- a/arch/powerpc/perf/imc-pmu.c +++ b/arch/powerpc/perf/imc-pmu.c | |||
@@ -1392,7 +1392,7 @@ int init_imc_pmu(struct device_node *parent, struct imc_pmu *pmu_ptr, int pmu_id | |||
1392 | if (ret) | 1392 | if (ret) |
1393 | goto err_free_cpuhp_mem; | 1393 | goto err_free_cpuhp_mem; |
1394 | 1394 | ||
1395 | pr_info("%s performance monitor hardware support registered\n", | 1395 | pr_debug("%s performance monitor hardware support registered\n", |
1396 | pmu_ptr->pmu.name); | 1396 | pmu_ptr->pmu.name); |
1397 | 1397 | ||
1398 | return 0; | 1398 | return 0; |
diff --git a/arch/powerpc/perf/power7-pmu.c b/arch/powerpc/perf/power7-pmu.c index 7963658dbc22..6dbae9884ec4 100644 --- a/arch/powerpc/perf/power7-pmu.c +++ b/arch/powerpc/perf/power7-pmu.c | |||
@@ -238,6 +238,7 @@ static int power7_marked_instr_event(u64 event) | |||
238 | case 6: | 238 | case 6: |
239 | if (psel == 0x64) | 239 | if (psel == 0x64) |
240 | return pmc >= 3; | 240 | return pmc >= 3; |
241 | break; | ||
241 | case 8: | 242 | case 8: |
242 | return unit == 0xd; | 243 | return unit == 0xd; |
243 | } | 244 | } |
diff --git a/arch/powerpc/platforms/40x/Kconfig b/arch/powerpc/platforms/40x/Kconfig index 60254a321a91..2a9d66254ffc 100644 --- a/arch/powerpc/platforms/40x/Kconfig +++ b/arch/powerpc/platforms/40x/Kconfig | |||
@@ -2,7 +2,6 @@ | |||
2 | config ACADIA | 2 | config ACADIA |
3 | bool "Acadia" | 3 | bool "Acadia" |
4 | depends on 40x | 4 | depends on 40x |
5 | default n | ||
6 | select PPC40x_SIMPLE | 5 | select PPC40x_SIMPLE |
7 | select 405EZ | 6 | select 405EZ |
8 | help | 7 | help |
@@ -11,7 +10,6 @@ config ACADIA | |||
11 | config EP405 | 10 | config EP405 |
12 | bool "EP405/EP405PC" | 11 | bool "EP405/EP405PC" |
13 | depends on 40x | 12 | depends on 40x |
14 | default n | ||
15 | select 405GP | 13 | select 405GP |
16 | select PCI | 14 | select PCI |
17 | help | 15 | help |
@@ -20,7 +18,6 @@ config EP405 | |||
20 | config HOTFOOT | 18 | config HOTFOOT |
21 | bool "Hotfoot" | 19 | bool "Hotfoot" |
22 | depends on 40x | 20 | depends on 40x |
23 | default n | ||
24 | select PPC40x_SIMPLE | 21 | select PPC40x_SIMPLE |
25 | select PCI | 22 | select PCI |
26 | help | 23 | help |
@@ -29,7 +26,6 @@ config HOTFOOT | |||
29 | config KILAUEA | 26 | config KILAUEA |
30 | bool "Kilauea" | 27 | bool "Kilauea" |
31 | depends on 40x | 28 | depends on 40x |
32 | default n | ||
33 | select 405EX | 29 | select 405EX |
34 | select PPC40x_SIMPLE | 30 | select PPC40x_SIMPLE |
35 | select PPC4xx_PCI_EXPRESS | 31 | select PPC4xx_PCI_EXPRESS |
@@ -41,7 +37,6 @@ config KILAUEA | |||
41 | config MAKALU | 37 | config MAKALU |
42 | bool "Makalu" | 38 | bool "Makalu" |
43 | depends on 40x | 39 | depends on 40x |
44 | default n | ||
45 | select 405EX | 40 | select 405EX |
46 | select PCI | 41 | select PCI |
47 | select PPC4xx_PCI_EXPRESS | 42 | select PPC4xx_PCI_EXPRESS |
@@ -62,7 +57,6 @@ config WALNUT | |||
62 | config XILINX_VIRTEX_GENERIC_BOARD | 57 | config XILINX_VIRTEX_GENERIC_BOARD |
63 | bool "Generic Xilinx Virtex board" | 58 | bool "Generic Xilinx Virtex board" |
64 | depends on 40x | 59 | depends on 40x |
65 | default n | ||
66 | select XILINX_VIRTEX_II_PRO | 60 | select XILINX_VIRTEX_II_PRO |
67 | select XILINX_VIRTEX_4_FX | 61 | select XILINX_VIRTEX_4_FX |
68 | select XILINX_INTC | 62 | select XILINX_INTC |
@@ -80,7 +74,6 @@ config XILINX_VIRTEX_GENERIC_BOARD | |||
80 | config OBS600 | 74 | config OBS600 |
81 | bool "OpenBlockS 600" | 75 | bool "OpenBlockS 600" |
82 | depends on 40x | 76 | depends on 40x |
83 | default n | ||
84 | select 405EX | 77 | select 405EX |
85 | select PPC40x_SIMPLE | 78 | select PPC40x_SIMPLE |
86 | help | 79 | help |
@@ -90,7 +83,6 @@ config OBS600 | |||
90 | config PPC40x_SIMPLE | 83 | config PPC40x_SIMPLE |
91 | bool "Simple PowerPC 40x board support" | 84 | bool "Simple PowerPC 40x board support" |
92 | depends on 40x | 85 | depends on 40x |
93 | default n | ||
94 | help | 86 | help |
95 | This option enables the simple PowerPC 40x platform support. | 87 | This option enables the simple PowerPC 40x platform support. |
96 | 88 | ||
@@ -156,7 +148,6 @@ config IBM405_ERR51 | |||
156 | config APM8018X | 148 | config APM8018X |
157 | bool "APM8018X" | 149 | bool "APM8018X" |
158 | depends on 40x | 150 | depends on 40x |
159 | default n | ||
160 | select PPC40x_SIMPLE | 151 | select PPC40x_SIMPLE |
161 | help | 152 | help |
162 | This option enables support for the AppliedMicro APM8018X evaluation | 153 | This option enables support for the AppliedMicro APM8018X evaluation |
diff --git a/arch/powerpc/platforms/44x/Kconfig b/arch/powerpc/platforms/44x/Kconfig index a6011422b861..f024efd5a4c2 100644 --- a/arch/powerpc/platforms/44x/Kconfig +++ b/arch/powerpc/platforms/44x/Kconfig | |||
@@ -2,7 +2,6 @@ | |||
2 | config PPC_47x | 2 | config PPC_47x |
3 | bool "Support for 47x variant" | 3 | bool "Support for 47x variant" |
4 | depends on 44x | 4 | depends on 44x |
5 | default n | ||
6 | select MPIC | 5 | select MPIC |
7 | help | 6 | help |
8 | This option enables support for the 47x family of processors and is | 7 | This option enables support for the 47x family of processors and is |
@@ -11,7 +10,6 @@ config PPC_47x | |||
11 | config BAMBOO | 10 | config BAMBOO |
12 | bool "Bamboo" | 11 | bool "Bamboo" |
13 | depends on 44x | 12 | depends on 44x |
14 | default n | ||
15 | select PPC44x_SIMPLE | 13 | select PPC44x_SIMPLE |
16 | select 440EP | 14 | select 440EP |
17 | select PCI | 15 | select PCI |
@@ -21,7 +19,6 @@ config BAMBOO | |||
21 | config BLUESTONE | 19 | config BLUESTONE |
22 | bool "Bluestone" | 20 | bool "Bluestone" |
23 | depends on 44x | 21 | depends on 44x |
24 | default n | ||
25 | select PPC44x_SIMPLE | 22 | select PPC44x_SIMPLE |
26 | select APM821xx | 23 | select APM821xx |
27 | select PCI_MSI | 24 | select PCI_MSI |
@@ -44,7 +41,6 @@ config EBONY | |||
44 | config SAM440EP | 41 | config SAM440EP |
45 | bool "Sam440ep" | 42 | bool "Sam440ep" |
46 | depends on 44x | 43 | depends on 44x |
47 | default n | ||
48 | select 440EP | 44 | select 440EP |
49 | select PCI | 45 | select PCI |
50 | help | 46 | help |
@@ -53,7 +49,6 @@ config SAM440EP | |||
53 | config SEQUOIA | 49 | config SEQUOIA |
54 | bool "Sequoia" | 50 | bool "Sequoia" |
55 | depends on 44x | 51 | depends on 44x |
56 | default n | ||
57 | select PPC44x_SIMPLE | 52 | select PPC44x_SIMPLE |
58 | select 440EPX | 53 | select 440EPX |
59 | help | 54 | help |
@@ -62,7 +57,6 @@ config SEQUOIA | |||
62 | config TAISHAN | 57 | config TAISHAN |
63 | bool "Taishan" | 58 | bool "Taishan" |
64 | depends on 44x | 59 | depends on 44x |
65 | default n | ||
66 | select PPC44x_SIMPLE | 60 | select PPC44x_SIMPLE |
67 | select 440GX | 61 | select 440GX |
68 | select PCI | 62 | select PCI |
@@ -73,7 +67,6 @@ config TAISHAN | |||
73 | config KATMAI | 67 | config KATMAI |
74 | bool "Katmai" | 68 | bool "Katmai" |
75 | depends on 44x | 69 | depends on 44x |
76 | default n | ||
77 | select PPC44x_SIMPLE | 70 | select PPC44x_SIMPLE |
78 | select 440SPe | 71 | select 440SPe |
79 | select PCI | 72 | select PCI |
@@ -86,7 +79,6 @@ config KATMAI | |||
86 | config RAINIER | 79 | config RAINIER |
87 | bool "Rainier" | 80 | bool "Rainier" |
88 | depends on 44x | 81 | depends on 44x |
89 | default n | ||
90 | select PPC44x_SIMPLE | 82 | select PPC44x_SIMPLE |
91 | select 440GRX | 83 | select 440GRX |
92 | select PCI | 84 | select PCI |
@@ -96,7 +88,6 @@ config RAINIER | |||
96 | config WARP | 88 | config WARP |
97 | bool "PIKA Warp" | 89 | bool "PIKA Warp" |
98 | depends on 44x | 90 | depends on 44x |
99 | default n | ||
100 | select 440EP | 91 | select 440EP |
101 | help | 92 | help |
102 | This option enables support for the PIKA Warp(tm) Appliance. The Warp | 93 | This option enables support for the PIKA Warp(tm) Appliance. The Warp |
@@ -109,7 +100,6 @@ config WARP | |||
109 | config ARCHES | 100 | config ARCHES |
110 | bool "Arches" | 101 | bool "Arches" |
111 | depends on 44x | 102 | depends on 44x |
112 | default n | ||
113 | select PPC44x_SIMPLE | 103 | select PPC44x_SIMPLE |
114 | select 460EX # Odd since it uses 460GT but the effects are the same | 104 | select 460EX # Odd since it uses 460GT but the effects are the same |
115 | select PCI | 105 | select PCI |
@@ -120,7 +110,6 @@ config ARCHES | |||
120 | config CANYONLANDS | 110 | config CANYONLANDS |
121 | bool "Canyonlands" | 111 | bool "Canyonlands" |
122 | depends on 44x | 112 | depends on 44x |
123 | default n | ||
124 | select 460EX | 113 | select 460EX |
125 | select PCI | 114 | select PCI |
126 | select PPC4xx_PCI_EXPRESS | 115 | select PPC4xx_PCI_EXPRESS |
@@ -134,7 +123,6 @@ config CANYONLANDS | |||
134 | config GLACIER | 123 | config GLACIER |
135 | bool "Glacier" | 124 | bool "Glacier" |
136 | depends on 44x | 125 | depends on 44x |
137 | default n | ||
138 | select PPC44x_SIMPLE | 126 | select PPC44x_SIMPLE |
139 | select 460EX # Odd since it uses 460GT but the effects are the same | 127 | select 460EX # Odd since it uses 460GT but the effects are the same |
140 | select PCI | 128 | select PCI |
@@ -147,7 +135,6 @@ config GLACIER | |||
147 | config REDWOOD | 135 | config REDWOOD |
148 | bool "Redwood" | 136 | bool "Redwood" |
149 | depends on 44x | 137 | depends on 44x |
150 | default n | ||
151 | select PPC44x_SIMPLE | 138 | select PPC44x_SIMPLE |
152 | select 460SX | 139 | select 460SX |
153 | select PCI | 140 | select PCI |
@@ -160,7 +147,6 @@ config REDWOOD | |||
160 | config EIGER | 147 | config EIGER |
161 | bool "Eiger" | 148 | bool "Eiger" |
162 | depends on 44x | 149 | depends on 44x |
163 | default n | ||
164 | select PPC44x_SIMPLE | 150 | select PPC44x_SIMPLE |
165 | select 460SX | 151 | select 460SX |
166 | select PCI | 152 | select PCI |
@@ -172,7 +158,6 @@ config EIGER | |||
172 | config YOSEMITE | 158 | config YOSEMITE |
173 | bool "Yosemite" | 159 | bool "Yosemite" |
174 | depends on 44x | 160 | depends on 44x |
175 | default n | ||
176 | select PPC44x_SIMPLE | 161 | select PPC44x_SIMPLE |
177 | select 440EP | 162 | select 440EP |
178 | select PCI | 163 | select PCI |
@@ -182,7 +167,6 @@ config YOSEMITE | |||
182 | config ISS4xx | 167 | config ISS4xx |
183 | bool "ISS 4xx Simulator" | 168 | bool "ISS 4xx Simulator" |
184 | depends on (44x || 40x) | 169 | depends on (44x || 40x) |
185 | default n | ||
186 | select 405GP if 40x | 170 | select 405GP if 40x |
187 | select 440GP if 44x && !PPC_47x | 171 | select 440GP if 44x && !PPC_47x |
188 | select PPC_FPU | 172 | select PPC_FPU |
@@ -193,7 +177,6 @@ config ISS4xx | |||
193 | config CURRITUCK | 177 | config CURRITUCK |
194 | bool "IBM Currituck (476fpe) Support" | 178 | bool "IBM Currituck (476fpe) Support" |
195 | depends on PPC_47x | 179 | depends on PPC_47x |
196 | default n | ||
197 | select SWIOTLB | 180 | select SWIOTLB |
198 | select 476FPE | 181 | select 476FPE |
199 | select PPC4xx_PCI_EXPRESS | 182 | select PPC4xx_PCI_EXPRESS |
@@ -203,7 +186,6 @@ config CURRITUCK | |||
203 | config FSP2 | 186 | config FSP2 |
204 | bool "IBM FSP2 (476fpe) Support" | 187 | bool "IBM FSP2 (476fpe) Support" |
205 | depends on PPC_47x | 188 | depends on PPC_47x |
206 | default n | ||
207 | select 476FPE | 189 | select 476FPE |
208 | select IBM_EMAC_EMAC4 if IBM_EMAC | 190 | select IBM_EMAC_EMAC4 if IBM_EMAC |
209 | select IBM_EMAC_RGMII if IBM_EMAC | 191 | select IBM_EMAC_RGMII if IBM_EMAC |
@@ -215,7 +197,6 @@ config FSP2 | |||
215 | config AKEBONO | 197 | config AKEBONO |
216 | bool "IBM Akebono (476gtr) Support" | 198 | bool "IBM Akebono (476gtr) Support" |
217 | depends on PPC_47x | 199 | depends on PPC_47x |
218 | default n | ||
219 | select SWIOTLB | 200 | select SWIOTLB |
220 | select 476FPE | 201 | select 476FPE |
221 | select PPC4xx_PCI_EXPRESS | 202 | select PPC4xx_PCI_EXPRESS |
@@ -241,7 +222,6 @@ config AKEBONO | |||
241 | config ICON | 222 | config ICON |
242 | bool "Icon" | 223 | bool "Icon" |
243 | depends on 44x | 224 | depends on 44x |
244 | default n | ||
245 | select PPC44x_SIMPLE | 225 | select PPC44x_SIMPLE |
246 | select 440SPe | 226 | select 440SPe |
247 | select PCI | 227 | select PCI |
@@ -252,7 +232,6 @@ config ICON | |||
252 | config XILINX_VIRTEX440_GENERIC_BOARD | 232 | config XILINX_VIRTEX440_GENERIC_BOARD |
253 | bool "Generic Xilinx Virtex 5 FXT board support" | 233 | bool "Generic Xilinx Virtex 5 FXT board support" |
254 | depends on 44x | 234 | depends on 44x |
255 | default n | ||
256 | select XILINX_VIRTEX_5_FXT | 235 | select XILINX_VIRTEX_5_FXT |
257 | select XILINX_INTC | 236 | select XILINX_INTC |
258 | help | 237 | help |
@@ -280,7 +259,6 @@ config XILINX_ML510 | |||
280 | config PPC44x_SIMPLE | 259 | config PPC44x_SIMPLE |
281 | bool "Simple PowerPC 44x board support" | 260 | bool "Simple PowerPC 44x board support" |
282 | depends on 44x | 261 | depends on 44x |
283 | default n | ||
284 | help | 262 | help |
285 | This option enables the simple PowerPC 44x platform support. | 263 | This option enables the simple PowerPC 44x platform support. |
286 | 264 | ||
diff --git a/arch/powerpc/platforms/44x/fsp2.c b/arch/powerpc/platforms/44x/fsp2.c index 04f0c73a9b4f..7a507f775308 100644 --- a/arch/powerpc/platforms/44x/fsp2.c +++ b/arch/powerpc/platforms/44x/fsp2.c | |||
@@ -210,15 +210,15 @@ static void node_irq_request(const char *compat, irq_handler_t errirq_handler) | |||
210 | for_each_compatible_node(np, NULL, compat) { | 210 | for_each_compatible_node(np, NULL, compat) { |
211 | irq = irq_of_parse_and_map(np, 0); | 211 | irq = irq_of_parse_and_map(np, 0); |
212 | if (irq == NO_IRQ) { | 212 | if (irq == NO_IRQ) { |
213 | pr_err("device tree node %s is missing a interrupt", | 213 | pr_err("device tree node %pOFn is missing a interrupt", |
214 | np->name); | 214 | np); |
215 | return; | 215 | return; |
216 | } | 216 | } |
217 | 217 | ||
218 | rc = request_irq(irq, errirq_handler, 0, np->name, np); | 218 | rc = request_irq(irq, errirq_handler, 0, np->name, np); |
219 | if (rc) { | 219 | if (rc) { |
220 | pr_err("fsp_of_probe: request_irq failed: np=%s rc=%d", | 220 | pr_err("fsp_of_probe: request_irq failed: np=%pOF rc=%d", |
221 | np->full_name, rc); | 221 | np, rc); |
222 | return; | 222 | return; |
223 | } | 223 | } |
224 | } | 224 | } |
diff --git a/arch/powerpc/platforms/4xx/ocm.c b/arch/powerpc/platforms/4xx/ocm.c index 69d9f60d9fe5..f5bbd4563342 100644 --- a/arch/powerpc/platforms/4xx/ocm.c +++ b/arch/powerpc/platforms/4xx/ocm.c | |||
@@ -113,7 +113,6 @@ static void __init ocm_init_node(int count, struct device_node *node) | |||
113 | int len; | 113 | int len; |
114 | 114 | ||
115 | struct resource rsrc; | 115 | struct resource rsrc; |
116 | int ioflags; | ||
117 | 116 | ||
118 | ocm = ocm_get_node(count); | 117 | ocm = ocm_get_node(count); |
119 | 118 | ||
@@ -179,9 +178,8 @@ static void __init ocm_init_node(int count, struct device_node *node) | |||
179 | 178 | ||
180 | /* ioremap the non-cached region */ | 179 | /* ioremap the non-cached region */ |
181 | if (ocm->nc.memtotal) { | 180 | if (ocm->nc.memtotal) { |
182 | ioflags = _PAGE_NO_CACHE | _PAGE_GUARDED | _PAGE_EXEC; | ||
183 | ocm->nc.virt = __ioremap(ocm->nc.phys, ocm->nc.memtotal, | 181 | ocm->nc.virt = __ioremap(ocm->nc.phys, ocm->nc.memtotal, |
184 | ioflags); | 182 | _PAGE_EXEC | PAGE_KERNEL_NCG); |
185 | 183 | ||
186 | if (!ocm->nc.virt) { | 184 | if (!ocm->nc.virt) { |
187 | printk(KERN_ERR | 185 | printk(KERN_ERR |
@@ -195,9 +193,8 @@ static void __init ocm_init_node(int count, struct device_node *node) | |||
195 | /* ioremap the cached region */ | 193 | /* ioremap the cached region */ |
196 | 194 | ||
197 | if (ocm->c.memtotal) { | 195 | if (ocm->c.memtotal) { |
198 | ioflags = _PAGE_EXEC; | ||
199 | ocm->c.virt = __ioremap(ocm->c.phys, ocm->c.memtotal, | 196 | ocm->c.virt = __ioremap(ocm->c.phys, ocm->c.memtotal, |
200 | ioflags); | 197 | _PAGE_EXEC | PAGE_KERNEL); |
201 | 198 | ||
202 | if (!ocm->c.virt) { | 199 | if (!ocm->c.virt) { |
203 | printk(KERN_ERR | 200 | printk(KERN_ERR |
diff --git a/arch/powerpc/platforms/82xx/Kconfig b/arch/powerpc/platforms/82xx/Kconfig index 6e04099361b9..1947a88bc69f 100644 --- a/arch/powerpc/platforms/82xx/Kconfig +++ b/arch/powerpc/platforms/82xx/Kconfig | |||
@@ -51,7 +51,6 @@ endif | |||
51 | 51 | ||
52 | config PQ2ADS | 52 | config PQ2ADS |
53 | bool | 53 | bool |
54 | default n | ||
55 | 54 | ||
56 | config 8260 | 55 | config 8260 |
57 | bool | 56 | bool |
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c index 7e966f4cf19a..fff72425727a 100644 --- a/arch/powerpc/platforms/85xx/smp.c +++ b/arch/powerpc/platforms/85xx/smp.c | |||
@@ -216,8 +216,8 @@ static int smp_85xx_start_cpu(int cpu) | |||
216 | 216 | ||
217 | /* Map the spin table */ | 217 | /* Map the spin table */ |
218 | if (ioremappable) | 218 | if (ioremappable) |
219 | spin_table = ioremap_prot(*cpu_rel_addr, | 219 | spin_table = ioremap_coherent(*cpu_rel_addr, |
220 | sizeof(struct epapr_spin_table), _PAGE_COHERENT); | 220 | sizeof(struct epapr_spin_table)); |
221 | else | 221 | else |
222 | spin_table = phys_to_virt(*cpu_rel_addr); | 222 | spin_table = phys_to_virt(*cpu_rel_addr); |
223 | 223 | ||
diff --git a/arch/powerpc/platforms/8xx/machine_check.c b/arch/powerpc/platforms/8xx/machine_check.c index 402016705a39..9944fc303df0 100644 --- a/arch/powerpc/platforms/8xx/machine_check.c +++ b/arch/powerpc/platforms/8xx/machine_check.c | |||
@@ -18,9 +18,9 @@ int machine_check_8xx(struct pt_regs *regs) | |||
18 | pr_err("Machine check in kernel mode.\n"); | 18 | pr_err("Machine check in kernel mode.\n"); |
19 | pr_err("Caused by (from SRR1=%lx): ", reason); | 19 | pr_err("Caused by (from SRR1=%lx): ", reason); |
20 | if (reason & 0x40000000) | 20 | if (reason & 0x40000000) |
21 | pr_err("Fetch error at address %lx\n", regs->nip); | 21 | pr_cont("Fetch error at address %lx\n", regs->nip); |
22 | else | 22 | else |
23 | pr_err("Data access error at address %lx\n", regs->dar); | 23 | pr_cont("Data access error at address %lx\n", regs->dar); |
24 | 24 | ||
25 | #ifdef CONFIG_PCI | 25 | #ifdef CONFIG_PCI |
26 | /* the qspan pci read routines can cause machine checks -- Cort | 26 | /* the qspan pci read routines can cause machine checks -- Cort |
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig index 14ef17e10ec9..260a56b7602d 100644 --- a/arch/powerpc/platforms/Kconfig +++ b/arch/powerpc/platforms/Kconfig | |||
@@ -23,7 +23,6 @@ source "arch/powerpc/platforms/amigaone/Kconfig" | |||
23 | 23 | ||
24 | config KVM_GUEST | 24 | config KVM_GUEST |
25 | bool "KVM Guest support" | 25 | bool "KVM Guest support" |
26 | default n | ||
27 | select EPAPR_PARAVIRT | 26 | select EPAPR_PARAVIRT |
28 | ---help--- | 27 | ---help--- |
29 | This option enables various optimizations for running under the KVM | 28 | This option enables various optimizations for running under the KVM |
@@ -34,7 +33,6 @@ config KVM_GUEST | |||
34 | 33 | ||
35 | config EPAPR_PARAVIRT | 34 | config EPAPR_PARAVIRT |
36 | bool "ePAPR para-virtualization support" | 35 | bool "ePAPR para-virtualization support" |
37 | default n | ||
38 | help | 36 | help |
39 | Enables ePAPR para-virtualization support for guests. | 37 | Enables ePAPR para-virtualization support for guests. |
40 | 38 | ||
@@ -74,7 +72,6 @@ config PPC_DT_CPU_FTRS | |||
74 | config UDBG_RTAS_CONSOLE | 72 | config UDBG_RTAS_CONSOLE |
75 | bool "RTAS based debug console" | 73 | bool "RTAS based debug console" |
76 | depends on PPC_RTAS | 74 | depends on PPC_RTAS |
77 | default n | ||
78 | 75 | ||
79 | config PPC_SMP_MUXED_IPI | 76 | config PPC_SMP_MUXED_IPI |
80 | bool | 77 | bool |
@@ -86,16 +83,13 @@ config PPC_SMP_MUXED_IPI | |||
86 | 83 | ||
87 | config IPIC | 84 | config IPIC |
88 | bool | 85 | bool |
89 | default n | ||
90 | 86 | ||
91 | config MPIC | 87 | config MPIC |
92 | bool | 88 | bool |
93 | default n | ||
94 | 89 | ||
95 | config MPIC_TIMER | 90 | config MPIC_TIMER |
96 | bool "MPIC Global Timer" | 91 | bool "MPIC Global Timer" |
97 | depends on MPIC && FSL_SOC | 92 | depends on MPIC && FSL_SOC |
98 | default n | ||
99 | help | 93 | help |
100 | The MPIC global timer is a hardware timer inside the | 94 | The MPIC global timer is a hardware timer inside the |
101 | Freescale PIC complying with OpenPIC standard. When the | 95 | Freescale PIC complying with OpenPIC standard. When the |
@@ -107,7 +101,6 @@ config MPIC_TIMER | |||
107 | config FSL_MPIC_TIMER_WAKEUP | 101 | config FSL_MPIC_TIMER_WAKEUP |
108 | tristate "Freescale MPIC global timer wakeup driver" | 102 | tristate "Freescale MPIC global timer wakeup driver" |
109 | depends on FSL_SOC && MPIC_TIMER && PM | 103 | depends on FSL_SOC && MPIC_TIMER && PM |
110 | default n | ||
111 | help | 104 | help |
112 | The driver provides a way to wake up the system by MPIC | 105 | The driver provides a way to wake up the system by MPIC |
113 | timer. | 106 | timer. |
@@ -115,43 +108,35 @@ config FSL_MPIC_TIMER_WAKEUP | |||
115 | 108 | ||
116 | config PPC_EPAPR_HV_PIC | 109 | config PPC_EPAPR_HV_PIC |
117 | bool | 110 | bool |
118 | default n | ||
119 | select EPAPR_PARAVIRT | 111 | select EPAPR_PARAVIRT |
120 | 112 | ||
121 | config MPIC_WEIRD | 113 | config MPIC_WEIRD |
122 | bool | 114 | bool |
123 | default n | ||
124 | 115 | ||
125 | config MPIC_MSGR | 116 | config MPIC_MSGR |
126 | bool "MPIC message register support" | 117 | bool "MPIC message register support" |
127 | depends on MPIC | 118 | depends on MPIC |
128 | default n | ||
129 | help | 119 | help |
130 | Enables support for the MPIC message registers. These | 120 | Enables support for the MPIC message registers. These |
131 | registers are used for inter-processor communication. | 121 | registers are used for inter-processor communication. |
132 | 122 | ||
133 | config PPC_I8259 | 123 | config PPC_I8259 |
134 | bool | 124 | bool |
135 | default n | ||
136 | 125 | ||
137 | config U3_DART | 126 | config U3_DART |
138 | bool | 127 | bool |
139 | depends on PPC64 | 128 | depends on PPC64 |
140 | default n | ||
141 | 129 | ||
142 | config PPC_RTAS | 130 | config PPC_RTAS |
143 | bool | 131 | bool |
144 | default n | ||
145 | 132 | ||
146 | config RTAS_ERROR_LOGGING | 133 | config RTAS_ERROR_LOGGING |
147 | bool | 134 | bool |
148 | depends on PPC_RTAS | 135 | depends on PPC_RTAS |
149 | default n | ||
150 | 136 | ||
151 | config PPC_RTAS_DAEMON | 137 | config PPC_RTAS_DAEMON |
152 | bool | 138 | bool |
153 | depends on PPC_RTAS | 139 | depends on PPC_RTAS |
154 | default n | ||
155 | 140 | ||
156 | config RTAS_PROC | 141 | config RTAS_PROC |
157 | bool "Proc interface to RTAS" | 142 | bool "Proc interface to RTAS" |
@@ -164,11 +149,9 @@ config RTAS_FLASH | |||
164 | 149 | ||
165 | config MMIO_NVRAM | 150 | config MMIO_NVRAM |
166 | bool | 151 | bool |
167 | default n | ||
168 | 152 | ||
169 | config MPIC_U3_HT_IRQS | 153 | config MPIC_U3_HT_IRQS |
170 | bool | 154 | bool |
171 | default n | ||
172 | 155 | ||
173 | config MPIC_BROKEN_REGREAD | 156 | config MPIC_BROKEN_REGREAD |
174 | bool | 157 | bool |
@@ -187,15 +170,12 @@ config EEH | |||
187 | 170 | ||
188 | config PPC_MPC106 | 171 | config PPC_MPC106 |
189 | bool | 172 | bool |
190 | default n | ||
191 | 173 | ||
192 | config PPC_970_NAP | 174 | config PPC_970_NAP |
193 | bool | 175 | bool |
194 | default n | ||
195 | 176 | ||
196 | config PPC_P7_NAP | 177 | config PPC_P7_NAP |
197 | bool | 178 | bool |
198 | default n | ||
199 | 179 | ||
200 | config PPC_INDIRECT_PIO | 180 | config PPC_INDIRECT_PIO |
201 | bool | 181 | bool |
@@ -295,7 +275,6 @@ config CPM2 | |||
295 | 275 | ||
296 | config FSL_ULI1575 | 276 | config FSL_ULI1575 |
297 | bool | 277 | bool |
298 | default n | ||
299 | select GENERIC_ISA_DMA | 278 | select GENERIC_ISA_DMA |
300 | help | 279 | help |
301 | Supports for the ULI1575 PCIe south bridge that exists on some | 280 | Supports for the ULI1575 PCIe south bridge that exists on some |
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype index 6c6a7c72cae4..f4e2c5729374 100644 --- a/arch/powerpc/platforms/Kconfig.cputype +++ b/arch/powerpc/platforms/Kconfig.cputype | |||
@@ -1,7 +1,6 @@ | |||
1 | # SPDX-License-Identifier: GPL-2.0 | 1 | # SPDX-License-Identifier: GPL-2.0 |
2 | config PPC64 | 2 | config PPC64 |
3 | bool "64-bit kernel" | 3 | bool "64-bit kernel" |
4 | default n | ||
5 | select ZLIB_DEFLATE | 4 | select ZLIB_DEFLATE |
6 | help | 5 | help |
7 | This option selects whether a 32-bit or a 64-bit kernel | 6 | This option selects whether a 32-bit or a 64-bit kernel |
@@ -72,6 +71,7 @@ config PPC_BOOK3S_64 | |||
72 | select PPC_HAVE_PMU_SUPPORT | 71 | select PPC_HAVE_PMU_SUPPORT |
73 | select SYS_SUPPORTS_HUGETLBFS | 72 | select SYS_SUPPORTS_HUGETLBFS |
74 | select HAVE_ARCH_TRANSPARENT_HUGEPAGE | 73 | select HAVE_ARCH_TRANSPARENT_HUGEPAGE |
74 | select ARCH_ENABLE_THP_MIGRATION if TRANSPARENT_HUGEPAGE | ||
75 | select ARCH_SUPPORTS_NUMA_BALANCING | 75 | select ARCH_SUPPORTS_NUMA_BALANCING |
76 | select IRQ_WORK | 76 | select IRQ_WORK |
77 | 77 | ||
@@ -368,7 +368,6 @@ config PPC_MM_SLICES | |||
368 | bool | 368 | bool |
369 | default y if PPC_BOOK3S_64 | 369 | default y if PPC_BOOK3S_64 |
370 | default y if PPC_8xx && HUGETLB_PAGE | 370 | default y if PPC_8xx && HUGETLB_PAGE |
371 | default n | ||
372 | 371 | ||
373 | config PPC_HAVE_PMU_SUPPORT | 372 | config PPC_HAVE_PMU_SUPPORT |
374 | bool | 373 | bool |
@@ -382,7 +381,6 @@ config PPC_PERF_CTRS | |||
382 | config FORCE_SMP | 381 | config FORCE_SMP |
383 | # Allow platforms to force SMP=y by selecting this | 382 | # Allow platforms to force SMP=y by selecting this |
384 | bool | 383 | bool |
385 | default n | ||
386 | select SMP | 384 | select SMP |
387 | 385 | ||
388 | config SMP | 386 | config SMP |
@@ -423,7 +421,6 @@ config CHECK_CACHE_COHERENCY | |||
423 | 421 | ||
424 | config PPC_DOORBELL | 422 | config PPC_DOORBELL |
425 | bool | 423 | bool |
426 | default n | ||
427 | 424 | ||
428 | endmenu | 425 | endmenu |
429 | 426 | ||
diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile index e46bb7ea710f..143d4417f6cc 100644 --- a/arch/powerpc/platforms/Makefile +++ b/arch/powerpc/platforms/Makefile | |||
@@ -1,7 +1,5 @@ | |||
1 | # SPDX-License-Identifier: GPL-2.0 | 1 | # SPDX-License-Identifier: GPL-2.0 |
2 | 2 | ||
3 | subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror | ||
4 | |||
5 | obj-$(CONFIG_FSL_ULI1575) += fsl_uli1575.o | 3 | obj-$(CONFIG_FSL_ULI1575) += fsl_uli1575.o |
6 | 4 | ||
7 | obj-$(CONFIG_PPC_PMAC) += powermac/ | 5 | obj-$(CONFIG_PPC_PMAC) += powermac/ |
diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig index 9f5958f16923..4b2f114f3116 100644 --- a/arch/powerpc/platforms/cell/Kconfig +++ b/arch/powerpc/platforms/cell/Kconfig | |||
@@ -1,7 +1,6 @@ | |||
1 | # SPDX-License-Identifier: GPL-2.0 | 1 | # SPDX-License-Identifier: GPL-2.0 |
2 | config PPC_CELL | 2 | config PPC_CELL |
3 | bool | 3 | bool |
4 | default n | ||
5 | 4 | ||
6 | config PPC_CELL_COMMON | 5 | config PPC_CELL_COMMON |
7 | bool | 6 | bool |
@@ -22,7 +21,6 @@ config PPC_CELL_NATIVE | |||
22 | select IBM_EMAC_RGMII if IBM_EMAC | 21 | select IBM_EMAC_RGMII if IBM_EMAC |
23 | select IBM_EMAC_ZMII if IBM_EMAC #test only | 22 | select IBM_EMAC_ZMII if IBM_EMAC #test only |
24 | select IBM_EMAC_TAH if IBM_EMAC #test only | 23 | select IBM_EMAC_TAH if IBM_EMAC #test only |
25 | default n | ||
26 | 24 | ||
27 | config PPC_IBM_CELL_BLADE | 25 | config PPC_IBM_CELL_BLADE |
28 | bool "IBM Cell Blade" | 26 | bool "IBM Cell Blade" |
@@ -54,7 +52,6 @@ config SPU_FS | |||
54 | 52 | ||
55 | config SPU_BASE | 53 | config SPU_BASE |
56 | bool | 54 | bool |
57 | default n | ||
58 | select PPC_COPRO_BASE | 55 | select PPC_COPRO_BASE |
59 | 56 | ||
60 | config CBE_RAS | 57 | config CBE_RAS |
diff --git a/arch/powerpc/platforms/cell/spu_manage.c b/arch/powerpc/platforms/cell/spu_manage.c index 5c409c98cca8..f7e36373f6e0 100644 --- a/arch/powerpc/platforms/cell/spu_manage.c +++ b/arch/powerpc/platforms/cell/spu_manage.c | |||
@@ -180,35 +180,22 @@ out: | |||
180 | 180 | ||
181 | static int __init spu_map_interrupts(struct spu *spu, struct device_node *np) | 181 | static int __init spu_map_interrupts(struct spu *spu, struct device_node *np) |
182 | { | 182 | { |
183 | struct of_phandle_args oirq; | ||
184 | int ret; | ||
185 | int i; | 183 | int i; |
186 | 184 | ||
187 | for (i=0; i < 3; i++) { | 185 | for (i=0; i < 3; i++) { |
188 | ret = of_irq_parse_one(np, i, &oirq); | 186 | spu->irqs[i] = irq_of_parse_and_map(np, i); |
189 | if (ret) { | 187 | if (!spu->irqs[i]) |
190 | pr_debug("spu_new: failed to get irq %d\n", i); | ||
191 | goto err; | ||
192 | } | ||
193 | ret = -EINVAL; | ||
194 | pr_debug(" irq %d no 0x%x on %pOF\n", i, oirq.args[0], | ||
195 | oirq.np); | ||
196 | spu->irqs[i] = irq_create_of_mapping(&oirq); | ||
197 | if (!spu->irqs[i]) { | ||
198 | pr_debug("spu_new: failed to map it !\n"); | ||
199 | goto err; | 188 | goto err; |
200 | } | ||
201 | } | 189 | } |
202 | return 0; | 190 | return 0; |
203 | 191 | ||
204 | err: | 192 | err: |
205 | pr_debug("failed to map irq %x for spu %s\n", *oirq.args, | 193 | pr_debug("failed to map irq %x for spu %s\n", i, spu->name); |
206 | spu->name); | ||
207 | for (; i >= 0; i--) { | 194 | for (; i >= 0; i--) { |
208 | if (spu->irqs[i]) | 195 | if (spu->irqs[i]) |
209 | irq_dispose_mapping(spu->irqs[i]); | 196 | irq_dispose_mapping(spu->irqs[i]); |
210 | } | 197 | } |
211 | return ret; | 198 | return -EINVAL; |
212 | } | 199 | } |
213 | 200 | ||
214 | static int spu_map_resource(struct spu *spu, int nr, | 201 | static int spu_map_resource(struct spu *spu, int nr, |
@@ -295,8 +282,8 @@ static int __init of_enumerate_spus(int (*fn)(void *data)) | |||
295 | for_each_node_by_type(node, "spe") { | 282 | for_each_node_by_type(node, "spe") { |
296 | ret = fn(node); | 283 | ret = fn(node); |
297 | if (ret) { | 284 | if (ret) { |
298 | printk(KERN_WARNING "%s: Error initializing %s\n", | 285 | printk(KERN_WARNING "%s: Error initializing %pOFn\n", |
299 | __func__, node->name); | 286 | __func__, node); |
300 | of_node_put(node); | 287 | of_node_put(node); |
301 | break; | 288 | break; |
302 | } | 289 | } |
diff --git a/arch/powerpc/platforms/embedded6xx/wii.c b/arch/powerpc/platforms/embedded6xx/wii.c index 403523c061ba..ecf703ee3a76 100644 --- a/arch/powerpc/platforms/embedded6xx/wii.c +++ b/arch/powerpc/platforms/embedded6xx/wii.c | |||
@@ -112,7 +112,7 @@ static void __iomem *wii_ioremap_hw_regs(char *name, char *compatible) | |||
112 | } | 112 | } |
113 | error = of_address_to_resource(np, 0, &res); | 113 | error = of_address_to_resource(np, 0, &res); |
114 | if (error) { | 114 | if (error) { |
115 | pr_err("no valid reg found for %s\n", np->name); | 115 | pr_err("no valid reg found for %pOFn\n", np); |
116 | goto out_put; | 116 | goto out_put; |
117 | } | 117 | } |
118 | 118 | ||
diff --git a/arch/powerpc/platforms/maple/Kconfig b/arch/powerpc/platforms/maple/Kconfig index 376d0be36b66..2601fac50354 100644 --- a/arch/powerpc/platforms/maple/Kconfig +++ b/arch/powerpc/platforms/maple/Kconfig | |||
@@ -13,7 +13,6 @@ config PPC_MAPLE | |||
13 | select PPC_RTAS | 13 | select PPC_RTAS |
14 | select MMIO_NVRAM | 14 | select MMIO_NVRAM |
15 | select ATA_NONSTANDARD if ATA | 15 | select ATA_NONSTANDARD if ATA |
16 | default n | ||
17 | help | 16 | help |
18 | This option enables support for the Maple 970FX Evaluation Board. | 17 | This option enables support for the Maple 970FX Evaluation Board. |
19 | For more information, refer to <http://www.970eval.com> | 18 | For more information, refer to <http://www.970eval.com> |
diff --git a/arch/powerpc/platforms/pasemi/Kconfig b/arch/powerpc/platforms/pasemi/Kconfig index d458a791d35b..98e3bc22bebc 100644 --- a/arch/powerpc/platforms/pasemi/Kconfig +++ b/arch/powerpc/platforms/pasemi/Kconfig | |||
@@ -2,7 +2,6 @@ | |||
2 | config PPC_PASEMI | 2 | config PPC_PASEMI |
3 | depends on PPC64 && PPC_BOOK3S && CPU_BIG_ENDIAN | 3 | depends on PPC64 && PPC_BOOK3S && CPU_BIG_ENDIAN |
4 | bool "PA Semi SoC-based platforms" | 4 | bool "PA Semi SoC-based platforms" |
5 | default n | ||
6 | select MPIC | 5 | select MPIC |
7 | select PCI | 6 | select PCI |
8 | select PPC_UDBG_16550 | 7 | select PPC_UDBG_16550 |
diff --git a/arch/powerpc/platforms/pasemi/dma_lib.c b/arch/powerpc/platforms/pasemi/dma_lib.c index c80f72c370ae..53384eb42a76 100644 --- a/arch/powerpc/platforms/pasemi/dma_lib.c +++ b/arch/powerpc/platforms/pasemi/dma_lib.c | |||
@@ -576,7 +576,7 @@ int pasemi_dma_init(void) | |||
576 | res.start = 0xfd800000; | 576 | res.start = 0xfd800000; |
577 | res.end = res.start + 0x1000; | 577 | res.end = res.start + 0x1000; |
578 | } | 578 | } |
579 | dma_status = __ioremap(res.start, resource_size(&res), 0); | 579 | dma_status = ioremap_cache(res.start, resource_size(&res)); |
580 | pci_dev_put(iob_pdev); | 580 | pci_dev_put(iob_pdev); |
581 | 581 | ||
582 | for (i = 0; i < MAX_TXCH; i++) | 582 | for (i = 0; i < MAX_TXCH; i++) |
diff --git a/arch/powerpc/platforms/powermac/Makefile b/arch/powerpc/platforms/powermac/Makefile index f2839eed0f89..923bfb340433 100644 --- a/arch/powerpc/platforms/powermac/Makefile +++ b/arch/powerpc/platforms/powermac/Makefile | |||
@@ -1,9 +1,10 @@ | |||
1 | # SPDX-License-Identifier: GPL-2.0 | 1 | # SPDX-License-Identifier: GPL-2.0 |
2 | CFLAGS_bootx_init.o += -fPIC | 2 | CFLAGS_bootx_init.o += -fPIC |
3 | CFLAGS_bootx_init.o += $(call cc-option, -fno-stack-protector) | ||
3 | 4 | ||
4 | ifdef CONFIG_FUNCTION_TRACER | 5 | ifdef CONFIG_FUNCTION_TRACER |
5 | # Do not trace early boot code | 6 | # Do not trace early boot code |
6 | CFLAGS_REMOVE_bootx_init.o = -mno-sched-epilog $(CC_FLAGS_FTRACE) | 7 | CFLAGS_REMOVE_bootx_init.o = $(CC_FLAGS_FTRACE) |
7 | endif | 8 | endif |
8 | 9 | ||
9 | obj-y += pic.o setup.o time.o feature.o pci.o \ | 10 | obj-y += pic.o setup.o time.o feature.o pci.o \ |
diff --git a/arch/powerpc/platforms/powermac/time.c b/arch/powerpc/platforms/powermac/time.c index f92c1918fb56..f157e3d071f2 100644 --- a/arch/powerpc/platforms/powermac/time.c +++ b/arch/powerpc/platforms/powermac/time.c | |||
@@ -45,13 +45,6 @@ | |||
45 | #endif | 45 | #endif |
46 | 46 | ||
47 | /* | 47 | /* |
48 | * Offset between Unix time (1970-based) and Mac time (1904-based). Cuda and PMU | ||
49 | * times wrap in 2040. If we need to handle later times, the read_time functions | ||
50 | * need to be changed to interpret wrapped times as post-2040. | ||
51 | */ | ||
52 | #define RTC_OFFSET 2082844800 | ||
53 | |||
54 | /* | ||
55 | * Calibrate the decrementer frequency with the VIA timer 1. | 48 | * Calibrate the decrementer frequency with the VIA timer 1. |
56 | */ | 49 | */ |
57 | #define VIA_TIMER_FREQ_6 4700000 /* time 1 frequency * 6 */ | 50 | #define VIA_TIMER_FREQ_6 4700000 /* time 1 frequency * 6 */ |
@@ -90,98 +83,6 @@ long __init pmac_time_init(void) | |||
90 | return delta; | 83 | return delta; |
91 | } | 84 | } |
92 | 85 | ||
93 | #ifdef CONFIG_ADB_CUDA | ||
94 | static time64_t cuda_get_time(void) | ||
95 | { | ||
96 | struct adb_request req; | ||
97 | time64_t now; | ||
98 | |||
99 | if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME) < 0) | ||
100 | return 0; | ||
101 | while (!req.complete) | ||
102 | cuda_poll(); | ||
103 | if (req.reply_len != 7) | ||
104 | printk(KERN_ERR "cuda_get_time: got %d byte reply\n", | ||
105 | req.reply_len); | ||
106 | now = (u32)((req.reply[3] << 24) + (req.reply[4] << 16) + | ||
107 | (req.reply[5] << 8) + req.reply[6]); | ||
108 | /* it's either after year 2040, or the RTC has gone backwards */ | ||
109 | WARN_ON(now < RTC_OFFSET); | ||
110 | |||
111 | return now - RTC_OFFSET; | ||
112 | } | ||
113 | |||
114 | #define cuda_get_rtc_time(tm) rtc_time64_to_tm(cuda_get_time(), (tm)) | ||
115 | |||
116 | static int cuda_set_rtc_time(struct rtc_time *tm) | ||
117 | { | ||
118 | u32 nowtime; | ||
119 | struct adb_request req; | ||
120 | |||
121 | nowtime = lower_32_bits(rtc_tm_to_time64(tm) + RTC_OFFSET); | ||
122 | if (cuda_request(&req, NULL, 6, CUDA_PACKET, CUDA_SET_TIME, | ||
123 | nowtime >> 24, nowtime >> 16, nowtime >> 8, | ||
124 | nowtime) < 0) | ||
125 | return -ENXIO; | ||
126 | while (!req.complete) | ||
127 | cuda_poll(); | ||
128 | if ((req.reply_len != 3) && (req.reply_len != 7)) | ||
129 | printk(KERN_ERR "cuda_set_rtc_time: got %d byte reply\n", | ||
130 | req.reply_len); | ||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | #else | ||
135 | #define cuda_get_time() 0 | ||
136 | #define cuda_get_rtc_time(tm) | ||
137 | #define cuda_set_rtc_time(tm) 0 | ||
138 | #endif | ||
139 | |||
140 | #ifdef CONFIG_ADB_PMU | ||
141 | static time64_t pmu_get_time(void) | ||
142 | { | ||
143 | struct adb_request req; | ||
144 | time64_t now; | ||
145 | |||
146 | if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0) | ||
147 | return 0; | ||
148 | pmu_wait_complete(&req); | ||
149 | if (req.reply_len != 4) | ||
150 | printk(KERN_ERR "pmu_get_time: got %d byte reply from PMU\n", | ||
151 | req.reply_len); | ||
152 | now = (u32)((req.reply[0] << 24) + (req.reply[1] << 16) + | ||
153 | (req.reply[2] << 8) + req.reply[3]); | ||
154 | |||
155 | /* it's either after year 2040, or the RTC has gone backwards */ | ||
156 | WARN_ON(now < RTC_OFFSET); | ||
157 | |||
158 | return now - RTC_OFFSET; | ||
159 | } | ||
160 | |||
161 | #define pmu_get_rtc_time(tm) rtc_time64_to_tm(pmu_get_time(), (tm)) | ||
162 | |||
163 | static int pmu_set_rtc_time(struct rtc_time *tm) | ||
164 | { | ||
165 | u32 nowtime; | ||
166 | struct adb_request req; | ||
167 | |||
168 | nowtime = lower_32_bits(rtc_tm_to_time64(tm) + RTC_OFFSET); | ||
169 | if (pmu_request(&req, NULL, 5, PMU_SET_RTC, nowtime >> 24, | ||
170 | nowtime >> 16, nowtime >> 8, nowtime) < 0) | ||
171 | return -ENXIO; | ||
172 | pmu_wait_complete(&req); | ||
173 | if (req.reply_len != 0) | ||
174 | printk(KERN_ERR "pmu_set_rtc_time: %d byte reply from PMU\n", | ||
175 | req.reply_len); | ||
176 | return 0; | ||
177 | } | ||
178 | |||
179 | #else | ||
180 | #define pmu_get_time() 0 | ||
181 | #define pmu_get_rtc_time(tm) | ||
182 | #define pmu_set_rtc_time(tm) 0 | ||
183 | #endif | ||
184 | |||
185 | #ifdef CONFIG_PMAC_SMU | 86 | #ifdef CONFIG_PMAC_SMU |
186 | static time64_t smu_get_time(void) | 87 | static time64_t smu_get_time(void) |
187 | { | 88 | { |
@@ -191,11 +92,6 @@ static time64_t smu_get_time(void) | |||
191 | return 0; | 92 | return 0; |
192 | return rtc_tm_to_time64(&tm); | 93 | return rtc_tm_to_time64(&tm); |
193 | } | 94 | } |
194 | |||
195 | #else | ||
196 | #define smu_get_time() 0 | ||
197 | #define smu_get_rtc_time(tm, spin) | ||
198 | #define smu_set_rtc_time(tm, spin) 0 | ||
199 | #endif | 95 | #endif |
200 | 96 | ||
201 | /* Can't be __init, it's called when suspending and resuming */ | 97 | /* Can't be __init, it's called when suspending and resuming */ |
@@ -203,12 +99,18 @@ time64_t pmac_get_boot_time(void) | |||
203 | { | 99 | { |
204 | /* Get the time from the RTC, used only at boot time */ | 100 | /* Get the time from the RTC, used only at boot time */ |
205 | switch (sys_ctrler) { | 101 | switch (sys_ctrler) { |
102 | #ifdef CONFIG_ADB_CUDA | ||
206 | case SYS_CTRLER_CUDA: | 103 | case SYS_CTRLER_CUDA: |
207 | return cuda_get_time(); | 104 | return cuda_get_time(); |
105 | #endif | ||
106 | #ifdef CONFIG_ADB_PMU | ||
208 | case SYS_CTRLER_PMU: | 107 | case SYS_CTRLER_PMU: |
209 | return pmu_get_time(); | 108 | return pmu_get_time(); |
109 | #endif | ||
110 | #ifdef CONFIG_PMAC_SMU | ||
210 | case SYS_CTRLER_SMU: | 111 | case SYS_CTRLER_SMU: |
211 | return smu_get_time(); | 112 | return smu_get_time(); |
113 | #endif | ||
212 | default: | 114 | default: |
213 | return 0; | 115 | return 0; |
214 | } | 116 | } |
@@ -218,15 +120,21 @@ void pmac_get_rtc_time(struct rtc_time *tm) | |||
218 | { | 120 | { |
219 | /* Get the time from the RTC, used only at boot time */ | 121 | /* Get the time from the RTC, used only at boot time */ |
220 | switch (sys_ctrler) { | 122 | switch (sys_ctrler) { |
123 | #ifdef CONFIG_ADB_CUDA | ||
221 | case SYS_CTRLER_CUDA: | 124 | case SYS_CTRLER_CUDA: |
222 | cuda_get_rtc_time(tm); | 125 | rtc_time64_to_tm(cuda_get_time(), tm); |
223 | break; | 126 | break; |
127 | #endif | ||
128 | #ifdef CONFIG_ADB_PMU | ||
224 | case SYS_CTRLER_PMU: | 129 | case SYS_CTRLER_PMU: |
225 | pmu_get_rtc_time(tm); | 130 | rtc_time64_to_tm(pmu_get_time(), tm); |
226 | break; | 131 | break; |
132 | #endif | ||
133 | #ifdef CONFIG_PMAC_SMU | ||
227 | case SYS_CTRLER_SMU: | 134 | case SYS_CTRLER_SMU: |
228 | smu_get_rtc_time(tm, 1); | 135 | smu_get_rtc_time(tm, 1); |
229 | break; | 136 | break; |
137 | #endif | ||
230 | default: | 138 | default: |
231 | ; | 139 | ; |
232 | } | 140 | } |
@@ -235,12 +143,18 @@ void pmac_get_rtc_time(struct rtc_time *tm) | |||
235 | int pmac_set_rtc_time(struct rtc_time *tm) | 143 | int pmac_set_rtc_time(struct rtc_time *tm) |
236 | { | 144 | { |
237 | switch (sys_ctrler) { | 145 | switch (sys_ctrler) { |
146 | #ifdef CONFIG_ADB_CUDA | ||
238 | case SYS_CTRLER_CUDA: | 147 | case SYS_CTRLER_CUDA: |
239 | return cuda_set_rtc_time(tm); | 148 | return cuda_set_rtc_time(tm); |
149 | #endif | ||
150 | #ifdef CONFIG_ADB_PMU | ||
240 | case SYS_CTRLER_PMU: | 151 | case SYS_CTRLER_PMU: |
241 | return pmu_set_rtc_time(tm); | 152 | return pmu_set_rtc_time(tm); |
153 | #endif | ||
154 | #ifdef CONFIG_PMAC_SMU | ||
242 | case SYS_CTRLER_SMU: | 155 | case SYS_CTRLER_SMU: |
243 | return smu_set_rtc_time(tm, 1); | 156 | return smu_set_rtc_time(tm, 1); |
157 | #endif | ||
244 | default: | 158 | default: |
245 | return -ENODEV; | 159 | return -ENODEV; |
246 | } | 160 | } |
diff --git a/arch/powerpc/platforms/powernv/Kconfig b/arch/powerpc/platforms/powernv/Kconfig index f8dc98d3dc01..99083fe992d5 100644 --- a/arch/powerpc/platforms/powernv/Kconfig +++ b/arch/powerpc/platforms/powernv/Kconfig | |||
@@ -15,11 +15,6 @@ config PPC_POWERNV | |||
15 | select PPC_SCOM | 15 | select PPC_SCOM |
16 | select ARCH_RANDOM | 16 | select ARCH_RANDOM |
17 | select CPU_FREQ | 17 | select CPU_FREQ |
18 | select CPU_FREQ_GOV_PERFORMANCE | ||
19 | select CPU_FREQ_GOV_POWERSAVE | ||
20 | select CPU_FREQ_GOV_USERSPACE | ||
21 | select CPU_FREQ_GOV_ONDEMAND | ||
22 | select CPU_FREQ_GOV_CONSERVATIVE | ||
23 | select PPC_DOORBELL | 18 | select PPC_DOORBELL |
24 | select MMU_NOTIFIER | 19 | select MMU_NOTIFIER |
25 | select FORCE_SMP | 20 | select FORCE_SMP |
@@ -35,7 +30,6 @@ config OPAL_PRD | |||
35 | config PPC_MEMTRACE | 30 | config PPC_MEMTRACE |
36 | bool "Enable removal of RAM from kernel mappings for tracing" | 31 | bool "Enable removal of RAM from kernel mappings for tracing" |
37 | depends on PPC_POWERNV && MEMORY_HOTREMOVE | 32 | depends on PPC_POWERNV && MEMORY_HOTREMOVE |
38 | default n | ||
39 | help | 33 | help |
40 | Enabling this option allows for the removal of memory (RAM) | 34 | Enabling this option allows for the removal of memory (RAM) |
41 | from the kernel mappings to be used for hardware tracing. | 35 | from the kernel mappings to be used for hardware tracing. |
diff --git a/arch/powerpc/platforms/powernv/eeh-powernv.c b/arch/powerpc/platforms/powernv/eeh-powernv.c index 3c1beae29f2d..abc0be7507c8 100644 --- a/arch/powerpc/platforms/powernv/eeh-powernv.c +++ b/arch/powerpc/platforms/powernv/eeh-powernv.c | |||
@@ -223,14 +223,6 @@ int pnv_eeh_post_init(void) | |||
223 | eeh_probe_devices(); | 223 | eeh_probe_devices(); |
224 | eeh_addr_cache_build(); | 224 | eeh_addr_cache_build(); |
225 | 225 | ||
226 | if (eeh_has_flag(EEH_POSTPONED_PROBE)) { | ||
227 | eeh_clear_flag(EEH_POSTPONED_PROBE); | ||
228 | if (eeh_enabled()) | ||
229 | pr_info("EEH: PCI Enhanced I/O Error Handling Enabled\n"); | ||
230 | else | ||
231 | pr_info("EEH: No capable adapters found\n"); | ||
232 | } | ||
233 | |||
234 | /* Register OPAL event notifier */ | 226 | /* Register OPAL event notifier */ |
235 | eeh_event_irq = opal_event_request(ilog2(OPAL_EVENT_PCI_ERROR)); | 227 | eeh_event_irq = opal_event_request(ilog2(OPAL_EVENT_PCI_ERROR)); |
236 | if (eeh_event_irq < 0) { | 228 | if (eeh_event_irq < 0) { |
@@ -391,12 +383,6 @@ static void *pnv_eeh_probe(struct pci_dn *pdn, void *data) | |||
391 | if ((pdn->class_code >> 8) == PCI_CLASS_BRIDGE_ISA) | 383 | if ((pdn->class_code >> 8) == PCI_CLASS_BRIDGE_ISA) |
392 | return NULL; | 384 | return NULL; |
393 | 385 | ||
394 | /* Skip if we haven't probed yet */ | ||
395 | if (phb->ioda.pe_rmap[config_addr] == IODA_INVALID_PE) { | ||
396 | eeh_add_flag(EEH_POSTPONED_PROBE); | ||
397 | return NULL; | ||
398 | } | ||
399 | |||
400 | /* Initialize eeh device */ | 386 | /* Initialize eeh device */ |
401 | edev->class_code = pdn->class_code; | 387 | edev->class_code = pdn->class_code; |
402 | edev->mode &= 0xFFFFFF00; | 388 | edev->mode &= 0xFFFFFF00; |
@@ -604,7 +590,7 @@ static int pnv_eeh_get_phb_state(struct eeh_pe *pe) | |||
604 | EEH_STATE_MMIO_ENABLED | | 590 | EEH_STATE_MMIO_ENABLED | |
605 | EEH_STATE_DMA_ENABLED); | 591 | EEH_STATE_DMA_ENABLED); |
606 | } else if (!(pe->state & EEH_PE_ISOLATED)) { | 592 | } else if (!(pe->state & EEH_PE_ISOLATED)) { |
607 | eeh_pe_state_mark(pe, EEH_PE_ISOLATED); | 593 | eeh_pe_mark_isolated(pe); |
608 | pnv_eeh_get_phb_diag(pe); | 594 | pnv_eeh_get_phb_diag(pe); |
609 | 595 | ||
610 | if (eeh_has_flag(EEH_EARLY_DUMP_LOG)) | 596 | if (eeh_has_flag(EEH_EARLY_DUMP_LOG)) |
@@ -706,7 +692,7 @@ static int pnv_eeh_get_pe_state(struct eeh_pe *pe) | |||
706 | if (phb->freeze_pe) | 692 | if (phb->freeze_pe) |
707 | phb->freeze_pe(phb, pe->addr); | 693 | phb->freeze_pe(phb, pe->addr); |
708 | 694 | ||
709 | eeh_pe_state_mark(pe, EEH_PE_ISOLATED); | 695 | eeh_pe_mark_isolated(pe); |
710 | pnv_eeh_get_phb_diag(pe); | 696 | pnv_eeh_get_phb_diag(pe); |
711 | 697 | ||
712 | if (eeh_has_flag(EEH_EARLY_DUMP_LOG)) | 698 | if (eeh_has_flag(EEH_EARLY_DUMP_LOG)) |
@@ -1054,7 +1040,7 @@ static int pnv_eeh_reset_vf_pe(struct eeh_pe *pe, int option) | |||
1054 | int ret; | 1040 | int ret; |
1055 | 1041 | ||
1056 | /* The VF PE should have only one child device */ | 1042 | /* The VF PE should have only one child device */ |
1057 | edev = list_first_entry_or_null(&pe->edevs, struct eeh_dev, list); | 1043 | edev = list_first_entry_or_null(&pe->edevs, struct eeh_dev, entry); |
1058 | pdn = eeh_dev_to_pdn(edev); | 1044 | pdn = eeh_dev_to_pdn(edev); |
1059 | if (!pdn) | 1045 | if (!pdn) |
1060 | return -ENXIO; | 1046 | return -ENXIO; |
@@ -1148,43 +1134,6 @@ static int pnv_eeh_reset(struct eeh_pe *pe, int option) | |||
1148 | } | 1134 | } |
1149 | 1135 | ||
1150 | /** | 1136 | /** |
1151 | * pnv_eeh_wait_state - Wait for PE state | ||
1152 | * @pe: EEH PE | ||
1153 | * @max_wait: maximal period in millisecond | ||
1154 | * | ||
1155 | * Wait for the state of associated PE. It might take some time | ||
1156 | * to retrieve the PE's state. | ||
1157 | */ | ||
1158 | static int pnv_eeh_wait_state(struct eeh_pe *pe, int max_wait) | ||
1159 | { | ||
1160 | int ret; | ||
1161 | int mwait; | ||
1162 | |||
1163 | while (1) { | ||
1164 | ret = pnv_eeh_get_state(pe, &mwait); | ||
1165 | |||
1166 | /* | ||
1167 | * If the PE's state is temporarily unavailable, | ||
1168 | * we have to wait for the specified time. Otherwise, | ||
1169 | * the PE's state will be returned immediately. | ||
1170 | */ | ||
1171 | if (ret != EEH_STATE_UNAVAILABLE) | ||
1172 | return ret; | ||
1173 | |||
1174 | if (max_wait <= 0) { | ||
1175 | pr_warn("%s: Timeout getting PE#%x's state (%d)\n", | ||
1176 | __func__, pe->addr, max_wait); | ||
1177 | return EEH_STATE_NOT_SUPPORT; | ||
1178 | } | ||
1179 | |||
1180 | max_wait -= mwait; | ||
1181 | msleep(mwait); | ||
1182 | } | ||
1183 | |||
1184 | return EEH_STATE_NOT_SUPPORT; | ||
1185 | } | ||
1186 | |||
1187 | /** | ||
1188 | * pnv_eeh_get_log - Retrieve error log | 1137 | * pnv_eeh_get_log - Retrieve error log |
1189 | * @pe: EEH PE | 1138 | * @pe: EEH PE |
1190 | * @severity: temporary or permanent error log | 1139 | * @severity: temporary or permanent error log |
@@ -1611,7 +1560,7 @@ static int pnv_eeh_next_error(struct eeh_pe **pe) | |||
1611 | if ((ret == EEH_NEXT_ERR_FROZEN_PE || | 1560 | if ((ret == EEH_NEXT_ERR_FROZEN_PE || |
1612 | ret == EEH_NEXT_ERR_FENCED_PHB) && | 1561 | ret == EEH_NEXT_ERR_FENCED_PHB) && |
1613 | !((*pe)->state & EEH_PE_ISOLATED)) { | 1562 | !((*pe)->state & EEH_PE_ISOLATED)) { |
1614 | eeh_pe_state_mark(*pe, EEH_PE_ISOLATED); | 1563 | eeh_pe_mark_isolated(*pe); |
1615 | pnv_eeh_get_phb_diag(*pe); | 1564 | pnv_eeh_get_phb_diag(*pe); |
1616 | 1565 | ||
1617 | if (eeh_has_flag(EEH_EARLY_DUMP_LOG)) | 1566 | if (eeh_has_flag(EEH_EARLY_DUMP_LOG)) |
@@ -1640,7 +1589,7 @@ static int pnv_eeh_next_error(struct eeh_pe **pe) | |||
1640 | } | 1589 | } |
1641 | 1590 | ||
1642 | /* We possibly migrate to another PE */ | 1591 | /* We possibly migrate to another PE */ |
1643 | eeh_pe_state_mark(*pe, EEH_PE_ISOLATED); | 1592 | eeh_pe_mark_isolated(*pe); |
1644 | } | 1593 | } |
1645 | 1594 | ||
1646 | /* | 1595 | /* |
@@ -1702,7 +1651,6 @@ static struct eeh_ops pnv_eeh_ops = { | |||
1702 | .get_pe_addr = pnv_eeh_get_pe_addr, | 1651 | .get_pe_addr = pnv_eeh_get_pe_addr, |
1703 | .get_state = pnv_eeh_get_state, | 1652 | .get_state = pnv_eeh_get_state, |
1704 | .reset = pnv_eeh_reset, | 1653 | .reset = pnv_eeh_reset, |
1705 | .wait_state = pnv_eeh_wait_state, | ||
1706 | .get_log = pnv_eeh_get_log, | 1654 | .get_log = pnv_eeh_get_log, |
1707 | .configure_bridge = pnv_eeh_configure_bridge, | 1655 | .configure_bridge = pnv_eeh_configure_bridge, |
1708 | .err_inject = pnv_eeh_err_inject, | 1656 | .err_inject = pnv_eeh_err_inject, |
diff --git a/arch/powerpc/platforms/powernv/memtrace.c b/arch/powerpc/platforms/powernv/memtrace.c index 51dc398ae3f7..a29fdf8a2e56 100644 --- a/arch/powerpc/platforms/powernv/memtrace.c +++ b/arch/powerpc/platforms/powernv/memtrace.c | |||
@@ -90,17 +90,15 @@ static bool memtrace_offline_pages(u32 nid, u64 start_pfn, u64 nr_pages) | |||
90 | walk_memory_range(start_pfn, end_pfn, (void *)MEM_OFFLINE, | 90 | walk_memory_range(start_pfn, end_pfn, (void *)MEM_OFFLINE, |
91 | change_memblock_state); | 91 | change_memblock_state); |
92 | 92 | ||
93 | lock_device_hotplug(); | ||
94 | remove_memory(nid, start_pfn << PAGE_SHIFT, nr_pages << PAGE_SHIFT); | ||
95 | unlock_device_hotplug(); | ||
96 | 93 | ||
97 | return true; | 94 | return true; |
98 | } | 95 | } |
99 | 96 | ||
100 | static u64 memtrace_alloc_node(u32 nid, u64 size) | 97 | static u64 memtrace_alloc_node(u32 nid, u64 size) |
101 | { | 98 | { |
102 | u64 start_pfn, end_pfn, nr_pages; | 99 | u64 start_pfn, end_pfn, nr_pages, pfn; |
103 | u64 base_pfn; | 100 | u64 base_pfn; |
101 | u64 bytes = memory_block_size_bytes(); | ||
104 | 102 | ||
105 | if (!node_spanned_pages(nid)) | 103 | if (!node_spanned_pages(nid)) |
106 | return 0; | 104 | return 0; |
@@ -113,8 +111,21 @@ static u64 memtrace_alloc_node(u32 nid, u64 size) | |||
113 | end_pfn = round_down(end_pfn - nr_pages, nr_pages); | 111 | end_pfn = round_down(end_pfn - nr_pages, nr_pages); |
114 | 112 | ||
115 | for (base_pfn = end_pfn; base_pfn > start_pfn; base_pfn -= nr_pages) { | 113 | for (base_pfn = end_pfn; base_pfn > start_pfn; base_pfn -= nr_pages) { |
116 | if (memtrace_offline_pages(nid, base_pfn, nr_pages) == true) | 114 | if (memtrace_offline_pages(nid, base_pfn, nr_pages) == true) { |
115 | /* | ||
116 | * Remove memory in memory block size chunks so that | ||
117 | * iomem resources are always split to the same size and | ||
118 | * we never try to remove memory that spans two iomem | ||
119 | * resources. | ||
120 | */ | ||
121 | lock_device_hotplug(); | ||
122 | end_pfn = base_pfn + nr_pages; | ||
123 | for (pfn = base_pfn; pfn < end_pfn; pfn += bytes>> PAGE_SHIFT) { | ||
124 | remove_memory(nid, pfn << PAGE_SHIFT, bytes); | ||
125 | } | ||
126 | unlock_device_hotplug(); | ||
117 | return base_pfn << PAGE_SHIFT; | 127 | return base_pfn << PAGE_SHIFT; |
128 | } | ||
118 | } | 129 | } |
119 | 130 | ||
120 | return 0; | 131 | return 0; |
diff --git a/arch/powerpc/platforms/powernv/npu-dma.c b/arch/powerpc/platforms/powernv/npu-dma.c index 8006c54a91e3..6f60e0931922 100644 --- a/arch/powerpc/platforms/powernv/npu-dma.c +++ b/arch/powerpc/platforms/powernv/npu-dma.c | |||
@@ -17,7 +17,7 @@ | |||
17 | #include <linux/pci.h> | 17 | #include <linux/pci.h> |
18 | #include <linux/memblock.h> | 18 | #include <linux/memblock.h> |
19 | #include <linux/iommu.h> | 19 | #include <linux/iommu.h> |
20 | #include <linux/debugfs.h> | 20 | #include <linux/sizes.h> |
21 | 21 | ||
22 | #include <asm/debugfs.h> | 22 | #include <asm/debugfs.h> |
23 | #include <asm/tlb.h> | 23 | #include <asm/tlb.h> |
@@ -42,14 +42,6 @@ | |||
42 | static DEFINE_SPINLOCK(npu_context_lock); | 42 | static DEFINE_SPINLOCK(npu_context_lock); |
43 | 43 | ||
44 | /* | 44 | /* |
45 | * When an address shootdown range exceeds this threshold we invalidate the | ||
46 | * entire TLB on the GPU for the given PID rather than each specific address in | ||
47 | * the range. | ||
48 | */ | ||
49 | static uint64_t atsd_threshold = 2 * 1024 * 1024; | ||
50 | static struct dentry *atsd_threshold_dentry; | ||
51 | |||
52 | /* | ||
53 | * Other types of TCE cache invalidation are not functional in the | 45 | * Other types of TCE cache invalidation are not functional in the |
54 | * hardware. | 46 | * hardware. |
55 | */ | 47 | */ |
@@ -454,79 +446,73 @@ static void put_mmio_atsd_reg(struct npu *npu, int reg) | |||
454 | } | 446 | } |
455 | 447 | ||
456 | /* MMIO ATSD register offsets */ | 448 | /* MMIO ATSD register offsets */ |
457 | #define XTS_ATSD_AVA 1 | 449 | #define XTS_ATSD_LAUNCH 0 |
458 | #define XTS_ATSD_STAT 2 | 450 | #define XTS_ATSD_AVA 1 |
459 | 451 | #define XTS_ATSD_STAT 2 | |
460 | static void mmio_launch_invalidate(struct mmio_atsd_reg *mmio_atsd_reg, | ||
461 | unsigned long launch, unsigned long va) | ||
462 | { | ||
463 | struct npu *npu = mmio_atsd_reg->npu; | ||
464 | int reg = mmio_atsd_reg->reg; | ||
465 | |||
466 | __raw_writeq_be(va, npu->mmio_atsd_regs[reg] + XTS_ATSD_AVA); | ||
467 | eieio(); | ||
468 | __raw_writeq_be(launch, npu->mmio_atsd_regs[reg]); | ||
469 | } | ||
470 | 452 | ||
471 | static void mmio_invalidate_pid(struct mmio_atsd_reg mmio_atsd_reg[NV_MAX_NPUS], | 453 | static unsigned long get_atsd_launch_val(unsigned long pid, unsigned long psize) |
472 | unsigned long pid, bool flush) | ||
473 | { | 454 | { |
474 | int i; | 455 | unsigned long launch = 0; |
475 | unsigned long launch; | ||
476 | |||
477 | for (i = 0; i <= max_npu2_index; i++) { | ||
478 | if (mmio_atsd_reg[i].reg < 0) | ||
479 | continue; | ||
480 | 456 | ||
481 | /* IS set to invalidate matching PID */ | 457 | if (psize == MMU_PAGE_COUNT) { |
482 | launch = PPC_BIT(12); | 458 | /* IS set to invalidate entire matching PID */ |
483 | 459 | launch |= PPC_BIT(12); | |
484 | /* PRS set to process-scoped */ | 460 | } else { |
485 | launch |= PPC_BIT(13); | 461 | /* AP set to invalidate region of psize */ |
462 | launch |= (u64)mmu_get_ap(psize) << PPC_BITLSHIFT(17); | ||
463 | } | ||
486 | 464 | ||
487 | /* AP */ | 465 | /* PRS set to process-scoped */ |
488 | launch |= (u64) | 466 | launch |= PPC_BIT(13); |
489 | mmu_get_ap(mmu_virtual_psize) << PPC_BITLSHIFT(17); | ||
490 | 467 | ||
491 | /* PID */ | 468 | /* PID */ |
492 | launch |= pid << PPC_BITLSHIFT(38); | 469 | launch |= pid << PPC_BITLSHIFT(38); |
493 | 470 | ||
494 | /* No flush */ | 471 | /* Leave "No flush" (bit 39) 0 so every ATSD performs a flush */ |
495 | launch |= !flush << PPC_BITLSHIFT(39); | ||
496 | 472 | ||
497 | /* Invalidating the entire process doesn't use a va */ | 473 | return launch; |
498 | mmio_launch_invalidate(&mmio_atsd_reg[i], launch, 0); | ||
499 | } | ||
500 | } | 474 | } |
501 | 475 | ||
502 | static void mmio_invalidate_va(struct mmio_atsd_reg mmio_atsd_reg[NV_MAX_NPUS], | 476 | static void mmio_atsd_regs_write(struct mmio_atsd_reg |
503 | unsigned long va, unsigned long pid, bool flush) | 477 | mmio_atsd_reg[NV_MAX_NPUS], unsigned long offset, |
478 | unsigned long val) | ||
504 | { | 479 | { |
505 | int i; | 480 | struct npu *npu; |
506 | unsigned long launch; | 481 | int i, reg; |
507 | 482 | ||
508 | for (i = 0; i <= max_npu2_index; i++) { | 483 | for (i = 0; i <= max_npu2_index; i++) { |
509 | if (mmio_atsd_reg[i].reg < 0) | 484 | reg = mmio_atsd_reg[i].reg; |
485 | if (reg < 0) | ||
510 | continue; | 486 | continue; |
511 | 487 | ||
512 | /* IS set to invalidate target VA */ | 488 | npu = mmio_atsd_reg[i].npu; |
513 | launch = 0; | 489 | __raw_writeq_be(val, npu->mmio_atsd_regs[reg] + offset); |
490 | } | ||
491 | } | ||
492 | |||
493 | static void mmio_invalidate_pid(struct mmio_atsd_reg mmio_atsd_reg[NV_MAX_NPUS], | ||
494 | unsigned long pid) | ||
495 | { | ||
496 | unsigned long launch = get_atsd_launch_val(pid, MMU_PAGE_COUNT); | ||
514 | 497 | ||
515 | /* PRS set to process scoped */ | 498 | /* Invalidating the entire process doesn't use a va */ |
516 | launch |= PPC_BIT(13); | 499 | mmio_atsd_regs_write(mmio_atsd_reg, XTS_ATSD_LAUNCH, launch); |
500 | } | ||
517 | 501 | ||
518 | /* AP */ | 502 | static void mmio_invalidate_range(struct mmio_atsd_reg |
519 | launch |= (u64) | 503 | mmio_atsd_reg[NV_MAX_NPUS], unsigned long pid, |
520 | mmu_get_ap(mmu_virtual_psize) << PPC_BITLSHIFT(17); | 504 | unsigned long start, unsigned long psize) |
505 | { | ||
506 | unsigned long launch = get_atsd_launch_val(pid, psize); | ||
521 | 507 | ||
522 | /* PID */ | 508 | /* Write all VAs first */ |
523 | launch |= pid << PPC_BITLSHIFT(38); | 509 | mmio_atsd_regs_write(mmio_atsd_reg, XTS_ATSD_AVA, start); |
524 | 510 | ||
525 | /* No flush */ | 511 | /* Issue one barrier for all address writes */ |
526 | launch |= !flush << PPC_BITLSHIFT(39); | 512 | eieio(); |
527 | 513 | ||
528 | mmio_launch_invalidate(&mmio_atsd_reg[i], launch, va); | 514 | /* Launch */ |
529 | } | 515 | mmio_atsd_regs_write(mmio_atsd_reg, XTS_ATSD_LAUNCH, launch); |
530 | } | 516 | } |
531 | 517 | ||
532 | #define mn_to_npu_context(x) container_of(x, struct npu_context, mn) | 518 | #define mn_to_npu_context(x) container_of(x, struct npu_context, mn) |
@@ -612,14 +598,36 @@ static void release_atsd_reg(struct mmio_atsd_reg mmio_atsd_reg[NV_MAX_NPUS]) | |||
612 | } | 598 | } |
613 | 599 | ||
614 | /* | 600 | /* |
615 | * Invalidate either a single address or an entire PID depending on | 601 | * Invalidate a virtual address range |
616 | * the value of va. | ||
617 | */ | 602 | */ |
618 | static void mmio_invalidate(struct npu_context *npu_context, int va, | 603 | static void mmio_invalidate(struct npu_context *npu_context, |
619 | unsigned long address, bool flush) | 604 | unsigned long start, unsigned long size) |
620 | { | 605 | { |
621 | struct mmio_atsd_reg mmio_atsd_reg[NV_MAX_NPUS]; | 606 | struct mmio_atsd_reg mmio_atsd_reg[NV_MAX_NPUS]; |
622 | unsigned long pid = npu_context->mm->context.id; | 607 | unsigned long pid = npu_context->mm->context.id; |
608 | unsigned long atsd_start = 0; | ||
609 | unsigned long end = start + size - 1; | ||
610 | int atsd_psize = MMU_PAGE_COUNT; | ||
611 | |||
612 | /* | ||
613 | * Convert the input range into one of the supported sizes. If the range | ||
614 | * doesn't fit, use the next larger supported size. Invalidation latency | ||
615 | * is high, so over-invalidation is preferred to issuing multiple | ||
616 | * invalidates. | ||
617 | * | ||
618 | * A 4K page size isn't supported by NPU/GPU ATS, so that case is | ||
619 | * ignored. | ||
620 | */ | ||
621 | if (size == SZ_64K) { | ||
622 | atsd_start = start; | ||
623 | atsd_psize = MMU_PAGE_64K; | ||
624 | } else if (ALIGN_DOWN(start, SZ_2M) == ALIGN_DOWN(end, SZ_2M)) { | ||
625 | atsd_start = ALIGN_DOWN(start, SZ_2M); | ||
626 | atsd_psize = MMU_PAGE_2M; | ||
627 | } else if (ALIGN_DOWN(start, SZ_1G) == ALIGN_DOWN(end, SZ_1G)) { | ||
628 | atsd_start = ALIGN_DOWN(start, SZ_1G); | ||
629 | atsd_psize = MMU_PAGE_1G; | ||
630 | } | ||
623 | 631 | ||
624 | if (npu_context->nmmu_flush) | 632 | if (npu_context->nmmu_flush) |
625 | /* | 633 | /* |
@@ -634,23 +642,25 @@ static void mmio_invalidate(struct npu_context *npu_context, int va, | |||
634 | * an invalidate. | 642 | * an invalidate. |
635 | */ | 643 | */ |
636 | acquire_atsd_reg(npu_context, mmio_atsd_reg); | 644 | acquire_atsd_reg(npu_context, mmio_atsd_reg); |
637 | if (va) | 645 | |
638 | mmio_invalidate_va(mmio_atsd_reg, address, pid, flush); | 646 | if (atsd_psize == MMU_PAGE_COUNT) |
647 | mmio_invalidate_pid(mmio_atsd_reg, pid); | ||
639 | else | 648 | else |
640 | mmio_invalidate_pid(mmio_atsd_reg, pid, flush); | 649 | mmio_invalidate_range(mmio_atsd_reg, pid, atsd_start, |
650 | atsd_psize); | ||
641 | 651 | ||
642 | mmio_invalidate_wait(mmio_atsd_reg); | 652 | mmio_invalidate_wait(mmio_atsd_reg); |
643 | if (flush) { | 653 | |
644 | /* | 654 | /* |
645 | * The GPU requires two flush ATSDs to ensure all entries have | 655 | * The GPU requires two flush ATSDs to ensure all entries have been |
646 | * been flushed. We use PID 0 as it will never be used for a | 656 | * flushed. We use PID 0 as it will never be used for a process on the |
647 | * process on the GPU. | 657 | * GPU. |
648 | */ | 658 | */ |
649 | mmio_invalidate_pid(mmio_atsd_reg, 0, true); | 659 | mmio_invalidate_pid(mmio_atsd_reg, 0); |
650 | mmio_invalidate_wait(mmio_atsd_reg); | 660 | mmio_invalidate_wait(mmio_atsd_reg); |
651 | mmio_invalidate_pid(mmio_atsd_reg, 0, true); | 661 | mmio_invalidate_pid(mmio_atsd_reg, 0); |
652 | mmio_invalidate_wait(mmio_atsd_reg); | 662 | mmio_invalidate_wait(mmio_atsd_reg); |
653 | } | 663 | |
654 | release_atsd_reg(mmio_atsd_reg); | 664 | release_atsd_reg(mmio_atsd_reg); |
655 | } | 665 | } |
656 | 666 | ||
@@ -667,7 +677,7 @@ static void pnv_npu2_mn_release(struct mmu_notifier *mn, | |||
667 | * There should be no more translation requests for this PID, but we | 677 | * There should be no more translation requests for this PID, but we |
668 | * need to ensure any entries for it are removed from the TLB. | 678 | * need to ensure any entries for it are removed from the TLB. |
669 | */ | 679 | */ |
670 | mmio_invalidate(npu_context, 0, 0, true); | 680 | mmio_invalidate(npu_context, 0, ~0UL); |
671 | } | 681 | } |
672 | 682 | ||
673 | static void pnv_npu2_mn_change_pte(struct mmu_notifier *mn, | 683 | static void pnv_npu2_mn_change_pte(struct mmu_notifier *mn, |
@@ -676,8 +686,7 @@ static void pnv_npu2_mn_change_pte(struct mmu_notifier *mn, | |||
676 | pte_t pte) | 686 | pte_t pte) |
677 | { | 687 | { |
678 | struct npu_context *npu_context = mn_to_npu_context(mn); | 688 | struct npu_context *npu_context = mn_to_npu_context(mn); |
679 | 689 | mmio_invalidate(npu_context, address, PAGE_SIZE); | |
680 | mmio_invalidate(npu_context, 1, address, true); | ||
681 | } | 690 | } |
682 | 691 | ||
683 | static void pnv_npu2_mn_invalidate_range(struct mmu_notifier *mn, | 692 | static void pnv_npu2_mn_invalidate_range(struct mmu_notifier *mn, |
@@ -685,21 +694,7 @@ static void pnv_npu2_mn_invalidate_range(struct mmu_notifier *mn, | |||
685 | unsigned long start, unsigned long end) | 694 | unsigned long start, unsigned long end) |
686 | { | 695 | { |
687 | struct npu_context *npu_context = mn_to_npu_context(mn); | 696 | struct npu_context *npu_context = mn_to_npu_context(mn); |
688 | unsigned long address; | 697 | mmio_invalidate(npu_context, start, end - start); |
689 | |||
690 | if (end - start > atsd_threshold) { | ||
691 | /* | ||
692 | * Just invalidate the entire PID if the address range is too | ||
693 | * large. | ||
694 | */ | ||
695 | mmio_invalidate(npu_context, 0, 0, true); | ||
696 | } else { | ||
697 | for (address = start; address < end; address += PAGE_SIZE) | ||
698 | mmio_invalidate(npu_context, 1, address, false); | ||
699 | |||
700 | /* Do the flush only on the final addess == end */ | ||
701 | mmio_invalidate(npu_context, 1, address, true); | ||
702 | } | ||
703 | } | 698 | } |
704 | 699 | ||
705 | static const struct mmu_notifier_ops nv_nmmu_notifier_ops = { | 700 | static const struct mmu_notifier_ops nv_nmmu_notifier_ops = { |
@@ -962,11 +957,6 @@ int pnv_npu2_init(struct pnv_phb *phb) | |||
962 | static int npu_index; | 957 | static int npu_index; |
963 | uint64_t rc = 0; | 958 | uint64_t rc = 0; |
964 | 959 | ||
965 | if (!atsd_threshold_dentry) { | ||
966 | atsd_threshold_dentry = debugfs_create_x64("atsd_threshold", | ||
967 | 0600, powerpc_debugfs_root, &atsd_threshold); | ||
968 | } | ||
969 | |||
970 | phb->npu.nmmu_flush = | 960 | phb->npu.nmmu_flush = |
971 | of_property_read_bool(phb->hose->dn, "ibm,nmmu-flush"); | 961 | of_property_read_bool(phb->hose->dn, "ibm,nmmu-flush"); |
972 | for_each_child_of_node(phb->hose->dn, dn) { | 962 | for_each_child_of_node(phb->hose->dn, dn) { |
diff --git a/arch/powerpc/platforms/powernv/opal-powercap.c b/arch/powerpc/platforms/powernv/opal-powercap.c index badb29bde93f..d90ee4fc2c6a 100644 --- a/arch/powerpc/platforms/powernv/opal-powercap.c +++ b/arch/powerpc/platforms/powernv/opal-powercap.c | |||
@@ -199,7 +199,7 @@ void __init opal_powercap_init(void) | |||
199 | } | 199 | } |
200 | 200 | ||
201 | j = 0; | 201 | j = 0; |
202 | pcaps[i].pg.name = node->name; | 202 | pcaps[i].pg.name = kasprintf(GFP_KERNEL, "%pOFn", node); |
203 | if (has_min) { | 203 | if (has_min) { |
204 | powercap_add_attr(min, "powercap-min", | 204 | powercap_add_attr(min, "powercap-min", |
205 | &pcaps[i].pattrs[j]); | 205 | &pcaps[i].pattrs[j]); |
@@ -237,6 +237,7 @@ out_pcaps_pattrs: | |||
237 | while (--i >= 0) { | 237 | while (--i >= 0) { |
238 | kfree(pcaps[i].pattrs); | 238 | kfree(pcaps[i].pattrs); |
239 | kfree(pcaps[i].pg.attrs); | 239 | kfree(pcaps[i].pg.attrs); |
240 | kfree(pcaps[i].pg.name); | ||
240 | } | 241 | } |
241 | kobject_put(powercap_kobj); | 242 | kobject_put(powercap_kobj); |
242 | out_pcaps: | 243 | out_pcaps: |
diff --git a/arch/powerpc/platforms/powernv/opal-sensor-groups.c b/arch/powerpc/platforms/powernv/opal-sensor-groups.c index f7d04b6a2d7a..179609220e6f 100644 --- a/arch/powerpc/platforms/powernv/opal-sensor-groups.c +++ b/arch/powerpc/platforms/powernv/opal-sensor-groups.c | |||
@@ -214,9 +214,9 @@ void __init opal_sensor_groups_init(void) | |||
214 | } | 214 | } |
215 | 215 | ||
216 | if (!of_property_read_u32(node, "ibm,chip-id", &chipid)) | 216 | if (!of_property_read_u32(node, "ibm,chip-id", &chipid)) |
217 | sprintf(sgs[i].name, "%s%d", node->name, chipid); | 217 | sprintf(sgs[i].name, "%pOFn%d", node, chipid); |
218 | else | 218 | else |
219 | sprintf(sgs[i].name, "%s", node->name); | 219 | sprintf(sgs[i].name, "%pOFn", node); |
220 | 220 | ||
221 | sgs[i].sg.name = sgs[i].name; | 221 | sgs[i].sg.name = sgs[i].name; |
222 | if (add_attr_group(ops, len, &sgs[i], sgid)) { | 222 | if (add_attr_group(ops, len, &sgs[i], sgid)) { |
diff --git a/arch/powerpc/platforms/powernv/opal-sysparam.c b/arch/powerpc/platforms/powernv/opal-sysparam.c index 9aa87df114fd..916a4b7b1bb5 100644 --- a/arch/powerpc/platforms/powernv/opal-sysparam.c +++ b/arch/powerpc/platforms/powernv/opal-sysparam.c | |||
@@ -194,7 +194,7 @@ void __init opal_sys_param_init(void) | |||
194 | count = of_property_count_strings(sysparam, "param-name"); | 194 | count = of_property_count_strings(sysparam, "param-name"); |
195 | if (count < 0) { | 195 | if (count < 0) { |
196 | pr_err("SYSPARAM: No string found of property param-name in " | 196 | pr_err("SYSPARAM: No string found of property param-name in " |
197 | "the node %s\n", sysparam->name); | 197 | "the node %pOFn\n", sysparam); |
198 | goto out_param_buf; | 198 | goto out_param_buf; |
199 | } | 199 | } |
200 | 200 | ||
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c index 38fe4087484a..a4641515956f 100644 --- a/arch/powerpc/platforms/powernv/opal.c +++ b/arch/powerpc/platforms/powernv/opal.c | |||
@@ -535,7 +535,7 @@ static int opal_recover_mce(struct pt_regs *regs, | |||
535 | return recovered; | 535 | return recovered; |
536 | } | 536 | } |
537 | 537 | ||
538 | void pnv_platform_error_reboot(struct pt_regs *regs, const char *msg) | 538 | void __noreturn pnv_platform_error_reboot(struct pt_regs *regs, const char *msg) |
539 | { | 539 | { |
540 | panic_flush_kmsg_start(); | 540 | panic_flush_kmsg_start(); |
541 | 541 | ||
diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c index adddde023622..14befee4b3f1 100644 --- a/arch/powerpc/platforms/powernv/setup.c +++ b/arch/powerpc/platforms/powernv/setup.c | |||
@@ -219,17 +219,41 @@ static void pnv_prepare_going_down(void) | |||
219 | 219 | ||
220 | static void __noreturn pnv_restart(char *cmd) | 220 | static void __noreturn pnv_restart(char *cmd) |
221 | { | 221 | { |
222 | long rc = OPAL_BUSY; | 222 | long rc; |
223 | 223 | ||
224 | pnv_prepare_going_down(); | 224 | pnv_prepare_going_down(); |
225 | 225 | ||
226 | while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) { | 226 | do { |
227 | rc = opal_cec_reboot(); | 227 | if (!cmd) |
228 | if (rc == OPAL_BUSY_EVENT) | 228 | rc = opal_cec_reboot(); |
229 | opal_poll_events(NULL); | 229 | else if (strcmp(cmd, "full") == 0) |
230 | rc = opal_cec_reboot2(OPAL_REBOOT_FULL_IPL, NULL); | ||
230 | else | 231 | else |
232 | rc = OPAL_UNSUPPORTED; | ||
233 | |||
234 | if (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) { | ||
235 | /* Opal is busy wait for some time and retry */ | ||
236 | opal_poll_events(NULL); | ||
231 | mdelay(10); | 237 | mdelay(10); |
232 | } | 238 | |
239 | } else if (cmd && rc) { | ||
240 | /* Unknown error while issuing reboot */ | ||
241 | if (rc == OPAL_UNSUPPORTED) | ||
242 | pr_err("Unsupported '%s' reboot.\n", cmd); | ||
243 | else | ||
244 | pr_err("Unable to issue '%s' reboot. Err=%ld\n", | ||
245 | cmd, rc); | ||
246 | pr_info("Forcing a cec-reboot\n"); | ||
247 | cmd = NULL; | ||
248 | rc = OPAL_BUSY; | ||
249 | |||
250 | } else if (rc != OPAL_SUCCESS) { | ||
251 | /* Unknown error while issuing cec-reboot */ | ||
252 | pr_err("Unable to reboot. Err=%ld\n", rc); | ||
253 | } | ||
254 | |||
255 | } while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT); | ||
256 | |||
233 | for (;;) | 257 | for (;;) |
234 | opal_poll_events(NULL); | 258 | opal_poll_events(NULL); |
235 | } | 259 | } |
@@ -437,6 +461,16 @@ static unsigned long pnv_get_proc_freq(unsigned int cpu) | |||
437 | return ret_freq; | 461 | return ret_freq; |
438 | } | 462 | } |
439 | 463 | ||
464 | static long pnv_machine_check_early(struct pt_regs *regs) | ||
465 | { | ||
466 | long handled = 0; | ||
467 | |||
468 | if (cur_cpu_spec && cur_cpu_spec->machine_check_early) | ||
469 | handled = cur_cpu_spec->machine_check_early(regs); | ||
470 | |||
471 | return handled; | ||
472 | } | ||
473 | |||
440 | define_machine(powernv) { | 474 | define_machine(powernv) { |
441 | .name = "PowerNV", | 475 | .name = "PowerNV", |
442 | .probe = pnv_probe, | 476 | .probe = pnv_probe, |
@@ -448,6 +482,7 @@ define_machine(powernv) { | |||
448 | .machine_shutdown = pnv_shutdown, | 482 | .machine_shutdown = pnv_shutdown, |
449 | .power_save = NULL, | 483 | .power_save = NULL, |
450 | .calibrate_decr = generic_calibrate_decr, | 484 | .calibrate_decr = generic_calibrate_decr, |
485 | .machine_check_early = pnv_machine_check_early, | ||
451 | #ifdef CONFIG_KEXEC_CORE | 486 | #ifdef CONFIG_KEXEC_CORE |
452 | .kexec_cpu_down = pnv_kexec_cpu_down, | 487 | .kexec_cpu_down = pnv_kexec_cpu_down, |
453 | #endif | 488 | #endif |
diff --git a/arch/powerpc/platforms/ps3/Kconfig b/arch/powerpc/platforms/ps3/Kconfig index 6f7525555b19..24864b8aaf5d 100644 --- a/arch/powerpc/platforms/ps3/Kconfig +++ b/arch/powerpc/platforms/ps3/Kconfig | |||
@@ -49,7 +49,6 @@ config PS3_HTAB_SIZE | |||
49 | config PS3_DYNAMIC_DMA | 49 | config PS3_DYNAMIC_DMA |
50 | depends on PPC_PS3 | 50 | depends on PPC_PS3 |
51 | bool "PS3 Platform dynamic DMA page table management" | 51 | bool "PS3 Platform dynamic DMA page table management" |
52 | default n | ||
53 | help | 52 | help |
54 | This option will enable kernel support to take advantage of the | 53 | This option will enable kernel support to take advantage of the |
55 | per device dynamic DMA page table management provided by the Cell | 54 | per device dynamic DMA page table management provided by the Cell |
@@ -89,7 +88,6 @@ config PS3_SYS_MANAGER | |||
89 | config PS3_REPOSITORY_WRITE | 88 | config PS3_REPOSITORY_WRITE |
90 | bool "PS3 Repository write support" if PS3_ADVANCED | 89 | bool "PS3 Repository write support" if PS3_ADVANCED |
91 | depends on PPC_PS3 | 90 | depends on PPC_PS3 |
92 | default n | ||
93 | help | 91 | help |
94 | Enables support for writing to the PS3 System Repository. | 92 | Enables support for writing to the PS3 System Repository. |
95 | 93 | ||
diff --git a/arch/powerpc/platforms/ps3/os-area.c b/arch/powerpc/platforms/ps3/os-area.c index cdbfc5cfd6f3..f5387ad82279 100644 --- a/arch/powerpc/platforms/ps3/os-area.c +++ b/arch/powerpc/platforms/ps3/os-area.c | |||
@@ -664,7 +664,7 @@ static int update_flash_db(void) | |||
664 | db_set_64(db, &os_area_db_id_rtc_diff, saved_params.rtc_diff); | 664 | db_set_64(db, &os_area_db_id_rtc_diff, saved_params.rtc_diff); |
665 | 665 | ||
666 | count = os_area_flash_write(db, sizeof(struct os_area_db), pos); | 666 | count = os_area_flash_write(db, sizeof(struct os_area_db), pos); |
667 | if (count < sizeof(struct os_area_db)) { | 667 | if (count < 0 || count < sizeof(struct os_area_db)) { |
668 | pr_debug("%s: os_area_flash_write failed %zd\n", __func__, | 668 | pr_debug("%s: os_area_flash_write failed %zd\n", __func__, |
669 | count); | 669 | count); |
670 | error = count < 0 ? count : -EIO; | 670 | error = count < 0 ? count : -EIO; |
diff --git a/arch/powerpc/platforms/ps3/spu.c b/arch/powerpc/platforms/ps3/spu.c index b54850845466..7746c2a3c509 100644 --- a/arch/powerpc/platforms/ps3/spu.c +++ b/arch/powerpc/platforms/ps3/spu.c | |||
@@ -215,8 +215,7 @@ static int __init setup_areas(struct spu *spu) | |||
215 | goto fail_ioremap; | 215 | goto fail_ioremap; |
216 | } | 216 | } |
217 | 217 | ||
218 | spu->local_store = (__force void *)ioremap_prot(spu->local_store_phys, | 218 | spu->local_store = (__force void *)ioremap_wc(spu->local_store_phys, LS_SIZE); |
219 | LS_SIZE, pgprot_val(pgprot_noncached_wc(__pgprot(0)))); | ||
220 | 219 | ||
221 | if (!spu->local_store) { | 220 | if (!spu->local_store) { |
222 | pr_debug("%s:%d: ioremap local_store failed\n", | 221 | pr_debug("%s:%d: ioremap local_store failed\n", |
diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig index 0c698fd6d491..2e4bd32154b5 100644 --- a/arch/powerpc/platforms/pseries/Kconfig +++ b/arch/powerpc/platforms/pseries/Kconfig | |||
@@ -28,7 +28,6 @@ config PPC_PSERIES | |||
28 | config PPC_SPLPAR | 28 | config PPC_SPLPAR |
29 | depends on PPC_PSERIES | 29 | depends on PPC_PSERIES |
30 | bool "Support for shared-processor logical partitions" | 30 | bool "Support for shared-processor logical partitions" |
31 | default n | ||
32 | help | 31 | help |
33 | Enabling this option will make the kernel run more efficiently | 32 | Enabling this option will make the kernel run more efficiently |
34 | on logically-partitioned pSeries systems which use shared | 33 | on logically-partitioned pSeries systems which use shared |
@@ -99,7 +98,6 @@ config PPC_SMLPAR | |||
99 | bool "Support for shared-memory logical partitions" | 98 | bool "Support for shared-memory logical partitions" |
100 | depends on PPC_PSERIES | 99 | depends on PPC_PSERIES |
101 | select LPARCFG | 100 | select LPARCFG |
102 | default n | ||
103 | help | 101 | help |
104 | Select this option to enable shared memory partition support. | 102 | Select this option to enable shared memory partition support. |
105 | With this option a system running in an LPAR can be given more | 103 | With this option a system running in an LPAR can be given more |
@@ -140,3 +138,10 @@ config IBMEBUS | |||
140 | bool "Support for GX bus based adapters" | 138 | bool "Support for GX bus based adapters" |
141 | help | 139 | help |
142 | Bus device driver for GX bus based adapters. | 140 | Bus device driver for GX bus based adapters. |
141 | |||
142 | config PAPR_SCM | ||
143 | depends on PPC_PSERIES && MEMORY_HOTPLUG | ||
144 | select LIBNVDIMM | ||
145 | tristate "Support for the PAPR Storage Class Memory interface" | ||
146 | help | ||
147 | Enable access to hypervisor provided storage class memory. | ||
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile index 7e89d5c47068..a43ec843c8e2 100644 --- a/arch/powerpc/platforms/pseries/Makefile +++ b/arch/powerpc/platforms/pseries/Makefile | |||
@@ -13,7 +13,7 @@ obj-$(CONFIG_KEXEC_CORE) += kexec.o | |||
13 | obj-$(CONFIG_PSERIES_ENERGY) += pseries_energy.o | 13 | obj-$(CONFIG_PSERIES_ENERGY) += pseries_energy.o |
14 | 14 | ||
15 | obj-$(CONFIG_HOTPLUG_CPU) += hotplug-cpu.o | 15 | obj-$(CONFIG_HOTPLUG_CPU) += hotplug-cpu.o |
16 | obj-$(CONFIG_MEMORY_HOTPLUG) += hotplug-memory.o | 16 | obj-$(CONFIG_MEMORY_HOTPLUG) += hotplug-memory.o pmem.o |
17 | 17 | ||
18 | obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o | 18 | obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o |
19 | obj-$(CONFIG_HVCS) += hvcserver.o | 19 | obj-$(CONFIG_HVCS) += hvcserver.o |
@@ -24,6 +24,7 @@ obj-$(CONFIG_IO_EVENT_IRQ) += io_event_irq.o | |||
24 | obj-$(CONFIG_LPARCFG) += lparcfg.o | 24 | obj-$(CONFIG_LPARCFG) += lparcfg.o |
25 | obj-$(CONFIG_IBMVIO) += vio.o | 25 | obj-$(CONFIG_IBMVIO) += vio.o |
26 | obj-$(CONFIG_IBMEBUS) += ibmebus.o | 26 | obj-$(CONFIG_IBMEBUS) += ibmebus.o |
27 | obj-$(CONFIG_PAPR_SCM) += papr_scm.o | ||
27 | 28 | ||
28 | ifdef CONFIG_PPC_PSERIES | 29 | ifdef CONFIG_PPC_PSERIES |
29 | obj-$(CONFIG_SUSPEND) += suspend.o | 30 | obj-$(CONFIG_SUSPEND) += suspend.o |
diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c index a0b20c03f078..7625546caefd 100644 --- a/arch/powerpc/platforms/pseries/dlpar.c +++ b/arch/powerpc/platforms/pseries/dlpar.c | |||
@@ -32,8 +32,6 @@ static struct workqueue_struct *pseries_hp_wq; | |||
32 | struct pseries_hp_work { | 32 | struct pseries_hp_work { |
33 | struct work_struct work; | 33 | struct work_struct work; |
34 | struct pseries_hp_errorlog *errlog; | 34 | struct pseries_hp_errorlog *errlog; |
35 | struct completion *hp_completion; | ||
36 | int *rc; | ||
37 | }; | 35 | }; |
38 | 36 | ||
39 | struct cc_workarea { | 37 | struct cc_workarea { |
@@ -329,7 +327,7 @@ int dlpar_release_drc(u32 drc_index) | |||
329 | return 0; | 327 | return 0; |
330 | } | 328 | } |
331 | 329 | ||
332 | static int handle_dlpar_errorlog(struct pseries_hp_errorlog *hp_elog) | 330 | int handle_dlpar_errorlog(struct pseries_hp_errorlog *hp_elog) |
333 | { | 331 | { |
334 | int rc; | 332 | int rc; |
335 | 333 | ||
@@ -357,6 +355,10 @@ static int handle_dlpar_errorlog(struct pseries_hp_errorlog *hp_elog) | |||
357 | case PSERIES_HP_ELOG_RESOURCE_CPU: | 355 | case PSERIES_HP_ELOG_RESOURCE_CPU: |
358 | rc = dlpar_cpu(hp_elog); | 356 | rc = dlpar_cpu(hp_elog); |
359 | break; | 357 | break; |
358 | case PSERIES_HP_ELOG_RESOURCE_PMEM: | ||
359 | rc = dlpar_hp_pmem(hp_elog); | ||
360 | break; | ||
361 | |||
360 | default: | 362 | default: |
361 | pr_warn_ratelimited("Invalid resource (%d) specified\n", | 363 | pr_warn_ratelimited("Invalid resource (%d) specified\n", |
362 | hp_elog->resource); | 364 | hp_elog->resource); |
@@ -371,20 +373,13 @@ static void pseries_hp_work_fn(struct work_struct *work) | |||
371 | struct pseries_hp_work *hp_work = | 373 | struct pseries_hp_work *hp_work = |
372 | container_of(work, struct pseries_hp_work, work); | 374 | container_of(work, struct pseries_hp_work, work); |
373 | 375 | ||
374 | if (hp_work->rc) | 376 | handle_dlpar_errorlog(hp_work->errlog); |
375 | *(hp_work->rc) = handle_dlpar_errorlog(hp_work->errlog); | ||
376 | else | ||
377 | handle_dlpar_errorlog(hp_work->errlog); | ||
378 | |||
379 | if (hp_work->hp_completion) | ||
380 | complete(hp_work->hp_completion); | ||
381 | 377 | ||
382 | kfree(hp_work->errlog); | 378 | kfree(hp_work->errlog); |
383 | kfree((void *)work); | 379 | kfree((void *)work); |
384 | } | 380 | } |
385 | 381 | ||
386 | void queue_hotplug_event(struct pseries_hp_errorlog *hp_errlog, | 382 | void queue_hotplug_event(struct pseries_hp_errorlog *hp_errlog) |
387 | struct completion *hotplug_done, int *rc) | ||
388 | { | 383 | { |
389 | struct pseries_hp_work *work; | 384 | struct pseries_hp_work *work; |
390 | struct pseries_hp_errorlog *hp_errlog_copy; | 385 | struct pseries_hp_errorlog *hp_errlog_copy; |
@@ -397,13 +392,9 @@ void queue_hotplug_event(struct pseries_hp_errorlog *hp_errlog, | |||
397 | if (work) { | 392 | if (work) { |
398 | INIT_WORK((struct work_struct *)work, pseries_hp_work_fn); | 393 | INIT_WORK((struct work_struct *)work, pseries_hp_work_fn); |
399 | work->errlog = hp_errlog_copy; | 394 | work->errlog = hp_errlog_copy; |
400 | work->hp_completion = hotplug_done; | ||
401 | work->rc = rc; | ||
402 | queue_work(pseries_hp_wq, (struct work_struct *)work); | 395 | queue_work(pseries_hp_wq, (struct work_struct *)work); |
403 | } else { | 396 | } else { |
404 | *rc = -ENOMEM; | ||
405 | kfree(hp_errlog_copy); | 397 | kfree(hp_errlog_copy); |
406 | complete(hotplug_done); | ||
407 | } | 398 | } |
408 | } | 399 | } |
409 | 400 | ||
@@ -521,18 +512,15 @@ static int dlpar_parse_id_type(char **cmd, struct pseries_hp_errorlog *hp_elog) | |||
521 | static ssize_t dlpar_store(struct class *class, struct class_attribute *attr, | 512 | static ssize_t dlpar_store(struct class *class, struct class_attribute *attr, |
522 | const char *buf, size_t count) | 513 | const char *buf, size_t count) |
523 | { | 514 | { |
524 | struct pseries_hp_errorlog *hp_elog; | 515 | struct pseries_hp_errorlog hp_elog; |
525 | struct completion hotplug_done; | ||
526 | char *argbuf; | 516 | char *argbuf; |
527 | char *args; | 517 | char *args; |
528 | int rc; | 518 | int rc; |
529 | 519 | ||
530 | args = argbuf = kstrdup(buf, GFP_KERNEL); | 520 | args = argbuf = kstrdup(buf, GFP_KERNEL); |
531 | hp_elog = kzalloc(sizeof(*hp_elog), GFP_KERNEL); | 521 | if (!argbuf) { |
532 | if (!hp_elog || !argbuf) { | ||
533 | pr_info("Could not allocate resources for DLPAR operation\n"); | 522 | pr_info("Could not allocate resources for DLPAR operation\n"); |
534 | kfree(argbuf); | 523 | kfree(argbuf); |
535 | kfree(hp_elog); | ||
536 | return -ENOMEM; | 524 | return -ENOMEM; |
537 | } | 525 | } |
538 | 526 | ||
@@ -540,25 +528,22 @@ static ssize_t dlpar_store(struct class *class, struct class_attribute *attr, | |||
540 | * Parse out the request from the user, this will be in the form: | 528 | * Parse out the request from the user, this will be in the form: |
541 | * <resource> <action> <id_type> <id> | 529 | * <resource> <action> <id_type> <id> |
542 | */ | 530 | */ |
543 | rc = dlpar_parse_resource(&args, hp_elog); | 531 | rc = dlpar_parse_resource(&args, &hp_elog); |
544 | if (rc) | 532 | if (rc) |
545 | goto dlpar_store_out; | 533 | goto dlpar_store_out; |
546 | 534 | ||
547 | rc = dlpar_parse_action(&args, hp_elog); | 535 | rc = dlpar_parse_action(&args, &hp_elog); |
548 | if (rc) | 536 | if (rc) |
549 | goto dlpar_store_out; | 537 | goto dlpar_store_out; |
550 | 538 | ||
551 | rc = dlpar_parse_id_type(&args, hp_elog); | 539 | rc = dlpar_parse_id_type(&args, &hp_elog); |
552 | if (rc) | 540 | if (rc) |
553 | goto dlpar_store_out; | 541 | goto dlpar_store_out; |
554 | 542 | ||
555 | init_completion(&hotplug_done); | 543 | rc = handle_dlpar_errorlog(&hp_elog); |
556 | queue_hotplug_event(hp_elog, &hotplug_done, &rc); | ||
557 | wait_for_completion(&hotplug_done); | ||
558 | 544 | ||
559 | dlpar_store_out: | 545 | dlpar_store_out: |
560 | kfree(argbuf); | 546 | kfree(argbuf); |
561 | kfree(hp_elog); | ||
562 | 547 | ||
563 | if (rc) | 548 | if (rc) |
564 | pr_err("Could not handle DLPAR request \"%s\"\n", buf); | 549 | pr_err("Could not handle DLPAR request \"%s\"\n", buf); |
diff --git a/arch/powerpc/platforms/pseries/dtl.c b/arch/powerpc/platforms/pseries/dtl.c index 18014cdeb590..ef6595153642 100644 --- a/arch/powerpc/platforms/pseries/dtl.c +++ b/arch/powerpc/platforms/pseries/dtl.c | |||
@@ -149,7 +149,7 @@ static int dtl_start(struct dtl *dtl) | |||
149 | 149 | ||
150 | /* Register our dtl buffer with the hypervisor. The HV expects the | 150 | /* Register our dtl buffer with the hypervisor. The HV expects the |
151 | * buffer size to be passed in the second word of the buffer */ | 151 | * buffer size to be passed in the second word of the buffer */ |
152 | ((u32 *)dtl->buf)[1] = DISPATCH_LOG_BYTES; | 152 | ((u32 *)dtl->buf)[1] = cpu_to_be32(DISPATCH_LOG_BYTES); |
153 | 153 | ||
154 | hwcpu = get_hard_smp_processor_id(dtl->cpu); | 154 | hwcpu = get_hard_smp_processor_id(dtl->cpu); |
155 | addr = __pa(dtl->buf); | 155 | addr = __pa(dtl->buf); |
@@ -184,7 +184,7 @@ static void dtl_stop(struct dtl *dtl) | |||
184 | 184 | ||
185 | static u64 dtl_current_index(struct dtl *dtl) | 185 | static u64 dtl_current_index(struct dtl *dtl) |
186 | { | 186 | { |
187 | return lppaca_of(dtl->cpu).dtl_idx; | 187 | return be64_to_cpu(lppaca_of(dtl->cpu).dtl_idx); |
188 | } | 188 | } |
189 | #endif /* CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */ | 189 | #endif /* CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */ |
190 | 190 | ||
diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c b/arch/powerpc/platforms/pseries/eeh_pseries.c index 823cb27efa8b..c9e5ca4afb26 100644 --- a/arch/powerpc/platforms/pseries/eeh_pseries.c +++ b/arch/powerpc/platforms/pseries/eeh_pseries.c | |||
@@ -438,7 +438,7 @@ static int pseries_eeh_get_pe_addr(struct eeh_pe *pe) | |||
438 | /** | 438 | /** |
439 | * pseries_eeh_get_state - Retrieve PE state | 439 | * pseries_eeh_get_state - Retrieve PE state |
440 | * @pe: EEH PE | 440 | * @pe: EEH PE |
441 | * @state: return value | 441 | * @delay: suggested time to wait if state is unavailable |
442 | * | 442 | * |
443 | * Retrieve the state of the specified PE. On RTAS compliant | 443 | * Retrieve the state of the specified PE. On RTAS compliant |
444 | * pseries platform, there already has one dedicated RTAS function | 444 | * pseries platform, there already has one dedicated RTAS function |
@@ -448,7 +448,7 @@ static int pseries_eeh_get_pe_addr(struct eeh_pe *pe) | |||
448 | * RTAS calls for the purpose, we need to try the new one and back | 448 | * RTAS calls for the purpose, we need to try the new one and back |
449 | * to the old one if the new one couldn't work properly. | 449 | * to the old one if the new one couldn't work properly. |
450 | */ | 450 | */ |
451 | static int pseries_eeh_get_state(struct eeh_pe *pe, int *state) | 451 | static int pseries_eeh_get_state(struct eeh_pe *pe, int *delay) |
452 | { | 452 | { |
453 | int config_addr; | 453 | int config_addr; |
454 | int ret; | 454 | int ret; |
@@ -499,7 +499,8 @@ static int pseries_eeh_get_state(struct eeh_pe *pe, int *state) | |||
499 | break; | 499 | break; |
500 | case 5: | 500 | case 5: |
501 | if (rets[2]) { | 501 | if (rets[2]) { |
502 | if (state) *state = rets[2]; | 502 | if (delay) |
503 | *delay = rets[2]; | ||
503 | result = EEH_STATE_UNAVAILABLE; | 504 | result = EEH_STATE_UNAVAILABLE; |
504 | } else { | 505 | } else { |
505 | result = EEH_STATE_NOT_SUPPORT; | 506 | result = EEH_STATE_NOT_SUPPORT; |
@@ -554,64 +555,6 @@ static int pseries_eeh_reset(struct eeh_pe *pe, int option) | |||
554 | } | 555 | } |
555 | 556 | ||
556 | /** | 557 | /** |
557 | * pseries_eeh_wait_state - Wait for PE state | ||
558 | * @pe: EEH PE | ||
559 | * @max_wait: maximal period in millisecond | ||
560 | * | ||
561 | * Wait for the state of associated PE. It might take some time | ||
562 | * to retrieve the PE's state. | ||
563 | */ | ||
564 | static int pseries_eeh_wait_state(struct eeh_pe *pe, int max_wait) | ||
565 | { | ||
566 | int ret; | ||
567 | int mwait; | ||
568 | |||
569 | /* | ||
570 | * According to PAPR, the state of PE might be temporarily | ||
571 | * unavailable. Under the circumstance, we have to wait | ||
572 | * for indicated time determined by firmware. The maximal | ||
573 | * wait time is 5 minutes, which is acquired from the original | ||
574 | * EEH implementation. Also, the original implementation | ||
575 | * also defined the minimal wait time as 1 second. | ||
576 | */ | ||
577 | #define EEH_STATE_MIN_WAIT_TIME (1000) | ||
578 | #define EEH_STATE_MAX_WAIT_TIME (300 * 1000) | ||
579 | |||
580 | while (1) { | ||
581 | ret = pseries_eeh_get_state(pe, &mwait); | ||
582 | |||
583 | /* | ||
584 | * If the PE's state is temporarily unavailable, | ||
585 | * we have to wait for the specified time. Otherwise, | ||
586 | * the PE's state will be returned immediately. | ||
587 | */ | ||
588 | if (ret != EEH_STATE_UNAVAILABLE) | ||
589 | return ret; | ||
590 | |||
591 | if (max_wait <= 0) { | ||
592 | pr_warn("%s: Timeout when getting PE's state (%d)\n", | ||
593 | __func__, max_wait); | ||
594 | return EEH_STATE_NOT_SUPPORT; | ||
595 | } | ||
596 | |||
597 | if (mwait <= 0) { | ||
598 | pr_warn("%s: Firmware returned bad wait value %d\n", | ||
599 | __func__, mwait); | ||
600 | mwait = EEH_STATE_MIN_WAIT_TIME; | ||
601 | } else if (mwait > EEH_STATE_MAX_WAIT_TIME) { | ||
602 | pr_warn("%s: Firmware returned too long wait value %d\n", | ||
603 | __func__, mwait); | ||
604 | mwait = EEH_STATE_MAX_WAIT_TIME; | ||
605 | } | ||
606 | |||
607 | max_wait -= mwait; | ||
608 | msleep(mwait); | ||
609 | } | ||
610 | |||
611 | return EEH_STATE_NOT_SUPPORT; | ||
612 | } | ||
613 | |||
614 | /** | ||
615 | * pseries_eeh_get_log - Retrieve error log | 558 | * pseries_eeh_get_log - Retrieve error log |
616 | * @pe: EEH PE | 559 | * @pe: EEH PE |
617 | * @severity: temporary or permanent error log | 560 | * @severity: temporary or permanent error log |
@@ -849,7 +792,6 @@ static struct eeh_ops pseries_eeh_ops = { | |||
849 | .get_pe_addr = pseries_eeh_get_pe_addr, | 792 | .get_pe_addr = pseries_eeh_get_pe_addr, |
850 | .get_state = pseries_eeh_get_state, | 793 | .get_state = pseries_eeh_get_state, |
851 | .reset = pseries_eeh_reset, | 794 | .reset = pseries_eeh_reset, |
852 | .wait_state = pseries_eeh_wait_state, | ||
853 | .get_log = pseries_eeh_get_log, | 795 | .get_log = pseries_eeh_get_log, |
854 | .configure_bridge = pseries_eeh_configure_bridge, | 796 | .configure_bridge = pseries_eeh_configure_bridge, |
855 | .err_inject = NULL, | 797 | .err_inject = NULL, |
diff --git a/arch/powerpc/platforms/pseries/event_sources.c b/arch/powerpc/platforms/pseries/event_sources.c index 6eeb0d4bab61..446ef104fb3a 100644 --- a/arch/powerpc/platforms/pseries/event_sources.c +++ b/arch/powerpc/platforms/pseries/event_sources.c | |||
@@ -16,7 +16,8 @@ | |||
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <asm/prom.h> | 19 | #include <linux/interrupt.h> |
20 | #include <linux/of_irq.h> | ||
20 | 21 | ||
21 | #include "pseries.h" | 22 | #include "pseries.h" |
22 | 23 | ||
@@ -24,34 +25,19 @@ void request_event_sources_irqs(struct device_node *np, | |||
24 | irq_handler_t handler, | 25 | irq_handler_t handler, |
25 | const char *name) | 26 | const char *name) |
26 | { | 27 | { |
27 | int i, index, count = 0; | 28 | int i, virq, rc; |
28 | struct of_phandle_args oirq; | ||
29 | unsigned int virqs[16]; | ||
30 | 29 | ||
31 | /* First try to do a proper OF tree parsing */ | 30 | for (i = 0; i < 16; i++) { |
32 | for (index = 0; of_irq_parse_one(np, index, &oirq) == 0; | 31 | virq = of_irq_get(np, i); |
33 | index++) { | 32 | if (virq < 0) |
34 | if (count > 15) | 33 | return; |
35 | break; | 34 | if (WARN(!virq, "event-sources: Unable to allocate " |
36 | virqs[count] = irq_create_of_mapping(&oirq); | 35 | "interrupt number for %pOF\n", np)) |
37 | if (!virqs[count]) { | 36 | continue; |
38 | pr_err("event-sources: Unable to allocate " | ||
39 | "interrupt number for %pOF\n", | ||
40 | np); | ||
41 | WARN_ON(1); | ||
42 | } else { | ||
43 | count++; | ||
44 | } | ||
45 | } | ||
46 | 37 | ||
47 | /* Now request them */ | 38 | rc = request_irq(virq, handler, 0, name, NULL); |
48 | for (i = 0; i < count; i++) { | 39 | if (WARN(rc, "event-sources: Unable to request interrupt %d for %pOF\n", |
49 | if (request_irq(virqs[i], handler, 0, name, NULL)) { | 40 | virq, np)) |
50 | pr_err("event-sources: Unable to request interrupt " | ||
51 | "%d for %pOF\n", virqs[i], np); | ||
52 | WARN_ON(1); | ||
53 | return; | 41 | return; |
54 | } | ||
55 | } | 42 | } |
56 | } | 43 | } |
57 | |||
diff --git a/arch/powerpc/platforms/pseries/firmware.c b/arch/powerpc/platforms/pseries/firmware.c index a3bbeb43689e..608ecad0178f 100644 --- a/arch/powerpc/platforms/pseries/firmware.c +++ b/arch/powerpc/platforms/pseries/firmware.c | |||
@@ -65,6 +65,8 @@ hypertas_fw_features_table[] = { | |||
65 | {FW_FEATURE_SET_MODE, "hcall-set-mode"}, | 65 | {FW_FEATURE_SET_MODE, "hcall-set-mode"}, |
66 | {FW_FEATURE_BEST_ENERGY, "hcall-best-energy-1*"}, | 66 | {FW_FEATURE_BEST_ENERGY, "hcall-best-energy-1*"}, |
67 | {FW_FEATURE_HPT_RESIZE, "hcall-hpt-resize"}, | 67 | {FW_FEATURE_HPT_RESIZE, "hcall-hpt-resize"}, |
68 | {FW_FEATURE_BLOCK_REMOVE, "hcall-block-remove"}, | ||
69 | {FW_FEATURE_PAPR_SCM, "hcall-scm"}, | ||
68 | }; | 70 | }; |
69 | 71 | ||
70 | /* Build up the firmware features bitmask using the contents of | 72 | /* Build up the firmware features bitmask using the contents of |
diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c index 6ef77caf7bcf..2f8e62163602 100644 --- a/arch/powerpc/platforms/pseries/hotplug-cpu.c +++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c | |||
@@ -287,7 +287,7 @@ static int pseries_add_processor(struct device_node *np) | |||
287 | 287 | ||
288 | if (cpumask_empty(tmp)) { | 288 | if (cpumask_empty(tmp)) { |
289 | printk(KERN_ERR "Unable to find space in cpu_present_mask for" | 289 | printk(KERN_ERR "Unable to find space in cpu_present_mask for" |
290 | " processor %s with %d thread(s)\n", np->name, | 290 | " processor %pOFn with %d thread(s)\n", np, |
291 | nthreads); | 291 | nthreads); |
292 | goto out_unlock; | 292 | goto out_unlock; |
293 | } | 293 | } |
@@ -481,8 +481,8 @@ static ssize_t dlpar_cpu_add(u32 drc_index) | |||
481 | 481 | ||
482 | if (rc) { | 482 | if (rc) { |
483 | saved_rc = rc; | 483 | saved_rc = rc; |
484 | pr_warn("Failed to attach node %s, rc: %d, drc index: %x\n", | 484 | pr_warn("Failed to attach node %pOFn, rc: %d, drc index: %x\n", |
485 | dn->name, rc, drc_index); | 485 | dn, rc, drc_index); |
486 | 486 | ||
487 | rc = dlpar_release_drc(drc_index); | 487 | rc = dlpar_release_drc(drc_index); |
488 | if (!rc) | 488 | if (!rc) |
@@ -494,8 +494,8 @@ static ssize_t dlpar_cpu_add(u32 drc_index) | |||
494 | rc = dlpar_online_cpu(dn); | 494 | rc = dlpar_online_cpu(dn); |
495 | if (rc) { | 495 | if (rc) { |
496 | saved_rc = rc; | 496 | saved_rc = rc; |
497 | pr_warn("Failed to online cpu %s, rc: %d, drc index: %x\n", | 497 | pr_warn("Failed to online cpu %pOFn, rc: %d, drc index: %x\n", |
498 | dn->name, rc, drc_index); | 498 | dn, rc, drc_index); |
499 | 499 | ||
500 | rc = dlpar_detach_node(dn); | 500 | rc = dlpar_detach_node(dn); |
501 | if (!rc) | 501 | if (!rc) |
@@ -504,7 +504,7 @@ static ssize_t dlpar_cpu_add(u32 drc_index) | |||
504 | return saved_rc; | 504 | return saved_rc; |
505 | } | 505 | } |
506 | 506 | ||
507 | pr_debug("Successfully added CPU %s, drc index: %x\n", dn->name, | 507 | pr_debug("Successfully added CPU %pOFn, drc index: %x\n", dn, |
508 | drc_index); | 508 | drc_index); |
509 | return rc; | 509 | return rc; |
510 | } | 510 | } |
@@ -570,19 +570,19 @@ static ssize_t dlpar_cpu_remove(struct device_node *dn, u32 drc_index) | |||
570 | { | 570 | { |
571 | int rc; | 571 | int rc; |
572 | 572 | ||
573 | pr_debug("Attempting to remove CPU %s, drc index: %x\n", | 573 | pr_debug("Attempting to remove CPU %pOFn, drc index: %x\n", |
574 | dn->name, drc_index); | 574 | dn, drc_index); |
575 | 575 | ||
576 | rc = dlpar_offline_cpu(dn); | 576 | rc = dlpar_offline_cpu(dn); |
577 | if (rc) { | 577 | if (rc) { |
578 | pr_warn("Failed to offline CPU %s, rc: %d\n", dn->name, rc); | 578 | pr_warn("Failed to offline CPU %pOFn, rc: %d\n", dn, rc); |
579 | return -EINVAL; | 579 | return -EINVAL; |
580 | } | 580 | } |
581 | 581 | ||
582 | rc = dlpar_release_drc(drc_index); | 582 | rc = dlpar_release_drc(drc_index); |
583 | if (rc) { | 583 | if (rc) { |
584 | pr_warn("Failed to release drc (%x) for CPU %s, rc: %d\n", | 584 | pr_warn("Failed to release drc (%x) for CPU %pOFn, rc: %d\n", |
585 | drc_index, dn->name, rc); | 585 | drc_index, dn, rc); |
586 | dlpar_online_cpu(dn); | 586 | dlpar_online_cpu(dn); |
587 | return rc; | 587 | return rc; |
588 | } | 588 | } |
@@ -591,7 +591,7 @@ static ssize_t dlpar_cpu_remove(struct device_node *dn, u32 drc_index) | |||
591 | if (rc) { | 591 | if (rc) { |
592 | int saved_rc = rc; | 592 | int saved_rc = rc; |
593 | 593 | ||
594 | pr_warn("Failed to detach CPU %s, rc: %d", dn->name, rc); | 594 | pr_warn("Failed to detach CPU %pOFn, rc: %d", dn, rc); |
595 | 595 | ||
596 | rc = dlpar_acquire_drc(drc_index); | 596 | rc = dlpar_acquire_drc(drc_index); |
597 | if (!rc) | 597 | if (!rc) |
@@ -662,8 +662,8 @@ static int find_dlpar_cpus_to_remove(u32 *cpu_drcs, int cpus_to_remove) | |||
662 | rc = of_property_read_u32(dn, "ibm,my-drc-index", | 662 | rc = of_property_read_u32(dn, "ibm,my-drc-index", |
663 | &cpu_drcs[cpus_found - 1]); | 663 | &cpu_drcs[cpus_found - 1]); |
664 | if (rc) { | 664 | if (rc) { |
665 | pr_warn("Error occurred getting drc-index for %s\n", | 665 | pr_warn("Error occurred getting drc-index for %pOFn\n", |
666 | dn->name); | 666 | dn); |
667 | of_node_put(dn); | 667 | of_node_put(dn); |
668 | return -1; | 668 | return -1; |
669 | } | 669 | } |
diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c index c1578f54c626..2b796da822c2 100644 --- a/arch/powerpc/platforms/pseries/hotplug-memory.c +++ b/arch/powerpc/platforms/pseries/hotplug-memory.c | |||
@@ -101,11 +101,12 @@ static struct property *dlpar_clone_property(struct property *prop, | |||
101 | return new_prop; | 101 | return new_prop; |
102 | } | 102 | } |
103 | 103 | ||
104 | static u32 find_aa_index(struct device_node *dr_node, | 104 | static bool find_aa_index(struct device_node *dr_node, |
105 | struct property *ala_prop, const u32 *lmb_assoc) | 105 | struct property *ala_prop, |
106 | const u32 *lmb_assoc, u32 *aa_index) | ||
106 | { | 107 | { |
107 | u32 *assoc_arrays; | 108 | u32 *assoc_arrays, new_prop_size; |
108 | u32 aa_index; | 109 | struct property *new_prop; |
109 | int aa_arrays, aa_array_entries, aa_array_sz; | 110 | int aa_arrays, aa_array_entries, aa_array_sz; |
110 | int i, index; | 111 | int i, index; |
111 | 112 | ||
@@ -121,54 +122,48 @@ static u32 find_aa_index(struct device_node *dr_node, | |||
121 | aa_array_entries = be32_to_cpu(assoc_arrays[1]); | 122 | aa_array_entries = be32_to_cpu(assoc_arrays[1]); |
122 | aa_array_sz = aa_array_entries * sizeof(u32); | 123 | aa_array_sz = aa_array_entries * sizeof(u32); |
123 | 124 | ||
124 | aa_index = -1; | ||
125 | for (i = 0; i < aa_arrays; i++) { | 125 | for (i = 0; i < aa_arrays; i++) { |
126 | index = (i * aa_array_entries) + 2; | 126 | index = (i * aa_array_entries) + 2; |
127 | 127 | ||
128 | if (memcmp(&assoc_arrays[index], &lmb_assoc[1], aa_array_sz)) | 128 | if (memcmp(&assoc_arrays[index], &lmb_assoc[1], aa_array_sz)) |
129 | continue; | 129 | continue; |
130 | 130 | ||
131 | aa_index = i; | 131 | *aa_index = i; |
132 | break; | 132 | return true; |
133 | } | 133 | } |
134 | 134 | ||
135 | if (aa_index == -1) { | 135 | new_prop_size = ala_prop->length + aa_array_sz; |
136 | struct property *new_prop; | 136 | new_prop = dlpar_clone_property(ala_prop, new_prop_size); |
137 | u32 new_prop_size; | 137 | if (!new_prop) |
138 | 138 | return false; | |
139 | new_prop_size = ala_prop->length + aa_array_sz; | ||
140 | new_prop = dlpar_clone_property(ala_prop, new_prop_size); | ||
141 | if (!new_prop) | ||
142 | return -1; | ||
143 | |||
144 | assoc_arrays = new_prop->value; | ||
145 | 139 | ||
146 | /* increment the number of entries in the lookup array */ | 140 | assoc_arrays = new_prop->value; |
147 | assoc_arrays[0] = cpu_to_be32(aa_arrays + 1); | ||
148 | 141 | ||
149 | /* copy the new associativity into the lookup array */ | 142 | /* increment the number of entries in the lookup array */ |
150 | index = aa_arrays * aa_array_entries + 2; | 143 | assoc_arrays[0] = cpu_to_be32(aa_arrays + 1); |
151 | memcpy(&assoc_arrays[index], &lmb_assoc[1], aa_array_sz); | ||
152 | 144 | ||
153 | of_update_property(dr_node, new_prop); | 145 | /* copy the new associativity into the lookup array */ |
146 | index = aa_arrays * aa_array_entries + 2; | ||
147 | memcpy(&assoc_arrays[index], &lmb_assoc[1], aa_array_sz); | ||
154 | 148 | ||
155 | /* | 149 | of_update_property(dr_node, new_prop); |
156 | * The associativity lookup array index for this lmb is | ||
157 | * number of entries - 1 since we added its associativity | ||
158 | * to the end of the lookup array. | ||
159 | */ | ||
160 | aa_index = be32_to_cpu(assoc_arrays[0]) - 1; | ||
161 | } | ||
162 | 150 | ||
163 | return aa_index; | 151 | /* |
152 | * The associativity lookup array index for this lmb is | ||
153 | * number of entries - 1 since we added its associativity | ||
154 | * to the end of the lookup array. | ||
155 | */ | ||
156 | *aa_index = be32_to_cpu(assoc_arrays[0]) - 1; | ||
157 | return true; | ||
164 | } | 158 | } |
165 | 159 | ||
166 | static u32 lookup_lmb_associativity_index(struct drmem_lmb *lmb) | 160 | static int update_lmb_associativity_index(struct drmem_lmb *lmb) |
167 | { | 161 | { |
168 | struct device_node *parent, *lmb_node, *dr_node; | 162 | struct device_node *parent, *lmb_node, *dr_node; |
169 | struct property *ala_prop; | 163 | struct property *ala_prop; |
170 | const u32 *lmb_assoc; | 164 | const u32 *lmb_assoc; |
171 | u32 aa_index; | 165 | u32 aa_index; |
166 | bool found; | ||
172 | 167 | ||
173 | parent = of_find_node_by_path("/"); | 168 | parent = of_find_node_by_path("/"); |
174 | if (!parent) | 169 | if (!parent) |
@@ -200,46 +195,17 @@ static u32 lookup_lmb_associativity_index(struct drmem_lmb *lmb) | |||
200 | return -ENODEV; | 195 | return -ENODEV; |
201 | } | 196 | } |
202 | 197 | ||
203 | aa_index = find_aa_index(dr_node, ala_prop, lmb_assoc); | 198 | found = find_aa_index(dr_node, ala_prop, lmb_assoc, &aa_index); |
204 | 199 | ||
205 | dlpar_free_cc_nodes(lmb_node); | 200 | dlpar_free_cc_nodes(lmb_node); |
206 | return aa_index; | ||
207 | } | ||
208 | 201 | ||
209 | static int dlpar_add_device_tree_lmb(struct drmem_lmb *lmb) | 202 | if (!found) { |
210 | { | 203 | pr_err("Could not find LMB associativity\n"); |
211 | int rc, aa_index; | 204 | return -1; |
212 | |||
213 | lmb->flags |= DRCONF_MEM_ASSIGNED; | ||
214 | |||
215 | aa_index = lookup_lmb_associativity_index(lmb); | ||
216 | if (aa_index < 0) { | ||
217 | pr_err("Couldn't find associativity index for drc index %x\n", | ||
218 | lmb->drc_index); | ||
219 | return aa_index; | ||
220 | } | 205 | } |
221 | 206 | ||
222 | lmb->aa_index = aa_index; | 207 | lmb->aa_index = aa_index; |
223 | 208 | return 0; | |
224 | rtas_hp_event = true; | ||
225 | rc = drmem_update_dt(); | ||
226 | rtas_hp_event = false; | ||
227 | |||
228 | return rc; | ||
229 | } | ||
230 | |||
231 | static int dlpar_remove_device_tree_lmb(struct drmem_lmb *lmb) | ||
232 | { | ||
233 | int rc; | ||
234 | |||
235 | lmb->flags &= ~DRCONF_MEM_ASSIGNED; | ||
236 | lmb->aa_index = 0xffffffff; | ||
237 | |||
238 | rtas_hp_event = true; | ||
239 | rc = drmem_update_dt(); | ||
240 | rtas_hp_event = false; | ||
241 | |||
242 | return rc; | ||
243 | } | 209 | } |
244 | 210 | ||
245 | static struct memory_block *lmb_to_memblock(struct drmem_lmb *lmb) | 211 | static struct memory_block *lmb_to_memblock(struct drmem_lmb *lmb) |
@@ -428,7 +394,9 @@ static int dlpar_remove_lmb(struct drmem_lmb *lmb) | |||
428 | /* Update memory regions for memory remove */ | 394 | /* Update memory regions for memory remove */ |
429 | memblock_remove(lmb->base_addr, block_sz); | 395 | memblock_remove(lmb->base_addr, block_sz); |
430 | 396 | ||
431 | dlpar_remove_device_tree_lmb(lmb); | 397 | invalidate_lmb_associativity_index(lmb); |
398 | lmb->flags &= ~DRCONF_MEM_ASSIGNED; | ||
399 | |||
432 | return 0; | 400 | return 0; |
433 | } | 401 | } |
434 | 402 | ||
@@ -688,10 +656,8 @@ static int dlpar_add_lmb(struct drmem_lmb *lmb) | |||
688 | if (lmb->flags & DRCONF_MEM_ASSIGNED) | 656 | if (lmb->flags & DRCONF_MEM_ASSIGNED) |
689 | return -EINVAL; | 657 | return -EINVAL; |
690 | 658 | ||
691 | rc = dlpar_add_device_tree_lmb(lmb); | 659 | rc = update_lmb_associativity_index(lmb); |
692 | if (rc) { | 660 | if (rc) { |
693 | pr_err("Couldn't update device tree for drc index %x\n", | ||
694 | lmb->drc_index); | ||
695 | dlpar_release_drc(lmb->drc_index); | 661 | dlpar_release_drc(lmb->drc_index); |
696 | return rc; | 662 | return rc; |
697 | } | 663 | } |
@@ -704,14 +670,14 @@ static int dlpar_add_lmb(struct drmem_lmb *lmb) | |||
704 | /* Add the memory */ | 670 | /* Add the memory */ |
705 | rc = add_memory(nid, lmb->base_addr, block_sz); | 671 | rc = add_memory(nid, lmb->base_addr, block_sz); |
706 | if (rc) { | 672 | if (rc) { |
707 | dlpar_remove_device_tree_lmb(lmb); | 673 | invalidate_lmb_associativity_index(lmb); |
708 | return rc; | 674 | return rc; |
709 | } | 675 | } |
710 | 676 | ||
711 | rc = dlpar_online_lmb(lmb); | 677 | rc = dlpar_online_lmb(lmb); |
712 | if (rc) { | 678 | if (rc) { |
713 | remove_memory(nid, lmb->base_addr, block_sz); | 679 | remove_memory(nid, lmb->base_addr, block_sz); |
714 | dlpar_remove_device_tree_lmb(lmb); | 680 | invalidate_lmb_associativity_index(lmb); |
715 | } else { | 681 | } else { |
716 | lmb->flags |= DRCONF_MEM_ASSIGNED; | 682 | lmb->flags |= DRCONF_MEM_ASSIGNED; |
717 | } | 683 | } |
@@ -958,6 +924,12 @@ int dlpar_memory(struct pseries_hp_errorlog *hp_elog) | |||
958 | break; | 924 | break; |
959 | } | 925 | } |
960 | 926 | ||
927 | if (!rc) { | ||
928 | rtas_hp_event = true; | ||
929 | rc = drmem_update_dt(); | ||
930 | rtas_hp_event = false; | ||
931 | } | ||
932 | |||
961 | unlock_device_hotplug(); | 933 | unlock_device_hotplug(); |
962 | return rc; | 934 | return rc; |
963 | } | 935 | } |
diff --git a/arch/powerpc/platforms/pseries/ibmebus.c b/arch/powerpc/platforms/pseries/ibmebus.c index c7c1140c13b6..5b4a56131904 100644 --- a/arch/powerpc/platforms/pseries/ibmebus.c +++ b/arch/powerpc/platforms/pseries/ibmebus.c | |||
@@ -404,7 +404,7 @@ static ssize_t name_show(struct device *dev, | |||
404 | struct platform_device *ofdev; | 404 | struct platform_device *ofdev; |
405 | 405 | ||
406 | ofdev = to_platform_device(dev); | 406 | ofdev = to_platform_device(dev); |
407 | return sprintf(buf, "%s\n", ofdev->dev.of_node->name); | 407 | return sprintf(buf, "%pOFn\n", ofdev->dev.of_node); |
408 | } | 408 | } |
409 | static DEVICE_ATTR_RO(name); | 409 | static DEVICE_ATTR_RO(name); |
410 | 410 | ||
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index d3992ced0782..32d4452973e7 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c | |||
@@ -48,6 +48,7 @@ | |||
48 | #include <asm/kexec.h> | 48 | #include <asm/kexec.h> |
49 | #include <asm/fadump.h> | 49 | #include <asm/fadump.h> |
50 | #include <asm/asm-prototypes.h> | 50 | #include <asm/asm-prototypes.h> |
51 | #include <asm/debugfs.h> | ||
51 | 52 | ||
52 | #include "pseries.h" | 53 | #include "pseries.h" |
53 | 54 | ||
@@ -417,6 +418,79 @@ static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long vpn, | |||
417 | BUG_ON(lpar_rc != H_SUCCESS); | 418 | BUG_ON(lpar_rc != H_SUCCESS); |
418 | } | 419 | } |
419 | 420 | ||
421 | |||
422 | /* | ||
423 | * As defined in the PAPR's section 14.5.4.1.8 | ||
424 | * The control mask doesn't include the returned reference and change bit from | ||
425 | * the processed PTE. | ||
426 | */ | ||
427 | #define HBLKR_AVPN 0x0100000000000000UL | ||
428 | #define HBLKR_CTRL_MASK 0xf800000000000000UL | ||
429 | #define HBLKR_CTRL_SUCCESS 0x8000000000000000UL | ||
430 | #define HBLKR_CTRL_ERRNOTFOUND 0x8800000000000000UL | ||
431 | #define HBLKR_CTRL_ERRBUSY 0xa000000000000000UL | ||
432 | |||
433 | /** | ||
434 | * H_BLOCK_REMOVE caller. | ||
435 | * @idx should point to the latest @param entry set with a PTEX. | ||
436 | * If PTE cannot be processed because another CPUs has already locked that | ||
437 | * group, those entries are put back in @param starting at index 1. | ||
438 | * If entries has to be retried and @retry_busy is set to true, these entries | ||
439 | * are retried until success. If @retry_busy is set to false, the returned | ||
440 | * is the number of entries yet to process. | ||
441 | */ | ||
442 | static unsigned long call_block_remove(unsigned long idx, unsigned long *param, | ||
443 | bool retry_busy) | ||
444 | { | ||
445 | unsigned long i, rc, new_idx; | ||
446 | unsigned long retbuf[PLPAR_HCALL9_BUFSIZE]; | ||
447 | |||
448 | if (idx < 2) { | ||
449 | pr_warn("Unexpected empty call to H_BLOCK_REMOVE"); | ||
450 | return 0; | ||
451 | } | ||
452 | again: | ||
453 | new_idx = 0; | ||
454 | if (idx > PLPAR_HCALL9_BUFSIZE) { | ||
455 | pr_err("Too many PTEs (%lu) for H_BLOCK_REMOVE", idx); | ||
456 | idx = PLPAR_HCALL9_BUFSIZE; | ||
457 | } else if (idx < PLPAR_HCALL9_BUFSIZE) | ||
458 | param[idx] = HBR_END; | ||
459 | |||
460 | rc = plpar_hcall9(H_BLOCK_REMOVE, retbuf, | ||
461 | param[0], /* AVA */ | ||
462 | param[1], param[2], param[3], param[4], /* TS0-7 */ | ||
463 | param[5], param[6], param[7], param[8]); | ||
464 | if (rc == H_SUCCESS) | ||
465 | return 0; | ||
466 | |||
467 | BUG_ON(rc != H_PARTIAL); | ||
468 | |||
469 | /* Check that the unprocessed entries were 'not found' or 'busy' */ | ||
470 | for (i = 0; i < idx-1; i++) { | ||
471 | unsigned long ctrl = retbuf[i] & HBLKR_CTRL_MASK; | ||
472 | |||
473 | if (ctrl == HBLKR_CTRL_ERRBUSY) { | ||
474 | param[++new_idx] = param[i+1]; | ||
475 | continue; | ||
476 | } | ||
477 | |||
478 | BUG_ON(ctrl != HBLKR_CTRL_SUCCESS | ||
479 | && ctrl != HBLKR_CTRL_ERRNOTFOUND); | ||
480 | } | ||
481 | |||
482 | /* | ||
483 | * If there were entries found busy, retry these entries if requested, | ||
484 | * of if all the entries have to be retried. | ||
485 | */ | ||
486 | if (new_idx && (retry_busy || new_idx == (PLPAR_HCALL9_BUFSIZE-1))) { | ||
487 | idx = new_idx + 1; | ||
488 | goto again; | ||
489 | } | ||
490 | |||
491 | return new_idx; | ||
492 | } | ||
493 | |||
420 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE | 494 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE |
421 | /* | 495 | /* |
422 | * Limit iterations holding pSeries_lpar_tlbie_lock to 3. We also need | 496 | * Limit iterations holding pSeries_lpar_tlbie_lock to 3. We also need |
@@ -424,17 +498,57 @@ static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long vpn, | |||
424 | */ | 498 | */ |
425 | #define PPC64_HUGE_HPTE_BATCH 12 | 499 | #define PPC64_HUGE_HPTE_BATCH 12 |
426 | 500 | ||
427 | static void __pSeries_lpar_hugepage_invalidate(unsigned long *slot, | 501 | static void hugepage_block_invalidate(unsigned long *slot, unsigned long *vpn, |
428 | unsigned long *vpn, int count, | 502 | int count, int psize, int ssize) |
429 | int psize, int ssize) | ||
430 | { | 503 | { |
431 | unsigned long param[PLPAR_HCALL9_BUFSIZE]; | 504 | unsigned long param[PLPAR_HCALL9_BUFSIZE]; |
432 | int i = 0, pix = 0, rc; | 505 | unsigned long shift, current_vpgb, vpgb; |
433 | unsigned long flags = 0; | 506 | int i, pix = 0; |
434 | int lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE); | ||
435 | 507 | ||
436 | if (lock_tlbie) | 508 | shift = mmu_psize_defs[psize].shift; |
437 | spin_lock_irqsave(&pSeries_lpar_tlbie_lock, flags); | 509 | |
510 | for (i = 0; i < count; i++) { | ||
511 | /* | ||
512 | * Shifting 3 bits more on the right to get a | ||
513 | * 8 pages aligned virtual addresse. | ||
514 | */ | ||
515 | vpgb = (vpn[i] >> (shift - VPN_SHIFT + 3)); | ||
516 | if (!pix || vpgb != current_vpgb) { | ||
517 | /* | ||
518 | * Need to start a new 8 pages block, flush | ||
519 | * the current one if needed. | ||
520 | */ | ||
521 | if (pix) | ||
522 | (void)call_block_remove(pix, param, true); | ||
523 | current_vpgb = vpgb; | ||
524 | param[0] = hpte_encode_avpn(vpn[i], psize, ssize); | ||
525 | pix = 1; | ||
526 | } | ||
527 | |||
528 | param[pix++] = HBR_REQUEST | HBLKR_AVPN | slot[i]; | ||
529 | if (pix == PLPAR_HCALL9_BUFSIZE) { | ||
530 | pix = call_block_remove(pix, param, false); | ||
531 | /* | ||
532 | * pix = 0 means that all the entries were | ||
533 | * removed, we can start a new block. | ||
534 | * Otherwise, this means that there are entries | ||
535 | * to retry, and pix points to latest one, so | ||
536 | * we should increment it and try to continue | ||
537 | * the same block. | ||
538 | */ | ||
539 | if (pix) | ||
540 | pix++; | ||
541 | } | ||
542 | } | ||
543 | if (pix) | ||
544 | (void)call_block_remove(pix, param, true); | ||
545 | } | ||
546 | |||
547 | static void hugepage_bulk_invalidate(unsigned long *slot, unsigned long *vpn, | ||
548 | int count, int psize, int ssize) | ||
549 | { | ||
550 | unsigned long param[PLPAR_HCALL9_BUFSIZE]; | ||
551 | int i = 0, pix = 0, rc; | ||
438 | 552 | ||
439 | for (i = 0; i < count; i++) { | 553 | for (i = 0; i < count; i++) { |
440 | 554 | ||
@@ -462,6 +576,23 @@ static void __pSeries_lpar_hugepage_invalidate(unsigned long *slot, | |||
462 | param[6], param[7]); | 576 | param[6], param[7]); |
463 | BUG_ON(rc != H_SUCCESS); | 577 | BUG_ON(rc != H_SUCCESS); |
464 | } | 578 | } |
579 | } | ||
580 | |||
581 | static inline void __pSeries_lpar_hugepage_invalidate(unsigned long *slot, | ||
582 | unsigned long *vpn, | ||
583 | int count, int psize, | ||
584 | int ssize) | ||
585 | { | ||
586 | unsigned long flags = 0; | ||
587 | int lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE); | ||
588 | |||
589 | if (lock_tlbie) | ||
590 | spin_lock_irqsave(&pSeries_lpar_tlbie_lock, flags); | ||
591 | |||
592 | if (firmware_has_feature(FW_FEATURE_BLOCK_REMOVE)) | ||
593 | hugepage_block_invalidate(slot, vpn, count, psize, ssize); | ||
594 | else | ||
595 | hugepage_bulk_invalidate(slot, vpn, count, psize, ssize); | ||
465 | 596 | ||
466 | if (lock_tlbie) | 597 | if (lock_tlbie) |
467 | spin_unlock_irqrestore(&pSeries_lpar_tlbie_lock, flags); | 598 | spin_unlock_irqrestore(&pSeries_lpar_tlbie_lock, flags); |
@@ -546,6 +677,86 @@ static int pSeries_lpar_hpte_removebolted(unsigned long ea, | |||
546 | return 0; | 677 | return 0; |
547 | } | 678 | } |
548 | 679 | ||
680 | |||
681 | static inline unsigned long compute_slot(real_pte_t pte, | ||
682 | unsigned long vpn, | ||
683 | unsigned long index, | ||
684 | unsigned long shift, | ||
685 | int ssize) | ||
686 | { | ||
687 | unsigned long slot, hash, hidx; | ||
688 | |||
689 | hash = hpt_hash(vpn, shift, ssize); | ||
690 | hidx = __rpte_to_hidx(pte, index); | ||
691 | if (hidx & _PTEIDX_SECONDARY) | ||
692 | hash = ~hash; | ||
693 | slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; | ||
694 | slot += hidx & _PTEIDX_GROUP_IX; | ||
695 | return slot; | ||
696 | } | ||
697 | |||
698 | /** | ||
699 | * The hcall H_BLOCK_REMOVE implies that the virtual pages to processed are | ||
700 | * "all within the same naturally aligned 8 page virtual address block". | ||
701 | */ | ||
702 | static void do_block_remove(unsigned long number, struct ppc64_tlb_batch *batch, | ||
703 | unsigned long *param) | ||
704 | { | ||
705 | unsigned long vpn; | ||
706 | unsigned long i, pix = 0; | ||
707 | unsigned long index, shift, slot, current_vpgb, vpgb; | ||
708 | real_pte_t pte; | ||
709 | int psize, ssize; | ||
710 | |||
711 | psize = batch->psize; | ||
712 | ssize = batch->ssize; | ||
713 | |||
714 | for (i = 0; i < number; i++) { | ||
715 | vpn = batch->vpn[i]; | ||
716 | pte = batch->pte[i]; | ||
717 | pte_iterate_hashed_subpages(pte, psize, vpn, index, shift) { | ||
718 | /* | ||
719 | * Shifting 3 bits more on the right to get a | ||
720 | * 8 pages aligned virtual addresse. | ||
721 | */ | ||
722 | vpgb = (vpn >> (shift - VPN_SHIFT + 3)); | ||
723 | if (!pix || vpgb != current_vpgb) { | ||
724 | /* | ||
725 | * Need to start a new 8 pages block, flush | ||
726 | * the current one if needed. | ||
727 | */ | ||
728 | if (pix) | ||
729 | (void)call_block_remove(pix, param, | ||
730 | true); | ||
731 | current_vpgb = vpgb; | ||
732 | param[0] = hpte_encode_avpn(vpn, psize, | ||
733 | ssize); | ||
734 | pix = 1; | ||
735 | } | ||
736 | |||
737 | slot = compute_slot(pte, vpn, index, shift, ssize); | ||
738 | param[pix++] = HBR_REQUEST | HBLKR_AVPN | slot; | ||
739 | |||
740 | if (pix == PLPAR_HCALL9_BUFSIZE) { | ||
741 | pix = call_block_remove(pix, param, false); | ||
742 | /* | ||
743 | * pix = 0 means that all the entries were | ||
744 | * removed, we can start a new block. | ||
745 | * Otherwise, this means that there are entries | ||
746 | * to retry, and pix points to latest one, so | ||
747 | * we should increment it and try to continue | ||
748 | * the same block. | ||
749 | */ | ||
750 | if (pix) | ||
751 | pix++; | ||
752 | } | ||
753 | } pte_iterate_hashed_end(); | ||
754 | } | ||
755 | |||
756 | if (pix) | ||
757 | (void)call_block_remove(pix, param, true); | ||
758 | } | ||
759 | |||
549 | /* | 760 | /* |
550 | * Take a spinlock around flushes to avoid bouncing the hypervisor tlbie | 761 | * Take a spinlock around flushes to avoid bouncing the hypervisor tlbie |
551 | * lock. | 762 | * lock. |
@@ -558,13 +769,18 @@ static void pSeries_lpar_flush_hash_range(unsigned long number, int local) | |||
558 | struct ppc64_tlb_batch *batch = this_cpu_ptr(&ppc64_tlb_batch); | 769 | struct ppc64_tlb_batch *batch = this_cpu_ptr(&ppc64_tlb_batch); |
559 | int lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE); | 770 | int lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE); |
560 | unsigned long param[PLPAR_HCALL9_BUFSIZE]; | 771 | unsigned long param[PLPAR_HCALL9_BUFSIZE]; |
561 | unsigned long hash, index, shift, hidx, slot; | 772 | unsigned long index, shift, slot; |
562 | real_pte_t pte; | 773 | real_pte_t pte; |
563 | int psize, ssize; | 774 | int psize, ssize; |
564 | 775 | ||
565 | if (lock_tlbie) | 776 | if (lock_tlbie) |
566 | spin_lock_irqsave(&pSeries_lpar_tlbie_lock, flags); | 777 | spin_lock_irqsave(&pSeries_lpar_tlbie_lock, flags); |
567 | 778 | ||
779 | if (firmware_has_feature(FW_FEATURE_BLOCK_REMOVE)) { | ||
780 | do_block_remove(number, batch, param); | ||
781 | goto out; | ||
782 | } | ||
783 | |||
568 | psize = batch->psize; | 784 | psize = batch->psize; |
569 | ssize = batch->ssize; | 785 | ssize = batch->ssize; |
570 | pix = 0; | 786 | pix = 0; |
@@ -572,12 +788,7 @@ static void pSeries_lpar_flush_hash_range(unsigned long number, int local) | |||
572 | vpn = batch->vpn[i]; | 788 | vpn = batch->vpn[i]; |
573 | pte = batch->pte[i]; | 789 | pte = batch->pte[i]; |
574 | pte_iterate_hashed_subpages(pte, psize, vpn, index, shift) { | 790 | pte_iterate_hashed_subpages(pte, psize, vpn, index, shift) { |
575 | hash = hpt_hash(vpn, shift, ssize); | 791 | slot = compute_slot(pte, vpn, index, shift, ssize); |
576 | hidx = __rpte_to_hidx(pte, index); | ||
577 | if (hidx & _PTEIDX_SECONDARY) | ||
578 | hash = ~hash; | ||
579 | slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; | ||
580 | slot += hidx & _PTEIDX_GROUP_IX; | ||
581 | if (!firmware_has_feature(FW_FEATURE_BULK_REMOVE)) { | 792 | if (!firmware_has_feature(FW_FEATURE_BULK_REMOVE)) { |
582 | /* | 793 | /* |
583 | * lpar doesn't use the passed actual page size | 794 | * lpar doesn't use the passed actual page size |
@@ -608,6 +819,7 @@ static void pSeries_lpar_flush_hash_range(unsigned long number, int local) | |||
608 | BUG_ON(rc != H_SUCCESS); | 819 | BUG_ON(rc != H_SUCCESS); |
609 | } | 820 | } |
610 | 821 | ||
822 | out: | ||
611 | if (lock_tlbie) | 823 | if (lock_tlbie) |
612 | spin_unlock_irqrestore(&pSeries_lpar_tlbie_lock, flags); | 824 | spin_unlock_irqrestore(&pSeries_lpar_tlbie_lock, flags); |
613 | } | 825 | } |
@@ -1028,3 +1240,56 @@ static int __init reserve_vrma_context_id(void) | |||
1028 | return 0; | 1240 | return 0; |
1029 | } | 1241 | } |
1030 | machine_device_initcall(pseries, reserve_vrma_context_id); | 1242 | machine_device_initcall(pseries, reserve_vrma_context_id); |
1243 | |||
1244 | #ifdef CONFIG_DEBUG_FS | ||
1245 | /* debugfs file interface for vpa data */ | ||
1246 | static ssize_t vpa_file_read(struct file *filp, char __user *buf, size_t len, | ||
1247 | loff_t *pos) | ||
1248 | { | ||
1249 | int cpu = (long)filp->private_data; | ||
1250 | struct lppaca *lppaca = &lppaca_of(cpu); | ||
1251 | |||
1252 | return simple_read_from_buffer(buf, len, pos, lppaca, | ||
1253 | sizeof(struct lppaca)); | ||
1254 | } | ||
1255 | |||
1256 | static const struct file_operations vpa_fops = { | ||
1257 | .open = simple_open, | ||
1258 | .read = vpa_file_read, | ||
1259 | .llseek = default_llseek, | ||
1260 | }; | ||
1261 | |||
1262 | static int __init vpa_debugfs_init(void) | ||
1263 | { | ||
1264 | char name[16]; | ||
1265 | long i; | ||
1266 | static struct dentry *vpa_dir; | ||
1267 | |||
1268 | if (!firmware_has_feature(FW_FEATURE_SPLPAR)) | ||
1269 | return 0; | ||
1270 | |||
1271 | vpa_dir = debugfs_create_dir("vpa", powerpc_debugfs_root); | ||
1272 | if (!vpa_dir) { | ||
1273 | pr_warn("%s: can't create vpa root dir\n", __func__); | ||
1274 | return -ENOMEM; | ||
1275 | } | ||
1276 | |||
1277 | /* set up the per-cpu vpa file*/ | ||
1278 | for_each_possible_cpu(i) { | ||
1279 | struct dentry *d; | ||
1280 | |||
1281 | sprintf(name, "cpu-%ld", i); | ||
1282 | |||
1283 | d = debugfs_create_file(name, 0400, vpa_dir, (void *)i, | ||
1284 | &vpa_fops); | ||
1285 | if (!d) { | ||
1286 | pr_warn("%s: can't create per-cpu vpa file\n", | ||
1287 | __func__); | ||
1288 | return -ENOMEM; | ||
1289 | } | ||
1290 | } | ||
1291 | |||
1292 | return 0; | ||
1293 | } | ||
1294 | machine_arch_initcall(pseries, vpa_debugfs_init); | ||
1295 | #endif /* CONFIG_DEBUG_FS */ | ||
diff --git a/arch/powerpc/platforms/pseries/lparcfg.c b/arch/powerpc/platforms/pseries/lparcfg.c index 7c872dc01bdb..8bd590af488a 100644 --- a/arch/powerpc/platforms/pseries/lparcfg.c +++ b/arch/powerpc/platforms/pseries/lparcfg.c | |||
@@ -585,8 +585,7 @@ static ssize_t update_mpp(u64 *entitlement, u8 *weight) | |||
585 | static ssize_t lparcfg_write(struct file *file, const char __user * buf, | 585 | static ssize_t lparcfg_write(struct file *file, const char __user * buf, |
586 | size_t count, loff_t * off) | 586 | size_t count, loff_t * off) |
587 | { | 587 | { |
588 | int kbuf_sz = 64; | 588 | char kbuf[64]; |
589 | char kbuf[kbuf_sz]; | ||
590 | char *tmp; | 589 | char *tmp; |
591 | u64 new_entitled, *new_entitled_ptr = &new_entitled; | 590 | u64 new_entitled, *new_entitled_ptr = &new_entitled; |
592 | u8 new_weight, *new_weight_ptr = &new_weight; | 591 | u8 new_weight, *new_weight_ptr = &new_weight; |
@@ -595,7 +594,7 @@ static ssize_t lparcfg_write(struct file *file, const char __user * buf, | |||
595 | if (!firmware_has_feature(FW_FEATURE_SPLPAR)) | 594 | if (!firmware_has_feature(FW_FEATURE_SPLPAR)) |
596 | return -EINVAL; | 595 | return -EINVAL; |
597 | 596 | ||
598 | if (count > kbuf_sz) | 597 | if (count > sizeof(kbuf)) |
599 | return -EINVAL; | 598 | return -EINVAL; |
600 | 599 | ||
601 | if (copy_from_user(kbuf, buf, count)) | 600 | if (copy_from_user(kbuf, buf, count)) |
diff --git a/arch/powerpc/platforms/pseries/mobility.c b/arch/powerpc/platforms/pseries/mobility.c index f0e30dc94988..88925f8ca8a0 100644 --- a/arch/powerpc/platforms/pseries/mobility.c +++ b/arch/powerpc/platforms/pseries/mobility.c | |||
@@ -242,7 +242,7 @@ static int add_dt_node(__be32 parent_phandle, __be32 drc_index) | |||
242 | 242 | ||
243 | static void prrn_update_node(__be32 phandle) | 243 | static void prrn_update_node(__be32 phandle) |
244 | { | 244 | { |
245 | struct pseries_hp_errorlog *hp_elog; | 245 | struct pseries_hp_errorlog hp_elog; |
246 | struct device_node *dn; | 246 | struct device_node *dn; |
247 | 247 | ||
248 | /* | 248 | /* |
@@ -255,18 +255,12 @@ static void prrn_update_node(__be32 phandle) | |||
255 | return; | 255 | return; |
256 | } | 256 | } |
257 | 257 | ||
258 | hp_elog = kzalloc(sizeof(*hp_elog), GFP_KERNEL); | 258 | hp_elog.resource = PSERIES_HP_ELOG_RESOURCE_MEM; |
259 | if(!hp_elog) | 259 | hp_elog.action = PSERIES_HP_ELOG_ACTION_READD; |
260 | return; | 260 | hp_elog.id_type = PSERIES_HP_ELOG_ID_DRC_INDEX; |
261 | 261 | hp_elog._drc_u.drc_index = phandle; | |
262 | hp_elog->resource = PSERIES_HP_ELOG_RESOURCE_MEM; | ||
263 | hp_elog->action = PSERIES_HP_ELOG_ACTION_READD; | ||
264 | hp_elog->id_type = PSERIES_HP_ELOG_ID_DRC_INDEX; | ||
265 | hp_elog->_drc_u.drc_index = phandle; | ||
266 | |||
267 | queue_hotplug_event(hp_elog, NULL, NULL); | ||
268 | 262 | ||
269 | kfree(hp_elog); | 263 | handle_dlpar_errorlog(&hp_elog); |
270 | } | 264 | } |
271 | 265 | ||
272 | int pseries_devicetree_update(s32 scope) | 266 | int pseries_devicetree_update(s32 scope) |
@@ -366,6 +360,8 @@ static ssize_t migration_store(struct class *class, | |||
366 | if (rc) | 360 | if (rc) |
367 | return rc; | 361 | return rc; |
368 | 362 | ||
363 | stop_topology_update(); | ||
364 | |||
369 | do { | 365 | do { |
370 | rc = rtas_ibm_suspend_me(streamid); | 366 | rc = rtas_ibm_suspend_me(streamid); |
371 | if (rc == -EAGAIN) | 367 | if (rc == -EAGAIN) |
@@ -376,6 +372,9 @@ static ssize_t migration_store(struct class *class, | |||
376 | return rc; | 372 | return rc; |
377 | 373 | ||
378 | post_mobility_fixup(); | 374 | post_mobility_fixup(); |
375 | |||
376 | start_topology_update(); | ||
377 | |||
379 | return count; | 378 | return count; |
380 | } | 379 | } |
381 | 380 | ||
diff --git a/arch/powerpc/platforms/pseries/msi.c b/arch/powerpc/platforms/pseries/msi.c index b7496948129e..8011b4129e3a 100644 --- a/arch/powerpc/platforms/pseries/msi.c +++ b/arch/powerpc/platforms/pseries/msi.c | |||
@@ -203,7 +203,8 @@ static struct device_node *find_pe_dn(struct pci_dev *dev, int *total) | |||
203 | /* Get the top level device in the PE */ | 203 | /* Get the top level device in the PE */ |
204 | edev = pdn_to_eeh_dev(PCI_DN(dn)); | 204 | edev = pdn_to_eeh_dev(PCI_DN(dn)); |
205 | if (edev->pe) | 205 | if (edev->pe) |
206 | edev = list_first_entry(&edev->pe->edevs, struct eeh_dev, list); | 206 | edev = list_first_entry(&edev->pe->edevs, struct eeh_dev, |
207 | entry); | ||
207 | dn = pci_device_to_OF_node(edev->pdev); | 208 | dn = pci_device_to_OF_node(edev->pdev); |
208 | if (!dn) | 209 | if (!dn) |
209 | return NULL; | 210 | return NULL; |
diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c new file mode 100644 index 000000000000..ee9372b65ca5 --- /dev/null +++ b/arch/powerpc/platforms/pseries/papr_scm.c | |||
@@ -0,0 +1,345 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | |||
3 | #define pr_fmt(fmt) "papr-scm: " fmt | ||
4 | |||
5 | #include <linux/of.h> | ||
6 | #include <linux/kernel.h> | ||
7 | #include <linux/module.h> | ||
8 | #include <linux/ioport.h> | ||
9 | #include <linux/slab.h> | ||
10 | #include <linux/ndctl.h> | ||
11 | #include <linux/sched.h> | ||
12 | #include <linux/libnvdimm.h> | ||
13 | #include <linux/platform_device.h> | ||
14 | |||
15 | #include <asm/plpar_wrappers.h> | ||
16 | |||
17 | #define BIND_ANY_ADDR (~0ul) | ||
18 | |||
19 | #define PAPR_SCM_DIMM_CMD_MASK \ | ||
20 | ((1ul << ND_CMD_GET_CONFIG_SIZE) | \ | ||
21 | (1ul << ND_CMD_GET_CONFIG_DATA) | \ | ||
22 | (1ul << ND_CMD_SET_CONFIG_DATA)) | ||
23 | |||
24 | struct papr_scm_priv { | ||
25 | struct platform_device *pdev; | ||
26 | struct device_node *dn; | ||
27 | uint32_t drc_index; | ||
28 | uint64_t blocks; | ||
29 | uint64_t block_size; | ||
30 | int metadata_size; | ||
31 | |||
32 | uint64_t bound_addr; | ||
33 | |||
34 | struct nvdimm_bus_descriptor bus_desc; | ||
35 | struct nvdimm_bus *bus; | ||
36 | struct nvdimm *nvdimm; | ||
37 | struct resource res; | ||
38 | struct nd_region *region; | ||
39 | struct nd_interleave_set nd_set; | ||
40 | }; | ||
41 | |||
42 | static int drc_pmem_bind(struct papr_scm_priv *p) | ||
43 | { | ||
44 | unsigned long ret[PLPAR_HCALL_BUFSIZE]; | ||
45 | uint64_t rc, token; | ||
46 | |||
47 | /* | ||
48 | * When the hypervisor cannot map all the requested memory in a single | ||
49 | * hcall it returns H_BUSY and we call again with the token until | ||
50 | * we get H_SUCCESS. Aborting the retry loop before getting H_SUCCESS | ||
51 | * leave the system in an undefined state, so we wait. | ||
52 | */ | ||
53 | token = 0; | ||
54 | |||
55 | do { | ||
56 | rc = plpar_hcall(H_SCM_BIND_MEM, ret, p->drc_index, 0, | ||
57 | p->blocks, BIND_ANY_ADDR, token); | ||
58 | token = be64_to_cpu(ret[0]); | ||
59 | cond_resched(); | ||
60 | } while (rc == H_BUSY); | ||
61 | |||
62 | if (rc) { | ||
63 | dev_err(&p->pdev->dev, "bind err: %lld\n", rc); | ||
64 | return -ENXIO; | ||
65 | } | ||
66 | |||
67 | p->bound_addr = be64_to_cpu(ret[1]); | ||
68 | |||
69 | dev_dbg(&p->pdev->dev, "bound drc %x to %pR\n", p->drc_index, &p->res); | ||
70 | |||
71 | return 0; | ||
72 | } | ||
73 | |||
74 | static int drc_pmem_unbind(struct papr_scm_priv *p) | ||
75 | { | ||
76 | unsigned long ret[PLPAR_HCALL_BUFSIZE]; | ||
77 | uint64_t rc, token; | ||
78 | |||
79 | token = 0; | ||
80 | |||
81 | /* NB: unbind has the same retry requirements mentioned above */ | ||
82 | do { | ||
83 | rc = plpar_hcall(H_SCM_UNBIND_MEM, ret, p->drc_index, | ||
84 | p->bound_addr, p->blocks, token); | ||
85 | token = be64_to_cpu(ret); | ||
86 | cond_resched(); | ||
87 | } while (rc == H_BUSY); | ||
88 | |||
89 | if (rc) | ||
90 | dev_err(&p->pdev->dev, "unbind error: %lld\n", rc); | ||
91 | |||
92 | return !!rc; | ||
93 | } | ||
94 | |||
95 | static int papr_scm_meta_get(struct papr_scm_priv *p, | ||
96 | struct nd_cmd_get_config_data_hdr *hdr) | ||
97 | { | ||
98 | unsigned long data[PLPAR_HCALL_BUFSIZE]; | ||
99 | int64_t ret; | ||
100 | |||
101 | if (hdr->in_offset >= p->metadata_size || hdr->in_length != 1) | ||
102 | return -EINVAL; | ||
103 | |||
104 | ret = plpar_hcall(H_SCM_READ_METADATA, data, p->drc_index, | ||
105 | hdr->in_offset, 1); | ||
106 | |||
107 | if (ret == H_PARAMETER) /* bad DRC index */ | ||
108 | return -ENODEV; | ||
109 | if (ret) | ||
110 | return -EINVAL; /* other invalid parameter */ | ||
111 | |||
112 | hdr->out_buf[0] = data[0] & 0xff; | ||
113 | |||
114 | return 0; | ||
115 | } | ||
116 | |||
117 | static int papr_scm_meta_set(struct papr_scm_priv *p, | ||
118 | struct nd_cmd_set_config_hdr *hdr) | ||
119 | { | ||
120 | int64_t ret; | ||
121 | |||
122 | if (hdr->in_offset >= p->metadata_size || hdr->in_length != 1) | ||
123 | return -EINVAL; | ||
124 | |||
125 | ret = plpar_hcall_norets(H_SCM_WRITE_METADATA, | ||
126 | p->drc_index, hdr->in_offset, hdr->in_buf[0], 1); | ||
127 | |||
128 | if (ret == H_PARAMETER) /* bad DRC index */ | ||
129 | return -ENODEV; | ||
130 | if (ret) | ||
131 | return -EINVAL; /* other invalid parameter */ | ||
132 | |||
133 | return 0; | ||
134 | } | ||
135 | |||
136 | int papr_scm_ndctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm, | ||
137 | unsigned int cmd, void *buf, unsigned int buf_len, int *cmd_rc) | ||
138 | { | ||
139 | struct nd_cmd_get_config_size *get_size_hdr; | ||
140 | struct papr_scm_priv *p; | ||
141 | |||
142 | /* Only dimm-specific calls are supported atm */ | ||
143 | if (!nvdimm) | ||
144 | return -EINVAL; | ||
145 | |||
146 | p = nvdimm_provider_data(nvdimm); | ||
147 | |||
148 | switch (cmd) { | ||
149 | case ND_CMD_GET_CONFIG_SIZE: | ||
150 | get_size_hdr = buf; | ||
151 | |||
152 | get_size_hdr->status = 0; | ||
153 | get_size_hdr->max_xfer = 1; | ||
154 | get_size_hdr->config_size = p->metadata_size; | ||
155 | *cmd_rc = 0; | ||
156 | break; | ||
157 | |||
158 | case ND_CMD_GET_CONFIG_DATA: | ||
159 | *cmd_rc = papr_scm_meta_get(p, buf); | ||
160 | break; | ||
161 | |||
162 | case ND_CMD_SET_CONFIG_DATA: | ||
163 | *cmd_rc = papr_scm_meta_set(p, buf); | ||
164 | break; | ||
165 | |||
166 | default: | ||
167 | return -EINVAL; | ||
168 | } | ||
169 | |||
170 | dev_dbg(&p->pdev->dev, "returned with cmd_rc = %d\n", *cmd_rc); | ||
171 | |||
172 | return 0; | ||
173 | } | ||
174 | |||
175 | static const struct attribute_group *region_attr_groups[] = { | ||
176 | &nd_region_attribute_group, | ||
177 | &nd_device_attribute_group, | ||
178 | &nd_mapping_attribute_group, | ||
179 | &nd_numa_attribute_group, | ||
180 | NULL, | ||
181 | }; | ||
182 | |||
183 | static const struct attribute_group *bus_attr_groups[] = { | ||
184 | &nvdimm_bus_attribute_group, | ||
185 | NULL, | ||
186 | }; | ||
187 | |||
188 | static const struct attribute_group *papr_scm_dimm_groups[] = { | ||
189 | &nvdimm_attribute_group, | ||
190 | &nd_device_attribute_group, | ||
191 | NULL, | ||
192 | }; | ||
193 | |||
194 | static int papr_scm_nvdimm_init(struct papr_scm_priv *p) | ||
195 | { | ||
196 | struct device *dev = &p->pdev->dev; | ||
197 | struct nd_mapping_desc mapping; | ||
198 | struct nd_region_desc ndr_desc; | ||
199 | unsigned long dimm_flags; | ||
200 | |||
201 | p->bus_desc.ndctl = papr_scm_ndctl; | ||
202 | p->bus_desc.module = THIS_MODULE; | ||
203 | p->bus_desc.of_node = p->pdev->dev.of_node; | ||
204 | p->bus_desc.attr_groups = bus_attr_groups; | ||
205 | p->bus_desc.provider_name = kstrdup(p->pdev->name, GFP_KERNEL); | ||
206 | |||
207 | if (!p->bus_desc.provider_name) | ||
208 | return -ENOMEM; | ||
209 | |||
210 | p->bus = nvdimm_bus_register(NULL, &p->bus_desc); | ||
211 | if (!p->bus) { | ||
212 | dev_err(dev, "Error creating nvdimm bus %pOF\n", p->dn); | ||
213 | return -ENXIO; | ||
214 | } | ||
215 | |||
216 | dimm_flags = 0; | ||
217 | set_bit(NDD_ALIASING, &dimm_flags); | ||
218 | |||
219 | p->nvdimm = nvdimm_create(p->bus, p, papr_scm_dimm_groups, | ||
220 | dimm_flags, PAPR_SCM_DIMM_CMD_MASK, 0, NULL); | ||
221 | if (!p->nvdimm) { | ||
222 | dev_err(dev, "Error creating DIMM object for %pOF\n", p->dn); | ||
223 | goto err; | ||
224 | } | ||
225 | |||
226 | /* now add the region */ | ||
227 | |||
228 | memset(&mapping, 0, sizeof(mapping)); | ||
229 | mapping.nvdimm = p->nvdimm; | ||
230 | mapping.start = 0; | ||
231 | mapping.size = p->blocks * p->block_size; // XXX: potential overflow? | ||
232 | |||
233 | memset(&ndr_desc, 0, sizeof(ndr_desc)); | ||
234 | ndr_desc.attr_groups = region_attr_groups; | ||
235 | ndr_desc.numa_node = dev_to_node(&p->pdev->dev); | ||
236 | ndr_desc.res = &p->res; | ||
237 | ndr_desc.of_node = p->dn; | ||
238 | ndr_desc.provider_data = p; | ||
239 | ndr_desc.mapping = &mapping; | ||
240 | ndr_desc.num_mappings = 1; | ||
241 | ndr_desc.nd_set = &p->nd_set; | ||
242 | set_bit(ND_REGION_PAGEMAP, &ndr_desc.flags); | ||
243 | |||
244 | p->region = nvdimm_pmem_region_create(p->bus, &ndr_desc); | ||
245 | if (!p->region) { | ||
246 | dev_err(dev, "Error registering region %pR from %pOF\n", | ||
247 | ndr_desc.res, p->dn); | ||
248 | goto err; | ||
249 | } | ||
250 | |||
251 | return 0; | ||
252 | |||
253 | err: nvdimm_bus_unregister(p->bus); | ||
254 | kfree(p->bus_desc.provider_name); | ||
255 | return -ENXIO; | ||
256 | } | ||
257 | |||
258 | static int papr_scm_probe(struct platform_device *pdev) | ||
259 | { | ||
260 | uint32_t drc_index, metadata_size, unit_cap[2]; | ||
261 | struct device_node *dn = pdev->dev.of_node; | ||
262 | struct papr_scm_priv *p; | ||
263 | int rc; | ||
264 | |||
265 | /* check we have all the required DT properties */ | ||
266 | if (of_property_read_u32(dn, "ibm,my-drc-index", &drc_index)) { | ||
267 | dev_err(&pdev->dev, "%pOF: missing drc-index!\n", dn); | ||
268 | return -ENODEV; | ||
269 | } | ||
270 | |||
271 | if (of_property_read_u32_array(dn, "ibm,unit-capacity", unit_cap, 2)) { | ||
272 | dev_err(&pdev->dev, "%pOF: missing unit-capacity!\n", dn); | ||
273 | return -ENODEV; | ||
274 | } | ||
275 | |||
276 | p = kzalloc(sizeof(*p), GFP_KERNEL); | ||
277 | if (!p) | ||
278 | return -ENOMEM; | ||
279 | |||
280 | /* optional DT properties */ | ||
281 | of_property_read_u32(dn, "ibm,metadata-size", &metadata_size); | ||
282 | |||
283 | p->dn = dn; | ||
284 | p->drc_index = drc_index; | ||
285 | p->block_size = unit_cap[0]; | ||
286 | p->blocks = unit_cap[1]; | ||
287 | |||
288 | /* might be zero */ | ||
289 | p->metadata_size = metadata_size; | ||
290 | p->pdev = pdev; | ||
291 | |||
292 | /* request the hypervisor to bind this region to somewhere in memory */ | ||
293 | rc = drc_pmem_bind(p); | ||
294 | if (rc) | ||
295 | goto err; | ||
296 | |||
297 | /* setup the resource for the newly bound range */ | ||
298 | p->res.start = p->bound_addr; | ||
299 | p->res.end = p->bound_addr + p->blocks * p->block_size; | ||
300 | p->res.name = pdev->name; | ||
301 | p->res.flags = IORESOURCE_MEM; | ||
302 | |||
303 | rc = papr_scm_nvdimm_init(p); | ||
304 | if (rc) | ||
305 | goto err2; | ||
306 | |||
307 | platform_set_drvdata(pdev, p); | ||
308 | |||
309 | return 0; | ||
310 | |||
311 | err2: drc_pmem_unbind(p); | ||
312 | err: kfree(p); | ||
313 | return rc; | ||
314 | } | ||
315 | |||
316 | static int papr_scm_remove(struct platform_device *pdev) | ||
317 | { | ||
318 | struct papr_scm_priv *p = platform_get_drvdata(pdev); | ||
319 | |||
320 | nvdimm_bus_unregister(p->bus); | ||
321 | drc_pmem_unbind(p); | ||
322 | kfree(p); | ||
323 | |||
324 | return 0; | ||
325 | } | ||
326 | |||
327 | static const struct of_device_id papr_scm_match[] = { | ||
328 | { .compatible = "ibm,pmemory" }, | ||
329 | { }, | ||
330 | }; | ||
331 | |||
332 | static struct platform_driver papr_scm_driver = { | ||
333 | .probe = papr_scm_probe, | ||
334 | .remove = papr_scm_remove, | ||
335 | .driver = { | ||
336 | .name = "papr_scm", | ||
337 | .owner = THIS_MODULE, | ||
338 | .of_match_table = papr_scm_match, | ||
339 | }, | ||
340 | }; | ||
341 | |||
342 | module_platform_driver(papr_scm_driver); | ||
343 | MODULE_DEVICE_TABLE(of, papr_scm_match); | ||
344 | MODULE_LICENSE("GPL"); | ||
345 | MODULE_AUTHOR("IBM Corporation"); | ||
diff --git a/arch/powerpc/platforms/pseries/pci.c b/arch/powerpc/platforms/pseries/pci.c index eab96637d6cf..41d8a4d1d02e 100644 --- a/arch/powerpc/platforms/pseries/pci.c +++ b/arch/powerpc/platforms/pseries/pci.c | |||
@@ -239,6 +239,7 @@ void __init pSeries_final_fixup(void) | |||
239 | { | 239 | { |
240 | pSeries_request_regions(); | 240 | pSeries_request_regions(); |
241 | 241 | ||
242 | eeh_probe_devices(); | ||
242 | eeh_addr_cache_build(); | 243 | eeh_addr_cache_build(); |
243 | 244 | ||
244 | #ifdef CONFIG_PCI_IOV | 245 | #ifdef CONFIG_PCI_IOV |
diff --git a/arch/powerpc/platforms/pseries/pmem.c b/arch/powerpc/platforms/pseries/pmem.c new file mode 100644 index 000000000000..a27f40eb57b1 --- /dev/null +++ b/arch/powerpc/platforms/pseries/pmem.c | |||
@@ -0,0 +1,164 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | |||
3 | /* | ||
4 | * Handles hot and cold plug of persistent memory regions on pseries. | ||
5 | */ | ||
6 | |||
7 | #define pr_fmt(fmt) "pseries-pmem: " fmt | ||
8 | |||
9 | #include <linux/kernel.h> | ||
10 | #include <linux/interrupt.h> | ||
11 | #include <linux/delay.h> | ||
12 | #include <linux/sched.h> /* for idle_task_exit */ | ||
13 | #include <linux/sched/hotplug.h> | ||
14 | #include <linux/cpu.h> | ||
15 | #include <linux/of.h> | ||
16 | #include <linux/of_platform.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include <asm/prom.h> | ||
19 | #include <asm/rtas.h> | ||
20 | #include <asm/firmware.h> | ||
21 | #include <asm/machdep.h> | ||
22 | #include <asm/vdso_datapage.h> | ||
23 | #include <asm/plpar_wrappers.h> | ||
24 | #include <asm/topology.h> | ||
25 | |||
26 | #include "pseries.h" | ||
27 | #include "offline_states.h" | ||
28 | |||
29 | static struct device_node *pmem_node; | ||
30 | |||
31 | static ssize_t pmem_drc_add_node(u32 drc_index) | ||
32 | { | ||
33 | struct device_node *dn; | ||
34 | int rc; | ||
35 | |||
36 | pr_debug("Attempting to add pmem node, drc index: %x\n", drc_index); | ||
37 | |||
38 | rc = dlpar_acquire_drc(drc_index); | ||
39 | if (rc) { | ||
40 | pr_err("Failed to acquire DRC, rc: %d, drc index: %x\n", | ||
41 | rc, drc_index); | ||
42 | return -EINVAL; | ||
43 | } | ||
44 | |||
45 | dn = dlpar_configure_connector(cpu_to_be32(drc_index), pmem_node); | ||
46 | if (!dn) { | ||
47 | pr_err("configure-connector failed for drc %x\n", drc_index); | ||
48 | dlpar_release_drc(drc_index); | ||
49 | return -EINVAL; | ||
50 | } | ||
51 | |||
52 | /* NB: The of reconfig notifier creates platform device from the node */ | ||
53 | rc = dlpar_attach_node(dn, pmem_node); | ||
54 | if (rc) { | ||
55 | pr_err("Failed to attach node %s, rc: %d, drc index: %x\n", | ||
56 | dn->name, rc, drc_index); | ||
57 | |||
58 | if (dlpar_release_drc(drc_index)) | ||
59 | dlpar_free_cc_nodes(dn); | ||
60 | |||
61 | return rc; | ||
62 | } | ||
63 | |||
64 | pr_info("Successfully added %pOF, drc index: %x\n", dn, drc_index); | ||
65 | |||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | static ssize_t pmem_drc_remove_node(u32 drc_index) | ||
70 | { | ||
71 | struct device_node *dn; | ||
72 | uint32_t index; | ||
73 | int rc; | ||
74 | |||
75 | for_each_child_of_node(pmem_node, dn) { | ||
76 | if (of_property_read_u32(dn, "ibm,my-drc-index", &index)) | ||
77 | continue; | ||
78 | if (index == drc_index) | ||
79 | break; | ||
80 | } | ||
81 | |||
82 | if (!dn) { | ||
83 | pr_err("Attempting to remove unused DRC index %x\n", drc_index); | ||
84 | return -ENODEV; | ||
85 | } | ||
86 | |||
87 | pr_debug("Attempting to remove %pOF, drc index: %x\n", dn, drc_index); | ||
88 | |||
89 | /* * NB: tears down the ibm,pmemory device as a side-effect */ | ||
90 | rc = dlpar_detach_node(dn); | ||
91 | if (rc) | ||
92 | return rc; | ||
93 | |||
94 | rc = dlpar_release_drc(drc_index); | ||
95 | if (rc) { | ||
96 | pr_err("Failed to release drc (%x) for CPU %s, rc: %d\n", | ||
97 | drc_index, dn->name, rc); | ||
98 | dlpar_attach_node(dn, pmem_node); | ||
99 | return rc; | ||
100 | } | ||
101 | |||
102 | pr_info("Successfully removed PMEM with drc index: %x\n", drc_index); | ||
103 | |||
104 | return 0; | ||
105 | } | ||
106 | |||
107 | int dlpar_hp_pmem(struct pseries_hp_errorlog *hp_elog) | ||
108 | { | ||
109 | u32 count, drc_index; | ||
110 | int rc; | ||
111 | |||
112 | /* slim chance, but we might get a hotplug event while booting */ | ||
113 | if (!pmem_node) | ||
114 | pmem_node = of_find_node_by_type(NULL, "ibm,persistent-memory"); | ||
115 | if (!pmem_node) { | ||
116 | pr_err("Hotplug event for a pmem device, but none exists\n"); | ||
117 | return -ENODEV; | ||
118 | } | ||
119 | |||
120 | if (hp_elog->id_type != PSERIES_HP_ELOG_ID_DRC_INDEX) { | ||
121 | pr_err("Unsupported hotplug event type %d\n", | ||
122 | hp_elog->id_type); | ||
123 | return -EINVAL; | ||
124 | } | ||
125 | |||
126 | count = hp_elog->_drc_u.drc_count; | ||
127 | drc_index = hp_elog->_drc_u.drc_index; | ||
128 | |||
129 | lock_device_hotplug(); | ||
130 | |||
131 | if (hp_elog->action == PSERIES_HP_ELOG_ACTION_ADD) { | ||
132 | rc = pmem_drc_add_node(drc_index); | ||
133 | } else if (hp_elog->action == PSERIES_HP_ELOG_ACTION_REMOVE) { | ||
134 | rc = pmem_drc_remove_node(drc_index); | ||
135 | } else { | ||
136 | pr_err("Unsupported hotplug action (%d)\n", hp_elog->action); | ||
137 | rc = -EINVAL; | ||
138 | } | ||
139 | |||
140 | unlock_device_hotplug(); | ||
141 | return rc; | ||
142 | } | ||
143 | |||
144 | const struct of_device_id drc_pmem_match[] = { | ||
145 | { .type = "ibm,persistent-memory", }, | ||
146 | {} | ||
147 | }; | ||
148 | |||
149 | static int pseries_pmem_init(void) | ||
150 | { | ||
151 | pmem_node = of_find_node_by_type(NULL, "ibm,persistent-memory"); | ||
152 | if (!pmem_node) | ||
153 | return 0; | ||
154 | |||
155 | /* | ||
156 | * The generic OF bus probe/populate handles creating platform devices | ||
157 | * from the child (ibm,pmemory) nodes. The generic code registers an of | ||
158 | * reconfig notifier to handle the hot-add/remove cases too. | ||
159 | */ | ||
160 | of_platform_bus_probe(pmem_node, drc_pmem_match, NULL); | ||
161 | |||
162 | return 0; | ||
163 | } | ||
164 | machine_arch_initcall(pseries, pseries_pmem_init); | ||
diff --git a/arch/powerpc/platforms/pseries/pseries.h b/arch/powerpc/platforms/pseries/pseries.h index 60db2ee511fb..7dee8c5d3363 100644 --- a/arch/powerpc/platforms/pseries/pseries.h +++ b/arch/powerpc/platforms/pseries/pseries.h | |||
@@ -24,6 +24,7 @@ struct pt_regs; | |||
24 | 24 | ||
25 | extern int pSeries_system_reset_exception(struct pt_regs *regs); | 25 | extern int pSeries_system_reset_exception(struct pt_regs *regs); |
26 | extern int pSeries_machine_check_exception(struct pt_regs *regs); | 26 | extern int pSeries_machine_check_exception(struct pt_regs *regs); |
27 | extern long pseries_machine_check_realmode(struct pt_regs *regs); | ||
27 | 28 | ||
28 | #ifdef CONFIG_SMP | 29 | #ifdef CONFIG_SMP |
29 | extern void smp_init_pseries(void); | 30 | extern void smp_init_pseries(void); |
@@ -59,15 +60,21 @@ extern int dlpar_detach_node(struct device_node *); | |||
59 | extern int dlpar_acquire_drc(u32 drc_index); | 60 | extern int dlpar_acquire_drc(u32 drc_index); |
60 | extern int dlpar_release_drc(u32 drc_index); | 61 | extern int dlpar_release_drc(u32 drc_index); |
61 | 62 | ||
62 | void queue_hotplug_event(struct pseries_hp_errorlog *hp_errlog, | 63 | void queue_hotplug_event(struct pseries_hp_errorlog *hp_errlog); |
63 | struct completion *hotplug_done, int *rc); | 64 | int handle_dlpar_errorlog(struct pseries_hp_errorlog *hp_errlog); |
65 | |||
64 | #ifdef CONFIG_MEMORY_HOTPLUG | 66 | #ifdef CONFIG_MEMORY_HOTPLUG |
65 | int dlpar_memory(struct pseries_hp_errorlog *hp_elog); | 67 | int dlpar_memory(struct pseries_hp_errorlog *hp_elog); |
68 | int dlpar_hp_pmem(struct pseries_hp_errorlog *hp_elog); | ||
66 | #else | 69 | #else |
67 | static inline int dlpar_memory(struct pseries_hp_errorlog *hp_elog) | 70 | static inline int dlpar_memory(struct pseries_hp_errorlog *hp_elog) |
68 | { | 71 | { |
69 | return -EOPNOTSUPP; | 72 | return -EOPNOTSUPP; |
70 | } | 73 | } |
74 | static inline int dlpar_hp_pmem(struct pseries_hp_errorlog *hp_elog) | ||
75 | { | ||
76 | return -EOPNOTSUPP; | ||
77 | } | ||
71 | #endif | 78 | #endif |
72 | 79 | ||
73 | #ifdef CONFIG_HOTPLUG_CPU | 80 | #ifdef CONFIG_HOTPLUG_CPU |
diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c index 851ce326874a..d97d52772789 100644 --- a/arch/powerpc/platforms/pseries/ras.c +++ b/arch/powerpc/platforms/pseries/ras.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <asm/machdep.h> | 27 | #include <asm/machdep.h> |
28 | #include <asm/rtas.h> | 28 | #include <asm/rtas.h> |
29 | #include <asm/firmware.h> | 29 | #include <asm/firmware.h> |
30 | #include <asm/mce.h> | ||
30 | 31 | ||
31 | #include "pseries.h" | 32 | #include "pseries.h" |
32 | 33 | ||
@@ -50,6 +51,101 @@ static irqreturn_t ras_hotplug_interrupt(int irq, void *dev_id); | |||
50 | static irqreturn_t ras_epow_interrupt(int irq, void *dev_id); | 51 | static irqreturn_t ras_epow_interrupt(int irq, void *dev_id); |
51 | static irqreturn_t ras_error_interrupt(int irq, void *dev_id); | 52 | static irqreturn_t ras_error_interrupt(int irq, void *dev_id); |
52 | 53 | ||
54 | /* RTAS pseries MCE errorlog section. */ | ||
55 | struct pseries_mc_errorlog { | ||
56 | __be32 fru_id; | ||
57 | __be32 proc_id; | ||
58 | u8 error_type; | ||
59 | /* | ||
60 | * sub_err_type (1 byte). Bit fields depends on error_type | ||
61 | * | ||
62 | * MSB0 | ||
63 | * | | ||
64 | * V | ||
65 | * 01234567 | ||
66 | * XXXXXXXX | ||
67 | * | ||
68 | * For error_type == MC_ERROR_TYPE_UE | ||
69 | * XXXXXXXX | ||
70 | * X 1: Permanent or Transient UE. | ||
71 | * X 1: Effective address provided. | ||
72 | * X 1: Logical address provided. | ||
73 | * XX 2: Reserved. | ||
74 | * XXX 3: Type of UE error. | ||
75 | * | ||
76 | * For error_type != MC_ERROR_TYPE_UE | ||
77 | * XXXXXXXX | ||
78 | * X 1: Effective address provided. | ||
79 | * XXXXX 5: Reserved. | ||
80 | * XX 2: Type of SLB/ERAT/TLB error. | ||
81 | */ | ||
82 | u8 sub_err_type; | ||
83 | u8 reserved_1[6]; | ||
84 | __be64 effective_address; | ||
85 | __be64 logical_address; | ||
86 | } __packed; | ||
87 | |||
88 | /* RTAS pseries MCE error types */ | ||
89 | #define MC_ERROR_TYPE_UE 0x00 | ||
90 | #define MC_ERROR_TYPE_SLB 0x01 | ||
91 | #define MC_ERROR_TYPE_ERAT 0x02 | ||
92 | #define MC_ERROR_TYPE_TLB 0x04 | ||
93 | #define MC_ERROR_TYPE_D_CACHE 0x05 | ||
94 | #define MC_ERROR_TYPE_I_CACHE 0x07 | ||
95 | |||
96 | /* RTAS pseries MCE error sub types */ | ||
97 | #define MC_ERROR_UE_INDETERMINATE 0 | ||
98 | #define MC_ERROR_UE_IFETCH 1 | ||
99 | #define MC_ERROR_UE_PAGE_TABLE_WALK_IFETCH 2 | ||
100 | #define MC_ERROR_UE_LOAD_STORE 3 | ||
101 | #define MC_ERROR_UE_PAGE_TABLE_WALK_LOAD_STORE 4 | ||
102 | |||
103 | #define MC_ERROR_SLB_PARITY 0 | ||
104 | #define MC_ERROR_SLB_MULTIHIT 1 | ||
105 | #define MC_ERROR_SLB_INDETERMINATE 2 | ||
106 | |||
107 | #define MC_ERROR_ERAT_PARITY 1 | ||
108 | #define MC_ERROR_ERAT_MULTIHIT 2 | ||
109 | #define MC_ERROR_ERAT_INDETERMINATE 3 | ||
110 | |||
111 | #define MC_ERROR_TLB_PARITY 1 | ||
112 | #define MC_ERROR_TLB_MULTIHIT 2 | ||
113 | #define MC_ERROR_TLB_INDETERMINATE 3 | ||
114 | |||
115 | static inline u8 rtas_mc_error_sub_type(const struct pseries_mc_errorlog *mlog) | ||
116 | { | ||
117 | switch (mlog->error_type) { | ||
118 | case MC_ERROR_TYPE_UE: | ||
119 | return (mlog->sub_err_type & 0x07); | ||
120 | case MC_ERROR_TYPE_SLB: | ||
121 | case MC_ERROR_TYPE_ERAT: | ||
122 | case MC_ERROR_TYPE_TLB: | ||
123 | return (mlog->sub_err_type & 0x03); | ||
124 | default: | ||
125 | return 0; | ||
126 | } | ||
127 | } | ||
128 | |||
129 | static | ||
130 | inline u64 rtas_mc_get_effective_addr(const struct pseries_mc_errorlog *mlog) | ||
131 | { | ||
132 | __be64 addr = 0; | ||
133 | |||
134 | switch (mlog->error_type) { | ||
135 | case MC_ERROR_TYPE_UE: | ||
136 | if (mlog->sub_err_type & 0x40) | ||
137 | addr = mlog->effective_address; | ||
138 | break; | ||
139 | case MC_ERROR_TYPE_SLB: | ||
140 | case MC_ERROR_TYPE_ERAT: | ||
141 | case MC_ERROR_TYPE_TLB: | ||
142 | if (mlog->sub_err_type & 0x80) | ||
143 | addr = mlog->effective_address; | ||
144 | default: | ||
145 | break; | ||
146 | } | ||
147 | return be64_to_cpu(addr); | ||
148 | } | ||
53 | 149 | ||
54 | /* | 150 | /* |
55 | * Enable the hotplug interrupt late because processing them may touch other | 151 | * Enable the hotplug interrupt late because processing them may touch other |
@@ -237,8 +333,9 @@ static irqreturn_t ras_hotplug_interrupt(int irq, void *dev_id) | |||
237 | * hotplug events on the ras_log_buf to be handled by rtas_errd. | 333 | * hotplug events on the ras_log_buf to be handled by rtas_errd. |
238 | */ | 334 | */ |
239 | if (hp_elog->resource == PSERIES_HP_ELOG_RESOURCE_MEM || | 335 | if (hp_elog->resource == PSERIES_HP_ELOG_RESOURCE_MEM || |
240 | hp_elog->resource == PSERIES_HP_ELOG_RESOURCE_CPU) | 336 | hp_elog->resource == PSERIES_HP_ELOG_RESOURCE_CPU || |
241 | queue_hotplug_event(hp_elog, NULL, NULL); | 337 | hp_elog->resource == PSERIES_HP_ELOG_RESOURCE_PMEM) |
338 | queue_hotplug_event(hp_elog); | ||
242 | else | 339 | else |
243 | log_error(ras_log_buf, ERR_TYPE_RTAS_LOG, 0); | 340 | log_error(ras_log_buf, ERR_TYPE_RTAS_LOG, 0); |
244 | 341 | ||
@@ -427,6 +524,188 @@ int pSeries_system_reset_exception(struct pt_regs *regs) | |||
427 | return 0; /* need to perform reset */ | 524 | return 0; /* need to perform reset */ |
428 | } | 525 | } |
429 | 526 | ||
527 | #define VAL_TO_STRING(ar, val) \ | ||
528 | (((val) < ARRAY_SIZE(ar)) ? ar[(val)] : "Unknown") | ||
529 | |||
530 | static void pseries_print_mce_info(struct pt_regs *regs, | ||
531 | struct rtas_error_log *errp) | ||
532 | { | ||
533 | const char *level, *sevstr; | ||
534 | struct pseries_errorlog *pseries_log; | ||
535 | struct pseries_mc_errorlog *mce_log; | ||
536 | u8 error_type, err_sub_type; | ||
537 | u64 addr; | ||
538 | u8 initiator = rtas_error_initiator(errp); | ||
539 | int disposition = rtas_error_disposition(errp); | ||
540 | |||
541 | static const char * const initiators[] = { | ||
542 | "Unknown", | ||
543 | "CPU", | ||
544 | "PCI", | ||
545 | "ISA", | ||
546 | "Memory", | ||
547 | "Power Mgmt", | ||
548 | }; | ||
549 | static const char * const mc_err_types[] = { | ||
550 | "UE", | ||
551 | "SLB", | ||
552 | "ERAT", | ||
553 | "TLB", | ||
554 | "D-Cache", | ||
555 | "Unknown", | ||
556 | "I-Cache", | ||
557 | }; | ||
558 | static const char * const mc_ue_types[] = { | ||
559 | "Indeterminate", | ||
560 | "Instruction fetch", | ||
561 | "Page table walk ifetch", | ||
562 | "Load/Store", | ||
563 | "Page table walk Load/Store", | ||
564 | }; | ||
565 | |||
566 | /* SLB sub errors valid values are 0x0, 0x1, 0x2 */ | ||
567 | static const char * const mc_slb_types[] = { | ||
568 | "Parity", | ||
569 | "Multihit", | ||
570 | "Indeterminate", | ||
571 | }; | ||
572 | |||
573 | /* TLB and ERAT sub errors valid values are 0x1, 0x2, 0x3 */ | ||
574 | static const char * const mc_soft_types[] = { | ||
575 | "Unknown", | ||
576 | "Parity", | ||
577 | "Multihit", | ||
578 | "Indeterminate", | ||
579 | }; | ||
580 | |||
581 | if (!rtas_error_extended(errp)) { | ||
582 | pr_err("Machine check interrupt: Missing extended error log\n"); | ||
583 | return; | ||
584 | } | ||
585 | |||
586 | pseries_log = get_pseries_errorlog(errp, PSERIES_ELOG_SECT_ID_MCE); | ||
587 | if (pseries_log == NULL) | ||
588 | return; | ||
589 | |||
590 | mce_log = (struct pseries_mc_errorlog *)pseries_log->data; | ||
591 | |||
592 | error_type = mce_log->error_type; | ||
593 | err_sub_type = rtas_mc_error_sub_type(mce_log); | ||
594 | |||
595 | switch (rtas_error_severity(errp)) { | ||
596 | case RTAS_SEVERITY_NO_ERROR: | ||
597 | level = KERN_INFO; | ||
598 | sevstr = "Harmless"; | ||
599 | break; | ||
600 | case RTAS_SEVERITY_WARNING: | ||
601 | level = KERN_WARNING; | ||
602 | sevstr = ""; | ||
603 | break; | ||
604 | case RTAS_SEVERITY_ERROR: | ||
605 | case RTAS_SEVERITY_ERROR_SYNC: | ||
606 | level = KERN_ERR; | ||
607 | sevstr = "Severe"; | ||
608 | break; | ||
609 | case RTAS_SEVERITY_FATAL: | ||
610 | default: | ||
611 | level = KERN_ERR; | ||
612 | sevstr = "Fatal"; | ||
613 | break; | ||
614 | } | ||
615 | |||
616 | #ifdef CONFIG_PPC_BOOK3S_64 | ||
617 | /* Display faulty slb contents for SLB errors. */ | ||
618 | if (error_type == MC_ERROR_TYPE_SLB) | ||
619 | slb_dump_contents(local_paca->mce_faulty_slbs); | ||
620 | #endif | ||
621 | |||
622 | printk("%s%s Machine check interrupt [%s]\n", level, sevstr, | ||
623 | disposition == RTAS_DISP_FULLY_RECOVERED ? | ||
624 | "Recovered" : "Not recovered"); | ||
625 | if (user_mode(regs)) { | ||
626 | printk("%s NIP: [%016lx] PID: %d Comm: %s\n", level, | ||
627 | regs->nip, current->pid, current->comm); | ||
628 | } else { | ||
629 | printk("%s NIP [%016lx]: %pS\n", level, regs->nip, | ||
630 | (void *)regs->nip); | ||
631 | } | ||
632 | printk("%s Initiator: %s\n", level, | ||
633 | VAL_TO_STRING(initiators, initiator)); | ||
634 | |||
635 | switch (error_type) { | ||
636 | case MC_ERROR_TYPE_UE: | ||
637 | printk("%s Error type: %s [%s]\n", level, | ||
638 | VAL_TO_STRING(mc_err_types, error_type), | ||
639 | VAL_TO_STRING(mc_ue_types, err_sub_type)); | ||
640 | break; | ||
641 | case MC_ERROR_TYPE_SLB: | ||
642 | printk("%s Error type: %s [%s]\n", level, | ||
643 | VAL_TO_STRING(mc_err_types, error_type), | ||
644 | VAL_TO_STRING(mc_slb_types, err_sub_type)); | ||
645 | break; | ||
646 | case MC_ERROR_TYPE_ERAT: | ||
647 | case MC_ERROR_TYPE_TLB: | ||
648 | printk("%s Error type: %s [%s]\n", level, | ||
649 | VAL_TO_STRING(mc_err_types, error_type), | ||
650 | VAL_TO_STRING(mc_soft_types, err_sub_type)); | ||
651 | break; | ||
652 | default: | ||
653 | printk("%s Error type: %s\n", level, | ||
654 | VAL_TO_STRING(mc_err_types, error_type)); | ||
655 | break; | ||
656 | } | ||
657 | |||
658 | addr = rtas_mc_get_effective_addr(mce_log); | ||
659 | if (addr) | ||
660 | printk("%s Effective address: %016llx\n", level, addr); | ||
661 | } | ||
662 | |||
663 | static int mce_handle_error(struct rtas_error_log *errp) | ||
664 | { | ||
665 | struct pseries_errorlog *pseries_log; | ||
666 | struct pseries_mc_errorlog *mce_log; | ||
667 | int disposition = rtas_error_disposition(errp); | ||
668 | u8 error_type; | ||
669 | |||
670 | if (!rtas_error_extended(errp)) | ||
671 | goto out; | ||
672 | |||
673 | pseries_log = get_pseries_errorlog(errp, PSERIES_ELOG_SECT_ID_MCE); | ||
674 | if (pseries_log == NULL) | ||
675 | goto out; | ||
676 | |||
677 | mce_log = (struct pseries_mc_errorlog *)pseries_log->data; | ||
678 | error_type = mce_log->error_type; | ||
679 | |||
680 | #ifdef CONFIG_PPC_BOOK3S_64 | ||
681 | if (disposition == RTAS_DISP_NOT_RECOVERED) { | ||
682 | switch (error_type) { | ||
683 | case MC_ERROR_TYPE_SLB: | ||
684 | case MC_ERROR_TYPE_ERAT: | ||
685 | /* | ||
686 | * Store the old slb content in paca before flushing. | ||
687 | * Print this when we go to virtual mode. | ||
688 | * There are chances that we may hit MCE again if there | ||
689 | * is a parity error on the SLB entry we trying to read | ||
690 | * for saving. Hence limit the slb saving to single | ||
691 | * level of recursion. | ||
692 | */ | ||
693 | if (local_paca->in_mce == 1) | ||
694 | slb_save_contents(local_paca->mce_faulty_slbs); | ||
695 | flush_and_reload_slb(); | ||
696 | disposition = RTAS_DISP_FULLY_RECOVERED; | ||
697 | rtas_set_disposition_recovered(errp); | ||
698 | break; | ||
699 | default: | ||
700 | break; | ||
701 | } | ||
702 | } | ||
703 | #endif | ||
704 | |||
705 | out: | ||
706 | return disposition; | ||
707 | } | ||
708 | |||
430 | /* | 709 | /* |
431 | * Process MCE rtas errlog event. | 710 | * Process MCE rtas errlog event. |
432 | */ | 711 | */ |
@@ -452,8 +731,11 @@ static int recover_mce(struct pt_regs *regs, struct rtas_error_log *err) | |||
452 | int recovered = 0; | 731 | int recovered = 0; |
453 | int disposition = rtas_error_disposition(err); | 732 | int disposition = rtas_error_disposition(err); |
454 | 733 | ||
734 | pseries_print_mce_info(regs, err); | ||
735 | |||
455 | if (!(regs->msr & MSR_RI)) { | 736 | if (!(regs->msr & MSR_RI)) { |
456 | /* If MSR_RI isn't set, we cannot recover */ | 737 | /* If MSR_RI isn't set, we cannot recover */ |
738 | pr_err("Machine check interrupt unrecoverable: MSR(RI=0)\n"); | ||
457 | recovered = 0; | 739 | recovered = 0; |
458 | 740 | ||
459 | } else if (disposition == RTAS_DISP_FULLY_RECOVERED) { | 741 | } else if (disposition == RTAS_DISP_FULLY_RECOVERED) { |
@@ -503,11 +785,31 @@ int pSeries_machine_check_exception(struct pt_regs *regs) | |||
503 | struct rtas_error_log *errp; | 785 | struct rtas_error_log *errp; |
504 | 786 | ||
505 | if (fwnmi_active) { | 787 | if (fwnmi_active) { |
506 | errp = fwnmi_get_errinfo(regs); | ||
507 | fwnmi_release_errinfo(); | 788 | fwnmi_release_errinfo(); |
789 | errp = fwnmi_get_errlog(); | ||
508 | if (errp && recover_mce(regs, errp)) | 790 | if (errp && recover_mce(regs, errp)) |
509 | return 1; | 791 | return 1; |
510 | } | 792 | } |
511 | 793 | ||
512 | return 0; | 794 | return 0; |
513 | } | 795 | } |
796 | |||
797 | long pseries_machine_check_realmode(struct pt_regs *regs) | ||
798 | { | ||
799 | struct rtas_error_log *errp; | ||
800 | int disposition; | ||
801 | |||
802 | if (fwnmi_active) { | ||
803 | errp = fwnmi_get_errinfo(regs); | ||
804 | /* | ||
805 | * Call to fwnmi_release_errinfo() in real mode causes kernel | ||
806 | * to panic. Hence we will call it as soon as we go into | ||
807 | * virtual mode. | ||
808 | */ | ||
809 | disposition = mce_handle_error(errp); | ||
810 | if (disposition == RTAS_DISP_FULLY_RECOVERED) | ||
811 | return 1; | ||
812 | } | ||
813 | |||
814 | return 0; | ||
815 | } | ||
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index ba1791fd3234..0f553dcfa548 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c | |||
@@ -107,6 +107,10 @@ static void __init fwnmi_init(void) | |||
107 | u8 *mce_data_buf; | 107 | u8 *mce_data_buf; |
108 | unsigned int i; | 108 | unsigned int i; |
109 | int nr_cpus = num_possible_cpus(); | 109 | int nr_cpus = num_possible_cpus(); |
110 | #ifdef CONFIG_PPC_BOOK3S_64 | ||
111 | struct slb_entry *slb_ptr; | ||
112 | size_t size; | ||
113 | #endif | ||
110 | 114 | ||
111 | int ibm_nmi_register = rtas_token("ibm,nmi-register"); | 115 | int ibm_nmi_register = rtas_token("ibm,nmi-register"); |
112 | if (ibm_nmi_register == RTAS_UNKNOWN_SERVICE) | 116 | if (ibm_nmi_register == RTAS_UNKNOWN_SERVICE) |
@@ -132,6 +136,15 @@ static void __init fwnmi_init(void) | |||
132 | paca_ptrs[i]->mce_data_buf = mce_data_buf + | 136 | paca_ptrs[i]->mce_data_buf = mce_data_buf + |
133 | (RTAS_ERROR_LOG_MAX * i); | 137 | (RTAS_ERROR_LOG_MAX * i); |
134 | } | 138 | } |
139 | |||
140 | #ifdef CONFIG_PPC_BOOK3S_64 | ||
141 | /* Allocate per cpu slb area to save old slb contents during MCE */ | ||
142 | size = sizeof(struct slb_entry) * mmu_slb_size * nr_cpus; | ||
143 | slb_ptr = __va(memblock_alloc_base(size, sizeof(struct slb_entry), | ||
144 | ppc64_rma_size)); | ||
145 | for_each_possible_cpu(i) | ||
146 | paca_ptrs[i]->mce_faulty_slbs = slb_ptr + (mmu_slb_size * i); | ||
147 | #endif | ||
135 | } | 148 | } |
136 | 149 | ||
137 | static void pseries_8259_cascade(struct irq_desc *desc) | 150 | static void pseries_8259_cascade(struct irq_desc *desc) |
@@ -1017,6 +1030,7 @@ define_machine(pseries) { | |||
1017 | .calibrate_decr = generic_calibrate_decr, | 1030 | .calibrate_decr = generic_calibrate_decr, |
1018 | .progress = rtas_progress, | 1031 | .progress = rtas_progress, |
1019 | .system_reset_exception = pSeries_system_reset_exception, | 1032 | .system_reset_exception = pSeries_system_reset_exception, |
1033 | .machine_check_early = pseries_machine_check_realmode, | ||
1020 | .machine_check_exception = pSeries_machine_check_exception, | 1034 | .machine_check_exception = pSeries_machine_check_exception, |
1021 | #ifdef CONFIG_KEXEC_CORE | 1035 | #ifdef CONFIG_KEXEC_CORE |
1022 | .machine_kexec = pSeries_machine_kexec, | 1036 | .machine_kexec = pSeries_machine_kexec, |
diff --git a/arch/powerpc/platforms/pseries/vio.c b/arch/powerpc/platforms/pseries/vio.c index 49e04ec19238..88f1ad1d6309 100644 --- a/arch/powerpc/platforms/pseries/vio.c +++ b/arch/powerpc/platforms/pseries/vio.c | |||
@@ -1349,7 +1349,6 @@ struct vio_dev *vio_register_device_node(struct device_node *of_node) | |||
1349 | struct device_node *parent_node; | 1349 | struct device_node *parent_node; |
1350 | const __be32 *prop; | 1350 | const __be32 *prop; |
1351 | enum vio_dev_family family; | 1351 | enum vio_dev_family family; |
1352 | const char *of_node_name = of_node->name ? of_node->name : "<unknown>"; | ||
1353 | 1352 | ||
1354 | /* | 1353 | /* |
1355 | * Determine if this node is a under the /vdevice node or under the | 1354 | * Determine if this node is a under the /vdevice node or under the |
@@ -1362,24 +1361,24 @@ struct vio_dev *vio_register_device_node(struct device_node *of_node) | |||
1362 | else if (!strcmp(parent_node->type, "vdevice")) | 1361 | else if (!strcmp(parent_node->type, "vdevice")) |
1363 | family = VDEVICE; | 1362 | family = VDEVICE; |
1364 | else { | 1363 | else { |
1365 | pr_warn("%s: parent(%pOF) of %s not recognized.\n", | 1364 | pr_warn("%s: parent(%pOF) of %pOFn not recognized.\n", |
1366 | __func__, | 1365 | __func__, |
1367 | parent_node, | 1366 | parent_node, |
1368 | of_node_name); | 1367 | of_node); |
1369 | of_node_put(parent_node); | 1368 | of_node_put(parent_node); |
1370 | return NULL; | 1369 | return NULL; |
1371 | } | 1370 | } |
1372 | of_node_put(parent_node); | 1371 | of_node_put(parent_node); |
1373 | } else { | 1372 | } else { |
1374 | pr_warn("%s: could not determine the parent of node %s.\n", | 1373 | pr_warn("%s: could not determine the parent of node %pOFn.\n", |
1375 | __func__, of_node_name); | 1374 | __func__, of_node); |
1376 | return NULL; | 1375 | return NULL; |
1377 | } | 1376 | } |
1378 | 1377 | ||
1379 | if (family == PFO) { | 1378 | if (family == PFO) { |
1380 | if (of_get_property(of_node, "interrupt-controller", NULL)) { | 1379 | if (of_get_property(of_node, "interrupt-controller", NULL)) { |
1381 | pr_debug("%s: Skipping the interrupt controller %s.\n", | 1380 | pr_debug("%s: Skipping the interrupt controller %pOFn.\n", |
1382 | __func__, of_node_name); | 1381 | __func__, of_node); |
1383 | return NULL; | 1382 | return NULL; |
1384 | } | 1383 | } |
1385 | } | 1384 | } |
@@ -1399,15 +1398,15 @@ struct vio_dev *vio_register_device_node(struct device_node *of_node) | |||
1399 | if (of_node->type != NULL) | 1398 | if (of_node->type != NULL) |
1400 | viodev->type = of_node->type; | 1399 | viodev->type = of_node->type; |
1401 | else { | 1400 | else { |
1402 | pr_warn("%s: node %s is missing the 'device_type' " | 1401 | pr_warn("%s: node %pOFn is missing the 'device_type' " |
1403 | "property.\n", __func__, of_node_name); | 1402 | "property.\n", __func__, of_node); |
1404 | goto out; | 1403 | goto out; |
1405 | } | 1404 | } |
1406 | 1405 | ||
1407 | prop = of_get_property(of_node, "reg", NULL); | 1406 | prop = of_get_property(of_node, "reg", NULL); |
1408 | if (prop == NULL) { | 1407 | if (prop == NULL) { |
1409 | pr_warn("%s: node %s missing 'reg'\n", | 1408 | pr_warn("%s: node %pOFn missing 'reg'\n", |
1410 | __func__, of_node_name); | 1409 | __func__, of_node); |
1411 | goto out; | 1410 | goto out; |
1412 | } | 1411 | } |
1413 | unit_address = of_read_number(prop, 1); | 1412 | unit_address = of_read_number(prop, 1); |
@@ -1422,8 +1421,8 @@ struct vio_dev *vio_register_device_node(struct device_node *of_node) | |||
1422 | if (prop != NULL) | 1421 | if (prop != NULL) |
1423 | viodev->resource_id = of_read_number(prop, 1); | 1422 | viodev->resource_id = of_read_number(prop, 1); |
1424 | 1423 | ||
1425 | dev_set_name(&viodev->dev, "%s", of_node_name); | 1424 | dev_set_name(&viodev->dev, "%pOFn", of_node); |
1426 | viodev->type = of_node_name; | 1425 | viodev->type = dev_name(&viodev->dev); |
1427 | viodev->irq = 0; | 1426 | viodev->irq = 0; |
1428 | } | 1427 | } |
1429 | 1428 | ||
@@ -1694,7 +1693,7 @@ struct vio_dev *vio_find_node(struct device_node *vnode) | |||
1694 | snprintf(kobj_name, sizeof(kobj_name), "%x", | 1693 | snprintf(kobj_name, sizeof(kobj_name), "%x", |
1695 | (uint32_t)of_read_number(prop, 1)); | 1694 | (uint32_t)of_read_number(prop, 1)); |
1696 | } else if (!strcmp(dev_type, "ibm,platform-facilities")) | 1695 | } else if (!strcmp(dev_type, "ibm,platform-facilities")) |
1697 | snprintf(kobj_name, sizeof(kobj_name), "%s", vnode->name); | 1696 | snprintf(kobj_name, sizeof(kobj_name), "%pOFn", vnode); |
1698 | else | 1697 | else |
1699 | return NULL; | 1698 | return NULL; |
1700 | 1699 | ||
diff --git a/arch/powerpc/sysdev/Kconfig b/arch/powerpc/sysdev/Kconfig index bcef2ac56479..e0dbec780fe9 100644 --- a/arch/powerpc/sysdev/Kconfig +++ b/arch/powerpc/sysdev/Kconfig | |||
@@ -6,19 +6,16 @@ | |||
6 | config PPC4xx_PCI_EXPRESS | 6 | config PPC4xx_PCI_EXPRESS |
7 | bool | 7 | bool |
8 | depends on PCI && 4xx | 8 | depends on PCI && 4xx |
9 | default n | ||
10 | 9 | ||
11 | config PPC4xx_HSTA_MSI | 10 | config PPC4xx_HSTA_MSI |
12 | bool | 11 | bool |
13 | depends on PCI_MSI | 12 | depends on PCI_MSI |
14 | depends on PCI && 4xx | 13 | depends on PCI && 4xx |
15 | default n | ||
16 | 14 | ||
17 | config PPC4xx_MSI | 15 | config PPC4xx_MSI |
18 | bool | 16 | bool |
19 | depends on PCI_MSI | 17 | depends on PCI_MSI |
20 | depends on PCI && 4xx | 18 | depends on PCI && 4xx |
21 | default n | ||
22 | 19 | ||
23 | config PPC_MSI_BITMAP | 20 | config PPC_MSI_BITMAP |
24 | bool | 21 | bool |
@@ -37,11 +34,9 @@ config PPC_SCOM | |||
37 | config SCOM_DEBUGFS | 34 | config SCOM_DEBUGFS |
38 | bool "Expose SCOM controllers via debugfs" | 35 | bool "Expose SCOM controllers via debugfs" |
39 | depends on PPC_SCOM && DEBUG_FS | 36 | depends on PPC_SCOM && DEBUG_FS |
40 | default n | ||
41 | 37 | ||
42 | config GE_FPGA | 38 | config GE_FPGA |
43 | bool | 39 | bool |
44 | default n | ||
45 | 40 | ||
46 | config FSL_CORENET_RCPM | 41 | config FSL_CORENET_RCPM |
47 | bool | 42 | bool |
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile index f730539074c4..2caa4defdfb6 100644 --- a/arch/powerpc/sysdev/Makefile +++ b/arch/powerpc/sysdev/Makefile | |||
@@ -1,5 +1,4 @@ | |||
1 | # SPDX-License-Identifier: GPL-2.0 | 1 | # SPDX-License-Identifier: GPL-2.0 |
2 | subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror | ||
3 | 2 | ||
4 | ccflags-$(CONFIG_PPC64) := $(NO_MINIMAL_TOC) | 3 | ccflags-$(CONFIG_PPC64) := $(NO_MINIMAL_TOC) |
5 | 4 | ||
@@ -56,8 +55,6 @@ obj-$(CONFIG_PPC_SCOM) += scom.o | |||
56 | 55 | ||
57 | obj-$(CONFIG_PPC_EARLY_DEBUG_MEMCONS) += udbg_memcons.o | 56 | obj-$(CONFIG_PPC_EARLY_DEBUG_MEMCONS) += udbg_memcons.o |
58 | 57 | ||
59 | subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror | ||
60 | |||
61 | obj-$(CONFIG_PPC_XICS) += xics/ | 58 | obj-$(CONFIG_PPC_XICS) += xics/ |
62 | obj-$(CONFIG_PPC_XIVE) += xive/ | 59 | obj-$(CONFIG_PPC_XIVE) += xive/ |
63 | 60 | ||
diff --git a/arch/powerpc/sysdev/fsl_85xx_cache_sram.c b/arch/powerpc/sysdev/fsl_85xx_cache_sram.c index 00ccf3e4fcb4..15cbdd4fde06 100644 --- a/arch/powerpc/sysdev/fsl_85xx_cache_sram.c +++ b/arch/powerpc/sysdev/fsl_85xx_cache_sram.c | |||
@@ -107,11 +107,11 @@ int __init instantiate_cache_sram(struct platform_device *dev, | |||
107 | goto out_free; | 107 | goto out_free; |
108 | } | 108 | } |
109 | 109 | ||
110 | cache_sram->base_virt = ioremap_prot(cache_sram->base_phys, | 110 | cache_sram->base_virt = ioremap_coherent(cache_sram->base_phys, |
111 | cache_sram->size, _PAGE_COHERENT | PAGE_KERNEL); | 111 | cache_sram->size); |
112 | if (!cache_sram->base_virt) { | 112 | if (!cache_sram->base_virt) { |
113 | dev_err(&dev->dev, "%pOF: ioremap_prot failed\n", | 113 | dev_err(&dev->dev, "%pOF: ioremap_coherent failed\n", |
114 | dev->dev.of_node); | 114 | dev->dev.of_node); |
115 | ret = -ENOMEM; | 115 | ret = -ENOMEM; |
116 | goto out_release; | 116 | goto out_release; |
117 | } | 117 | } |
diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c index 535cf1f6941c..6300123ce965 100644 --- a/arch/powerpc/sysdev/ipic.c +++ b/arch/powerpc/sysdev/ipic.c | |||
@@ -846,7 +846,7 @@ void ipic_disable_mcp(enum ipic_mcp_irq mcp_irq) | |||
846 | 846 | ||
847 | u32 ipic_get_mcp_status(void) | 847 | u32 ipic_get_mcp_status(void) |
848 | { | 848 | { |
849 | return ipic_read(primary_ipic->regs, IPIC_SERSR); | 849 | return primary_ipic ? ipic_read(primary_ipic->regs, IPIC_SERSR) : 0; |
850 | } | 850 | } |
851 | 851 | ||
852 | void ipic_clear_mcp_status(u32 mask) | 852 | void ipic_clear_mcp_status(u32 mask) |
diff --git a/arch/powerpc/sysdev/xics/Makefile b/arch/powerpc/sysdev/xics/Makefile index 5d438d92472b..ba1e3117b1c0 100644 --- a/arch/powerpc/sysdev/xics/Makefile +++ b/arch/powerpc/sysdev/xics/Makefile | |||
@@ -1,5 +1,4 @@ | |||
1 | # SPDX-License-Identifier: GPL-2.0 | 1 | # SPDX-License-Identifier: GPL-2.0 |
2 | subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror | ||
3 | 2 | ||
4 | obj-y += xics-common.o | 3 | obj-y += xics-common.o |
5 | obj-$(CONFIG_PPC_ICP_NATIVE) += icp-native.o | 4 | obj-$(CONFIG_PPC_ICP_NATIVE) += icp-native.o |
diff --git a/arch/powerpc/sysdev/xive/Kconfig b/arch/powerpc/sysdev/xive/Kconfig index 70ee976e1de0..785c292d104b 100644 --- a/arch/powerpc/sysdev/xive/Kconfig +++ b/arch/powerpc/sysdev/xive/Kconfig | |||
@@ -1,17 +1,14 @@ | |||
1 | # SPDX-License-Identifier: GPL-2.0 | 1 | # SPDX-License-Identifier: GPL-2.0 |
2 | config PPC_XIVE | 2 | config PPC_XIVE |
3 | bool | 3 | bool |
4 | default n | ||
5 | select PPC_SMP_MUXED_IPI | 4 | select PPC_SMP_MUXED_IPI |
6 | select HARDIRQS_SW_RESEND | 5 | select HARDIRQS_SW_RESEND |
7 | 6 | ||
8 | config PPC_XIVE_NATIVE | 7 | config PPC_XIVE_NATIVE |
9 | bool | 8 | bool |
10 | default n | ||
11 | select PPC_XIVE | 9 | select PPC_XIVE |
12 | depends on PPC_POWERNV | 10 | depends on PPC_POWERNV |
13 | 11 | ||
14 | config PPC_XIVE_SPAPR | 12 | config PPC_XIVE_SPAPR |
15 | bool | 13 | bool |
16 | default n | ||
17 | select PPC_XIVE | 14 | select PPC_XIVE |
diff --git a/arch/powerpc/sysdev/xive/Makefile b/arch/powerpc/sysdev/xive/Makefile index 536d6e5706e3..dea2abc23f4d 100644 --- a/arch/powerpc/sysdev/xive/Makefile +++ b/arch/powerpc/sysdev/xive/Makefile | |||
@@ -1,4 +1,3 @@ | |||
1 | subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror | ||
2 | 1 | ||
3 | obj-y += common.o | 2 | obj-y += common.o |
4 | obj-$(CONFIG_PPC_XIVE_NATIVE) += native.o | 3 | obj-$(CONFIG_PPC_XIVE_NATIVE) += native.o |
diff --git a/arch/powerpc/sysdev/xive/common.c b/arch/powerpc/sysdev/xive/common.c index 959a2a62f233..9824074ec1b5 100644 --- a/arch/powerpc/sysdev/xive/common.c +++ b/arch/powerpc/sysdev/xive/common.c | |||
@@ -1010,12 +1010,13 @@ static void xive_ipi_eoi(struct irq_data *d) | |||
1010 | { | 1010 | { |
1011 | struct xive_cpu *xc = __this_cpu_read(xive_cpu); | 1011 | struct xive_cpu *xc = __this_cpu_read(xive_cpu); |
1012 | 1012 | ||
1013 | DBG_VERBOSE("IPI eoi: irq=%d [0x%lx] (HW IRQ 0x%x) pending=%02x\n", | ||
1014 | d->irq, irqd_to_hwirq(d), xc->hw_ipi, xc->pending_prio); | ||
1015 | |||
1016 | /* Handle possible race with unplug and drop stale IPIs */ | 1013 | /* Handle possible race with unplug and drop stale IPIs */ |
1017 | if (!xc) | 1014 | if (!xc) |
1018 | return; | 1015 | return; |
1016 | |||
1017 | DBG_VERBOSE("IPI eoi: irq=%d [0x%lx] (HW IRQ 0x%x) pending=%02x\n", | ||
1018 | d->irq, irqd_to_hwirq(d), xc->hw_ipi, xc->pending_prio); | ||
1019 | |||
1019 | xive_do_source_eoi(xc->hw_ipi, &xc->ipi_data); | 1020 | xive_do_source_eoi(xc->hw_ipi, &xc->ipi_data); |
1020 | xive_do_queue_eoi(xc); | 1021 | xive_do_queue_eoi(xc); |
1021 | } | 1022 | } |
diff --git a/arch/powerpc/sysdev/xive/native.c b/arch/powerpc/sysdev/xive/native.c index 5b20a678d755..1ca127d052a6 100644 --- a/arch/powerpc/sysdev/xive/native.c +++ b/arch/powerpc/sysdev/xive/native.c | |||
@@ -238,20 +238,11 @@ static bool xive_native_match(struct device_node *node) | |||
238 | #ifdef CONFIG_SMP | 238 | #ifdef CONFIG_SMP |
239 | static int xive_native_get_ipi(unsigned int cpu, struct xive_cpu *xc) | 239 | static int xive_native_get_ipi(unsigned int cpu, struct xive_cpu *xc) |
240 | { | 240 | { |
241 | struct device_node *np; | ||
242 | unsigned int chip_id; | ||
243 | s64 irq; | 241 | s64 irq; |
244 | 242 | ||
245 | /* Find the chip ID */ | ||
246 | np = of_get_cpu_node(cpu, NULL); | ||
247 | if (np) { | ||
248 | if (of_property_read_u32(np, "ibm,chip-id", &chip_id) < 0) | ||
249 | chip_id = 0; | ||
250 | } | ||
251 | |||
252 | /* Allocate an IPI and populate info about it */ | 243 | /* Allocate an IPI and populate info about it */ |
253 | for (;;) { | 244 | for (;;) { |
254 | irq = opal_xive_allocate_irq(chip_id); | 245 | irq = opal_xive_allocate_irq(xc->chip_id); |
255 | if (irq == OPAL_BUSY) { | 246 | if (irq == OPAL_BUSY) { |
256 | msleep(OPAL_BUSY_DELAY_MS); | 247 | msleep(OPAL_BUSY_DELAY_MS); |
257 | continue; | 248 | continue; |
diff --git a/arch/powerpc/xmon/Makefile b/arch/powerpc/xmon/Makefile index 1bc3abb237cd..69e7fb47bcaa 100644 --- a/arch/powerpc/xmon/Makefile +++ b/arch/powerpc/xmon/Makefile | |||
@@ -1,14 +1,15 @@ | |||
1 | # SPDX-License-Identifier: GPL-2.0 | 1 | # SPDX-License-Identifier: GPL-2.0 |
2 | # Makefile for xmon | 2 | # Makefile for xmon |
3 | 3 | ||
4 | subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror | 4 | # Disable clang warning for using setjmp without setjmp.h header |
5 | subdir-ccflags-y := $(call cc-disable-warning, builtin-requires-header) | ||
5 | 6 | ||
6 | GCOV_PROFILE := n | 7 | GCOV_PROFILE := n |
7 | UBSAN_SANITIZE := n | 8 | UBSAN_SANITIZE := n |
8 | 9 | ||
9 | # Disable ftrace for the entire directory | 10 | # Disable ftrace for the entire directory |
10 | ORIG_CFLAGS := $(KBUILD_CFLAGS) | 11 | ORIG_CFLAGS := $(KBUILD_CFLAGS) |
11 | KBUILD_CFLAGS = $(subst -mno-sched-epilog,,$(subst $(CC_FLAGS_FTRACE),,$(ORIG_CFLAGS))) | 12 | KBUILD_CFLAGS = $(subst $(CC_FLAGS_FTRACE),,$(ORIG_CFLAGS)) |
12 | 13 | ||
13 | ccflags-$(CONFIG_PPC64) := $(NO_MINIMAL_TOC) | 14 | ccflags-$(CONFIG_PPC64) := $(NO_MINIMAL_TOC) |
14 | 15 | ||
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index 4264aedc7775..36b8dc47a3c3 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c | |||
@@ -2378,25 +2378,33 @@ static void dump_one_paca(int cpu) | |||
2378 | DUMP(p, cpu_start, "%#-*x"); | 2378 | DUMP(p, cpu_start, "%#-*x"); |
2379 | DUMP(p, kexec_state, "%#-*x"); | 2379 | DUMP(p, kexec_state, "%#-*x"); |
2380 | #ifdef CONFIG_PPC_BOOK3S_64 | 2380 | #ifdef CONFIG_PPC_BOOK3S_64 |
2381 | for (i = 0; i < SLB_NUM_BOLTED; i++) { | 2381 | if (!early_radix_enabled()) { |
2382 | u64 esid, vsid; | 2382 | for (i = 0; i < SLB_NUM_BOLTED; i++) { |
2383 | u64 esid, vsid; | ||
2383 | 2384 | ||
2384 | if (!p->slb_shadow_ptr) | 2385 | if (!p->slb_shadow_ptr) |
2385 | continue; | 2386 | continue; |
2387 | |||
2388 | esid = be64_to_cpu(p->slb_shadow_ptr->save_area[i].esid); | ||
2389 | vsid = be64_to_cpu(p->slb_shadow_ptr->save_area[i].vsid); | ||
2386 | 2390 | ||
2387 | esid = be64_to_cpu(p->slb_shadow_ptr->save_area[i].esid); | 2391 | if (esid || vsid) { |
2388 | vsid = be64_to_cpu(p->slb_shadow_ptr->save_area[i].vsid); | 2392 | printf(" %-*s[%d] = 0x%016llx 0x%016llx\n", |
2393 | 22, "slb_shadow", i, esid, vsid); | ||
2394 | } | ||
2395 | } | ||
2396 | DUMP(p, vmalloc_sllp, "%#-*x"); | ||
2397 | DUMP(p, stab_rr, "%#-*x"); | ||
2398 | DUMP(p, slb_used_bitmap, "%#-*x"); | ||
2399 | DUMP(p, slb_kern_bitmap, "%#-*x"); | ||
2389 | 2400 | ||
2390 | if (esid || vsid) { | 2401 | if (!early_cpu_has_feature(CPU_FTR_ARCH_300)) { |
2391 | printf(" %-*s[%d] = 0x%016llx 0x%016llx\n", | 2402 | DUMP(p, slb_cache_ptr, "%#-*x"); |
2392 | 22, "slb_shadow", i, esid, vsid); | 2403 | for (i = 0; i < SLB_CACHE_ENTRIES; i++) |
2404 | printf(" %-*s[%d] = 0x%016x\n", | ||
2405 | 22, "slb_cache", i, p->slb_cache[i]); | ||
2393 | } | 2406 | } |
2394 | } | 2407 | } |
2395 | DUMP(p, vmalloc_sllp, "%#-*x"); | ||
2396 | DUMP(p, slb_cache_ptr, "%#-*x"); | ||
2397 | for (i = 0; i < SLB_CACHE_ENTRIES; i++) | ||
2398 | printf(" %-*s[%d] = 0x%016x\n", | ||
2399 | 22, "slb_cache", i, p->slb_cache[i]); | ||
2400 | 2408 | ||
2401 | DUMP(p, rfi_flush_fallback_area, "%-*px"); | 2409 | DUMP(p, rfi_flush_fallback_area, "%-*px"); |
2402 | #endif | 2410 | #endif |
@@ -2412,7 +2420,9 @@ static void dump_one_paca(int cpu) | |||
2412 | DUMP(p, __current, "%-*px"); | 2420 | DUMP(p, __current, "%-*px"); |
2413 | DUMP(p, kstack, "%#-*llx"); | 2421 | DUMP(p, kstack, "%#-*llx"); |
2414 | printf(" %-*s = 0x%016llx\n", 25, "kstack_base", p->kstack & ~(THREAD_SIZE - 1)); | 2422 | printf(" %-*s = 0x%016llx\n", 25, "kstack_base", p->kstack & ~(THREAD_SIZE - 1)); |
2415 | DUMP(p, stab_rr, "%#-*llx"); | 2423 | #ifdef CONFIG_STACKPROTECTOR |
2424 | DUMP(p, canary, "%#-*lx"); | ||
2425 | #endif | ||
2416 | DUMP(p, saved_r1, "%#-*llx"); | 2426 | DUMP(p, saved_r1, "%#-*llx"); |
2417 | DUMP(p, trap_save, "%#-*x"); | 2427 | DUMP(p, trap_save, "%#-*x"); |
2418 | DUMP(p, irq_soft_mask, "%#-*x"); | 2428 | DUMP(p, irq_soft_mask, "%#-*x"); |
@@ -2444,11 +2454,15 @@ static void dump_one_paca(int cpu) | |||
2444 | 2454 | ||
2445 | DUMP(p, accounting.utime, "%#-*lx"); | 2455 | DUMP(p, accounting.utime, "%#-*lx"); |
2446 | DUMP(p, accounting.stime, "%#-*lx"); | 2456 | DUMP(p, accounting.stime, "%#-*lx"); |
2457 | #ifdef CONFIG_ARCH_HAS_SCALED_CPUTIME | ||
2447 | DUMP(p, accounting.utime_scaled, "%#-*lx"); | 2458 | DUMP(p, accounting.utime_scaled, "%#-*lx"); |
2459 | #endif | ||
2448 | DUMP(p, accounting.starttime, "%#-*lx"); | 2460 | DUMP(p, accounting.starttime, "%#-*lx"); |
2449 | DUMP(p, accounting.starttime_user, "%#-*lx"); | 2461 | DUMP(p, accounting.starttime_user, "%#-*lx"); |
2462 | #ifdef CONFIG_ARCH_HAS_SCALED_CPUTIME | ||
2450 | DUMP(p, accounting.startspurr, "%#-*lx"); | 2463 | DUMP(p, accounting.startspurr, "%#-*lx"); |
2451 | DUMP(p, accounting.utime_sspurr, "%#-*lx"); | 2464 | DUMP(p, accounting.utime_sspurr, "%#-*lx"); |
2465 | #endif | ||
2452 | DUMP(p, accounting.steal_time, "%#-*lx"); | 2466 | DUMP(p, accounting.steal_time, "%#-*lx"); |
2453 | #undef DUMP | 2467 | #undef DUMP |
2454 | 2468 | ||
@@ -2988,15 +3002,17 @@ static void show_task(struct task_struct *tsk) | |||
2988 | #ifdef CONFIG_PPC_BOOK3S_64 | 3002 | #ifdef CONFIG_PPC_BOOK3S_64 |
2989 | void format_pte(void *ptep, unsigned long pte) | 3003 | void format_pte(void *ptep, unsigned long pte) |
2990 | { | 3004 | { |
3005 | pte_t entry = __pte(pte); | ||
3006 | |||
2991 | printf("ptep @ 0x%016lx = 0x%016lx\n", (unsigned long)ptep, pte); | 3007 | printf("ptep @ 0x%016lx = 0x%016lx\n", (unsigned long)ptep, pte); |
2992 | printf("Maps physical address = 0x%016lx\n", pte & PTE_RPN_MASK); | 3008 | printf("Maps physical address = 0x%016lx\n", pte & PTE_RPN_MASK); |
2993 | 3009 | ||
2994 | printf("Flags = %s%s%s%s%s\n", | 3010 | printf("Flags = %s%s%s%s%s\n", |
2995 | (pte & _PAGE_ACCESSED) ? "Accessed " : "", | 3011 | pte_young(entry) ? "Accessed " : "", |
2996 | (pte & _PAGE_DIRTY) ? "Dirty " : "", | 3012 | pte_dirty(entry) ? "Dirty " : "", |
2997 | (pte & _PAGE_READ) ? "Read " : "", | 3013 | pte_read(entry) ? "Read " : "", |
2998 | (pte & _PAGE_WRITE) ? "Write " : "", | 3014 | pte_write(entry) ? "Write " : "", |
2999 | (pte & _PAGE_EXEC) ? "Exec " : ""); | 3015 | pte_exec(entry) ? "Exec " : ""); |
3000 | } | 3016 | } |
3001 | 3017 | ||
3002 | static void show_pte(unsigned long addr) | 3018 | static void show_pte(unsigned long addr) |
diff --git a/drivers/block/z2ram.c b/drivers/block/z2ram.c index 1106c076fa4b..600430685e28 100644 --- a/drivers/block/z2ram.c +++ b/drivers/block/z2ram.c | |||
@@ -191,8 +191,7 @@ static int z2_open(struct block_device *bdev, fmode_t mode) | |||
191 | vfree(vmalloc (size)); | 191 | vfree(vmalloc (size)); |
192 | } | 192 | } |
193 | 193 | ||
194 | vaddr = (unsigned long) __ioremap (paddr, size, | 194 | vaddr = (unsigned long)ioremap_wt(paddr, size); |
195 | _PAGE_WRITETHRU); | ||
196 | 195 | ||
197 | #else | 196 | #else |
198 | vaddr = (unsigned long)z_remap_nocache_nonser(paddr, size); | 197 | vaddr = (unsigned long)z_remap_nocache_nonser(paddr, size); |
diff --git a/drivers/macintosh/adb-iop.c b/drivers/macintosh/adb-iop.c index ca623e6446e4..fca31640e3ef 100644 --- a/drivers/macintosh/adb-iop.c +++ b/drivers/macintosh/adb-iop.c | |||
@@ -20,13 +20,13 @@ | |||
20 | #include <linux/init.h> | 20 | #include <linux/init.h> |
21 | #include <linux/proc_fs.h> | 21 | #include <linux/proc_fs.h> |
22 | 22 | ||
23 | #include <asm/macintosh.h> | 23 | #include <asm/macintosh.h> |
24 | #include <asm/macints.h> | 24 | #include <asm/macints.h> |
25 | #include <asm/mac_iop.h> | 25 | #include <asm/mac_iop.h> |
26 | #include <asm/mac_oss.h> | 26 | #include <asm/mac_oss.h> |
27 | #include <asm/adb_iop.h> | 27 | #include <asm/adb_iop.h> |
28 | 28 | ||
29 | #include <linux/adb.h> | 29 | #include <linux/adb.h> |
30 | 30 | ||
31 | /*#define DEBUG_ADB_IOP*/ | 31 | /*#define DEBUG_ADB_IOP*/ |
32 | 32 | ||
@@ -38,9 +38,9 @@ static unsigned char *reply_ptr; | |||
38 | #endif | 38 | #endif |
39 | 39 | ||
40 | static enum adb_iop_state { | 40 | static enum adb_iop_state { |
41 | idle, | 41 | idle, |
42 | sending, | 42 | sending, |
43 | awaiting_reply | 43 | awaiting_reply |
44 | } adb_iop_state; | 44 | } adb_iop_state; |
45 | 45 | ||
46 | static void adb_iop_start(void); | 46 | static void adb_iop_start(void); |
@@ -66,7 +66,8 @@ static void adb_iop_end_req(struct adb_request *req, int state) | |||
66 | { | 66 | { |
67 | req->complete = 1; | 67 | req->complete = 1; |
68 | current_req = req->next; | 68 | current_req = req->next; |
69 | if (req->done) (*req->done)(req); | 69 | if (req->done) |
70 | (*req->done)(req); | ||
70 | adb_iop_state = state; | 71 | adb_iop_state = state; |
71 | } | 72 | } |
72 | 73 | ||
@@ -100,7 +101,7 @@ static void adb_iop_complete(struct iop_msg *msg) | |||
100 | 101 | ||
101 | static void adb_iop_listen(struct iop_msg *msg) | 102 | static void adb_iop_listen(struct iop_msg *msg) |
102 | { | 103 | { |
103 | struct adb_iopmsg *amsg = (struct adb_iopmsg *) msg->message; | 104 | struct adb_iopmsg *amsg = (struct adb_iopmsg *)msg->message; |
104 | struct adb_request *req; | 105 | struct adb_request *req; |
105 | unsigned long flags; | 106 | unsigned long flags; |
106 | #ifdef DEBUG_ADB_IOP | 107 | #ifdef DEBUG_ADB_IOP |
@@ -113,9 +114,9 @@ static void adb_iop_listen(struct iop_msg *msg) | |||
113 | 114 | ||
114 | #ifdef DEBUG_ADB_IOP | 115 | #ifdef DEBUG_ADB_IOP |
115 | printk("adb_iop_listen %p: rcvd packet, %d bytes: %02X %02X", req, | 116 | printk("adb_iop_listen %p: rcvd packet, %d bytes: %02X %02X", req, |
116 | (uint) amsg->count + 2, (uint) amsg->flags, (uint) amsg->cmd); | 117 | (uint)amsg->count + 2, (uint)amsg->flags, (uint)amsg->cmd); |
117 | for (i = 0; i < amsg->count; i++) | 118 | for (i = 0; i < amsg->count; i++) |
118 | printk(" %02X", (uint) amsg->data[i]); | 119 | printk(" %02X", (uint)amsg->data[i]); |
119 | printk("\n"); | 120 | printk("\n"); |
120 | #endif | 121 | #endif |
121 | 122 | ||
@@ -168,14 +169,15 @@ static void adb_iop_start(void) | |||
168 | 169 | ||
169 | /* get the packet to send */ | 170 | /* get the packet to send */ |
170 | req = current_req; | 171 | req = current_req; |
171 | if (!req) return; | 172 | if (!req) |
173 | return; | ||
172 | 174 | ||
173 | local_irq_save(flags); | 175 | local_irq_save(flags); |
174 | 176 | ||
175 | #ifdef DEBUG_ADB_IOP | 177 | #ifdef DEBUG_ADB_IOP |
176 | printk("adb_iop_start %p: sending packet, %d bytes:", req, req->nbytes); | 178 | printk("adb_iop_start %p: sending packet, %d bytes:", req, req->nbytes); |
177 | for (i = 0 ; i < req->nbytes ; i++) | 179 | for (i = 0; i < req->nbytes; i++) |
178 | printk(" %02X", (uint) req->data[i]); | 180 | printk(" %02X", (uint)req->data[i]); |
179 | printk("\n"); | 181 | printk("\n"); |
180 | #endif | 182 | #endif |
181 | 183 | ||
@@ -196,19 +198,20 @@ static void adb_iop_start(void) | |||
196 | /* Now send it. The IOP manager will call adb_iop_complete */ | 198 | /* Now send it. The IOP manager will call adb_iop_complete */ |
197 | /* when the packet has been sent. */ | 199 | /* when the packet has been sent. */ |
198 | 200 | ||
199 | iop_send_message(ADB_IOP, ADB_CHAN, req, | 201 | iop_send_message(ADB_IOP, ADB_CHAN, req, sizeof(amsg), (__u8 *)&amsg, |
200 | sizeof(amsg), (__u8 *) &amsg, adb_iop_complete); | 202 | adb_iop_complete); |
201 | } | 203 | } |
202 | 204 | ||
203 | int adb_iop_probe(void) | 205 | int adb_iop_probe(void) |
204 | { | 206 | { |
205 | if (!iop_ism_present) return -ENODEV; | 207 | if (!iop_ism_present) |
208 | return -ENODEV; | ||
206 | return 0; | 209 | return 0; |
207 | } | 210 | } |
208 | 211 | ||
209 | int adb_iop_init(void) | 212 | int adb_iop_init(void) |
210 | { | 213 | { |
211 | printk("adb: IOP ISM driver v0.4 for Unified ADB.\n"); | 214 | pr_info("adb: IOP ISM driver v0.4 for Unified ADB\n"); |
212 | iop_listen(ADB_IOP, ADB_CHAN, adb_iop_listen, "ADB"); | 215 | iop_listen(ADB_IOP, ADB_CHAN, adb_iop_listen, "ADB"); |
213 | return 0; | 216 | return 0; |
214 | } | 217 | } |
@@ -218,10 +221,12 @@ int adb_iop_send_request(struct adb_request *req, int sync) | |||
218 | int err; | 221 | int err; |
219 | 222 | ||
220 | err = adb_iop_write(req); | 223 | err = adb_iop_write(req); |
221 | if (err) return err; | 224 | if (err) |
225 | return err; | ||
222 | 226 | ||
223 | if (sync) { | 227 | if (sync) { |
224 | while (!req->complete) adb_iop_poll(); | 228 | while (!req->complete) |
229 | adb_iop_poll(); | ||
225 | } | 230 | } |
226 | return 0; | 231 | return 0; |
227 | } | 232 | } |
@@ -251,7 +256,9 @@ static int adb_iop_write(struct adb_request *req) | |||
251 | } | 256 | } |
252 | 257 | ||
253 | local_irq_restore(flags); | 258 | local_irq_restore(flags); |
254 | if (adb_iop_state == idle) adb_iop_start(); | 259 | |
260 | if (adb_iop_state == idle) | ||
261 | adb_iop_start(); | ||
255 | return 0; | 262 | return 0; |
256 | } | 263 | } |
257 | 264 | ||
@@ -263,7 +270,8 @@ int adb_iop_autopoll(int devs) | |||
263 | 270 | ||
264 | void adb_iop_poll(void) | 271 | void adb_iop_poll(void) |
265 | { | 272 | { |
266 | if (adb_iop_state == idle) adb_iop_start(); | 273 | if (adb_iop_state == idle) |
274 | adb_iop_start(); | ||
267 | iop_ism_irq_poll(ADB_IOP); | 275 | iop_ism_irq_poll(ADB_IOP); |
268 | } | 276 | } |
269 | 277 | ||
diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c index 76e98f0f7a3e..e49d1f287a17 100644 --- a/drivers/macintosh/adb.c +++ b/drivers/macintosh/adb.c | |||
@@ -203,15 +203,15 @@ static int adb_scan_bus(void) | |||
203 | } | 203 | } |
204 | 204 | ||
205 | /* Now fill in the handler_id field of the adb_handler entries. */ | 205 | /* Now fill in the handler_id field of the adb_handler entries. */ |
206 | pr_debug("adb devices:\n"); | ||
207 | for (i = 1; i < 16; i++) { | 206 | for (i = 1; i < 16; i++) { |
208 | if (adb_handler[i].original_address == 0) | 207 | if (adb_handler[i].original_address == 0) |
209 | continue; | 208 | continue; |
210 | adb_request(&req, NULL, ADBREQ_SYNC | ADBREQ_REPLY, 1, | 209 | adb_request(&req, NULL, ADBREQ_SYNC | ADBREQ_REPLY, 1, |
211 | (i << 4) | 0xf); | 210 | (i << 4) | 0xf); |
212 | adb_handler[i].handler_id = req.reply[2]; | 211 | adb_handler[i].handler_id = req.reply[2]; |
213 | pr_debug(" [%d]: %d %x\n", i, adb_handler[i].original_address, | 212 | printk(KERN_DEBUG "adb device [%d]: %d 0x%X\n", i, |
214 | adb_handler[i].handler_id); | 213 | adb_handler[i].original_address, |
214 | adb_handler[i].handler_id); | ||
215 | devmask |= 1 << i; | 215 | devmask |= 1 << i; |
216 | } | 216 | } |
217 | return devmask; | 217 | return devmask; |
@@ -579,6 +579,8 @@ adb_try_handler_change(int address, int new_id) | |||
579 | mutex_lock(&adb_handler_mutex); | 579 | mutex_lock(&adb_handler_mutex); |
580 | ret = try_handler_change(address, new_id); | 580 | ret = try_handler_change(address, new_id); |
581 | mutex_unlock(&adb_handler_mutex); | 581 | mutex_unlock(&adb_handler_mutex); |
582 | if (ret) | ||
583 | pr_debug("adb handler change: [%d] 0x%X\n", address, new_id); | ||
582 | return ret; | 584 | return ret; |
583 | } | 585 | } |
584 | EXPORT_SYMBOL(adb_try_handler_change); | 586 | EXPORT_SYMBOL(adb_try_handler_change); |
diff --git a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c index a261892c03b3..75482eeab2c4 100644 --- a/drivers/macintosh/adbhid.c +++ b/drivers/macintosh/adbhid.c | |||
@@ -757,6 +757,7 @@ adbhid_input_register(int id, int default_id, int original_handler_id, | |||
757 | struct input_dev *input_dev; | 757 | struct input_dev *input_dev; |
758 | int err; | 758 | int err; |
759 | int i; | 759 | int i; |
760 | char *keyboard_type; | ||
760 | 761 | ||
761 | if (adbhid[id]) { | 762 | if (adbhid[id]) { |
762 | pr_err("Trying to reregister ADB HID on ID %d\n", id); | 763 | pr_err("Trying to reregister ADB HID on ID %d\n", id); |
@@ -798,24 +799,23 @@ adbhid_input_register(int id, int default_id, int original_handler_id, | |||
798 | 799 | ||
799 | memcpy(hid->keycode, adb_to_linux_keycodes, sizeof(adb_to_linux_keycodes)); | 800 | memcpy(hid->keycode, adb_to_linux_keycodes, sizeof(adb_to_linux_keycodes)); |
800 | 801 | ||
801 | pr_info("Detected ADB keyboard, type "); | ||
802 | switch (original_handler_id) { | 802 | switch (original_handler_id) { |
803 | default: | 803 | default: |
804 | pr_cont("<unknown>.\n"); | 804 | keyboard_type = "<unknown>"; |
805 | input_dev->id.version = ADB_KEYBOARD_UNKNOWN; | 805 | input_dev->id.version = ADB_KEYBOARD_UNKNOWN; |
806 | break; | 806 | break; |
807 | 807 | ||
808 | case 0x01: case 0x02: case 0x03: case 0x06: case 0x08: | 808 | case 0x01: case 0x02: case 0x03: case 0x06: case 0x08: |
809 | case 0x0C: case 0x10: case 0x18: case 0x1B: case 0x1C: | 809 | case 0x0C: case 0x10: case 0x18: case 0x1B: case 0x1C: |
810 | case 0xC0: case 0xC3: case 0xC6: | 810 | case 0xC0: case 0xC3: case 0xC6: |
811 | pr_cont("ANSI.\n"); | 811 | keyboard_type = "ANSI"; |
812 | input_dev->id.version = ADB_KEYBOARD_ANSI; | 812 | input_dev->id.version = ADB_KEYBOARD_ANSI; |
813 | break; | 813 | break; |
814 | 814 | ||
815 | case 0x04: case 0x05: case 0x07: case 0x09: case 0x0D: | 815 | case 0x04: case 0x05: case 0x07: case 0x09: case 0x0D: |
816 | case 0x11: case 0x14: case 0x19: case 0x1D: case 0xC1: | 816 | case 0x11: case 0x14: case 0x19: case 0x1D: case 0xC1: |
817 | case 0xC4: case 0xC7: | 817 | case 0xC4: case 0xC7: |
818 | pr_cont("ISO, swapping keys.\n"); | 818 | keyboard_type = "ISO, swapping keys"; |
819 | input_dev->id.version = ADB_KEYBOARD_ISO; | 819 | input_dev->id.version = ADB_KEYBOARD_ISO; |
820 | i = hid->keycode[10]; | 820 | i = hid->keycode[10]; |
821 | hid->keycode[10] = hid->keycode[50]; | 821 | hid->keycode[10] = hid->keycode[50]; |
@@ -824,10 +824,11 @@ adbhid_input_register(int id, int default_id, int original_handler_id, | |||
824 | 824 | ||
825 | case 0x12: case 0x15: case 0x16: case 0x17: case 0x1A: | 825 | case 0x12: case 0x15: case 0x16: case 0x17: case 0x1A: |
826 | case 0x1E: case 0xC2: case 0xC5: case 0xC8: case 0xC9: | 826 | case 0x1E: case 0xC2: case 0xC5: case 0xC8: case 0xC9: |
827 | pr_cont("JIS.\n"); | 827 | keyboard_type = "JIS"; |
828 | input_dev->id.version = ADB_KEYBOARD_JIS; | 828 | input_dev->id.version = ADB_KEYBOARD_JIS; |
829 | break; | 829 | break; |
830 | } | 830 | } |
831 | pr_info("Detected ADB keyboard, type %s.\n", keyboard_type); | ||
831 | 832 | ||
832 | for (i = 0; i < 128; i++) | 833 | for (i = 0; i < 128; i++) |
833 | if (hid->keycode[i]) | 834 | if (hid->keycode[i]) |
@@ -972,16 +973,13 @@ adbhid_probe(void) | |||
972 | ->get it to send separate codes for left and right shift, | 973 | ->get it to send separate codes for left and right shift, |
973 | control, option keys */ | 974 | control, option keys */ |
974 | #if 0 /* handler 5 doesn't send separate codes for R modifiers */ | 975 | #if 0 /* handler 5 doesn't send separate codes for R modifiers */ |
975 | if (adb_try_handler_change(id, 5)) | 976 | if (!adb_try_handler_change(id, 5)) |
976 | printk("ADB keyboard at %d, handler set to 5\n", id); | ||
977 | else | ||
978 | #endif | 977 | #endif |
979 | if (adb_try_handler_change(id, 3)) | 978 | adb_try_handler_change(id, 3); |
980 | printk("ADB keyboard at %d, handler set to 3\n", id); | ||
981 | else | ||
982 | printk("ADB keyboard at %d, handler 1\n", id); | ||
983 | 979 | ||
984 | adb_get_infos(id, &default_id, &cur_handler_id); | 980 | adb_get_infos(id, &default_id, &cur_handler_id); |
981 | printk(KERN_DEBUG "ADB keyboard at %d has handler 0x%X\n", | ||
982 | id, cur_handler_id); | ||
985 | reg |= adbhid_input_reregister(id, default_id, org_handler_id, | 983 | reg |= adbhid_input_reregister(id, default_id, org_handler_id, |
986 | cur_handler_id, 0); | 984 | cur_handler_id, 0); |
987 | } | 985 | } |
@@ -999,48 +997,44 @@ adbhid_probe(void) | |||
999 | for (i = 0; i < mouse_ids.nids; i++) { | 997 | for (i = 0; i < mouse_ids.nids; i++) { |
1000 | int id = mouse_ids.id[i]; | 998 | int id = mouse_ids.id[i]; |
1001 | int mouse_kind; | 999 | int mouse_kind; |
1000 | char *desc = "standard"; | ||
1002 | 1001 | ||
1003 | adb_get_infos(id, &default_id, &org_handler_id); | 1002 | adb_get_infos(id, &default_id, &org_handler_id); |
1004 | 1003 | ||
1005 | if (adb_try_handler_change(id, 4)) { | 1004 | if (adb_try_handler_change(id, 4)) { |
1006 | printk("ADB mouse at %d, handler set to 4", id); | ||
1007 | mouse_kind = ADBMOUSE_EXTENDED; | 1005 | mouse_kind = ADBMOUSE_EXTENDED; |
1008 | } | 1006 | } |
1009 | else if (adb_try_handler_change(id, 0x2F)) { | 1007 | else if (adb_try_handler_change(id, 0x2F)) { |
1010 | printk("ADB mouse at %d, handler set to 0x2F", id); | ||
1011 | mouse_kind = ADBMOUSE_MICROSPEED; | 1008 | mouse_kind = ADBMOUSE_MICROSPEED; |
1012 | } | 1009 | } |
1013 | else if (adb_try_handler_change(id, 0x42)) { | 1010 | else if (adb_try_handler_change(id, 0x42)) { |
1014 | printk("ADB mouse at %d, handler set to 0x42", id); | ||
1015 | mouse_kind = ADBMOUSE_TRACKBALLPRO; | 1011 | mouse_kind = ADBMOUSE_TRACKBALLPRO; |
1016 | } | 1012 | } |
1017 | else if (adb_try_handler_change(id, 0x66)) { | 1013 | else if (adb_try_handler_change(id, 0x66)) { |
1018 | printk("ADB mouse at %d, handler set to 0x66", id); | ||
1019 | mouse_kind = ADBMOUSE_MICROSPEED; | 1014 | mouse_kind = ADBMOUSE_MICROSPEED; |
1020 | } | 1015 | } |
1021 | else if (adb_try_handler_change(id, 0x5F)) { | 1016 | else if (adb_try_handler_change(id, 0x5F)) { |
1022 | printk("ADB mouse at %d, handler set to 0x5F", id); | ||
1023 | mouse_kind = ADBMOUSE_MICROSPEED; | 1017 | mouse_kind = ADBMOUSE_MICROSPEED; |
1024 | } | 1018 | } |
1025 | else if (adb_try_handler_change(id, 3)) { | 1019 | else if (adb_try_handler_change(id, 3)) { |
1026 | printk("ADB mouse at %d, handler set to 3", id); | ||
1027 | mouse_kind = ADBMOUSE_MS_A3; | 1020 | mouse_kind = ADBMOUSE_MS_A3; |
1028 | } | 1021 | } |
1029 | else if (adb_try_handler_change(id, 2)) { | 1022 | else if (adb_try_handler_change(id, 2)) { |
1030 | printk("ADB mouse at %d, handler set to 2", id); | ||
1031 | mouse_kind = ADBMOUSE_STANDARD_200; | 1023 | mouse_kind = ADBMOUSE_STANDARD_200; |
1032 | } | 1024 | } |
1033 | else { | 1025 | else { |
1034 | printk("ADB mouse at %d, handler 1", id); | ||
1035 | mouse_kind = ADBMOUSE_STANDARD_100; | 1026 | mouse_kind = ADBMOUSE_STANDARD_100; |
1036 | } | 1027 | } |
1037 | 1028 | ||
1038 | if ((mouse_kind == ADBMOUSE_TRACKBALLPRO) | 1029 | if ((mouse_kind == ADBMOUSE_TRACKBALLPRO) |
1039 | || (mouse_kind == ADBMOUSE_MICROSPEED)) { | 1030 | || (mouse_kind == ADBMOUSE_MICROSPEED)) { |
1031 | desc = "Microspeed/MacPoint or compatible"; | ||
1040 | init_microspeed(id); | 1032 | init_microspeed(id); |
1041 | } else if (mouse_kind == ADBMOUSE_MS_A3) { | 1033 | } else if (mouse_kind == ADBMOUSE_MS_A3) { |
1034 | desc = "Mouse Systems A3 Mouse or compatible"; | ||
1042 | init_ms_a3(id); | 1035 | init_ms_a3(id); |
1043 | } else if (mouse_kind == ADBMOUSE_EXTENDED) { | 1036 | } else if (mouse_kind == ADBMOUSE_EXTENDED) { |
1037 | desc = "extended"; | ||
1044 | /* | 1038 | /* |
1045 | * Register 1 is usually used for device | 1039 | * Register 1 is usually used for device |
1046 | * identification. Here, we try to identify | 1040 | * identification. Here, we try to identify |
@@ -1054,32 +1048,36 @@ adbhid_probe(void) | |||
1054 | (req.reply[1] == 0x9a) && ((req.reply[2] == 0x21) | 1048 | (req.reply[1] == 0x9a) && ((req.reply[2] == 0x21) |
1055 | || (req.reply[2] == 0x20))) { | 1049 | || (req.reply[2] == 0x20))) { |
1056 | mouse_kind = ADBMOUSE_TRACKBALL; | 1050 | mouse_kind = ADBMOUSE_TRACKBALL; |
1051 | desc = "trackman/mouseman"; | ||
1057 | init_trackball(id); | 1052 | init_trackball(id); |
1058 | } | 1053 | } |
1059 | else if ((req.reply_len >= 4) && | 1054 | else if ((req.reply_len >= 4) && |
1060 | (req.reply[1] == 0x74) && (req.reply[2] == 0x70) && | 1055 | (req.reply[1] == 0x74) && (req.reply[2] == 0x70) && |
1061 | (req.reply[3] == 0x61) && (req.reply[4] == 0x64)) { | 1056 | (req.reply[3] == 0x61) && (req.reply[4] == 0x64)) { |
1062 | mouse_kind = ADBMOUSE_TRACKPAD; | 1057 | mouse_kind = ADBMOUSE_TRACKPAD; |
1058 | desc = "trackpad"; | ||
1063 | init_trackpad(id); | 1059 | init_trackpad(id); |
1064 | } | 1060 | } |
1065 | else if ((req.reply_len >= 4) && | 1061 | else if ((req.reply_len >= 4) && |
1066 | (req.reply[1] == 0x4b) && (req.reply[2] == 0x4d) && | 1062 | (req.reply[1] == 0x4b) && (req.reply[2] == 0x4d) && |
1067 | (req.reply[3] == 0x4c) && (req.reply[4] == 0x31)) { | 1063 | (req.reply[3] == 0x4c) && (req.reply[4] == 0x31)) { |
1068 | mouse_kind = ADBMOUSE_TURBOMOUSE5; | 1064 | mouse_kind = ADBMOUSE_TURBOMOUSE5; |
1065 | desc = "TurboMouse 5"; | ||
1069 | init_turbomouse(id); | 1066 | init_turbomouse(id); |
1070 | } | 1067 | } |
1071 | else if ((req.reply_len == 9) && | 1068 | else if ((req.reply_len == 9) && |
1072 | (req.reply[1] == 0x4b) && (req.reply[2] == 0x4f) && | 1069 | (req.reply[1] == 0x4b) && (req.reply[2] == 0x4f) && |
1073 | (req.reply[3] == 0x49) && (req.reply[4] == 0x54)) { | 1070 | (req.reply[3] == 0x49) && (req.reply[4] == 0x54)) { |
1074 | if (adb_try_handler_change(id, 0x42)) { | 1071 | if (adb_try_handler_change(id, 0x42)) { |
1075 | pr_cont("\nADB MacAlly 2-button mouse at %d, handler set to 0x42", id); | ||
1076 | mouse_kind = ADBMOUSE_MACALLY2; | 1072 | mouse_kind = ADBMOUSE_MACALLY2; |
1073 | desc = "MacAlly 2-button"; | ||
1077 | } | 1074 | } |
1078 | } | 1075 | } |
1079 | } | 1076 | } |
1080 | pr_cont("\n"); | ||
1081 | 1077 | ||
1082 | adb_get_infos(id, &default_id, &cur_handler_id); | 1078 | adb_get_infos(id, &default_id, &cur_handler_id); |
1079 | printk(KERN_DEBUG "ADB mouse (%s) at %d has handler 0x%X\n", | ||
1080 | desc, id, cur_handler_id); | ||
1083 | reg |= adbhid_input_reregister(id, default_id, org_handler_id, | 1081 | reg |= adbhid_input_reregister(id, default_id, org_handler_id, |
1084 | cur_handler_id, mouse_kind); | 1082 | cur_handler_id, mouse_kind); |
1085 | } | 1083 | } |
@@ -1092,12 +1090,10 @@ init_trackpad(int id) | |||
1092 | struct adb_request req; | 1090 | struct adb_request req; |
1093 | unsigned char r1_buffer[8]; | 1091 | unsigned char r1_buffer[8]; |
1094 | 1092 | ||
1095 | pr_cont(" (trackpad)"); | ||
1096 | |||
1097 | adb_request(&req, NULL, ADBREQ_SYNC | ADBREQ_REPLY, 1, | 1093 | adb_request(&req, NULL, ADBREQ_SYNC | ADBREQ_REPLY, 1, |
1098 | ADB_READREG(id,1)); | 1094 | ADB_READREG(id,1)); |
1099 | if (req.reply_len < 8) | 1095 | if (req.reply_len < 8) |
1100 | pr_cont("bad length for reg. 1\n"); | 1096 | pr_err("%s: bad length for reg. 1\n", __func__); |
1101 | else | 1097 | else |
1102 | { | 1098 | { |
1103 | memcpy(r1_buffer, &req.reply[1], 8); | 1099 | memcpy(r1_buffer, &req.reply[1], 8); |
@@ -1145,8 +1141,6 @@ init_trackball(int id) | |||
1145 | { | 1141 | { |
1146 | struct adb_request req; | 1142 | struct adb_request req; |
1147 | 1143 | ||
1148 | pr_cont(" (trackman/mouseman)"); | ||
1149 | |||
1150 | adb_request(&req, NULL, ADBREQ_SYNC, 3, | 1144 | adb_request(&req, NULL, ADBREQ_SYNC, 3, |
1151 | ADB_WRITEREG(id,1), 00,0x81); | 1145 | ADB_WRITEREG(id,1), 00,0x81); |
1152 | 1146 | ||
@@ -1177,8 +1171,6 @@ init_turbomouse(int id) | |||
1177 | { | 1171 | { |
1178 | struct adb_request req; | 1172 | struct adb_request req; |
1179 | 1173 | ||
1180 | pr_cont(" (TurboMouse 5)"); | ||
1181 | |||
1182 | adb_request(&req, NULL, ADBREQ_SYNC, 1, ADB_FLUSH(id)); | 1174 | adb_request(&req, NULL, ADBREQ_SYNC, 1, ADB_FLUSH(id)); |
1183 | 1175 | ||
1184 | adb_request(&req, NULL, ADBREQ_SYNC, 1, ADB_FLUSH(3)); | 1176 | adb_request(&req, NULL, ADBREQ_SYNC, 1, ADB_FLUSH(3)); |
@@ -1213,8 +1205,6 @@ init_microspeed(int id) | |||
1213 | { | 1205 | { |
1214 | struct adb_request req; | 1206 | struct adb_request req; |
1215 | 1207 | ||
1216 | pr_cont(" (Microspeed/MacPoint or compatible)"); | ||
1217 | |||
1218 | adb_request(&req, NULL, ADBREQ_SYNC, 1, ADB_FLUSH(id)); | 1208 | adb_request(&req, NULL, ADBREQ_SYNC, 1, ADB_FLUSH(id)); |
1219 | 1209 | ||
1220 | /* This will initialize mice using the Microspeed, MacPoint and | 1210 | /* This will initialize mice using the Microspeed, MacPoint and |
@@ -1253,7 +1243,6 @@ init_ms_a3(int id) | |||
1253 | { | 1243 | { |
1254 | struct adb_request req; | 1244 | struct adb_request req; |
1255 | 1245 | ||
1256 | pr_cont(" (Mouse Systems A3 Mouse, or compatible)"); | ||
1257 | adb_request(&req, NULL, ADBREQ_SYNC, 3, | 1246 | adb_request(&req, NULL, ADBREQ_SYNC, 3, |
1258 | ADB_WRITEREG(id, 0x2), | 1247 | ADB_WRITEREG(id, 0x2), |
1259 | 0x00, | 1248 | 0x00, |
diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c index 07074820a167..17d3bc917562 100644 --- a/drivers/macintosh/macio_asic.c +++ b/drivers/macintosh/macio_asic.c | |||
@@ -360,9 +360,10 @@ static struct macio_dev * macio_add_one_device(struct macio_chip *chip, | |||
360 | struct macio_dev *in_bay, | 360 | struct macio_dev *in_bay, |
361 | struct resource *parent_res) | 361 | struct resource *parent_res) |
362 | { | 362 | { |
363 | char name[MAX_NODE_NAME_SIZE + 1]; | ||
363 | struct macio_dev *dev; | 364 | struct macio_dev *dev; |
364 | const u32 *reg; | 365 | const u32 *reg; |
365 | 366 | ||
366 | if (np == NULL) | 367 | if (np == NULL) |
367 | return NULL; | 368 | return NULL; |
368 | 369 | ||
@@ -402,6 +403,7 @@ static struct macio_dev * macio_add_one_device(struct macio_chip *chip, | |||
402 | #endif | 403 | #endif |
403 | 404 | ||
404 | /* MacIO itself has a different reg, we use it's PCI base */ | 405 | /* MacIO itself has a different reg, we use it's PCI base */ |
406 | snprintf(name, sizeof(name), "%pOFn", np); | ||
405 | if (np == chip->of_node) { | 407 | if (np == chip->of_node) { |
406 | dev_set_name(&dev->ofdev.dev, "%1d.%08x:%.*s", | 408 | dev_set_name(&dev->ofdev.dev, "%1d.%08x:%.*s", |
407 | chip->lbus.index, | 409 | chip->lbus.index, |
@@ -410,12 +412,12 @@ static struct macio_dev * macio_add_one_device(struct macio_chip *chip, | |||
410 | #else | 412 | #else |
411 | 0, /* NuBus may want to do something better here */ | 413 | 0, /* NuBus may want to do something better here */ |
412 | #endif | 414 | #endif |
413 | MAX_NODE_NAME_SIZE, np->name); | 415 | MAX_NODE_NAME_SIZE, name); |
414 | } else { | 416 | } else { |
415 | reg = of_get_property(np, "reg", NULL); | 417 | reg = of_get_property(np, "reg", NULL); |
416 | dev_set_name(&dev->ofdev.dev, "%1d.%08x:%.*s", | 418 | dev_set_name(&dev->ofdev.dev, "%1d.%08x:%.*s", |
417 | chip->lbus.index, | 419 | chip->lbus.index, |
418 | reg ? *reg : 0, MAX_NODE_NAME_SIZE, np->name); | 420 | reg ? *reg : 0, MAX_NODE_NAME_SIZE, name); |
419 | } | 421 | } |
420 | 422 | ||
421 | /* Setup interrupts & resources */ | 423 | /* Setup interrupts & resources */ |
diff --git a/drivers/macintosh/macio_sysfs.c b/drivers/macintosh/macio_sysfs.c index ca4fcffe454b..d2451e58acb9 100644 --- a/drivers/macintosh/macio_sysfs.c +++ b/drivers/macintosh/macio_sysfs.c | |||
@@ -58,7 +58,13 @@ static ssize_t devspec_show(struct device *dev, | |||
58 | static DEVICE_ATTR_RO(modalias); | 58 | static DEVICE_ATTR_RO(modalias); |
59 | static DEVICE_ATTR_RO(devspec); | 59 | static DEVICE_ATTR_RO(devspec); |
60 | 60 | ||
61 | macio_config_of_attr (name, "%s\n"); | 61 | static ssize_t name_show(struct device *dev, |
62 | struct device_attribute *attr, char *buf) | ||
63 | { | ||
64 | return sprintf(buf, "%pOFn\n", dev->of_node); | ||
65 | } | ||
66 | static DEVICE_ATTR_RO(name); | ||
67 | |||
62 | macio_config_of_attr (type, "%s\n"); | 68 | macio_config_of_attr (type, "%s\n"); |
63 | 69 | ||
64 | static struct attribute *macio_dev_attrs[] = { | 70 | static struct attribute *macio_dev_attrs[] = { |
diff --git a/drivers/macintosh/via-cuda.c b/drivers/macintosh/via-cuda.c index 98dd702eb867..bbec6ac0a966 100644 --- a/drivers/macintosh/via-cuda.c +++ b/drivers/macintosh/via-cuda.c | |||
@@ -766,3 +766,38 @@ cuda_input(unsigned char *buf, int nb) | |||
766 | buf, nb, false); | 766 | buf, nb, false); |
767 | } | 767 | } |
768 | } | 768 | } |
769 | |||
770 | /* Offset between Unix time (1970-based) and Mac time (1904-based) */ | ||
771 | #define RTC_OFFSET 2082844800 | ||
772 | |||
773 | time64_t cuda_get_time(void) | ||
774 | { | ||
775 | struct adb_request req; | ||
776 | u32 now; | ||
777 | |||
778 | if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME) < 0) | ||
779 | return 0; | ||
780 | while (!req.complete) | ||
781 | cuda_poll(); | ||
782 | if (req.reply_len != 7) | ||
783 | pr_err("%s: got %d byte reply\n", __func__, req.reply_len); | ||
784 | now = (req.reply[3] << 24) + (req.reply[4] << 16) + | ||
785 | (req.reply[5] << 8) + req.reply[6]; | ||
786 | return (time64_t)now - RTC_OFFSET; | ||
787 | } | ||
788 | |||
789 | int cuda_set_rtc_time(struct rtc_time *tm) | ||
790 | { | ||
791 | u32 now; | ||
792 | struct adb_request req; | ||
793 | |||
794 | now = lower_32_bits(rtc_tm_to_time64(tm) + RTC_OFFSET); | ||
795 | if (cuda_request(&req, NULL, 6, CUDA_PACKET, CUDA_SET_TIME, | ||
796 | now >> 24, now >> 16, now >> 8, now) < 0) | ||
797 | return -ENXIO; | ||
798 | while (!req.complete) | ||
799 | cuda_poll(); | ||
800 | if ((req.reply_len != 3) && (req.reply_len != 7)) | ||
801 | pr_err("%s: got %d byte reply\n", __func__, req.reply_len); | ||
802 | return 0; | ||
803 | } | ||
diff --git a/drivers/macintosh/via-macii.c b/drivers/macintosh/via-macii.c index cf6f7d52d6be..ac824d7b2dcf 100644 --- a/drivers/macintosh/via-macii.c +++ b/drivers/macintosh/via-macii.c | |||
@@ -12,7 +12,7 @@ | |||
12 | * | 12 | * |
13 | * 1999-08-02 (jmt) - Initial rewrite for Unified ADB. | 13 | * 1999-08-02 (jmt) - Initial rewrite for Unified ADB. |
14 | * 2000-03-29 Tony Mantler <tonym@mac.linux-m68k.org> | 14 | * 2000-03-29 Tony Mantler <tonym@mac.linux-m68k.org> |
15 | * - Big overhaul, should actually work now. | 15 | * - Big overhaul, should actually work now. |
16 | * 2006-12-31 Finn Thain - Another overhaul. | 16 | * 2006-12-31 Finn Thain - Another overhaul. |
17 | * | 17 | * |
18 | * Suggested reading: | 18 | * Suggested reading: |
@@ -23,7 +23,7 @@ | |||
23 | * Apple's "ADB Analyzer" bus sniffer is invaluable: | 23 | * Apple's "ADB Analyzer" bus sniffer is invaluable: |
24 | * ftp://ftp.apple.com/developer/Tool_Chest/Devices_-_Hardware/Apple_Desktop_Bus/ | 24 | * ftp://ftp.apple.com/developer/Tool_Chest/Devices_-_Hardware/Apple_Desktop_Bus/ |
25 | */ | 25 | */ |
26 | 26 | ||
27 | #include <stdarg.h> | 27 | #include <stdarg.h> |
28 | #include <linux/types.h> | 28 | #include <linux/types.h> |
29 | #include <linux/errno.h> | 29 | #include <linux/errno.h> |
@@ -77,7 +77,7 @@ static volatile unsigned char *via; | |||
77 | #define ST_ODD 0x20 /* ADB state: odd data byte */ | 77 | #define ST_ODD 0x20 /* ADB state: odd data byte */ |
78 | #define ST_IDLE 0x30 /* ADB state: idle, nothing to send */ | 78 | #define ST_IDLE 0x30 /* ADB state: idle, nothing to send */ |
79 | 79 | ||
80 | static int macii_init_via(void); | 80 | static int macii_init_via(void); |
81 | static void macii_start(void); | 81 | static void macii_start(void); |
82 | static irqreturn_t macii_interrupt(int irq, void *arg); | 82 | static irqreturn_t macii_interrupt(int irq, void *arg); |
83 | static void macii_queue_poll(void); | 83 | static void macii_queue_poll(void); |
@@ -120,31 +120,15 @@ static int srq_asserted; /* have to poll for the device that asserted it */ | |||
120 | static int command_byte; /* the most recent command byte transmitted */ | 120 | static int command_byte; /* the most recent command byte transmitted */ |
121 | static int autopoll_devs; /* bits set are device addresses to be polled */ | 121 | static int autopoll_devs; /* bits set are device addresses to be polled */ |
122 | 122 | ||
123 | /* Sanity check for request queue. Doesn't check for cycles. */ | ||
124 | static int request_is_queued(struct adb_request *req) { | ||
125 | struct adb_request *cur; | ||
126 | unsigned long flags; | ||
127 | local_irq_save(flags); | ||
128 | cur = current_req; | ||
129 | while (cur) { | ||
130 | if (cur == req) { | ||
131 | local_irq_restore(flags); | ||
132 | return 1; | ||
133 | } | ||
134 | cur = cur->next; | ||
135 | } | ||
136 | local_irq_restore(flags); | ||
137 | return 0; | ||
138 | } | ||
139 | |||
140 | /* Check for MacII style ADB */ | 123 | /* Check for MacII style ADB */ |
141 | static int macii_probe(void) | 124 | static int macii_probe(void) |
142 | { | 125 | { |
143 | if (macintosh_config->adb_type != MAC_ADB_II) return -ENODEV; | 126 | if (macintosh_config->adb_type != MAC_ADB_II) |
127 | return -ENODEV; | ||
144 | 128 | ||
145 | via = via1; | 129 | via = via1; |
146 | 130 | ||
147 | printk("adb: Mac II ADB Driver v1.0 for Unified ADB\n"); | 131 | pr_info("adb: Mac II ADB Driver v1.0 for Unified ADB\n"); |
148 | return 0; | 132 | return 0; |
149 | } | 133 | } |
150 | 134 | ||
@@ -153,15 +137,17 @@ int macii_init(void) | |||
153 | { | 137 | { |
154 | unsigned long flags; | 138 | unsigned long flags; |
155 | int err; | 139 | int err; |
156 | 140 | ||
157 | local_irq_save(flags); | 141 | local_irq_save(flags); |
158 | 142 | ||
159 | err = macii_init_via(); | 143 | err = macii_init_via(); |
160 | if (err) goto out; | 144 | if (err) |
145 | goto out; | ||
161 | 146 | ||
162 | err = request_irq(IRQ_MAC_ADB, macii_interrupt, 0, "ADB", | 147 | err = request_irq(IRQ_MAC_ADB, macii_interrupt, 0, "ADB", |
163 | macii_interrupt); | 148 | macii_interrupt); |
164 | if (err) goto out; | 149 | if (err) |
150 | goto out; | ||
165 | 151 | ||
166 | macii_state = idle; | 152 | macii_state = idle; |
167 | out: | 153 | out: |
@@ -169,7 +155,7 @@ out: | |||
169 | return err; | 155 | return err; |
170 | } | 156 | } |
171 | 157 | ||
172 | /* initialize the hardware */ | 158 | /* initialize the hardware */ |
173 | static int macii_init_via(void) | 159 | static int macii_init_via(void) |
174 | { | 160 | { |
175 | unsigned char x; | 161 | unsigned char x; |
@@ -179,7 +165,7 @@ static int macii_init_via(void) | |||
179 | 165 | ||
180 | /* Set up state: idle */ | 166 | /* Set up state: idle */ |
181 | via[B] |= ST_IDLE; | 167 | via[B] |= ST_IDLE; |
182 | last_status = via[B] & (ST_MASK|CTLR_IRQ); | 168 | last_status = via[B] & (ST_MASK | CTLR_IRQ); |
183 | 169 | ||
184 | /* Shift register on input */ | 170 | /* Shift register on input */ |
185 | via[ACR] = (via[ACR] & ~SR_CTRL) | SR_EXT; | 171 | via[ACR] = (via[ACR] & ~SR_CTRL) | SR_EXT; |
@@ -205,7 +191,8 @@ static void macii_queue_poll(void) | |||
205 | int next_device; | 191 | int next_device; |
206 | static struct adb_request req; | 192 | static struct adb_request req; |
207 | 193 | ||
208 | if (!autopoll_devs) return; | 194 | if (!autopoll_devs) |
195 | return; | ||
209 | 196 | ||
210 | device_mask = (1 << (((command_byte & 0xF0) >> 4) + 1)) - 1; | 197 | device_mask = (1 << (((command_byte & 0xF0) >> 4) + 1)) - 1; |
211 | if (autopoll_devs & ~device_mask) | 198 | if (autopoll_devs & ~device_mask) |
@@ -213,10 +200,7 @@ static void macii_queue_poll(void) | |||
213 | else | 200 | else |
214 | next_device = ffs(autopoll_devs) - 1; | 201 | next_device = ffs(autopoll_devs) - 1; |
215 | 202 | ||
216 | BUG_ON(request_is_queued(&req)); | 203 | adb_request(&req, NULL, ADBREQ_NOSEND, 1, ADB_READREG(next_device, 0)); |
217 | |||
218 | adb_request(&req, NULL, ADBREQ_NOSEND, 1, | ||
219 | ADB_READREG(next_device, 0)); | ||
220 | 204 | ||
221 | req.sent = 0; | 205 | req.sent = 0; |
222 | req.complete = 0; | 206 | req.complete = 0; |
@@ -235,45 +219,47 @@ static void macii_queue_poll(void) | |||
235 | static int macii_send_request(struct adb_request *req, int sync) | 219 | static int macii_send_request(struct adb_request *req, int sync) |
236 | { | 220 | { |
237 | int err; | 221 | int err; |
238 | unsigned long flags; | ||
239 | 222 | ||
240 | BUG_ON(request_is_queued(req)); | ||
241 | |||
242 | local_irq_save(flags); | ||
243 | err = macii_write(req); | 223 | err = macii_write(req); |
244 | local_irq_restore(flags); | 224 | if (err) |
225 | return err; | ||
245 | 226 | ||
246 | if (!err && sync) { | 227 | if (sync) |
247 | while (!req->complete) { | 228 | while (!req->complete) |
248 | macii_poll(); | 229 | macii_poll(); |
249 | } | ||
250 | BUG_ON(request_is_queued(req)); | ||
251 | } | ||
252 | 230 | ||
253 | return err; | 231 | return 0; |
254 | } | 232 | } |
255 | 233 | ||
256 | /* Send an ADB request (append to request queue) */ | 234 | /* Send an ADB request (append to request queue) */ |
257 | static int macii_write(struct adb_request *req) | 235 | static int macii_write(struct adb_request *req) |
258 | { | 236 | { |
237 | unsigned long flags; | ||
238 | |||
259 | if (req->nbytes < 2 || req->data[0] != ADB_PACKET || req->nbytes > 15) { | 239 | if (req->nbytes < 2 || req->data[0] != ADB_PACKET || req->nbytes > 15) { |
260 | req->complete = 1; | 240 | req->complete = 1; |
261 | return -EINVAL; | 241 | return -EINVAL; |
262 | } | 242 | } |
263 | 243 | ||
264 | req->next = NULL; | 244 | req->next = NULL; |
265 | req->sent = 0; | 245 | req->sent = 0; |
266 | req->complete = 0; | 246 | req->complete = 0; |
267 | req->reply_len = 0; | 247 | req->reply_len = 0; |
268 | 248 | ||
249 | local_irq_save(flags); | ||
250 | |||
269 | if (current_req != NULL) { | 251 | if (current_req != NULL) { |
270 | last_req->next = req; | 252 | last_req->next = req; |
271 | last_req = req; | 253 | last_req = req; |
272 | } else { | 254 | } else { |
273 | current_req = req; | 255 | current_req = req; |
274 | last_req = req; | 256 | last_req = req; |
275 | if (macii_state == idle) macii_start(); | 257 | if (macii_state == idle) |
258 | macii_start(); | ||
276 | } | 259 | } |
260 | |||
261 | local_irq_restore(flags); | ||
262 | |||
277 | return 0; | 263 | return 0; |
278 | } | 264 | } |
279 | 265 | ||
@@ -287,7 +273,8 @@ static int macii_autopoll(int devs) | |||
287 | /* bit 1 == device 1, and so on. */ | 273 | /* bit 1 == device 1, and so on. */ |
288 | autopoll_devs = devs & 0xFFFE; | 274 | autopoll_devs = devs & 0xFFFE; |
289 | 275 | ||
290 | if (!autopoll_devs) return 0; | 276 | if (!autopoll_devs) |
277 | return 0; | ||
291 | 278 | ||
292 | local_irq_save(flags); | 279 | local_irq_save(flags); |
293 | 280 | ||
@@ -304,7 +291,8 @@ static int macii_autopoll(int devs) | |||
304 | return err; | 291 | return err; |
305 | } | 292 | } |
306 | 293 | ||
307 | static inline int need_autopoll(void) { | 294 | static inline int need_autopoll(void) |
295 | { | ||
308 | /* Was the last command Talk Reg 0 | 296 | /* Was the last command Talk Reg 0 |
309 | * and is the target on the autopoll list? | 297 | * and is the target on the autopoll list? |
310 | */ | 298 | */ |
@@ -317,21 +305,17 @@ static inline int need_autopoll(void) { | |||
317 | /* Prod the chip without interrupts */ | 305 | /* Prod the chip without interrupts */ |
318 | static void macii_poll(void) | 306 | static void macii_poll(void) |
319 | { | 307 | { |
320 | disable_irq(IRQ_MAC_ADB); | ||
321 | macii_interrupt(0, NULL); | 308 | macii_interrupt(0, NULL); |
322 | enable_irq(IRQ_MAC_ADB); | ||
323 | } | 309 | } |
324 | 310 | ||
325 | /* Reset the bus */ | 311 | /* Reset the bus */ |
326 | static int macii_reset_bus(void) | 312 | static int macii_reset_bus(void) |
327 | { | 313 | { |
328 | static struct adb_request req; | 314 | static struct adb_request req; |
329 | |||
330 | if (request_is_queued(&req)) | ||
331 | return 0; | ||
332 | 315 | ||
333 | /* Command = 0, Address = ignored */ | 316 | /* Command = 0, Address = ignored */ |
334 | adb_request(&req, NULL, 0, 1, ADB_BUSRESET); | 317 | adb_request(&req, NULL, ADBREQ_NOSEND, 1, ADB_BUSRESET); |
318 | macii_send_request(&req, 1); | ||
335 | 319 | ||
336 | /* Don't want any more requests during the Global Reset low time. */ | 320 | /* Don't want any more requests during the Global Reset low time. */ |
337 | udelay(3000); | 321 | udelay(3000); |
@@ -346,10 +330,6 @@ static void macii_start(void) | |||
346 | 330 | ||
347 | req = current_req; | 331 | req = current_req; |
348 | 332 | ||
349 | BUG_ON(req == NULL); | ||
350 | |||
351 | BUG_ON(macii_state != idle); | ||
352 | |||
353 | /* Now send it. Be careful though, that first byte of the request | 333 | /* Now send it. Be careful though, that first byte of the request |
354 | * is actually ADB_PACKET; the real data begins at index 1! | 334 | * is actually ADB_PACKET; the real data begins at index 1! |
355 | * And req->nbytes is the number of bytes of real data plus one. | 335 | * And req->nbytes is the number of bytes of real data plus one. |
@@ -375,7 +355,7 @@ static void macii_start(void) | |||
375 | * to be activity on the ADB bus. The chip will poll to achieve this. | 355 | * to be activity on the ADB bus. The chip will poll to achieve this. |
376 | * | 356 | * |
377 | * The basic ADB state machine was left unchanged from the original MacII code | 357 | * The basic ADB state machine was left unchanged from the original MacII code |
378 | * by Alan Cox, which was based on the CUDA driver for PowerMac. | 358 | * by Alan Cox, which was based on the CUDA driver for PowerMac. |
379 | * The syntax of the ADB status lines is totally different on MacII, | 359 | * The syntax of the ADB status lines is totally different on MacII, |
380 | * though. MacII uses the states Command -> Even -> Odd -> Even ->...-> Idle | 360 | * though. MacII uses the states Command -> Even -> Odd -> Even ->...-> Idle |
381 | * for sending and Idle -> Even -> Odd -> Even ->...-> Idle for receiving. | 361 | * for sending and Idle -> Even -> Odd -> Even ->...-> Idle for receiving. |
@@ -387,164 +367,166 @@ static void macii_start(void) | |||
387 | static irqreturn_t macii_interrupt(int irq, void *arg) | 367 | static irqreturn_t macii_interrupt(int irq, void *arg) |
388 | { | 368 | { |
389 | int x; | 369 | int x; |
390 | static int entered; | ||
391 | struct adb_request *req; | 370 | struct adb_request *req; |
371 | unsigned long flags; | ||
372 | |||
373 | local_irq_save(flags); | ||
392 | 374 | ||
393 | if (!arg) { | 375 | if (!arg) { |
394 | /* Clear the SR IRQ flag when polling. */ | 376 | /* Clear the SR IRQ flag when polling. */ |
395 | if (via[IFR] & SR_INT) | 377 | if (via[IFR] & SR_INT) |
396 | via[IFR] = SR_INT; | 378 | via[IFR] = SR_INT; |
397 | else | 379 | else { |
380 | local_irq_restore(flags); | ||
398 | return IRQ_NONE; | 381 | return IRQ_NONE; |
382 | } | ||
399 | } | 383 | } |
400 | 384 | ||
401 | BUG_ON(entered++); | ||
402 | |||
403 | last_status = status; | 385 | last_status = status; |
404 | status = via[B] & (ST_MASK|CTLR_IRQ); | 386 | status = via[B] & (ST_MASK | CTLR_IRQ); |
405 | 387 | ||
406 | switch (macii_state) { | 388 | switch (macii_state) { |
407 | case idle: | 389 | case idle: |
408 | if (reading_reply) { | 390 | if (reading_reply) { |
409 | reply_ptr = current_req->reply; | 391 | reply_ptr = current_req->reply; |
410 | } else { | 392 | } else { |
411 | BUG_ON(current_req != NULL); | 393 | WARN_ON(current_req); |
412 | reply_ptr = reply_buf; | 394 | reply_ptr = reply_buf; |
413 | } | 395 | } |
414 | 396 | ||
415 | x = via[SR]; | 397 | x = via[SR]; |
416 | 398 | ||
417 | if ((status & CTLR_IRQ) && (x == 0xFF)) { | 399 | if ((status & CTLR_IRQ) && (x == 0xFF)) { |
418 | /* Bus timeout without SRQ sequence: | 400 | /* Bus timeout without SRQ sequence: |
419 | * data is "FF" while CTLR_IRQ is "H" | 401 | * data is "FF" while CTLR_IRQ is "H" |
420 | */ | 402 | */ |
421 | reply_len = 0; | 403 | reply_len = 0; |
422 | srq_asserted = 0; | 404 | srq_asserted = 0; |
423 | macii_state = read_done; | 405 | macii_state = read_done; |
424 | } else { | 406 | } else { |
425 | macii_state = reading; | 407 | macii_state = reading; |
426 | *reply_ptr = x; | 408 | *reply_ptr = x; |
427 | reply_len = 1; | 409 | reply_len = 1; |
428 | } | 410 | } |
429 | 411 | ||
430 | /* set ADB state = even for first data byte */ | 412 | /* set ADB state = even for first data byte */ |
431 | via[B] = (via[B] & ~ST_MASK) | ST_EVEN; | 413 | via[B] = (via[B] & ~ST_MASK) | ST_EVEN; |
432 | break; | 414 | break; |
433 | 415 | ||
434 | case sending: | 416 | case sending: |
435 | req = current_req; | 417 | req = current_req; |
436 | if (data_index >= req->nbytes) { | 418 | if (data_index >= req->nbytes) { |
437 | req->sent = 1; | 419 | req->sent = 1; |
438 | macii_state = idle; | 420 | macii_state = idle; |
439 | |||
440 | if (req->reply_expected) { | ||
441 | reading_reply = 1; | ||
442 | } else { | ||
443 | req->complete = 1; | ||
444 | current_req = req->next; | ||
445 | if (req->done) (*req->done)(req); | ||
446 | |||
447 | if (current_req) | ||
448 | macii_start(); | ||
449 | else | ||
450 | if (need_autopoll()) | ||
451 | macii_autopoll(autopoll_devs); | ||
452 | } | ||
453 | 421 | ||
454 | if (macii_state == idle) { | 422 | if (req->reply_expected) { |
455 | /* reset to shift in */ | 423 | reading_reply = 1; |
456 | via[ACR] &= ~SR_OUT; | ||
457 | x = via[SR]; | ||
458 | /* set ADB state idle - might get SRQ */ | ||
459 | via[B] = (via[B] & ~ST_MASK) | ST_IDLE; | ||
460 | } | ||
461 | } else { | 424 | } else { |
462 | via[SR] = req->data[data_index++]; | 425 | req->complete = 1; |
463 | 426 | current_req = req->next; | |
464 | if ( (via[B] & ST_MASK) == ST_CMD ) { | 427 | if (req->done) |
465 | /* just sent the command byte, set to EVEN */ | 428 | (*req->done)(req); |
466 | via[B] = (via[B] & ~ST_MASK) | ST_EVEN; | ||
467 | } else { | ||
468 | /* invert state bits, toggle ODD/EVEN */ | ||
469 | via[B] ^= ST_MASK; | ||
470 | } | ||
471 | } | ||
472 | break; | ||
473 | |||
474 | case reading: | ||
475 | x = via[SR]; | ||
476 | BUG_ON((status & ST_MASK) == ST_CMD || | ||
477 | (status & ST_MASK) == ST_IDLE); | ||
478 | |||
479 | /* Bus timeout with SRQ sequence: | ||
480 | * data is "XX FF" while CTLR_IRQ is "L L" | ||
481 | * End of packet without SRQ sequence: | ||
482 | * data is "XX...YY 00" while CTLR_IRQ is "L...H L" | ||
483 | * End of packet SRQ sequence: | ||
484 | * data is "XX...YY 00" while CTLR_IRQ is "L...L L" | ||
485 | * (where XX is the first response byte and | ||
486 | * YY is the last byte of valid response data.) | ||
487 | */ | ||
488 | 429 | ||
489 | srq_asserted = 0; | 430 | if (current_req) |
490 | if (!(status & CTLR_IRQ)) { | 431 | macii_start(); |
491 | if (x == 0xFF) { | 432 | else if (need_autopoll()) |
492 | if (!(last_status & CTLR_IRQ)) { | 433 | macii_autopoll(autopoll_devs); |
493 | macii_state = read_done; | ||
494 | reply_len = 0; | ||
495 | srq_asserted = 1; | ||
496 | } | ||
497 | } else if (x == 0x00) { | ||
498 | macii_state = read_done; | ||
499 | if (!(last_status & CTLR_IRQ)) | ||
500 | srq_asserted = 1; | ||
501 | } | ||
502 | } | 434 | } |
503 | 435 | ||
504 | if (macii_state == reading) { | 436 | if (macii_state == idle) { |
505 | BUG_ON(reply_len > 15); | 437 | /* reset to shift in */ |
506 | reply_ptr++; | 438 | via[ACR] &= ~SR_OUT; |
507 | *reply_ptr = x; | 439 | x = via[SR]; |
508 | reply_len++; | 440 | /* set ADB state idle - might get SRQ */ |
441 | via[B] = (via[B] & ~ST_MASK) | ST_IDLE; | ||
509 | } | 442 | } |
443 | } else { | ||
444 | via[SR] = req->data[data_index++]; | ||
510 | 445 | ||
511 | /* invert state bits, toggle ODD/EVEN */ | 446 | if ((via[B] & ST_MASK) == ST_CMD) { |
512 | via[B] ^= ST_MASK; | 447 | /* just sent the command byte, set to EVEN */ |
513 | break; | 448 | via[B] = (via[B] & ~ST_MASK) | ST_EVEN; |
449 | } else { | ||
450 | /* invert state bits, toggle ODD/EVEN */ | ||
451 | via[B] ^= ST_MASK; | ||
452 | } | ||
453 | } | ||
454 | break; | ||
514 | 455 | ||
515 | case read_done: | 456 | case reading: |
516 | x = via[SR]; | 457 | x = via[SR]; |
458 | WARN_ON((status & ST_MASK) == ST_CMD || | ||
459 | (status & ST_MASK) == ST_IDLE); | ||
460 | |||
461 | /* Bus timeout with SRQ sequence: | ||
462 | * data is "XX FF" while CTLR_IRQ is "L L" | ||
463 | * End of packet without SRQ sequence: | ||
464 | * data is "XX...YY 00" while CTLR_IRQ is "L...H L" | ||
465 | * End of packet SRQ sequence: | ||
466 | * data is "XX...YY 00" while CTLR_IRQ is "L...L L" | ||
467 | * (where XX is the first response byte and | ||
468 | * YY is the last byte of valid response data.) | ||
469 | */ | ||
517 | 470 | ||
518 | if (reading_reply) { | 471 | srq_asserted = 0; |
519 | reading_reply = 0; | 472 | if (!(status & CTLR_IRQ)) { |
520 | req = current_req; | 473 | if (x == 0xFF) { |
521 | req->reply_len = reply_len; | 474 | if (!(last_status & CTLR_IRQ)) { |
522 | req->complete = 1; | 475 | macii_state = read_done; |
523 | current_req = req->next; | 476 | reply_len = 0; |
524 | if (req->done) (*req->done)(req); | 477 | srq_asserted = 1; |
525 | } else if (reply_len && autopoll_devs) | 478 | } |
526 | adb_input(reply_buf, reply_len, 0); | 479 | } else if (x == 0x00) { |
480 | macii_state = read_done; | ||
481 | if (!(last_status & CTLR_IRQ)) | ||
482 | srq_asserted = 1; | ||
483 | } | ||
484 | } | ||
527 | 485 | ||
528 | macii_state = idle; | 486 | if (macii_state == reading && |
487 | reply_len < ARRAY_SIZE(reply_buf)) { | ||
488 | reply_ptr++; | ||
489 | *reply_ptr = x; | ||
490 | reply_len++; | ||
491 | } | ||
529 | 492 | ||
530 | /* SRQ seen before, initiate poll now */ | 493 | /* invert state bits, toggle ODD/EVEN */ |
531 | if (srq_asserted) | 494 | via[B] ^= ST_MASK; |
532 | macii_queue_poll(); | 495 | break; |
533 | 496 | ||
534 | if (current_req) | 497 | case read_done: |
535 | macii_start(); | 498 | x = via[SR]; |
536 | else | ||
537 | if (need_autopoll()) | ||
538 | macii_autopoll(autopoll_devs); | ||
539 | 499 | ||
540 | if (macii_state == idle) | 500 | if (reading_reply) { |
541 | via[B] = (via[B] & ~ST_MASK) | ST_IDLE; | 501 | reading_reply = 0; |
542 | break; | 502 | req = current_req; |
503 | req->reply_len = reply_len; | ||
504 | req->complete = 1; | ||
505 | current_req = req->next; | ||
506 | if (req->done) | ||
507 | (*req->done)(req); | ||
508 | } else if (reply_len && autopoll_devs) | ||
509 | adb_input(reply_buf, reply_len, 0); | ||
510 | |||
511 | macii_state = idle; | ||
512 | |||
513 | /* SRQ seen before, initiate poll now */ | ||
514 | if (srq_asserted) | ||
515 | macii_queue_poll(); | ||
516 | |||
517 | if (current_req) | ||
518 | macii_start(); | ||
519 | else if (need_autopoll()) | ||
520 | macii_autopoll(autopoll_devs); | ||
521 | |||
522 | if (macii_state == idle) | ||
523 | via[B] = (via[B] & ~ST_MASK) | ST_IDLE; | ||
524 | break; | ||
543 | 525 | ||
544 | default: | 526 | default: |
545 | break; | 527 | break; |
546 | } | 528 | } |
547 | 529 | ||
548 | entered--; | 530 | local_irq_restore(flags); |
549 | return IRQ_HANDLED; | 531 | return IRQ_HANDLED; |
550 | } | 532 | } |
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c index d72c450aebe5..60f57e2abf21 100644 --- a/drivers/macintosh/via-pmu.c +++ b/drivers/macintosh/via-pmu.c | |||
@@ -1737,6 +1737,39 @@ pmu_enable_irled(int on) | |||
1737 | pmu_wait_complete(&req); | 1737 | pmu_wait_complete(&req); |
1738 | } | 1738 | } |
1739 | 1739 | ||
1740 | /* Offset between Unix time (1970-based) and Mac time (1904-based) */ | ||
1741 | #define RTC_OFFSET 2082844800 | ||
1742 | |||
1743 | time64_t pmu_get_time(void) | ||
1744 | { | ||
1745 | struct adb_request req; | ||
1746 | u32 now; | ||
1747 | |||
1748 | if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0) | ||
1749 | return 0; | ||
1750 | pmu_wait_complete(&req); | ||
1751 | if (req.reply_len != 4) | ||
1752 | pr_err("%s: got %d byte reply\n", __func__, req.reply_len); | ||
1753 | now = (req.reply[0] << 24) + (req.reply[1] << 16) + | ||
1754 | (req.reply[2] << 8) + req.reply[3]; | ||
1755 | return (time64_t)now - RTC_OFFSET; | ||
1756 | } | ||
1757 | |||
1758 | int pmu_set_rtc_time(struct rtc_time *tm) | ||
1759 | { | ||
1760 | u32 now; | ||
1761 | struct adb_request req; | ||
1762 | |||
1763 | now = lower_32_bits(rtc_tm_to_time64(tm) + RTC_OFFSET); | ||
1764 | if (pmu_request(&req, NULL, 5, PMU_SET_RTC, | ||
1765 | now >> 24, now >> 16, now >> 8, now) < 0) | ||
1766 | return -ENXIO; | ||
1767 | pmu_wait_complete(&req); | ||
1768 | if (req.reply_len != 0) | ||
1769 | pr_err("%s: got %d byte reply\n", __func__, req.reply_len); | ||
1770 | return 0; | ||
1771 | } | ||
1772 | |||
1740 | void | 1773 | void |
1741 | pmu_restart(void) | 1774 | pmu_restart(void) |
1742 | { | 1775 | { |
diff --git a/drivers/macintosh/windfarm_smu_controls.c b/drivers/macintosh/windfarm_smu_controls.c index d174c7437337..86d65462a61c 100644 --- a/drivers/macintosh/windfarm_smu_controls.c +++ b/drivers/macintosh/windfarm_smu_controls.c | |||
@@ -277,7 +277,7 @@ static int __init smu_controls_init(void) | |||
277 | fct = smu_fan_create(fan, 0); | 277 | fct = smu_fan_create(fan, 0); |
278 | if (fct == NULL) { | 278 | if (fct == NULL) { |
279 | printk(KERN_WARNING "windfarm: Failed to create SMU " | 279 | printk(KERN_WARNING "windfarm: Failed to create SMU " |
280 | "RPM fan %s\n", fan->name); | 280 | "RPM fan %pOFn\n", fan); |
281 | continue; | 281 | continue; |
282 | } | 282 | } |
283 | list_add(&fct->link, &smu_fans); | 283 | list_add(&fct->link, &smu_fans); |
@@ -296,7 +296,7 @@ static int __init smu_controls_init(void) | |||
296 | fct = smu_fan_create(fan, 1); | 296 | fct = smu_fan_create(fan, 1); |
297 | if (fct == NULL) { | 297 | if (fct == NULL) { |
298 | printk(KERN_WARNING "windfarm: Failed to create SMU " | 298 | printk(KERN_WARNING "windfarm: Failed to create SMU " |
299 | "PWM fan %s\n", fan->name); | 299 | "PWM fan %pOFn\n", fan); |
300 | continue; | 300 | continue; |
301 | } | 301 | } |
302 | list_add(&fct->link, &smu_fans); | 302 | list_add(&fct->link, &smu_fans); |
diff --git a/drivers/macintosh/windfarm_smu_sat.c b/drivers/macintosh/windfarm_smu_sat.c index da7f4fc1a51d..a0f61eb853c5 100644 --- a/drivers/macintosh/windfarm_smu_sat.c +++ b/drivers/macintosh/windfarm_smu_sat.c | |||
@@ -22,14 +22,6 @@ | |||
22 | 22 | ||
23 | #define VERSION "1.0" | 23 | #define VERSION "1.0" |
24 | 24 | ||
25 | #define DEBUG | ||
26 | |||
27 | #ifdef DEBUG | ||
28 | #define DBG(args...) printk(args) | ||
29 | #else | ||
30 | #define DBG(args...) do { } while(0) | ||
31 | #endif | ||
32 | |||
33 | /* If the cache is older than 800ms we'll refetch it */ | 25 | /* If the cache is older than 800ms we'll refetch it */ |
34 | #define MAX_AGE msecs_to_jiffies(800) | 26 | #define MAX_AGE msecs_to_jiffies(800) |
35 | 27 | ||
@@ -106,13 +98,10 @@ struct smu_sdbp_header *smu_sat_get_sdb_partition(unsigned int sat_id, int id, | |||
106 | buf[i+2] = data[3]; | 98 | buf[i+2] = data[3]; |
107 | buf[i+3] = data[2]; | 99 | buf[i+3] = data[2]; |
108 | } | 100 | } |
109 | #ifdef DEBUG | ||
110 | DBG(KERN_DEBUG "sat %d partition %x:", sat_id, id); | ||
111 | for (i = 0; i < len; ++i) | ||
112 | DBG(" %x", buf[i]); | ||
113 | DBG("\n"); | ||
114 | #endif | ||
115 | 101 | ||
102 | printk(KERN_DEBUG "sat %d partition %x:", sat_id, id); | ||
103 | print_hex_dump(KERN_DEBUG, " ", DUMP_PREFIX_OFFSET, | ||
104 | 16, 1, buf, len, false); | ||
116 | if (size) | 105 | if (size) |
117 | *size = len; | 106 | *size = len; |
118 | return (struct smu_sdbp_header *) buf; | 107 | return (struct smu_sdbp_header *) buf; |
@@ -132,13 +121,13 @@ static int wf_sat_read_cache(struct wf_sat *sat) | |||
132 | if (err < 0) | 121 | if (err < 0) |
133 | return err; | 122 | return err; |
134 | sat->last_read = jiffies; | 123 | sat->last_read = jiffies; |
124 | |||
135 | #ifdef LOTSA_DEBUG | 125 | #ifdef LOTSA_DEBUG |
136 | { | 126 | { |
137 | int i; | 127 | int i; |
138 | DBG(KERN_DEBUG "wf_sat_get: data is"); | 128 | printk(KERN_DEBUG "wf_sat_get: data is"); |
139 | for (i = 0; i < 16; ++i) | 129 | print_hex_dump(KERN_DEBUG, " ", DUMP_PREFIX_OFFSET, |
140 | DBG(" %.2x", sat->cache[i]); | 130 | 16, 1, sat->cache, 16, false); |
141 | DBG("\n"); | ||
142 | } | 131 | } |
143 | #endif | 132 | #endif |
144 | return 0; | 133 | return 0; |
diff --git a/drivers/misc/ocxl/config.c b/drivers/misc/ocxl/config.c index 2e30de9c694a..57a6bb1fd3c9 100644 --- a/drivers/misc/ocxl/config.c +++ b/drivers/misc/ocxl/config.c | |||
@@ -280,7 +280,9 @@ int ocxl_config_check_afu_index(struct pci_dev *dev, | |||
280 | u32 val; | 280 | u32 val; |
281 | int rc, templ_major, templ_minor, len; | 281 | int rc, templ_major, templ_minor, len; |
282 | 282 | ||
283 | pci_write_config_word(dev, fn->dvsec_afu_info_pos, afu_idx); | 283 | pci_write_config_byte(dev, |
284 | fn->dvsec_afu_info_pos + OCXL_DVSEC_AFU_INFO_AFU_IDX, | ||
285 | afu_idx); | ||
284 | rc = read_afu_info(dev, fn, OCXL_DVSEC_TEMPL_VERSION, &val); | 286 | rc = read_afu_info(dev, fn, OCXL_DVSEC_TEMPL_VERSION, &val); |
285 | if (rc) | 287 | if (rc) |
286 | return rc; | 288 | return rc; |
diff --git a/drivers/pci/hotplug/pnv_php.c b/drivers/pci/hotplug/pnv_php.c index ee54f5bacad1..6758fd7c382e 100644 --- a/drivers/pci/hotplug/pnv_php.c +++ b/drivers/pci/hotplug/pnv_php.c | |||
@@ -746,7 +746,7 @@ static irqreturn_t pnv_php_interrupt(int irq, void *data) | |||
746 | pe = edev ? edev->pe : NULL; | 746 | pe = edev ? edev->pe : NULL; |
747 | if (pe) { | 747 | if (pe) { |
748 | eeh_serialize_lock(&flags); | 748 | eeh_serialize_lock(&flags); |
749 | eeh_pe_state_mark(pe, EEH_PE_ISOLATED); | 749 | eeh_pe_mark_isolated(pe); |
750 | eeh_serialize_unlock(flags); | 750 | eeh_serialize_unlock(flags); |
751 | eeh_pe_set_option(pe, EEH_OPT_FREEZE_PE); | 751 | eeh_pe_set_option(pe, EEH_OPT_FREEZE_PE); |
752 | } | 752 | } |
diff --git a/drivers/pcmcia/electra_cf.c b/drivers/pcmcia/electra_cf.c index 9671ded549f0..b31abe35ed2c 100644 --- a/drivers/pcmcia/electra_cf.c +++ b/drivers/pcmcia/electra_cf.c | |||
@@ -230,7 +230,7 @@ static int electra_cf_probe(struct platform_device *ofdev) | |||
230 | 230 | ||
231 | if (!cf->mem_base || !cf->io_virt || !cf->gpio_base || | 231 | if (!cf->mem_base || !cf->io_virt || !cf->gpio_base || |
232 | (__ioremap_at(io.start, cf->io_virt, cf->io_size, | 232 | (__ioremap_at(io.start, cf->io_virt, cf->io_size, |
233 | pgprot_val(pgprot_noncached(__pgprot(0)))) == NULL)) { | 233 | pgprot_noncached(PAGE_KERNEL)) == NULL)) { |
234 | dev_err(device, "can't ioremap ranges\n"); | 234 | dev_err(device, "can't ioremap ranges\n"); |
235 | status = -ENOMEM; | 235 | status = -ENOMEM; |
236 | goto fail1; | 236 | goto fail1; |
diff --git a/drivers/soc/fsl/qbman/qman_ccsr.c b/drivers/soc/fsl/qbman/qman_ccsr.c index 6fd5fef5f39b..109b38de3176 100644 --- a/drivers/soc/fsl/qbman/qman_ccsr.c +++ b/drivers/soc/fsl/qbman/qman_ccsr.c | |||
@@ -419,7 +419,7 @@ static size_t fqd_sz, pfdr_sz; | |||
419 | static int zero_priv_mem(phys_addr_t addr, size_t sz) | 419 | static int zero_priv_mem(phys_addr_t addr, size_t sz) |
420 | { | 420 | { |
421 | /* map as cacheable, non-guarded */ | 421 | /* map as cacheable, non-guarded */ |
422 | void __iomem *tmpp = ioremap_prot(addr, sz, 0); | 422 | void __iomem *tmpp = ioremap_cache(addr, sz); |
423 | 423 | ||
424 | if (!tmpp) | 424 | if (!tmpp) |
425 | return -ENOMEM; | 425 | return -ENOMEM; |
diff --git a/drivers/video/fbdev/chipsfb.c b/drivers/video/fbdev/chipsfb.c index f103665cad43..40182ed85648 100644 --- a/drivers/video/fbdev/chipsfb.c +++ b/drivers/video/fbdev/chipsfb.c | |||
@@ -27,7 +27,6 @@ | |||
27 | #include <linux/init.h> | 27 | #include <linux/init.h> |
28 | #include <linux/pci.h> | 28 | #include <linux/pci.h> |
29 | #include <linux/console.h> | 29 | #include <linux/console.h> |
30 | #include <asm/io.h> | ||
31 | 30 | ||
32 | #ifdef CONFIG_PMAC_BACKLIGHT | 31 | #ifdef CONFIG_PMAC_BACKLIGHT |
33 | #include <asm/backlight.h> | 32 | #include <asm/backlight.h> |
@@ -401,7 +400,7 @@ static int chipsfb_pci_init(struct pci_dev *dp, const struct pci_device_id *ent) | |||
401 | #endif /* CONFIG_PMAC_BACKLIGHT */ | 400 | #endif /* CONFIG_PMAC_BACKLIGHT */ |
402 | 401 | ||
403 | #ifdef CONFIG_PPC | 402 | #ifdef CONFIG_PPC |
404 | p->screen_base = __ioremap(addr, 0x200000, _PAGE_NO_CACHE); | 403 | p->screen_base = ioremap_wc(addr, 0x200000); |
405 | #else | 404 | #else |
406 | p->screen_base = ioremap(addr, 0x200000); | 405 | p->screen_base = ioremap(addr, 0x200000); |
407 | #endif | 406 | #endif |
diff --git a/drivers/video/fbdev/controlfb.c b/drivers/video/fbdev/controlfb.c index 8d14b29aafea..9cb0ef7ac29e 100644 --- a/drivers/video/fbdev/controlfb.c +++ b/drivers/video/fbdev/controlfb.c | |||
@@ -48,9 +48,7 @@ | |||
48 | #include <linux/nvram.h> | 48 | #include <linux/nvram.h> |
49 | #include <linux/adb.h> | 49 | #include <linux/adb.h> |
50 | #include <linux/cuda.h> | 50 | #include <linux/cuda.h> |
51 | #include <asm/io.h> | ||
52 | #include <asm/prom.h> | 51 | #include <asm/prom.h> |
53 | #include <asm/pgtable.h> | ||
54 | #include <asm/btext.h> | 52 | #include <asm/btext.h> |
55 | 53 | ||
56 | #include "macmodes.h" | 54 | #include "macmodes.h" |
@@ -715,8 +713,7 @@ static int __init control_of_init(struct device_node *dp) | |||
715 | goto error_out; | 713 | goto error_out; |
716 | } | 714 | } |
717 | /* map at most 8MB for the frame buffer */ | 715 | /* map at most 8MB for the frame buffer */ |
718 | p->frame_buffer = __ioremap(p->frame_buffer_phys, 0x800000, | 716 | p->frame_buffer = ioremap_wt(p->frame_buffer_phys, 0x800000); |
719 | _PAGE_WRITETHRU); | ||
720 | 717 | ||
721 | if (!p->control_regs_phys || | 718 | if (!p->control_regs_phys || |
722 | !request_mem_region(p->control_regs_phys, p->control_regs_size, | 719 | !request_mem_region(p->control_regs_phys, p->control_regs_size, |
diff --git a/drivers/video/fbdev/platinumfb.c b/drivers/video/fbdev/platinumfb.c index 377d3399a3ad..bf6b7fb83cf4 100644 --- a/drivers/video/fbdev/platinumfb.c +++ b/drivers/video/fbdev/platinumfb.c | |||
@@ -32,9 +32,7 @@ | |||
32 | #include <linux/nvram.h> | 32 | #include <linux/nvram.h> |
33 | #include <linux/of_device.h> | 33 | #include <linux/of_device.h> |
34 | #include <linux/of_platform.h> | 34 | #include <linux/of_platform.h> |
35 | #include <asm/io.h> | ||
36 | #include <asm/prom.h> | 35 | #include <asm/prom.h> |
37 | #include <asm/pgtable.h> | ||
38 | 36 | ||
39 | #include "macmodes.h" | 37 | #include "macmodes.h" |
40 | #include "platinumfb.h" | 38 | #include "platinumfb.h" |
@@ -577,8 +575,7 @@ static int platinumfb_probe(struct platform_device* odev) | |||
577 | 575 | ||
578 | /* frame buffer - map only 4MB */ | 576 | /* frame buffer - map only 4MB */ |
579 | pinfo->frame_buffer_phys = pinfo->rsrc_fb.start; | 577 | pinfo->frame_buffer_phys = pinfo->rsrc_fb.start; |
580 | pinfo->frame_buffer = __ioremap(pinfo->rsrc_fb.start, 0x400000, | 578 | pinfo->frame_buffer = ioremap_wt(pinfo->rsrc_fb.start, 0x400000); |
581 | _PAGE_WRITETHRU); | ||
582 | pinfo->base_frame_buffer = pinfo->frame_buffer; | 579 | pinfo->base_frame_buffer = pinfo->frame_buffer; |
583 | 580 | ||
584 | /* registers */ | 581 | /* registers */ |
diff --git a/drivers/video/fbdev/valkyriefb.c b/drivers/video/fbdev/valkyriefb.c index 275fb98236d3..d51c3a8009cb 100644 --- a/drivers/video/fbdev/valkyriefb.c +++ b/drivers/video/fbdev/valkyriefb.c | |||
@@ -54,13 +54,11 @@ | |||
54 | #include <linux/nvram.h> | 54 | #include <linux/nvram.h> |
55 | #include <linux/adb.h> | 55 | #include <linux/adb.h> |
56 | #include <linux/cuda.h> | 56 | #include <linux/cuda.h> |
57 | #include <asm/io.h> | ||
58 | #ifdef CONFIG_MAC | 57 | #ifdef CONFIG_MAC |
59 | #include <asm/macintosh.h> | 58 | #include <asm/macintosh.h> |
60 | #else | 59 | #else |
61 | #include <asm/prom.h> | 60 | #include <asm/prom.h> |
62 | #endif | 61 | #endif |
63 | #include <asm/pgtable.h> | ||
64 | 62 | ||
65 | #include "macmodes.h" | 63 | #include "macmodes.h" |
66 | #include "valkyriefb.h" | 64 | #include "valkyriefb.h" |
@@ -318,7 +316,7 @@ static void __init valkyrie_choose_mode(struct fb_info_valkyrie *p) | |||
318 | int __init valkyriefb_init(void) | 316 | int __init valkyriefb_init(void) |
319 | { | 317 | { |
320 | struct fb_info_valkyrie *p; | 318 | struct fb_info_valkyrie *p; |
321 | unsigned long frame_buffer_phys, cmap_regs_phys, flags; | 319 | unsigned long frame_buffer_phys, cmap_regs_phys; |
322 | int err; | 320 | int err; |
323 | char *option = NULL; | 321 | char *option = NULL; |
324 | 322 | ||
@@ -337,7 +335,6 @@ int __init valkyriefb_init(void) | |||
337 | /* Hardcoded addresses... welcome to 68k Macintosh country :-) */ | 335 | /* Hardcoded addresses... welcome to 68k Macintosh country :-) */ |
338 | frame_buffer_phys = 0xf9000000; | 336 | frame_buffer_phys = 0xf9000000; |
339 | cmap_regs_phys = 0x50f24000; | 337 | cmap_regs_phys = 0x50f24000; |
340 | flags = IOMAP_NOCACHE_SER; /* IOMAP_WRITETHROUGH?? */ | ||
341 | #else /* ppc (!CONFIG_MAC) */ | 338 | #else /* ppc (!CONFIG_MAC) */ |
342 | { | 339 | { |
343 | struct device_node *dp; | 340 | struct device_node *dp; |
@@ -354,7 +351,6 @@ int __init valkyriefb_init(void) | |||
354 | 351 | ||
355 | frame_buffer_phys = r.start; | 352 | frame_buffer_phys = r.start; |
356 | cmap_regs_phys = r.start + 0x304000; | 353 | cmap_regs_phys = r.start + 0x304000; |
357 | flags = _PAGE_WRITETHRU; | ||
358 | } | 354 | } |
359 | #endif /* ppc (!CONFIG_MAC) */ | 355 | #endif /* ppc (!CONFIG_MAC) */ |
360 | 356 | ||
@@ -369,7 +365,11 @@ int __init valkyriefb_init(void) | |||
369 | } | 365 | } |
370 | p->total_vram = 0x100000; | 366 | p->total_vram = 0x100000; |
371 | p->frame_buffer_phys = frame_buffer_phys; | 367 | p->frame_buffer_phys = frame_buffer_phys; |
372 | p->frame_buffer = __ioremap(frame_buffer_phys, p->total_vram, flags); | 368 | #ifdef CONFIG_MAC |
369 | p->frame_buffer = ioremap_nocache(frame_buffer_phys, p->total_vram); | ||
370 | #else | ||
371 | p->frame_buffer = ioremap_wt(frame_buffer_phys, p->total_vram); | ||
372 | #endif | ||
373 | p->cmap_regs_phys = cmap_regs_phys; | 373 | p->cmap_regs_phys = cmap_regs_phys; |
374 | p->cmap_regs = ioremap(p->cmap_regs_phys, 0x1000); | 374 | p->cmap_regs = ioremap(p->cmap_regs_phys, 0x1000); |
375 | p->valkyrie_regs_phys = cmap_regs_phys+0x6000; | 375 | p->valkyrie_regs_phys = cmap_regs_phys+0x6000; |
diff --git a/include/linux/cuda.h b/include/linux/cuda.h index 056867f09a01..45bfe9d61271 100644 --- a/include/linux/cuda.h +++ b/include/linux/cuda.h | |||
@@ -8,6 +8,7 @@ | |||
8 | #ifndef _LINUX_CUDA_H | 8 | #ifndef _LINUX_CUDA_H |
9 | #define _LINUX_CUDA_H | 9 | #define _LINUX_CUDA_H |
10 | 10 | ||
11 | #include <linux/rtc.h> | ||
11 | #include <uapi/linux/cuda.h> | 12 | #include <uapi/linux/cuda.h> |
12 | 13 | ||
13 | 14 | ||
@@ -16,4 +17,7 @@ extern int cuda_request(struct adb_request *req, | |||
16 | void (*done)(struct adb_request *), int nbytes, ...); | 17 | void (*done)(struct adb_request *), int nbytes, ...); |
17 | extern void cuda_poll(void); | 18 | extern void cuda_poll(void); |
18 | 19 | ||
20 | extern time64_t cuda_get_time(void); | ||
21 | extern int cuda_set_rtc_time(struct rtc_time *tm); | ||
22 | |||
19 | #endif /* _LINUX_CUDA_H */ | 23 | #endif /* _LINUX_CUDA_H */ |
diff --git a/include/linux/pmu.h b/include/linux/pmu.h index 9ac8fc60ad49..52453a24a24f 100644 --- a/include/linux/pmu.h +++ b/include/linux/pmu.h | |||
@@ -9,6 +9,7 @@ | |||
9 | #ifndef _LINUX_PMU_H | 9 | #ifndef _LINUX_PMU_H |
10 | #define _LINUX_PMU_H | 10 | #define _LINUX_PMU_H |
11 | 11 | ||
12 | #include <linux/rtc.h> | ||
12 | #include <uapi/linux/pmu.h> | 13 | #include <uapi/linux/pmu.h> |
13 | 14 | ||
14 | 15 | ||
@@ -36,6 +37,9 @@ static inline void pmu_resume(void) | |||
36 | 37 | ||
37 | extern void pmu_enable_irled(int on); | 38 | extern void pmu_enable_irled(int on); |
38 | 39 | ||
40 | extern time64_t pmu_get_time(void); | ||
41 | extern int pmu_set_rtc_time(struct rtc_time *tm); | ||
42 | |||
39 | extern void pmu_restart(void); | 43 | extern void pmu_restart(void); |
40 | extern void pmu_shutdown(void); | 44 | extern void pmu_shutdown(void); |
41 | extern void pmu_unlock(void); | 45 | extern void pmu_unlock(void); |
diff --git a/tools/testing/selftests/powerpc/Makefile b/tools/testing/selftests/powerpc/Makefile index 201b598558b9..b3ad909aefbc 100644 --- a/tools/testing/selftests/powerpc/Makefile +++ b/tools/testing/selftests/powerpc/Makefile | |||
@@ -28,7 +28,8 @@ SUB_DIRS = alignment \ | |||
28 | tm \ | 28 | tm \ |
29 | vphn \ | 29 | vphn \ |
30 | math \ | 30 | math \ |
31 | ptrace | 31 | ptrace \ |
32 | security | ||
32 | 33 | ||
33 | endif | 34 | endif |
34 | 35 | ||
diff --git a/tools/testing/selftests/powerpc/include/reg.h b/tools/testing/selftests/powerpc/include/reg.h index 7f348c059bc2..52b4710469d2 100644 --- a/tools/testing/selftests/powerpc/include/reg.h +++ b/tools/testing/selftests/powerpc/include/reg.h | |||
@@ -17,6 +17,7 @@ | |||
17 | : "memory") | 17 | : "memory") |
18 | 18 | ||
19 | #define mb() asm volatile("sync" : : : "memory"); | 19 | #define mb() asm volatile("sync" : : : "memory"); |
20 | #define barrier() asm volatile("" : : : "memory"); | ||
20 | 21 | ||
21 | #define SPRN_MMCR2 769 | 22 | #define SPRN_MMCR2 769 |
22 | #define SPRN_MMCRA 770 | 23 | #define SPRN_MMCRA 770 |
diff --git a/tools/testing/selftests/powerpc/include/utils.h b/tools/testing/selftests/powerpc/include/utils.h index c58c370828b4..49621822d7c3 100644 --- a/tools/testing/selftests/powerpc/include/utils.h +++ b/tools/testing/selftests/powerpc/include/utils.h | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <stdint.h> | 11 | #include <stdint.h> |
12 | #include <stdbool.h> | 12 | #include <stdbool.h> |
13 | #include <linux/auxvec.h> | 13 | #include <linux/auxvec.h> |
14 | #include <linux/perf_event.h> | ||
14 | #include "reg.h" | 15 | #include "reg.h" |
15 | 16 | ||
16 | /* Avoid headaches with PRI?64 - just use %ll? always */ | 17 | /* Avoid headaches with PRI?64 - just use %ll? always */ |
@@ -31,6 +32,15 @@ void *get_auxv_entry(int type); | |||
31 | 32 | ||
32 | int pick_online_cpu(void); | 33 | int pick_online_cpu(void); |
33 | 34 | ||
35 | int read_debugfs_file(char *debugfs_file, int *result); | ||
36 | int write_debugfs_file(char *debugfs_file, int result); | ||
37 | void set_dscr(unsigned long val); | ||
38 | int perf_event_open_counter(unsigned int type, | ||
39 | unsigned long config, int group_fd); | ||
40 | int perf_event_enable(int fd); | ||
41 | int perf_event_disable(int fd); | ||
42 | int perf_event_reset(int fd); | ||
43 | |||
34 | static inline bool have_hwcap(unsigned long ftr) | 44 | static inline bool have_hwcap(unsigned long ftr) |
35 | { | 45 | { |
36 | return ((unsigned long)get_auxv_entry(AT_HWCAP) & ftr) == ftr; | 46 | return ((unsigned long)get_auxv_entry(AT_HWCAP) & ftr) == ftr; |
@@ -80,4 +90,12 @@ do { \ | |||
80 | #define PPC_FEATURE2_ARCH_3_00 0x00800000 | 90 | #define PPC_FEATURE2_ARCH_3_00 0x00800000 |
81 | #endif | 91 | #endif |
82 | 92 | ||
93 | #if defined(__powerpc64__) | ||
94 | #define UCONTEXT_NIA(UC) (UC)->uc_mcontext.gp_regs[PT_NIP] | ||
95 | #elif defined(__powerpc__) | ||
96 | #define UCONTEXT_NIA(UC) (UC)->uc_mcontext.uc_regs->gregs[PT_NIP] | ||
97 | #else | ||
98 | #error implement UCONTEXT_NIA | ||
99 | #endif | ||
100 | |||
83 | #endif /* _SELFTESTS_POWERPC_UTILS_H */ | 101 | #endif /* _SELFTESTS_POWERPC_UTILS_H */ |
diff --git a/tools/testing/selftests/powerpc/mm/.gitignore b/tools/testing/selftests/powerpc/mm/.gitignore index 7d7c42ed6de9..ba919308fe30 100644 --- a/tools/testing/selftests/powerpc/mm/.gitignore +++ b/tools/testing/selftests/powerpc/mm/.gitignore | |||
@@ -2,4 +2,5 @@ hugetlb_vs_thp_test | |||
2 | subpage_prot | 2 | subpage_prot |
3 | tempfile | 3 | tempfile |
4 | prot_sao | 4 | prot_sao |
5 | segv_errors \ No newline at end of file | 5 | segv_errors |
6 | wild_bctr \ No newline at end of file | ||
diff --git a/tools/testing/selftests/powerpc/mm/Makefile b/tools/testing/selftests/powerpc/mm/Makefile index 33ced6e0ad25..43d68420e363 100644 --- a/tools/testing/selftests/powerpc/mm/Makefile +++ b/tools/testing/selftests/powerpc/mm/Makefile | |||
@@ -2,7 +2,7 @@ | |||
2 | noarg: | 2 | noarg: |
3 | $(MAKE) -C ../ | 3 | $(MAKE) -C ../ |
4 | 4 | ||
5 | TEST_GEN_PROGS := hugetlb_vs_thp_test subpage_prot prot_sao segv_errors | 5 | TEST_GEN_PROGS := hugetlb_vs_thp_test subpage_prot prot_sao segv_errors wild_bctr |
6 | TEST_GEN_FILES := tempfile | 6 | TEST_GEN_FILES := tempfile |
7 | 7 | ||
8 | top_srcdir = ../../../../.. | 8 | top_srcdir = ../../../../.. |
@@ -12,6 +12,8 @@ $(TEST_GEN_PROGS): ../harness.c | |||
12 | 12 | ||
13 | $(OUTPUT)/prot_sao: ../utils.c | 13 | $(OUTPUT)/prot_sao: ../utils.c |
14 | 14 | ||
15 | $(OUTPUT)/wild_bctr: CFLAGS += -m64 | ||
16 | |||
15 | $(OUTPUT)/tempfile: | 17 | $(OUTPUT)/tempfile: |
16 | dd if=/dev/zero of=$@ bs=64k count=1 | 18 | dd if=/dev/zero of=$@ bs=64k count=1 |
17 | 19 | ||
diff --git a/tools/testing/selftests/powerpc/mm/wild_bctr.c b/tools/testing/selftests/powerpc/mm/wild_bctr.c new file mode 100644 index 000000000000..1b0e9e9a2ddc --- /dev/null +++ b/tools/testing/selftests/powerpc/mm/wild_bctr.c | |||
@@ -0,0 +1,155 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0+ | ||
2 | /* | ||
3 | * Copyright 2018, Michael Ellerman, IBM Corp. | ||
4 | * | ||
5 | * Test that an out-of-bounds branch to counter behaves as expected. | ||
6 | */ | ||
7 | |||
8 | #include <setjmp.h> | ||
9 | #include <stdio.h> | ||
10 | #include <stdlib.h> | ||
11 | #include <string.h> | ||
12 | #include <sys/mman.h> | ||
13 | #include <sys/types.h> | ||
14 | #include <sys/wait.h> | ||
15 | #include <ucontext.h> | ||
16 | #include <unistd.h> | ||
17 | |||
18 | #include "utils.h" | ||
19 | |||
20 | |||
21 | #define BAD_NIP 0x788c545a18000000ull | ||
22 | |||
23 | static struct pt_regs signal_regs; | ||
24 | static jmp_buf setjmp_env; | ||
25 | |||
26 | static void save_regs(ucontext_t *ctxt) | ||
27 | { | ||
28 | struct pt_regs *regs = ctxt->uc_mcontext.regs; | ||
29 | |||
30 | memcpy(&signal_regs, regs, sizeof(signal_regs)); | ||
31 | } | ||
32 | |||
33 | static void segv_handler(int signum, siginfo_t *info, void *ctxt_v) | ||
34 | { | ||
35 | save_regs(ctxt_v); | ||
36 | longjmp(setjmp_env, 1); | ||
37 | } | ||
38 | |||
39 | static void usr2_handler(int signum, siginfo_t *info, void *ctxt_v) | ||
40 | { | ||
41 | save_regs(ctxt_v); | ||
42 | } | ||
43 | |||
44 | static int ok(void) | ||
45 | { | ||
46 | printf("Everything is OK in here.\n"); | ||
47 | return 0; | ||
48 | } | ||
49 | |||
50 | #define REG_POISON 0x5a5aUL | ||
51 | #define POISONED_REG(n) ((REG_POISON << 48) | ((n) << 32) | (REG_POISON << 16) | (n)) | ||
52 | |||
53 | static inline void poison_regs(void) | ||
54 | { | ||
55 | #define POISON_REG(n) \ | ||
56 | "lis " __stringify(n) "," __stringify(REG_POISON) ";" \ | ||
57 | "addi " __stringify(n) "," __stringify(n) "," __stringify(n) ";" \ | ||
58 | "sldi " __stringify(n) "," __stringify(n) ", 32 ;" \ | ||
59 | "oris " __stringify(n) "," __stringify(n) "," __stringify(REG_POISON) ";" \ | ||
60 | "addi " __stringify(n) "," __stringify(n) "," __stringify(n) ";" | ||
61 | |||
62 | asm (POISON_REG(15) | ||
63 | POISON_REG(16) | ||
64 | POISON_REG(17) | ||
65 | POISON_REG(18) | ||
66 | POISON_REG(19) | ||
67 | POISON_REG(20) | ||
68 | POISON_REG(21) | ||
69 | POISON_REG(22) | ||
70 | POISON_REG(23) | ||
71 | POISON_REG(24) | ||
72 | POISON_REG(25) | ||
73 | POISON_REG(26) | ||
74 | POISON_REG(27) | ||
75 | POISON_REG(28) | ||
76 | POISON_REG(29) | ||
77 | : // inputs | ||
78 | : // outputs | ||
79 | : "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", | ||
80 | "26", "27", "28", "29" | ||
81 | ); | ||
82 | #undef POISON_REG | ||
83 | } | ||
84 | |||
85 | static int check_regs(void) | ||
86 | { | ||
87 | unsigned long i; | ||
88 | |||
89 | for (i = 15; i <= 29; i++) | ||
90 | FAIL_IF(signal_regs.gpr[i] != POISONED_REG(i)); | ||
91 | |||
92 | printf("Regs OK\n"); | ||
93 | return 0; | ||
94 | } | ||
95 | |||
96 | static void dump_regs(void) | ||
97 | { | ||
98 | for (int i = 0; i < 32; i += 4) { | ||
99 | printf("r%02d 0x%016lx r%02d 0x%016lx " \ | ||
100 | "r%02d 0x%016lx r%02d 0x%016lx\n", | ||
101 | i, signal_regs.gpr[i], | ||
102 | i+1, signal_regs.gpr[i+1], | ||
103 | i+2, signal_regs.gpr[i+2], | ||
104 | i+3, signal_regs.gpr[i+3]); | ||
105 | } | ||
106 | } | ||
107 | |||
108 | int test_wild_bctr(void) | ||
109 | { | ||
110 | int (*func_ptr)(void); | ||
111 | struct sigaction segv = { | ||
112 | .sa_sigaction = segv_handler, | ||
113 | .sa_flags = SA_SIGINFO | ||
114 | }; | ||
115 | struct sigaction usr2 = { | ||
116 | .sa_sigaction = usr2_handler, | ||
117 | .sa_flags = SA_SIGINFO | ||
118 | }; | ||
119 | |||
120 | FAIL_IF(sigaction(SIGSEGV, &segv, NULL)); | ||
121 | FAIL_IF(sigaction(SIGUSR2, &usr2, NULL)); | ||
122 | |||
123 | bzero(&signal_regs, sizeof(signal_regs)); | ||
124 | |||
125 | if (setjmp(setjmp_env) == 0) { | ||
126 | func_ptr = ok; | ||
127 | func_ptr(); | ||
128 | |||
129 | kill(getpid(), SIGUSR2); | ||
130 | printf("Regs before:\n"); | ||
131 | dump_regs(); | ||
132 | bzero(&signal_regs, sizeof(signal_regs)); | ||
133 | |||
134 | poison_regs(); | ||
135 | |||
136 | func_ptr = (int (*)(void))BAD_NIP; | ||
137 | func_ptr(); | ||
138 | |||
139 | FAIL_IF(1); /* we didn't segv? */ | ||
140 | } | ||
141 | |||
142 | FAIL_IF(signal_regs.nip != BAD_NIP); | ||
143 | |||
144 | printf("All good - took SEGV as expected branching to 0x%llx\n", BAD_NIP); | ||
145 | |||
146 | dump_regs(); | ||
147 | FAIL_IF(check_regs()); | ||
148 | |||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | int main(void) | ||
153 | { | ||
154 | return test_harness(test_wild_bctr, "wild_bctr"); | ||
155 | } | ||
diff --git a/tools/testing/selftests/powerpc/primitives/load_unaligned_zeropad.c b/tools/testing/selftests/powerpc/primitives/load_unaligned_zeropad.c index ed3239bbfae2..ee1e9ca22f0d 100644 --- a/tools/testing/selftests/powerpc/primitives/load_unaligned_zeropad.c +++ b/tools/testing/selftests/powerpc/primitives/load_unaligned_zeropad.c | |||
@@ -65,14 +65,6 @@ static int unprotect_region(void) | |||
65 | extern char __start___ex_table[]; | 65 | extern char __start___ex_table[]; |
66 | extern char __stop___ex_table[]; | 66 | extern char __stop___ex_table[]; |
67 | 67 | ||
68 | #if defined(__powerpc64__) | ||
69 | #define UCONTEXT_NIA(UC) (UC)->uc_mcontext.gp_regs[PT_NIP] | ||
70 | #elif defined(__powerpc__) | ||
71 | #define UCONTEXT_NIA(UC) (UC)->uc_mcontext.uc_regs->gregs[PT_NIP] | ||
72 | #else | ||
73 | #error implement UCONTEXT_NIA | ||
74 | #endif | ||
75 | |||
76 | struct extbl_entry { | 68 | struct extbl_entry { |
77 | int insn; | 69 | int insn; |
78 | int fixup; | 70 | int fixup; |
diff --git a/tools/testing/selftests/powerpc/ptrace/Makefile b/tools/testing/selftests/powerpc/ptrace/Makefile index 923d531265f8..9b35ca8e8f13 100644 --- a/tools/testing/selftests/powerpc/ptrace/Makefile +++ b/tools/testing/selftests/powerpc/ptrace/Makefile | |||
@@ -2,7 +2,7 @@ | |||
2 | TEST_PROGS := ptrace-gpr ptrace-tm-gpr ptrace-tm-spd-gpr \ | 2 | TEST_PROGS := ptrace-gpr ptrace-tm-gpr ptrace-tm-spd-gpr \ |
3 | ptrace-tar ptrace-tm-tar ptrace-tm-spd-tar ptrace-vsx ptrace-tm-vsx \ | 3 | ptrace-tar ptrace-tm-tar ptrace-tm-spd-tar ptrace-vsx ptrace-tm-vsx \ |
4 | ptrace-tm-spd-vsx ptrace-tm-spr ptrace-hwbreak ptrace-pkey core-pkey \ | 4 | ptrace-tm-spd-vsx ptrace-tm-spr ptrace-hwbreak ptrace-pkey core-pkey \ |
5 | perf-hwbreak | 5 | perf-hwbreak ptrace-syscall |
6 | 6 | ||
7 | top_srcdir = ../../../../.. | 7 | top_srcdir = ../../../../.. |
8 | include ../../lib.mk | 8 | include ../../lib.mk |
diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace-syscall.c b/tools/testing/selftests/powerpc/ptrace/ptrace-syscall.c new file mode 100644 index 000000000000..3353210dcdbd --- /dev/null +++ b/tools/testing/selftests/powerpc/ptrace/ptrace-syscall.c | |||
@@ -0,0 +1,228 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /* | ||
3 | * A ptrace test for testing PTRACE_SYSEMU, PTRACE_SETREGS and | ||
4 | * PTRACE_GETREG. This test basically create a child process that executes | ||
5 | * syscalls and the parent process check if it is being traced appropriated. | ||
6 | * | ||
7 | * This test is heavily based on tools/testing/selftests/x86/ptrace_syscall.c | ||
8 | * test, and it was adapted to run on Powerpc by | ||
9 | * Breno Leitao <leitao@debian.org> | ||
10 | */ | ||
11 | #define _GNU_SOURCE | ||
12 | |||
13 | #include <sys/ptrace.h> | ||
14 | #include <sys/types.h> | ||
15 | #include <sys/wait.h> | ||
16 | #include <sys/syscall.h> | ||
17 | #include <sys/user.h> | ||
18 | #include <unistd.h> | ||
19 | #include <errno.h> | ||
20 | #include <stddef.h> | ||
21 | #include <stdio.h> | ||
22 | #include <err.h> | ||
23 | #include <string.h> | ||
24 | #include <sys/auxv.h> | ||
25 | #include "utils.h" | ||
26 | |||
27 | /* Bitness-agnostic defines for user_regs_struct fields. */ | ||
28 | #define user_syscall_nr gpr[0] | ||
29 | #define user_arg0 gpr[3] | ||
30 | #define user_arg1 gpr[4] | ||
31 | #define user_arg2 gpr[5] | ||
32 | #define user_arg3 gpr[6] | ||
33 | #define user_arg4 gpr[7] | ||
34 | #define user_arg5 gpr[8] | ||
35 | #define user_ip nip | ||
36 | |||
37 | #define PTRACE_SYSEMU 0x1d | ||
38 | |||
39 | static int nerrs; | ||
40 | |||
41 | static void wait_trap(pid_t chld) | ||
42 | { | ||
43 | siginfo_t si; | ||
44 | |||
45 | if (waitid(P_PID, chld, &si, WEXITED|WSTOPPED) != 0) | ||
46 | err(1, "waitid"); | ||
47 | if (si.si_pid != chld) | ||
48 | errx(1, "got unexpected pid in event\n"); | ||
49 | if (si.si_code != CLD_TRAPPED) | ||
50 | errx(1, "got unexpected event type %d\n", si.si_code); | ||
51 | } | ||
52 | |||
53 | static void test_ptrace_syscall_restart(void) | ||
54 | { | ||
55 | int status; | ||
56 | struct pt_regs regs; | ||
57 | pid_t chld; | ||
58 | |||
59 | printf("[RUN]\tptrace-induced syscall restart\n"); | ||
60 | |||
61 | chld = fork(); | ||
62 | if (chld < 0) | ||
63 | err(1, "fork"); | ||
64 | |||
65 | /* | ||
66 | * Child process is running 4 syscalls after ptrace. | ||
67 | * | ||
68 | * 1) getpid() | ||
69 | * 2) gettid() | ||
70 | * 3) tgkill() -> Send SIGSTOP | ||
71 | * 4) gettid() -> Where the tests will happen essentially | ||
72 | */ | ||
73 | if (chld == 0) { | ||
74 | if (ptrace(PTRACE_TRACEME, 0, 0, 0) != 0) | ||
75 | err(1, "PTRACE_TRACEME"); | ||
76 | |||
77 | pid_t pid = getpid(), tid = syscall(SYS_gettid); | ||
78 | |||
79 | printf("\tChild will make one syscall\n"); | ||
80 | syscall(SYS_tgkill, pid, tid, SIGSTOP); | ||
81 | |||
82 | syscall(SYS_gettid, 10, 11, 12, 13, 14, 15); | ||
83 | _exit(0); | ||
84 | } | ||
85 | /* Parent process below */ | ||
86 | |||
87 | /* Wait for SIGSTOP sent by tgkill above. */ | ||
88 | if (waitpid(chld, &status, 0) != chld || !WIFSTOPPED(status)) | ||
89 | err(1, "waitpid"); | ||
90 | |||
91 | printf("[RUN]\tSYSEMU\n"); | ||
92 | if (ptrace(PTRACE_SYSEMU, chld, 0, 0) != 0) | ||
93 | err(1, "PTRACE_SYSEMU"); | ||
94 | wait_trap(chld); | ||
95 | |||
96 | if (ptrace(PTRACE_GETREGS, chld, 0, ®s) != 0) | ||
97 | err(1, "PTRACE_GETREGS"); | ||
98 | |||
99 | /* | ||
100 | * Ptrace trapped prior to executing the syscall, thus r3 still has | ||
101 | * the syscall number instead of the sys_gettid() result | ||
102 | */ | ||
103 | if (regs.user_syscall_nr != SYS_gettid || | ||
104 | regs.user_arg0 != 10 || regs.user_arg1 != 11 || | ||
105 | regs.user_arg2 != 12 || regs.user_arg3 != 13 || | ||
106 | regs.user_arg4 != 14 || regs.user_arg5 != 15) { | ||
107 | printf("[FAIL]\tInitial args are wrong (nr=%lu, args=%lu %lu %lu %lu %lu %lu)\n", | ||
108 | (unsigned long)regs.user_syscall_nr, | ||
109 | (unsigned long)regs.user_arg0, | ||
110 | (unsigned long)regs.user_arg1, | ||
111 | (unsigned long)regs.user_arg2, | ||
112 | (unsigned long)regs.user_arg3, | ||
113 | (unsigned long)regs.user_arg4, | ||
114 | (unsigned long)regs.user_arg5); | ||
115 | nerrs++; | ||
116 | } else { | ||
117 | printf("[OK]\tInitial nr and args are correct\n"); } | ||
118 | |||
119 | printf("[RUN]\tRestart the syscall (ip = 0x%lx)\n", | ||
120 | (unsigned long)regs.user_ip); | ||
121 | |||
122 | /* | ||
123 | * Rewind to retry the same syscall again. This will basically test | ||
124 | * the rewind process together with PTRACE_SETREGS and PTRACE_GETREGS. | ||
125 | */ | ||
126 | regs.user_ip -= 4; | ||
127 | if (ptrace(PTRACE_SETREGS, chld, 0, ®s) != 0) | ||
128 | err(1, "PTRACE_SETREGS"); | ||
129 | |||
130 | if (ptrace(PTRACE_SYSEMU, chld, 0, 0) != 0) | ||
131 | err(1, "PTRACE_SYSEMU"); | ||
132 | wait_trap(chld); | ||
133 | |||
134 | if (ptrace(PTRACE_GETREGS, chld, 0, ®s) != 0) | ||
135 | err(1, "PTRACE_GETREGS"); | ||
136 | |||
137 | if (regs.user_syscall_nr != SYS_gettid || | ||
138 | regs.user_arg0 != 10 || regs.user_arg1 != 11 || | ||
139 | regs.user_arg2 != 12 || regs.user_arg3 != 13 || | ||
140 | regs.user_arg4 != 14 || regs.user_arg5 != 15) { | ||
141 | printf("[FAIL]\tRestart nr or args are wrong (nr=%lu, args=%lu %lu %lu %lu %lu %lu)\n", | ||
142 | (unsigned long)regs.user_syscall_nr, | ||
143 | (unsigned long)regs.user_arg0, | ||
144 | (unsigned long)regs.user_arg1, | ||
145 | (unsigned long)regs.user_arg2, | ||
146 | (unsigned long)regs.user_arg3, | ||
147 | (unsigned long)regs.user_arg4, | ||
148 | (unsigned long)regs.user_arg5); | ||
149 | nerrs++; | ||
150 | } else { | ||
151 | printf("[OK]\tRestarted nr and args are correct\n"); | ||
152 | } | ||
153 | |||
154 | printf("[RUN]\tChange nr and args and restart the syscall (ip = 0x%lx)\n", | ||
155 | (unsigned long)regs.user_ip); | ||
156 | |||
157 | /* | ||
158 | * Inject a new syscall (getpid) in the same place the previous | ||
159 | * syscall (gettid), rewind and re-execute. | ||
160 | */ | ||
161 | regs.user_syscall_nr = SYS_getpid; | ||
162 | regs.user_arg0 = 20; | ||
163 | regs.user_arg1 = 21; | ||
164 | regs.user_arg2 = 22; | ||
165 | regs.user_arg3 = 23; | ||
166 | regs.user_arg4 = 24; | ||
167 | regs.user_arg5 = 25; | ||
168 | regs.user_ip -= 4; | ||
169 | |||
170 | if (ptrace(PTRACE_SETREGS, chld, 0, ®s) != 0) | ||
171 | err(1, "PTRACE_SETREGS"); | ||
172 | |||
173 | if (ptrace(PTRACE_SYSEMU, chld, 0, 0) != 0) | ||
174 | err(1, "PTRACE_SYSEMU"); | ||
175 | wait_trap(chld); | ||
176 | |||
177 | if (ptrace(PTRACE_GETREGS, chld, 0, ®s) != 0) | ||
178 | err(1, "PTRACE_GETREGS"); | ||
179 | |||
180 | /* Check that ptrace stopped at the new syscall that was | ||
181 | * injected, and guarantee that it haven't executed, i.e, user_args | ||
182 | * contain the arguments and not the syscall return value, for | ||
183 | * instance. | ||
184 | */ | ||
185 | if (regs.user_syscall_nr != SYS_getpid | ||
186 | || regs.user_arg0 != 20 || regs.user_arg1 != 21 | ||
187 | || regs.user_arg2 != 22 || regs.user_arg3 != 23 | ||
188 | || regs.user_arg4 != 24 || regs.user_arg5 != 25) { | ||
189 | |||
190 | printf("[FAIL]\tRestart nr or args are wrong (nr=%lu, args=%lu %lu %lu %lu %lu %lu)\n", | ||
191 | (unsigned long)regs.user_syscall_nr, | ||
192 | (unsigned long)regs.user_arg0, | ||
193 | (unsigned long)regs.user_arg1, | ||
194 | (unsigned long)regs.user_arg2, | ||
195 | (unsigned long)regs.user_arg3, | ||
196 | (unsigned long)regs.user_arg4, | ||
197 | (unsigned long)regs.user_arg5); | ||
198 | nerrs++; | ||
199 | } else { | ||
200 | printf("[OK]\tReplacement nr and args are correct\n"); | ||
201 | } | ||
202 | |||
203 | if (ptrace(PTRACE_CONT, chld, 0, 0) != 0) | ||
204 | err(1, "PTRACE_CONT"); | ||
205 | |||
206 | if (waitpid(chld, &status, 0) != chld) | ||
207 | err(1, "waitpid"); | ||
208 | |||
209 | /* Guarantee that the process executed properly, returning 0 */ | ||
210 | if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { | ||
211 | printf("[FAIL]\tChild failed\n"); | ||
212 | nerrs++; | ||
213 | } else { | ||
214 | printf("[OK]\tChild exited cleanly\n"); | ||
215 | } | ||
216 | } | ||
217 | |||
218 | int ptrace_syscall(void) | ||
219 | { | ||
220 | test_ptrace_syscall_restart(); | ||
221 | |||
222 | return nerrs; | ||
223 | } | ||
224 | |||
225 | int main(void) | ||
226 | { | ||
227 | return test_harness(ptrace_syscall, "ptrace_syscall"); | ||
228 | } | ||
diff --git a/tools/testing/selftests/powerpc/security/Makefile b/tools/testing/selftests/powerpc/security/Makefile new file mode 100644 index 000000000000..44690f1bb26a --- /dev/null +++ b/tools/testing/selftests/powerpc/security/Makefile | |||
@@ -0,0 +1,9 @@ | |||
1 | # SPDX-License-Identifier: GPL-2.0+ | ||
2 | |||
3 | TEST_GEN_PROGS := rfi_flush | ||
4 | |||
5 | CFLAGS += -I../../../../../usr/include | ||
6 | |||
7 | include ../../lib.mk | ||
8 | |||
9 | $(TEST_GEN_PROGS): ../harness.c ../utils.c | ||
diff --git a/tools/testing/selftests/powerpc/security/rfi_flush.c b/tools/testing/selftests/powerpc/security/rfi_flush.c new file mode 100644 index 000000000000..564ed45bbf73 --- /dev/null +++ b/tools/testing/selftests/powerpc/security/rfi_flush.c | |||
@@ -0,0 +1,132 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0+ | ||
2 | |||
3 | /* | ||
4 | * Copyright 2018 IBM Corporation. | ||
5 | */ | ||
6 | |||
7 | #define __SANE_USERSPACE_TYPES__ | ||
8 | |||
9 | #include <sys/types.h> | ||
10 | #include <stdint.h> | ||
11 | #include <malloc.h> | ||
12 | #include <unistd.h> | ||
13 | #include <stdlib.h> | ||
14 | #include <string.h> | ||
15 | #include <stdio.h> | ||
16 | #include "utils.h" | ||
17 | |||
18 | #define CACHELINE_SIZE 128 | ||
19 | |||
20 | struct perf_event_read { | ||
21 | __u64 nr; | ||
22 | __u64 l1d_misses; | ||
23 | }; | ||
24 | |||
25 | static inline __u64 load(void *addr) | ||
26 | { | ||
27 | __u64 tmp; | ||
28 | |||
29 | asm volatile("ld %0,0(%1)" : "=r"(tmp) : "b"(addr)); | ||
30 | |||
31 | return tmp; | ||
32 | } | ||
33 | |||
34 | static void syscall_loop(char *p, unsigned long iterations, | ||
35 | unsigned long zero_size) | ||
36 | { | ||
37 | for (unsigned long i = 0; i < iterations; i++) { | ||
38 | for (unsigned long j = 0; j < zero_size; j += CACHELINE_SIZE) | ||
39 | load(p + j); | ||
40 | getppid(); | ||
41 | } | ||
42 | } | ||
43 | |||
44 | int rfi_flush_test(void) | ||
45 | { | ||
46 | char *p; | ||
47 | int repetitions = 10; | ||
48 | int fd, passes = 0, iter, rc = 0; | ||
49 | struct perf_event_read v; | ||
50 | __u64 l1d_misses_total = 0; | ||
51 | unsigned long iterations = 100000, zero_size = 24 * 1024; | ||
52 | int rfi_flush_org, rfi_flush; | ||
53 | |||
54 | SKIP_IF(geteuid() != 0); | ||
55 | |||
56 | if (read_debugfs_file("powerpc/rfi_flush", &rfi_flush_org)) { | ||
57 | perror("Unable to read powerpc/rfi_flush debugfs file"); | ||
58 | SKIP_IF(1); | ||
59 | } | ||
60 | |||
61 | rfi_flush = rfi_flush_org; | ||
62 | |||
63 | fd = perf_event_open_counter(PERF_TYPE_RAW, /* L1d miss */ 0x400f0, -1); | ||
64 | FAIL_IF(fd < 0); | ||
65 | |||
66 | p = (char *)memalign(zero_size, CACHELINE_SIZE); | ||
67 | |||
68 | FAIL_IF(perf_event_enable(fd)); | ||
69 | |||
70 | set_dscr(1); | ||
71 | |||
72 | iter = repetitions; | ||
73 | |||
74 | again: | ||
75 | FAIL_IF(perf_event_reset(fd)); | ||
76 | |||
77 | syscall_loop(p, iterations, zero_size); | ||
78 | |||
79 | FAIL_IF(read(fd, &v, sizeof(v)) != sizeof(v)); | ||
80 | |||
81 | /* Expect at least zero_size/CACHELINE_SIZE misses per iteration */ | ||
82 | if (v.l1d_misses >= (iterations * zero_size / CACHELINE_SIZE) && rfi_flush) | ||
83 | passes++; | ||
84 | else if (v.l1d_misses < iterations && !rfi_flush) | ||
85 | passes++; | ||
86 | |||
87 | l1d_misses_total += v.l1d_misses; | ||
88 | |||
89 | while (--iter) | ||
90 | goto again; | ||
91 | |||
92 | if (passes < repetitions) { | ||
93 | printf("FAIL (L1D misses with rfi_flush=%d: %llu %c %lu) [%d/%d failures]\n", | ||
94 | rfi_flush, l1d_misses_total, rfi_flush ? '<' : '>', | ||
95 | rfi_flush ? (repetitions * iterations * zero_size / CACHELINE_SIZE) : iterations, | ||
96 | repetitions - passes, repetitions); | ||
97 | rc = 1; | ||
98 | } else | ||
99 | printf("PASS (L1D misses with rfi_flush=%d: %llu %c %lu) [%d/%d pass]\n", | ||
100 | rfi_flush, l1d_misses_total, rfi_flush ? '>' : '<', | ||
101 | rfi_flush ? (repetitions * iterations * zero_size / CACHELINE_SIZE) : iterations, | ||
102 | passes, repetitions); | ||
103 | |||
104 | if (rfi_flush == rfi_flush_org) { | ||
105 | rfi_flush = !rfi_flush_org; | ||
106 | if (write_debugfs_file("powerpc/rfi_flush", rfi_flush) < 0) { | ||
107 | perror("error writing to powerpc/rfi_flush debugfs file"); | ||
108 | return 1; | ||
109 | } | ||
110 | iter = repetitions; | ||
111 | l1d_misses_total = 0; | ||
112 | passes = 0; | ||
113 | goto again; | ||
114 | } | ||
115 | |||
116 | perf_event_disable(fd); | ||
117 | close(fd); | ||
118 | |||
119 | set_dscr(0); | ||
120 | |||
121 | if (write_debugfs_file("powerpc/rfi_flush", rfi_flush_org) < 0) { | ||
122 | perror("unable to restore original value of powerpc/rfi_flush debugfs file"); | ||
123 | return 1; | ||
124 | } | ||
125 | |||
126 | return rc; | ||
127 | } | ||
128 | |||
129 | int main(int argc, char *argv[]) | ||
130 | { | ||
131 | return test_harness(rfi_flush_test, "rfi_flush_test"); | ||
132 | } | ||
diff --git a/tools/testing/selftests/powerpc/tm/tm-tmspr.c b/tools/testing/selftests/powerpc/tm/tm-tmspr.c index 2bda81c7bf23..df1d7d4b1c89 100644 --- a/tools/testing/selftests/powerpc/tm/tm-tmspr.c +++ b/tools/testing/selftests/powerpc/tm/tm-tmspr.c | |||
@@ -98,7 +98,7 @@ void texasr(void *in) | |||
98 | 98 | ||
99 | int test_tmspr() | 99 | int test_tmspr() |
100 | { | 100 | { |
101 | pthread_t thread; | 101 | pthread_t *thread; |
102 | int thread_num; | 102 | int thread_num; |
103 | unsigned long i; | 103 | unsigned long i; |
104 | 104 | ||
@@ -107,21 +107,28 @@ int test_tmspr() | |||
107 | /* To cause some context switching */ | 107 | /* To cause some context switching */ |
108 | thread_num = 10 * sysconf(_SC_NPROCESSORS_ONLN); | 108 | thread_num = 10 * sysconf(_SC_NPROCESSORS_ONLN); |
109 | 109 | ||
110 | thread = malloc(thread_num * sizeof(pthread_t)); | ||
111 | if (thread == NULL) | ||
112 | return EXIT_FAILURE; | ||
113 | |||
110 | /* Test TFIAR and TFHAR */ | 114 | /* Test TFIAR and TFHAR */ |
111 | for (i = 0 ; i < thread_num ; i += 2){ | 115 | for (i = 0; i < thread_num; i += 2) { |
112 | if (pthread_create(&thread, NULL, (void*)tfiar_tfhar, (void *)i)) | 116 | if (pthread_create(&thread[i], NULL, (void *)tfiar_tfhar, |
117 | (void *)i)) | ||
113 | return EXIT_FAILURE; | 118 | return EXIT_FAILURE; |
114 | } | 119 | } |
115 | if (pthread_join(thread, NULL) != 0) | ||
116 | return EXIT_FAILURE; | ||
117 | |||
118 | /* Test TEXASR */ | 120 | /* Test TEXASR */ |
119 | for (i = 0 ; i < thread_num ; i++){ | 121 | for (i = 1; i < thread_num; i += 2) { |
120 | if (pthread_create(&thread, NULL, (void*)texasr, (void *)i)) | 122 | if (pthread_create(&thread[i], NULL, (void *)texasr, (void *)i)) |
121 | return EXIT_FAILURE; | 123 | return EXIT_FAILURE; |
122 | } | 124 | } |
123 | if (pthread_join(thread, NULL) != 0) | 125 | |
124 | return EXIT_FAILURE; | 126 | for (i = 0; i < thread_num; i++) { |
127 | if (pthread_join(thread[i], NULL) != 0) | ||
128 | return EXIT_FAILURE; | ||
129 | } | ||
130 | |||
131 | free(thread); | ||
125 | 132 | ||
126 | if (passed) | 133 | if (passed) |
127 | return 0; | 134 | return 0; |
diff --git a/tools/testing/selftests/powerpc/tm/tm-unavailable.c b/tools/testing/selftests/powerpc/tm/tm-unavailable.c index 156c8e750259..09894f4ff62e 100644 --- a/tools/testing/selftests/powerpc/tm/tm-unavailable.c +++ b/tools/testing/selftests/powerpc/tm/tm-unavailable.c | |||
@@ -236,7 +236,8 @@ void *tm_una_ping(void *input) | |||
236 | } | 236 | } |
237 | 237 | ||
238 | /* Check if we were not expecting a failure and a it occurred. */ | 238 | /* Check if we were not expecting a failure and a it occurred. */ |
239 | if (!expecting_failure() && is_failure(cr_)) { | 239 | if (!expecting_failure() && is_failure(cr_) && |
240 | !failure_is_reschedule()) { | ||
240 | printf("\n\tUnexpected transaction failure 0x%02lx\n\t", | 241 | printf("\n\tUnexpected transaction failure 0x%02lx\n\t", |
241 | failure_code()); | 242 | failure_code()); |
242 | return (void *) -1; | 243 | return (void *) -1; |
@@ -244,9 +245,11 @@ void *tm_una_ping(void *input) | |||
244 | 245 | ||
245 | /* | 246 | /* |
246 | * Check if TM failed due to the cause we were expecting. 0xda is a | 247 | * Check if TM failed due to the cause we were expecting. 0xda is a |
247 | * TM_CAUSE_FAC_UNAV cause, otherwise it's an unexpected cause. | 248 | * TM_CAUSE_FAC_UNAV cause, otherwise it's an unexpected cause, unless |
249 | * it was caused by a reschedule. | ||
248 | */ | 250 | */ |
249 | if (is_failure(cr_) && !failure_is_unavailable()) { | 251 | if (is_failure(cr_) && !failure_is_unavailable() && |
252 | !failure_is_reschedule()) { | ||
250 | printf("\n\tUnexpected failure cause 0x%02lx\n\t", | 253 | printf("\n\tUnexpected failure cause 0x%02lx\n\t", |
251 | failure_code()); | 254 | failure_code()); |
252 | return (void *) -1; | 255 | return (void *) -1; |
diff --git a/tools/testing/selftests/powerpc/tm/tm.h b/tools/testing/selftests/powerpc/tm/tm.h index df4204247d45..5518b1d4ef8b 100644 --- a/tools/testing/selftests/powerpc/tm/tm.h +++ b/tools/testing/selftests/powerpc/tm/tm.h | |||
@@ -52,6 +52,15 @@ static inline bool failure_is_unavailable(void) | |||
52 | return (failure_code() & TM_CAUSE_FAC_UNAV) == TM_CAUSE_FAC_UNAV; | 52 | return (failure_code() & TM_CAUSE_FAC_UNAV) == TM_CAUSE_FAC_UNAV; |
53 | } | 53 | } |
54 | 54 | ||
55 | static inline bool failure_is_reschedule(void) | ||
56 | { | ||
57 | if ((failure_code() & TM_CAUSE_RESCHED) == TM_CAUSE_RESCHED || | ||
58 | (failure_code() & TM_CAUSE_KVM_RESCHED) == TM_CAUSE_KVM_RESCHED) | ||
59 | return true; | ||
60 | |||
61 | return false; | ||
62 | } | ||
63 | |||
55 | static inline bool failure_is_nesting(void) | 64 | static inline bool failure_is_nesting(void) |
56 | { | 65 | { |
57 | return (__builtin_get_texasru() & 0x400000); | 66 | return (__builtin_get_texasru() & 0x400000); |
diff --git a/tools/testing/selftests/powerpc/utils.c b/tools/testing/selftests/powerpc/utils.c index aa8fc1e6365b..43c342845be0 100644 --- a/tools/testing/selftests/powerpc/utils.c +++ b/tools/testing/selftests/powerpc/utils.c | |||
@@ -10,16 +10,22 @@ | |||
10 | #include <fcntl.h> | 10 | #include <fcntl.h> |
11 | #include <link.h> | 11 | #include <link.h> |
12 | #include <sched.h> | 12 | #include <sched.h> |
13 | #include <signal.h> | ||
13 | #include <stdio.h> | 14 | #include <stdio.h> |
15 | #include <stdlib.h> | ||
14 | #include <string.h> | 16 | #include <string.h> |
17 | #include <sys/ioctl.h> | ||
15 | #include <sys/stat.h> | 18 | #include <sys/stat.h> |
16 | #include <sys/types.h> | 19 | #include <sys/types.h> |
17 | #include <sys/utsname.h> | 20 | #include <sys/utsname.h> |
18 | #include <unistd.h> | 21 | #include <unistd.h> |
22 | #include <asm/unistd.h> | ||
23 | #include <linux/limits.h> | ||
19 | 24 | ||
20 | #include "utils.h" | 25 | #include "utils.h" |
21 | 26 | ||
22 | static char auxv[4096]; | 27 | static char auxv[4096]; |
28 | extern unsigned int dscr_insn[]; | ||
23 | 29 | ||
24 | int read_auxv(char *buf, ssize_t buf_size) | 30 | int read_auxv(char *buf, ssize_t buf_size) |
25 | { | 31 | { |
@@ -121,3 +127,149 @@ bool is_ppc64le(void) | |||
121 | 127 | ||
122 | return strcmp(uts.machine, "ppc64le") == 0; | 128 | return strcmp(uts.machine, "ppc64le") == 0; |
123 | } | 129 | } |
130 | |||
131 | int read_debugfs_file(char *debugfs_file, int *result) | ||
132 | { | ||
133 | int rc = -1, fd; | ||
134 | char path[PATH_MAX]; | ||
135 | char value[16]; | ||
136 | |||
137 | strcpy(path, "/sys/kernel/debug/"); | ||
138 | strncat(path, debugfs_file, PATH_MAX - strlen(path) - 1); | ||
139 | |||
140 | if ((fd = open(path, O_RDONLY)) < 0) | ||
141 | return rc; | ||
142 | |||
143 | if ((rc = read(fd, value, sizeof(value))) < 0) | ||
144 | return rc; | ||
145 | |||
146 | value[15] = 0; | ||
147 | *result = atoi(value); | ||
148 | close(fd); | ||
149 | |||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | int write_debugfs_file(char *debugfs_file, int result) | ||
154 | { | ||
155 | int rc = -1, fd; | ||
156 | char path[PATH_MAX]; | ||
157 | char value[16]; | ||
158 | |||
159 | strcpy(path, "/sys/kernel/debug/"); | ||
160 | strncat(path, debugfs_file, PATH_MAX - strlen(path) - 1); | ||
161 | |||
162 | if ((fd = open(path, O_WRONLY)) < 0) | ||
163 | return rc; | ||
164 | |||
165 | snprintf(value, 16, "%d", result); | ||
166 | |||
167 | if ((rc = write(fd, value, strlen(value))) < 0) | ||
168 | return rc; | ||
169 | |||
170 | close(fd); | ||
171 | |||
172 | return 0; | ||
173 | } | ||
174 | |||
175 | static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid, | ||
176 | int cpu, int group_fd, unsigned long flags) | ||
177 | { | ||
178 | return syscall(__NR_perf_event_open, hw_event, pid, cpu, | ||
179 | group_fd, flags); | ||
180 | } | ||
181 | |||
182 | static void perf_event_attr_init(struct perf_event_attr *event_attr, | ||
183 | unsigned int type, | ||
184 | unsigned long config) | ||
185 | { | ||
186 | memset(event_attr, 0, sizeof(*event_attr)); | ||
187 | |||
188 | event_attr->type = type; | ||
189 | event_attr->size = sizeof(struct perf_event_attr); | ||
190 | event_attr->config = config; | ||
191 | event_attr->read_format = PERF_FORMAT_GROUP; | ||
192 | event_attr->disabled = 1; | ||
193 | event_attr->exclude_kernel = 1; | ||
194 | event_attr->exclude_hv = 1; | ||
195 | event_attr->exclude_guest = 1; | ||
196 | } | ||
197 | |||
198 | int perf_event_open_counter(unsigned int type, | ||
199 | unsigned long config, int group_fd) | ||
200 | { | ||
201 | int fd; | ||
202 | struct perf_event_attr event_attr; | ||
203 | |||
204 | perf_event_attr_init(&event_attr, type, config); | ||
205 | |||
206 | fd = perf_event_open(&event_attr, 0, -1, group_fd, 0); | ||
207 | |||
208 | if (fd < 0) | ||
209 | perror("perf_event_open() failed"); | ||
210 | |||
211 | return fd; | ||
212 | } | ||
213 | |||
214 | int perf_event_enable(int fd) | ||
215 | { | ||
216 | if (ioctl(fd, PERF_EVENT_IOC_ENABLE, PERF_IOC_FLAG_GROUP) == -1) { | ||
217 | perror("error while enabling perf events"); | ||
218 | return -1; | ||
219 | } | ||
220 | |||
221 | return 0; | ||
222 | } | ||
223 | |||
224 | int perf_event_disable(int fd) | ||
225 | { | ||
226 | if (ioctl(fd, PERF_EVENT_IOC_DISABLE, PERF_IOC_FLAG_GROUP) == -1) { | ||
227 | perror("error disabling perf events"); | ||
228 | return -1; | ||
229 | } | ||
230 | |||
231 | return 0; | ||
232 | } | ||
233 | |||
234 | int perf_event_reset(int fd) | ||
235 | { | ||
236 | if (ioctl(fd, PERF_EVENT_IOC_RESET, PERF_IOC_FLAG_GROUP) == -1) { | ||
237 | perror("error resetting perf events"); | ||
238 | return -1; | ||
239 | } | ||
240 | |||
241 | return 0; | ||
242 | } | ||
243 | |||
244 | static void sigill_handler(int signr, siginfo_t *info, void *unused) | ||
245 | { | ||
246 | static int warned = 0; | ||
247 | ucontext_t *ctx = (ucontext_t *)unused; | ||
248 | unsigned long *pc = &UCONTEXT_NIA(ctx); | ||
249 | |||
250 | if (*pc == (unsigned long)&dscr_insn) { | ||
251 | if (!warned++) | ||
252 | printf("WARNING: Skipping over dscr setup. Consider running 'ppc64_cpu --dscr=1' manually.\n"); | ||
253 | *pc += 4; | ||
254 | } else { | ||
255 | printf("SIGILL at %p\n", pc); | ||
256 | abort(); | ||
257 | } | ||
258 | } | ||
259 | |||
260 | void set_dscr(unsigned long val) | ||
261 | { | ||
262 | static int init = 0; | ||
263 | struct sigaction sa; | ||
264 | |||
265 | if (!init) { | ||
266 | memset(&sa, 0, sizeof(sa)); | ||
267 | sa.sa_sigaction = sigill_handler; | ||
268 | sa.sa_flags = SA_SIGINFO; | ||
269 | if (sigaction(SIGILL, &sa, NULL)) | ||
270 | perror("sigill_handler"); | ||
271 | init = 1; | ||
272 | } | ||
273 | |||
274 | asm volatile("dscr_insn: mtspr %1,%0" : : "r" (val), "i" (SPRN_DSCR)); | ||
275 | } | ||