[PATCH 3/3] powerpc/sstep: Always test lmw and stmw
Load Multiple Word (lmw) and Store Multiple Word (stmw) will raise an Alignment Exception: - Little Endian mode: always - Big Endian mode: address not word aligned These conditions do not depend on cache inhibited memory. Test the alignment handler emulation of these instructions regardless of if there is cache inhibited memory available or not. Signed-off-by: Jordan Niethe --- .../powerpc/alignment/alignment_handler.c | 96 ++- 1 file changed, 94 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/powerpc/alignment/alignment_handler.c b/tools/testing/selftests/powerpc/alignment/alignment_handler.c index f5eb5b85a2cf..c3003f95e043 100644 --- a/tools/testing/selftests/powerpc/alignment/alignment_handler.c +++ b/tools/testing/selftests/powerpc/alignment/alignment_handler.c @@ -45,6 +45,7 @@ #include #include #include +#include #include "utils.h" #include "instructions.h" @@ -434,7 +435,6 @@ int test_alignment_handler_integer(void) LOAD_DFORM_TEST(ldu); LOAD_XFORM_TEST(ldx); LOAD_XFORM_TEST(ldux); - LOAD_DFORM_TEST(lmw); STORE_DFORM_TEST(stb); STORE_XFORM_TEST(stbx); STORE_DFORM_TEST(stbu); @@ -453,7 +453,6 @@ int test_alignment_handler_integer(void) STORE_XFORM_TEST(stdx); STORE_DFORM_TEST(stdu); STORE_XFORM_TEST(stdux); - STORE_DFORM_TEST(stmw); return rc; } @@ -599,6 +598,97 @@ int test_alignment_handler_fp_prefix(void) return rc; } +int test_alignment_handler_multiple(void) +{ + int offset, width, r, rc = 0; + void *src1, *dst1, *src2, *dst2; + + rc = posix_memalign(, bufsize, bufsize); + if (rc) { + printf("\n"); + return rc; + } + + rc = posix_memalign(, bufsize, bufsize); + if (rc) { + printf("\n"); + free(src1); + return rc; + } + + src2 = malloc(bufsize); + if (!src2) { + printf("\n"); + free(src1); + free(dst1); + return -ENOMEM; + } + + dst2 = malloc(bufsize); + if (!dst2) { + printf("\n"); + free(src1); + free(dst1); + free(src2); + return -ENOMEM; + } + + /* lmw */ + width = 4; + printf("\tDoing lmw:\t"); + for (offset = 0; offset < width; offset++) { + preload_data(src1, offset, width); + preload_data(src2, offset, width); + + asm volatile("lmw 31, 0(%0) ; std 31, 0(%1)" +:: "r"(src1 + offset), "r"(dst1 + offset), "r"(0) +: "memory", "r31"); + + memcpy(dst2 + offset, src1 + offset, width); + + r = test_memcmp(dst1, dst2, width, offset, "test_lmw"); + if (r && !debug) { + printf("FAILED: Wrong Data\n"); + break; + } + } + + if (!r) + printf("PASSED\n"); + else + rc |= 1; + + /* stmw */ + width = 4; + printf("\tDoing stmw:\t"); + for (offset = 0; offset < width; offset++) { + preload_data(src1, offset, width); + preload_data(src2, offset, width); + + asm volatile("ld 31, 0(%0) ; stmw 31, 0(%1)" +:: "r"(src1 + offset), "r"(dst1 + offset), "r"(0) +: "memory", "r31"); + + memcpy(dst2 + offset, src1 + offset, width); + + r = test_memcmp(dst1, dst2, width, offset, "test_stmw"); + if (r && !debug) { + printf("FAILED: Wrong Data\n"); + break; + } + } + if (!r) + printf("PASSED\n"); + else + rc |= 1; + + free(src1); + free(src2); + free(dst1); + free(dst2); + return rc; +} + void usage(char *prog) { printf("Usage: %s [options] [path [offset]]\n", prog); @@ -673,5 +763,7 @@ int main(int argc, char *argv[]) "test_alignment_handler_fp_206"); rc |= test_harness(test_alignment_handler_fp_prefix, "test_alignment_handler_fp_prefix"); + rc |= test_harness(test_alignment_handler_multiple, + "test_alignment_handler_multiple"); return rc; } -- 2.25.1
[PATCH 2/3] selftests/powerpc: Suggest memtrace instead of /dev/mem for ci memory
The suggested alternative for getting cache-inhibited memory with 'mem=' and /dev/mem is pretty hacky. Also, PAPR guests do not allow system memory to be mapped cache-inhibited so despite /dev/mem being available this will not work which can cause confusion. Instead recommend using the memtrace buffers. memtrace is only available on powernv so there will not be any chance of trying to do this in a guest. Signed-off-by: Jordan Niethe --- .../selftests/powerpc/alignment/alignment_handler.c | 11 +-- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/tools/testing/selftests/powerpc/alignment/alignment_handler.c b/tools/testing/selftests/powerpc/alignment/alignment_handler.c index cb53a8b777e6..f5eb5b85a2cf 100644 --- a/tools/testing/selftests/powerpc/alignment/alignment_handler.c +++ b/tools/testing/selftests/powerpc/alignment/alignment_handler.c @@ -10,16 +10,7 @@ * * We create two sets of source and destination buffers, one in regular memory, * the other cache-inhibited (by default we use /dev/fb0 for this, but an - * alterative path for cache-inhibited memory may be provided). - * - * One way to get cache-inhibited memory is to use the "mem" kernel parameter - * to limit the kernel to less memory than actually exists. Addresses above - * the limit may still be accessed but will be treated as cache-inhibited. For - * example, if there is actually 4GB of memory and the parameter "mem=3GB" is - * used, memory from address 0xC000 onwards is treated as cache-inhibited. - * To access this region /dev/mem is used. The kernel should be configured - * without CONFIG_STRICT_DEVMEM. In this case use: - * ./alignment_handler /dev/mem 0xc000 + * alterative path for cache-inhibited memory may be provided, e.g. memtrace). * * We initialise the source buffers, then use whichever set of load/store * instructions is under test to copy bytes from the source buffers to the -- 2.25.1
[PATCH 1/3] powernv/memtrace: Allow mmaping trace buffers
Let the memory removed from the linear mapping to be used for the trace buffers be mmaped. This is a useful way of providing cache-inhibited memory for the alignment_handler selftest. Signed-off-by: Jordan Niethe --- arch/powerpc/platforms/powernv/memtrace.c | 18 +- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/platforms/powernv/memtrace.c b/arch/powerpc/platforms/powernv/memtrace.c index 5fc9408bb0b3..8a1df39305e9 100644 --- a/arch/powerpc/platforms/powernv/memtrace.c +++ b/arch/powerpc/platforms/powernv/memtrace.c @@ -45,10 +45,26 @@ static ssize_t memtrace_read(struct file *filp, char __user *ubuf, return simple_read_from_buffer(ubuf, count, ppos, ent->mem, ent->size); } +int memtrace_mmap(struct file *filp, struct vm_area_struct *vma) +{ + struct memtrace_entry *ent = filp->private_data; + + if (ent->size < vma->vm_end - vma->vm_start) + return -EINVAL; + + if (vma->vm_pgoff << PAGE_SHIFT >= ent->size) + return -EINVAL; + + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + return remap_pfn_range(vma, vma->vm_start, PHYS_PFN(ent->start) + vma->vm_pgoff, + vma->vm_end - vma->vm_start, vma->vm_page_prot); +} + static const struct file_operations memtrace_fops = { .llseek = default_llseek, .read = memtrace_read, .open = simple_open, + .mmap = memtrace_mmap, }; static void memtrace_clear_range(unsigned long start_pfn, @@ -158,7 +174,7 @@ static int memtrace_init_debugfs(void) dir = debugfs_create_dir(ent->name, memtrace_debugfs_dir); ent->dir = dir; - debugfs_create_file("trace", 0400, dir, ent, _fops); + debugfs_create_file_unsafe("trace", 0600, dir, ent, _fops); debugfs_create_x64("start", 0400, dir, >start); debugfs_create_x64("size", 0400, dir, >size); } -- 2.25.1
[PATCH] powerpc/sstep: Fix VSX instruction emulation
Commit af99da74333b ("powerpc/sstep: Support VSX vector paired storage access instructions") added loading and storing 32 word long data into adjacent VSRs. However the calculation used to determine if two VSRs needed to be loaded/stored inadvertently prevented the load/storing taking place for instructions with a data length less than 16 words. This causes the emulation to not function correctly, which can be seen by the alignment_handler selftest: $ ./alignment_handler [snip] test: test_alignment_handler_vsx_207 tags: git_version:powerpc-5.12-1-0-g82d2c16b350f VSX: 2.07B Doing lxsspx: PASSED Doing lxsiwax: FAILED: Wrong Data Doing lxsiwzx: PASSED Doing stxsspx: PASSED Doing stxsiwx: PASSED failure: test_alignment_handler_vsx_207 test: test_alignment_handler_vsx_300 tags: git_version:powerpc-5.12-1-0-g82d2c16b350f VSX: 3.00B Doing lxsd: PASSED Doing lxsibzx: PASSED Doing lxsihzx: PASSED Doing lxssp:FAILED: Wrong Data Doing lxv: PASSED Doing lxvb16x: PASSED Doing lxvh8x: PASSED Doing lxvx: PASSED Doing lxvwsx: FAILED: Wrong Data Doing lxvl: PASSED Doing lxvll:PASSED Doing stxsd:PASSED Doing stxsibx: PASSED Doing stxsihx: PASSED Doing stxssp: PASSED Doing stxv: PASSED Doing stxvb16x: PASSED Doing stxvh8x: PASSED Doing stxvx:PASSED Doing stxvl:PASSED Doing stxvll: PASSED failure: test_alignment_handler_vsx_300 [snip] Fix this by making sure all VSX instruction emulation correctly load/store from the VSRs. Fixes: af99da74333b ("powerpc/sstep: Support VSX vector paired storage access instructions") Signed-off-by: Jordan Niethe --- arch/powerpc/lib/sstep.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c index 683f7c20f74b..3953e63bbba5 100644 --- a/arch/powerpc/lib/sstep.c +++ b/arch/powerpc/lib/sstep.c @@ -902,7 +902,7 @@ static nokprobe_inline int do_vsx_load(struct instruction_op *op, if (!address_ok(regs, ea, size) || copy_mem_in(mem, ea, size, regs)) return -EFAULT; - nr_vsx_regs = size / sizeof(__vector128); + nr_vsx_regs = max(1ul, size / sizeof(__vector128)); emulate_vsx_load(op, buf, mem, cross_endian); preempt_disable(); if (reg < 32) { @@ -949,7 +949,7 @@ static nokprobe_inline int do_vsx_store(struct instruction_op *op, if (!address_ok(regs, ea, size)) return -EFAULT; - nr_vsx_regs = size / sizeof(__vector128); + nr_vsx_regs = max(1ul, size / sizeof(__vector128)); preempt_disable(); if (reg < 32) { /* FP regs + extensions */ -- 2.25.1
[PATCH v3 2/2] selftests/powerpc: Test for spurious kernel memory faults on radix
Previously when mapping kernel memory on radix, no ptesync was included which would periodically lead to unhandled spurious faults. Mapping kernel memory is used when code patching with Strict RWX enabled. As suggested by Chris Riedl, turning ftrace on and off does a large amount of code patching so is a convenient way to see this kind of fault. Add a selftest to try and trigger this kind of a spurious fault. It tests for 30 seconds which is usually long enough for the issue to show up. Signed-off-by: Jordan Niethe --- v3: New to series --- tools/testing/selftests/powerpc/mm/Makefile | 1 + .../selftests/powerpc/mm/spurious_fault.sh| 49 +++ 2 files changed, 50 insertions(+) create mode 100755 tools/testing/selftests/powerpc/mm/spurious_fault.sh diff --git a/tools/testing/selftests/powerpc/mm/Makefile b/tools/testing/selftests/powerpc/mm/Makefile index defe488d6bf1..56c2896bed53 100644 --- a/tools/testing/selftests/powerpc/mm/Makefile +++ b/tools/testing/selftests/powerpc/mm/Makefile @@ -5,6 +5,7 @@ noarg: TEST_GEN_PROGS := hugetlb_vs_thp_test subpage_prot prot_sao segv_errors wild_bctr \ large_vm_fork_separation bad_accesses pkey_exec_prot \ pkey_siginfo stack_expansion_signal stack_expansion_ldst +TEST_PROGS := spurious_fault.sh TEST_GEN_PROGS_EXTENDED := tlbie_test TEST_GEN_FILES := tempfile diff --git a/tools/testing/selftests/powerpc/mm/spurious_fault.sh b/tools/testing/selftests/powerpc/mm/spurious_fault.sh new file mode 100755 index ..e454509659f6 --- /dev/null +++ b/tools/testing/selftests/powerpc/mm/spurious_fault.sh @@ -0,0 +1,49 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0-or-later + +TIMEOUT=30 + +DEBUFS_DIR=`cat /proc/mounts | grep debugfs | awk '{print $2}'` +if [ ! -e "$DEBUFS_DIR" ] +then + echo "debugfs not found, skipping" 1>&2 + exit 4 +fi + +if [ ! -e "$DEBUFS_DIR/tracing/current_tracer" ] +then + echo "Tracing files not found, skipping" 1>&2 + exit 4 +fi + + +echo "Testing for spurious faults when mapping kernel memory..." + +if grep -q "FUNCTION TRACING IS CORRUPTED" "$DEBUFS_DIR/tracing/trace" +then + echo "FAILED: Ftrace already dead. Probably due to a spurious fault" 1>&2 + exit 1 +fi + +dmesg -C +START_TIME=`date +%s` +END_TIME=`expr $START_TIME + $TIMEOUT` +while [ `date +%s` -lt $END_TIME ] +do + echo function > $DEBUFS_DIR/tracing/current_tracer + echo nop > $DEBUFS_DIR/tracing/current_tracer + if dmesg | grep -q 'ftrace bug' + then + break + fi +done + +echo nop > $DEBUFS_DIR/tracing/current_tracer +if dmesg | grep -q 'ftrace bug' +then + echo "FAILED: Mapping kernel memory causes spurious faults" 1>&2 + exit 1 +else + echo "OK: Mapping kernel memory does not cause spurious faults" + exit 0 +fi -- 2.25.1
[PATCH v3 1/2] powerpc/64s: Fix pte update for kernel memory on radix
+0x44/0xc0 [ 146.669451][ T809] [c4c8bb00] [c024dc88] ftrace_startup+0xf8/0x1c0 [ 146.669461][ T809] [c4c8bb40] [c024dd9c] register_ftrace_function+0x4c/0xc0 [ 146.669472][ T809] [c4c8bb70] [c026e750] function_trace_init+0x80/0xb0 [ 146.669484][ T809] [c4c8bba0] [c0266b84] tracing_set_tracer+0x2a4/0x4f0 [ 146.669495][ T809] [c4c8bc70] [c0266ea4] tracing_set_trace_write+0xd4/0x130 [ 146.669506][ T809] [c4c8bd20] [c0422790] vfs_write+0xf0/0x330 [ 146.669518][ T809] [c4c8bd70] [c0422bb4] ksys_write+0x84/0x140 [ 146.669529][ T809] [c4c8bdc0] [c003499c] system_call_exception+0x14c/0x230 [ 146.669540][ T809] [c4c8be20] [c000d860] system_call_common+0xf0/0x27c [ 146.669549][ T809] Instruction dump: [ 146.669558][ T809] 4814 3c62fe88 38631718 4bf5a941 6000 7fc3f378 4bff877d 7c641b78 [ 146.669598][ T809] 3c62fe88 38631730 4bf5a925 6000 <0fe0> 38210090 3d22fd90 3901 [ 146.669638][ T809] ---[ end trace 5ea7076ea28c0fbd ]--- To fix this when updating kernel memory ptes using ptesync. Fixes: f1cb8f9beba8 ("powerpc/64s/radix: avoid ptesync after set_pte and ptep_set_access_flags") Reviewed-by: Nicholas Piggin Signed-off-by: Jordan Niethe --- v2: Only ptesync is needed v3: Fix Fixes tag --- arch/powerpc/include/asm/book3s/64/radix.h | 6 -- arch/powerpc/mm/book3s64/radix_pgtable.c | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/arch/powerpc/include/asm/book3s/64/radix.h b/arch/powerpc/include/asm/book3s/64/radix.h index c7813dc628fc..59cab558e2f0 100644 --- a/arch/powerpc/include/asm/book3s/64/radix.h +++ b/arch/powerpc/include/asm/book3s/64/radix.h @@ -222,8 +222,10 @@ static inline void radix__set_pte_at(struct mm_struct *mm, unsigned long addr, * from ptesync, it should probably go into update_mmu_cache, rather * than set_pte_at (which is used to set ptes unrelated to faults). * -* Spurious faults to vmalloc region are not tolerated, so there is -* a ptesync in flush_cache_vmap. +* Spurious faults from the kernel memory are not tolerated, so there +* is a ptesync in flush_cache_vmap, and __map_kernel_page() follows +* the pte update sequence from ISA Book III 6.10 Translation Table +* Update Synchronization Requirements. */ } diff --git a/arch/powerpc/mm/book3s64/radix_pgtable.c b/arch/powerpc/mm/book3s64/radix_pgtable.c index 3adcf730f478..1d5eec847b88 100644 --- a/arch/powerpc/mm/book3s64/radix_pgtable.c +++ b/arch/powerpc/mm/book3s64/radix_pgtable.c @@ -108,7 +108,7 @@ static int early_map_kernel_page(unsigned long ea, unsigned long pa, set_the_pte: set_pte_at(_mm, ea, ptep, pfn_pte(pfn, flags)); - smp_wmb(); + asm volatile("ptesync": : :"memory"); return 0; } @@ -168,7 +168,7 @@ static int __map_kernel_page(unsigned long ea, unsigned long pa, set_the_pte: set_pte_at(_mm, ea, ptep, pfn_pte(pfn, flags)); - smp_wmb(); + asm volatile("ptesync": : :"memory"); return 0; } -- 2.25.1
Re: [PATCH v2] powerpc/64s: Fix pte update for kernel memory on radix
000 > > [ 146.669208][ T809] GPR16: 23ec37c5 > > 0008 > > [ 146.669208][ T809] GPR20: c4c8bc90 c27a2d20 > > c4c8bcd0 c2612fe8 > > [ 146.669208][ T809] GPR24: 0038 0030 > > 0028 0020 > > [ 146.669208][ T809] GPR28: c0ff1b68 c0bf8e5c > > c312f700 c0fbb9b0 > > [ 146.669384][ T809] NIP [c024f334] ftrace_bug+0x28c/0x2e8 > > [ 146.669391][ T809] LR [c024f330] ftrace_bug+0x288/0x2e8 > > [ 146.669396][ T809] Call Trace: > > [ 146.669403][ T809] [c4c8b9f0] [c024f330] > > ftrace_bug+0x288/0x2e8 (unreliable) > > [ 146.669418][ T809] [c4c8ba80] [c0248778] > > ftrace_modify_all_code+0x168/0x210 > > [ 146.669429][ T809] [c4c8bab0] [c006c528] > > arch_ftrace_update_code+0x18/0x30 > > [ 146.669440][ T809] [c4c8bad0] [c0248954] > > ftrace_run_update_code+0x44/0xc0 > > [ 146.669451][ T809] [c4c8bb00] [c024dc88] > > ftrace_startup+0xf8/0x1c0 > > [ 146.669461][ T809] [c4c8bb40] [c024dd9c] > > register_ftrace_function+0x4c/0xc0 > > [ 146.669472][ T809] [c4c8bb70] [c026e750] > > function_trace_init+0x80/0xb0 > > [ 146.669484][ T809] [c4c8bba0] [c0266b84] > > tracing_set_tracer+0x2a4/0x4f0 > > [ 146.669495][ T809] [c4c8bc70] [c0266ea4] > > tracing_set_trace_write+0xd4/0x130 > > [ 146.669506][ T809] [c4c8bd20] [c0422790] > > vfs_write+0xf0/0x330 > > [ 146.669518][ T809] [c4c8bd70] [c0422bb4] > > ksys_write+0x84/0x140 > > [ 146.669529][ T809] [c4c8bdc0] [c003499c] > > system_call_exception+0x14c/0x230 > > [ 146.669540][ T809] [c4c8be20] [c000d860] > > system_call_common+0xf0/0x27c > > [ 146.669549][ T809] Instruction dump: > > [ 146.669558][ T809] 4814 3c62fe88 38631718 4bf5a941 6000 > > 7fc3f378 4bff877d 7c641b78 > > [ 146.669598][ T809] 3c62fe88 38631730 4bf5a925 6000 <0fe0> > > 38210090 3d22fd90 3901 > > [ 146.669638][ T809] ---[ end trace 5ea7076ea28c0fbd ]--- > > > > To fix this when updating kernel memory ptes using ptesync. > > > > Fixes: 37bc3e5fd764 ("powerpc/lib/code-patching: Use alternate map for > > patch_instruction()") > > Fixes: f1cb8f9beba8 ("powerpc/64s/radix: avoid ptesync after set_pte and > > ptep_set_access_flags") > > Signed-off-by: Jordan Niethe > > Good catch. I would say it just fixes the latter patch doesn't it? The > previous one just happens to break because it's using the broken API? Yes that is true. I will send another revision that removes that from the 'Fixes' and also add a self test. > > Anyhow, > > Reviewed-by: Nicholas Piggin > > > --- > > v2: Only ptesync is needed > > --- > > arch/powerpc/include/asm/book3s/64/radix.h | 6 -- > > arch/powerpc/mm/book3s64/radix_pgtable.c | 4 ++-- > > 2 files changed, 6 insertions(+), 4 deletions(-) > > > > diff --git a/arch/powerpc/include/asm/book3s/64/radix.h > > b/arch/powerpc/include/asm/book3s/64/radix.h > > index c7813dc628fc..59cab558e2f0 100644 > > --- a/arch/powerpc/include/asm/book3s/64/radix.h > > +++ b/arch/powerpc/include/asm/book3s/64/radix.h > > @@ -222,8 +222,10 @@ static inline void radix__set_pte_at(struct mm_struct > > *mm, unsigned long addr, > >* from ptesync, it should probably go into update_mmu_cache, rather > >* than set_pte_at (which is used to set ptes unrelated to faults). > >* > > - * Spurious faults to vmalloc region are not tolerated, so there is > > - * a ptesync in flush_cache_vmap. > > + * Spurious faults from the kernel memory are not tolerated, so there > > + * is a ptesync in flush_cache_vmap, and __map_kernel_page() follows > > + * the pte update sequence from ISA Book III 6.10 Translation Table > > + * Update Synchronization Requirements. > >*/ > > } > > > > diff --git a/arch/powerpc/mm/book3s64/radix_pgtable.c > > b/arch/powerpc/mm/book3s64/radix_pgtable.c > > index 3adcf730f478..1d5eec847b88 100644 > > --- a/arch/powerpc/mm/book3s64/radix_pgtable.c > > +++ b/arch/powerpc/mm/book3s64/radix_pgtable.c > > @@ -108,7 +108,7 @@ static int early_map_kernel_page(unsigned long ea, > > unsigned long pa, > > > > set_the_pte: > > set_pte_at(_mm, ea, ptep, pfn_pte(pfn, flags)); > > - smp_wmb(); > > + asm volatile("ptesync": : :"memory"); > > return 0; > > } > > > > @@ -168,7 +168,7 @@ static int __map_kernel_page(unsigned long ea, unsigned > > long pa, > > > > set_the_pte: > > set_pte_at(_mm, ea, ptep, pfn_pte(pfn, flags)); > > - smp_wmb(); > > + asm volatile("ptesync": : :"memory"); > > return 0; > > } > > > > -- > > 2.25.1 > > > >
[PATCH v2] powerpc/64s: Fix pte update for kernel memory on radix
+0x44/0xc0 [ 146.669451][ T809] [c4c8bb00] [c024dc88] ftrace_startup+0xf8/0x1c0 [ 146.669461][ T809] [c4c8bb40] [c024dd9c] register_ftrace_function+0x4c/0xc0 [ 146.669472][ T809] [c4c8bb70] [c026e750] function_trace_init+0x80/0xb0 [ 146.669484][ T809] [c4c8bba0] [c0266b84] tracing_set_tracer+0x2a4/0x4f0 [ 146.669495][ T809] [c4c8bc70] [c0266ea4] tracing_set_trace_write+0xd4/0x130 [ 146.669506][ T809] [c4c8bd20] [c0422790] vfs_write+0xf0/0x330 [ 146.669518][ T809] [c4c8bd70] [c0422bb4] ksys_write+0x84/0x140 [ 146.669529][ T809] [c4c8bdc0] [c003499c] system_call_exception+0x14c/0x230 [ 146.669540][ T809] [c4c8be20] [c000d860] system_call_common+0xf0/0x27c [ 146.669549][ T809] Instruction dump: [ 146.669558][ T809] 4814 3c62fe88 38631718 4bf5a941 6000 7fc3f378 4bff877d 7c641b78 [ 146.669598][ T809] 3c62fe88 38631730 4bf5a925 6000 <0fe0> 38210090 3d22fd90 3901 [ 146.669638][ T809] ---[ end trace 5ea7076ea28c0fbd ]--- To fix this when updating kernel memory ptes using ptesync. Fixes: 37bc3e5fd764 ("powerpc/lib/code-patching: Use alternate map for patch_instruction()") Fixes: f1cb8f9beba8 ("powerpc/64s/radix: avoid ptesync after set_pte and ptep_set_access_flags") Signed-off-by: Jordan Niethe --- v2: Only ptesync is needed --- arch/powerpc/include/asm/book3s/64/radix.h | 6 -- arch/powerpc/mm/book3s64/radix_pgtable.c | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/arch/powerpc/include/asm/book3s/64/radix.h b/arch/powerpc/include/asm/book3s/64/radix.h index c7813dc628fc..59cab558e2f0 100644 --- a/arch/powerpc/include/asm/book3s/64/radix.h +++ b/arch/powerpc/include/asm/book3s/64/radix.h @@ -222,8 +222,10 @@ static inline void radix__set_pte_at(struct mm_struct *mm, unsigned long addr, * from ptesync, it should probably go into update_mmu_cache, rather * than set_pte_at (which is used to set ptes unrelated to faults). * -* Spurious faults to vmalloc region are not tolerated, so there is -* a ptesync in flush_cache_vmap. +* Spurious faults from the kernel memory are not tolerated, so there +* is a ptesync in flush_cache_vmap, and __map_kernel_page() follows +* the pte update sequence from ISA Book III 6.10 Translation Table +* Update Synchronization Requirements. */ } diff --git a/arch/powerpc/mm/book3s64/radix_pgtable.c b/arch/powerpc/mm/book3s64/radix_pgtable.c index 3adcf730f478..1d5eec847b88 100644 --- a/arch/powerpc/mm/book3s64/radix_pgtable.c +++ b/arch/powerpc/mm/book3s64/radix_pgtable.c @@ -108,7 +108,7 @@ static int early_map_kernel_page(unsigned long ea, unsigned long pa, set_the_pte: set_pte_at(_mm, ea, ptep, pfn_pte(pfn, flags)); - smp_wmb(); + asm volatile("ptesync": : :"memory"); return 0; } @@ -168,7 +168,7 @@ static int __map_kernel_page(unsigned long ea, unsigned long pa, set_the_pte: set_pte_at(_mm, ea, ptep, pfn_pte(pfn, flags)); - smp_wmb(); + asm volatile("ptesync": : :"memory"); return 0; } -- 2.25.1
[PATCH 2/2] Revert "powerpc/64s: Disable STRICT_KERNEL_RWX"
This reverts commit 8659a0e0efdd975c73355dbc033f79ba3b31e82c. Signed-off-by: Jordan Niethe --- arch/powerpc/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 294108e0e5c6..a7113ee85994 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -135,7 +135,7 @@ config PPC select ARCH_HAS_MEMBARRIER_CALLBACKS select ARCH_HAS_MEMBARRIER_SYNC_CORE select ARCH_HAS_SCALED_CPUTIME if VIRT_CPU_ACCOUNTING_NATIVE && PPC_BOOK3S_64 - select ARCH_HAS_STRICT_KERNEL_RWX if (PPC32 && !HIBERNATION) + select ARCH_HAS_STRICT_KERNEL_RWX if ((PPC_BOOK3S_64 || PPC32) && !HIBERNATION) select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST select ARCH_HAS_UACCESS_FLUSHCACHE select ARCH_HAS_COPY_MC if PPC64 -- 2.25.1
[PATCH 1/2] powerpc/64s: Fix pte update for kernel memory on radix
0004c8bab0] [c006c528] arch_ftrace_update_code+0x18/0x30 [ 146.669440][ T809] [c4c8bad0] [c0248954] ftrace_run_update_code+0x44/0xc0 [ 146.669451][ T809] [c4c8bb00] [c024dc88] ftrace_startup+0xf8/0x1c0 [ 146.669461][ T809] [c4c8bb40] [c024dd9c] register_ftrace_function+0x4c/0xc0 [ 146.669472][ T809] [c4c8bb70] [c026e750] function_trace_init+0x80/0xb0 [ 146.669484][ T809] [c4c8bba0] [c0266b84] tracing_set_tracer+0x2a4/0x4f0 [ 146.669495][ T809] [c4c8bc70] [c0266ea4] tracing_set_trace_write+0xd4/0x130 [ 146.669506][ T809] [c4c8bd20] [c0422790] vfs_write+0xf0/0x330 [ 146.669518][ T809] [c4c8bd70] [c0422bb4] ksys_write+0x84/0x140 [ 146.669529][ T809] [c4c8bdc0] [c003499c] system_call_exception+0x14c/0x230 [ 146.669540][ T809] [c4c8be20] [c000d860] system_call_common+0xf0/0x27c [ 146.669549][ T809] Instruction dump: [ 146.669558][ T809] 4814 3c62fe88 38631718 4bf5a941 6000 7fc3f378 4bff877d 7c641b78 [ 146.669598][ T809] 3c62fe88 38631730 4bf5a925 6000 <0fe0> 38210090 3d22fd90 3901 [ 146.669638][ T809] ---[ end trace 5ea7076ea28c0fbd ]--- To fix this when updating kernel memory ptes, follow the ISA recommended sequence. Fixes: 37bc3e5fd764 ("powerpc/lib/code-patching: Use alternate map for patch_instruction()") Fixes: f1cb8f9beba8 ("powerpc/64s/radix: avoid ptesync after set_pte and ptep_set_access_flags") Signed-off-by: Jordan Niethe --- arch/powerpc/include/asm/book3s/64/radix.h | 6 -- arch/powerpc/mm/book3s64/radix_pgtable.c | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/arch/powerpc/include/asm/book3s/64/radix.h b/arch/powerpc/include/asm/book3s/64/radix.h index c7813dc628fc..59cab558e2f0 100644 --- a/arch/powerpc/include/asm/book3s/64/radix.h +++ b/arch/powerpc/include/asm/book3s/64/radix.h @@ -222,8 +222,10 @@ static inline void radix__set_pte_at(struct mm_struct *mm, unsigned long addr, * from ptesync, it should probably go into update_mmu_cache, rather * than set_pte_at (which is used to set ptes unrelated to faults). * -* Spurious faults to vmalloc region are not tolerated, so there is -* a ptesync in flush_cache_vmap. +* Spurious faults from the kernel memory are not tolerated, so there +* is a ptesync in flush_cache_vmap, and __map_kernel_page() follows +* the pte update sequence from ISA Book III 6.10 Translation Table +* Update Synchronization Requirements. */ } diff --git a/arch/powerpc/mm/book3s64/radix_pgtable.c b/arch/powerpc/mm/book3s64/radix_pgtable.c index 3adcf730f478..001e2350bc51 100644 --- a/arch/powerpc/mm/book3s64/radix_pgtable.c +++ b/arch/powerpc/mm/book3s64/radix_pgtable.c @@ -108,7 +108,7 @@ static int early_map_kernel_page(unsigned long ea, unsigned long pa, set_the_pte: set_pte_at(_mm, ea, ptep, pfn_pte(pfn, flags)); - smp_wmb(); + asm volatile("eieio; tlbsync; ptesync": : :"memory"); return 0; } @@ -168,7 +168,7 @@ static int __map_kernel_page(unsigned long ea, unsigned long pa, set_the_pte: set_pte_at(_mm, ea, ptep, pfn_pte(pfn, flags)); - smp_wmb(); + asm volatile("eieio; tlbsync; ptesync": : :"memory"); return 0; } -- 2.25.1
[PATCH 2/2] powerpc/powernv/idle: Restore CIABR after idle for Power9
On Power9, CIABR is lost after idle. This means that instruction breakpoints set by xmon which use CIABR do not work. Fix this by restoring CIABR after idle. Signed-off-by: Jordan Niethe --- arch/powerpc/platforms/powernv/idle.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/powerpc/platforms/powernv/idle.c b/arch/powerpc/platforms/powernv/idle.c index 1ed7c5286487..e6f461812856 100644 --- a/arch/powerpc/platforms/powernv/idle.c +++ b/arch/powerpc/platforms/powernv/idle.c @@ -589,6 +589,7 @@ struct p9_sprs { u64 spurr; u64 dscr; u64 wort; + u64 ciabr; u64 mmcra; u32 mmcr0; @@ -668,6 +669,7 @@ static unsigned long power9_idle_stop(unsigned long psscr, bool mmu_on) sprs.spurr = mfspr(SPRN_SPURR); sprs.dscr = mfspr(SPRN_DSCR); sprs.wort = mfspr(SPRN_WORT); + sprs.ciabr = mfspr(SPRN_CIABR); sprs.mmcra = mfspr(SPRN_MMCRA); sprs.mmcr0 = mfspr(SPRN_MMCR0); @@ -785,6 +787,7 @@ static unsigned long power9_idle_stop(unsigned long psscr, bool mmu_on) mtspr(SPRN_SPURR, sprs.spurr); mtspr(SPRN_DSCR,sprs.dscr); mtspr(SPRN_WORT,sprs.wort); + mtspr(SPRN_CIABR, sprs.ciabr); mtspr(SPRN_MMCRA, sprs.mmcra); mtspr(SPRN_MMCR0, sprs.mmcr0); -- 2.17.1
[PATCH 1/2] powerpc/book3s64/kexec: Clear CIABR on kexec
The value in CIABR persists across kexec which can lead to unintended results when the new kernel hits the old kernel's breakpoint. For example: 0:mon> bi $loadavg_proc_show 0:mon> b typeaddress 1 inst c0519060 loadavg_proc_show+0x0/0x130 0:mon> x $ kexec -l /mnt/vmlinux --initrd=/mnt/rootfs.cpio.gz --append='xmon=off' $ kexec -e $ cat /proc/loadavg Trace/breakpoint trap Make sure CIABR is cleared so this does not happen. Signed-off-by: Jordan Niethe --- arch/powerpc/include/asm/book3s/64/kexec.h | 5 + 1 file changed, 5 insertions(+) diff --git a/arch/powerpc/include/asm/book3s/64/kexec.h b/arch/powerpc/include/asm/book3s/64/kexec.h index 6b5c3a248ba2..d4b9d476ecba 100644 --- a/arch/powerpc/include/asm/book3s/64/kexec.h +++ b/arch/powerpc/include/asm/book3s/64/kexec.h @@ -3,6 +3,7 @@ #ifndef _ASM_POWERPC_BOOK3S_64_KEXEC_H_ #define _ASM_POWERPC_BOOK3S_64_KEXEC_H_ +#include #define reset_sprs reset_sprs static inline void reset_sprs(void) @@ -14,6 +15,10 @@ static inline void reset_sprs(void) if (cpu_has_feature(CPU_FTR_ARCH_207S)) { mtspr(SPRN_IAMR, 0); + if (cpu_has_feature(CPU_FTR_HVMODE)) + mtspr(SPRN_CIABR, 0); + else + plpar_set_ciabr(0); } /* Do we need isync()? We are going via a kexec reset */ -- 2.17.1
[PATCH v2] powerpc: Allow relative pointers in bug table entries
This enables GENERIC_BUG_RELATIVE_POINTERS on Power so that 32-bit offsets are stored in the bug entries rather than 64-bit pointers. While this doesn't save space for 32-bit machines, use it anyway so there is only one code path. Signed-off-by: Jordan Niethe --- v2: Remove non-relative pointers code --- arch/powerpc/Kconfig | 4 arch/powerpc/include/asm/bug.h | 8 arch/powerpc/xmon/xmon.c | 4 ++-- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index e9f13fe08492..294108e0e5c6 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -311,6 +311,10 @@ config GENERIC_BUG default y depends on BUG +config GENERIC_BUG_RELATIVE_POINTERS + def_bool y + depends on GENERIC_BUG + config SYS_SUPPORTS_APM_EMULATION default y if PMAC_APM_EMU bool diff --git a/arch/powerpc/include/asm/bug.h b/arch/powerpc/include/asm/bug.h index 338f36cd9934..ba0500872cce 100644 --- a/arch/powerpc/include/asm/bug.h +++ b/arch/powerpc/include/asm/bug.h @@ -12,7 +12,7 @@ #ifdef CONFIG_DEBUG_BUGVERBOSE .macro EMIT_BUG_ENTRY addr,file,line,flags .section __bug_table,"aw" -5001: PPC_LONG \addr, 5002f +5001: .4byte \addr - 5001b, 5002f - 5001b .short \line, \flags .org 5001b+BUG_ENTRY_SIZE .previous @@ -23,7 +23,7 @@ #else .macro EMIT_BUG_ENTRY addr,file,line,flags .section __bug_table,"aw" -5001: PPC_LONG \addr +5001: .4byte \addr - 5001b .short \flags .org 5001b+BUG_ENTRY_SIZE .previous @@ -36,14 +36,14 @@ #ifdef CONFIG_DEBUG_BUGVERBOSE #define _EMIT_BUG_ENTRY\ ".section __bug_table,\"aw\"\n" \ - "2:\t" PPC_LONG "1b, %0\n" \ + "2:\t.4byte 1b - 2b, %0 - 2b\n" \ "\t.short %1, %2\n" \ ".org 2b+%3\n" \ ".previous\n" #else #define _EMIT_BUG_ENTRY\ ".section __bug_table,\"aw\"\n" \ - "2:\t" PPC_LONG "1b\n" \ + "2:\t.4byte 1b - 2b\n" \ "\t.short %2\n" \ ".org 2b+%3\n" \ ".previous\n" diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index 55c43a6c9111..9704c81aff7d 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c @@ -1745,9 +1745,9 @@ static void print_bug_trap(struct pt_regs *regs) #ifdef CONFIG_DEBUG_BUGVERBOSE printf("kernel BUG at %s:%u!\n", - bug->file, bug->line); + (char *)bug + bug->file_disp, bug->line); #else - printf("kernel BUG at %px!\n", (void *)bug->bug_addr); + printf("kernel BUG at %px!\n", (void *)bug + bug->bug_addr_disp); #endif #endif /* CONFIG_BUG */ } -- 2.17.1
Re: [PATCH] powerpc: Allow relative pointers in bug table entries
On Mon, Nov 30, 2020 at 12:42 PM Michael Ellerman wrote: > > Christophe Leroy writes: > > Le 27/11/2020 à 04:02, Jordan Niethe a écrit : > >> This enables GENERIC_BUG_RELATIVE_POINTERS on Power so that 32-bit > >> offsets are stored in the bug entries rather than 64-bit pointers. > >> > >> Signed-off-by: Jordan Niethe > >> --- > >> arch/powerpc/Kconfig | 4 > >> arch/powerpc/include/asm/bug.h | 37 -- > >> arch/powerpc/xmon/xmon.c | 17 ++-- > >> 3 files changed, 54 insertions(+), 4 deletions(-) > >> > >> diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig > >> index e9f13fe08492..294108e0e5c6 100644 > >> --- a/arch/powerpc/Kconfig > >> +++ b/arch/powerpc/Kconfig > >> @@ -311,6 +311,10 @@ config GENERIC_BUG > >> default y > >> depends on BUG > >> > >> +config GENERIC_BUG_RELATIVE_POINTERS > >> +def_bool y > >> +depends on GENERIC_BUG > >> + > >> config SYS_SUPPORTS_APM_EMULATION > >> default y if PMAC_APM_EMU > >> bool > >> diff --git a/arch/powerpc/include/asm/bug.h > >> b/arch/powerpc/include/asm/bug.h > >> index 338f36cd9934..d03d834042a1 100644 > >> --- a/arch/powerpc/include/asm/bug.h > >> +++ b/arch/powerpc/include/asm/bug.h > >> @@ -12,7 +12,11 @@ > >> #ifdef CONFIG_DEBUG_BUGVERBOSE > >> .macro EMIT_BUG_ENTRY addr,file,line,flags > >> .section __bug_table,"aw" > >> +#ifndef CONFIG_GENERIC_BUG_RELATIVE_POINTERS > > > > As far as I understand, as soon as CONFIG_BUG is selected, GENERIC_BUG is > > automatically selected so > > GENERIC_BUG_RELATIVE_POINTERS is selected as well. Therefore this #ifndef > > is never possible. > > Yeah. > > There is one place in the generic code that has an ifndef > CONFIG_GENERIC_BUG_RELATIVE_POINTERS > but that's because it has to support arches that don't select it. > > In the arch code we know that it's enabled, so there should be no need > for any ifdefs. For 32bit, pointers are 4 bytes anyway so it would be pointless to store a displacement, so won't we need some ifdefs for that? > > cheers
Re: [PATCH] powerpc: Allow relative pointers in bug table entries
On Sun, Nov 29, 2020 at 6:00 AM Christophe Leroy wrote: > > > > Le 27/11/2020 à 04:02, Jordan Niethe a écrit : > > This enables GENERIC_BUG_RELATIVE_POINTERS on Power so that 32-bit > > offsets are stored in the bug entries rather than 64-bit pointers. > > > > Signed-off-by: Jordan Niethe > > --- > > arch/powerpc/Kconfig | 4 > > arch/powerpc/include/asm/bug.h | 37 -- > > arch/powerpc/xmon/xmon.c | 17 ++-- > > 3 files changed, 54 insertions(+), 4 deletions(-) > > > > diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig > > index e9f13fe08492..294108e0e5c6 100644 > > --- a/arch/powerpc/Kconfig > > +++ b/arch/powerpc/Kconfig > > @@ -311,6 +311,10 @@ config GENERIC_BUG > > default y > > depends on BUG > > > > +config GENERIC_BUG_RELATIVE_POINTERS > > + def_bool y > > + depends on GENERIC_BUG > > + > > config SYS_SUPPORTS_APM_EMULATION > > default y if PMAC_APM_EMU > > bool > > diff --git a/arch/powerpc/include/asm/bug.h b/arch/powerpc/include/asm/bug.h > > index 338f36cd9934..d03d834042a1 100644 > > --- a/arch/powerpc/include/asm/bug.h > > +++ b/arch/powerpc/include/asm/bug.h > > @@ -12,7 +12,11 @@ > > #ifdef CONFIG_DEBUG_BUGVERBOSE > > .macro EMIT_BUG_ENTRY addr,file,line,flags > >.section __bug_table,"aw" > > +#ifndef CONFIG_GENERIC_BUG_RELATIVE_POINTERS > > As far as I understand, as soon as CONFIG_BUG is selected, GENERIC_BUG is > automatically selected so > GENERIC_BUG_RELATIVE_POINTERS is selected as well. Therefore this #ifndef is > never possible. Thanks, you are right. I'll fix that up. > > > 5001:PPC_LONG \addr, 5002f > > +#else > > +5001: .4byte \addr - 5001b, 5002f - 5001b > > +#endif /* CONFIG_GENERIC_BUG_RELATIVE_POINTERS */ > >.short \line, \flags > >.org 5001b+BUG_ENTRY_SIZE > >.previous > > @@ -23,7 +27,11 @@ > > #else > > .macro EMIT_BUG_ENTRY addr,file,line,flags > >.section __bug_table,"aw" > > +#ifndef CONFIG_GENERIC_BUG_RELATIVE_POINTERS > > Same > > > 5001:PPC_LONG \addr > > +#else > > +5001: .4byte \addr - 5001b > > +#endif /* CONFIG_GENERIC_BUG_RELATIVE_POINTERS */ > >.short \flags > >.org 5001b+BUG_ENTRY_SIZE > >.previous > > @@ -34,20 +42,45 @@ > > /* _EMIT_BUG_ENTRY expects args %0,%1,%2,%3 to be FILE, LINE, flags and > > sizeof(struct bug_entry), respectively */ > > #ifdef CONFIG_DEBUG_BUGVERBOSE > > +#ifndef CONFIG_GENERIC_BUG_RELATIVE_POINTERS > > Same > > > #define _EMIT_BUG_ENTRY \ > > ".section __bug_table,\"aw\"\n" \ > > "2:\t" PPC_LONG "1b, %0\n" \ > > "\t.short %1, %2\n" \ > > ".org 2b+%3\n" \ > > ".previous\n" > > -#else > > + > > +#else /* relative pointers */ > > + > > +#define _EMIT_BUG_ENTRY \ > > + ".section __bug_table,\"aw\"\n" \ > > + "2:\t.4byte 1b - 2b, %0 - 2b\n" \ > > + "\t.short %1, %2\n" \ > > + ".org 2b+%3\n" \ > > + ".previous\n" > > +#endif /* relative pointers */ > > + > > +#else /* verbose */ > > + > > +#ifndef CONFIG_GENERIC_BUG_RELATIVE_POINTERS > > Same > > > #define _EMIT_BUG_ENTRY \ > > ".section __bug_table,\"aw\"\n" \ > > "2:\t" PPC_LONG "1b\n" \ > > "\t.short %2\n" \ > > ".org 2b+%3\n" \ > > ".previous\n" > > -#endif > > + > > +#else /* relative pointers */ > > + > > +#define _EMIT_BUG_ENTRY \ > > + ".section __bug_table,\"aw\"\n" \ > > + "2:\t.4byte 1b - 2b\n" \ > > + "\t.short %2\n" \ > > + ".org 2b+%3\n" \ > > + ".previous\n" > > + > > +#endif /* relative pointers */ > > +#endif /* verbose */ > > > > #define BUG_ENTR
[PATCH] powerpc/64: Fix an EMIT_BUG_ENTRY in head_64.S
Commit 63ce271b5e37 ("powerpc/prom: convert PROM_BUG() to standard trap") added an EMIT_BUG_ENTRY for the trap after the branch to start_kernel(). The EMIT_BUG_ENTRY was for the address "0b", however the trap was not labeled with "0". Hence the address used for bug is in relative_toc() where the previous "0" label is. Label the trap as "0" so the correct address is used. Fixes: 63ce271b5e37 ("powerpc/prom: convert PROM_BUG() to standard trap") Signed-off-by: Jordan Niethe --- arch/powerpc/kernel/head_64.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 3bae6286c17c..f63d01c78398 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -995,7 +995,7 @@ start_here_common: bl start_kernel /* Not reached */ - trap +0: trap EMIT_BUG_ENTRY 0b, __FILE__, __LINE__, 0 .previous -- 2.17.1
[PATCH] powerpc: Allow relative pointers in bug table entries
This enables GENERIC_BUG_RELATIVE_POINTERS on Power so that 32-bit offsets are stored in the bug entries rather than 64-bit pointers. Signed-off-by: Jordan Niethe --- arch/powerpc/Kconfig | 4 arch/powerpc/include/asm/bug.h | 37 -- arch/powerpc/xmon/xmon.c | 17 ++-- 3 files changed, 54 insertions(+), 4 deletions(-) diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index e9f13fe08492..294108e0e5c6 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -311,6 +311,10 @@ config GENERIC_BUG default y depends on BUG +config GENERIC_BUG_RELATIVE_POINTERS + def_bool y + depends on GENERIC_BUG + config SYS_SUPPORTS_APM_EMULATION default y if PMAC_APM_EMU bool diff --git a/arch/powerpc/include/asm/bug.h b/arch/powerpc/include/asm/bug.h index 338f36cd9934..d03d834042a1 100644 --- a/arch/powerpc/include/asm/bug.h +++ b/arch/powerpc/include/asm/bug.h @@ -12,7 +12,11 @@ #ifdef CONFIG_DEBUG_BUGVERBOSE .macro EMIT_BUG_ENTRY addr,file,line,flags .section __bug_table,"aw" +#ifndef CONFIG_GENERIC_BUG_RELATIVE_POINTERS 5001: PPC_LONG \addr, 5002f +#else +5001: .4byte \addr - 5001b, 5002f - 5001b +#endif /* CONFIG_GENERIC_BUG_RELATIVE_POINTERS */ .short \line, \flags .org 5001b+BUG_ENTRY_SIZE .previous @@ -23,7 +27,11 @@ #else .macro EMIT_BUG_ENTRY addr,file,line,flags .section __bug_table,"aw" +#ifndef CONFIG_GENERIC_BUG_RELATIVE_POINTERS 5001: PPC_LONG \addr +#else +5001: .4byte \addr - 5001b +#endif /* CONFIG_GENERIC_BUG_RELATIVE_POINTERS */ .short \flags .org 5001b+BUG_ENTRY_SIZE .previous @@ -34,20 +42,45 @@ /* _EMIT_BUG_ENTRY expects args %0,%1,%2,%3 to be FILE, LINE, flags and sizeof(struct bug_entry), respectively */ #ifdef CONFIG_DEBUG_BUGVERBOSE +#ifndef CONFIG_GENERIC_BUG_RELATIVE_POINTERS #define _EMIT_BUG_ENTRY\ ".section __bug_table,\"aw\"\n" \ "2:\t" PPC_LONG "1b, %0\n" \ "\t.short %1, %2\n" \ ".org 2b+%3\n" \ ".previous\n" -#else + +#else /* relative pointers */ + +#define _EMIT_BUG_ENTRY\ + ".section __bug_table,\"aw\"\n" \ + "2:\t.4byte 1b - 2b, %0 - 2b\n" \ + "\t.short %1, %2\n" \ + ".org 2b+%3\n" \ + ".previous\n" +#endif /* relative pointers */ + +#else /* verbose */ + +#ifndef CONFIG_GENERIC_BUG_RELATIVE_POINTERS #define _EMIT_BUG_ENTRY\ ".section __bug_table,\"aw\"\n" \ "2:\t" PPC_LONG "1b\n" \ "\t.short %2\n" \ ".org 2b+%3\n" \ ".previous\n" -#endif + +#else /* relative pointers */ + +#define _EMIT_BUG_ENTRY\ + ".section __bug_table,\"aw\"\n" \ + "2:\t.4byte 1b - 2b\n" \ + "\t.short %2\n" \ + ".org 2b+%3\n" \ + ".previous\n" + +#endif /* relative pointers */ +#endif /* verbose */ #define BUG_ENTRY(insn, flags, ...)\ __asm__ __volatile__( \ diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index 55c43a6c9111..5f7cf7e95767 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c @@ -1731,6 +1731,9 @@ static void print_bug_trap(struct pt_regs *regs) #ifdef CONFIG_BUG const struct bug_entry *bug; unsigned long addr; +#ifdef CONFIG_DEBUG_BUGVERBOSE + char *file; +#endif if (regs->msr & MSR_PR) return; /* not in kernel */ @@ -1744,10 +1747,20 @@ static void print_bug_trap(struct pt_regs *regs) return; #ifdef CONFIG_DEBUG_BUGVERBOSE +#ifndef CONFIG_GENERIC_BUG_RELATIVE_POINTERS + file = bug->file; +#else /* relative pointers */ + file = (char *)bug + bug->file_disp; +#endif /* relative pointers */ printf("kernel BUG at %s:%u!\n", - bug->file, bug->line); + file, bug->line); #else - printf("kernel BUG at %px!\n", (void *)bug->bug_addr); +#ifndef CONFIG_GENERIC_BUG_RELATIVE_POINTERS + addr = bug->addr; +#else /* relative pointers */ + addr = (unsigned long)bug + bug->bug_addr_disp; +#endif /* relative pointers */ + printf("kernel BUG at %px!\n", (void *)addr); #endif #endif /* CONFIG_BUG */ } -- 2.17.1
Re: [PATCH] powerpc/powernv/memtrace: Fake non-memblock aligned sized traces
On Mon, Nov 16, 2020 at 11:02 PM Michael Ellerman wrote: > > Jordan Niethe writes: > > The hardware trace macros which use the memory provided by memtrace are > > able to use trace sizes as small as 16MB. Only memblock aligned values > > can be removed from each NUMA node by writing that value to > > memtrace/enable in debugfs. This means setting up, say, a 16MB trace is > > not possible. To allow such a trace size, instead align whatever value > > is written to memtrace/enable to the memblock size for the purpose of > > removing it from each NUMA node but report the written value from > > memtrace/enable and memtrace/x/size in debugfs. > > Why does it matter if the size that's removed is larger than the size > that was requested? > > Is it about constraining the size of the trace? If so that seems like it > should be the job of the tracing tools, not the kernel. Yeah about constraining the size, I'll just do it in the trace tools. > > cheers
[PATCH] powerpc/powernv/memtrace: Fake non-memblock aligned sized traces
The hardware trace macros which use the memory provided by memtrace are able to use trace sizes as small as 16MB. Only memblock aligned values can be removed from each NUMA node by writing that value to memtrace/enable in debugfs. This means setting up, say, a 16MB trace is not possible. To allow such a trace size, instead align whatever value is written to memtrace/enable to the memblock size for the purpose of removing it from each NUMA node but report the written value from memtrace/enable and memtrace/x/size in debugfs. Signed-off-by: Jordan Niethe --- arch/powerpc/platforms/powernv/memtrace.c | 20 ++-- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/arch/powerpc/platforms/powernv/memtrace.c b/arch/powerpc/platforms/powernv/memtrace.c index 6828108486f8..1188bc8fd090 100644 --- a/arch/powerpc/platforms/powernv/memtrace.c +++ b/arch/powerpc/platforms/powernv/memtrace.c @@ -191,7 +191,7 @@ static int memtrace_init_debugfs(void) ent->dir = dir; debugfs_create_file("trace", 0400, dir, ent, _fops); debugfs_create_x64("start", 0400, dir, >start); - debugfs_create_x64("size", 0400, dir, >size); + debugfs_create_x64("size", 0400, dir, _size); } return ret; @@ -259,33 +259,25 @@ static int memtrace_enable_set(void *data, u64 val) { u64 bytes; - /* -* Don't attempt to do anything if size isn't aligned to a memory -* block or equal to zero. -*/ - bytes = memory_block_size_bytes(); - if (val & (bytes - 1)) { - pr_err("Value must be aligned with 0x%llx\n", bytes); - return -EINVAL; - } - /* Re-add/online previously removed/offlined memory */ if (memtrace_size) { if (memtrace_online()) return -EAGAIN; } + memtrace_size = val; + if (!val) return 0; - /* Offline and remove memory */ - if (memtrace_init_regions_runtime(val)) + /* Offline and remove memory aligned to memory blocks */ + bytes = memory_block_size_bytes(); + if (memtrace_init_regions_runtime(ALIGN(val, bytes))) return -EINVAL; if (memtrace_init_debugfs()) return -EINVAL; - memtrace_size = val; return 0; } -- 2.17.1
Re: [PATCH v2 1/2] powerpc: Introduce POWER10_DD1 feature
On Thu, Oct 22, 2020 at 4:33 PM Ravi Bangoria wrote: > > > > On 10/22/20 10:41 AM, Jordan Niethe wrote: > > On Thu, Oct 22, 2020 at 2:40 PM Ravi Bangoria > > wrote: > >> > >> POWER10_DD1 feature flag will be needed while adding > >> conditional code that applies only for Power10 DD1. > >> > >> Signed-off-by: Ravi Bangoria > >> --- > >> arch/powerpc/include/asm/cputable.h | 8 ++-- > >> arch/powerpc/kernel/dt_cpu_ftrs.c | 3 +++ > >> arch/powerpc/kernel/prom.c | 9 + > >> 3 files changed, 18 insertions(+), 2 deletions(-) > >> > >> diff --git a/arch/powerpc/include/asm/cputable.h > >> b/arch/powerpc/include/asm/cputable.h > >> index 93bc70d4c9a1..d486f56c0d33 100644 > >> --- a/arch/powerpc/include/asm/cputable.h > >> +++ b/arch/powerpc/include/asm/cputable.h > >> @@ -216,6 +216,7 @@ static inline void cpu_feature_keys_init(void) { } > >> #define CPU_FTR_P9_RADIX_PREFETCH_BUG LONG_ASM_CONST(0x0002) > >> #define CPU_FTR_ARCH_31 > >> LONG_ASM_CONST(0x0004) > >> #define CPU_FTR_DAWR1 LONG_ASM_CONST(0x0008) > >> +#define CPU_FTR_POWER10_DD1LONG_ASM_CONST(0x0010) > >> > >> #ifndef __ASSEMBLY__ > >> > >> @@ -479,6 +480,7 @@ static inline void cpu_feature_keys_init(void) { } > >> CPU_FTR_DBELL | CPU_FTR_HAS_PPR | CPU_FTR_ARCH_207S | \ > >> CPU_FTR_TM_COMP | CPU_FTR_ARCH_300 | CPU_FTR_ARCH_31 | \ > >> CPU_FTR_DAWR | CPU_FTR_DAWR1) > >> +#define CPU_FTRS_POWER10_DD1 (CPU_FTRS_POWER10 | CPU_FTR_POWER10_DD1) > >> #define CPU_FTRS_CELL (CPU_FTR_LWSYNC | \ > >> CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ > >> CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \ > >> @@ -497,14 +499,16 @@ static inline void cpu_feature_keys_init(void) { } > >> #define CPU_FTRS_POSSIBLE \ > >> (CPU_FTRS_POWER7 | CPU_FTRS_POWER8E | CPU_FTRS_POWER8 | \ > >> CPU_FTR_ALTIVEC_COMP | CPU_FTR_VSX_COMP | CPU_FTRS_POWER9 | \ > >> -CPU_FTRS_POWER9_DD2_1 | CPU_FTRS_POWER9_DD2_2 | > >> CPU_FTRS_POWER10) > >> +CPU_FTRS_POWER9_DD2_1 | CPU_FTRS_POWER9_DD2_2 | > >> CPU_FTRS_POWER10 | \ > >> +CPU_FTRS_POWER10_DD1) > >> #else > >> #define CPU_FTRS_POSSIBLE \ > >> (CPU_FTRS_PPC970 | CPU_FTRS_POWER5 | \ > >> CPU_FTRS_POWER6 | CPU_FTRS_POWER7 | CPU_FTRS_POWER8E | \ > >> CPU_FTRS_POWER8 | CPU_FTRS_CELL | CPU_FTRS_PA6T | \ > >> CPU_FTR_VSX_COMP | CPU_FTR_ALTIVEC_COMP | CPU_FTRS_POWER9 | \ > >> -CPU_FTRS_POWER9_DD2_1 | CPU_FTRS_POWER9_DD2_2 | > >> CPU_FTRS_POWER10) > >> +CPU_FTRS_POWER9_DD2_1 | CPU_FTRS_POWER9_DD2_2 | > >> CPU_FTRS_POWER10 | \ > >> +CPU_FTRS_POWER10_DD1) > >> #endif /* CONFIG_CPU_LITTLE_ENDIAN */ > >> #endif > >> #else > >> diff --git a/arch/powerpc/kernel/dt_cpu_ftrs.c > >> b/arch/powerpc/kernel/dt_cpu_ftrs.c > >> index 1098863e17ee..b2327f2967ff 100644 > >> --- a/arch/powerpc/kernel/dt_cpu_ftrs.c > >> +++ b/arch/powerpc/kernel/dt_cpu_ftrs.c > >> @@ -811,6 +811,9 @@ static __init void cpufeatures_cpu_quirks(void) > >> } > >> > >> update_tlbie_feature_flag(version); > >> + > >> + if ((version & 0x) == 0x00800100) > >> + cur_cpu_spec->cpu_features |= CPU_FTR_POWER10_DD1; > >> } > >> > >> static void __init cpufeatures_setup_finished(void) > >> diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c > >> index c1545f22c077..c778c81284f7 100644 > >> --- a/arch/powerpc/kernel/prom.c > >> +++ b/arch/powerpc/kernel/prom.c > >> @@ -305,6 +305,14 @@ static void __init > >> check_cpu_feature_properties(unsigned long node) > >> } > >> } > >> > >> +static void __init fixup_cpu_features(void) > >> +{ > >> + unsigned long version = mfspr(SPRN_PVR); > >> + > >> + if ((version & 0x) == 0x00800100) > >> + cur_cpu_spec->cpu_features |= CPU_FTR_POWER10_DD1; > >> +} > >> + > > I am just wondering why this is needed here, but the same thing is not &g
Re: [PATCH v2 1/2] powerpc: Introduce POWER10_DD1 feature
On Thu, Oct 22, 2020 at 2:40 PM Ravi Bangoria wrote: > > POWER10_DD1 feature flag will be needed while adding > conditional code that applies only for Power10 DD1. > > Signed-off-by: Ravi Bangoria > --- > arch/powerpc/include/asm/cputable.h | 8 ++-- > arch/powerpc/kernel/dt_cpu_ftrs.c | 3 +++ > arch/powerpc/kernel/prom.c | 9 + > 3 files changed, 18 insertions(+), 2 deletions(-) > > diff --git a/arch/powerpc/include/asm/cputable.h > b/arch/powerpc/include/asm/cputable.h > index 93bc70d4c9a1..d486f56c0d33 100644 > --- a/arch/powerpc/include/asm/cputable.h > +++ b/arch/powerpc/include/asm/cputable.h > @@ -216,6 +216,7 @@ static inline void cpu_feature_keys_init(void) { } > #define CPU_FTR_P9_RADIX_PREFETCH_BUG LONG_ASM_CONST(0x0002) > #define CPU_FTR_ARCH_31 > LONG_ASM_CONST(0x0004) > #define CPU_FTR_DAWR1 LONG_ASM_CONST(0x0008) > +#define CPU_FTR_POWER10_DD1LONG_ASM_CONST(0x0010) > > #ifndef __ASSEMBLY__ > > @@ -479,6 +480,7 @@ static inline void cpu_feature_keys_init(void) { } > CPU_FTR_DBELL | CPU_FTR_HAS_PPR | CPU_FTR_ARCH_207S | \ > CPU_FTR_TM_COMP | CPU_FTR_ARCH_300 | CPU_FTR_ARCH_31 | \ > CPU_FTR_DAWR | CPU_FTR_DAWR1) > +#define CPU_FTRS_POWER10_DD1 (CPU_FTRS_POWER10 | CPU_FTR_POWER10_DD1) > #define CPU_FTRS_CELL (CPU_FTR_LWSYNC | \ > CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ > CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \ > @@ -497,14 +499,16 @@ static inline void cpu_feature_keys_init(void) { } > #define CPU_FTRS_POSSIBLE \ > (CPU_FTRS_POWER7 | CPU_FTRS_POWER8E | CPU_FTRS_POWER8 | \ > CPU_FTR_ALTIVEC_COMP | CPU_FTR_VSX_COMP | CPU_FTRS_POWER9 | \ > -CPU_FTRS_POWER9_DD2_1 | CPU_FTRS_POWER9_DD2_2 | CPU_FTRS_POWER10) > +CPU_FTRS_POWER9_DD2_1 | CPU_FTRS_POWER9_DD2_2 | CPU_FTRS_POWER10 > | \ > +CPU_FTRS_POWER10_DD1) > #else > #define CPU_FTRS_POSSIBLE \ > (CPU_FTRS_PPC970 | CPU_FTRS_POWER5 | \ > CPU_FTRS_POWER6 | CPU_FTRS_POWER7 | CPU_FTRS_POWER8E | \ > CPU_FTRS_POWER8 | CPU_FTRS_CELL | CPU_FTRS_PA6T | \ > CPU_FTR_VSX_COMP | CPU_FTR_ALTIVEC_COMP | CPU_FTRS_POWER9 | \ > -CPU_FTRS_POWER9_DD2_1 | CPU_FTRS_POWER9_DD2_2 | CPU_FTRS_POWER10) > +CPU_FTRS_POWER9_DD2_1 | CPU_FTRS_POWER9_DD2_2 | CPU_FTRS_POWER10 > | \ > +CPU_FTRS_POWER10_DD1) > #endif /* CONFIG_CPU_LITTLE_ENDIAN */ > #endif > #else > diff --git a/arch/powerpc/kernel/dt_cpu_ftrs.c > b/arch/powerpc/kernel/dt_cpu_ftrs.c > index 1098863e17ee..b2327f2967ff 100644 > --- a/arch/powerpc/kernel/dt_cpu_ftrs.c > +++ b/arch/powerpc/kernel/dt_cpu_ftrs.c > @@ -811,6 +811,9 @@ static __init void cpufeatures_cpu_quirks(void) > } > > update_tlbie_feature_flag(version); > + > + if ((version & 0x) == 0x00800100) > + cur_cpu_spec->cpu_features |= CPU_FTR_POWER10_DD1; > } > > static void __init cpufeatures_setup_finished(void) > diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c > index c1545f22c077..c778c81284f7 100644 > --- a/arch/powerpc/kernel/prom.c > +++ b/arch/powerpc/kernel/prom.c > @@ -305,6 +305,14 @@ static void __init check_cpu_feature_properties(unsigned > long node) > } > } > > +static void __init fixup_cpu_features(void) > +{ > + unsigned long version = mfspr(SPRN_PVR); > + > + if ((version & 0x) == 0x00800100) > + cur_cpu_spec->cpu_features |= CPU_FTR_POWER10_DD1; > +} > + I am just wondering why this is needed here, but the same thing is not done for, say, CPU_FTR_POWER9_DD2_1? And should we get a /* Power10 DD 1 */ added to cpu_specs[]? > static int __init early_init_dt_scan_cpus(unsigned long node, > const char *uname, int depth, > void *data) > @@ -378,6 +386,7 @@ static int __init early_init_dt_scan_cpus(unsigned long > node, > > check_cpu_feature_properties(node); > check_cpu_pa_features(node); > + fixup_cpu_features(); > } > > identical_pvr_fixup(node); > -- > 2.25.1 >
[PATCH v4 2/2] powerpc/64s: Convert some cpu_setup() and cpu_restore() functions to C
The only thing keeping the cpu_setup() and cpu_restore() functions used in the cputable entries for Power7, Power8, Power9 and Power10 in assembly was cpu_restore() being called before there was a stack in generic_secondary_smp_init(). Commit ("powerpc/64: Set up a kernel stack for secondaries before cpu_restore()") means that it is now possible to use C. Rewrite the functions in C so they are a little bit easier to read. This is not changing their functionality. Signed-off-by: Jordan Niethe --- arch/powerpc/include/asm/cpu_setup_power.h | 12 + arch/powerpc/kernel/cpu_setup_power.S | 252 --- arch/powerpc/kernel/cpu_setup_power.c | 269 + arch/powerpc/kernel/cputable.c | 12 +- 4 files changed, 285 insertions(+), 260 deletions(-) create mode 100644 arch/powerpc/include/asm/cpu_setup_power.h delete mode 100644 arch/powerpc/kernel/cpu_setup_power.S create mode 100644 arch/powerpc/kernel/cpu_setup_power.c diff --git a/arch/powerpc/include/asm/cpu_setup_power.h b/arch/powerpc/include/asm/cpu_setup_power.h new file mode 100644 index ..24be9131f803 --- /dev/null +++ b/arch/powerpc/include/asm/cpu_setup_power.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2020 IBM Corporation + */ +void __setup_cpu_power7(unsigned long offset, struct cpu_spec *spec); +void __restore_cpu_power7(void); +void __setup_cpu_power8(unsigned long offset, struct cpu_spec *spec); +void __restore_cpu_power8(void); +void __setup_cpu_power9(unsigned long offset, struct cpu_spec *spec); +void __restore_cpu_power9(void); +void __setup_cpu_power10(unsigned long offset, struct cpu_spec *spec); +void __restore_cpu_power10(void); diff --git a/arch/powerpc/kernel/cpu_setup_power.S b/arch/powerpc/kernel/cpu_setup_power.S deleted file mode 100644 index 704e8b9501ee.. --- a/arch/powerpc/kernel/cpu_setup_power.S +++ /dev/null @@ -1,252 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * This file contains low level CPU setup functions. - *Copyright (C) 2003 Benjamin Herrenschmidt (b...@kernel.crashing.org) - */ - -#include -#include -#include -#include -#include -#include -#include - -/* Entry: r3 = crap, r4 = ptr to cputable entry - * - * Note that we can be called twice for pseudo-PVRs - */ -_GLOBAL(__setup_cpu_power7) - mflrr11 - bl __init_hvmode_206 - mtlrr11 - beqlr - li r0,0 - mtspr SPRN_LPID,r0 - LOAD_REG_IMMEDIATE(r0, PCR_MASK) - mtspr SPRN_PCR,r0 - mfspr r3,SPRN_LPCR - li r4,(LPCR_LPES1 >> LPCR_LPES_SH) - bl __init_LPCR_ISA206 - mtlrr11 - blr - -_GLOBAL(__restore_cpu_power7) - mflrr11 - mfmsr r3 - rldicl. r0,r3,4,63 - beqlr - li r0,0 - mtspr SPRN_LPID,r0 - LOAD_REG_IMMEDIATE(r0, PCR_MASK) - mtspr SPRN_PCR,r0 - mfspr r3,SPRN_LPCR - li r4,(LPCR_LPES1 >> LPCR_LPES_SH) - bl __init_LPCR_ISA206 - mtlrr11 - blr - -_GLOBAL(__setup_cpu_power8) - mflrr11 - bl __init_FSCR - bl __init_PMU - bl __init_PMU_ISA207 - bl __init_hvmode_206 - mtlrr11 - beqlr - li r0,0 - mtspr SPRN_LPID,r0 - LOAD_REG_IMMEDIATE(r0, PCR_MASK) - mtspr SPRN_PCR,r0 - mfspr r3,SPRN_LPCR - ori r3, r3, LPCR_PECEDH - li r4,0 /* LPES = 0 */ - bl __init_LPCR_ISA206 - bl __init_HFSCR - bl __init_PMU_HV - bl __init_PMU_HV_ISA207 - mtlrr11 - blr - -_GLOBAL(__restore_cpu_power8) - mflrr11 - bl __init_FSCR - bl __init_PMU - bl __init_PMU_ISA207 - mfmsr r3 - rldicl. r0,r3,4,63 - mtlrr11 - beqlr - li r0,0 - mtspr SPRN_LPID,r0 - LOAD_REG_IMMEDIATE(r0, PCR_MASK) - mtspr SPRN_PCR,r0 - mfspr r3,SPRN_LPCR - ori r3, r3, LPCR_PECEDH - li r4,0 /* LPES = 0 */ - bl __init_LPCR_ISA206 - bl __init_HFSCR - bl __init_PMU_HV - bl __init_PMU_HV_ISA207 - mtlrr11 - blr - -_GLOBAL(__setup_cpu_power10) - mflrr11 - bl __init_FSCR_power10 - bl __init_PMU - bl __init_PMU_ISA31 - b 1f - -_GLOBAL(__setup_cpu_power9) - mflrr11 - bl __init_FSCR_power9 - bl __init_PMU -1: bl __init_hvmode_206 - mtlrr11 - beqlr - li r0,0 - mtspr SPRN_PSSCR,r0 - mtspr SPRN_LPID,r0 - mtspr SPRN_PID,r0 - LOAD_REG_IMMEDIATE(r0, PCR_MASK) - mtspr SPRN_PCR,r0 - mfspr r3,SPRN_LPCR - LOAD_REG_IMMEDIATE(r4, LPCR_PECEDH | LPCR_PECE_HVEE | LPCR_HVICE | LPCR_HEIC) - or r3, r3, r4 -
[PATCH v4 1/2] powerpc/64: Set up a kernel stack for secondaries before cpu_restore()
Currently in generic_secondary_smp_init(), cur_cpu_spec->cpu_restore() is called before a stack has been set up in r1. This was previously fine as the cpu_restore() functions were implemented in assembly and did not use a stack. However commit 5a61ef74f269 ("powerpc/64s: Support new device tree binding for discovering CPU features") used __restore_cpu_cpufeatures() as the cpu_restore() function for a device-tree features based cputable entry. This is a C function and hence uses a stack in r1. generic_secondary_smp_init() is entered on the secondary cpus via the primary cpu using the OPAL call opal_start_cpu(). In OPAL, each hardware thread has its own stack. The OPAL call is ran in the primary's hardware thread. During the call, a job is scheduled on a secondary cpu that will start executing at the address of generic_secondary_smp_init(). Hence the value that will be left in r1 when the secondary cpu enters the kernel is part of that secondary cpu's individual OPAL stack. This means that __restore_cpu_cpufeatures() will write to that OPAL stack. This is not horribly bad as each hardware thread has its own stack and the call that enters the kernel from OPAL never returns, but it is still wrong and should be corrected. Create the temp kernel stack before calling cpu_restore(). As noted by mpe, for a kexec boot, the secondary CPUs are released from the spin loop at address 0x60 by smp_release_cpus() and then jump to generic_secondary_smp_init(). The call to smp_release_cpus() is in setup_arch(), and it comes before the call to emergency_stack_init(). emergency_stack_init() allocates an emergency stack in the PACA for each CPU. This address in the PACA is what is used to set up the temp kernel stack in generic_secondary_smp_init(). Move releasing the secondary CPUs to after the PACAs have been allocated an emergency stack, otherwise the PACA stack pointer will contain garbage and hence the temp kernel stack created from it will be broken. Fixes: 5a61ef74f269 ("powerpc/64s: Support new device tree binding for discovering CPU features") Signed-off-by: Jordan Niethe --- v2: Add more detail to the commit message v3: Release secondary CPUs after the emergency stack is created v4: No need to guard smp_release_cpus() with #ifdef CONFIG_SMP --- arch/powerpc/kernel/head_64.S | 8 arch/powerpc/kernel/setup-common.c | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 0e05a9a47a4b..4b7f4c6c2600 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -420,6 +420,10 @@ generic_secondary_common_init: /* From now on, r24 is expected to be logical cpuid */ mr r24,r5 + /* Create a temp kernel stack for use before relocation is on. */ + ld r1,PACAEMERGSP(r13) + subir1,r1,STACK_FRAME_OVERHEAD + /* See if we need to call a cpu state restore handler */ LOAD_REG_ADDR(r23, cur_cpu_spec) ld r23,0(r23) @@ -448,10 +452,6 @@ generic_secondary_common_init: sync/* order paca.run and cur_cpu_spec */ isync /* In case code patching happened */ - /* Create a temp kernel stack for use before relocation is on. */ - ld r1,PACAEMERGSP(r13) - subir1,r1,STACK_FRAME_OVERHEAD - b __secondary_start #endif /* SMP */ diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index 808ec9fab605..da8c71f321ad 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c @@ -919,8 +919,6 @@ void __init setup_arch(char **cmdline_p) /* On BookE, setup per-core TLB data structures. */ setup_tlb_core_data(); - - smp_release_cpus(); #endif /* Print various info about the machine that has been gathered so far. */ @@ -944,6 +942,8 @@ void __init setup_arch(char **cmdline_p) exc_lvl_early_init(); emergency_stack_init(); + smp_release_cpus(); + initmem_init(); early_memtest(min_low_pfn << PAGE_SHIFT, max_low_pfn << PAGE_SHIFT); -- 2.17.1
Re: [PATCH v3 1/2] powerpc/64: Set up a kernel stack for secondaries before cpu_restore()
On Tue, Sep 22, 2020 at 3:59 PM Christophe Leroy wrote: > > > > Le 22/09/2020 à 07:53, Jordan Niethe a écrit : > > Currently in generic_secondary_smp_init(), cur_cpu_spec->cpu_restore() > > is called before a stack has been set up in r1. This was previously fine > > as the cpu_restore() functions were implemented in assembly and did not > > use a stack. However commit 5a61ef74f269 ("powerpc/64s: Support new > > device tree binding for discovering CPU features") used > > __restore_cpu_cpufeatures() as the cpu_restore() function for a > > device-tree features based cputable entry. This is a C function and > > hence uses a stack in r1. > > > > generic_secondary_smp_init() is entered on the secondary cpus via the > > primary cpu using the OPAL call opal_start_cpu(). In OPAL, each hardware > > thread has its own stack. The OPAL call is ran in the primary's hardware > > thread. During the call, a job is scheduled on a secondary cpu that will > > start executing at the address of generic_secondary_smp_init(). Hence > > the value that will be left in r1 when the secondary cpu enters the > > kernel is part of that secondary cpu's individual OPAL stack. This means > > that __restore_cpu_cpufeatures() will write to that OPAL stack. This is > > not horribly bad as each hardware thread has its own stack and the call > > that enters the kernel from OPAL never returns, but it is still wrong > > and should be corrected. > > > > Create the temp kernel stack before calling cpu_restore(). > > > > As noted by mpe, for a kexec boot, the secondary CPUs are released from > > the spin loop at address 0x60 by smp_release_cpus() and then jump to > > generic_secondary_smp_init(). The call to smp_release_cpus() is in > > setup_arch(), and it comes before the call to emergency_stack_init(). > > emergency_stack_init() allocates an emergency stack in the PACA for each > > CPU. This address in the PACA is what is used to set up the temp kernel > > stack in generic_secondary_smp_init(). Move releasing the secondary CPUs > > to after the PACAs have been allocated an emergency stack, otherwise the > > PACA stack pointer will contain garbage and hence the temp kernel stack > > created from it will be broken. > > > > Fixes: 5a61ef74f269 ("powerpc/64s: Support new device tree binding for > > discovering CPU features") > > Signed-off-by: Jordan Niethe > > --- > > v2: Add more detail to the commit message > > v3: Release secondary CPUs after the emergency stack is created > > --- > > arch/powerpc/kernel/head_64.S | 8 > > arch/powerpc/kernel/setup-common.c | 6 -- > > 2 files changed, 8 insertions(+), 6 deletions(-) > > > > diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S > > index 0e05a9a47a4b..4b7f4c6c2600 100644 > > --- a/arch/powerpc/kernel/head_64.S > > +++ b/arch/powerpc/kernel/head_64.S > > @@ -420,6 +420,10 @@ generic_secondary_common_init: > > /* From now on, r24 is expected to be logical cpuid */ > > mr r24,r5 > > > > + /* Create a temp kernel stack for use before relocation is on. */ > > + ld r1,PACAEMERGSP(r13) > > + subir1,r1,STACK_FRAME_OVERHEAD > > + > > /* See if we need to call a cpu state restore handler */ > > LOAD_REG_ADDR(r23, cur_cpu_spec) > > ld r23,0(r23) > > @@ -448,10 +452,6 @@ generic_secondary_common_init: > > sync/* order paca.run and cur_cpu_spec */ > > isync /* In case code patching happened */ > > > > - /* Create a temp kernel stack for use before relocation is on. */ > > - ld r1,PACAEMERGSP(r13) > > - subir1,r1,STACK_FRAME_OVERHEAD > > - > > b __secondary_start > > #endif /* SMP */ > > > > diff --git a/arch/powerpc/kernel/setup-common.c > > b/arch/powerpc/kernel/setup-common.c > > index 808ec9fab605..fff714e36b37 100644 > > --- a/arch/powerpc/kernel/setup-common.c > > +++ b/arch/powerpc/kernel/setup-common.c > > @@ -919,8 +919,6 @@ void __init setup_arch(char **cmdline_p) > > > > /* On BookE, setup per-core TLB data structures. */ > > setup_tlb_core_data(); > > - > > - smp_release_cpus(); > > #endif > > > > /* Print various info about the machine that has been gathered so > > far. */ > > @@ -944,6 +942,10 @@ void __init setup_arch(char **cmdline_p) > > exc_lvl_early_init(); > > emergency_stack_init(); > > > > +#ifdef CONFIG_SMP > > + smp_release_cpus(); > > +#endif > > Are you sure you need that #ifdef ? Thanks, you are right, should not be necessary. > > In asm/smp.h, we have: > > #if defined(CONFIG_PPC64) && (defined(CONFIG_SMP) || > defined(CONFIG_KEXEC_CORE)) > extern void smp_release_cpus(void); > #else > static inline void smp_release_cpus(void) { }; > #endif > > > > + > > initmem_init(); > > > > early_memtest(min_low_pfn << PAGE_SHIFT, max_low_pfn << PAGE_SHIFT); > > > > Christophe
[PATCH v3 2/2] powerpc/64s: Convert some cpu_setup() and cpu_restore() functions to C
The only thing keeping the cpu_setup() and cpu_restore() functions used in the cputable entries for Power7, Power8, Power9 and Power10 in assembly was cpu_restore() being called before there was a stack in generic_secondary_smp_init(). Commit ("powerpc/64: Set up a kernel stack for secondaries before cpu_restore()") means that it is now possible to use C. Rewrite the functions in C so they are a little bit easier to read. This is not changing their functionality. Signed-off-by: Jordan Niethe --- arch/powerpc/include/asm/cpu_setup_power.h | 12 + arch/powerpc/kernel/cpu_setup_power.S | 252 --- arch/powerpc/kernel/cpu_setup_power.c | 269 + arch/powerpc/kernel/cputable.c | 12 +- 4 files changed, 285 insertions(+), 260 deletions(-) create mode 100644 arch/powerpc/include/asm/cpu_setup_power.h delete mode 100644 arch/powerpc/kernel/cpu_setup_power.S create mode 100644 arch/powerpc/kernel/cpu_setup_power.c diff --git a/arch/powerpc/include/asm/cpu_setup_power.h b/arch/powerpc/include/asm/cpu_setup_power.h new file mode 100644 index ..24be9131f803 --- /dev/null +++ b/arch/powerpc/include/asm/cpu_setup_power.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2020 IBM Corporation + */ +void __setup_cpu_power7(unsigned long offset, struct cpu_spec *spec); +void __restore_cpu_power7(void); +void __setup_cpu_power8(unsigned long offset, struct cpu_spec *spec); +void __restore_cpu_power8(void); +void __setup_cpu_power9(unsigned long offset, struct cpu_spec *spec); +void __restore_cpu_power9(void); +void __setup_cpu_power10(unsigned long offset, struct cpu_spec *spec); +void __restore_cpu_power10(void); diff --git a/arch/powerpc/kernel/cpu_setup_power.S b/arch/powerpc/kernel/cpu_setup_power.S deleted file mode 100644 index 704e8b9501ee.. --- a/arch/powerpc/kernel/cpu_setup_power.S +++ /dev/null @@ -1,252 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * This file contains low level CPU setup functions. - *Copyright (C) 2003 Benjamin Herrenschmidt (b...@kernel.crashing.org) - */ - -#include -#include -#include -#include -#include -#include -#include - -/* Entry: r3 = crap, r4 = ptr to cputable entry - * - * Note that we can be called twice for pseudo-PVRs - */ -_GLOBAL(__setup_cpu_power7) - mflrr11 - bl __init_hvmode_206 - mtlrr11 - beqlr - li r0,0 - mtspr SPRN_LPID,r0 - LOAD_REG_IMMEDIATE(r0, PCR_MASK) - mtspr SPRN_PCR,r0 - mfspr r3,SPRN_LPCR - li r4,(LPCR_LPES1 >> LPCR_LPES_SH) - bl __init_LPCR_ISA206 - mtlrr11 - blr - -_GLOBAL(__restore_cpu_power7) - mflrr11 - mfmsr r3 - rldicl. r0,r3,4,63 - beqlr - li r0,0 - mtspr SPRN_LPID,r0 - LOAD_REG_IMMEDIATE(r0, PCR_MASK) - mtspr SPRN_PCR,r0 - mfspr r3,SPRN_LPCR - li r4,(LPCR_LPES1 >> LPCR_LPES_SH) - bl __init_LPCR_ISA206 - mtlrr11 - blr - -_GLOBAL(__setup_cpu_power8) - mflrr11 - bl __init_FSCR - bl __init_PMU - bl __init_PMU_ISA207 - bl __init_hvmode_206 - mtlrr11 - beqlr - li r0,0 - mtspr SPRN_LPID,r0 - LOAD_REG_IMMEDIATE(r0, PCR_MASK) - mtspr SPRN_PCR,r0 - mfspr r3,SPRN_LPCR - ori r3, r3, LPCR_PECEDH - li r4,0 /* LPES = 0 */ - bl __init_LPCR_ISA206 - bl __init_HFSCR - bl __init_PMU_HV - bl __init_PMU_HV_ISA207 - mtlrr11 - blr - -_GLOBAL(__restore_cpu_power8) - mflrr11 - bl __init_FSCR - bl __init_PMU - bl __init_PMU_ISA207 - mfmsr r3 - rldicl. r0,r3,4,63 - mtlrr11 - beqlr - li r0,0 - mtspr SPRN_LPID,r0 - LOAD_REG_IMMEDIATE(r0, PCR_MASK) - mtspr SPRN_PCR,r0 - mfspr r3,SPRN_LPCR - ori r3, r3, LPCR_PECEDH - li r4,0 /* LPES = 0 */ - bl __init_LPCR_ISA206 - bl __init_HFSCR - bl __init_PMU_HV - bl __init_PMU_HV_ISA207 - mtlrr11 - blr - -_GLOBAL(__setup_cpu_power10) - mflrr11 - bl __init_FSCR_power10 - bl __init_PMU - bl __init_PMU_ISA31 - b 1f - -_GLOBAL(__setup_cpu_power9) - mflrr11 - bl __init_FSCR_power9 - bl __init_PMU -1: bl __init_hvmode_206 - mtlrr11 - beqlr - li r0,0 - mtspr SPRN_PSSCR,r0 - mtspr SPRN_LPID,r0 - mtspr SPRN_PID,r0 - LOAD_REG_IMMEDIATE(r0, PCR_MASK) - mtspr SPRN_PCR,r0 - mfspr r3,SPRN_LPCR - LOAD_REG_IMMEDIATE(r4, LPCR_PECEDH | LPCR_PECE_HVEE | LPCR_HVICE | LPCR_HEIC) - or r3, r3, r4 -
[PATCH v3 1/2] powerpc/64: Set up a kernel stack for secondaries before cpu_restore()
Currently in generic_secondary_smp_init(), cur_cpu_spec->cpu_restore() is called before a stack has been set up in r1. This was previously fine as the cpu_restore() functions were implemented in assembly and did not use a stack. However commit 5a61ef74f269 ("powerpc/64s: Support new device tree binding for discovering CPU features") used __restore_cpu_cpufeatures() as the cpu_restore() function for a device-tree features based cputable entry. This is a C function and hence uses a stack in r1. generic_secondary_smp_init() is entered on the secondary cpus via the primary cpu using the OPAL call opal_start_cpu(). In OPAL, each hardware thread has its own stack. The OPAL call is ran in the primary's hardware thread. During the call, a job is scheduled on a secondary cpu that will start executing at the address of generic_secondary_smp_init(). Hence the value that will be left in r1 when the secondary cpu enters the kernel is part of that secondary cpu's individual OPAL stack. This means that __restore_cpu_cpufeatures() will write to that OPAL stack. This is not horribly bad as each hardware thread has its own stack and the call that enters the kernel from OPAL never returns, but it is still wrong and should be corrected. Create the temp kernel stack before calling cpu_restore(). As noted by mpe, for a kexec boot, the secondary CPUs are released from the spin loop at address 0x60 by smp_release_cpus() and then jump to generic_secondary_smp_init(). The call to smp_release_cpus() is in setup_arch(), and it comes before the call to emergency_stack_init(). emergency_stack_init() allocates an emergency stack in the PACA for each CPU. This address in the PACA is what is used to set up the temp kernel stack in generic_secondary_smp_init(). Move releasing the secondary CPUs to after the PACAs have been allocated an emergency stack, otherwise the PACA stack pointer will contain garbage and hence the temp kernel stack created from it will be broken. Fixes: 5a61ef74f269 ("powerpc/64s: Support new device tree binding for discovering CPU features") Signed-off-by: Jordan Niethe --- v2: Add more detail to the commit message v3: Release secondary CPUs after the emergency stack is created --- arch/powerpc/kernel/head_64.S | 8 arch/powerpc/kernel/setup-common.c | 6 -- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 0e05a9a47a4b..4b7f4c6c2600 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -420,6 +420,10 @@ generic_secondary_common_init: /* From now on, r24 is expected to be logical cpuid */ mr r24,r5 + /* Create a temp kernel stack for use before relocation is on. */ + ld r1,PACAEMERGSP(r13) + subir1,r1,STACK_FRAME_OVERHEAD + /* See if we need to call a cpu state restore handler */ LOAD_REG_ADDR(r23, cur_cpu_spec) ld r23,0(r23) @@ -448,10 +452,6 @@ generic_secondary_common_init: sync/* order paca.run and cur_cpu_spec */ isync /* In case code patching happened */ - /* Create a temp kernel stack for use before relocation is on. */ - ld r1,PACAEMERGSP(r13) - subir1,r1,STACK_FRAME_OVERHEAD - b __secondary_start #endif /* SMP */ diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index 808ec9fab605..fff714e36b37 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c @@ -919,8 +919,6 @@ void __init setup_arch(char **cmdline_p) /* On BookE, setup per-core TLB data structures. */ setup_tlb_core_data(); - - smp_release_cpus(); #endif /* Print various info about the machine that has been gathered so far. */ @@ -944,6 +942,10 @@ void __init setup_arch(char **cmdline_p) exc_lvl_early_init(); emergency_stack_init(); +#ifdef CONFIG_SMP + smp_release_cpus(); +#endif + initmem_init(); early_memtest(min_low_pfn << PAGE_SHIFT, max_low_pfn << PAGE_SHIFT); -- 2.17.1
Re: [PATCH v2 1/2] powerpc/64: Set up a kernel stack for secondaries before cpu_restore()
On Fri, Sep 18, 2020 at 5:21 PM Michael Ellerman wrote: > > Hi Jordan, > > Jordan Niethe writes: > > Currently in generic_secondary_smp_init(), cur_cpu_spec->cpu_restore() > > is called before a stack has been set up in r1. This was previously fine > > as the cpu_restore() functions were implemented in assembly and did not > > use a stack. However commit 5a61ef74f269 ("powerpc/64s: Support new > > device tree binding for discovering CPU features") used > > __restore_cpu_cpufeatures() as the cpu_restore() function for a > > device-tree features based cputable entry. This is a C function and > > hence uses a stack in r1. > > > > generic_secondary_smp_init() is entered on the secondary cpus via the > > primary cpu using the OPAL call opal_start_cpu(). In OPAL, each hardware > > thread has its own stack. The OPAL call is ran in the primary's hardware > > thread. During the call, a job is scheduled on a secondary cpu that will > > start executing at the address of generic_secondary_smp_init(). Hence > > the value that will be left in r1 when the secondary cpu enters the > > kernel is part of that secondary cpu's individual OPAL stack. This means > > that __restore_cpu_cpufeatures() will write to that OPAL stack. This is > > not horribly bad as each hardware thread has its own stack and the call > > that enters the kernel from OPAL never returns, but it is still wrong > > and should be corrected. > > > > Create the temp kernel stack before calling cpu_restore(). > > > > Fixes: 5a61ef74f269 ("powerpc/64s: Support new device tree binding for > > discovering CPU features") > > Signed-off-by: Jordan Niethe > > --- > > v2: Add more detail to the commit message > > --- > > arch/powerpc/kernel/head_64.S | 8 > > 1 file changed, 4 insertions(+), 4 deletions(-) > > Unfortunately this breaks booting via kexec. > > In that case the secondaries come in to 0x60 and spin until they're > released by smp_release_cpus(), which is before emergency_stack_init() > has run. That means they pick up a bad r1 value and crash/get stuck. > > I'm not sure what the best solution is. Would it be simplest to just call smp_release_cpus() after setting up the stack? > > I've thought in the past that it would be nicer if the CPU setup didn't > run until the secondary is told to start (via PACAPROCSTART), ie. more > the CPU setup call below there. > > But that opens the possibility that we run threads with different > settings of some SPRs until SMP bringup, and if the user has said not to > start secondaries then possibly for ever. And I haven't though hard > enough about whether that's actually problematic (running with different > SPR values). > > cheers > > > > diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S > > index 0e05a9a47a4b..4b7f4c6c2600 100644 > > --- a/arch/powerpc/kernel/head_64.S > > +++ b/arch/powerpc/kernel/head_64.S > > @@ -420,6 +420,10 @@ generic_secondary_common_init: > > /* From now on, r24 is expected to be logical cpuid */ > > mr r24,r5 > > > > + /* Create a temp kernel stack for use before relocation is on. */ > > + ld r1,PACAEMERGSP(r13) > > + subir1,r1,STACK_FRAME_OVERHEAD > > + > > /* See if we need to call a cpu state restore handler */ > > LOAD_REG_ADDR(r23, cur_cpu_spec) > > ld r23,0(r23) > > @@ -448,10 +452,6 @@ generic_secondary_common_init: > > sync/* order paca.run and cur_cpu_spec */ > > isync /* In case code patching happened */ > > > > - /* Create a temp kernel stack for use before relocation is on. */ > > - ld r1,PACAEMERGSP(r13) > > - subir1,r1,STACK_FRAME_OVERHEAD > > - > > b __secondary_start > > #endif /* SMP */ > > > > -- > > 2.17.1
[PATCH v2 2/2] powerpc/64s: Convert some cpu_setup() and cpu_restore() functions to C
The only thing keeping the cpu_setup() and cpu_restore() functions used in the cputable entries for Power7, Power8, Power9 and Power10 in assembly was cpu_restore() being called before there was a stack in generic_secondary_smp_init(). Commit ("powerpc/64: Set up a kernel stack for secondaries before cpu_restore()") means that it is now possible to use C. Rewrite the functions in C so they are a little bit easier to read. This is not changing their functionality. Signed-off-by: Jordan Niethe --- arch/powerpc/include/asm/cpu_setup_power.h | 12 + arch/powerpc/kernel/cpu_setup_power.S | 252 --- arch/powerpc/kernel/cpu_setup_power.c | 269 + arch/powerpc/kernel/cputable.c | 9 +- 4 files changed, 282 insertions(+), 260 deletions(-) create mode 100644 arch/powerpc/include/asm/cpu_setup_power.h delete mode 100644 arch/powerpc/kernel/cpu_setup_power.S create mode 100644 arch/powerpc/kernel/cpu_setup_power.c diff --git a/arch/powerpc/include/asm/cpu_setup_power.h b/arch/powerpc/include/asm/cpu_setup_power.h new file mode 100644 index ..24be9131f803 --- /dev/null +++ b/arch/powerpc/include/asm/cpu_setup_power.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2020 IBM Corporation + */ +void __setup_cpu_power7(unsigned long offset, struct cpu_spec *spec); +void __restore_cpu_power7(void); +void __setup_cpu_power8(unsigned long offset, struct cpu_spec *spec); +void __restore_cpu_power8(void); +void __setup_cpu_power9(unsigned long offset, struct cpu_spec *spec); +void __restore_cpu_power9(void); +void __setup_cpu_power10(unsigned long offset, struct cpu_spec *spec); +void __restore_cpu_power10(void); diff --git a/arch/powerpc/kernel/cpu_setup_power.S b/arch/powerpc/kernel/cpu_setup_power.S deleted file mode 100644 index 704e8b9501ee.. --- a/arch/powerpc/kernel/cpu_setup_power.S +++ /dev/null @@ -1,252 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * This file contains low level CPU setup functions. - *Copyright (C) 2003 Benjamin Herrenschmidt (b...@kernel.crashing.org) - */ - -#include -#include -#include -#include -#include -#include -#include - -/* Entry: r3 = crap, r4 = ptr to cputable entry - * - * Note that we can be called twice for pseudo-PVRs - */ -_GLOBAL(__setup_cpu_power7) - mflrr11 - bl __init_hvmode_206 - mtlrr11 - beqlr - li r0,0 - mtspr SPRN_LPID,r0 - LOAD_REG_IMMEDIATE(r0, PCR_MASK) - mtspr SPRN_PCR,r0 - mfspr r3,SPRN_LPCR - li r4,(LPCR_LPES1 >> LPCR_LPES_SH) - bl __init_LPCR_ISA206 - mtlrr11 - blr - -_GLOBAL(__restore_cpu_power7) - mflrr11 - mfmsr r3 - rldicl. r0,r3,4,63 - beqlr - li r0,0 - mtspr SPRN_LPID,r0 - LOAD_REG_IMMEDIATE(r0, PCR_MASK) - mtspr SPRN_PCR,r0 - mfspr r3,SPRN_LPCR - li r4,(LPCR_LPES1 >> LPCR_LPES_SH) - bl __init_LPCR_ISA206 - mtlrr11 - blr - -_GLOBAL(__setup_cpu_power8) - mflrr11 - bl __init_FSCR - bl __init_PMU - bl __init_PMU_ISA207 - bl __init_hvmode_206 - mtlrr11 - beqlr - li r0,0 - mtspr SPRN_LPID,r0 - LOAD_REG_IMMEDIATE(r0, PCR_MASK) - mtspr SPRN_PCR,r0 - mfspr r3,SPRN_LPCR - ori r3, r3, LPCR_PECEDH - li r4,0 /* LPES = 0 */ - bl __init_LPCR_ISA206 - bl __init_HFSCR - bl __init_PMU_HV - bl __init_PMU_HV_ISA207 - mtlrr11 - blr - -_GLOBAL(__restore_cpu_power8) - mflrr11 - bl __init_FSCR - bl __init_PMU - bl __init_PMU_ISA207 - mfmsr r3 - rldicl. r0,r3,4,63 - mtlrr11 - beqlr - li r0,0 - mtspr SPRN_LPID,r0 - LOAD_REG_IMMEDIATE(r0, PCR_MASK) - mtspr SPRN_PCR,r0 - mfspr r3,SPRN_LPCR - ori r3, r3, LPCR_PECEDH - li r4,0 /* LPES = 0 */ - bl __init_LPCR_ISA206 - bl __init_HFSCR - bl __init_PMU_HV - bl __init_PMU_HV_ISA207 - mtlrr11 - blr - -_GLOBAL(__setup_cpu_power10) - mflrr11 - bl __init_FSCR_power10 - bl __init_PMU - bl __init_PMU_ISA31 - b 1f - -_GLOBAL(__setup_cpu_power9) - mflrr11 - bl __init_FSCR_power9 - bl __init_PMU -1: bl __init_hvmode_206 - mtlrr11 - beqlr - li r0,0 - mtspr SPRN_PSSCR,r0 - mtspr SPRN_LPID,r0 - mtspr SPRN_PID,r0 - LOAD_REG_IMMEDIATE(r0, PCR_MASK) - mtspr SPRN_PCR,r0 - mfspr r3,SPRN_LPCR - LOAD_REG_IMMEDIATE(r4, LPCR_PECEDH | LPCR_PECE_HVEE | LPCR_HVICE | LPCR_HEIC) - or r3, r3, r4 -
[PATCH v2 1/2] powerpc/64: Set up a kernel stack for secondaries before cpu_restore()
Currently in generic_secondary_smp_init(), cur_cpu_spec->cpu_restore() is called before a stack has been set up in r1. This was previously fine as the cpu_restore() functions were implemented in assembly and did not use a stack. However commit 5a61ef74f269 ("powerpc/64s: Support new device tree binding for discovering CPU features") used __restore_cpu_cpufeatures() as the cpu_restore() function for a device-tree features based cputable entry. This is a C function and hence uses a stack in r1. generic_secondary_smp_init() is entered on the secondary cpus via the primary cpu using the OPAL call opal_start_cpu(). In OPAL, each hardware thread has its own stack. The OPAL call is ran in the primary's hardware thread. During the call, a job is scheduled on a secondary cpu that will start executing at the address of generic_secondary_smp_init(). Hence the value that will be left in r1 when the secondary cpu enters the kernel is part of that secondary cpu's individual OPAL stack. This means that __restore_cpu_cpufeatures() will write to that OPAL stack. This is not horribly bad as each hardware thread has its own stack and the call that enters the kernel from OPAL never returns, but it is still wrong and should be corrected. Create the temp kernel stack before calling cpu_restore(). Fixes: 5a61ef74f269 ("powerpc/64s: Support new device tree binding for discovering CPU features") Signed-off-by: Jordan Niethe --- v2: Add more detail to the commit message --- arch/powerpc/kernel/head_64.S | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 0e05a9a47a4b..4b7f4c6c2600 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -420,6 +420,10 @@ generic_secondary_common_init: /* From now on, r24 is expected to be logical cpuid */ mr r24,r5 + /* Create a temp kernel stack for use before relocation is on. */ + ld r1,PACAEMERGSP(r13) + subir1,r1,STACK_FRAME_OVERHEAD + /* See if we need to call a cpu state restore handler */ LOAD_REG_ADDR(r23, cur_cpu_spec) ld r23,0(r23) @@ -448,10 +452,6 @@ generic_secondary_common_init: sync/* order paca.run and cur_cpu_spec */ isync /* In case code patching happened */ - /* Create a temp kernel stack for use before relocation is on. */ - ld r1,PACAEMERGSP(r13) - subir1,r1,STACK_FRAME_OVERHEAD - b __secondary_start #endif /* SMP */ -- 2.17.1
[PATCH 2/2] powerpc/64s: Convert some cpu_setup() and cpu_restore() functions to C
The only thing keeping the cpu_setup() and cpu_restore() functions used in the cputable entries for Power7, Power8, Power9 and Power10 in assembly was cpu_restore() being called before there was a stack in generic_secondary_smp_init(). Commit ("powerpc/64: Set up a kernel stack for secondaries before cpu_restore()") means that it is now possible to use C. Rewrite the functions in C so they are a little bit easier to read. This is not changing their functionality. Signed-off-by: Jordan Niethe --- arch/powerpc/include/asm/cpu_setup_power.h | 12 + arch/powerpc/kernel/cpu_setup_power.S | 252 --- arch/powerpc/kernel/cpu_setup_power.c | 269 + arch/powerpc/kernel/cputable.c | 9 +- 4 files changed, 282 insertions(+), 260 deletions(-) create mode 100644 arch/powerpc/include/asm/cpu_setup_power.h delete mode 100644 arch/powerpc/kernel/cpu_setup_power.S create mode 100644 arch/powerpc/kernel/cpu_setup_power.c diff --git a/arch/powerpc/include/asm/cpu_setup_power.h b/arch/powerpc/include/asm/cpu_setup_power.h new file mode 100644 index ..24be9131f803 --- /dev/null +++ b/arch/powerpc/include/asm/cpu_setup_power.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2020 IBM Corporation + */ +void __setup_cpu_power7(unsigned long offset, struct cpu_spec *spec); +void __restore_cpu_power7(void); +void __setup_cpu_power8(unsigned long offset, struct cpu_spec *spec); +void __restore_cpu_power8(void); +void __setup_cpu_power9(unsigned long offset, struct cpu_spec *spec); +void __restore_cpu_power9(void); +void __setup_cpu_power10(unsigned long offset, struct cpu_spec *spec); +void __restore_cpu_power10(void); diff --git a/arch/powerpc/kernel/cpu_setup_power.S b/arch/powerpc/kernel/cpu_setup_power.S deleted file mode 100644 index 704e8b9501ee.. --- a/arch/powerpc/kernel/cpu_setup_power.S +++ /dev/null @@ -1,252 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * This file contains low level CPU setup functions. - *Copyright (C) 2003 Benjamin Herrenschmidt (b...@kernel.crashing.org) - */ - -#include -#include -#include -#include -#include -#include -#include - -/* Entry: r3 = crap, r4 = ptr to cputable entry - * - * Note that we can be called twice for pseudo-PVRs - */ -_GLOBAL(__setup_cpu_power7) - mflrr11 - bl __init_hvmode_206 - mtlrr11 - beqlr - li r0,0 - mtspr SPRN_LPID,r0 - LOAD_REG_IMMEDIATE(r0, PCR_MASK) - mtspr SPRN_PCR,r0 - mfspr r3,SPRN_LPCR - li r4,(LPCR_LPES1 >> LPCR_LPES_SH) - bl __init_LPCR_ISA206 - mtlrr11 - blr - -_GLOBAL(__restore_cpu_power7) - mflrr11 - mfmsr r3 - rldicl. r0,r3,4,63 - beqlr - li r0,0 - mtspr SPRN_LPID,r0 - LOAD_REG_IMMEDIATE(r0, PCR_MASK) - mtspr SPRN_PCR,r0 - mfspr r3,SPRN_LPCR - li r4,(LPCR_LPES1 >> LPCR_LPES_SH) - bl __init_LPCR_ISA206 - mtlrr11 - blr - -_GLOBAL(__setup_cpu_power8) - mflrr11 - bl __init_FSCR - bl __init_PMU - bl __init_PMU_ISA207 - bl __init_hvmode_206 - mtlrr11 - beqlr - li r0,0 - mtspr SPRN_LPID,r0 - LOAD_REG_IMMEDIATE(r0, PCR_MASK) - mtspr SPRN_PCR,r0 - mfspr r3,SPRN_LPCR - ori r3, r3, LPCR_PECEDH - li r4,0 /* LPES = 0 */ - bl __init_LPCR_ISA206 - bl __init_HFSCR - bl __init_PMU_HV - bl __init_PMU_HV_ISA207 - mtlrr11 - blr - -_GLOBAL(__restore_cpu_power8) - mflrr11 - bl __init_FSCR - bl __init_PMU - bl __init_PMU_ISA207 - mfmsr r3 - rldicl. r0,r3,4,63 - mtlrr11 - beqlr - li r0,0 - mtspr SPRN_LPID,r0 - LOAD_REG_IMMEDIATE(r0, PCR_MASK) - mtspr SPRN_PCR,r0 - mfspr r3,SPRN_LPCR - ori r3, r3, LPCR_PECEDH - li r4,0 /* LPES = 0 */ - bl __init_LPCR_ISA206 - bl __init_HFSCR - bl __init_PMU_HV - bl __init_PMU_HV_ISA207 - mtlrr11 - blr - -_GLOBAL(__setup_cpu_power10) - mflrr11 - bl __init_FSCR_power10 - bl __init_PMU - bl __init_PMU_ISA31 - b 1f - -_GLOBAL(__setup_cpu_power9) - mflrr11 - bl __init_FSCR_power9 - bl __init_PMU -1: bl __init_hvmode_206 - mtlrr11 - beqlr - li r0,0 - mtspr SPRN_PSSCR,r0 - mtspr SPRN_LPID,r0 - mtspr SPRN_PID,r0 - LOAD_REG_IMMEDIATE(r0, PCR_MASK) - mtspr SPRN_PCR,r0 - mfspr r3,SPRN_LPCR - LOAD_REG_IMMEDIATE(r4, LPCR_PECEDH | LPCR_PECE_HVEE | LPCR_HVICE | LPCR_HEIC) - or r3, r3, r4 -
[PATCH 1/2] powerpc/64: Set up a kernel stack for secondaries before cpu_restore()
Currently in generic_secondary_smp_init(), cur_cpu_spec->cpu_restore() is called before a stack has been set up in r1. This was previously fine as the cpu_restore() functions were implemented in assembly and did not use a stack. However commit 5a61ef74f269 ("powerpc/64s: Support new device tree binding for discovering CPU features") used __restore_cpu_cpufeatures() as the cpu_restore() function for a device-tree features based cputable entry. This is a nonleaf C function and hence requires a stack in r1. Create the temp kernel stack before calling cpu_restore(). Fixes: 5a61ef74f269 ("powerpc/64s: Support new device tree binding for discovering CPU features") Signed-off-by: Jordan Niethe --- arch/powerpc/kernel/head_64.S | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 0e05a9a47a4b..4b7f4c6c2600 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -420,6 +420,10 @@ generic_secondary_common_init: /* From now on, r24 is expected to be logical cpuid */ mr r24,r5 + /* Create a temp kernel stack for use before relocation is on. */ + ld r1,PACAEMERGSP(r13) + subir1,r1,STACK_FRAME_OVERHEAD + /* See if we need to call a cpu state restore handler */ LOAD_REG_ADDR(r23, cur_cpu_spec) ld r23,0(r23) @@ -448,10 +452,6 @@ generic_secondary_common_init: sync/* order paca.run and cur_cpu_spec */ isync /* In case code patching happened */ - /* Create a temp kernel stack for use before relocation is on. */ - ld r1,PACAEMERGSP(r13) - subir1,r1,STACK_FRAME_OVERHEAD - b __secondary_start #endif /* SMP */ -- 2.17.1
Re: [RFC PATCH 2/2] KVM: PPC: Book3S HV: Support prefixed instructions
On Wed, Sep 2, 2020 at 4:18 PM Paul Mackerras wrote: > > On Thu, Aug 20, 2020 at 01:39:22PM +1000, Jordan Niethe wrote: > > There are two main places where instructions are loaded from the guest: > > * Emulate loadstore - such as when performing MMIO emulation > > triggered by an HDSI > > * After an HV emulation assistance interrupt (e40) > > > > If it is a prefixed instruction that triggers these cases, its suffix > > must be loaded. Use the SRR1_PREFIX bit to decide if a suffix needs to > > be loaded. Make sure if this bit is set inject_interrupt() also sets it > > when giving an interrupt to the guest. > > > > ISA v3.10 extends the Hypervisor Emulation Instruction Register (HEIR) > > to 64 bits long to accommodate prefixed instructions. For interrupts > > caused by a word instruction the instruction is loaded into bits 32:63 > > and bits 0:31 are zeroed. When caused by a prefixed instruction the > > prefix and suffix are loaded into bits 0:63. > > > > Signed-off-by: Jordan Niethe > > --- > > arch/powerpc/kvm/book3s.c | 15 +-- > > arch/powerpc/kvm/book3s_64_mmu_hv.c | 10 +++--- > > arch/powerpc/kvm/book3s_hv_builtin.c| 3 +++ > > arch/powerpc/kvm/book3s_hv_rmhandlers.S | 14 ++ > > 4 files changed, 37 insertions(+), 5 deletions(-) > > > > diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c > > index 70d8967acc9b..18b1928a571b 100644 > > --- a/arch/powerpc/kvm/book3s.c > > +++ b/arch/powerpc/kvm/book3s.c > > @@ -456,13 +456,24 @@ int kvmppc_load_last_inst(struct kvm_vcpu *vcpu, > > { > > ulong pc = kvmppc_get_pc(vcpu); > > u32 word; > > + u64 doubleword; > > int r; > > > > if (type == INST_SC) > > pc -= 4; > > > > - r = kvmppc_ld(vcpu, , sizeof(u32), , false); > > - *inst = ppc_inst(word); > > + if ((kvmppc_get_msr(vcpu) & SRR1_PREFIXED)) { > > + r = kvmppc_ld(vcpu, , sizeof(u64), , false); > > Should we also have a check here that the doubleword is not crossing a > page boundary? I can't think of a way to get this code to cross a > page boundary, assuming the hardware is working correctly, but it > makes me just a little nervous. I didn't think it could happen but I will add a check to be safe. > > > +#ifdef CONFIG_CPU_LITTLE_ENDIAN > > + *inst = ppc_inst_prefix(doubleword & 0x, doubleword > > >> 32); > > +#else > > + *inst = ppc_inst_prefix(doubleword >> 32, doubleword & > > 0x); > > +#endif > > Ick. Is there a cleaner way to do this? Would it be nicer to read the prefix as u32 then the suffix as a u32 too? > > > + } else { > > + r = kvmppc_ld(vcpu, , sizeof(u32), , false); > > + *inst = ppc_inst(word); > > + } > > + > > if (r == EMULATE_DONE) > > return r; > > else > > diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c > > b/arch/powerpc/kvm/book3s_64_mmu_hv.c > > index 775ce41738ce..0802471f4856 100644 > > --- a/arch/powerpc/kvm/book3s_64_mmu_hv.c > > +++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c > > @@ -411,9 +411,13 @@ static int instruction_is_store(struct ppc_inst instr) > > unsigned int mask; > > > > mask = 0x1000; > > - if ((ppc_inst_val(instr) & 0xfc00) == 0x7c00) > > - mask = 0x100; /* major opcode 31 */ > > - return (ppc_inst_val(instr) & mask) != 0; > > + if (ppc_inst_prefixed(instr)) { > > + return (ppc_inst_suffix(instr) & mask) != 0; > > + } else { > > + if ((ppc_inst_val(instr) & 0xfc00) == 0x7c00) > > + mask = 0x100; /* major opcode 31 */ > > + return (ppc_inst_val(instr) & mask) != 0; > > + } > > The way the code worked before, the mask depended on whether the > instruction was a D-form (or DS-form or other variant) instruction, > where you can tell loads and stores apart by looking at the major > opcode, or an X-form instruction, where you look at the minor opcode. > > Now we are only looking at the minor opcode if it is not a prefixed > instruction. Are there no X-form prefixed loads or stores? I could not see an X-form load/stores so I went with just that. But checking the ISA it does mention "..X-form instructions that are preceded by an MLS-form or MMLS-form prefix..." so I shall use the other mask too. > > Paul. Thank you for the comments and suggestions.
Re: [RFC PATCH 1/2] KVM: PPC: Use the ppc_inst type
On Wed, Sep 2, 2020 at 4:18 PM Paul Mackerras wrote: > > On Thu, Aug 20, 2020 at 01:39:21PM +1000, Jordan Niethe wrote: > > The ppc_inst type was added to help cope with the addition of prefixed > > instructions to the ISA. Convert KVM to use this new type for dealing > > wiht instructions. For now do not try to add further support for > > prefixed instructions. > > This change does seem to splatter itself across a lot of code that > mostly or exclusively runs on machines which are not POWER10 and will > never need to handle prefixed instructions, unfortunately. I wonder > if there is a less invasive way to approach this. Something less invasive would be good. > > In particular we are inflicting this 64-bit struct on 32-bit platforms > unnecessarily (I assume, correct me if I am wrong here). No, that is something that I wanted to to avoid, on 32 bit platforms it is a 32bit struct: struct ppc_inst { u32 val; #ifdef CONFIG_PPC64 u32 suffix; #endif } __packed; > > How would it be to do something like: > > typedef unsigned long ppc_inst_t; > > so it is 32 bits on 32-bit platforms and 64 bits on 64-bit platforms, > and then use that instead of 'struct ppc_inst'? You would still need > to change the function declarations but I think most of the function > bodies would not need to be changed. In particular you would avoid a > lot of the churn related to having to add ppc_inst_val() and suchlike. Would the idea be to get rid of `struct ppc_inst` entirely or just not use it in kvm? In an earlier series I did something similar (at least code shared between 32bit and 64bit would need helpers, but 32bit only code need not change): #ifdef __powerpc64__ typedef struct ppc_inst { union { struct { u32 word; u32 pad; } __packed; struct { u32 prefix; u32 suffix; } __packed; }; } ppc_inst; #else /* !__powerpc64__ */ typedef u32 ppc_inst; #endif However mpe wanted to avoid using a typedef (https://patchwork.ozlabs.org/comment/2391845/) We did also talk about just using a u64 for instructions (https://lore.kernel.org/linuxppc-dev/1585028462.t27rstc2uf.astr...@bobo.none/) but the concern was that as prefixed instructions act as two separate u32s (prefix is always before the suffix regardless of endianess) keeping it as a u64 would lead to lot of macros and potential confusion. But it does seem if that can avoid a lot of needless churn it might worth the trade off. > > > -static inline unsigned make_dsisr(unsigned instr) > > +static inline unsigned make_dsisr(struct ppc_inst instr) > > { > > unsigned dsisr; > > + u32 word = ppc_inst_val(instr); > > > > > > /* bits 6:15 --> 22:31 */ > > - dsisr = (instr & 0x03ff) >> 16; > > + dsisr = (word & 0x03ff) >> 16; > > > > if (IS_XFORM(instr)) { > > /* bits 29:30 --> 15:16 */ > > - dsisr |= (instr & 0x0006) << 14; > > + dsisr |= (word & 0x0006) << 14; > > /* bit 25 -->17 */ > > - dsisr |= (instr & 0x0040) << 8; > > + dsisr |= (word & 0x0040) << 8; > > /* bits 21:24 --> 18:21 */ > > - dsisr |= (instr & 0x0780) << 3; > > + dsisr |= (word & 0x0780) << 3; > > } else { > > /* bit 5 -->17 */ > > - dsisr |= (instr & 0x0400) >> 12; > > + dsisr |= (word & 0x0400) >> 12; > > /* bits 1: 4 --> 18:21 */ > > - dsisr |= (instr & 0x7800) >> 17; > > + dsisr |= (word & 0x7800) >> 17; > > /* bits 30:31 --> 12:13 */ > > if (IS_DSFORM(instr)) > > - dsisr |= (instr & 0x0003) << 18; > > + dsisr |= (word & 0x0003) << 18; > > Here I would have done something like: > > > -static inline unsigned make_dsisr(unsigned instr) > > +static inline unsigned make_dsisr(struct ppc_inst pi) > > { > > unsigned dsisr; > > + u32 instr = ppc_inst_val(pi); > > and left the rest of the function unchanged. That is better. > > At first I wondered why we still had that function, since IBM Power > CPUs have not set DSISR on an alignment interrupt since POWER3 days. > It turns out it this function is used by PR KVM when it is emulating > one of the old 32-bit PowerPC CPUs (601, 603, 604, 750, 7450 etc.). > > > diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c > > Despite the file name, this code is not used on IBM Power servers. > It is for platforms which run under an ePAPR (not server PAPR) > hypervisor (which would be a KVM variant, but generally book E KVM not > book 3S). > > Paul.
Re: [PATCH v2] powerpc: Update documentation of ISA versions for Power10
On Thu, Aug 27, 2020 at 2:49 PM Christophe Leroy wrote: > > > > Le 27/08/2020 à 06:05, Jordan Niethe a écrit : > > Update the CPU to ISA Version Mapping document to include Power10 and > > ISA v3.1. > > Maybe Documentation/powerpc/cpu_families.rst should be updated as well. Good idea it still needs Power9 too. > > Christophe > > > > > > > Signed-off-by: Jordan Niethe > > --- > > v2: Transactional Memory = No > > --- > > Documentation/powerpc/isa-versions.rst | 4 > > 1 file changed, 4 insertions(+) > > > > diff --git a/Documentation/powerpc/isa-versions.rst > > b/Documentation/powerpc/isa-versions.rst > > index a363d8c1603c..3873bbba183a 100644 > > --- a/Documentation/powerpc/isa-versions.rst > > +++ b/Documentation/powerpc/isa-versions.rst > > @@ -7,6 +7,7 @@ Mapping of some CPU versions to relevant ISA versions. > > = > > > > CPU Architecture version > > = > > > > +Power10 Power ISA v3.1 > > Power9Power ISA v3.0B > > Power8Power ISA v2.07 > > Power7Power ISA v2.06 > > @@ -32,6 +33,7 @@ Key Features > > == == > > CPUVMX (aka. Altivec) > > == == > > +Power10Yes > > Power9 Yes > > Power8 Yes > > Power7 Yes > > @@ -47,6 +49,7 @@ PPC970 Yes > > == > > CPUVSX > > == > > +Power10Yes > > Power9 Yes > > Power8 Yes > > Power7 Yes > > @@ -62,6 +65,7 @@ PPC970 No > > == > > CPUTransactional Memory > > == > > +Power10No (* see Power ISA v3.1 Appendix A.) > > Power9 Yes (* see transactional_memory.txt) > > Power8 Yes > > Power7 No > >
[PATCH v2] powerpc: Update documentation of ISA versions for Power10
Update the CPU to ISA Version Mapping document to include Power10 and ISA v3.1. Signed-off-by: Jordan Niethe --- v2: Transactional Memory = No --- Documentation/powerpc/isa-versions.rst | 4 1 file changed, 4 insertions(+) diff --git a/Documentation/powerpc/isa-versions.rst b/Documentation/powerpc/isa-versions.rst index a363d8c1603c..3873bbba183a 100644 --- a/Documentation/powerpc/isa-versions.rst +++ b/Documentation/powerpc/isa-versions.rst @@ -7,6 +7,7 @@ Mapping of some CPU versions to relevant ISA versions. = CPU Architecture version = +Power10 Power ISA v3.1 Power9Power ISA v3.0B Power8Power ISA v2.07 Power7Power ISA v2.06 @@ -32,6 +33,7 @@ Key Features == == CPUVMX (aka. Altivec) == == +Power10Yes Power9 Yes Power8 Yes Power7 Yes @@ -47,6 +49,7 @@ PPC970 Yes == CPUVSX == +Power10Yes Power9 Yes Power8 Yes Power7 Yes @@ -62,6 +65,7 @@ PPC970 No == CPUTransactional Memory == +Power10No (* see Power ISA v3.1 Appendix A.) Power9 Yes (* see transactional_memory.txt) Power8 Yes Power7 No -- 2.17.1
[PATCH] powerpc/64s: Remove TM from Power10 features
ISA v3.1 removes transactional memory and hence it should not be present in cpu_features or cpu_user_features2. Remove CPU_FTR_TM_COMP from CPU_FTRS_POWER10. Remove PPC_FEATURE2_HTM_COMP and PPC_FEATURE2_HTM_NOSC_COMP from COMMON_USER2_POWER10. Fixes: a3ea40d5c736 ("powerpc: Add POWER10 architected mode") Signed-off-by: Jordan Niethe --- arch/powerpc/include/asm/cputable.h | 2 +- arch/powerpc/kernel/cputable.c | 13 ++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h index fdddb822d564..5322fec6d413 100644 --- a/arch/powerpc/include/asm/cputable.h +++ b/arch/powerpc/include/asm/cputable.h @@ -478,7 +478,7 @@ static inline void cpu_feature_keys_init(void) { } CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \ CPU_FTR_CFAR | CPU_FTR_HVMODE | CPU_FTR_VMX_COPY | \ CPU_FTR_DBELL | CPU_FTR_HAS_PPR | CPU_FTR_ARCH_207S | \ - CPU_FTR_TM_COMP | CPU_FTR_ARCH_300 | CPU_FTR_ARCH_31 | \ + CPU_FTR_ARCH_300 | CPU_FTR_ARCH_31 | \ CPU_FTR_DAWR | CPU_FTR_DAWR1) #define CPU_FTRS_CELL (CPU_FTR_LWSYNC | \ CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 2f10a874e849..23f9bb51edc3 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -123,9 +123,16 @@ extern void __restore_cpu_e6500(void); PPC_FEATURE2_DARN | \ PPC_FEATURE2_SCV) #define COMMON_USER_POWER10COMMON_USER_POWER9 -#define COMMON_USER2_POWER10 (COMMON_USER2_POWER9 | \ -PPC_FEATURE2_ARCH_3_1 | \ -PPC_FEATURE2_MMA) +#define COMMON_USER2_POWER10 (PPC_FEATURE2_ARCH_3_1 | \ +PPC_FEATURE2_MMA | \ +PPC_FEATURE2_ARCH_3_00 | \ +PPC_FEATURE2_HAS_IEEE128 | \ +PPC_FEATURE2_DARN | \ +PPC_FEATURE2_SCV | \ +PPC_FEATURE2_ARCH_2_07 | \ +PPC_FEATURE2_DSCR | \ +PPC_FEATURE2_ISEL | PPC_FEATURE2_TAR | \ +PPC_FEATURE2_VEC_CRYPTO) #ifdef CONFIG_PPC_BOOK3E_64 #define COMMON_USER_BOOKE (COMMON_USER_PPC64 | PPC_FEATURE_BOOKE) -- 2.17.1
Re: [PATCH] selftests/powerpc: Fix prefixes in alignment_handler signal handler
On Mon, Aug 24, 2020 at 11:12 PM Jordan Niethe wrote: > > The signal handler in the alignment handler self test has the ability to > jump over the instruction that triggered the signal. It does this by > incrementing the PT_NIP in the user context by 4. If it were a prefixed > instruction this will mean that the suffix is then executed which is > incorrect. Instead check if the major opcode indicates a prefixed > instruction (e.g. it is 1) and if so increment PT_NIP by 8. > > If ISA v3.1 is not available treat it as a word instruction even if the > major opcode is 1. > > Fixes: 620a6473df36 ("selftests/powerpc: Add prefixed loads/stores to > alignment_handler test") > Signed-off-by: Jordan Niethe > --- > .../selftests/powerpc/alignment/alignment_handler.c | 11 ++- > 1 file changed, 10 insertions(+), 1 deletion(-) > > diff --git a/tools/testing/selftests/powerpc/alignment/alignment_handler.c > b/tools/testing/selftests/powerpc/alignment/alignment_handler.c > index 55ef15184057..c197ff828120 100644 > --- a/tools/testing/selftests/powerpc/alignment/alignment_handler.c > +++ b/tools/testing/selftests/powerpc/alignment/alignment_handler.c > @@ -64,12 +64,14 @@ int bufsize; > int debug; > int testing; > volatile int gotsig; > +bool haveprefixes; > char *cipath = "/dev/fb0"; > long cioffset; > > void sighandler(int sig, siginfo_t *info, void *ctx) > { > ucontext_t *ucp = ctx; > + u32 inst; Oh this should be befine __powerpc64__/CONFIG_PPC64 (thank you patchwork). > > if (!testing) { > signal(sig, SIG_DFL); > @@ -77,7 +79,12 @@ void sighandler(int sig, siginfo_t *info, void *ctx) > } > gotsig = sig; > #ifdef __powerpc64__ > - ucp->uc_mcontext.gp_regs[PT_NIP] += 4; > + if (haveprefixes) { > + inst = *(u32 *)ucp->uc_mcontext.gp_regs[PT_NIP]; > + ucp->uc_mcontext.gp_regs[PT_NIP] += ((inst >> 26 == 1) ? 8 : > 4); > + } else { > + ucp->uc_mcontext.gp_regs[PT_NIP] += 4; > + } > #else > ucp->uc_mcontext.uc_regs->gregs[PT_NIP] += 4; > #endif > @@ -648,6 +655,8 @@ int main(int argc, char *argv[]) > exit(1); > } > > + haveprefixes = have_hwcap2(PPC_FEATURE2_ARCH_3_1); > + > rc |= test_harness(test_alignment_handler_vsx_206, >"test_alignment_handler_vsx_206"); > rc |= test_harness(test_alignment_handler_vsx_207, > -- > 2.17.1 >
Re: [PATCH] powerpc: Update documentation of ISA versions for Power10
On Tue, Aug 25, 2020 at 10:41 PM Gabriel Paubert wrote: > > On Tue, Aug 25, 2020 at 09:45:07PM +1000, Jordan Niethe wrote: > > Update the CPU to ISA Version Mapping document to include Power10 and > > ISA v3.1. > > > > Signed-off-by: Jordan Niethe > > --- > > Documentation/powerpc/isa-versions.rst | 4 > > 1 file changed, 4 insertions(+) > > > > diff --git a/Documentation/powerpc/isa-versions.rst > > b/Documentation/powerpc/isa-versions.rst > > index a363d8c1603c..72aff1eaaea1 100644 > > --- a/Documentation/powerpc/isa-versions.rst > > +++ b/Documentation/powerpc/isa-versions.rst > > @@ -7,6 +7,7 @@ Mapping of some CPU versions to relevant ISA versions. > > = > > > > CPU Architecture version > > = > > > > +Power10 Power ISA v3.1 > > Power9Power ISA v3.0B > > Power8Power ISA v2.07 > > Power7Power ISA v2.06 > > @@ -32,6 +33,7 @@ Key Features > > == == > > CPUVMX (aka. Altivec) > > == == > > +Power10Yes > > Power9 Yes > > Power8 Yes > > Power7 Yes > > @@ -47,6 +49,7 @@ PPC970 Yes > > == > > CPUVSX > > == > > +Power10Yes > > Power9 Yes > > Power8 Yes > > Power7 Yes > > @@ -62,6 +65,7 @@ PPC970 No > > == > > CPUTransactional Memory > > == > > +Power10Yes > > Power9 Yes (* see transactional_memory.txt) > > Power8 Yes > > Power7 No > > Huh? > > Transactional memory has been removed from the architecture for Power10. Yeah you're right, I confused myself looking at CPU_FTRS_POWER10... #define CPU_FTRS_POWER10 (CPU_FTR_LWSYNC | \ CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | CPU_FTR_ARCH_206 |\ CPU_FTR_MMCRA | CPU_FTR_SMT | \ CPU_FTR_COHERENT_ICACHE | \ CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \ CPU_FTR_DSCR | \ CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \ CPU_FTR_CFAR | CPU_FTR_HVMODE | CPU_FTR_VMX_COPY | \ CPU_FTR_DBELL | CPU_FTR_HAS_PPR | CPU_FTR_ARCH_207S | \ CPU_FTR_TM_COMP | CPU_FTR_ARCH_300 | CPU_FTR_ARCH_31 | \ CPU_FTR_DAWR | CPU_FTR_DAWR1) CPU_FTR_TM_COMP should not be in there. > > Gabriel > >
[PATCH] powerpc: Update documentation of ISA versions for Power10
Update the CPU to ISA Version Mapping document to include Power10 and ISA v3.1. Signed-off-by: Jordan Niethe --- Documentation/powerpc/isa-versions.rst | 4 1 file changed, 4 insertions(+) diff --git a/Documentation/powerpc/isa-versions.rst b/Documentation/powerpc/isa-versions.rst index a363d8c1603c..72aff1eaaea1 100644 --- a/Documentation/powerpc/isa-versions.rst +++ b/Documentation/powerpc/isa-versions.rst @@ -7,6 +7,7 @@ Mapping of some CPU versions to relevant ISA versions. = CPU Architecture version = +Power10 Power ISA v3.1 Power9Power ISA v3.0B Power8Power ISA v2.07 Power7Power ISA v2.06 @@ -32,6 +33,7 @@ Key Features == == CPUVMX (aka. Altivec) == == +Power10Yes Power9 Yes Power8 Yes Power7 Yes @@ -47,6 +49,7 @@ PPC970 Yes == CPUVSX == +Power10Yes Power9 Yes Power8 Yes Power7 Yes @@ -62,6 +65,7 @@ PPC970 No == CPUTransactional Memory == +Power10Yes Power9 Yes (* see transactional_memory.txt) Power8 Yes Power7 No -- 2.17.1
[PATCH] powerpc/boot: Update Makefile comment for 64bit wrapper
As of commit 147c05168fc8 ("powerpc/boot: Add support for 64bit little endian wrapper") the comment in the Makefile is misleading. The wrapper packaging 64bit kernel may built as a 32 or 64 bit elf. Update the comment to reflect this. Signed-off-by: Jordan Niethe --- arch/powerpc/boot/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index b88fd27a45f0..f8ce6d2dde7b 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile @@ -7,7 +7,7 @@ # Based on coffboot by Paul Mackerras # Simplified for ppc64 by Todd Inglett # -# NOTE:this code is built for 32 bit in ELF32 format even though +# NOTE:this code may be built for 32 bit in ELF32 format even though # it packages a 64 bit kernel. We do this to simplify the # bootloader and increase compatibility with OpenFirmware. # -- 2.17.1
[PATCH] selftests/powerpc: Fix prefixes in alignment_handler signal handler
The signal handler in the alignment handler self test has the ability to jump over the instruction that triggered the signal. It does this by incrementing the PT_NIP in the user context by 4. If it were a prefixed instruction this will mean that the suffix is then executed which is incorrect. Instead check if the major opcode indicates a prefixed instruction (e.g. it is 1) and if so increment PT_NIP by 8. If ISA v3.1 is not available treat it as a word instruction even if the major opcode is 1. Fixes: 620a6473df36 ("selftests/powerpc: Add prefixed loads/stores to alignment_handler test") Signed-off-by: Jordan Niethe --- .../selftests/powerpc/alignment/alignment_handler.c | 11 ++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/powerpc/alignment/alignment_handler.c b/tools/testing/selftests/powerpc/alignment/alignment_handler.c index 55ef15184057..c197ff828120 100644 --- a/tools/testing/selftests/powerpc/alignment/alignment_handler.c +++ b/tools/testing/selftests/powerpc/alignment/alignment_handler.c @@ -64,12 +64,14 @@ int bufsize; int debug; int testing; volatile int gotsig; +bool haveprefixes; char *cipath = "/dev/fb0"; long cioffset; void sighandler(int sig, siginfo_t *info, void *ctx) { ucontext_t *ucp = ctx; + u32 inst; if (!testing) { signal(sig, SIG_DFL); @@ -77,7 +79,12 @@ void sighandler(int sig, siginfo_t *info, void *ctx) } gotsig = sig; #ifdef __powerpc64__ - ucp->uc_mcontext.gp_regs[PT_NIP] += 4; + if (haveprefixes) { + inst = *(u32 *)ucp->uc_mcontext.gp_regs[PT_NIP]; + ucp->uc_mcontext.gp_regs[PT_NIP] += ((inst >> 26 == 1) ? 8 : 4); + } else { + ucp->uc_mcontext.gp_regs[PT_NIP] += 4; + } #else ucp->uc_mcontext.uc_regs->gregs[PT_NIP] += 4; #endif @@ -648,6 +655,8 @@ int main(int argc, char *argv[]) exit(1); } + haveprefixes = have_hwcap2(PPC_FEATURE2_ARCH_3_1); + rc |= test_harness(test_alignment_handler_vsx_206, "test_alignment_handler_vsx_206"); rc |= test_harness(test_alignment_handler_vsx_207, -- 2.17.1
[RFC PATCH 2/2] KVM: PPC: Book3S HV: Support prefixed instructions
There are two main places where instructions are loaded from the guest: * Emulate loadstore - such as when performing MMIO emulation triggered by an HDSI * After an HV emulation assistance interrupt (e40) If it is a prefixed instruction that triggers these cases, its suffix must be loaded. Use the SRR1_PREFIX bit to decide if a suffix needs to be loaded. Make sure if this bit is set inject_interrupt() also sets it when giving an interrupt to the guest. ISA v3.10 extends the Hypervisor Emulation Instruction Register (HEIR) to 64 bits long to accommodate prefixed instructions. For interrupts caused by a word instruction the instruction is loaded into bits 32:63 and bits 0:31 are zeroed. When caused by a prefixed instruction the prefix and suffix are loaded into bits 0:63. Signed-off-by: Jordan Niethe --- arch/powerpc/kvm/book3s.c | 15 +-- arch/powerpc/kvm/book3s_64_mmu_hv.c | 10 +++--- arch/powerpc/kvm/book3s_hv_builtin.c| 3 +++ arch/powerpc/kvm/book3s_hv_rmhandlers.S | 14 ++ 4 files changed, 37 insertions(+), 5 deletions(-) diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c index 70d8967acc9b..18b1928a571b 100644 --- a/arch/powerpc/kvm/book3s.c +++ b/arch/powerpc/kvm/book3s.c @@ -456,13 +456,24 @@ int kvmppc_load_last_inst(struct kvm_vcpu *vcpu, { ulong pc = kvmppc_get_pc(vcpu); u32 word; + u64 doubleword; int r; if (type == INST_SC) pc -= 4; - r = kvmppc_ld(vcpu, , sizeof(u32), , false); - *inst = ppc_inst(word); + if ((kvmppc_get_msr(vcpu) & SRR1_PREFIXED)) { + r = kvmppc_ld(vcpu, , sizeof(u64), , false); +#ifdef CONFIG_CPU_LITTLE_ENDIAN + *inst = ppc_inst_prefix(doubleword & 0x, doubleword >> 32); +#else + *inst = ppc_inst_prefix(doubleword >> 32, doubleword & 0x); +#endif + } else { + r = kvmppc_ld(vcpu, , sizeof(u32), , false); + *inst = ppc_inst(word); + } + if (r == EMULATE_DONE) return r; else diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c index 775ce41738ce..0802471f4856 100644 --- a/arch/powerpc/kvm/book3s_64_mmu_hv.c +++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c @@ -411,9 +411,13 @@ static int instruction_is_store(struct ppc_inst instr) unsigned int mask; mask = 0x1000; - if ((ppc_inst_val(instr) & 0xfc00) == 0x7c00) - mask = 0x100; /* major opcode 31 */ - return (ppc_inst_val(instr) & mask) != 0; + if (ppc_inst_prefixed(instr)) { + return (ppc_inst_suffix(instr) & mask) != 0; + } else { + if ((ppc_inst_val(instr) & 0xfc00) == 0x7c00) + mask = 0x100; /* major opcode 31 */ + return (ppc_inst_val(instr) & mask) != 0; + } } int kvmppc_hv_emulate_mmio(struct kvm_vcpu *vcpu, diff --git a/arch/powerpc/kvm/book3s_hv_builtin.c b/arch/powerpc/kvm/book3s_hv_builtin.c index 073617ce83e0..41e07e63104b 100644 --- a/arch/powerpc/kvm/book3s_hv_builtin.c +++ b/arch/powerpc/kvm/book3s_hv_builtin.c @@ -807,6 +807,9 @@ static void inject_interrupt(struct kvm_vcpu *vcpu, int vec, u64 srr1_flags) new_pc += 0xC0004000ULL; } + if (msr & SRR1_PREFIXED) + srr1_flags |= SRR1_PREFIXED; + kvmppc_set_srr0(vcpu, pc); kvmppc_set_srr1(vcpu, (msr & SRR1_MSR_BITS) | srr1_flags); kvmppc_set_pc(vcpu, new_pc); diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S index 4853b3444c5f..f2a609413621 100644 --- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S +++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S @@ -1365,6 +1365,16 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR) cmpwi r12,BOOK3S_INTERRUPT_H_EMUL_ASSIST bne 11f mfspr r3,SPRN_HEIR + andis. r0,r11,SRR1_PREFIXED@h + cmpwi r0,0 + beq 12f + rldicl r4,r3,0,32 /* Suffix */ + srdir3,r3,32/* Prefix */ + b 11f +12: +BEGIN_FTR_SECTION + rldicl r3,r3,0,32 /* Word */ +END_FTR_SECTION_IFSET(CPU_FTR_ARCH_31) 11:stw r3,VCPU_HEIR(r9) stw r4,VCPU_HEIR+4(r9) @@ -2175,6 +2185,10 @@ fast_interrupt_c_return: ori r4, r3, MSR_DR /* Enable paging for data */ mtmsrd r4 lwz r8, 0(r10) + andis. r7, r11, SRR1_PREFIXED@h + cmpwi r7,0 + beq +4 + lwz r5, 4(r10) mtmsrd r3 /* Store the result */ -- 2.17.1
[RFC PATCH 1/2] KVM: PPC: Use the ppc_inst type
The ppc_inst type was added to help cope with the addition of prefixed instructions to the ISA. Convert KVM to use this new type for dealing wiht instructions. For now do not try to add further support for prefixed instructions. Signed-off-by: Jordan Niethe --- arch/powerpc/include/asm/disassemble.h| 80 +- arch/powerpc/include/asm/kvm_book3s.h | 4 +- arch/powerpc/include/asm/kvm_book3s_asm.h | 3 +- arch/powerpc/include/asm/kvm_host.h | 5 +- arch/powerpc/include/asm/kvm_ppc.h| 14 ++-- arch/powerpc/kernel/asm-offsets.c | 2 + arch/powerpc/kernel/kvm.c | 99 +++ arch/powerpc/kvm/book3s.c | 6 +- arch/powerpc/kvm/book3s.h | 2 +- arch/powerpc/kvm/book3s_64_mmu_hv.c | 8 +- arch/powerpc/kvm/book3s_emulate.c | 30 +++ arch/powerpc/kvm/book3s_hv.c | 19 ++--- arch/powerpc/kvm/book3s_hv_nested.c | 4 +- arch/powerpc/kvm/book3s_hv_rmhandlers.S | 5 ++ arch/powerpc/kvm/book3s_hv_tm.c | 17 ++-- arch/powerpc/kvm/book3s_hv_tm_builtin.c | 12 +-- arch/powerpc/kvm/book3s_paired_singles.c | 15 ++-- arch/powerpc/kvm/book3s_pr.c | 20 ++--- arch/powerpc/kvm/booke.c | 18 ++--- arch/powerpc/kvm/booke.h | 4 +- arch/powerpc/kvm/booke_emulate.c | 4 +- arch/powerpc/kvm/e500_emulate.c | 6 +- arch/powerpc/kvm/e500_mmu_host.c | 6 +- arch/powerpc/kvm/emulate.c| 15 ++-- arch/powerpc/kvm/emulate_loadstore.c | 8 +- arch/powerpc/kvm/powerpc.c| 4 +- arch/powerpc/kvm/trace.h | 9 ++- arch/powerpc/kvm/trace_booke.h| 8 +- arch/powerpc/kvm/trace_pr.h | 8 +- arch/powerpc/lib/inst.c | 4 +- arch/powerpc/lib/sstep.c | 4 +- arch/powerpc/sysdev/fsl_pci.c | 4 +- 32 files changed, 237 insertions(+), 210 deletions(-) diff --git a/arch/powerpc/include/asm/disassemble.h b/arch/powerpc/include/asm/disassemble.h index 8d2ebc36d5e3..91dbe8e5cd13 100644 --- a/arch/powerpc/include/asm/disassemble.h +++ b/arch/powerpc/include/asm/disassemble.h @@ -10,75 +10,82 @@ #define __ASM_PPC_DISASSEMBLE_H__ #include +#include -static inline unsigned int get_op(u32 inst) +static inline unsigned int get_op(struct ppc_inst inst) { - return inst >> 26; + return ppc_inst_val(inst) >> 26; } -static inline unsigned int get_xop(u32 inst) +static inline unsigned int get_xop(struct ppc_inst inst) { - return (inst >> 1) & 0x3ff; + return (ppc_inst_val(inst) >> 1) & 0x3ff; } -static inline unsigned int get_sprn(u32 inst) +static inline unsigned int get_sprn(struct ppc_inst inst) { - return ((inst >> 16) & 0x1f) | ((inst >> 6) & 0x3e0); + u32 word = ppc_inst_val(inst); + + return ((word >> 16) & 0x1f) | ((word >> 6) & 0x3e0); } -static inline unsigned int get_dcrn(u32 inst) +static inline unsigned int get_dcrn(struct ppc_inst inst) { - return ((inst >> 16) & 0x1f) | ((inst >> 6) & 0x3e0); + u32 word = ppc_inst_val(inst); + + return ((word >> 16) & 0x1f) | ((word >> 6) & 0x3e0); } -static inline unsigned int get_tmrn(u32 inst) +static inline unsigned int get_tmrn(struct ppc_inst inst) { - return ((inst >> 16) & 0x1f) | ((inst >> 6) & 0x3e0); + u32 word = ppc_inst_val(inst); + + return ((word >> 16) & 0x1f) | ((word >> 6) & 0x3e0); } -static inline unsigned int get_rt(u32 inst) +static inline unsigned int get_rt(struct ppc_inst inst) { - return (inst >> 21) & 0x1f; + return (ppc_inst_val(inst) >> 21) & 0x1f; } -static inline unsigned int get_rs(u32 inst) +static inline unsigned int get_rs(struct ppc_inst inst) { - return (inst >> 21) & 0x1f; + return (ppc_inst_val(inst) >> 21) & 0x1f; } -static inline unsigned int get_ra(u32 inst) +static inline unsigned int get_ra(struct ppc_inst inst) { - return (inst >> 16) & 0x1f; + return (ppc_inst_val(inst) >> 16) & 0x1f; } -static inline unsigned int get_rb(u32 inst) +static inline unsigned int get_rb(struct ppc_inst inst) { - return (inst >> 11) & 0x1f; + return (ppc_inst_val(inst) >> 11) & 0x1f; } -static inline unsigned int get_rc(u32 inst) +static inline unsigned int get_rc(struct ppc_inst inst) { - return inst & 0x1; + return ppc_inst_val(inst) & 0x1; } -static inline unsigned int get_ws(u32 inst) +static inline unsigned int get_ws(struct ppc_inst inst) { - return (inst >> 11) & 0x1f; + return (ppc_inst_val(inst) >> 11) & 0x1f; } -static inline unsigned int get_d(u32 inst) +st
Re: [v4] powerpc/perf: Initialize power10 PMU registers in cpu setup routine
On Thu, Jul 23, 2020 at 5:32 PM Athira Rajeev wrote: > > Initialize Monitor Mode Control Register 3 (MMCR3) > SPR which is new in power10. For PowerISA v3.1, BHRB disable > is controlled via Monitor Mode Control Register A (MMCRA) bit, > namely "BHRB Recording Disable (BHRBRD)". This patch also initializes > MMCRA BHRBRD to disable BHRB feature at boot for power10. > > Signed-off-by: Athira Rajeev Reviewed-by: Jordan Niethe > --- > Dependency: > - On power10 PMU base enablement series V3: > https://patchwork.ozlabs.org/project/linuxppc-dev/list/?series=190462 > > Changes from v3 -> v4 > - Addressed review comments from Jordan and Michael Ellerman. > This patch was initially part of Power10 PMU base enablement > series. Moving this as separate patch as suggested by Michael > Ellerman. Hence dependency of initial series Patch 7 which defines > MMCRA_BHRB_DISABLE. Addressed review comments from Jordan to make > sure existing PMU function (__INIT_PMU) will not overwrite ISA 3.1 > updates > > Changes from v2 -> v3 > - Addressed review comment from Michael Ellerman to > call PMU init from __setup_cpu_power10 > > arch/powerpc/kernel/cpu_setup_power.S | 19 +++ > 1 file changed, 15 insertions(+), 4 deletions(-) > > diff --git a/arch/powerpc/kernel/cpu_setup_power.S > b/arch/powerpc/kernel/cpu_setup_power.S > index efdcfa7..3fa6eef 100644 > --- a/arch/powerpc/kernel/cpu_setup_power.S > +++ b/arch/powerpc/kernel/cpu_setup_power.S > @@ -94,13 +94,15 @@ _GLOBAL(__restore_cpu_power8) > _GLOBAL(__setup_cpu_power10) > mflrr11 > bl __init_FSCR_power10 > + bl __init_PMU > + bl __init_PMU_ISA31 > b 1f > > _GLOBAL(__setup_cpu_power9) > mflrr11 > bl __init_FSCR > -1: bl __init_PMU > - bl __init_hvmode_206 > + bl __init_PMU > +1: bl __init_hvmode_206 > mtlrr11 > beqlr > li r0,0 > @@ -124,13 +126,15 @@ _GLOBAL(__setup_cpu_power9) > _GLOBAL(__restore_cpu_power10) > mflrr11 > bl __init_FSCR_power10 > + bl __init_PMU > + bl __init_PMU_ISA31 > b 1f > > _GLOBAL(__restore_cpu_power9) > mflrr11 > bl __init_FSCR > -1: bl __init_PMU > - mfmsr r3 > + bl __init_PMU > +1: mfmsr r3 > rldicl. r0,r3,4,63 > mtlrr11 > beqlr > @@ -233,3 +237,10 @@ __init_PMU_ISA207: > li r5,0 > mtspr SPRN_MMCRS,r5 > blr > + > +__init_PMU_ISA31: > + li r5,0 > + mtspr SPRN_MMCR3,r5 > + LOAD_REG_IMMEDIATE(r5, MMCRA_BHRB_DISABLE) > + mtspr SPRN_MMCRA,r5 > + blr > -- > 1.8.3.1 >
Re: [v3 11/15] powerpc/perf: BHRB control to disable BHRB logic when not used
On Thu, Jul 23, 2020 at 11:26 AM Jordan Niethe wrote: > > On Sat, Jul 18, 2020 at 1:26 AM Athira Rajeev > wrote: > > > > PowerISA v3.1 has few updates for the Branch History Rolling Buffer(BHRB). > > > > BHRB disable is controlled via Monitor Mode Control Register A (MMCRA) > > bit, namely "BHRB Recording Disable (BHRBRD)". This field controls > > whether BHRB entries are written when BHRB recording is enabled by other > > bits. This patch implements support for this BHRB disable bit. > > > > By setting 0b1 to this bit will disable the BHRB and by setting 0b0 > > to this bit will have BHRB enabled. This addresses backward > > compatibility (for older OS), since this bit will be cleared and > > hardware will be writing to BHRB by default. > > > > This patch addresses changes to set MMCRA (BHRBRD) at boot for power10 > > ( there by the core will run faster) and enable this feature only on > > runtime ie, on explicit need from user. Also save/restore MMCRA in the > > restore path of state-loss idle state to make sure we keep BHRB disabled > > if it was not enabled on request at runtime. > > > > Signed-off-by: Athira Rajeev > > --- > > arch/powerpc/perf/core-book3s.c | 20 > > arch/powerpc/perf/isa207-common.c | 12 > > arch/powerpc/platforms/powernv/idle.c | 22 -- > > 3 files changed, 48 insertions(+), 6 deletions(-) > > > > diff --git a/arch/powerpc/perf/core-book3s.c > > b/arch/powerpc/perf/core-book3s.c > > index bd125fe..31c0535 100644 > > --- a/arch/powerpc/perf/core-book3s.c > > +++ b/arch/powerpc/perf/core-book3s.c > > @@ -1218,7 +1218,7 @@ static void write_mmcr0(struct cpu_hw_events *cpuhw, > > unsigned long mmcr0) > > static void power_pmu_disable(struct pmu *pmu) > > { > > struct cpu_hw_events *cpuhw; > > - unsigned long flags, mmcr0, val; > > + unsigned long flags, mmcr0, val, mmcra; > > > > if (!ppmu) > > return; > > @@ -1251,12 +1251,24 @@ static void power_pmu_disable(struct pmu *pmu) > > mb(); > > isync(); > > > > + val = mmcra = cpuhw->mmcr.mmcra; > > + > > /* > > * Disable instruction sampling if it was enabled > > */ > > - if (cpuhw->mmcr.mmcra & MMCRA_SAMPLE_ENABLE) { > > - mtspr(SPRN_MMCRA, > > - cpuhw->mmcr.mmcra & ~MMCRA_SAMPLE_ENABLE); > > + if (cpuhw->mmcr.mmcra & MMCRA_SAMPLE_ENABLE) > > + val &= ~MMCRA_SAMPLE_ENABLE; > > + > > + /* Disable BHRB via mmcra (BHRBRD) for p10 */ > > + if (ppmu->flags & PPMU_ARCH_310S) > > + val |= MMCRA_BHRB_DISABLE; > > + > > + /* > > +* Write SPRN_MMCRA if mmcra has either disabled > > +* instruction sampling or BHRB. > > +*/ > > + if (val != mmcra) { > > + mtspr(SPRN_MMCRA, mmcra); > > mb(); > > isync(); > > } > > diff --git a/arch/powerpc/perf/isa207-common.c > > b/arch/powerpc/perf/isa207-common.c > > index 77643f3..964437a 100644 > > --- a/arch/powerpc/perf/isa207-common.c > > +++ b/arch/powerpc/perf/isa207-common.c > > @@ -404,6 +404,13 @@ int isa207_compute_mmcr(u64 event[], int n_ev, > > > > mmcra = mmcr1 = mmcr2 = mmcr3 = 0; > > > > + /* > > +* Disable bhrb unless explicitly requested > > +* by setting MMCRA (BHRBRD) bit. > > +*/ > > + if (cpu_has_feature(CPU_FTR_ARCH_31)) > > + mmcra |= MMCRA_BHRB_DISABLE; > > + > > /* Second pass: assign PMCs, set all MMCR1 fields */ > > for (i = 0; i < n_ev; ++i) { > > pmc = (event[i] >> EVENT_PMC_SHIFT) & EVENT_PMC_MASK; > > @@ -479,6 +486,11 @@ int isa207_compute_mmcr(u64 event[], int n_ev, > > mmcra |= val << MMCRA_IFM_SHIFT; > > } > > > > + /* set MMCRA (BHRBRD) to 0 if there is user request for > > BHRB */ > > + if (cpu_has_feature(CPU_FTR_ARCH_31) && > > + (has_branch_stack(pevents[i]) || (event[i] > > & EVENT_WANTS_BHRB))) > >
Re: [v3 11/15] powerpc/perf: BHRB control to disable BHRB logic when not used
On Sat, Jul 18, 2020 at 1:26 AM Athira Rajeev wrote: > > PowerISA v3.1 has few updates for the Branch History Rolling Buffer(BHRB). > > BHRB disable is controlled via Monitor Mode Control Register A (MMCRA) > bit, namely "BHRB Recording Disable (BHRBRD)". This field controls > whether BHRB entries are written when BHRB recording is enabled by other > bits. This patch implements support for this BHRB disable bit. > > By setting 0b1 to this bit will disable the BHRB and by setting 0b0 > to this bit will have BHRB enabled. This addresses backward > compatibility (for older OS), since this bit will be cleared and > hardware will be writing to BHRB by default. > > This patch addresses changes to set MMCRA (BHRBRD) at boot for power10 > ( there by the core will run faster) and enable this feature only on > runtime ie, on explicit need from user. Also save/restore MMCRA in the > restore path of state-loss idle state to make sure we keep BHRB disabled > if it was not enabled on request at runtime. > > Signed-off-by: Athira Rajeev > --- > arch/powerpc/perf/core-book3s.c | 20 > arch/powerpc/perf/isa207-common.c | 12 > arch/powerpc/platforms/powernv/idle.c | 22 -- > 3 files changed, 48 insertions(+), 6 deletions(-) > > diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c > index bd125fe..31c0535 100644 > --- a/arch/powerpc/perf/core-book3s.c > +++ b/arch/powerpc/perf/core-book3s.c > @@ -1218,7 +1218,7 @@ static void write_mmcr0(struct cpu_hw_events *cpuhw, > unsigned long mmcr0) > static void power_pmu_disable(struct pmu *pmu) > { > struct cpu_hw_events *cpuhw; > - unsigned long flags, mmcr0, val; > + unsigned long flags, mmcr0, val, mmcra; > > if (!ppmu) > return; > @@ -1251,12 +1251,24 @@ static void power_pmu_disable(struct pmu *pmu) > mb(); > isync(); > > + val = mmcra = cpuhw->mmcr.mmcra; > + > /* > * Disable instruction sampling if it was enabled > */ > - if (cpuhw->mmcr.mmcra & MMCRA_SAMPLE_ENABLE) { > - mtspr(SPRN_MMCRA, > - cpuhw->mmcr.mmcra & ~MMCRA_SAMPLE_ENABLE); > + if (cpuhw->mmcr.mmcra & MMCRA_SAMPLE_ENABLE) > + val &= ~MMCRA_SAMPLE_ENABLE; > + > + /* Disable BHRB via mmcra (BHRBRD) for p10 */ > + if (ppmu->flags & PPMU_ARCH_310S) > + val |= MMCRA_BHRB_DISABLE; > + > + /* > +* Write SPRN_MMCRA if mmcra has either disabled > +* instruction sampling or BHRB. > +*/ > + if (val != mmcra) { > + mtspr(SPRN_MMCRA, mmcra); > mb(); > isync(); > } > diff --git a/arch/powerpc/perf/isa207-common.c > b/arch/powerpc/perf/isa207-common.c > index 77643f3..964437a 100644 > --- a/arch/powerpc/perf/isa207-common.c > +++ b/arch/powerpc/perf/isa207-common.c > @@ -404,6 +404,13 @@ int isa207_compute_mmcr(u64 event[], int n_ev, > > mmcra = mmcr1 = mmcr2 = mmcr3 = 0; > > + /* > +* Disable bhrb unless explicitly requested > +* by setting MMCRA (BHRBRD) bit. > +*/ > + if (cpu_has_feature(CPU_FTR_ARCH_31)) > + mmcra |= MMCRA_BHRB_DISABLE; > + > /* Second pass: assign PMCs, set all MMCR1 fields */ > for (i = 0; i < n_ev; ++i) { > pmc = (event[i] >> EVENT_PMC_SHIFT) & EVENT_PMC_MASK; > @@ -479,6 +486,11 @@ int isa207_compute_mmcr(u64 event[], int n_ev, > mmcra |= val << MMCRA_IFM_SHIFT; > } > > + /* set MMCRA (BHRBRD) to 0 if there is user request for BHRB > */ > + if (cpu_has_feature(CPU_FTR_ARCH_31) && > + (has_branch_stack(pevents[i]) || (event[i] & > EVENT_WANTS_BHRB))) > + mmcra &= ~MMCRA_BHRB_DISABLE; > + > if (pevents[i]->attr.exclude_user) > mmcr2 |= MMCR2_FCP(pmc); > > diff --git a/arch/powerpc/platforms/powernv/idle.c > b/arch/powerpc/platforms/powernv/idle.c > index 2dd4673..1c9d0a9 100644 > --- a/arch/powerpc/platforms/powernv/idle.c > +++ b/arch/powerpc/platforms/powernv/idle.c > @@ -611,6 +611,7 @@ static unsigned long power9_idle_stop(unsigned long > psscr, bool mmu_on) > unsigned long srr1; > unsigned long pls; > unsigned long mmcr0 = 0; > + unsigned long mmcra = 0; > struct p9_sprs sprs = {}; /* avoid false used-uninitialised */ > bool sprs_saved = false; > > @@ -657,6 +658,21 @@ static unsigned long power9_idle_stop(unsigned long > psscr, bool mmu_on) > */ > mmcr0 = mfspr(SPRN_MMCR0); > } > + > + if
Re: [v3 04/15] powerpc/perf: Add support for ISA3.1 PMU SPRs
On Wed, Jul 22, 2020 at 6:07 PM Athira Rajeev wrote: > > > > On 22-Jul-2020, at 9:48 AM, Jordan Niethe wrote: > > On Sat, Jul 18, 2020 at 1:02 AM Athira Rajeev > wrote: > > > From: Madhavan Srinivasan > > PowerISA v3.1 includes new performance monitoring unit(PMU) > special purpose registers (SPRs). They are > > Monitor Mode Control Register 3 (MMCR3) > Sampled Instruction Event Register 2 (SIER2) > Sampled Instruction Event Register 3 (SIER3) > > MMCR3 is added for further sampling related configuration > control. SIER2/SIER3 are added to provide additional > information about the sampled instruction. > > Patch adds new PPMU flag called "PPMU_ARCH_310S" to support > handling of these new SPRs, updates the struct thread_struct > to include these new SPRs, include MMCR3 in struct mmcr_regs. > This is needed to support programming of MMCR3 SPR during > event_[enable/disable]. Patch also adds the sysfs support > for the MMCR3 SPR along with SPRN_ macros for these new pmu sprs. > > Signed-off-by: Madhavan Srinivasan > --- > arch/powerpc/include/asm/perf_event_server.h | 2 ++ > arch/powerpc/include/asm/processor.h | 4 > arch/powerpc/include/asm/reg.h | 6 ++ > arch/powerpc/kernel/sysfs.c | 8 > arch/powerpc/perf/core-book3s.c | 29 > 5 files changed, 49 insertions(+) > > diff --git a/arch/powerpc/include/asm/perf_event_server.h > b/arch/powerpc/include/asm/perf_event_server.h > index 14b8dc1..832450a 100644 > --- a/arch/powerpc/include/asm/perf_event_server.h > +++ b/arch/powerpc/include/asm/perf_event_server.h > @@ -22,6 +22,7 @@ struct mmcr_regs { >unsigned long mmcr1; >unsigned long mmcr2; >unsigned long mmcra; > + unsigned long mmcr3; > }; > /* > * This struct provides the constants and functions needed to > @@ -75,6 +76,7 @@ struct power_pmu { > #define PPMU_HAS_SIER 0x0040 /* Has SIER */ > #define PPMU_ARCH_207S 0x0080 /* PMC is architecture v2.07S */ > #define PPMU_NO_SIAR 0x0100 /* Do not use SIAR */ > +#define PPMU_ARCH_310S 0x0200 /* Has MMCR3, SIER2 and SIER3 */ > > We elsewhere have CPU_FTR_ARCH_31, so should this be PPMU_ARCH_31S to > be consistent. > > > > Ok, > This change will need to be done in all places which are currently using > PPMU_ARCH_310S > > /* > * Values for flags to get_alternatives() > diff --git a/arch/powerpc/include/asm/processor.h > b/arch/powerpc/include/asm/processor.h > index 52a6783..a466e94 100644 > --- a/arch/powerpc/include/asm/processor.h > +++ b/arch/powerpc/include/asm/processor.h > @@ -272,6 +272,10 @@ struct thread_struct { >unsignedmmcr0; > >unsignedused_ebb; > + unsigned long mmcr3; > + unsigned long sier2; > + unsigned long sier3; > + > #endif > }; > > diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h > index 88e6c78..21a1b2d 100644 > --- a/arch/powerpc/include/asm/reg.h > +++ b/arch/powerpc/include/asm/reg.h > @@ -876,7 +876,9 @@ > #define MMCR0_FCHV 0x0001UL /* freeze conditions in hypervisor mode */ > #define SPRN_MMCR1 798 > #define SPRN_MMCR2 785 > +#define SPRN_MMCR3 754 > #define SPRN_UMMCR2769 > +#define SPRN_UMMCR3738 > #define SPRN_MMCRA 0x312 > #define MMCRA_SDSYNC 0x8000UL /* SDAR synced with SIAR */ > #define MMCRA_SDAR_DCACHE_MISS 0x4000UL > @@ -918,6 +920,10 @@ > #define SIER_SIHV0x100 /* Sampled MSR_HV */ > #define SIER_SIAR_VALID 0x040 /* SIAR contents valid */ > #define SIER_SDAR_VALID 0x020 /* SDAR contents valid */ > +#define SPRN_SIER2 752 > +#define SPRN_SIER3 753 > +#define SPRN_USIER2736 > +#define SPRN_USIER3737 > #define SPRN_SIAR 796 > #define SPRN_SDAR 797 > #define SPRN_TACR 888 > diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c > index 571b325..46b4ebc 100644 > --- a/arch/powerpc/kernel/sysfs.c > +++ b/arch/powerpc/kernel/sysfs.c > @@ -622,8 +622,10 @@ void ppc_enable_pmcs(void) > SYSFS_PMCSETUP(pmc8, SPRN_PMC8); > > SYSFS_PMCSETUP(mmcra, SPRN_MMCRA); > +SYSFS_PMCSETUP(mmcr3, SPRN_MMCR3); > > static DEVICE_ATTR(mmcra, 0600, show_mmcra, store_mmcra); > +static DEVICE_ATTR(mmcr3, 0600, show_mmcr3, store_mmcr3); > #endif /* HAS_PPC_PMC56 */ > > > @@ -886,6 +888,9 @@ static int register_cpu_online(unsigned int cpu) > #ifdef CONFIG_PMU_SYSFS >if (cpu_has_feature(CPU_FTR_MMCRA)) >device_create_file(s,
Re: [v3 07/15] powerpc/perf: Add power10_feat to dt_cpu_ftrs
On Wed, Jul 22, 2020 at 5:55 PM Athira Rajeev wrote: > > > > On 22-Jul-2020, at 10:11 AM, Jordan Niethe wrote: > > On Sat, Jul 18, 2020 at 1:13 AM Athira Rajeev > wrote: > > > From: Madhavan Srinivasan > > Add power10 feature function to dt_cpu_ftrs.c along > with a power10 specific init() to initialize pmu sprs, > sets the oprofile_cpu_type and cpu_features. This will > enable performance monitoring unit(PMU) for Power10 > in CPU features with "performance-monitor-power10". > > For PowerISA v3.1, BHRB disable is controlled via Monitor Mode > Control Register A (MMCRA) bit, namely "BHRB Recording Disable > (BHRBRD)". This patch initializes MMCRA BHRBRD to disable BHRB > feature at boot for power10. > > Signed-off-by: Madhavan Srinivasan > --- > arch/powerpc/include/asm/reg.h| 3 +++ > arch/powerpc/kernel/cpu_setup_power.S | 8 > arch/powerpc/kernel/dt_cpu_ftrs.c | 26 ++ > 3 files changed, 37 insertions(+) > > diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h > index 21a1b2d..900ada1 100644 > --- a/arch/powerpc/include/asm/reg.h > +++ b/arch/powerpc/include/asm/reg.h > @@ -1068,6 +1068,9 @@ > #define MMCR0_PMC2_LOADMISSTIME0x5 > #endif > > +/* BHRB disable bit for PowerISA v3.10 */ > +#define MMCRA_BHRB_DISABLE 0x0020 > > Shouldn't this go under SPRN_MMCRA with the other MMCRA_*. > > > > Hi Jordan > > Ok, the definition of MMCRA is under #ifdef for 64 bit . if I move > definition of MMCRA_BHRB_DISABLE along with other SPR's, I also > need to define this for 32-bit to satisfy core-book3s to compile as below: > > diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h > index 900ada10762c..7e271657b412 100644 > --- a/arch/powerpc/include/asm/reg.h > +++ b/arch/powerpc/include/asm/reg.h > @@ -888,6 +888,8 @@ > #define MMCRA_SLOT 0x0700UL /* SLOT bits (37-39) */ > #define MMCRA_SLOT_SHIFT 24 > #define MMCRA_SAMPLE_ENABLE 0x0001UL /* enable sampling */ > +/* BHRB disable bit for PowerISA v3.10 */ > +#define MMCRA_BHRB_DISABLE 0x0020 > #define POWER6_MMCRA_SDSYNC 0x0800ULL/* SDAR/SIAR synced */ > #define POWER6_MMCRA_SIHV 0x0400ULL > #define POWER6_MMCRA_SIPR 0x0200ULL > @@ -1068,9 +1070,6 @@ > #define MMCR0_PMC2_LOADMISSTIME0x5 > #endif > > > > -/* BHRB disable bit for PowerISA v3.10 */ > -#define MMCRA_BHRB_DISABLE 0x0020 > - > /* > * SPRG usage: > * > diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c > index 36baae666387..88068f20827c 100644 > --- a/arch/powerpc/perf/core-book3s.c > +++ b/arch/powerpc/perf/core-book3s.c > @@ -94,6 +94,7 @@ static unsigned int freeze_events_kernel = MMCR0_FCS; > #define SPRN_SIER2 0 > #define SPRN_SIER3 0 > #define MMCRA_SAMPLE_ENABLE0 > +#define MMCRA_BHRB_DISABLE 0 > > > > static inline unsigned long perf_ip_adjust(struct pt_regs *regs) > { > > > > + > /* > * SPRG usage: > * > diff --git a/arch/powerpc/kernel/cpu_setup_power.S > b/arch/powerpc/kernel/cpu_setup_power.S > index efdcfa7..b8e0d1e 100644 > --- a/arch/powerpc/kernel/cpu_setup_power.S > +++ b/arch/powerpc/kernel/cpu_setup_power.S > @@ -94,6 +94,7 @@ _GLOBAL(__restore_cpu_power8) > _GLOBAL(__setup_cpu_power10) >mflrr11 >bl __init_FSCR_power10 > + bl __init_PMU_ISA31 > > So we set MMCRA here but then aren't we still going to call __init_PMU > which will overwrite that? > Would this setting MMCRA also need to be handled in __restore_cpu_power10? > > > Thanks for this nice catch ! When I rebased code initial phase, we didn’t > had power10 part filled in. > It was a miss from my side in adding PMu init functions and thanks for > pointing this out. > Below patch will call __init_PMU functions in setup and restore. Please check > if this looks good > > -- > diff --git a/arch/powerpc/kernel/cpu_setup_power.S > b/arch/powerpc/kernel/cpu_setup_power.S > index efdcfa714106..e672a6c5fd7c 100644 > --- a/arch/powerpc/kernel/cpu_setup_power.S > +++ b/arch/powerpc/kernel/cpu_setup_power.S > @@ -94,6 +94,9 @@ _GLOBAL(__restore_cpu_power8) > _GLOBAL(__setup_cpu_power10) > mflr r11 > bl __init_FSCR_power10 > + bl __init_PMU > + bl __init_PMU_ISA31 > + bl __init_PMU_HV > b 1f > > _GLOBAL(__setup_cpu_power9) Won't you also need to change where the label 1 is: --- a/arch/powerpc/kernel/cpu_setup_power.S +++ b/arch/powerpc/kernel/cpu_setup_power.S @@ -100,8
Re: [v3 07/15] powerpc/perf: Add power10_feat to dt_cpu_ftrs
On Sat, Jul 18, 2020 at 1:13 AM Athira Rajeev wrote: > > From: Madhavan Srinivasan > > Add power10 feature function to dt_cpu_ftrs.c along > with a power10 specific init() to initialize pmu sprs, > sets the oprofile_cpu_type and cpu_features. This will > enable performance monitoring unit(PMU) for Power10 > in CPU features with "performance-monitor-power10". > > For PowerISA v3.1, BHRB disable is controlled via Monitor Mode > Control Register A (MMCRA) bit, namely "BHRB Recording Disable > (BHRBRD)". This patch initializes MMCRA BHRBRD to disable BHRB > feature at boot for power10. > > Signed-off-by: Madhavan Srinivasan > --- > arch/powerpc/include/asm/reg.h| 3 +++ > arch/powerpc/kernel/cpu_setup_power.S | 8 > arch/powerpc/kernel/dt_cpu_ftrs.c | 26 ++ > 3 files changed, 37 insertions(+) > > diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h > index 21a1b2d..900ada1 100644 > --- a/arch/powerpc/include/asm/reg.h > +++ b/arch/powerpc/include/asm/reg.h > @@ -1068,6 +1068,9 @@ > #define MMCR0_PMC2_LOADMISSTIME0x5 > #endif > > +/* BHRB disable bit for PowerISA v3.10 */ > +#define MMCRA_BHRB_DISABLE 0x0020 Shouldn't this go under SPRN_MMCRA with the other MMCRA_*. > + > /* > * SPRG usage: > * > diff --git a/arch/powerpc/kernel/cpu_setup_power.S > b/arch/powerpc/kernel/cpu_setup_power.S > index efdcfa7..b8e0d1e 100644 > --- a/arch/powerpc/kernel/cpu_setup_power.S > +++ b/arch/powerpc/kernel/cpu_setup_power.S > @@ -94,6 +94,7 @@ _GLOBAL(__restore_cpu_power8) > _GLOBAL(__setup_cpu_power10) > mflrr11 > bl __init_FSCR_power10 > + bl __init_PMU_ISA31 So we set MMCRA here but then aren't we still going to call __init_PMU which will overwrite that? Would this setting MMCRA also need to be handled in __restore_cpu_power10? > b 1f > > _GLOBAL(__setup_cpu_power9) > @@ -233,3 +234,10 @@ __init_PMU_ISA207: > li r5,0 > mtspr SPRN_MMCRS,r5 > blr > + > +__init_PMU_ISA31: > + li r5,0 > + mtspr SPRN_MMCR3,r5 > + LOAD_REG_IMMEDIATE(r5, MMCRA_BHRB_DISABLE) > + mtspr SPRN_MMCRA,r5 > + blr > diff --git a/arch/powerpc/kernel/dt_cpu_ftrs.c > b/arch/powerpc/kernel/dt_cpu_ftrs.c > index 3a40951..f482286 100644 > --- a/arch/powerpc/kernel/dt_cpu_ftrs.c > +++ b/arch/powerpc/kernel/dt_cpu_ftrs.c > @@ -450,6 +450,31 @@ static int __init feat_enable_pmu_power9(struct > dt_cpu_feature *f) > return 1; > } > > +static void init_pmu_power10(void) > +{ > + init_pmu_power9(); > + > + mtspr(SPRN_MMCR3, 0); > + mtspr(SPRN_MMCRA, MMCRA_BHRB_DISABLE); > +} > + > +static int __init feat_enable_pmu_power10(struct dt_cpu_feature *f) > +{ > + hfscr_pmu_enable(); > + > + init_pmu_power10(); > + init_pmu_registers = init_pmu_power10; > + > + cur_cpu_spec->cpu_features |= CPU_FTR_MMCRA; > + cur_cpu_spec->cpu_user_features |= PPC_FEATURE_PSERIES_PERFMON_COMPAT; > + > + cur_cpu_spec->num_pmcs = 6; > + cur_cpu_spec->pmc_type = PPC_PMC_IBM; > + cur_cpu_spec->oprofile_cpu_type = "ppc64/power10"; > + > + return 1; > +} > + > static int __init feat_enable_tm(struct dt_cpu_feature *f) > { > #ifdef CONFIG_PPC_TRANSACTIONAL_MEM > @@ -639,6 +664,7 @@ struct dt_cpu_feature_match { > {"pc-relative-addressing", feat_enable, 0}, > {"machine-check-power9", feat_enable_mce_power9, 0}, > {"performance-monitor-power9", feat_enable_pmu_power9, 0}, > + {"performance-monitor-power10", feat_enable_pmu_power10, 0}, > {"event-based-branch-v3", feat_enable, 0}, > {"random-number-generator", feat_enable, 0}, > {"system-call-vectored", feat_disable, 0}, > -- > 1.8.3.1 >
Re: [v3 04/15] powerpc/perf: Add support for ISA3.1 PMU SPRs
On Sat, Jul 18, 2020 at 1:02 AM Athira Rajeev wrote: > > From: Madhavan Srinivasan > > PowerISA v3.1 includes new performance monitoring unit(PMU) > special purpose registers (SPRs). They are > > Monitor Mode Control Register 3 (MMCR3) > Sampled Instruction Event Register 2 (SIER2) > Sampled Instruction Event Register 3 (SIER3) > > MMCR3 is added for further sampling related configuration > control. SIER2/SIER3 are added to provide additional > information about the sampled instruction. > > Patch adds new PPMU flag called "PPMU_ARCH_310S" to support > handling of these new SPRs, updates the struct thread_struct > to include these new SPRs, include MMCR3 in struct mmcr_regs. > This is needed to support programming of MMCR3 SPR during > event_[enable/disable]. Patch also adds the sysfs support > for the MMCR3 SPR along with SPRN_ macros for these new pmu sprs. > > Signed-off-by: Madhavan Srinivasan > --- > arch/powerpc/include/asm/perf_event_server.h | 2 ++ > arch/powerpc/include/asm/processor.h | 4 > arch/powerpc/include/asm/reg.h | 6 ++ > arch/powerpc/kernel/sysfs.c | 8 > arch/powerpc/perf/core-book3s.c | 29 > > 5 files changed, 49 insertions(+) > > diff --git a/arch/powerpc/include/asm/perf_event_server.h > b/arch/powerpc/include/asm/perf_event_server.h > index 14b8dc1..832450a 100644 > --- a/arch/powerpc/include/asm/perf_event_server.h > +++ b/arch/powerpc/include/asm/perf_event_server.h > @@ -22,6 +22,7 @@ struct mmcr_regs { > unsigned long mmcr1; > unsigned long mmcr2; > unsigned long mmcra; > + unsigned long mmcr3; > }; > /* > * This struct provides the constants and functions needed to > @@ -75,6 +76,7 @@ struct power_pmu { > #define PPMU_HAS_SIER 0x0040 /* Has SIER */ > #define PPMU_ARCH_207S 0x0080 /* PMC is architecture v2.07S */ > #define PPMU_NO_SIAR 0x0100 /* Do not use SIAR */ > +#define PPMU_ARCH_310S 0x0200 /* Has MMCR3, SIER2 and SIER3 */ We elsewhere have CPU_FTR_ARCH_31, so should this be PPMU_ARCH_31S to be consistent. > > /* > * Values for flags to get_alternatives() > diff --git a/arch/powerpc/include/asm/processor.h > b/arch/powerpc/include/asm/processor.h > index 52a6783..a466e94 100644 > --- a/arch/powerpc/include/asm/processor.h > +++ b/arch/powerpc/include/asm/processor.h > @@ -272,6 +272,10 @@ struct thread_struct { > unsignedmmcr0; > > unsignedused_ebb; > + unsigned long mmcr3; > + unsigned long sier2; > + unsigned long sier3; > + > #endif > }; > > diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h > index 88e6c78..21a1b2d 100644 > --- a/arch/powerpc/include/asm/reg.h > +++ b/arch/powerpc/include/asm/reg.h > @@ -876,7 +876,9 @@ > #define MMCR0_FCHV 0x0001UL /* freeze conditions in hypervisor mode > */ > #define SPRN_MMCR1 798 > #define SPRN_MMCR2 785 > +#define SPRN_MMCR3 754 > #define SPRN_UMMCR2769 > +#define SPRN_UMMCR3738 > #define SPRN_MMCRA 0x312 > #define MMCRA_SDSYNC 0x8000UL /* SDAR synced with SIAR */ > #define MMCRA_SDAR_DCACHE_MISS 0x4000UL > @@ -918,6 +920,10 @@ > #define SIER_SIHV0x100 /* Sampled MSR_HV */ > #define SIER_SIAR_VALID 0x040 /* SIAR contents valid */ > #define SIER_SDAR_VALID 0x020 /* SDAR contents valid */ > +#define SPRN_SIER2 752 > +#define SPRN_SIER3 753 > +#define SPRN_USIER2736 > +#define SPRN_USIER3737 > #define SPRN_SIAR 796 > #define SPRN_SDAR 797 > #define SPRN_TACR 888 > diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c > index 571b325..46b4ebc 100644 > --- a/arch/powerpc/kernel/sysfs.c > +++ b/arch/powerpc/kernel/sysfs.c > @@ -622,8 +622,10 @@ void ppc_enable_pmcs(void) > SYSFS_PMCSETUP(pmc8, SPRN_PMC8); > > SYSFS_PMCSETUP(mmcra, SPRN_MMCRA); > +SYSFS_PMCSETUP(mmcr3, SPRN_MMCR3); > > static DEVICE_ATTR(mmcra, 0600, show_mmcra, store_mmcra); > +static DEVICE_ATTR(mmcr3, 0600, show_mmcr3, store_mmcr3); > #endif /* HAS_PPC_PMC56 */ > > > @@ -886,6 +888,9 @@ static int register_cpu_online(unsigned int cpu) > #ifdef CONFIG_PMU_SYSFS > if (cpu_has_feature(CPU_FTR_MMCRA)) > device_create_file(s, _attr_mmcra); > + > + if (cpu_has_feature(CPU_FTR_ARCH_31)) > + device_create_file(s, _attr_mmcr3); > #endif /* CONFIG_PMU_SYSFS */ > > if (cpu_has_feature(CPU_FTR_PURR)) { > @@ -980,6 +985,9 @@ static int unregister_cpu_online(unsigned int cpu) > #ifdef CONFIG_PMU_SYSFS > if (cpu_has_feature(CPU_FTR_MMCRA)) > device_remove_file(s, _attr_mmcra); > + > + if (cpu_has_feature(CPU_FTR_ARCH_31)) > + device_remove_file(s, _attr_mmcr3); > #endif /* CONFIG_PMU_SYSFS */ > > if
Re: [PATCH 5/5] powerpc sstep: Add tests for Prefixed Add Immediate
On Mon, May 25, 2020 at 1:00 PM Jordan Niethe wrote: > > Use the existing support for testing compute type instructions to test > Prefixed Add Immediate (paddi). The R bit of the paddi instruction > controls whether current instruction address is used. Add test cases for > when R=1 and for R=0. paddi has a 34 bit immediate field formed by > concatenating si0 and si1. Add tests for the extreme values of this > field. > > Skip the paddi tests if ISA v3.1 is unsupported. > > Some of these test cases were added by Balamuruhan S. > > Signed-off-by: Jordan Niethe > --- > arch/powerpc/lib/test_emulate_step.c | 127 ++ > .../lib/test_emulate_step_exec_instr.S| 1 + > 2 files changed, 128 insertions(+) > > diff --git a/arch/powerpc/lib/test_emulate_step.c > b/arch/powerpc/lib/test_emulate_step.c > index 579b5db80674..33a72b7d2764 100644 > --- a/arch/powerpc/lib/test_emulate_step.c > +++ b/arch/powerpc/lib/test_emulate_step.c > @@ -105,6 +105,13 @@ > ___PPC_RA(a) | ___PPC_RB(b)) > #define TEST_ADDC_DOT(t, a, b) ppc_inst(PPC_INST_ADDC | ___PPC_RT(t) | > \ > ___PPC_RA(a) | ___PPC_RB(b) | 0x1) > +#define TEST_PADDI(t, a, i, pr)ppc_inst_prefix(PPC_PREFIX_MLS | > __PPC_PRFX_R(pr) | \ > + IMM_H(i), \ > + PPC_INST_ADDI | \ > + ___PPC_RT(t) | ___PPC_RA(a) | \ > + IMM_L(i)) > + > + > > #define MAX_SUBTESTS 16 > > @@ -699,6 +706,11 @@ struct compute_test { > } subtests[MAX_SUBTESTS + 1]; > }; > > +/* Extreme values for si0||si1 (the MLS:D-form 34 bit immediate field) */ > +#define SI_MIN BIT(33) > +#define SI_MAX (BIT(33) - 1) > +#define SI_UMAX (BIT(34) - 1) > + > static struct compute_test compute_tests[] = { > { > .mnemonic = "nop", > @@ -1071,6 +1083,121 @@ static struct compute_test compute_tests[] = { > } > } > } > + }, > + { > + .mnemonic = "paddi", > + .cpu_feature = CPU_FTR_ARCH_31, > + .subtests = { > + { > + .descr = "RA = LONG_MIN, SI = SI_MIN, R = 0", > + .instr = TEST_PADDI(21, 22, SI_MIN, 0), > + .regs = { > + .gpr[21] = 0, > + .gpr[22] = LONG_MIN, > + } > + }, > + { > + .descr = "RA = LONG_MIN, SI = SI_MAX, R = 0", > + .instr = TEST_PADDI(21, 22, SI_MAX, 0), > + .regs = { > + .gpr[21] = 0, > + .gpr[22] = LONG_MIN, > + } > + }, > + { > + .descr = "RA = LONG_MAX, SI = SI_MAX, R = 0", > + .instr = TEST_PADDI(21, 22, SI_MAX, 0), > + .regs = { > + .gpr[21] = 0, > + .gpr[22] = LONG_MAX, > + } > + }, > + { > + .descr = "RA = ULONG_MAX, SI = SI_UMAX, R = > 0", > + .instr = TEST_PADDI(21, 22, SI_UMAX, 0), > + .regs = { > + .gpr[21] = 0, > + .gpr[22] = ULONG_MAX, > + } > + }, > + { > + .descr = "RA = ULONG_MAX, SI = 0x1, R = 0", > + .instr = TEST_PADDI(21, 22, 0x1, 0), > + .regs = { > + .gpr[21] = 0, > + .gpr[22] = ULONG_MAX, > + } > + }, > + { > + .descr = "RA = INT_MIN, SI = SI_MIN, R = 0", > + .instr = TEST_PADDI(21, 22, SI_MIN, 0), > +
Re: [PATCH v4 09/10] powerpc/watchpoint: Return available watchpoints dynamically
On Tue, Jul 21, 2020 at 1:57 PM Ravi Bangoria wrote: > > > > On 7/20/20 9:12 AM, Jordan Niethe wrote: > > On Fri, Jul 17, 2020 at 2:11 PM Ravi Bangoria > > wrote: > >> > >> So far Book3S Powerpc supported only one watchpoint. Power10 is > >> introducing 2nd DAWR. Enable 2nd DAWR support for Power10. > >> Availability of 2nd DAWR will depend on CPU_FTR_DAWR1. > >> > >> Signed-off-by: Ravi Bangoria > >> --- > >> arch/powerpc/include/asm/cputable.h | 4 +++- > >> arch/powerpc/include/asm/hw_breakpoint.h | 5 +++-- > >> 2 files changed, 6 insertions(+), 3 deletions(-) > >> > >> diff --git a/arch/powerpc/include/asm/cputable.h > >> b/arch/powerpc/include/asm/cputable.h > >> index 3445c86e1f6f..36a0851a7a9b 100644 > >> --- a/arch/powerpc/include/asm/cputable.h > >> +++ b/arch/powerpc/include/asm/cputable.h > >> @@ -633,7 +633,9 @@ enum { > >>* Maximum number of hw breakpoint supported on powerpc. Number of > >>* breakpoints supported by actual hw might be less than this. > >>*/ > >> -#define HBP_NUM_MAX1 > >> +#define HBP_NUM_MAX2 > >> +#define HBP_NUM_ONE1 > >> +#define HBP_NUM_TWO2 > > I wonder if these defines are necessary - has it any advantage over > > just using the literal? > > No, not really. Initially I had something like: > > #define HBP_NUM_MAX2 > #define HBP_NUM_P8_P9 1 > #define HBP_NUM_P102 > > But then I thought it's also not right. So I made it _ONE and _TWO. > Now the function that decides nr watchpoints dynamically (nr_wp_slots) > is in different file, I thought to keep it like this so it would be > easier to figure out why _MAX is 2. > > >> > >> #endif /* !__ASSEMBLY__ */ > >> > >> diff --git a/arch/powerpc/include/asm/hw_breakpoint.h > >> b/arch/powerpc/include/asm/hw_breakpoint.h > >> index cb424799da0d..d4eab1694bcd 100644 > >> --- a/arch/powerpc/include/asm/hw_breakpoint.h > >> +++ b/arch/powerpc/include/asm/hw_breakpoint.h > >> @@ -5,10 +5,11 @@ > >>* Copyright 2010, IBM Corporation. > >>* Author: K.Prasad > >>*/ > >> - > > Was removing this line deliberate? > > Nah. Will remove that hunk. > > >> #ifndef _PPC_BOOK3S_64_HW_BREAKPOINT_H > >> #define _PPC_BOOK3S_64_HW_BREAKPOINT_H > >> > >> +#include > >> + > >> #ifdef __KERNEL__ > >> struct arch_hw_breakpoint { > >> unsigned long address; > >> @@ -46,7 +47,7 @@ struct arch_hw_breakpoint { > >> > >> static inline int nr_wp_slots(void) > >> { > >> - return HBP_NUM_MAX; > >> + return cpu_has_feature(CPU_FTR_DAWR1) ? HBP_NUM_TWO : HBP_NUM_ONE; > > So it'd be something like: > > + return cpu_has_feature(CPU_FTR_DAWR1) ? HBP_NUM_MAX : 1; > > But thinking that there might be more slots added in the future, it > > may be better to make the number of slots a variable that is set > > during the init and then have this function return that. > > Not sure I follow. What do you mean by setting number of slots a > variable that is set during the init? Sorry I was unclear there. I was just looking and saw arm also has a variable number of hw breakpoints. If we did something like how they handle it, it might look something like: static int num_wp_slots __ro_after_init; int nr_wp_slots(void) { return num_wp_slots; } static int __init arch_hw_breakpoint_init(void) { num_wp_slots = work out how many wp_slots } arch_initcall(arch_hw_breakpoint_init); Then we wouldn't have to calculate everytime nr_wp_slots() is called. In the future if more wp's are added nr_wp_slots() will get more complicated. But just an idea, feel free to ignore. > > Thanks, > Ravi
Re: [v3 01/15] powerpc/perf: Update cpu_hw_event to use `struct` for storing MMCR registers
On Sat, Jul 18, 2020 at 12:48 AM Athira Rajeev wrote: > > core-book3s currently uses array to store the MMCR registers as part > of per-cpu `cpu_hw_events`. This patch does a clean up to use `struct` > to store mmcr regs instead of array. This will make code easier to read > and reduces chance of any subtle bug that may come in the future, say > when new registers are added. Patch updates all relevant code that was > using MMCR array ( cpuhw->mmcr[x]) to use newly introduced `struct`. > This includes the PMU driver code for supported platforms (power5 > to power9) and ISA macros for counter support functions. > > Signed-off-by: Athira Rajeev > --- > arch/powerpc/include/asm/perf_event_server.h | 10 -- > arch/powerpc/perf/core-book3s.c | 53 > +--- > arch/powerpc/perf/isa207-common.c| 20 +-- > arch/powerpc/perf/isa207-common.h| 4 +-- > arch/powerpc/perf/mpc7450-pmu.c | 21 +++ > arch/powerpc/perf/power5+-pmu.c | 17 - > arch/powerpc/perf/power5-pmu.c | 17 - > arch/powerpc/perf/power6-pmu.c | 16 - > arch/powerpc/perf/power7-pmu.c | 17 - > arch/powerpc/perf/ppc970-pmu.c | 24 ++--- > 10 files changed, 105 insertions(+), 94 deletions(-) > > diff --git a/arch/powerpc/include/asm/perf_event_server.h > b/arch/powerpc/include/asm/perf_event_server.h > index 3e9703f..f9a3668 100644 > --- a/arch/powerpc/include/asm/perf_event_server.h > +++ b/arch/powerpc/include/asm/perf_event_server.h > @@ -17,6 +17,12 @@ > > struct perf_event; > > +struct mmcr_regs { > + unsigned long mmcr0; > + unsigned long mmcr1; > + unsigned long mmcr2; > + unsigned long mmcra; > +}; > /* > * This struct provides the constants and functions needed to > * describe the PMU on a particular POWER-family CPU. > @@ -28,7 +34,7 @@ struct power_pmu { > unsigned long add_fields; > unsigned long test_adder; > int (*compute_mmcr)(u64 events[], int n_ev, > - unsigned int hwc[], unsigned long mmcr[], > + unsigned int hwc[], struct mmcr_regs *mmcr, > struct perf_event *pevents[]); > int (*get_constraint)(u64 event_id, unsigned long *mskp, > unsigned long *valp); > @@ -41,7 +47,7 @@ struct power_pmu { > unsigned long group_constraint_val; > u64 (*bhrb_filter_map)(u64 branch_sample_type); > void(*config_bhrb)(u64 pmu_bhrb_filter); > - void(*disable_pmc)(unsigned int pmc, unsigned long > mmcr[]); > + void(*disable_pmc)(unsigned int pmc, struct mmcr_regs > *mmcr); > int (*limited_pmc_event)(u64 event_id); > u32 flags; > const struct attribute_group**attr_groups; > diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c > index cd6a742..18b1b6a 100644 > --- a/arch/powerpc/perf/core-book3s.c > +++ b/arch/powerpc/perf/core-book3s.c > @@ -37,12 +37,7 @@ struct cpu_hw_events { > struct perf_event *event[MAX_HWEVENTS]; > u64 events[MAX_HWEVENTS]; > unsigned int flags[MAX_HWEVENTS]; > - /* > -* The order of the MMCR array is: > -* - 64-bit, MMCR0, MMCR1, MMCRA, MMCR2 > -* - 32-bit, MMCR0, MMCR1, MMCR2 > -*/ > - unsigned long mmcr[4]; > + struct mmcr_regs mmcr; > struct perf_event *limited_counter[MAX_LIMITED_HWCOUNTERS]; > u8 limited_hwidx[MAX_LIMITED_HWCOUNTERS]; > u64 alternatives[MAX_HWEVENTS][MAX_EVENT_ALTERNATIVES]; > @@ -121,7 +116,7 @@ static void ebb_event_add(struct perf_event *event) { } > static void ebb_switch_out(unsigned long mmcr0) { } > static unsigned long ebb_switch_in(bool ebb, struct cpu_hw_events *cpuhw) > { > - return cpuhw->mmcr[0]; > + return cpuhw->mmcr.mmcr0; > } > > static inline void power_pmu_bhrb_enable(struct perf_event *event) {} > @@ -590,7 +585,7 @@ static void ebb_switch_out(unsigned long mmcr0) > > static unsigned long ebb_switch_in(bool ebb, struct cpu_hw_events *cpuhw) > { > - unsigned long mmcr0 = cpuhw->mmcr[0]; > + unsigned long mmcr0 = cpuhw->mmcr.mmcr0; > > if (!ebb) > goto out; > @@ -624,7 +619,7 @@ static unsigned long ebb_switch_in(bool ebb, struct > cpu_hw_events *cpuhw) > * unfreeze counters, it should not set exclude_xxx in its events and > * instead manage the MMCR2 entirely by itself. > */ > - mtspr(SPRN_MMCR2, cpuhw->mmcr[3] | current->thread.mmcr2); > + mtspr(SPRN_MMCR2, cpuhw->mmcr.mmcr2 | current->thread.mmcr2); > out: > return mmcr0; > } > @@ -1232,9 +1227,9 @@ static void power_pmu_disable(struct pmu *pmu) > /*
Re: [PATCH 04/11] powerpc/smp: Enable small core scheduling sooner
On Tue, Jul 14, 2020 at 2:44 PM Srikar Dronamraju wrote: > > Enable small core scheduling as soon as we detect that we are in a > system that supports thread group. Doing so would avoid a redundant > check. > > Cc: linuxppc-dev > Cc: Michael Ellerman > Cc: Nick Piggin > Cc: Oliver OHalloran > Cc: Nathan Lynch > Cc: Michael Neuling > Cc: Anton Blanchard > Cc: Gautham R Shenoy > Cc: Vaidyanathan Srinivasan > Signed-off-by: Srikar Dronamraju > --- > arch/powerpc/kernel/smp.c | 12 ++-- > 1 file changed, 6 insertions(+), 6 deletions(-) > > diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c > index 24529f6134aa..7d430fc536cc 100644 > --- a/arch/powerpc/kernel/smp.c > +++ b/arch/powerpc/kernel/smp.c > @@ -892,6 +892,12 @@ static int init_big_cores(void) > } > > has_big_cores = true; > + > +#ifdef CONFIG_SCHED_SMT > + pr_info("Big cores detected. Using small core scheduling\n"); Why change the wording from "Big cores detected but using small core scheduling\n"? > + powerpc_topology[0].mask = smallcore_smt_mask; > +#endif > + > return 0; > } > > @@ -1383,12 +1389,6 @@ void __init smp_cpus_done(unsigned int max_cpus) > > dump_numa_cpu_topology(); > > -#ifdef CONFIG_SCHED_SMT > - if (has_big_cores) { > - pr_info("Big cores detected but using small core > scheduling\n"); > - powerpc_topology[0].mask = smallcore_smt_mask; > - } > -#endif > set_sched_topology(powerpc_topology); > } > > -- > 2.17.1 >
Re: [PATCH v4 10/10] powerpc/watchpoint: Remove 512 byte boundary
On Fri, Jul 17, 2020 at 2:11 PM Ravi Bangoria wrote: > > Power10 has removed 512 bytes boundary from match criteria. i.e. The watch > range can cross 512 bytes boundary. It looks like this change is not mentioned in ISA v3.1 Book III 9.4 Data Address Watchpoint. It could be useful to mention that in the commit message. Also I wonder if could add a test for this to the ptrace-hwbreak selftest? > > Signed-off-by: Ravi Bangoria > --- > arch/powerpc/kernel/hw_breakpoint.c | 5 +++-- > 1 file changed, 3 insertions(+), 2 deletions(-) > > diff --git a/arch/powerpc/kernel/hw_breakpoint.c > b/arch/powerpc/kernel/hw_breakpoint.c > index c55e67bab271..1f4a1efa0074 100644 > --- a/arch/powerpc/kernel/hw_breakpoint.c > +++ b/arch/powerpc/kernel/hw_breakpoint.c > @@ -418,8 +418,9 @@ static int hw_breakpoint_validate_len(struct > arch_hw_breakpoint *hw) > > if (dawr_enabled()) { > max_len = DAWR_MAX_LEN; > - /* DAWR region can't cross 512 bytes boundary */ > - if (ALIGN_DOWN(start_addr, SZ_512) != ALIGN_DOWN(end_addr - > 1, SZ_512)) > + /* DAWR region can't cross 512 bytes boundary on p10 > predecessors */ > + if (!cpu_has_feature(CPU_FTR_ARCH_31) && > + (ALIGN_DOWN(start_addr, SZ_512) != ALIGN_DOWN(end_addr - > 1, SZ_512))) > return -EINVAL; > } else if (IS_ENABLED(CONFIG_PPC_8xx)) { > /* 8xx can setup a range without limitation */ > -- > 2.26.2 >
Re: [PATCH v4 09/10] powerpc/watchpoint: Return available watchpoints dynamically
On Fri, Jul 17, 2020 at 2:11 PM Ravi Bangoria wrote: > > So far Book3S Powerpc supported only one watchpoint. Power10 is > introducing 2nd DAWR. Enable 2nd DAWR support for Power10. > Availability of 2nd DAWR will depend on CPU_FTR_DAWR1. > > Signed-off-by: Ravi Bangoria > --- > arch/powerpc/include/asm/cputable.h | 4 +++- > arch/powerpc/include/asm/hw_breakpoint.h | 5 +++-- > 2 files changed, 6 insertions(+), 3 deletions(-) > > diff --git a/arch/powerpc/include/asm/cputable.h > b/arch/powerpc/include/asm/cputable.h > index 3445c86e1f6f..36a0851a7a9b 100644 > --- a/arch/powerpc/include/asm/cputable.h > +++ b/arch/powerpc/include/asm/cputable.h > @@ -633,7 +633,9 @@ enum { > * Maximum number of hw breakpoint supported on powerpc. Number of > * breakpoints supported by actual hw might be less than this. > */ > -#define HBP_NUM_MAX1 > +#define HBP_NUM_MAX2 > +#define HBP_NUM_ONE1 > +#define HBP_NUM_TWO2 I wonder if these defines are necessary - has it any advantage over just using the literal? > > #endif /* !__ASSEMBLY__ */ > > diff --git a/arch/powerpc/include/asm/hw_breakpoint.h > b/arch/powerpc/include/asm/hw_breakpoint.h > index cb424799da0d..d4eab1694bcd 100644 > --- a/arch/powerpc/include/asm/hw_breakpoint.h > +++ b/arch/powerpc/include/asm/hw_breakpoint.h > @@ -5,10 +5,11 @@ > * Copyright 2010, IBM Corporation. > * Author: K.Prasad > */ > - Was removing this line deliberate? > #ifndef _PPC_BOOK3S_64_HW_BREAKPOINT_H > #define _PPC_BOOK3S_64_HW_BREAKPOINT_H > > +#include > + > #ifdef __KERNEL__ > struct arch_hw_breakpoint { > unsigned long address; > @@ -46,7 +47,7 @@ struct arch_hw_breakpoint { > > static inline int nr_wp_slots(void) > { > - return HBP_NUM_MAX; > + return cpu_has_feature(CPU_FTR_DAWR1) ? HBP_NUM_TWO : HBP_NUM_ONE; So it'd be something like: + return cpu_has_feature(CPU_FTR_DAWR1) ? HBP_NUM_MAX : 1; But thinking that there might be more slots added in the future, it may be better to make the number of slots a variable that is set during the init and then have this function return that. > } > > #ifdef CONFIG_HAVE_HW_BREAKPOINT > -- > 2.26.2 >
Re: [PATCH v4 07/10] powerpc/watchpoint: Rename current H_SET_MODE DAWR macro
On Fri, Jul 17, 2020 at 2:11 PM Ravi Bangoria wrote: > > Current H_SET_MODE hcall macro name for setting/resetting DAWR0 is > H_SET_MODE_RESOURCE_SET_DAWR. Add suffix 0 to macro name as well. > > Signed-off-by: Ravi Bangoria Reviewed-by: Jordan Niethe > --- > arch/powerpc/include/asm/hvcall.h | 2 +- > arch/powerpc/include/asm/plpar_wrappers.h | 2 +- > arch/powerpc/kvm/book3s_hv.c | 2 +- > 3 files changed, 3 insertions(+), 3 deletions(-) > > diff --git a/arch/powerpc/include/asm/hvcall.h > b/arch/powerpc/include/asm/hvcall.h > index 43486e773bd6..b785e9f0071c 100644 > --- a/arch/powerpc/include/asm/hvcall.h > +++ b/arch/powerpc/include/asm/hvcall.h > @@ -355,7 +355,7 @@ > > /* Values for 2nd argument to H_SET_MODE */ > #define H_SET_MODE_RESOURCE_SET_CIABR 1 > -#define H_SET_MODE_RESOURCE_SET_DAWR 2 > +#define H_SET_MODE_RESOURCE_SET_DAWR0 2 > #define H_SET_MODE_RESOURCE_ADDR_TRANS_MODE3 > #define H_SET_MODE_RESOURCE_LE 4 > > diff --git a/arch/powerpc/include/asm/plpar_wrappers.h > b/arch/powerpc/include/asm/plpar_wrappers.h > index 4293c5d2ddf4..d12c3680d946 100644 > --- a/arch/powerpc/include/asm/plpar_wrappers.h > +++ b/arch/powerpc/include/asm/plpar_wrappers.h > @@ -312,7 +312,7 @@ static inline long plpar_set_ciabr(unsigned long ciabr) > > static inline long plpar_set_watchpoint0(unsigned long dawr0, unsigned long > dawrx0) > { > - return plpar_set_mode(0, H_SET_MODE_RESOURCE_SET_DAWR, dawr0, dawrx0); > + return plpar_set_mode(0, H_SET_MODE_RESOURCE_SET_DAWR0, dawr0, > dawrx0); > } > > static inline long plpar_signal_sys_reset(long cpu) > diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c > index 6bf66649ab92..7ad692c2d7c7 100644 > --- a/arch/powerpc/kvm/book3s_hv.c > +++ b/arch/powerpc/kvm/book3s_hv.c > @@ -764,7 +764,7 @@ static int kvmppc_h_set_mode(struct kvm_vcpu *vcpu, > unsigned long mflags, > return H_P3; > vcpu->arch.ciabr = value1; > return H_SUCCESS; > - case H_SET_MODE_RESOURCE_SET_DAWR: > + case H_SET_MODE_RESOURCE_SET_DAWR0: > if (!kvmppc_power8_compatible(vcpu)) > return H_P2; > if (!ppc_breakpoint_available()) > -- > 2.26.2 >
Re: [PATCH v4 06/10] powerpc/watchpoint: Set CPU_FTR_DAWR1 based on pa-features bit
On Fri, Jul 17, 2020 at 2:10 PM Ravi Bangoria wrote: > > As per the PAPR, bit 0 of byte 64 in pa-features property indicates > availability of 2nd DAWR registers. i.e. If this bit is set, 2nd > DAWR is present, otherwise not. Host generally uses "cpu-features", > which masks "pa-features". But "cpu-features" are still not used for > guests and thus this change is mostly applicable for guests only. > > Signed-off-by: Ravi Bangoria I checked those PAPR values are correct and checked running a powernv kernel in p10 mambo with dt_cpu_ftrs=off and it does set the CPU_FTR_DAWR1 bit. (using p10 skiboot). Tested-by: Jordan Niethe > --- > arch/powerpc/kernel/prom.c | 2 ++ > 1 file changed, 2 insertions(+) > > diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c > index 9cc49f265c86..c76c09b97bc8 100644 > --- a/arch/powerpc/kernel/prom.c > +++ b/arch/powerpc/kernel/prom.c > @@ -175,6 +175,8 @@ static struct ibm_pa_feature { > */ > { .pabyte = 22, .pabit = 0, .cpu_features = CPU_FTR_TM_COMP, > .cpu_user_ftrs2 = PPC_FEATURE2_HTM_COMP | > PPC_FEATURE2_HTM_NOSC_COMP }, > + > + { .pabyte = 64, .pabit = 0, .cpu_features = CPU_FTR_DAWR1 }, > }; > > static void __init scan_features(unsigned long node, const unsigned char > *ftrs, > -- > 2.26.2 >
Re: [PATCH v4 05/10] powerpc/dt_cpu_ftrs: Add feature for 2nd DAWR
On Fri, Jul 17, 2020 at 2:10 PM Ravi Bangoria wrote: > > Add new device-tree feature for 2nd DAWR. If this feature is present, > 2nd DAWR is supported, otherwise not. > > Signed-off-by: Ravi Bangoria > --- > arch/powerpc/include/asm/cputable.h | 7 +-- > arch/powerpc/kernel/dt_cpu_ftrs.c | 7 +++ > 2 files changed, 12 insertions(+), 2 deletions(-) > > diff --git a/arch/powerpc/include/asm/cputable.h > b/arch/powerpc/include/asm/cputable.h > index e506d429b1af..3445c86e1f6f 100644 > --- a/arch/powerpc/include/asm/cputable.h > +++ b/arch/powerpc/include/asm/cputable.h > @@ -214,6 +214,7 @@ static inline void cpu_feature_keys_init(void) { } > #define CPU_FTR_P9_TLBIE_ERAT_BUG LONG_ASM_CONST(0x0001) > #define CPU_FTR_P9_RADIX_PREFETCH_BUG LONG_ASM_CONST(0x0002) > #define CPU_FTR_ARCH_31 > LONG_ASM_CONST(0x0004) > +#define CPU_FTR_DAWR1 LONG_ASM_CONST(0x0008) > > #ifndef __ASSEMBLY__ > > @@ -497,14 +498,16 @@ static inline void cpu_feature_keys_init(void) { } > #define CPU_FTRS_POSSIBLE \ > (CPU_FTRS_POWER7 | CPU_FTRS_POWER8E | CPU_FTRS_POWER8 | \ > CPU_FTR_ALTIVEC_COMP | CPU_FTR_VSX_COMP | CPU_FTRS_POWER9 | \ > -CPU_FTRS_POWER9_DD2_1 | CPU_FTRS_POWER9_DD2_2 | CPU_FTRS_POWER10) > +CPU_FTRS_POWER9_DD2_1 | CPU_FTRS_POWER9_DD2_2 | CPU_FTRS_POWER10 > | \ > +CPU_FTR_DAWR1) > #else > #define CPU_FTRS_POSSIBLE \ > (CPU_FTRS_PPC970 | CPU_FTRS_POWER5 | \ > CPU_FTRS_POWER6 | CPU_FTRS_POWER7 | CPU_FTRS_POWER8E | \ > CPU_FTRS_POWER8 | CPU_FTRS_CELL | CPU_FTRS_PA6T | \ > CPU_FTR_VSX_COMP | CPU_FTR_ALTIVEC_COMP | CPU_FTRS_POWER9 | \ > -CPU_FTRS_POWER9_DD2_1 | CPU_FTRS_POWER9_DD2_2 | CPU_FTRS_POWER10) > +CPU_FTRS_POWER9_DD2_1 | CPU_FTRS_POWER9_DD2_2 | CPU_FTRS_POWER10 > | \ > +CPU_FTR_DAWR1) Instead of putting CPU_FTR_DAWR1 into CPU_FTRS_POSSIBLE should it go into CPU_FTRS_POWER10? Then it will be picked up by CPU_FTRS_POSSIBLE. > #endif /* CONFIG_CPU_LITTLE_ENDIAN */ > #endif > #else > diff --git a/arch/powerpc/kernel/dt_cpu_ftrs.c > b/arch/powerpc/kernel/dt_cpu_ftrs.c > index ac650c233cd9..c78cd3596ec4 100644 > --- a/arch/powerpc/kernel/dt_cpu_ftrs.c > +++ b/arch/powerpc/kernel/dt_cpu_ftrs.c > @@ -574,6 +574,12 @@ static int __init feat_enable_mma(struct dt_cpu_feature > *f) > return 1; > } > > +static int __init feat_enable_debug_facilities_v31(struct dt_cpu_feature *f) > +{ > + cur_cpu_spec->cpu_features |= CPU_FTR_DAWR1; > + return 1; > +} > + > struct dt_cpu_feature_match { > const char *name; > int (*enable)(struct dt_cpu_feature *f); > @@ -649,6 +655,7 @@ static struct dt_cpu_feature_match __initdata > {"wait-v3", feat_enable, 0}, > {"prefix-instructions", feat_enable, 0}, > {"matrix-multiply-assist", feat_enable_mma, 0}, > + {"debug-facilities-v31", feat_enable_debug_facilities_v31, 0}, Since all feat_enable_debug_facilities_v31() does is set CPU_FTR_DAWR1, if you just have: {"debug-facilities-v31", feat_enable, CPU_FTR_DAWR1}, I think cpufeatures_process_feature() should set it in for you at this point: if (m->enable(f)) { cur_cpu_spec->cpu_features |= m->cpu_ftr_bit_mask; break; } > }; > > static bool __initdata using_dt_cpu_ftrs; > -- > 2.26.2 >
Re: [PATCH v4 04/10] powerpc/watchpoint: Enable watchpoint functionality on power10 guest
On Fri, Jul 17, 2020 at 2:10 PM Ravi Bangoria wrote: > > CPU_FTR_DAWR is by default enabled for host via CPU_FTRS_DT_CPU_BASE > (controlled by CONFIG_PPC_DT_CPU_FTRS). But cpu-features device-tree > node is not PAPR compatible and thus not yet used by kvm or pHyp > guests. Enable watchpoint functionality on power10 guest (both kvm > and powervm) by adding CPU_FTR_DAWR to CPU_FTRS_POWER10. Note that > this change does not enable 2nd DAWR support. > > Signed-off-by: Ravi Bangoria I ran the ptrace-hwbreak selftest successfully within a power10 kvm guest. Tested-by: Jordan Niethe > --- > arch/powerpc/include/asm/cputable.h | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/arch/powerpc/include/asm/cputable.h > b/arch/powerpc/include/asm/cputable.h > index bac2252c839e..e506d429b1af 100644 > --- a/arch/powerpc/include/asm/cputable.h > +++ b/arch/powerpc/include/asm/cputable.h > @@ -478,7 +478,7 @@ static inline void cpu_feature_keys_init(void) { } > CPU_FTR_CFAR | CPU_FTR_HVMODE | CPU_FTR_VMX_COPY | \ > CPU_FTR_DBELL | CPU_FTR_HAS_PPR | CPU_FTR_ARCH_207S | \ > CPU_FTR_TM_COMP | CPU_FTR_ARCH_300 | CPU_FTR_PKEY | \ > - CPU_FTR_ARCH_31) > + CPU_FTR_ARCH_31 | CPU_FTR_DAWR) > #define CPU_FTRS_CELL (CPU_FTR_LWSYNC | \ > CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ > CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \ > -- > 2.26.2 >
Re: [PATCH v3 2/9] powerpc/watchpoint: Fix DAWR exception constraint
On Wed, Jul 8, 2020 at 2:52 PM Ravi Bangoria wrote: > > Pedro Miraglia Franco de Carvalho noticed that on p8, DAR value is > inconsistent with different type of load/store. Like for byte,word > etc. load/stores, DAR is set to the address of the first byte of > overlap between watch range and real access. But for quadword load/ > store it's set to the address of the first byte of real access. This > issue has been fixed in p10. In p10(ISA 3.1), DAR is always set to > the address of the first byte of overlap. Commit 27985b2a640e > ("powerpc/watchpoint: Don't ignore extraneous exceptions blindly") > wrongly assumes that DAR is set to the address of the first byte of > overlap for all load/stores on p8 as well. Fix that. With the fix, > we now rely on 'ea' provided by analyse_instr(). If analyse_instr() > fails, generate event unconditionally on p8, and on p10 generate > event only if DAR is within a DAWR range. > > Note: 8xx is not affected. > > Fixes: 27985b2a640e ("powerpc/watchpoint: Don't ignore extraneous exceptions > blindly") > Fixes: 74c6881019b7 ("powerpc/watchpoint: Prepare handler to handle more than > one watchpoint") > Reported-by: Pedro Miraglia Franco de Carvalho > Signed-off-by: Ravi Bangoria > --- > arch/powerpc/kernel/hw_breakpoint.c | 93 +++-- > 1 file changed, 63 insertions(+), 30 deletions(-) > > diff --git a/arch/powerpc/kernel/hw_breakpoint.c > b/arch/powerpc/kernel/hw_breakpoint.c > index 031e6defc08e..7a66c370a105 100644 > --- a/arch/powerpc/kernel/hw_breakpoint.c > +++ b/arch/powerpc/kernel/hw_breakpoint.c > @@ -498,11 +498,11 @@ static bool dar_in_user_range(unsigned long dar, struct > arch_hw_breakpoint *info > return ((info->address <= dar) && (dar - info->address < info->len)); > } > > -static bool dar_user_range_overlaps(unsigned long dar, int size, > - struct arch_hw_breakpoint *info) > +static bool ea_user_range_overlaps(unsigned long ea, int size, > + struct arch_hw_breakpoint *info) > { > - return ((dar < info->address + info->len) && > - (dar + size > info->address)); > + return ((ea < info->address + info->len) && > + (ea + size > info->address)); > } > > static bool dar_in_hw_range(unsigned long dar, struct arch_hw_breakpoint > *info) > @@ -515,20 +515,22 @@ static bool dar_in_hw_range(unsigned long dar, struct > arch_hw_breakpoint *info) > return ((hw_start_addr <= dar) && (hw_end_addr > dar)); > } > > -static bool dar_hw_range_overlaps(unsigned long dar, int size, > - struct arch_hw_breakpoint *info) > +static bool ea_hw_range_overlaps(unsigned long ea, int size, > +struct arch_hw_breakpoint *info) > { > unsigned long hw_start_addr, hw_end_addr; > > hw_start_addr = ALIGN_DOWN(info->address, HW_BREAKPOINT_SIZE); > hw_end_addr = ALIGN(info->address + info->len, HW_BREAKPOINT_SIZE); > > - return ((dar < hw_end_addr) && (dar + size > hw_start_addr)); > + return ((ea < hw_end_addr) && (ea + size > hw_start_addr)); > } > > /* > * If hw has multiple DAWR registers, we also need to check all > * dawrx constraint bits to confirm this is _really_ a valid event. > + * If type is UNKNOWN, but privilege level matches, consider it as > + * a positive match. > */ > static bool check_dawrx_constraints(struct pt_regs *regs, int type, > struct arch_hw_breakpoint *info) > @@ -536,7 +538,12 @@ static bool check_dawrx_constraints(struct pt_regs > *regs, int type, > if (OP_IS_LOAD(type) && !(info->type & HW_BRK_TYPE_READ)) > return false; > > - if (OP_IS_STORE(type) && !(info->type & HW_BRK_TYPE_WRITE)) > + /* > +* The Cache Management instructions other than dcbz never > +* cause a match. i.e. if type is CACHEOP, the instruction > +* is dcbz, and dcbz is treated as Store. > +*/ > + if ((OP_IS_STORE(type) || type == CACHEOP) && !(info->type & > HW_BRK_TYPE_WRITE)) > return false; This change seems seperate to this commit? > > if (is_kernel_addr(regs->nip) && !(info->type & HW_BRK_TYPE_KERNEL)) > @@ -553,7 +560,8 @@ static bool check_dawrx_constraints(struct pt_regs *regs, > int type, > * including extraneous exception. Otherwise return false. > */ > static bool check_constraints(struct pt_regs *regs, struct ppc_inst instr, > - int type, int size, struct arch_hw_breakpoint > *info) > + unsigned long ea, int type, int size, > + struct arch_hw_breakpoint *info) > { > bool in_user_range = dar_in_user_range(regs->dar, info); > bool dawrx_constraints; > @@ -569,11 +577,10 @@ static bool check_constraints(struct pt_regs *regs, > struct ppc_inst instr, > } > > if
Re: [PATCH v3 1/9] powerpc/watchpoint: Fix 512 byte boundary limit
On Wed, Jul 8, 2020 at 2:53 PM Ravi Bangoria wrote: > > Milton Miller reported that we are aligning start and end address to > wrong size SZ_512M. It should be SZ_512. Fix that. > > While doing this change I also found a case where ALIGN() comparison > fails. Within a given aligned range, ALIGN() of two addresses does not > match when start address is pointing to the first byte and end address > is pointing to any other byte except the first one. But that's not true > for ALIGN_DOWN(). ALIGN_DOWN() of any two addresses within that range > will always point to the first byte. So use ALIGN_DOWN() instead of > ALIGN(). > > Fixes: e68ef121c1f4 ("powerpc/watchpoint: Use builtin ALIGN*() macros") > Reported-by: Milton Miller > Signed-off-by: Ravi Bangoria I tested this with the ptrace-hwbreak selftest. Can confirm without also changing to ALIGN_DOWN() then these tests will fail. Tested-by: Jordan Niethe > --- > arch/powerpc/kernel/hw_breakpoint.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/arch/powerpc/kernel/hw_breakpoint.c > b/arch/powerpc/kernel/hw_breakpoint.c > index daf0e1da..031e6defc08e 100644 > --- a/arch/powerpc/kernel/hw_breakpoint.c > +++ b/arch/powerpc/kernel/hw_breakpoint.c > @@ -419,7 +419,7 @@ static int hw_breakpoint_validate_len(struct > arch_hw_breakpoint *hw) > if (dawr_enabled()) { > max_len = DAWR_MAX_LEN; > /* DAWR region can't cross 512 bytes boundary */ > - if (ALIGN(start_addr, SZ_512M) != ALIGN(end_addr - 1, > SZ_512M)) > + if (ALIGN_DOWN(start_addr, SZ_512) != ALIGN_DOWN(end_addr - > 1, SZ_512)) > return -EINVAL; > } else if (IS_ENABLED(CONFIG_PPC_8xx)) { > /* 8xx can setup a range without limitation */ > -- > 2.26.2 >
Re: [PATCH v3 1/9] powerpc/watchpoint: Fix 512 byte boundary limit
On Wed, Jul 8, 2020 at 2:53 PM Ravi Bangoria wrote: > > Milton Miller reported that we are aligning start and end address to > wrong size SZ_512M. It should be SZ_512. Fix that. > > While doing this change I also found a case where ALIGN() comparison > fails. Within a given aligned range, ALIGN() of two addresses does not > match when start address is pointing to the first byte and end address > is pointing to any other byte except the first one. But that's not true > for ALIGN_DOWN(). ALIGN_DOWN() of any two addresses within that range > will always point to the first byte. So use ALIGN_DOWN() instead of > ALIGN(). > > Fixes: e68ef121c1f4 ("powerpc/watchpoint: Use builtin ALIGN*() macros") > Reported-by: Milton Miller > Signed-off-by: Ravi Bangoria > --- > arch/powerpc/kernel/hw_breakpoint.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/arch/powerpc/kernel/hw_breakpoint.c > b/arch/powerpc/kernel/hw_breakpoint.c > index daf0e1da..031e6defc08e 100644 > --- a/arch/powerpc/kernel/hw_breakpoint.c > +++ b/arch/powerpc/kernel/hw_breakpoint.c > @@ -419,7 +419,7 @@ static int hw_breakpoint_validate_len(struct > arch_hw_breakpoint *hw) > if (dawr_enabled()) { > max_len = DAWR_MAX_LEN; > /* DAWR region can't cross 512 bytes boundary */ > - if (ALIGN(start_addr, SZ_512M) != ALIGN(end_addr - 1, > SZ_512M)) > + if (ALIGN_DOWN(start_addr, SZ_512) != ALIGN_DOWN(end_addr - > 1, SZ_512)) I wonder if you should use end_addr - 1, but rather end_addr. For example: 512 -> 1023, because of the -1, 1024 will now be included in this range meaning 513 bytes? > return -EINVAL; > } else if (IS_ENABLED(CONFIG_PPC_8xx)) { > /* 8xx can setup a range without limitation */ > -- > 2.26.2 >
Re: [PATCH 2/6] powerpc test_emulate_step: fix pr_info() to print 8-byte for prefixed instruction
On Mon, Jun 22, 2020 at 5:10 PM Balamuruhan S wrote: > > On test failure, `pr_log()` prints 4 bytes instruction > irrespective of word/prefix instruction, fix it by printing > them appropriately. This patch to add a ppc_inst_as_str() function should help with this, https://patchwork.ozlabs.org/project/linuxppc-dev/patch/20200602052728.18227-1-jniet...@gmail.com/ > > Signed-off-by: Balamuruhan S > --- > arch/powerpc/lib/test_emulate_step.c | 9 - > 1 file changed, 8 insertions(+), 1 deletion(-) > > diff --git a/arch/powerpc/lib/test_emulate_step.c > b/arch/powerpc/lib/test_emulate_step.c > index d5902b7b4e5c..e3b1797adfae 100644 > --- a/arch/powerpc/lib/test_emulate_step.c > +++ b/arch/powerpc/lib/test_emulate_step.c > @@ -1225,7 +1225,14 @@ static int __init emulate_compute_instr(struct pt_regs > *regs, > > if (analyse_instr(, regs, instr) != 1 || > GETTYPE(op.type) != COMPUTE) { > - pr_info("emulation failed, instruction = 0x%08x\n", > ppc_inst_val(instr)); > + if (!ppc_inst_prefixed(instr)) { > + pr_info("emulation failed, instruction = 0x%08x\n", > + ppc_inst_val(instr)); > + } else { > + pr_info("emulation failed, instruction = 0x%08x > 0x%08x\n", > + ppc_inst_val(instr), > + ppc_inst_suffix(instr)); > + } > return -EFAULT; > } > > -- > 2.24.1 >
Re: [PATCH 1/6] powerpc test_emulate_step: update nip with patched instruction address
On Mon, Jun 22, 2020 at 5:10 PM Balamuruhan S wrote: > > pt_regs are initialized to zero in the test infrastructure, R bit > in prefixed instruction form is used to specify whether the effective > address of the storage operand is computed relative to the address > of the instruction. > > If R = 1 and RA = R0|0, the sum of the address of the instruction > and the value SI is placed into register RT. So to assert the emulated > instruction with executed instruction, update nip of emulated pt_regs. > > Signed-off-by: Balamuruhan S > --- > arch/powerpc/lib/test_emulate_step.c | 13 - > 1 file changed, 12 insertions(+), 1 deletion(-) > > diff --git a/arch/powerpc/lib/test_emulate_step.c > b/arch/powerpc/lib/test_emulate_step.c > index 33a72b7d2764..d5902b7b4e5c 100644 > --- a/arch/powerpc/lib/test_emulate_step.c > +++ b/arch/powerpc/lib/test_emulate_step.c > @@ -1204,13 +1204,24 @@ static struct compute_test compute_tests[] = { > static int __init emulate_compute_instr(struct pt_regs *regs, > struct ppc_inst instr) > { > + int prefix_r, ra; > extern s32 patch__exec_instr; > struct instruction_op op; > > if (!regs || !ppc_inst_val(instr)) > return -EINVAL; > > - regs->nip = patch_site_addr(__exec_instr); Is there any harm in just always setting the NIP like this instead of only setting it for relative prefixed instructions? > + /* > +* If R=1 and RA=0 in Prefixed instruction form, calculate the address > +* of the instruction and update nip to assert with executed > +* instruction > +*/ > + if (ppc_inst_prefixed(instr)) { > + prefix_r = ppc_inst_val(instr) & (1UL << 20); > + ra = (ppc_inst_suffix(instr) >> 16) & 0x1f; > + if (prefix_r && !ra) > + regs->nip = patch_site_addr(__exec_instr); > + } > > if (analyse_instr(, regs, instr) != 1 || > GETTYPE(op.type) != COMPUTE) { > -- > 2.24.1 >
Re: [PATCH] powerpc/kvm: Enable support for ISA v3.1 guests
On Tue, Jun 2, 2020 at 3:55 PM Alistair Popple wrote: > > Adds support for emulating ISAv3.1 guests by adding the appropriate PCR > and FSCR bits. > > Signed-off-by: Alistair Popple > --- > arch/powerpc/include/asm/reg.h | 1 + > arch/powerpc/kvm/book3s_hv.c | 11 --- > 2 files changed, 9 insertions(+), 3 deletions(-) > > diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h > index 773f76402392..d77040d0588a 100644 > --- a/arch/powerpc/include/asm/reg.h > +++ b/arch/powerpc/include/asm/reg.h > @@ -1348,6 +1348,7 @@ > #define PVR_ARCH_206p 0x0f13 > #define PVR_ARCH_207 0x0f04 > #define PVR_ARCH_300 0x0f05 > +#define PVR_ARCH_310x0f06 > > /* Macros for setting and retrieving special purpose registers */ > #ifndef __ASSEMBLY__ > diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c > index 93493f0cbfe8..359bb2ed43e1 100644 > --- a/arch/powerpc/kvm/book3s_hv.c > +++ b/arch/powerpc/kvm/book3s_hv.c > @@ -345,7 +345,7 @@ static void kvmppc_set_pvr_hv(struct kvm_vcpu *vcpu, u32 > pvr) > } > > /* Dummy value used in computing PCR value below */ > -#define PCR_ARCH_300 (PCR_ARCH_207 << 1) > +#define PCR_ARCH_31(PCR_ARCH_300 << 1) > > static int kvmppc_set_arch_compat(struct kvm_vcpu *vcpu, u32 arch_compat) > { > @@ -353,7 +353,9 @@ static int kvmppc_set_arch_compat(struct kvm_vcpu *vcpu, > u32 arch_compat) > struct kvmppc_vcore *vc = vcpu->arch.vcore; > > /* We can (emulate) our own architecture version and anything older */ > - if (cpu_has_feature(CPU_FTR_ARCH_300)) > + if (cpu_has_feature(CPU_FTR_ARCH_31)) > + host_pcr_bit = PCR_ARCH_31; > + else if (cpu_has_feature(CPU_FTR_ARCH_300)) > host_pcr_bit = PCR_ARCH_300; > else if (cpu_has_feature(CPU_FTR_ARCH_207S)) > host_pcr_bit = PCR_ARCH_207; > @@ -379,6 +381,9 @@ static int kvmppc_set_arch_compat(struct kvm_vcpu *vcpu, > u32 arch_compat) > case PVR_ARCH_300: > guest_pcr_bit = PCR_ARCH_300; > break; > + case PVR_ARCH_31: > + guest_pcr_bit = PCR_ARCH_31; > + break; > default: > return -EINVAL; > } > @@ -2318,7 +2323,7 @@ static int kvmppc_core_vcpu_create_hv(struct kvm_vcpu > *vcpu) > * to trap and then we emulate them. > */ The comment above this: "... * Set the default HFSCR for the guest from the host value. * This value is only used on POWER9..." would need to be updated. > vcpu->arch.hfscr = HFSCR_TAR | HFSCR_EBB | HFSCR_PM | HFSCR_BHRB | > - HFSCR_DSCR | HFSCR_VECVSX | HFSCR_FP; > + HFSCR_DSCR | HFSCR_VECVSX | HFSCR_FP | HFSCR_PREFIX; > if (cpu_has_feature(CPU_FTR_HVMODE)) { > vcpu->arch.hfscr &= mfspr(SPRN_HFSCR); > if (cpu_has_feature(CPU_FTR_P9_TM_HV_ASSIST)) > -- > 2.20.1 >
[PATCH 4/4] powerpc: Handle prefixed instructions in show_instructions()
Currently show_instructions() treats prefixed instructions as two separate word instructions. '<' and '>' are placed around the instruction at the NIP, but as a result they only wrap around the prefix. Make '<' and '>' straddle the whole prefixed instruction. Currently showing a prefixed instruction looks like: Instruction dump: 6000 6000 6000 6000 6000 6000 6000 6000 6000 6000 6000 6000 <0400> 6000 6000 Make it look like: Instruction dump: 0x6000 0x6000 0x6000 0x6000 0x6000 0x6000 0x6000 0x6000 0x6000 0x6000 0x6000 0x6000 <0x0400 0x> 0x6000 0x6000 0x6000 Signed-off-by: Jordan Niethe --- arch/powerpc/kernel/process.c | 11 ++- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index b3f73e398d00..bcd7277a9395 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -1258,7 +1258,7 @@ static void show_instructions(struct pt_regs *regs) printk("Instruction dump:"); for (i = 0; i < NR_INSN_TO_PRINT; i++) { - int instr; + struct ppc_inst instr; if (!(i % 8)) pr_cont("\n"); @@ -1272,16 +1272,17 @@ static void show_instructions(struct pt_regs *regs) #endif if (!__kernel_text_address(pc) || - probe_kernel_address((const void *)pc, instr)) { + probe_kernel_read_inst(, (struct ppc_inst *)pc)) { + instr = ppc_inst(PPC_INST_NOP); pr_cont(" "); } else { if (regs->nip == pc) - pr_cont("<%08x> ", instr); + pr_cont("<%s> ", ppc_inst_as_str(instr)); else - pr_cont("%08x ", instr); + pr_cont("%s ", ppc_inst_as_str(instr)); } - pc += sizeof(int); + pc += ppc_inst_len(instr); } pr_cont("\n"); -- 2.17.1
[PATCH 3/4] powerpc: Handle prefixed instructions in show_user_instructions()
Currently prefixed instructions are treated as two word instructions by show_user_instructions(), treat them as a single instruction. '<' and '>' are placed around the instruction at the NIP, and for prefixed instructions this is placed around the prefix only. Make the '<' and '>' wrap the prefix and suffix. Currently showing a prefixed instruction looks like: fbe1fff8 3920 0600 a3e3 <0400> f7e4 ebe1fff8 4e800020 Make it look like: 0xfbe1fff8 0x3920 0x0600 0xa3e3 <0x0400 0xf7e4> 0xebe1fff8 0x4e800020 0x 0x0000 Signed-off-by: Jordan Niethe --- arch/powerpc/kernel/process.c | 12 +++- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 048d64c4e115..b3f73e398d00 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -1292,7 +1292,8 @@ void show_user_instructions(struct pt_regs *regs) unsigned long pc; int n = NR_INSN_TO_PRINT; struct seq_buf s; - char buf[96]; /* enough for 8 times 9 + 2 chars */ + char buf[8 * sizeof("0x 0x") + 2]; + struct ppc_inst instr; pc = regs->nip - (NR_INSN_TO_PRINT * 3 / 4 * sizeof(int)); @@ -1303,14 +1304,15 @@ void show_user_instructions(struct pt_regs *regs) seq_buf_clear(); - for (i = 0; i < 8 && n; i++, n--, pc += sizeof(int)) { - int instr; + for (i = 0; i < 8 && n; i++, n--, pc += ppc_inst_len(instr)) { - if (probe_user_read(, (void __user *)pc, sizeof(instr))) { + if (probe_user_read_inst(, (void __user *)pc)) { seq_buf_printf(, " "); + instr = ppc_inst(PPC_INST_NOP); continue; } - seq_buf_printf(, regs->nip == pc ? "<%08x> " : "%08x ", instr); + seq_buf_printf(, regs->nip == pc ? "<%s> " : "%s ", + ppc_inst_as_str(instr)); } if (!seq_buf_has_overflowed()) -- 2.17.1
[PATCH 2/4] powerpc/xmon: Improve dumping prefixed instructions
Currently prefixed instructions are dumped as two separate word instructions. Use mread_instr() so that prefixed instructions are read as such and update the incrementor in the loop to take this into account. 'dump_func' is print_insn_powerpc() which comes from ppc-dis.c which is taken from binutils. When this is updated prefixed instructions will be disassembled. Currently dumping prefixed instructions looks like this: 0:mon> di c0094168 c0094168 0x0600.long 0x600 c009416c 0x392a0003addir9,r10,3 c0094170 0x913f0028stw r9,40(r31) c0094174 0xe93f002alwa r9,40(r31) c0094178 0x7d234b78mr r3,r9 c009417c 0x383f0040addir1,r31,64 c0094180 0xebe1fff8ld r31,-8(r1) c0094184 0x4e800020blr c0094188 0x6000nop ... c0094190 0x3c4c0121addis r2,r12,289 c0094194 0x38429670addir2,r2,-27024 c0094198 0x7c0802a6mflrr0 c009419c 0x6000nop c00941a0 0xe9240100ld r9,256(r4) c00941a4 0x3941li r10,1 After this it looks like: 0:mon> di c0094168 c0094168 0x0600 0x392a0003 .long 0x392a00030600 c0094170 0x913f0028stw r9,40(r31) c0094174 0xe93f002alwa r9,40(r31) c0094178 0x7d234b78mr r3,r9 c009417c 0x383f0040addir1,r31,64 c0094180 0xebe1fff8ld r31,-8(r1) c0094184 0x4e800020blr c0094188 0x6000nop ... c0094190 0x3c4c0121addis r2,r12,289 c0094194 0x38429570addir2,r2,-27280 c0094198 0x7c0802a6mflrr0 c009419c 0x6000nop c00941a0 0xe9240100ld r9,256(r4) c00941a4 0x3941li r10,1 c00941a8 0x3d02000baddis r8,r2,11 Signed-off-by: Jordan Niethe --- arch/powerpc/xmon/xmon.c | 11 ++- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index 1dd3bf02021b..548571536bd1 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c @@ -2935,11 +2935,10 @@ generic_inst_dump(unsigned long adr, long count, int praddr, int nr, dotted; unsigned long first_adr; struct ppc_inst inst, last_inst = ppc_inst(0); - unsigned char val[4]; dotted = 0; - for (first_adr = adr; count > 0; --count, adr += 4) { - nr = mread(adr, val, 4); + for (first_adr = adr; count > 0; --count, adr += ppc_inst_len(inst)) { + nr = mread_instr(adr, ); if (nr == 0) { if (praddr) { const char *x = fault_chars[fault_type]; @@ -2947,7 +2946,6 @@ generic_inst_dump(unsigned long adr, long count, int praddr, } break; } - inst = ppc_inst(GETWORD(val)); if (adr > first_adr && ppc_inst_equal(inst, last_inst)) { if (!dotted) { printf(" ...\n"); @@ -2960,7 +2958,10 @@ generic_inst_dump(unsigned long adr, long count, int praddr, if (praddr) printf(REG" %s", adr, ppc_inst_as_str(inst)); printf("\t"); - dump_func(ppc_inst_val(inst), adr); + if (!ppc_inst_prefixed(inst)) + dump_func(ppc_inst_val(inst), adr); + else + dump_func(ppc_inst_as_u64(inst), adr); printf("\n"); } return adr - first_adr; -- 2.17.1
[PATCH 1/4] powerpc: Add a ppc_inst_as_str() helper
There are quite a few places where instructions are printed, this is done using a '%x' format specifier. With the introduction of prefixed instructions, this does not work well. Currently in these places, ppc_inst_val() is used for the value for %x so only the first word of prefixed instructions are printed. When the instructions are word instructions, only a single word should be printed. For prefixed instructions both the prefix and suffix should be printed. To accommodate both of these situations, instead of a '%x' specifier use '%s' and introduce a helper, __ppc_inst_as_str() which returns a char *. The char * __ppc_inst_as_str() returns is buffer that is passed to it by the caller. It is cumbersome to require every caller of __ppc_inst_as_str() to now declare a buffer. To make it more convenient to use __ppc_inst_as_str(), wrap it in a macro that uses a compound statement to allocate a buffer on the caller's stack before calling it. Signed-off-by: Jordan Niethe --- arch/powerpc/include/asm/inst.h | 19 +++ arch/powerpc/kernel/kprobes.c| 2 +- arch/powerpc/kernel/trace/ftrace.c | 26 +- arch/powerpc/lib/test_emulate_step.c | 4 ++-- arch/powerpc/xmon/xmon.c | 2 +- 5 files changed, 36 insertions(+), 17 deletions(-) diff --git a/arch/powerpc/include/asm/inst.h b/arch/powerpc/include/asm/inst.h index 45f3ec868258..3df7806e6dc3 100644 --- a/arch/powerpc/include/asm/inst.h +++ b/arch/powerpc/include/asm/inst.h @@ -122,6 +122,25 @@ static inline u64 ppc_inst_as_u64(struct ppc_inst x) #endif } +#define PPC_INST_STR_LEN sizeof("0x 0x") + +static inline char *__ppc_inst_as_str(char str[PPC_INST_STR_LEN], struct ppc_inst x) +{ + if (ppc_inst_prefixed(x)) + sprintf(str, "0x%08x 0x%08x", ppc_inst_val(x), ppc_inst_suffix(x)); + else + sprintf(str, "0x%08x", ppc_inst_val(x)); + + return str; +} + +#define ppc_inst_as_str(x) \ +({ \ + char __str[PPC_INST_STR_LEN]; \ + __ppc_inst_as_str(__str, x);\ + __str; \ +}) + int probe_user_read_inst(struct ppc_inst *inst, struct ppc_inst __user *nip); diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c index 227510df8c55..d0797171dba3 100644 --- a/arch/powerpc/kernel/kprobes.c +++ b/arch/powerpc/kernel/kprobes.c @@ -244,7 +244,7 @@ static int try_to_emulate(struct kprobe *p, struct pt_regs *regs) * So, we should never get here... but, its still * good to catch them, just in case... */ - printk("Can't step on instruction %x\n", ppc_inst_val(insn)); + printk("Can't step on instruction %s\n", ppc_inst_as_str(insn)); BUG(); } else { /* diff --git a/arch/powerpc/kernel/trace/ftrace.c b/arch/powerpc/kernel/trace/ftrace.c index 5e399628f51a..da11a26d8213 100644 --- a/arch/powerpc/kernel/trace/ftrace.c +++ b/arch/powerpc/kernel/trace/ftrace.c @@ -73,8 +73,8 @@ ftrace_modify_code(unsigned long ip, struct ppc_inst old, struct ppc_inst new) /* Make sure it is what we expect it to be */ if (!ppc_inst_equal(replaced, old)) { - pr_err("%p: replaced (%#x) != old (%#x)", - (void *)ip, ppc_inst_val(replaced), ppc_inst_val(old)); + pr_err("%p: replaced (%s) != old (%s)", + (void *)ip, ppc_inst_as_str(replaced), ppc_inst_as_str(old)); return -EINVAL; } @@ -137,7 +137,7 @@ __ftrace_make_nop(struct module *mod, /* Make sure that that this is still a 24bit jump */ if (!is_bl_op(op)) { - pr_err("Not expected bl: opcode is %x\n", ppc_inst_val(op)); + pr_err("Not expected bl: opcode is %s\n", ppc_inst_as_str(op)); return -EINVAL; } @@ -172,8 +172,8 @@ __ftrace_make_nop(struct module *mod, /* We expect either a mflr r0, or a std r0, LRSAVE(r1) */ if (!ppc_inst_equal(op, ppc_inst(PPC_INST_MFLR)) && !ppc_inst_equal(op, ppc_inst(PPC_INST_STD_LR))) { - pr_err("Unexpected instruction %08x around bl _mcount\n", - ppc_inst_val(op)); + pr_err("Unexpected instruction %s around bl _mcount\n", + ppc_inst_as_str(op)); return -EINVAL; } #else @@ -203,7 +203,7 @@ __ftrace_make_nop(struct module *mod, } if (!ppc_inst_equal(op, ppc_inst(PPC_INST_LD_TOC))) { - pr_err("Expected %08x found %08x\n", PPC_INST_LD_TOC, ppc_inst_val(op)); + pr_err("Expected %08x found %s\n", PPC_INST_LD_TOC, ppc_inst_as_str(op)); retur
Re: [PATCH] powerpc/64: Remove unused generic_secondary_thread_init()
On Tue, May 26, 2020 at 4:36 PM Michael Ellerman wrote: > > The last caller was removed in 2014 in commit fb5a515704d7 ("powerpc: > Remove platforms/wsp and associated pieces"). > > Once generic_secondary_thread_init() is removed there are no longer > any uses of book3e_secondary_thread_init() or > generic_secondary_common_init so remove them too. > > Signed-off-by: Michael Ellerman > --- > arch/powerpc/include/asm/smp.h | 1 - > arch/powerpc/kernel/exceptions-64e.S | 4 > arch/powerpc/kernel/head_64.S| 18 -- > 3 files changed, 23 deletions(-) > > diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h > index 49a25e2400f2..81a49566ccd8 100644 > --- a/arch/powerpc/include/asm/smp.h > +++ b/arch/powerpc/include/asm/smp.h > @@ -243,7 +243,6 @@ extern void arch_send_call_function_ipi_mask(const struct > cpumask *mask); > * 64-bit but defining them all here doesn't harm > */ > extern void generic_secondary_smp_init(void); > -extern void generic_secondary_thread_init(void); > extern unsigned long __secondary_hold_spinloop; > extern unsigned long __secondary_hold_acknowledge; > extern char __secondary_hold; > diff --git a/arch/powerpc/kernel/exceptions-64e.S > b/arch/powerpc/kernel/exceptions-64e.S > index d9ed79415100..9f9e8686798b 100644 > --- a/arch/powerpc/kernel/exceptions-64e.S > +++ b/arch/powerpc/kernel/exceptions-64e.S > @@ -1814,10 +1814,6 @@ _GLOBAL(book3e_secondary_core_init) > 1: mtlrr28 > blr > > -_GLOBAL(book3e_secondary_thread_init) > - mflrr28 > - b 3b > - > .globl init_core_book3e > init_core_book3e: > /* Establish the interrupt vector base */ > diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S > index 0e05a9a47a4b..4ae2c18c5fc6 100644 > --- a/arch/powerpc/kernel/head_64.S > +++ b/arch/powerpc/kernel/head_64.S > @@ -302,23 +302,6 @@ _GLOBAL(fsl_secondary_thread_init) > 1: > #endif Nothing directly calls generic_secondary_thread_init() but I think fsl_secondary_thread_init() which is directly above "falls through" into it. fsl_secondary_thread_init() still has callers. > > -_GLOBAL(generic_secondary_thread_init) > - mr r24,r3 > - > - /* turn on 64-bit mode */ > - bl enable_64b_mode > - > - /* get a valid TOC pointer, wherever we're mapped at */ > - bl relative_toc > - tovirt(r2,r2) > - > -#ifdef CONFIG_PPC_BOOK3E > - /* Book3E initialization */ > - mr r3,r24 > - bl book3e_secondary_thread_init > -#endif > - b generic_secondary_common_init > - > /* > * On pSeries and most other platforms, secondary processors spin > * in the following code. > @@ -385,7 +368,6 @@ _GLOBAL(generic_secondary_smp_init) > 20: > #endif > > -generic_secondary_common_init: > /* Set up a paca value for this processor. Since we have the > * physical cpu id in r24, we need to search the pacas to find > * which logical id maps to our physical one. > -- > 2.25.1 >
Re: [PATCH] powerpc: Add ppc_inst_as_u64()
On Mon, May 25, 2020 at 3:49 PM Michael Ellerman wrote: > > The code patching code wants to get the value of a struct ppc_inst as Might need to change the wording here as it also gets used in arch_prepare_optimized_kprobe() > a u64 when the instruction is prefixed, so we can pass the u64 down to > __put_user_asm() and write it with a single store. > > This is a bit awkward because the value differs based on the CPU > endianness, so add a helper to do the conversion. > > Signed-off-by: Michael Ellerman > --- > arch/powerpc/include/asm/inst.h | 9 + > arch/powerpc/kernel/optprobes.c | 3 +-- > arch/powerpc/lib/code-patching.c | 8 +--- > 3 files changed, 11 insertions(+), 9 deletions(-) > > diff --git a/arch/powerpc/include/asm/inst.h b/arch/powerpc/include/asm/inst.h > index d82e0c99cfa1..d61e07fb2937 100644 > --- a/arch/powerpc/include/asm/inst.h > +++ b/arch/powerpc/include/asm/inst.h > @@ -100,6 +100,15 @@ static inline int ppc_inst_len(struct ppc_inst x) > return ppc_inst_prefixed(x) ? 8 : 4; > } > > +static inline u64 ppc_inst_as_u64(struct ppc_inst x) > +{ > +#ifdef CONFIG_CPU_LITTLE_ENDIAN > + return (u64)ppc_inst_suffix(x) << 32 | ppc_inst_val(x); > +#else > + return (u64)ppc_inst_val(x) << 32 | ppc_inst_suffix(x); > +#endif > +} > + > int probe_user_read_inst(struct ppc_inst *inst, > struct ppc_inst __user *nip); > > diff --git a/arch/powerpc/kernel/optprobes.c b/arch/powerpc/kernel/optprobes.c > index 3ac105e7faae..69bfe96884e2 100644 > --- a/arch/powerpc/kernel/optprobes.c > +++ b/arch/powerpc/kernel/optprobes.c > @@ -283,8 +283,7 @@ int arch_prepare_optimized_kprobe(struct optimized_kprobe > *op, struct kprobe *p) > * 3. load instruction to be emulated into relevant register, and > */ > temp = ppc_inst_read((struct ppc_inst *)p->ainsn.insn); > - patch_imm64_load_insns(ppc_inst_val(temp) | > ((u64)ppc_inst_suffix(temp) << 32), > - 4, buff + TMPL_INSN_IDX); > + patch_imm64_load_insns(ppc_inst_as_u64(temp), 4, buff + > TMPL_INSN_IDX); > > /* > * 4. branch back from trampoline > diff --git a/arch/powerpc/lib/code-patching.c > b/arch/powerpc/lib/code-patching.c > index 64cf621e5b00..5ecf0d635a8d 100644 > --- a/arch/powerpc/lib/code-patching.c > +++ b/arch/powerpc/lib/code-patching.c > @@ -27,13 +27,7 @@ static int __patch_instruction(struct ppc_inst *exec_addr, > struct ppc_inst instr > if (!ppc_inst_prefixed(instr)) { > __put_user_asm(ppc_inst_val(instr), patch_addr, err, "stw"); > } else { > -#ifdef CONFIG_CPU_LITTLE_ENDIAN > - __put_user_asm((u64)ppc_inst_suffix(instr) << 32 | > - ppc_inst_val(instr), patch_addr, err, "std"); > -#else > - __put_user_asm((u64)ppc_inst_val(instr) << 32 | > - ppc_inst_suffix(instr), patch_addr, err, > "std"); > -#endif > + __put_user_asm(ppc_inst_as_u64(instr), patch_addr, err, > "std"); > } > > if (err) > -- > 2.25.1 > I booted a BE and LE kernel - test_prefixed_patching() worked on both. Also on BE and LE kernels I put optprobes on prefixed and non prefixed instructions. The correct value was passed via r4 to emulate_step(). Tested-by: Jordan Niethe
Re: [PATCH v2] powerpc: Add ppc_inst_next()
P); > + for (; dest < end; dest = ppc_inst_next(dest, )) > + raw_patch_instruction(dest, nop); > > return 0; > } > @@ -405,8 +406,8 @@ static void do_final_fixups(void) > while (src < end) { > inst = ppc_inst_read(src); > raw_patch_instruction(dest, inst); > - src = (void *)src + ppc_inst_len(inst); > - dest = (void *)dest + ppc_inst_len(inst); > + src = ppc_inst_next(src, src); > + dest = ppc_inst_next(dest, dest); > } > #endif > } > diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c > index fb135f2cd6b0..65cf853a4d26 100644 > --- a/arch/powerpc/xmon/xmon.c > +++ b/arch/powerpc/xmon/xmon.c > @@ -939,7 +939,7 @@ static void insert_bpts(void) > } > > patch_instruction(bp->instr, instr); > - patch_instruction((void *)bp->instr + ppc_inst_len(instr), > + patch_instruction(ppc_inst_next(bp->instr, ), > ppc_inst(bpinstr)); > if (bp->enabled & BP_CIABR) > continue; > -- > 2.25.1 > Reviewed-by: Jordan Niethe
[PATCH 5/5] powerpc sstep: Add tests for Prefixed Add Immediate
Use the existing support for testing compute type instructions to test Prefixed Add Immediate (paddi). The R bit of the paddi instruction controls whether current instruction address is used. Add test cases for when R=1 and for R=0. paddi has a 34 bit immediate field formed by concatenating si0 and si1. Add tests for the extreme values of this field. Skip the paddi tests if ISA v3.1 is unsupported. Some of these test cases were added by Balamuruhan S. Signed-off-by: Jordan Niethe --- arch/powerpc/lib/test_emulate_step.c | 127 ++ .../lib/test_emulate_step_exec_instr.S| 1 + 2 files changed, 128 insertions(+) diff --git a/arch/powerpc/lib/test_emulate_step.c b/arch/powerpc/lib/test_emulate_step.c index 579b5db80674..33a72b7d2764 100644 --- a/arch/powerpc/lib/test_emulate_step.c +++ b/arch/powerpc/lib/test_emulate_step.c @@ -105,6 +105,13 @@ ___PPC_RA(a) | ___PPC_RB(b)) #define TEST_ADDC_DOT(t, a, b) ppc_inst(PPC_INST_ADDC | ___PPC_RT(t) | \ ___PPC_RA(a) | ___PPC_RB(b) | 0x1) +#define TEST_PADDI(t, a, i, pr)ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | \ + IMM_H(i), \ + PPC_INST_ADDI | \ + ___PPC_RT(t) | ___PPC_RA(a) | \ + IMM_L(i)) + + #define MAX_SUBTESTS 16 @@ -699,6 +706,11 @@ struct compute_test { } subtests[MAX_SUBTESTS + 1]; }; +/* Extreme values for si0||si1 (the MLS:D-form 34 bit immediate field) */ +#define SI_MIN BIT(33) +#define SI_MAX (BIT(33) - 1) +#define SI_UMAX (BIT(34) - 1) + static struct compute_test compute_tests[] = { { .mnemonic = "nop", @@ -1071,6 +1083,121 @@ static struct compute_test compute_tests[] = { } } } + }, + { + .mnemonic = "paddi", + .cpu_feature = CPU_FTR_ARCH_31, + .subtests = { + { + .descr = "RA = LONG_MIN, SI = SI_MIN, R = 0", + .instr = TEST_PADDI(21, 22, SI_MIN, 0), + .regs = { + .gpr[21] = 0, + .gpr[22] = LONG_MIN, + } + }, + { + .descr = "RA = LONG_MIN, SI = SI_MAX, R = 0", + .instr = TEST_PADDI(21, 22, SI_MAX, 0), + .regs = { + .gpr[21] = 0, + .gpr[22] = LONG_MIN, + } + }, + { + .descr = "RA = LONG_MAX, SI = SI_MAX, R = 0", + .instr = TEST_PADDI(21, 22, SI_MAX, 0), + .regs = { + .gpr[21] = 0, + .gpr[22] = LONG_MAX, + } + }, + { + .descr = "RA = ULONG_MAX, SI = SI_UMAX, R = 0", + .instr = TEST_PADDI(21, 22, SI_UMAX, 0), + .regs = { + .gpr[21] = 0, + .gpr[22] = ULONG_MAX, + } + }, + { + .descr = "RA = ULONG_MAX, SI = 0x1, R = 0", + .instr = TEST_PADDI(21, 22, 0x1, 0), + .regs = { + .gpr[21] = 0, + .gpr[22] = ULONG_MAX, + } + }, + { + .descr = "RA = INT_MIN, SI = SI_MIN, R = 0", + .instr = TEST_PADDI(21, 22, SI_MIN, 0), + .regs = { + .gpr[21] = 0, + .gpr[22] = INT_MIN, + } + }, + { + .descr = "RA = INT_MIN, SI = SI_MAX, R = 0", + .instr = TEST_PADDI(21, 22, SI_MAX, 0), + .regs = { + .gpr[21] = 0, + .gpr[22] = INT_MIN, + } +
[PATCH 4/5] powerpc sstep: Let compute tests specify a required cpu feature
An a array of struct compute_test's are used to declare tests for compute instructions. Add a cpu_feature field to struct compute_test as an optional way to specify a cpu feature that must be present. If not present then skip the test. Signed-off-by: Jordan Niethe --- arch/powerpc/lib/test_emulate_step.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/arch/powerpc/lib/test_emulate_step.c b/arch/powerpc/lib/test_emulate_step.c index 427c2ca8191e..579b5db80674 100644 --- a/arch/powerpc/lib/test_emulate_step.c +++ b/arch/powerpc/lib/test_emulate_step.c @@ -690,6 +690,7 @@ static void __init run_tests_load_store(void) struct compute_test { char *mnemonic; + unsigned long cpu_feature; struct { char *descr; unsigned long flags; @@ -1133,6 +1134,11 @@ static void __init run_tests_compute(void) for (i = 0; i < ARRAY_SIZE(compute_tests); i++) { test = _tests[i]; + if (test->cpu_feature && !early_cpu_has_feature(test->cpu_feature)) { + show_result(test->mnemonic, "SKIP (!CPU_FTR)"); + continue; + } + for (j = 0; j < MAX_SUBTESTS && test->subtests[j].descr; j++) { instr = test->subtests[j].instr; flags = test->subtests[j].flags; -- 2.17.1
[PATCH 3/5] powerpc sstep: Set NIP in instruction emulation tests
The tests for emulation of compute instructions execute and emulate an instruction and then compare the results to verify the emulation. In ISA v3.1 there are instructions that operate relative to the NIP. Therefore set the NIP in the regs used for the emulated instruction to the location of the executed instruction so they will give the same result. This is a rework of a patch by Balamuruhan S. Signed-off-by: Jordan Niethe --- arch/powerpc/lib/test_emulate_step.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/powerpc/lib/test_emulate_step.c b/arch/powerpc/lib/test_emulate_step.c index 9599f3a03ca1..427c2ca8191e 100644 --- a/arch/powerpc/lib/test_emulate_step.c +++ b/arch/powerpc/lib/test_emulate_step.c @@ -1076,11 +1076,14 @@ static struct compute_test compute_tests[] = { static int __init emulate_compute_instr(struct pt_regs *regs, struct ppc_inst instr) { + extern s32 patch__exec_instr; struct instruction_op op; if (!regs || !ppc_inst_val(instr)) return -EINVAL; + regs->nip = patch_site_addr(__exec_instr); + if (analyse_instr(, regs, instr) != 1 || GETTYPE(op.type) != COMPUTE) { pr_info("emulation failed, instruction = 0x%08x\n", ppc_inst_val(instr)); -- 2.17.1
[PATCH 2/5] powerpc sstep: Add tests for prefixed floating-point load/stores
Add tests for the prefixed versions of the floating-point load/stores that are currently tested. This includes the following instructions: * Prefixed Load Floating-Point Single (plfs) * Prefixed Load Floating-Point Double (plfd) * Prefixed Store Floating-Point Single (pstfs) * Prefixed Store Floating-Point Double (pstfd) Skip the new tests if ISA v3.10 is unsupported. Signed-off-by: Jordan Niethe --- arch/powerpc/include/asm/ppc-opcode.h | 4 + arch/powerpc/lib/test_emulate_step.c | 136 ++ 2 files changed, 140 insertions(+) diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h index 9e3ecb42597e..6b5edec0e347 100644 --- a/arch/powerpc/include/asm/ppc-opcode.h +++ b/arch/powerpc/include/asm/ppc-opcode.h @@ -371,9 +371,13 @@ #define PPC_INST_LBZCIX0x7c0006aa #define PPC_INST_STBCIX0x7c0007aa #define PPC_INST_LWZX 0x7c2e +#define PPC_INST_LFS 0xc000 #define PPC_INST_LFSX 0x7c00042e +#define PPC_INST_STFS 0xd000 #define PPC_INST_STFSX 0x7c00052e +#define PPC_INST_LFD 0xc800 #define PPC_INST_LFDX 0x7c0004ae +#define PPC_INST_STFD 0xd800 #define PPC_INST_STFDX 0x7c0005ae #define PPC_INST_LVX 0x7cce #define PPC_INST_STVX 0x7c0001ce diff --git a/arch/powerpc/lib/test_emulate_step.c b/arch/powerpc/lib/test_emulate_step.c index 8d8953b5fe90..9599f3a03ca1 100644 --- a/arch/powerpc/lib/test_emulate_step.c +++ b/arch/powerpc/lib/test_emulate_step.c @@ -57,12 +57,40 @@ ___PPC_RA(a) | ___PPC_RB(b)) #define TEST_LFSX(t, a, b) ppc_inst(PPC_INST_LFSX | ___PPC_RT(t) | \ ___PPC_RA(a) | ___PPC_RB(b)) +#define TEST_PLFS(r, base, i, pr) ppc_inst_prefix(PPC_PREFIX_MLS | \ + __PPC_PRFX_R(pr) | \ + IMM_H(i), \ + PPC_INST_LFS | \ + ___PPC_RT(r) | \ + ___PPC_RA(base) | \ + IMM_L(i)) #define TEST_STFSX(s, a, b)ppc_inst(PPC_INST_STFSX | ___PPC_RS(s) | \ ___PPC_RA(a) | ___PPC_RB(b)) +#define TEST_PSTFS(r, base, i, pr) ppc_inst_prefix(PPC_PREFIX_MLS | \ + __PPC_PRFX_R(pr) | \ + IMM_H(i), \ + PPC_INST_STFS | \ + ___PPC_RT(r) | \ + ___PPC_RA(base) | \ + IMM_L(i)) #define TEST_LFDX(t, a, b) ppc_inst(PPC_INST_LFDX | ___PPC_RT(t) | \ ___PPC_RA(a) | ___PPC_RB(b)) +#define TEST_PLFD(r, base, i, pr) ppc_inst_prefix(PPC_PREFIX_MLS | \ + __PPC_PRFX_R(pr) | \ + IMM_H(i), \ + PPC_INST_LFD | \ + ___PPC_RT(r) | \ + ___PPC_RA(base) | \ + IMM_L(i)) #define TEST_STFDX(s, a, b)ppc_inst(PPC_INST_STFDX | ___PPC_RS(s) | \ ___PPC_RA(a) | ___PPC_RB(b)) +#define TEST_PSTFD(r, base, i, pr) ppc_inst_prefix(PPC_PREFIX_MLS | \ + __PPC_PRFX_R(pr) | \ + IMM_H(i), \ + PPC_INST_STFD | \ + ___PPC_RT(r) | \ + ___PPC_RA(base) | \ + IMM_L(i)) #define TEST_LVX(t, a, b) ppc_inst(PPC_INST_LVX | ___PPC_RT(t) | \ ___PPC_RA(a) | ___PPC_RB(b)) #define TEST_STVX(s, a, b) ppc_inst(PPC_INST_STVX | ___PPC_RS(s) | \ @@ -357,6 +385,53 @@ static void __init test_lfsx_stfsx(void) show_result("stfsx", "FAIL"); } +static void __init test_plfs_pstfs(void) +{ + struct pt_regs regs; + union { + float a; + int b; + } c; + int cached_b; +
[PATCH 1/5] powerpc sstep: Add tests for prefixed integer load/stores
Add tests for the prefixed versions of the integer load/stores that are currently tested. This includes the following instructions: * Prefixed Load Doubleword (pld) * Prefixed Load Word and Zero (plwz) * Prefixed Store Doubleword (pstd) Skip the new tests if ISA v3.1 is unsupported. Signed-off-by: Jordan Niethe --- arch/powerpc/include/asm/ppc-opcode.h | 9 +++ arch/powerpc/lib/test_emulate_step.c | 95 +++ 2 files changed, 104 insertions(+) diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h index 2a39c716c343..9e3ecb42597e 100644 --- a/arch/powerpc/include/asm/ppc-opcode.h +++ b/arch/powerpc/include/asm/ppc-opcode.h @@ -380,6 +380,14 @@ #define PPC_INST_VCMPEQUD 0x10c7 #define PPC_INST_VCMPEQUB 0x1006 +/* Prefixes */ +#define PPC_PREFIX_MLS 0x0600 +#define PPC_PREFIX_8LS 0x0400 + +/* Prefixed instructions */ +#define PPC_INST_PLD 0xe400 +#define PPC_INST_PSTD 0xf400 + /* macros to insert fields into opcodes */ #define ___PPC_RA(a) (((a) & 0x1f) << 16) #define ___PPC_RB(b) (((b) & 0x1f) << 11) @@ -411,6 +419,7 @@ #define __PPC_CT(t)(((t) & 0x0f) << 21) #define __PPC_SPR(r) r) & 0x1f) << 16) | r) >> 5) & 0x1f) << 11)) #define __PPC_RC21 (0x1 << 10) +#define __PPC_PRFX_R(r)(((r) & 0x1) << 20) /* * Both low and high 16 bits are added as SIGNED additions, so if low 16 bits diff --git a/arch/powerpc/lib/test_emulate_step.c b/arch/powerpc/lib/test_emulate_step.c index 46af80279ebc..8d8953b5fe90 100644 --- a/arch/powerpc/lib/test_emulate_step.c +++ b/arch/powerpc/lib/test_emulate_step.c @@ -15,6 +15,7 @@ #define IMM_L(i) ((uintptr_t)(i) & 0x) #define IMM_DS(i) ((uintptr_t)(i) & 0xfffc) +#define IMM_H(i) (((uintptr_t)(i) >> 16) & 0x3) /* * Defined with TEST_ prefix so it does not conflict with other @@ -22,12 +23,33 @@ */ #define TEST_LD(r, base, i)ppc_inst(PPC_INST_LD | ___PPC_RT(r) | \ ___PPC_RA(base) | IMM_DS(i)) +#define TEST_PLD(r, base, i, pr) ppc_inst_prefix(PPC_PREFIX_8LS | \ + __PPC_PRFX_R(pr) | \ + IMM_H(i), \ + PPC_INST_PLD | \ + ___PPC_RT(r) | \ + ___PPC_RA(base) | \ + IMM_L(i)) #define TEST_LWZ(r, base, i) ppc_inst(PPC_INST_LWZ | ___PPC_RT(r) | \ ___PPC_RA(base) | IMM_L(i)) +#define TEST_PLWZ(r, base, i, pr) ppc_inst_prefix(PPC_PREFIX_MLS | \ + __PPC_PRFX_R(pr) | \ + IMM_H(i), \ + PPC_INST_LWZ | \ + ___PPC_RT(r) | \ + ___PPC_RA(base) | \ + IMM_L(i)) #define TEST_LWZX(t, a, b) ppc_inst(PPC_INST_LWZX | ___PPC_RT(t) | \ ___PPC_RA(a) | ___PPC_RB(b)) #define TEST_STD(r, base, i) ppc_inst(PPC_INST_STD | ___PPC_RS(r) | \ ___PPC_RA(base) | IMM_DS(i)) +#define TEST_PSTD(r, base, i, pr) ppc_inst_prefix(PPC_PREFIX_8LS | \ + __PPC_PRFX_R(pr) | \ + IMM_H(i), \ + PPC_INST_PSTD | \ + ___PPC_RT(r) | \ + ___PPC_RA(base) | \ + IMM_L(i)) #define TEST_LDARX(t, a, b, eh)ppc_inst(PPC_INST_LDARX | ___PPC_RT(t) |\ ___PPC_RA(a) | ___PPC_RB(b) | \ __PPC_EH(eh)) @@ -113,6 +135,29 @@ static void __init test_ld(void) show_result("ld", "FAIL"); } +static void __init test_pld(void) +{ + struct pt_regs regs; + unsigned long a = 0x23; + int stepped = -1; + + if (!cpu_has_feature(CPU_FTR_ARCH_31)) { + show_result("pld", "SKIP (!CPU_FTR_ARCH_31)"); + return; + } + + init_pt_regs(); + regs.gpr[3] = (unsigned long)
Re: [PATCH] powerpc: Add ppc_inst_next()
On Wed, May 20, 2020 at 9:44 PM Michael Ellerman wrote: > > In a few places we want to calculate the address of the next > instruction. Previously that was simple, we just added 4 bytes, or if > using a u32 * we incremented that pointer by 1. > > But prefixed instructions make it more complicated, we need to advance > by either 4 or 8 bytes depending on the actual instruction. We also > can't do pointer arithmetic using struct ppc_inst, because it is > always 8 bytes in size on 64-bit, even though we might only need to > advance by 4 bytes. > > So add a ppc_inst_next() helper which calculates the location of the > next instruction, if the given instruction was located at the given > address. Note the instruction doesn't need to actually be at the > address in memory. > > Convert several locations to use it. > > Signed-off-by: Michael Ellerman > --- > arch/powerpc/include/asm/inst.h | 9 + > arch/powerpc/kernel/uprobes.c | 2 +- > arch/powerpc/lib/feature-fixups.c | 10 +- > arch/powerpc/xmon/xmon.c | 2 +- > 4 files changed, 16 insertions(+), 7 deletions(-) > > diff --git a/arch/powerpc/include/asm/inst.h b/arch/powerpc/include/asm/inst.h > index d82e0c99cfa1..7d5ee1309b92 100644 > --- a/arch/powerpc/include/asm/inst.h > +++ b/arch/powerpc/include/asm/inst.h > @@ -100,6 +100,15 @@ static inline int ppc_inst_len(struct ppc_inst x) > return ppc_inst_prefixed(x) ? 8 : 4; > } > > +/* > + * Return the address of the next instruction, if the instruction @value was > + * located at @location. > + */ > +static inline struct ppc_inst *ppc_inst_next(void *location, struct ppc_inst > value) > +{ > + return location + ppc_inst_len(value); > +} I think this is a good idea. I tried something similar in the initial post for an instruction type. I had: +#define PPC_INST_NEXT(ptr) ((ptr) += PPC_INST_LEN(DEREF_PPC_INST_PTR((ptr but how you've got it is much more clear/usable. I wonder why not +static inline struct ppc_inst *ppc_inst_next(void *location) +{ + return location + ppc_inst_len(ppc_inst_read((struct ppc_inst *)location); +} > + > int probe_user_read_inst(struct ppc_inst *inst, > struct ppc_inst __user *nip); > > diff --git a/arch/powerpc/kernel/uprobes.c b/arch/powerpc/kernel/uprobes.c > index 83e883e1a42d..683ba76919a7 100644 > --- a/arch/powerpc/kernel/uprobes.c > +++ b/arch/powerpc/kernel/uprobes.c > @@ -112,7 +112,7 @@ int arch_uprobe_post_xol(struct arch_uprobe *auprobe, > struct pt_regs *regs) > * support doesn't exist and have to fix-up the next instruction > * to be executed. > */ > - regs->nip = utask->vaddr + > ppc_inst_len(ppc_inst_read(>insn)); > + regs->nip = (unsigned long)ppc_inst_next((void *)utask->vaddr, > auprobe->insn); > > user_disable_single_step(current); > return 0; > diff --git a/arch/powerpc/lib/feature-fixups.c > b/arch/powerpc/lib/feature-fixups.c > index 80f320c2e189..0ad01eebf112 100644 > --- a/arch/powerpc/lib/feature-fixups.c > +++ b/arch/powerpc/lib/feature-fixups.c > @@ -84,13 +84,13 @@ static int patch_feature_section(unsigned long value, > struct fixup_entry *fcur) > src = alt_start; > dest = start; > > - for (; src < alt_end; src = (void *)src + > ppc_inst_len(ppc_inst_read(src)), > -(dest = (void *)dest + ppc_inst_len(ppc_inst_read(dest { > + for (; src < alt_end; src = ppc_inst_next(src, *src), > + dest = ppc_inst_next(dest, *dest)) { The reason to maybe use ppc_inst_read() in the helper instead of just *dest would be we don't always need to read 8 bytes. > if (patch_alt_instruction(src, dest, alt_start, alt_end)) > return 1; > } > > - for (; dest < end; dest = (void *)dest + > ppc_inst_len(ppc_inst(PPC_INST_NOP))) > + for (; dest < end; dest = ppc_inst_next(dest, ppc_inst(PPC_INST_NOP))) But then you wouldn't be able to do this as easily I guess. > raw_patch_instruction(dest, ppc_inst(PPC_INST_NOP)); > > return 0; > @@ -405,8 +405,8 @@ static void do_final_fixups(void) > while (src < end) { > inst = ppc_inst_read(src); > raw_patch_instruction(dest, inst); > - src = (void *)src + ppc_inst_len(inst); > - dest = (void *)dest + ppc_inst_len(inst); > + src = ppc_inst_next(src, *src); > + dest = ppc_inst_next(dest, *dest); > } > #endif > } > diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c > index fb135f2cd6b0..aa123f56b7d4 100644 > --- a/arch/powerpc/xmon/xmon.c > +++ b/arch/powerpc/xmon/xmon.c > @@ -939,7 +939,7 @@ static void insert_bpts(void) > } > > patch_instruction(bp->instr, instr); > - patch_instruction((void *)bp->instr + ppc_inst_len(instr), > + patch_instruction(ppc_inst_next(bp->instr,
[PATCH 2/2] selftests/powerpc: Add prefixed loads/stores to alignment_handler test
Extend the alignment handler selftest to exercise prefixed load store instructions. Add tests for prefixed VSX, floating point and integer instructions. Skip prefix tests if ISA version does not support prefixed instructions. Signed-off-by: Jordan Niethe --- .../powerpc/alignment/alignment_handler.c | 93 ++- .../selftests/powerpc/include/instructions.h | 77 +++ .../testing/selftests/powerpc/include/utils.h | 5 + 3 files changed, 172 insertions(+), 3 deletions(-) diff --git a/tools/testing/selftests/powerpc/alignment/alignment_handler.c b/tools/testing/selftests/powerpc/alignment/alignment_handler.c index eb6aba323f8b..e582e68b3b5b 100644 --- a/tools/testing/selftests/powerpc/alignment/alignment_handler.c +++ b/tools/testing/selftests/powerpc/alignment/alignment_handler.c @@ -58,6 +58,7 @@ #include #include "utils.h" +#include "instructions.h" int bufsize; int debug; @@ -96,6 +97,17 @@ void sighandler(int sig, siginfo_t *info, void *ctx) } \ rc |= do_test(#name, test_##name) +#define TESTP(name, ld_op, st_op, ld_reg, st_reg) \ + void test_##name(char *s, char *d) \ + { \ + asm volatile( \ + ld_op(ld_reg, %0, 0, 0) \ + st_op(st_reg, %1, 0, 0) \ + :: "r"(s), "r"(d), "r"(0) \ + : "memory", "vs0", "vs32", "r31"); \ + } \ + rc |= do_test(#name, test_##name) + #define LOAD_VSX_XFORM_TEST(op) TEST(op, op, stxvd2x, XFORM, 32, 32) #define STORE_VSX_XFORM_TEST(op) TEST(op, lxvd2x, op, XFORM, 32, 32) #define LOAD_VSX_DFORM_TEST(op) TEST(op, op, stxv, DFORM, 32, 32) @@ -115,6 +127,17 @@ void sighandler(int sig, siginfo_t *info, void *ctx) #define LOAD_FLOAT_XFORM_TEST(op) TEST(op, op, stfdx, XFORM, 0, 0) #define STORE_FLOAT_XFORM_TEST(op) TEST(op, lfdx, op, XFORM, 0, 0) +#define LOAD_MLS_PREFIX_TEST(op) TESTP(op, op, PSTD, 31, 31) +#define STORE_MLS_PREFIX_TEST(op) TESTP(op, PLD, op, 31, 31) + +#define LOAD_8LS_PREFIX_TEST(op) TESTP(op, op, PSTD, 31, 31) +#define STORE_8LS_PREFIX_TEST(op) TESTP(op, PLD, op, 31, 31) + +#define LOAD_FLOAT_MLS_PREFIX_TEST(op) TESTP(op, op, PSTFD, 0, 0) +#define STORE_FLOAT_MLS_PREFIX_TEST(op) TESTP(op, PLFD, op, 0, 0) + +#define LOAD_VSX_8LS_PREFIX_TEST(op, tail) TESTP(op, op, PSTXV ## tail, 0, 32) +#define STORE_VSX_8LS_PREFIX_TEST(op, tail) TESTP(op, PLXV ## tail, op, 32, 0) /* FIXME: Unimplemented tests: */ // STORE_DFORM_TEST(stq) /* FIXME: need two registers for quad */ @@ -361,6 +384,25 @@ int test_alignment_handler_vsx_300(void) return rc; } +int test_alignment_handler_vsx_prefix(void) +{ + int rc = 0; + + SKIP_IF(!can_open_cifile()); + SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_10)); + + printf("VSX: PREFIX\n"); + LOAD_VSX_8LS_PREFIX_TEST(PLXSD, 0); + LOAD_VSX_8LS_PREFIX_TEST(PLXSSP, 0); + LOAD_VSX_8LS_PREFIX_TEST(PLXV0, 0); + LOAD_VSX_8LS_PREFIX_TEST(PLXV1, 1); + STORE_VSX_8LS_PREFIX_TEST(PSTXSD, 0); + STORE_VSX_8LS_PREFIX_TEST(PSTXSSP, 0); + STORE_VSX_8LS_PREFIX_TEST(PSTXV0, 0); + STORE_VSX_8LS_PREFIX_TEST(PSTXV1, 1); + return rc; +} + int test_alignment_handler_integer(void) { int rc = 0; @@ -432,6 +474,27 @@ int test_alignment_handler_integer_206(void) return rc; } +int test_alignment_handler_integer_prefix(void) +{ + int rc = 0; + + SKIP_IF(!can_open_cifile()); + SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_10)); + + printf("Integer: PREFIX\n"); + LOAD_MLS_PREFIX_TEST(PLBZ); + LOAD_MLS_PREFIX_TEST(PLHZ); + LOAD_MLS_PREFIX_TEST(PLHA); + LOAD_MLS_PREFIX_TEST(PLWZ); + LOAD_8LS_PREFIX_TEST(PLWA); + LOAD_8LS_PREFIX_TEST(PLD); + STORE_MLS_PREFIX_TEST(PSTB); + STORE_MLS_PREFIX_TEST(PSTH); + STORE_MLS_PREFIX_TEST(PSTW); + STORE_8LS_PREFIX_TEST(PSTD); + return rc; +} + int test_alignment_handler_vmx(void) { int rc = 0; @@ -520,14 +583,32 @@ int test_alignment_handler_fp_206(void) return rc; } + +int test_alignment_handler_fp_prefix(void) +{ + int rc = 0; + + SKIP_IF(!can_open_cifile()); + SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_10)); + + printf("Floating point: PREFIX\n"); + LOAD_FLOAT_DFORM_TEST(lfs); + LOAD_FLOAT_MLS_PREFIX_TEST(PLFS); + LOAD_FLOAT_MLS_PREFIX_TEST(PLFD); + STORE_FLOAT_MLS_PREFIX_TEST(PSTFS); + STORE_FLOAT_MLS_PREFIX_TEST(PSTFD); + return rc; +} + void usage(char *prog) { printf(&
[PATCH 1/2] selftests/powerpc: Allow choice of CI memory location in alignment_handler test
The alignment handler selftest needs cache-inhibited memory and currently /dev/fb0 is relied on to provided this. This prevents running the test on systems without /dev/fb0 (e.g., mambo). Read the commandline arguments for an optional path to be used instead, as well as an optional offset to be for mmaping this path. Signed-off-by: Jordan Niethe --- .../powerpc/alignment/alignment_handler.c | 63 --- 1 file changed, 42 insertions(+), 21 deletions(-) diff --git a/tools/testing/selftests/powerpc/alignment/alignment_handler.c b/tools/testing/selftests/powerpc/alignment/alignment_handler.c index 0453c50c949c..eb6aba323f8b 100644 --- a/tools/testing/selftests/powerpc/alignment/alignment_handler.c +++ b/tools/testing/selftests/powerpc/alignment/alignment_handler.c @@ -9,7 +9,17 @@ * This selftest exercises the powerpc alignment fault handler. * * We create two sets of source and destination buffers, one in regular memory, - * the other cache-inhibited (we use /dev/fb0 for this). + * the other cache-inhibited (by default we use /dev/fb0 for this, but an + * alterative path for cache-inhibited memory may be provided). + * + * One way to get cache-inhibited memory is to use the "mem" kernel parameter + * to limit the kernel to less memory than actually exists. Addresses above + * the limit may still be accessed but will be treated as cache-inhibited. For + * example, if there is actually 4GB of memory and the parameter "mem=3GB" is + * used, memory from address 0xC000 onwards is treated as cache-inhibited. + * To access this region /dev/mem is used. The kernel should be configured + * without CONFIG_STRICT_DEVMEM. In this case use: + * ./alignment_handler /dev/mem 0xc000 * * We initialise the source buffers, then use whichever set of load/store * instructions is under test to copy bytes from the source buffers to the @@ -53,6 +63,8 @@ int bufsize; int debug; int testing; volatile int gotsig; +char *cipath = "/dev/fb0"; +long cioffset; void sighandler(int sig, siginfo_t *info, void *ctx) { @@ -195,17 +207,18 @@ int do_test(char *test_name, void (*test_func)(char *, char *)) printf("\tDoing %s:\t", test_name); - fd = open("/dev/fb0", O_RDWR); + fd = open(cipath, O_RDWR); if (fd < 0) { printf("\n"); - perror("Can't open /dev/fb0 now?"); + perror("Can't open ci file now?"); return 1; } - ci0 = mmap(NULL, bufsize, PROT_WRITE, MAP_SHARED, - fd, 0x0); - ci1 = mmap(NULL, bufsize, PROT_WRITE, MAP_SHARED, - fd, bufsize); + ci0 = mmap(NULL, bufsize, PROT_WRITE | PROT_READ, MAP_SHARED, + fd, cioffset); + ci1 = mmap(NULL, bufsize, PROT_WRITE | PROT_READ, MAP_SHARED, + fd, cioffset + bufsize); + if ((ci0 == MAP_FAILED) || (ci1 == MAP_FAILED)) { printf("\n"); perror("mmap failed"); @@ -270,11 +283,11 @@ int do_test(char *test_name, void (*test_func)(char *, char *)) return rc; } -static bool can_open_fb0(void) +static bool can_open_cifile(void) { int fd; - fd = open("/dev/fb0", O_RDWR); + fd = open(cipath, O_RDWR); if (fd < 0) return false; @@ -286,7 +299,7 @@ int test_alignment_handler_vsx_206(void) { int rc = 0; - SKIP_IF(!can_open_fb0()); + SKIP_IF(!can_open_cifile()); SKIP_IF(!have_hwcap(PPC_FEATURE_ARCH_2_06)); printf("VSX: 2.06B\n"); @@ -304,7 +317,7 @@ int test_alignment_handler_vsx_207(void) { int rc = 0; - SKIP_IF(!can_open_fb0()); + SKIP_IF(!can_open_cifile()); SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_2_07)); printf("VSX: 2.07B\n"); @@ -320,7 +333,7 @@ int test_alignment_handler_vsx_300(void) { int rc = 0; - SKIP_IF(!can_open_fb0()); + SKIP_IF(!can_open_cifile()); SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_00)); printf("VSX: 3.00B\n"); @@ -352,7 +365,7 @@ int test_alignment_handler_integer(void) { int rc = 0; - SKIP_IF(!can_open_fb0()); + SKIP_IF(!can_open_cifile()); printf("Integer\n"); LOAD_DFORM_TEST(lbz); @@ -408,7 +421,7 @@ int test_alignment_handler_integer_206(void) { int rc = 0; - SKIP_IF(!can_open_fb0()); + SKIP_IF(!can_open_cifile()); SKIP_IF(!have_hwcap(PPC_FEATURE_ARCH_2_06)); printf("Integer: 2.06\n"); @@ -423,7 +436,7 @@ int test_alignment_handler_vmx(void) { int rc = 0; - SKIP_IF(!can_open_fb0()); + SKIP_IF(!can_open_cifile()); SKIP_IF(!have_hwcap(PPC_FEATURE_HAS_ALTIVEC)); printf("VMX\n"); @@ -451,7 +464,7 @@ int test_alignment_handler_
Re: [PATCH v2 2/7] powerpc: Add support for ISA v3.1
On Tue, May 19, 2020 at 10:39 AM Alistair Popple wrote: > > Newer ISA versions are enabled by clearing all bits in the PCR > associated with previous versions of the ISA. Enable ISA v3.1 support > by updating the PCR mask to include ISA v3.0. This ensures all PCR > bits corresponding to earlier architecture versions get cleared > thereby enabling ISA v3.1 if supported by the hardware. > > Signed-off-by: Alistair Popple > --- > arch/powerpc/include/asm/cputable.h | 1 + > arch/powerpc/include/asm/reg.h | 3 ++- > arch/powerpc/kvm/book3s_hv.c| 3 --- > 3 files changed, 3 insertions(+), 4 deletions(-) > > diff --git a/arch/powerpc/include/asm/cputable.h > b/arch/powerpc/include/asm/cputable.h > index 40a4d3c6fd99..36f894dea9e7 100644 > --- a/arch/powerpc/include/asm/cputable.h > +++ b/arch/powerpc/include/asm/cputable.h > @@ -213,6 +213,7 @@ static inline void cpu_feature_keys_init(void) { } > #define CPU_FTR_P9_TIDR > LONG_ASM_CONST(0x8000) > #define CPU_FTR_P9_TLBIE_ERAT_BUG LONG_ASM_CONST(0x0001) > #define CPU_FTR_P9_RADIX_PREFETCH_BUG LONG_ASM_CONST(0x0002) > +#define CPU_FTR_ARCH_31 > LONG_ASM_CONST(0x0004) > > #ifndef __ASSEMBLY__ > > diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h > index 773f76402392..1931b1142599 100644 > --- a/arch/powerpc/include/asm/reg.h > +++ b/arch/powerpc/include/asm/reg.h > @@ -485,10 +485,11 @@ > * determine both the compatibility level which we want to emulate and the > * compatibility level which the host is capable of emulating. > */ > +#define PCR_ARCH_300 0x10/* Architecture 3.00 */ > #define PCR_ARCH_207 0x8 /* Architecture 2.07 */ > #define PCR_ARCH_206 0x4 /* Architecture 2.06 */ > #define PCR_ARCH_205 0x2 /* Architecture 2.05 */ > -#define PCR_LOW_BITS (PCR_ARCH_207 | PCR_ARCH_206 | PCR_ARCH_205) > +#define PCR_LOW_BITS (PCR_ARCH_207 | PCR_ARCH_206 | PCR_ARCH_205 | > PCR_ARCH_300) > #define PCR_MASK ~(PCR_HIGH_BITS | PCR_LOW_BITS) /* PCR Reserved Bits > */ > #defineSPRN_HEIR 0x153 /* Hypervisor Emulated Instruction > Register */ > #define SPRN_TLBINDEXR 0x154 /* P7 TLB control register */ > diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c > index 93493f0cbfe8..532215040f3e 100644 > --- a/arch/powerpc/kvm/book3s_hv.c > +++ b/arch/powerpc/kvm/book3s_hv.c > @@ -344,9 +344,6 @@ static void kvmppc_set_pvr_hv(struct kvm_vcpu *vcpu, u32 > pvr) > vcpu->arch.pvr = pvr; > } > > -/* Dummy value used in computing PCR value below */ > -#define PCR_ARCH_300 (PCR_ARCH_207 << 1) > - Later will we need +/* Dummy value used in computing PCR value below */ +#define PCR_ARCH_310 (PCR_ARCH_300 << 1) ? > static int kvmppc_set_arch_compat(struct kvm_vcpu *vcpu, u32 arch_compat) > { > unsigned long host_pcr_bit = 0, guest_pcr_bit = 0; > -- > 2.20.1 >
Re: [PATCH v2 7/7] powerpc: Add POWER10 architected mode
On Tue, May 19, 2020 at 10:48 AM Alistair Popple wrote: > > PVR value of 0x0F06 means we are arch v3.1 compliant (i.e. POWER10). > This is used by phyp and kvm when booting as a pseries guest to detect > the presence of new P10 features and to enable the appropriate hwcap and > facility bits. > > Signed-off-by: Alistair Popple > Signed-off-by: Cédric Le Goater > --- > arch/powerpc/include/asm/cputable.h | 15 -- > arch/powerpc/include/asm/mmu.h| 1 + > arch/powerpc/include/asm/prom.h | 1 + > arch/powerpc/kernel/cpu_setup_power.S | 20 -- > arch/powerpc/kernel/cputable.c| 30 +++ > arch/powerpc/kernel/prom_init.c | 12 +-- > 6 files changed, 73 insertions(+), 6 deletions(-) > > diff --git a/arch/powerpc/include/asm/cputable.h > b/arch/powerpc/include/asm/cputable.h > index 36f894dea9e7..10b6d93c9d0b 100644 > --- a/arch/powerpc/include/asm/cputable.h > +++ b/arch/powerpc/include/asm/cputable.h > @@ -468,6 +468,17 @@ static inline void cpu_feature_keys_init(void) { } > #define CPU_FTRS_POWER9_DD2_2 (CPU_FTRS_POWER9 | CPU_FTR_POWER9_DD2_1 | \ >CPU_FTR_P9_TM_HV_ASSIST | \ >CPU_FTR_P9_TM_XER_SO_BUG) > +#define CPU_FTRS_POWER10 (CPU_FTR_LWSYNC | \ > + CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | CPU_FTR_ARCH_206 |\ > + CPU_FTR_MMCRA | CPU_FTR_SMT | \ > + CPU_FTR_COHERENT_ICACHE | \ > + CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \ > + CPU_FTR_DSCR | CPU_FTR_SAO | \ > + CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | > \ > + CPU_FTR_CFAR | CPU_FTR_HVMODE | CPU_FTR_VMX_COPY | \ > + CPU_FTR_DBELL | CPU_FTR_HAS_PPR | CPU_FTR_ARCH_207S | \ > + CPU_FTR_TM_COMP | CPU_FTR_ARCH_300 | CPU_FTR_PKEY | \ > + CPU_FTR_ARCH_31) > #define CPU_FTRS_CELL (CPU_FTR_LWSYNC | \ > CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ > CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \ > @@ -486,14 +497,14 @@ static inline void cpu_feature_keys_init(void) { } > #define CPU_FTRS_POSSIBLE \ > (CPU_FTRS_POWER7 | CPU_FTRS_POWER8E | CPU_FTRS_POWER8 | \ > CPU_FTR_ALTIVEC_COMP | CPU_FTR_VSX_COMP | CPU_FTRS_POWER9 | \ > -CPU_FTRS_POWER9_DD2_1 | CPU_FTRS_POWER9_DD2_2) > +CPU_FTRS_POWER9_DD2_1 | CPU_FTRS_POWER9_DD2_2 | CPU_FTRS_POWER10) > #else > #define CPU_FTRS_POSSIBLE \ > (CPU_FTRS_PPC970 | CPU_FTRS_POWER5 | \ > CPU_FTRS_POWER6 | CPU_FTRS_POWER7 | CPU_FTRS_POWER8E | \ > CPU_FTRS_POWER8 | CPU_FTRS_CELL | CPU_FTRS_PA6T | \ > CPU_FTR_VSX_COMP | CPU_FTR_ALTIVEC_COMP | CPU_FTRS_POWER9 | \ > -CPU_FTRS_POWER9_DD2_1 | CPU_FTRS_POWER9_DD2_2) > +CPU_FTRS_POWER9_DD2_1 | CPU_FTRS_POWER9_DD2_2 | CPU_FTRS_POWER10) > #endif /* CONFIG_CPU_LITTLE_ENDIAN */ > #endif > #else > diff --git a/arch/powerpc/include/asm/mmu.h b/arch/powerpc/include/asm/mmu.h > index 0699cfeeb8c9..17b19510f204 100644 > --- a/arch/powerpc/include/asm/mmu.h > +++ b/arch/powerpc/include/asm/mmu.h > @@ -122,6 +122,7 @@ > #define MMU_FTRS_POWER7MMU_FTRS_POWER6 > #define MMU_FTRS_POWER8MMU_FTRS_POWER6 > #define MMU_FTRS_POWER9MMU_FTRS_POWER6 > +#define MMU_FTRS_POWER10 MMU_FTRS_POWER6 > #define MMU_FTRS_CELL MMU_FTRS_DEFAULT_HPTE_ARCH_V2 | \ > MMU_FTR_CI_LARGE_PAGE > #define MMU_FTRS_PA6T MMU_FTRS_DEFAULT_HPTE_ARCH_V2 | \ > diff --git a/arch/powerpc/include/asm/prom.h b/arch/powerpc/include/asm/prom.h > index 94e3fd54f2c8..324a13351749 100644 > --- a/arch/powerpc/include/asm/prom.h > +++ b/arch/powerpc/include/asm/prom.h > @@ -117,6 +117,7 @@ extern int of_read_drc_info_cell(struct property **prop, > #define OV1_PPC_2_07 0x01/* set if we support PowerPC 2.07 */ > > #define OV1_PPC_3_00 0x80/* set if we support PowerPC 3.00 */ > +#define OV1_PPC_3_10x40/* set if we support PowerPC > 3.1 */ > > /* Option vector 2: Open Firmware options supported */ > #define OV2_REAL_MODE 0x20/* set if we want OF in real mode */ > diff --git a/arch/powerpc/kernel/cpu_setup_power.S > b/arch/powerpc/kernel/cpu_setup_power.S > index a460298c7ddb..f3730cf904fa 100644 > --- a/arch/powerpc/kernel/cpu_setup_power.S > +++ b/arch/powerpc/kernel/cpu_setup_power.S > @@ -91,10 +91,15 @@ _GLOBAL(__restore_cpu_power8) > mtlrr11 > blr > > +_GLOBAL(__setup_cpu_power10) > + mflrr11 > + bl __init_FSCR_P10 > + b 1f > + > _GLOBAL(__setup_cpu_power9) > mflrr11 > bl __init_FSCR > - bl __init_PMU > +1: bl __init_PMU > bl __init_hvmode_206 > mtlrr11 > beqlr > @@ -116,10 +121,15 @@
Re: [PATCH v8 11/30] powerpc: Use a datatype for instructions
mpe, this is to go with the fixup I posted for mmu_patch_addis() in [PATCH v8 12/30] powerpc: Use a function for reading instructions. Thanks to Christophe pointing it out. diff --git a/arch/powerpc/mm/nohash/8xx.c b/arch/powerpc/mm/nohash/8xx.c --- a/arch/powerpc/mm/nohash/8xx.c +++ b/arch/powerpc/mm/nohash/8xx.c @@ -98,11 +98,12 @@ static void mmu_patch_cmp_limit(s32 *site, unsigned long mapped) static void mmu_patch_addis(s32 *site, long simm) { -unsigned int instr = *(unsigned int *)patch_site_addr(site); +struct ppc_inst instr = *(struct ppc_inst *)patch_site_addr(site); +unsigned int val = ppc_inst_val(instr); -instr &= 0x; -instr |= ((unsigned long)simm) >> 16; -patch_instruction_site(site, ppc_inst(instr)); +val &= 0x; +val |= ((unsigned long)simm) >> 16; +patch_instruction_site(site, ppc_inst(val)); } static void mmu_mapin_ram_chunk(unsigned long offset, unsigned long top, pgprot_t prot) --
Re: [PATCH v8 12/30] powerpc: Use a function for reading instructions
On Sun, May 17, 2020 at 4:39 AM Christophe Leroy wrote: > > > > Le 06/05/2020 à 05:40, Jordan Niethe a écrit : > > Prefixed instructions will mean there are instructions of different > > length. As a result dereferencing a pointer to an instruction will not > > necessarily give the desired result. Introduce a function for reading > > instructions from memory into the instruction data type. > > > Shouldn't this function be used in mmu_patch_addis() in mm/nohash/8xx.c ? > > Christophe Yes, that would be a good idea. mpe here is a fix, along with one I'll post for [PATCH v8 11/30] powerpc: Use a datatype for instructions. diff --git a/arch/powerpc/mm/nohash/8xx.c b/arch/powerpc/mm/nohash/8xx.c --- a/arch/powerpc/mm/nohash/8xx.c +++ b/arch/powerpc/mm/nohash/8xx.c @@ -98,7 +98,7 @@ static void mmu_patch_cmp_limit(s32 *site, unsigned long mapped) static void mmu_patch_addis(s32 *site, long simm) { -struct ppc_inst instr = *(struct ppc_inst *)patch_site_addr(site); +struct ppc_inst instr = ppc_inst_read((struct ppc_inst *)patch_site_addr(site)); unsigned int val = ppc_inst_val(instr); val &= 0x; -- > > > > > Reviewed-by: Alistair Popple > > Signed-off-by: Jordan Niethe > > --- > > v4: New to series > > v5: - Rename read_inst() -> probe_kernel_read_inst() > > - No longer modify uprobe probe type in this patch > > v6: - feature-fixups.c: do_final_fixups(): Use here > > - arch_prepare_kprobe(): patch_instruction(): no longer part of this > >patch > > - Move probe_kernel_read_inst() out of this patch > > - Use in uprobes > > v8: style > > --- > > arch/powerpc/include/asm/inst.h| 5 + > > arch/powerpc/kernel/kprobes.c | 6 +++--- > > arch/powerpc/kernel/mce_power.c| 2 +- > > arch/powerpc/kernel/optprobes.c| 4 ++-- > > arch/powerpc/kernel/trace/ftrace.c | 4 ++-- > > arch/powerpc/kernel/uprobes.c | 2 +- > > arch/powerpc/lib/code-patching.c | 26 ++ > > arch/powerpc/lib/feature-fixups.c | 4 ++-- > > arch/powerpc/xmon/xmon.c | 6 +++--- > > 9 files changed, 33 insertions(+), 26 deletions(-) > > > > diff --git a/arch/powerpc/include/asm/inst.h > > b/arch/powerpc/include/asm/inst.h > > index 19d8bb7a1c2b..552e953bf04f 100644 > > --- a/arch/powerpc/include/asm/inst.h > > +++ b/arch/powerpc/include/asm/inst.h > > @@ -27,6 +27,11 @@ static inline struct ppc_inst ppc_inst_swab(struct > > ppc_inst x) > > return ppc_inst(swab32(ppc_inst_val(x))); > > } > > > > +static inline struct ppc_inst ppc_inst_read(const struct ppc_inst *ptr) > > +{ > > + return *ptr; > > +} > > + > > static inline bool ppc_inst_equal(struct ppc_inst x, struct ppc_inst y) > > { > > return ppc_inst_val(x) == ppc_inst_val(y); > > diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c > > index a08ae5803622..f64312dca84f 100644 > > --- a/arch/powerpc/kernel/kprobes.c > > +++ b/arch/powerpc/kernel/kprobes.c > > @@ -106,7 +106,7 @@ kprobe_opcode_t *kprobe_lookup_name(const char *name, > > unsigned int offset) > > int arch_prepare_kprobe(struct kprobe *p) > > { > > int ret = 0; > > - struct ppc_inst insn = *(struct ppc_inst *)p->addr; > > + struct ppc_inst insn = ppc_inst_read((struct ppc_inst *)p->addr); > > > > if ((unsigned long)p->addr & 0x03) { > > printk("Attempt to register kprobe at an unaligned > > address\n"); > > @@ -127,7 +127,7 @@ int arch_prepare_kprobe(struct kprobe *p) > > if (!ret) { > > memcpy(p->ainsn.insn, p->addr, > > MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); > > - p->opcode = *p->addr; > > + p->opcode = ppc_inst_val(insn); > > flush_icache_range((unsigned long)p->ainsn.insn, > > (unsigned long)p->ainsn.insn + > > sizeof(kprobe_opcode_t)); > > } > > @@ -217,7 +217,7 @@ NOKPROBE_SYMBOL(arch_prepare_kretprobe); > > static int try_to_emulate(struct kprobe *p, struct pt_regs *regs) > > { > > int ret; > > - struct ppc_inst insn = *(struct ppc_inst *)p->ainsn.insn; > > + struct ppc_inst insn = ppc_inst_read((struct ppc_inst > > *)p->ainsn.insn); > > > > /* regs->nip is also adjusted if emulate_step returns 1 */ > > ret = emulate_step(regs, insn); > > diff --git a/arch
Re: [PATCH v8 08/30] powerpc: Use a function for getting the instruction op code
On Sat, May 16, 2020 at 9:08 PM Michael Ellerman wrote: > > Jordan Niethe writes: > > mpe, as suggested by Christophe could you please add this. > > I did that and ... > > > diff --git a/arch/powerpc/include/asm/inst.h > > b/arch/powerpc/include/asm/inst.h > > --- a/arch/powerpc/include/asm/inst.h > > +++ b/arch/powerpc/include/asm/inst.h > > @@ -2,6 +2,8 @@ > > #ifndef _ASM_INST_H > > #define _ASM_INST_H > > > > +#include > > .. this eventually breaks the build in some driver, because get_ra() is > redefined. > > So I've backed out this change for now. Thanks, that is fine with me. > > If we want to use the macros in disassemble.h we'll need to namespace > them better, eg. make them ppc_get_ra() and so on. > > cheers > > > /* > > * Instruction data type for POWER > > */ > > @@ -15,7 +17,7 @@ static inline u32 ppc_inst_val(u32 x) > > > > static inline int ppc_inst_primary_opcode(u32 x) > > { > > -return ppc_inst_val(x) >> 26; > > +return get_op(ppc_inst_val(x)); > > } > > > > #endif /* _ASM_INST_H */ > > -- > > 2.17.1
Re: [PATCH v8 30/30] powerpc sstep: Add support for prefixed fixed-point arithmetic
mpe, and this thanks. --- diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c --- a/arch/powerpc/lib/sstep.c +++ b/arch/powerpc/lib/sstep.c @@ -1343,7 +1343,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, rd = (suffix >> 21) & 0x1f; op->reg = rd; op->val = regs->gpr[rd]; -suffixopcode = suffix >> 26; +suffixopcode = get_op(suffix); prefixtype = (word >> 24) & 0x3; switch (prefixtype) { case 2: -- 2.17.1
Re: [PATCH v8 29/30] powerpc sstep: Add support for prefixed load/stores
mpe, and this thanks. diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c --- a/arch/powerpc/lib/sstep.c +++ b/arch/powerpc/lib/sstep.c @@ -1204,7 +1204,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, struct ppc_inst instr) { unsigned int opcode, ra, rb, rc, rd, spr, u; -#ifdef __powerpc64__ +#ifdef CONFIG_PPC64 unsigned int suffixopcode, prefixtype, prefix_r; #endif unsigned long int imm; @@ -2701,7 +2701,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, op->reg = rd; op->val = regs->gpr[rd]; -suffixopcode = suffix >> 26; +suffixopcode = get_op(suffix); prefixtype = (word >> 24) & 0x3; switch (prefixtype) { case 0: /* Type 00 Eight-Byte Load/Store */ -- 2.17.1
Re: [PATCH v8 25/30] powerpc: Test prefixed instructions in feature fixups
Hey mpe, could you add this thanks. diff --git a/arch/powerpc/lib/feature-fixups.c b/arch/powerpc/lib/feature-fixups.c --- a/arch/powerpc/lib/feature-fixups.c +++ b/arch/powerpc/lib/feature-fixups.c @@ -689,7 +689,7 @@ static void test_lwsync_macros(void) } } -#ifdef __powerpc64__ +#ifdef CONFIG_PPC64 static void __init test_prefix_patching(void) { extern unsigned int ftr_fixup_prefix1[]; @@ -755,7 +755,7 @@ static void __init test_prefix_word_alt_patching(void) patch_feature_section(0, ); check(memcmp(ftr_fixup_prefix3, ftr_fixup_prefix3_orig, size) != 0); } -#endif /* __powerpc64__ */ +#endif /* CONFIG_PPC64 */ static int __init test_feature_fixups(void) { @@ -771,7 +771,7 @@ static int __init test_feature_fixups(void) test_cpu_macros(); test_fw_macros(); test_lwsync_macros(); -#ifdef __powerpc64__ +#ifdef CONFIG_PPC64 test_prefix_patching(); test_prefix_alt_patching(); test_prefix_word_alt_patching(); --
Re: [PATCH v8 24/30] powerpc: Test prefixed code patching
Hey mpe could you add this please. diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c --- a/arch/powerpc/lib/code-patching.c +++ b/arch/powerpc/lib/code-patching.c @@ -707,7 +707,7 @@ static void __init test_translate_branch(void) vfree(buf); } -#ifdef __powerpc64__ +#ifdef CONFIG_PPC64 static void __init test_prefixed_patching(void) { extern unsigned int code_patching_test1[]; @@ -733,7 +733,7 @@ static int __init test_code_patching(void) test_branch_bform(); test_create_function_call(); test_translate_branch(); -#ifdef __powerpc64__ +#ifdef CONFIG_PPC64 test_prefixed_patching(); #endif -- 2.17.1
Re: [PATCH v8 23/30] powerpc: Add prefixed instructions to instruction data type
Hey mpe, fixes for the issues highlighted by Christophe, except KUAP as discussed. Will make the optprobe change as a preceding patch. diff --git a/arch/powerpc/include/asm/inst.h b/arch/powerpc/include/asm/inst.h --- a/arch/powerpc/include/asm/inst.h +++ b/arch/powerpc/include/asm/inst.h @@ -11,9 +11,9 @@ struct ppc_inst { u32 val; -#ifdef __powerpc64__ +#ifdef CONFIG_PPC64 u32 suffix; -#endif /* __powerpc64__ */ +#endif /* CONFIG_PPC64 */ } __packed; static inline u32 ppc_inst_val(struct ppc_inst x) @@ -26,7 +26,7 @@ static inline int ppc_inst_primary_opcode(struct ppc_inst x) return get_op(ppc_inst_val(x)); } -#ifdef __powerpc64__ +#ifdef CONFIG_PPC64 #define ppc_inst(x) ((struct ppc_inst){ .val = (x), .suffix = 0xff }) #define ppc_inst_prefix(x, y) ((struct ppc_inst){ .val = (x), .suffix = (y) }) @@ -52,7 +52,7 @@ static inline struct ppc_inst ppc_inst_read(const struct ppc_inst *ptr) u32 val, suffix; val = *(u32 *)ptr; -if ((val >> 26) == 1) { +if ((get_op(val)) == OP_PREFIX) { suffix = *((u32 *)ptr + 1); return ppc_inst_prefix(val, suffix); } else { @@ -94,7 +94,7 @@ static inline bool ppc_inst_equal(struct ppc_inst x, struct ppc_inst y) return ppc_inst_val(x) == ppc_inst_val(y); } -#endif /* __powerpc64__ */ +#endif /* CONFIG_PPC64 */ static inline int ppc_inst_len(struct ppc_inst x) { diff --git a/arch/powerpc/include/asm/uaccess.h b/arch/powerpc/include/asm/uaccess.h index e9027b3c641a..ac36a82321d4 100644 --- a/arch/powerpc/include/asm/uaccess.h +++ b/arch/powerpc/include/asm/uaccess.h @@ -105,7 +105,7 @@ static inline int __access_ok(unsigned long addr, unsigned long size, #define __put_user_inatomic(x, ptr) \ __put_user_nosleep((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr))) -#ifdef __powerpc64__ +#ifdef CONFIG_PPC64 #define __get_user_instr(x, ptr)\ ({\ long __gui_ret = 0;\ @@ -113,7 +113,7 @@ static inline int __access_ok(unsigned long addr, unsigned long size, struct ppc_inst __gui_inst;\ unsigned int prefix, suffix;\ __gui_ret = __get_user(prefix, (unsigned int __user *)__gui_ptr);\ -if (!__gui_ret && (prefix >> 26) == OP_PREFIX) {\ +if (!__gui_ret && (get_op(prefix)) == OP_PREFIX) {\ __gui_ret = __get_user(suffix,\ (unsigned int __user *)__gui_ptr + 1);\ __gui_inst = ppc_inst_prefix(prefix, suffix);\ @@ -131,7 +131,7 @@ static inline int __access_ok(unsigned long addr, unsigned long size, struct ppc_inst __gui_inst;\ unsigned int prefix, suffix;\ __gui_ret = __get_user_inatomic(prefix, (unsigned int __user *)__gui_ptr);\ -if (!__gui_ret && (prefix >> 26) == OP_PREFIX) {\ +if (!__gui_ret && (get_op(prefix)) == OP_PREFIX) {\ __gui_ret = __get_user_inatomic(suffix,\ (unsigned int __user *)__gui_ptr + 1);\ __gui_inst = ppc_inst_prefix(prefix, suffix);\ diff --git a/arch/powerpc/kernel/optprobes.c b/arch/powerpc/kernel/optprobes.c index a8e66603d12b..3ac105e7faae 100644 --- a/arch/powerpc/kernel/optprobes.c +++ b/arch/powerpc/kernel/optprobes.c @@ -283,10 +283,8 @@ int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe *p) * 3. load instruction to be emulated into relevant register, and */ temp = ppc_inst_read((struct ppc_inst *)p->ainsn.insn); -patch_imm64_load_insns(ppc_inst_val(temp) | - ((u64)ppc_inst_suffix(temp) << 32), - 4, - buff + TMPL_INSN_IDX); +patch_imm64_load_insns(ppc_inst_val(temp) | ((u64)ppc_inst_suffix(temp) << 32), + 4, buff + TMPL_INSN_IDX); /* * 4. branch back from trampoline diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c index 58b67b62d5d3..bfd4e1dae0fb 100644 --- a/arch/powerpc/lib/code-patching.c +++ b/arch/powerpc/lib/code-patching.c @@ -26,8 +26,6 @@ static int __patch_instruction(struct ppc_inst *exec_addr, struct ppc_inst instr if (!ppc_inst_prefixed(instr)) { __put_user_asm(ppc_inst_val(instr), patch_addr, err, "stw"); -if (err) -return err; } else { #ifdef CONFIG_CPU_LITTLE_ENDIAN __put_user_asm((u64)ppc_inst_suffix(instr) << 32 | @@ -36,12 +34,13 @@ static int __patch_instruction(struct ppc_inst *exec_addr, struct ppc_inst instr __put_user_asm((u64)ppc_inst_val(instr) << 32 | ppc_inst_suffix(instr), patch_addr, err, "std"); #endif /* CONFIG_CPU_LITTLE_ENDIAN */ -if (err) -return err; } +if (err) +return err; asm ("dcbst 0, %0; sync; icbi 0,%1; sync; isync" :: "r" (patch_addr), "r" (exec_addr)); + return 0; } diff --git a/arch/powerpc/lib/inst.c
Re: [PATCH v8 08/30] powerpc: Use a function for getting the instruction op code
mpe, as suggested by Christophe could you please add this. diff --git a/arch/powerpc/include/asm/inst.h b/arch/powerpc/include/asm/inst.h --- a/arch/powerpc/include/asm/inst.h +++ b/arch/powerpc/include/asm/inst.h @@ -2,6 +2,8 @@ #ifndef _ASM_INST_H #define _ASM_INST_H +#include + /* * Instruction data type for POWER */ @@ -15,7 +17,7 @@ static inline u32 ppc_inst_val(u32 x) static inline int ppc_inst_primary_opcode(u32 x) { -return ppc_inst_val(x) >> 26; +return get_op(ppc_inst_val(x)); } #endif /* _ASM_INST_H */ -- 2.17.1
Re: [PATCH v8 13/30] powerpc: Add a probe_user_read_inst() function
On Thu, May 14, 2020 at 3:46 PM Christophe Leroy wrote: > > > > Le 06/05/2020 à 05:40, Jordan Niethe a écrit : > > Introduce a probe_user_read_inst() function to use in cases where > > probe_user_read() is used for getting an instruction. This will be more > > useful for prefixed instructions. > > > > Reviewed-by: Alistair Popple > > Signed-off-by: Jordan Niethe > > --- > > v6: - New to series > > --- > > arch/powerpc/include/asm/inst.h | 3 +++ > > arch/powerpc/lib/Makefile | 2 +- > > arch/powerpc/lib/inst.c | 18 ++ > > arch/powerpc/mm/fault.c | 2 +- > > 4 files changed, 23 insertions(+), 2 deletions(-) > > create mode 100644 arch/powerpc/lib/inst.c > > > > diff --git a/arch/powerpc/include/asm/inst.h > > b/arch/powerpc/include/asm/inst.h > > index 552e953bf04f..3e9a58420151 100644 > > --- a/arch/powerpc/include/asm/inst.h > > +++ b/arch/powerpc/include/asm/inst.h > > @@ -37,4 +37,7 @@ static inline bool ppc_inst_equal(struct ppc_inst x, > > struct ppc_inst y) > > return ppc_inst_val(x) == ppc_inst_val(y); > > } > > > > +int probe_user_read_inst(struct ppc_inst *inst, > > + struct ppc_inst *nip); > > + > > #endif /* _ASM_INST_H */ > > diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile > > index b8de3be10eb4..546591848219 100644 > > --- a/arch/powerpc/lib/Makefile > > +++ b/arch/powerpc/lib/Makefile > > @@ -16,7 +16,7 @@ CFLAGS_code-patching.o += -DDISABLE_BRANCH_PROFILING > > CFLAGS_feature-fixups.o += -DDISABLE_BRANCH_PROFILING > > endif > > > > -obj-y += alloc.o code-patching.o feature-fixups.o pmem.o > > +obj-y += alloc.o code-patching.o feature-fixups.o pmem.o inst.o > > > > ifndef CONFIG_KASAN > > obj-y += string.o memcmp_$(BITS).o > > diff --git a/arch/powerpc/lib/inst.c b/arch/powerpc/lib/inst.c > > new file mode 100644 > > index ..eaf786afad2b > > --- /dev/null > > +++ b/arch/powerpc/lib/inst.c > > @@ -0,0 +1,18 @@ > > +// SPDX-License-Identifier: GPL-2.0-or-later > > +/* > > + * Copyright 2020, IBM Corporation. > > + */ > > + > > +#include > > +#include > > + > > +int probe_user_read_inst(struct ppc_inst *inst, > > + struct ppc_inst *nip) > > +{ > > + unsigned int val; > > + int err; > > + > > + err = probe_user_read(, nip, sizeof(val)); > > + *inst = ppc_inst(val); > > + return err; > > +} > > diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c > > index 4a50f125ec18..f3a943eae305 100644 > > --- a/arch/powerpc/mm/fault.c > > +++ b/arch/powerpc/mm/fault.c > > @@ -281,7 +281,7 @@ static bool bad_stack_expansion(struct pt_regs *regs, > > unsigned long address, > > access_ok(nip, sizeof(*nip))) { > > struct ppc_inst inst; > > > > - if (!probe_user_read(, nip, sizeof(inst))) > > + if (!probe_user_read_inst(, (struct ppc_inst > > __user *)nip)) > > Shouldn't 'nip' become de 'struct ppc_inst __user *' instead of casting ? > > > return !store_updates_sp(inst); > > *must_retry = true; > > } > > Yeah it would make more sense to do it like this. --- a/arch/powerpc/mm/fault.c +++ b/arch/powerpc/mm/fault.c @@ -256,7 +256,7 @@ static bool bad_stack_expansion(struct pt_regs *regs, unsigned long address, * expand to 1MB without further checks. */ if (address + 0x10 < vma->vm_end) { -unsigned int __user *nip = (unsigned int __user *)regs->nip; +struct ppc_inst __user *nip = (struct ppc_inst __user *)regs->nip; /* get user regs even if this fault is in kernel mode */ struct pt_regs *uregs = current->thread.regs; if (uregs == NULL) @@ -281,7 +281,7 @@ static bool bad_stack_expansion(struct pt_regs *regs, unsigned long address, access_ok(nip, sizeof(*nip))) { struct ppc_inst inst; -if (!probe_user_read_inst(, (struct ppc_inst __user *)nip)) +if (!probe_user_read_inst(, nip)) return !store_updates_sp(inst); *must_retry = true; } -- 2.17.1 > > Christophe
Re: [PATCH v8 23/30] powerpc: Add prefixed instructions to instruction data type
On Thu, May 14, 2020 at 10:06 PM Alistair Popple wrote: > > On Thursday, 14 May 2020 4:11:43 PM AEST Christophe Leroy wrote: > > @@ -249,7 +249,7 @@ int arch_prepare_optimized_kprobe(struct > > optimized_kprobe *op, struct kprobe *p) > > > * Fixup the template with instructions to: > > > * 1. load the address of the actual probepoint > > > */ > > > - patch_imm64_load_insns((unsigned long)op, buff + TMPL_OP_IDX); > > > + patch_imm64_load_insns((unsigned long)op, 3, buff + TMPL_OP_IDX); > > > > > > /* > > > * 2. branch to optimized_callback() and emulate_step() > > > @@ -282,7 +282,11 @@ int arch_prepare_optimized_kprobe(struct > > > optimized_kprobe *op, struct kprobe *p) /* > > > * 3. load instruction to be emulated into relevant register, and > > > */ > > > - patch_imm32_load_insns(*p->ainsn.insn, buff + TMPL_INSN_IDX); > > > + temp = ppc_inst_read((struct ppc_inst *)p->ainsn.insn); > > > + patch_imm64_load_insns(ppc_inst_val(temp) | > > > + ((u64)ppc_inst_suffix(temp) << 32), > > > + 4, > > > > So now we are also using r4 ? Any explanation somewhere on the way it > > works ? This change seems unrelated to this patch, nothing in the > > description about it. Can we suddenly use a new register without problem ? > > Unless I missed something there is no change in register usage here that I > could see. patch_imm32_load_insns() was/is hardcoded to use register r4. Yes, that is right. > > - Alistair > >
Re: [PATCH v8 23/30] powerpc: Add prefixed instructions to instruction data type
On Thu, May 14, 2020 at 4:12 PM Christophe Leroy wrote: > > > > Le 06/05/2020 à 05:40, Jordan Niethe a écrit : > > For powerpc64, redefine the ppc_inst type so both word and prefixed > > instructions can be represented. On powerpc32 the type will remain the > > same. Update places which had assumed instructions to be 4 bytes long. > > > > Reviewed-by: Alistair Popple > > Signed-off-by: Jordan Niethe > > --- > > v4: New to series > > v5: - Distinguish normal instructions from prefixed instructions with a > > 0xff marker for the suffix. > > - __patch_instruction() using std for prefixed instructions > > v6: - Return false instead of 0 in ppc_inst_prefixed() > > - Fix up types for ppc32 so it compiles > > - remove ppc_inst_write() > > - __patching_instruction(): move flush out of condition > > v8: - style > > - Define and use OP_PREFIX instead of '1' (back from v3) > > - __patch_instruction() fix for big endian > > --- > > arch/powerpc/include/asm/inst.h | 69 --- > > arch/powerpc/include/asm/kprobes.h| 2 +- > > arch/powerpc/include/asm/ppc-opcode.h | 3 ++ > > arch/powerpc/include/asm/uaccess.h| 40 +++- > > arch/powerpc/include/asm/uprobes.h| 2 +- > > arch/powerpc/kernel/crash_dump.c | 2 +- > > arch/powerpc/kernel/optprobes.c | 42 > > arch/powerpc/kernel/optprobes_head.S | 3 ++ > > arch/powerpc/lib/code-patching.c | 19 ++-- > > arch/powerpc/lib/feature-fixups.c | 5 +- > > arch/powerpc/lib/inst.c | 41 > > arch/powerpc/lib/sstep.c | 4 +- > > arch/powerpc/xmon/xmon.c | 4 +- > > arch/powerpc/xmon/xmon_bpts.S | 2 + > > 14 files changed, 200 insertions(+), 38 deletions(-) > > > > diff --git a/arch/powerpc/include/asm/inst.h > > b/arch/powerpc/include/asm/inst.h > > index 2f3c9d5bcf7c..7868b80b610e 100644 > > --- a/arch/powerpc/include/asm/inst.h > > +++ b/arch/powerpc/include/asm/inst.h > > @@ -2,29 +2,79 @@ > > #ifndef _ASM_INST_H > > #define _ASM_INST_H > > > > +#include > > /* > >* Instruction data type for POWER > >*/ > > > > struct ppc_inst { > > u32 val; > > +#ifdef __powerpc64__ > > CONFIG_PPC64 should be used instead. This is also reported by checkpatch. Sure will use that instead. > > > + u32 suffix; > > +#endif /* __powerpc64__ */ > > } __packed; > > > > -#define ppc_inst(x) ((struct ppc_inst){ .val = x }) > > - > > static inline u32 ppc_inst_val(struct ppc_inst x) > > { > > return x.val; > > } > > > > -static inline int ppc_inst_len(struct ppc_inst x) > > +static inline int ppc_inst_primary_opcode(struct ppc_inst x) > > { > > - return sizeof(struct ppc_inst); > > + return ppc_inst_val(x) >> 26; > > What about using get_op() from asm/disassemble.h instead of hardcodiing ? Okay will use it here and the other places you point out. > > > } > > > > -static inline int ppc_inst_primary_opcode(struct ppc_inst x) > > +#ifdef __powerpc64__ > > Use CONFIG_PPC64 > > > +#define ppc_inst(x) ((struct ppc_inst){ .val = (x), .suffix = 0xff }) > > + > > +#define ppc_inst_prefix(x, y) ((struct ppc_inst){ .val = (x), .suffix = > > (y) }) > > + > > +static inline u32 ppc_inst_suffix(struct ppc_inst x) > > { > > - return ppc_inst_val(x) >> 26; > > + return x.suffix; > > +} > > + > > +static inline bool ppc_inst_prefixed(struct ppc_inst x) > > +{ > > + return (ppc_inst_primary_opcode(x) == 1) && ppc_inst_suffix(x) != > > 0xff; > > +} > > + > > +static inline struct ppc_inst ppc_inst_swab(struct ppc_inst x) > > +{ > > + return ppc_inst_prefix(swab32(ppc_inst_val(x)), > > +swab32(ppc_inst_suffix(x))); > > +} > > + > > +static inline struct ppc_inst ppc_inst_read(const struct ppc_inst *ptr) > > +{ > > + u32 val, suffix; > > + > > + val = *(u32 *)ptr; > > + if ((val >> 26) == 1) { > > Don't hardcode, use ppc_inst_primary_opcode() and compare it to OP_PREFIX > Or use get_op() from asm/disassemble.h > > > > + suffix = *((u32 *)ptr + 1); > > + return ppc_inst_prefix(val, suffix); > > + } else { > > + return ppc_inst(val); > > +
Re: [PATCH v8 00/30] Initial Prefixed Instruction support
On Thu, May 14, 2020 at 3:31 PM Christophe Leroy wrote: > > > > Le 06/05/2020 à 05:40, Jordan Niethe a écrit : > > A future revision of the ISA will introduce prefixed instructions. A > > prefixed instruction is composed of a 4-byte prefix followed by a > > 4-byte suffix. > > > > All prefixes have the major opcode 1. A prefix will never be a valid > > word instruction. A suffix may be an existing word instruction or a > > new instruction. > > > > This series enables prefixed instructions and extends the instruction > > emulation to support them. Then the places where prefixed instructions > > might need to be emulated are updated. > > > > v8 incorporates feedback from Alistair Popple and Balamuruhan Suriyakumar. > > The major changes: > > - Fix some style issues > > - Fix __patch_instruction() on big endian > > - Reintroduce v3's forbidding breakpoints on second word of prefix > >instructions for kprobes and xmon. Missed this when changing to > >using a data type. > > - Use the data type in some places that were missed. > > Checkpatch seems to report the following warnings for pmac32_defconfig, > are they harmless ? > > +arch/powerpc/kernel/align.c:307:13: warning: cast removes address space > '' of expression > +arch/powerpc/kernel/align.c:307:13: warning: cast removes address space > '' of expression > +arch/powerpc/kernel/align.c:307:13: warning: cast removes address space > '' of expression > +arch/powerpc/kernel/align.c:307:13: warning: cast removes address space > '' of expression > +arch/powerpc/kernel/align.c:307:13: warning: cast removes address space > '' of expression > +arch/powerpc/kernel/align.c:307:13: warning: incorrect type in argument > 1 (different address spaces) expected void const volatile [noderef] > * got unsigned int [usertype] * > +arch/powerpc/kernel/align.c:307:13: warning: incorrect type in > initializer (different address spaces) expected unsigned int [noderef] > *__gu_addr got unsigned int [usertype] * > +arch/powerpc/kernel/hw_breakpoint.c:XX:13: warning: cast removes > address space '' of expression > +arch/powerpc/kernel/hw_breakpoint.c:XX:13: warning: cast removes > address space '' of expression > +arch/powerpc/kernel/hw_breakpoint.c:XX:13: warning: cast removes > address space '' of expression > +arch/powerpc/kernel/hw_breakpoint.c:XX:13: warning: cast removes > address space '' of expression > +arch/powerpc/kernel/hw_breakpoint.c:XX:13: warning: cast removes > address space '' of expression > -arch/powerpc/kernel/hw_breakpoint.c:XX:13: warning: incorrect type in > argument 1 (different address spaces) expected void const volatile > [noderef] * got unsigned int * > +arch/powerpc/kernel/hw_breakpoint.c:XX:13: warning: incorrect type in > argument 1 (different address spaces) expected void const volatile > [noderef] * got unsigned int [usertype] * > -arch/powerpc/kernel/hw_breakpoint.c:XX:13: warning: incorrect type in > initializer (different address spaces) expected unsigned int [noderef] > *__gu_addr got unsigned int * > +arch/powerpc/kernel/hw_breakpoint.c:XX:13: warning: incorrect type in > initializer (different address spaces) expected unsigned int [noderef] > *__gu_addr got unsigned int [usertype] * > +arch/powerpc/kernel/vecemu.c:269:13: warning: cast removes address > space '' of expression > +arch/powerpc/kernel/vecemu.c:269:13: warning: cast removes address > space '' of expression > +arch/powerpc/kernel/vecemu.c:269:13: warning: cast removes address > space '' of expression > +arch/powerpc/kernel/vecemu.c:269:13: warning: cast removes address > space '' of expression > +arch/powerpc/kernel/vecemu.c:269:13: warning: cast removes address > space '' of expression > +arch/powerpc/kernel/vecemu.c:269:13: warning: incorrect type in > argument 1 (different address spaces) expected void const volatile > [noderef] * got unsigned int [usertype] * > +arch/powerpc/kernel/vecemu.c:269:13: warning: incorrect type in > initializer (different address spaces) expected unsigned int [noderef] > *__gu_addr got unsigned int [usertype] * > +arch/powerpc/lib/inst.c:55:37: warning: incorrect type in argument 2 > (different address spaces) expected void const [noderef] *src > got struct ppc_inst *nip > +arch/powerpc/mm/fault.c:284:59: warning: incorrect type in argument 2 > (different address spaces) expected struct ppc_inst *nip got struct > ppc_inst [noderef] * Thanks, I was missing some __user. --- a/arch/powerpc/include/asm/uaccess.h +++ b/arch/powerpc/include/asm/uaccess.h @@ -106,10 +106,10 @@ static inline int __access_ok(unsigned long addr, unsigned long size, __put_user_nosleep((__typeof__(
Re: [PATCH v8 16/30] powerpc: Define and use __get_user_instr{, inatomic}()
Hi mpe, could you please take this. arch/powerpc/include/asm/uaccess.h | 3 +++ arch/powerpc/kernel/vecemu.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/include/asm/uaccess.h b/arch/powerpc/include/asm/uaccess.h --- a/arch/powerpc/include/asm/uaccess.h +++ b/arch/powerpc/include/asm/uaccess.h @@ -105,6 +105,9 @@ static inline int __access_ok(unsigned long addr, unsigned long size, #define __put_user_inatomic(x, ptr) \ __put_user_nosleep((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr))) +#define get_user_instr(x, ptr) \ +get_user((x).val, (u32 *)(ptr)) + #define __get_user_instr(x, ptr) \ __get_user_nocheck((x).val, (u32 *)(ptr), sizeof(u32), true) diff --git a/arch/powerpc/kernel/vecemu.c b/arch/powerpc/kernel/vecemu.c index 60ed5aea8d4e..ae632569446f 100644 --- a/arch/powerpc/kernel/vecemu.c +++ b/arch/powerpc/kernel/vecemu.c @@ -266,7 +266,7 @@ int emulate_altivec(struct pt_regs *regs) unsigned int va, vb, vc, vd; vector128 *vrs; -if (__get_user_instr(instr, (void __user *)regs->nip)) +if (get_user_instr(instr, (void __user *)regs->nip)) return -EFAULT; word = ppc_inst_val(instr);
Re: [PATCH v8 23/30] powerpc: Add prefixed instructions to instruction data type
Hi mpe, Relating to your message on [PATCH v8 16/30] powerpc: Define and use __get_user_instr{,inatomic}() - could you please take this. diff --git a/arch/powerpc/include/asm/uaccess.h b/arch/powerpc/include/asm/uaccess.h --- a/arch/powerpc/include/asm/uaccess.h +++ b/arch/powerpc/include/asm/uaccess.h @@ -106,6 +106,24 @@ static inline int __access_ok(unsigned long addr, unsigned long size, __put_user_nosleep((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr))) #ifdef __powerpc64__ +#define get_user_instr(x, ptr) \ +({\ +long __gui_ret = 0;\ +unsigned long __gui_ptr = (unsigned long)ptr;\ +struct ppc_inst __gui_inst;\ +unsigned int prefix, suffix;\ +__gui_ret = get_user(prefix, (unsigned int __user *)__gui_ptr);\ +if (!__gui_ret && (prefix >> 26) == OP_PREFIX) {\ +__gui_ret = get_user(suffix,\ + (unsigned int __user *)__gui_ptr + 1);\ +__gui_inst = ppc_inst_prefix(prefix, suffix);\ +} else {\ +__gui_inst = ppc_inst(prefix);\ +}\ +(x) = __gui_inst;\ +__gui_ret;\ +}) + #define __get_user_instr(x, ptr)\ ({\ long __gui_ret = 0;\ @@ -142,6 +160,8 @@ static inline int __access_ok(unsigned long addr, unsigned long size, __gui_ret;\ }) #else +#define get_user_instr(x, ptr) \ +get_user((x).val, (u32 *)(ptr)) #define __get_user_instr(x, ptr) \ __get_user_nocheck((x).val, (u32 *)(ptr), sizeof(u32), true) #define __get_user_instr_inatomic(x, ptr) \
Re: [PATCH v8 16/30] powerpc: Define and use __get_user_instr{, inatomic}()
On Thu, May 14, 2020 at 12:17 AM Michael Ellerman wrote: > > Jordan Niethe writes: > > Define specific __get_user_instr() and __get_user_instr_inatomic() > > macros for reading instructions from user space. > > At least for fix_alignment() we could be coming from the kernel, not > sure about the other cases. > > I can tweak the change log. > > > diff --git a/arch/powerpc/include/asm/uaccess.h > > b/arch/powerpc/include/asm/uaccess.h > > index 2f500debae21..c0a35e4586a5 100644 > > --- a/arch/powerpc/include/asm/uaccess.h > > +++ b/arch/powerpc/include/asm/uaccess.h > > @@ -105,6 +105,11 @@ static inline int __access_ok(unsigned long addr, > > unsigned long size, > > #define __put_user_inatomic(x, ptr) \ > > __put_user_nosleep((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr))) > > > > +#define __get_user_instr(x, ptr) \ > > + __get_user_nocheck((x).val, (u32 *)(ptr), sizeof(u32), true) > > + > > +#define __get_user_instr_inatomic(x, ptr) \ > > + __get_user_nosleep((x).val, (u32 *)(ptr), sizeof(u32)) > > I'm not super keen on adding new __ versions, which lack the access_ok() > check, but I guess we have to. > > > diff --git a/arch/powerpc/kernel/vecemu.c b/arch/powerpc/kernel/vecemu.c > > index 3dd70eeb10c5..60ed5aea8d4e 100644 > > --- a/arch/powerpc/kernel/vecemu.c > > +++ b/arch/powerpc/kernel/vecemu.c > > @@ -266,7 +266,7 @@ int emulate_altivec(struct pt_regs *regs) > > unsigned int va, vb, vc, vd; > > vector128 *vrs; > > > > - if (get_user(instr.val, (unsigned int __user *)regs->nip)) > > + if (__get_user_instr(instr, (void __user *)regs->nip)) > > return -EFAULT; > > That drops the access_ok() check, which is not OK, at least without a > reasonable justification. > > Given it's regs->nip I guess it should be safe, but it should still be > called out. Or preferably switched to __get_user() in a precursor patch. Or should I add a get_user_instr() that includes the check? > > cheers
Re: [PATCH v8 13/30] powerpc: Add a probe_user_read_inst() function
On Wed, May 13, 2020 at 10:52 PM Michael Ellerman wrote: > > Jordan Niethe writes: > > diff --git a/arch/powerpc/lib/inst.c b/arch/powerpc/lib/inst.c > > new file mode 100644 > > index ..eaf786afad2b > > --- /dev/null > > +++ b/arch/powerpc/lib/inst.c > > @@ -0,0 +1,18 @@ > > +// SPDX-License-Identifier: GPL-2.0-or-later > > +/* > > + * Copyright 2020, IBM Corporation. > > + */ > > + > > +#include > > +#include > > + > > +int probe_user_read_inst(struct ppc_inst *inst, > > + struct ppc_inst *nip) > > +{ > > + unsigned int val; > > + int err; > > + > > + err = probe_user_read(, nip, sizeof(val)); > > + *inst = ppc_inst(val); > > We shouldn't be storing to *inst if the read failed? Good point. > > I changed it to: > > + if (!err) > + *inst = ppc_inst(val); > + > > Similarly for probe_kernel_read_inst(). Thanks. > > cheers