History

Merge tag 'powerpc-4.12-3' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux

Pull powerpc fixes from Michael Ellerman: "The headliner is a fix for FP/VMX register corruption when using transactional memory, and a new selftest to go with it. Then there's the virt_addr_valid() fix, currently HARDENDED_USERCOPY is tripping on that causing some machines to crash. A few other fairly minor fixes for long tail things, and a couple of fixes for code we just merged. Thanks to: Breno Leitao, Gautham Shenoy, Michael Neuling, Naveen Rao. Nicholas Piggin, Paul Mackerras" * tag 'powerpc-4.12-3' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux: powerpc/mm: Fix virt_addr_valid() etc. on 64-bit hash powerpc/mm: Fix crash in page table dump with huge pages powerpc/kprobes: Fix handling of instruction emulation on probe re-entry powerpc/powernv: Set NAPSTATELOST after recovering paca on P9 DD1 selftests/powerpc: Test TM and VMX register state powerpc/tm: Fix FP and VMX register corruption powerpc/modules: If mprofile-kernel is enabled add it to vermagic

Linus Torvalds committed 9 years ago

Commit e5a489a2 parents 8b4822d e41e53c9 files · +164 −6Browse files

Unified · Split

9 files
  1. arch/powerpc/include/asm/module.h +4 −0
  2. arch/powerpc/include/asm/page.h +12 −0
  3. arch/powerpc/kernel/idle_book3s.S +1 −1
  4. arch/powerpc/kernel/kprobes.c +2 −1
  5. arch/powerpc/kernel/process.c +19 −0
  6. arch/powerpc/mm/dump_linuxpagetables.c +4 −3
  7. tools/testing/selftests/powerpc/tm/.gitignore +1 −0
  8. tools/testing/selftests/powerpc/tm/Makefile +3 −1
  9. tools/testing/selftests/powerpc/tm/tm-vmx-unavail.c +118 −0
arch/powerpc/include/asm/module.h+4−0
@@ -14,6 +14,10 @@ · 13 unmodified lines
1414 #include <asm-generic/module.h>
1515
1616
17+#ifdef CC_USING_MPROFILE_KERNEL
18+#define MODULE_ARCH_VERMAGIC "mprofile-kernel"
19+#endif
20+
1721 #ifndef __powerpc64__
1822 /*
1923 * Thanks to Paul M for explaining this.
arch/powerpc/include/asm/page.h+12−0
@@ -132,7 +132,19 @@ extern long long virt_phys_offset; · 131 unmodified lines
132132 #define virt_to_pfn(kaddr) (__pa(kaddr) >> PAGE_SHIFT)
133133 #define virt_to_page(kaddr) pfn_to_page(virt_to_pfn(kaddr))
134134 #define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT)
135+
136+#ifdef CONFIG_PPC_BOOK3S_64
137+/*
138+ * On hash the vmalloc and other regions alias to the kernel region when passed
139+ * through __pa(), which virt_to_pfn() uses. That means virt_addr_valid() can
140+ * return true for some vmalloc addresses, which is incorrect. So explicitly
141+ * check that the address is in the kernel region.
142+ */
143+#define virt_addr_valid(kaddr) (REGION_ID(kaddr) == KERNEL_REGION_ID && \
144+ pfn_valid(virt_to_pfn(kaddr)))
145+#else
135146 #define virt_addr_valid(kaddr) pfn_valid(virt_to_pfn(kaddr))
147+#endif
136148
137149 /*
138150 * On Book-E parts we need __va to parse the device tree and we can't
arch/powerpc/kernel/idle_book3s.S+1−1
@@ -416,7 +416,7 @@ power9_dd1_recover_paca: · 415 unmodified lines
416416 * which needs to be restored from the stack.
417417 */
418418 li r3, 1
419− stb r0,PACA_NAPSTATELOST(r13)
419+ stb r3,PACA_NAPSTATELOST(r13)
420420 blr
421421
422422 /*
arch/powerpc/kernel/kprobes.c+2−1
@@ -305,16 +305,17 @@ int kprobe_handler(struct pt_regs *regs) · 304 unmodified lines
305305 save_previous_kprobe(kcb);
306306 set_current_kprobe(p, regs, kcb);
307307 kprobes_inc_nmissed_count(p);
308− prepare_singlestep(p, regs);
309308 kcb->kprobe_status = KPROBE_REENTER;
310309 if (p->ainsn.boostable >= 0) {
311310 ret = try_to_emulate(p, regs);
312311
313312 if (ret > 0) {
314313 restore_previous_kprobe(kcb);
314+ preempt_enable_no_resched();
315315 return 1;
316316 }
317317 }
318+ prepare_singlestep(p, regs);
318319 return 1;
319320 } else {
320321 if (*addr != BREAKPOINT_INSTRUCTION) {
arch/powerpc/kernel/process.c+19−0
@@ -864,6 +864,25 @@ static void tm_reclaim_thread(struct thread_struct *thr, · 863 unmodified lines
864864 if (!MSR_TM_SUSPENDED(mfmsr()))
865865 return;
866866
867+ /*
868+ * If we are in a transaction and FP is off then we can't have
869+ * used FP inside that transaction. Hence the checkpointed
870+ * state is the same as the live state. We need to copy the
871+ * live state to the checkpointed state so that when the
872+ * transaction is restored, the checkpointed state is correct
873+ * and the aborted transaction sees the correct state. We use
874+ * ckpt_regs.msr here as that's what tm_reclaim will use to
875+ * determine if it's going to write the checkpointed state or
876+ * not. So either this will write the checkpointed registers,
877+ * or reclaim will. Similarly for VMX.
878+ */
879+ if ((thr->ckpt_regs.msr & MSR_FP) == 0)
880+ memcpy(&thr->ckfp_state, &thr->fp_state,
881+ sizeof(struct thread_fp_state));
882+ if ((thr->ckpt_regs.msr & MSR_VEC) == 0)
883+ memcpy(&thr->ckvr_state, &thr->vr_state,
884+ sizeof(struct thread_vr_state));
885+
867886 giveup_all(container_of(thr, struct task_struct, thread));
868887
869888 tm_reclaim(thr, thr->ckpt_regs.msr, cause);
arch/powerpc/mm/dump_linuxpagetables.c+4−3
@@ -16,6 +16,7 @@ · 15 unmodified lines
1616 */
1717 #include <linux/debugfs.h>
1818 #include <linux/fs.h>
19+#include <linux/hugetlb.h>
1920 #include <linux/io.h>
2021 #include <linux/mm.h>
2122 #include <linux/sched.h>
@@ -391,7 +392,7 @@ static void walk_pmd(struct pg_state *st, pud_t *pud, unsigned long start) · 369 unmodified lines
391392
392393 for (i = 0; i < PTRS_PER_PMD; i++, pmd++) {
393394 addr = start + i * PMD_SIZE;
394− if (!pmd_none(*pmd))
395+ if (!pmd_none(*pmd) && !pmd_huge(*pmd))
395396 /* pmd exists */
396397 walk_pte(st, pmd, addr);
397398 else
@@ -407,7 +408,7 @@ static void walk_pud(struct pg_state *st, pgd_t *pgd, unsigned long start) · 9 unmodified lines
407408
408409 for (i = 0; i < PTRS_PER_PUD; i++, pud++) {
409410 addr = start + i * PUD_SIZE;
410− if (!pud_none(*pud))
411+ if (!pud_none(*pud) && !pud_huge(*pud))
411412 /* pud exists */
412413 walk_pmd(st, pud, addr);
413414 else
@@ -427,7 +428,7 @@ static void walk_pagetables(struct pg_state *st) · 13 unmodified lines
427428 */
428429 for (i = 0; i < PTRS_PER_PGD; i++, pgd++) {
429430 addr = KERN_VIRT_START + i * PGDIR_SIZE;
430− if (!pgd_none(*pgd))
431+ if (!pgd_none(*pgd) && !pgd_huge(*pgd))
431432 /* pgd exists */
432433 walk_pud(st, pgd, addr);
433434 else
tools/testing/selftests/powerpc/tm/.gitignore+1−0
@@ -11,3 +11,4 @@ tm-signal-context-chk-fpu · 10 unmodified lines
1111 tm-signal-context-chk-gpr
1212 tm-signal-context-chk-vmx
1313 tm-signal-context-chk-vsx
14+tm-vmx-unavail
tools/testing/selftests/powerpc/tm/Makefile+3−1
@@ -2,7 +2,8 @@ SIGNAL_CONTEXT_CHK_TESTS := tm-signal-context-chk-gpr tm-signal-context-chk-fpu · 1 unmodified line
22 tm-signal-context-chk-vmx tm-signal-context-chk-vsx
33
44 TEST_GEN_PROGS := tm-resched-dscr tm-syscall tm-signal-msr-resv tm-signal-stack \
5− tm-vmxcopy tm-fork tm-tar tm-tmspr $(SIGNAL_CONTEXT_CHK_TESTS)
5+ tm-vmxcopy tm-fork tm-tar tm-tmspr tm-vmx-unavail \
6+ $(SIGNAL_CONTEXT_CHK_TESTS)
67
78 include ../../lib.mk
89
@@ -13,6 +14,7 @@ CFLAGS += -mhtm · 4 unmodified lines
1314 $(OUTPUT)/tm-syscall: tm-syscall-asm.S
1415 $(OUTPUT)/tm-syscall: CFLAGS += -I../../../../../usr/include
1516 $(OUTPUT)/tm-tmspr: CFLAGS += -pthread
17+$(OUTPUT)/tm-vmx-unavail: CFLAGS += -pthread -m64
1618
1719 SIGNAL_CONTEXT_CHK_TESTS := $(patsubst %,$(OUTPUT)/%,$(SIGNAL_CONTEXT_CHK_TESTS))
1820 $(SIGNAL_CONTEXT_CHK_TESTS): tm-signal.S
tools/testing/selftests/powerpc/tm/tm-vmx-unavail.c+118−0
@@ -0,0 +1,118 @@
1+/*
2+ * Copyright 2017, Michael Neuling, IBM Corp.
3+ * Licensed under GPLv2.
4+ * Original: Breno Leitao <brenohl@br.ibm.com> &
5+ * Gustavo Bueno Romero <gromero@br.ibm.com>
6+ * Edited: Michael Neuling
7+ *
8+ * Force VMX unavailable during a transaction and see if it corrupts
9+ * the checkpointed VMX register state after the abort.
10+ */
11+
12+#include <inttypes.h>
13+#include <htmintrin.h>
14+#include <string.h>
15+#include <stdlib.h>
16+#include <stdio.h>
17+#include <pthread.h>
18+#include <sys/mman.h>
19+#include <unistd.h>
20+#include <pthread.h>
21+
22+#include "tm.h"
23+#include "utils.h"
24+
25+int passed;
26+
27+void *worker(void *unused)
28+{
29+ __int128 vmx0;
30+ uint64_t texasr;
31+
32+ asm goto (
33+ "li 3, 1;" /* Stick non-zero value in VMX0 */
34+ "std 3, 0(%[vmx0_ptr]);"
35+ "lvx 0, 0, %[vmx0_ptr];"
36+
37+ /* Wait here a bit so we get scheduled out 255 times */
38+ "lis 3, 0x3fff;"
39+ "1: ;"
40+ "addi 3, 3, -1;"
41+ "cmpdi 3, 0;"
42+ "bne 1b;"
43+
44+ /* Kernel will hopefully turn VMX off now */
45+
46+ "tbegin. ;"
47+ "beq failure;"
48+
49+ /* Cause VMX unavail. Any VMX instruction */
50+ "vaddcuw 0,0,0;"
51+
52+ "tend. ;"
53+ "b %l[success];"
54+
55+ /* Check VMX0 sanity after abort */
56+ "failure: ;"
57+ "lvx 1, 0, %[vmx0_ptr];"
58+ "vcmpequb. 2, 0, 1;"
59+ "bc 4, 24, %l[value_mismatch];"
60+ "b %l[value_match];"
61+ :
62+ : [vmx0_ptr] "r"(&vmx0)
63+ : "r3"
64+ : success, value_match, value_mismatch
65+ );
66+
67+ /* HTM aborted and VMX0 is corrupted */
68+value_mismatch:
69+ texasr = __builtin_get_texasr();
70+
71+ printf("\n\n==============\n\n");
72+ printf("Failure with error: %lx\n", _TEXASR_FAILURE_CODE(texasr));
73+ printf("Summary error : %lx\n", _TEXASR_FAILURE_SUMMARY(texasr));
74+ printf("TFIAR exact : %lx\n\n", _TEXASR_TFIAR_EXACT(texasr));
75+
76+ passed = 0;
77+ return NULL;
78+
79+ /* HTM aborted but VMX0 is correct */
80+value_match:
81+// printf("!");
82+ return NULL;
83+
84+success:
85+// printf(".");
86+ return NULL;
87+}
88+
89+int tm_vmx_unavail_test()
90+{
91+ int threads;
92+ pthread_t *thread;
93+
94+ SKIP_IF(!have_htm());
95+
96+ passed = 1;
97+
98+ threads = sysconf(_SC_NPROCESSORS_ONLN) * 4;
99+ thread = malloc(sizeof(pthread_t)*threads);
100+ if (!thread)
101+ return EXIT_FAILURE;
102+
103+ for (uint64_t i = 0; i < threads; i++)
104+ pthread_create(&thread[i], NULL, &worker, NULL);
105+
106+ for (uint64_t i = 0; i < threads; i++)
107+ pthread_join(thread[i], NULL);
108+
109+ free(thread);
110+
111+ return passed ? EXIT_SUCCESS : EXIT_FAILURE;
112+}
113+
114+
115+int main(int argc, char **argv)
116+{
117+ return test_harness(tm_vmx_unavail_test, "tm_vmx_unavail_test");
118+}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t