Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

+164 -6
+4
arch/powerpc/include/asm/module.h
··· 14 14 #include <asm-generic/module.h> 15 15 16 16 17 + #ifdef CC_USING_MPROFILE_KERNEL 18 + #define MODULE_ARCH_VERMAGIC "mprofile-kernel" 19 + #endif 20 + 17 21 #ifndef __powerpc64__ 18 22 /* 19 23 * Thanks to Paul M for explaining this.
+12
arch/powerpc/include/asm/page.h
··· 132 132 #define virt_to_pfn(kaddr) (__pa(kaddr) >> PAGE_SHIFT) 133 133 #define virt_to_page(kaddr) pfn_to_page(virt_to_pfn(kaddr)) 134 134 #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 135 146 #define virt_addr_valid(kaddr) pfn_valid(virt_to_pfn(kaddr)) 147 + #endif 136 148 137 149 /* 138 150 * On Book-E parts we need __va to parse the device tree and we can't
+1 -1
arch/powerpc/kernel/idle_book3s.S
··· 416 416 * which needs to be restored from the stack. 417 417 */ 418 418 li r3, 1 419 - stb r0,PACA_NAPSTATELOST(r13) 419 + stb r3,PACA_NAPSTATELOST(r13) 420 420 blr 421 421 422 422 /*
+2 -1
arch/powerpc/kernel/kprobes.c
··· 305 305 save_previous_kprobe(kcb); 306 306 set_current_kprobe(p, regs, kcb); 307 307 kprobes_inc_nmissed_count(p); 308 - prepare_singlestep(p, regs); 309 308 kcb->kprobe_status = KPROBE_REENTER; 310 309 if (p->ainsn.boostable >= 0) { 311 310 ret = try_to_emulate(p, regs); 312 311 313 312 if (ret > 0) { 314 313 restore_previous_kprobe(kcb); 314 + preempt_enable_no_resched(); 315 315 return 1; 316 316 } 317 317 } 318 + prepare_singlestep(p, regs); 318 319 return 1; 319 320 } else { 320 321 if (*addr != BREAKPOINT_INSTRUCTION) {
+19
arch/powerpc/kernel/process.c
··· 864 864 if (!MSR_TM_SUSPENDED(mfmsr())) 865 865 return; 866 866 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 + 867 886 giveup_all(container_of(thr, struct task_struct, thread)); 868 887 869 888 tm_reclaim(thr, thr->ckpt_regs.msr, cause);
+4 -3
arch/powerpc/mm/dump_linuxpagetables.c
··· 16 16 */ 17 17 #include <linux/debugfs.h> 18 18 #include <linux/fs.h> 19 + #include <linux/hugetlb.h> 19 20 #include <linux/io.h> 20 21 #include <linux/mm.h> 21 22 #include <linux/sched.h> ··· 392 391 393 392 for (i = 0; i < PTRS_PER_PMD; i++, pmd++) { 394 393 addr = start + i * PMD_SIZE; 395 - if (!pmd_none(*pmd)) 394 + if (!pmd_none(*pmd) && !pmd_huge(*pmd)) 396 395 /* pmd exists */ 397 396 walk_pte(st, pmd, addr); 398 397 else ··· 408 407 409 408 for (i = 0; i < PTRS_PER_PUD; i++, pud++) { 410 409 addr = start + i * PUD_SIZE; 411 - if (!pud_none(*pud)) 410 + if (!pud_none(*pud) && !pud_huge(*pud)) 412 411 /* pud exists */ 413 412 walk_pmd(st, pud, addr); 414 413 else ··· 428 427 */ 429 428 for (i = 0; i < PTRS_PER_PGD; i++, pgd++) { 430 429 addr = KERN_VIRT_START + i * PGDIR_SIZE; 431 - if (!pgd_none(*pgd)) 430 + if (!pgd_none(*pgd) && !pgd_huge(*pgd)) 432 431 /* pgd exists */ 433 432 walk_pud(st, pgd, addr); 434 433 else
+1
tools/testing/selftests/powerpc/tm/.gitignore
··· 11 11 tm-signal-context-chk-gpr 12 12 tm-signal-context-chk-vmx 13 13 tm-signal-context-chk-vsx 14 + tm-vmx-unavail
+3 -1
tools/testing/selftests/powerpc/tm/Makefile
··· 2 2 tm-signal-context-chk-vmx tm-signal-context-chk-vsx 3 3 4 4 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) 6 7 7 8 include ../../lib.mk 8 9 ··· 14 13 $(OUTPUT)/tm-syscall: tm-syscall-asm.S 15 14 $(OUTPUT)/tm-syscall: CFLAGS += -I../../../../../usr/include 16 15 $(OUTPUT)/tm-tmspr: CFLAGS += -pthread 16 + $(OUTPUT)/tm-vmx-unavail: CFLAGS += -pthread -m64 17 17 18 18 SIGNAL_CONTEXT_CHK_TESTS := $(patsubst %,$(OUTPUT)/%,$(SIGNAL_CONTEXT_CHK_TESTS)) 19 19 $(SIGNAL_CONTEXT_CHK_TESTS): tm-signal.S
+118
tools/testing/selftests/powerpc/tm/tm-vmx-unavail.c
··· 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 + }