Re: [PATCH v2 7/9] sparc64: numa: check the node id consistently for sparc64
From: Yunsheng Lin Date: Sat, 31 Aug 2019 13:58:21 +0800 > According to Section 6.2.14 from ACPI spec 6.3 [1], the setting > of proximity domain is optional, as below: What in the world does the ACPI spec have to do with sparc64 NUMA node ID checking?
Re: [PATCH v7 4/6] powerpc/64: make buildable without CONFIG_COMPAT
Le 30/08/2019 à 23:03, Michal Suchanek a écrit : There are numerous references to 32bit functions in generic and 64bit code so ifdef them out. Signed-off-by: Michal Suchanek Reviewed-by: Christophe Leroy --- v2: - fix 32bit ifdef condition in signal.c - simplify the compat ifdef condition in vdso.c - 64bit is redundant - simplify the compat ifdef condition in callchain.c - 64bit is redundant v3: - use IS_ENABLED and maybe_unused where possible - do not ifdef declarations - clean up Makefile v4: - further makefile cleanup - simplify is_32bit_task conditions - avoid ifdef in condition by using return v5: - avoid unreachable code on 32bit - make is_current_64bit constant on !COMPAT - add stub perf_callchain_user_32 to avoid some ifdefs v6: - consolidate current_is_64bit v7: - remove leftover perf_callchain_user_32 stub from previous series version --- arch/powerpc/include/asm/thread_info.h | 4 ++-- arch/powerpc/kernel/Makefile | 7 +++--- arch/powerpc/kernel/entry_64.S | 2 ++ arch/powerpc/kernel/signal.c | 3 +-- arch/powerpc/kernel/syscall_64.c | 6 ++--- arch/powerpc/kernel/vdso.c | 5 ++--- arch/powerpc/perf/callchain.c | 31 +- 7 files changed, 27 insertions(+), 31 deletions(-) diff --git a/arch/powerpc/include/asm/thread_info.h b/arch/powerpc/include/asm/thread_info.h index 8e1d0195ac36..c128d8a48ea3 100644 --- a/arch/powerpc/include/asm/thread_info.h +++ b/arch/powerpc/include/asm/thread_info.h @@ -144,10 +144,10 @@ static inline bool test_thread_local_flags(unsigned int flags) return (ti->local_flags & flags) != 0; } -#ifdef CONFIG_PPC64 +#ifdef CONFIG_COMPAT #define is_32bit_task() (test_thread_flag(TIF_32BIT)) #else -#define is_32bit_task()(1) +#define is_32bit_task()(IS_ENABLED(CONFIG_PPC32)) #endif #if defined(CONFIG_PPC64) diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 1d646a94d96c..9d8772e863b9 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile @@ -44,16 +44,15 @@ CFLAGS_btext.o += -DDISABLE_BRANCH_PROFILING endif obj-y:= cputable.o ptrace.o syscalls.o \ - irq.o align.o signal_32.o pmc.o vdso.o \ + irq.o align.o signal_$(BITS).o pmc.o vdso.o \ process.o systbl.o idle.o \ signal.o sysfs.o cacheinfo.o time.o \ prom.o traps.o setup-common.o \ udbg.o misc.o io.o misc_$(BITS).o \ of_platform.o prom_parse.o -obj-$(CONFIG_PPC64)+= setup_64.o sys_ppc32.o \ - signal_64.o ptrace32.o \ - paca.o nvram_64.o firmware.o \ +obj-$(CONFIG_PPC64)+= setup_64.o paca.o nvram_64.o firmware.o \ syscall_64.o +obj-$(CONFIG_COMPAT) += sys_ppc32.o ptrace32.o signal_32.o obj-$(CONFIG_VDSO32) += vdso32/ obj-$(CONFIG_PPC_WATCHDOG)+= watchdog.o obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 2ec825a85f5b..a2dbf216f607 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -51,8 +51,10 @@ SYS_CALL_TABLE: .tc sys_call_table[TC],sys_call_table +#ifdef CONFIG_COMPAT COMPAT_SYS_CALL_TABLE: .tc compat_sys_call_table[TC],compat_sys_call_table +#endif /* This value is used to mark exception frames on the stack. */ exception_marker: diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c index 60436432399f..61678cb0e6a1 100644 --- a/arch/powerpc/kernel/signal.c +++ b/arch/powerpc/kernel/signal.c @@ -247,7 +247,6 @@ static void do_signal(struct task_struct *tsk) sigset_t *oldset = sigmask_to_save(); struct ksignal ksig = { .sig = 0 }; int ret; - int is32 = is_32bit_task(); BUG_ON(tsk != current); @@ -277,7 +276,7 @@ static void do_signal(struct task_struct *tsk) rseq_signal_deliver(&ksig, tsk->thread.regs); - if (is32) { + if (is_32bit_task()) { if (ksig.ka.sa.sa_flags & SA_SIGINFO) ret = handle_rt_signal32(&ksig, oldset, tsk); else diff --git a/arch/powerpc/kernel/syscall_64.c b/arch/powerpc/kernel/syscall_64.c index 98ed970796d5..0d5cbbe54cf1 100644 --- a/arch/powerpc/kernel/syscall_64.c +++ b/arch/powerpc/kernel/syscall_64.c @@ -38,7 +38,6 @@ typedef long (*syscall_fn)(long, long, long, long, long, long); long system_call_exception(long r3, long r4, long r5, long r6, long r7, long r8, unsigned long r0, struct pt_regs *regs) { - unsigned long ti_flags; syscall_fn f; BUG_ON(!(regs->msr & MSR_PR)); @@ -83,8 +82,7 @@ long
Re: [PATCH v7 0/6] Disable compat cruft on ppc64le v7
Le 30/08/2019 à 23:03, Michal Suchanek a écrit : Less code means less bugs so add a knob to skip the compat stuff. I guess on PPC64 you have Gigabytes of memory and thousands of bogomips, hence you focus on bugs. My main focus usually is kernel size and performance, which makes this series interesting as well. Anyway, I was wondering, would it make sense (in a following series, not in this one) to make it buildable as a module, just like some of binfmt ? Christophe This is tested on ppc64le top of https://patchwork.ozlabs.org/cover/1153556/ Changes in v2: saner CONFIG_COMPAT ifdefs Changes in v3: - change llseek to 32bit instead of builing it unconditionally in fs - clanup the makefile conditionals - remove some ifdefs or convert to IS_DEFINED where possible Changes in v4: - cleanup is_32bit_task and current_is_64bit - more makefile cleanup Changes in v5: - more current_is_64bit cleanup - split off callchain.c 32bit and 64bit parts Changes in v6: - cleanup makefile after split - consolidate read_user_stack_32 - fix some checkpatch warnings Changes in v7: - add back __ARCH_WANT_SYS_LLSEEK to fix build with llseek - remove leftover hunk - add review tags Michal Suchanek (6): powerpc: Add back __ARCH_WANT_SYS_LLSEEK macro powerpc: move common register copy functions from signal_32.c to signal.c powerpc/perf: consolidate read_user_stack_32 powerpc/64: make buildable without CONFIG_COMPAT powerpc/64: Make COMPAT user-selectable disabled on littleendian by default. powerpc/perf: split callchain.c by bitness arch/powerpc/Kconfig | 5 +- arch/powerpc/include/asm/thread_info.h | 4 +- arch/powerpc/include/asm/unistd.h | 1 + arch/powerpc/kernel/Makefile | 7 +- arch/powerpc/kernel/entry_64.S | 2 + arch/powerpc/kernel/signal.c | 144 +- arch/powerpc/kernel/signal_32.c| 140 - arch/powerpc/kernel/syscall_64.c | 6 +- arch/powerpc/kernel/vdso.c | 5 +- arch/powerpc/perf/Makefile | 5 +- arch/powerpc/perf/callchain.c | 377 + arch/powerpc/perf/callchain.h | 11 + arch/powerpc/perf/callchain_32.c | 204 + arch/powerpc/perf/callchain_64.c | 185 fs/read_write.c| 3 +- 15 files changed, 566 insertions(+), 533 deletions(-) create mode 100644 arch/powerpc/perf/callchain.h create mode 100644 arch/powerpc/perf/callchain_32.c create mode 100644 arch/powerpc/perf/callchain_64.c
Re: Oops (request_key_auth_describe) while running cve-2016-7042 from LTP
> On 30-Aug-2019, at 8:43 PM, David Howells wrote: > > Can you try this patch instead of Hillf’s? Works for me. Test ran fine without any problem. Tested-by: Sachin Sant Thanks -Sachin
lockdep warning while booting POWER9 PowerNV
https://raw.githubusercontent.com/cailca/linux-mm/master/powerpc.config Once in a while, booting an IBM POWER9 PowerNV system (8335-GTH) would generate a warning in lockdep_register_key() at, if (WARN_ON_ONCE(static_obj(key))) because key = 0xc19ad118 &_stext = 0xc000 &_end = 0xc49d i.e., it will cause static_obj() returns 1. [ 23.738200][ T13] ahci 0004:03:00.0: enabling device (0541 -> 0543) [ 23.748692][T5] tg3.c:v3.137 (May 11, 2014) [ 23.748731][T5] tg3 0005:01:00.0: enabling device (0140 -> 0142) [ 23.751478][ T13] ahci 0004:03:00.0: AHCI 0001. 32 slots 4 ports 6 Gbps 0xf impl SATA mode [ 23.751517][ T13] ahci 0004:03:00.0: flags: 64bit ncq sntf led only pmp fbs pio slum part sxs [ 23.791077][ T13] scsi host0: ahci [ 23.802752][ T13] [ cut here ] [ 23.802786][ T13] WARNING: CPU: 0 PID: 13 at kernel/locking/lockdep.c:1120 lockdep_register_key+0x68/0x200 [ 23.802814][ T13] Modules linked in: mdio tg3(+) ahci(+) libahci libphy firmware_class libata dm_mirror dm_region_hash dm_log dm_mod [ 23.802884][ T13] CPU: 0 PID: 13 Comm: kworker/0:1 Not tainted 5.3.0-rc6- next-20190830 #4 [ 23.802930][ T13] Workqueue: events work_for_cpu_fn [ 23.802962][ T13] NIP: c019eed8 LR: c0129400 CTR: c08a46dc [ 23.802988][ T13] REGS: c0002db2f130 TRAP: 0700 Not tainted (5.3.0- rc6-next-20190830) [ 23.803032][ T13] MSR: 9282b033 CR: 48800a89 XER: 2004 [ 23.803096][ T13] CFAR: c019eeac IRQMASK: 0 [ 23.803096][ T13] GPR00: c0129400 c0002db2f3c0 c2bb9400 c49d [ 23.803096][ T13] GPR04: c2d84718 0a01ff10 [ 23.803096][ T13] GPR08: c0b8a16b c0a515cc c0b8a16a 0044 [ 23.803096][ T13] GPR12: 88800a89 c49d c0080eea3290 0001 [ 23.803096][ T13] GPR16: c01bca584500 c7244954 c01bca584508 0020 [ 23.803096][ T13] GPR20: c1aea180 0001 c0080eee7560 c01bca584500 [ 23.803096][ T13] GPR24: c01bca584448 0002000a c1aea148 c0b8a161 [ 23.803096][ T13] GPR28: c1aea020 c1aea118 c1aea000 c0002db2f440 [ 23.803407][ T13] NIP [c019eed8] lockdep_register_key+0x68/0x200 [ 23.803432][ T13] LR [c0129400] wq_init_lockdep+0x40/0xc0 [ 23.803461][ T13] Call Trace: [ 23.803491][ T13] [c0002db2f3c0] [c0b8a16a] trunc_msg+0x385f9/0x4c30f (unreliable) [ 23.803531][ T13] [c0002db2f440] [c0129400] wq_init_lockdep+0x40/0xc0 [ 23.803577][ T13] [c0002db2f4c0] [c0128d90] alloc_workqueue+0x1e0/0x620 [ 23.803623][ T13] [c0002db2f5c0] [c06ca048] scsi_host_alloc+0x3d8/0x490 [ 23.803701][ T13] [c0002db2f660] [c0080ee73198] ata_scsi_add_hosts+0xd0/0x220 [libata] [ 23.803771][ T13] [c0002db2f6f0] [c0080ee6d440] ata_host_register+0x178/0x400 [libata] [ 23.803840][ T13] [c0002db2f7d0] [c0080ee6d8f4] ata_host_activate+0x17c/0x210 [libata] [ 23.803883][ T13] [c0002db2f880] [c0080edf4c3c] ahci_host_activate+0x84/0x250 [libahci] [ 23.803944][ T13] [c0002db2f940] [c0080f050c7c] ahci_init_one+0xc74/0xdc0 [ahci] [ 23.803992][ T13] [c0002db2faa0] [c062b188] local_pci_probe+0x78/0x100 [ 23.804048][ T13] [c0002db2fb30] [c012c0b0] work_for_cpu_fn+0x40/0x70 [ 23.804087][ T13] [c0002db2fb60] [c0130328] process_one_work+0x388/0x750 [ 23.804135][ T13] [c0002db2fc60] [c012fe30] process_scheduled_works+0x50/0x90 [ 23.804180][ T13] [c0002db2fca0] [c0130c50] worker_thread+0x3d0/0x570 [ 23.804216][ T13] [c0002db2fda0] [c0139a08] kthread+0x1b8/0x1e0 [ 23.804253][ T13] [c0002db2fe20] [c000b660] ret_from_kernel_thread+0x5c/0x7c [ 23.804298][ T13] Instruction dump: [ 23.804326][ T13] fbc10070 4194002c 7fa3eb78 481864a5 6000 70630001 41810018 7fa3eb78 [ 23.804373][ T13] 48075121 6000 70630001 40810020 <0fe0> ebc10070 eba10068 38210080 [ 23.804419][ T13] ---[ end trace 9ceca43eedad2a2b ]--- [ 23.810924][T5] tg3 0005:01:00.0 eth0: Tigon3 [partno(BCM95719) rev 5719001] (PCI Express) MAC address 08:94:ef:80:81:c0 [ 23.810967][T5] tg3 0005:01:00.0 eth0: attached PHY is 5719C (10/100/1000Base-T Ethernet) (WireSpeed[1], EEE[1]) [ 23.811027][T5] tg3 0005:01:00.0 eth0: RXcsums[1] LinkChgREG[0] MIirq[0] ASF[1] TSOcap[1] [ 23.811074][T5] tg3 0005:01:00.0 eth0: dma_rwctrl[] dma_mask[64- bit] [ 23.811284][ T13] scsi host1: ahci
[PATCH v7 6/6] powerpc/perf: split callchain.c by bitness
Building callchain.c with !COMPAT proved quite ugly with all the defines. Splitting out the 32bit and 64bit parts looks better. No code change intended. Signed-off-by: Michal Suchanek Reviewed-by: Christophe Leroy --- v6: - move current_is_64bit consolidetaion to earlier patch - move defines to the top of callchain_32.c - Makefile cleanup --- arch/powerpc/perf/Makefile | 5 +- arch/powerpc/perf/callchain.c| 365 +-- arch/powerpc/perf/callchain.h| 11 + arch/powerpc/perf/callchain_32.c | 204 + arch/powerpc/perf/callchain_64.c | 185 5 files changed, 405 insertions(+), 365 deletions(-) create mode 100644 arch/powerpc/perf/callchain.h create mode 100644 arch/powerpc/perf/callchain_32.c create mode 100644 arch/powerpc/perf/callchain_64.c diff --git a/arch/powerpc/perf/Makefile b/arch/powerpc/perf/Makefile index c155dcbb8691..53d614e98537 100644 --- a/arch/powerpc/perf/Makefile +++ b/arch/powerpc/perf/Makefile @@ -1,6 +1,9 @@ # SPDX-License-Identifier: GPL-2.0 -obj-$(CONFIG_PERF_EVENTS) += callchain.o perf_regs.o +obj-$(CONFIG_PERF_EVENTS) += callchain.o callchain_$(BITS).o perf_regs.o +ifdef CONFIG_COMPAT +obj-$(CONFIG_PERF_EVENTS) += callchain_32.o +endif obj-$(CONFIG_PPC_PERF_CTRS)+= core-book3s.o bhrb.o obj64-$(CONFIG_PPC_PERF_CTRS) += ppc970-pmu.o power5-pmu.o \ diff --git a/arch/powerpc/perf/callchain.c b/arch/powerpc/perf/callchain.c index 9b8dc822f531..8f30f1b47c78 100644 --- a/arch/powerpc/perf/callchain.c +++ b/arch/powerpc/perf/callchain.c @@ -15,11 +15,9 @@ #include #include #include -#ifdef CONFIG_COMPAT -#include "../kernel/ppc32.h" -#endif #include +#include "callchain.h" /* * Is sp valid as the address of the next kernel stack frame after prev_sp? @@ -102,367 +100,6 @@ perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, struct pt_regs *re } } -#ifdef CONFIG_PPC64 -/* - * On 64-bit we don't want to invoke hash_page on user addresses from - * interrupt context, so if the access faults, we read the page tables - * to find which page (if any) is mapped and access it directly. - */ -static int read_user_stack_slow(void __user *ptr, void *buf, int nb) -{ - int ret = -EFAULT; - pgd_t *pgdir; - pte_t *ptep, pte; - unsigned shift; - unsigned long addr = (unsigned long) ptr; - unsigned long offset; - unsigned long pfn, flags; - void *kaddr; - - pgdir = current->mm->pgd; - if (!pgdir) - return -EFAULT; - - local_irq_save(flags); - ptep = find_current_mm_pte(pgdir, addr, NULL, &shift); - if (!ptep) - goto err_out; - if (!shift) - shift = PAGE_SHIFT; - - /* align address to page boundary */ - offset = addr & ((1UL << shift) - 1); - - pte = READ_ONCE(*ptep); - if (!pte_present(pte) || !pte_user(pte)) - goto err_out; - pfn = pte_pfn(pte); - if (!page_is_ram(pfn)) - goto err_out; - - /* no highmem to worry about here */ - kaddr = pfn_to_kaddr(pfn); - memcpy(buf, kaddr + offset, nb); - ret = 0; -err_out: - local_irq_restore(flags); - return ret; -} - -static int read_user_stack_64(unsigned long __user *ptr, unsigned long *ret) -{ - if ((unsigned long)ptr > TASK_SIZE - sizeof(unsigned long) || - ((unsigned long)ptr & 7)) - return -EFAULT; - - pagefault_disable(); - if (!__get_user_inatomic(*ret, ptr)) { - pagefault_enable(); - return 0; - } - pagefault_enable(); - - return read_user_stack_slow(ptr, ret, 8); -} - -static inline int valid_user_sp(unsigned long sp, int is_64) -{ - if (!sp || (sp & 7) || sp > (is_64 ? TASK_SIZE : 0x1UL) - 32) - return 0; - return 1; -} - -/* - * 64-bit user processes use the same stack frame for RT and non-RT signals. - */ -struct signal_frame_64 { - chardummy[__SIGNAL_FRAMESIZE]; - struct ucontext uc; - unsigned long unused[2]; - unsigned inttramp[6]; - struct siginfo *pinfo; - void*puc; - struct siginfo info; - charabigap[288]; -}; - -static int is_sigreturn_64_address(unsigned long nip, unsigned long fp) -{ - if (nip == fp + offsetof(struct signal_frame_64, tramp)) - return 1; - if (vdso64_rt_sigtramp && current->mm->context.vdso_base && - nip == current->mm->context.vdso_base + vdso64_rt_sigtramp) - return 1; - return 0; -} - -/* - * Do some sanity checking on the signal frame pointed to by sp. - * We check the pinfo and puc pointers in the frame. - */ -static int sane_signal_64_frame(unsigned long sp) -{ - struct signal_frame_64 __user *sf; - unsigned long pinfo, puc; - - sf = (struct signal_frame_64 __user *) sp; -
[PATCH v7 5/6] powerpc/64: Make COMPAT user-selectable disabled on littleendian by default.
On bigendian ppc64 it is common to have 32bit legacy binaries but much less so on littleendian. Signed-off-by: Michal Suchanek Reviewed-by: Christophe Leroy --- v3: make configurable --- arch/powerpc/Kconfig | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 5bab0bb6b833..b0339e892329 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -264,8 +264,9 @@ config PANIC_TIMEOUT default 180 config COMPAT - bool - default y if PPC64 + bool "Enable support for 32bit binaries" + depends on PPC64 + default y if !CPU_LITTLE_ENDIAN select COMPAT_BINFMT_ELF select ARCH_WANT_OLD_COMPAT_IPC select COMPAT_OLD_SIGACTION -- 2.22.0
[PATCH v7 4/6] powerpc/64: make buildable without CONFIG_COMPAT
There are numerous references to 32bit functions in generic and 64bit code so ifdef them out. Signed-off-by: Michal Suchanek --- v2: - fix 32bit ifdef condition in signal.c - simplify the compat ifdef condition in vdso.c - 64bit is redundant - simplify the compat ifdef condition in callchain.c - 64bit is redundant v3: - use IS_ENABLED and maybe_unused where possible - do not ifdef declarations - clean up Makefile v4: - further makefile cleanup - simplify is_32bit_task conditions - avoid ifdef in condition by using return v5: - avoid unreachable code on 32bit - make is_current_64bit constant on !COMPAT - add stub perf_callchain_user_32 to avoid some ifdefs v6: - consolidate current_is_64bit v7: - remove leftover perf_callchain_user_32 stub from previous series version --- arch/powerpc/include/asm/thread_info.h | 4 ++-- arch/powerpc/kernel/Makefile | 7 +++--- arch/powerpc/kernel/entry_64.S | 2 ++ arch/powerpc/kernel/signal.c | 3 +-- arch/powerpc/kernel/syscall_64.c | 6 ++--- arch/powerpc/kernel/vdso.c | 5 ++--- arch/powerpc/perf/callchain.c | 31 +- 7 files changed, 27 insertions(+), 31 deletions(-) diff --git a/arch/powerpc/include/asm/thread_info.h b/arch/powerpc/include/asm/thread_info.h index 8e1d0195ac36..c128d8a48ea3 100644 --- a/arch/powerpc/include/asm/thread_info.h +++ b/arch/powerpc/include/asm/thread_info.h @@ -144,10 +144,10 @@ static inline bool test_thread_local_flags(unsigned int flags) return (ti->local_flags & flags) != 0; } -#ifdef CONFIG_PPC64 +#ifdef CONFIG_COMPAT #define is_32bit_task()(test_thread_flag(TIF_32BIT)) #else -#define is_32bit_task()(1) +#define is_32bit_task()(IS_ENABLED(CONFIG_PPC32)) #endif #if defined(CONFIG_PPC64) diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 1d646a94d96c..9d8772e863b9 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile @@ -44,16 +44,15 @@ CFLAGS_btext.o += -DDISABLE_BRANCH_PROFILING endif obj-y := cputable.o ptrace.o syscalls.o \ - irq.o align.o signal_32.o pmc.o vdso.o \ + irq.o align.o signal_$(BITS).o pmc.o vdso.o \ process.o systbl.o idle.o \ signal.o sysfs.o cacheinfo.o time.o \ prom.o traps.o setup-common.o \ udbg.o misc.o io.o misc_$(BITS).o \ of_platform.o prom_parse.o -obj-$(CONFIG_PPC64)+= setup_64.o sys_ppc32.o \ - signal_64.o ptrace32.o \ - paca.o nvram_64.o firmware.o \ +obj-$(CONFIG_PPC64)+= setup_64.o paca.o nvram_64.o firmware.o \ syscall_64.o +obj-$(CONFIG_COMPAT) += sys_ppc32.o ptrace32.o signal_32.o obj-$(CONFIG_VDSO32) += vdso32/ obj-$(CONFIG_PPC_WATCHDOG) += watchdog.o obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 2ec825a85f5b..a2dbf216f607 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -51,8 +51,10 @@ SYS_CALL_TABLE: .tc sys_call_table[TC],sys_call_table +#ifdef CONFIG_COMPAT COMPAT_SYS_CALL_TABLE: .tc compat_sys_call_table[TC],compat_sys_call_table +#endif /* This value is used to mark exception frames on the stack. */ exception_marker: diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c index 60436432399f..61678cb0e6a1 100644 --- a/arch/powerpc/kernel/signal.c +++ b/arch/powerpc/kernel/signal.c @@ -247,7 +247,6 @@ static void do_signal(struct task_struct *tsk) sigset_t *oldset = sigmask_to_save(); struct ksignal ksig = { .sig = 0 }; int ret; - int is32 = is_32bit_task(); BUG_ON(tsk != current); @@ -277,7 +276,7 @@ static void do_signal(struct task_struct *tsk) rseq_signal_deliver(&ksig, tsk->thread.regs); - if (is32) { + if (is_32bit_task()) { if (ksig.ka.sa.sa_flags & SA_SIGINFO) ret = handle_rt_signal32(&ksig, oldset, tsk); else diff --git a/arch/powerpc/kernel/syscall_64.c b/arch/powerpc/kernel/syscall_64.c index 98ed970796d5..0d5cbbe54cf1 100644 --- a/arch/powerpc/kernel/syscall_64.c +++ b/arch/powerpc/kernel/syscall_64.c @@ -38,7 +38,6 @@ typedef long (*syscall_fn)(long, long, long, long, long, long); long system_call_exception(long r3, long r4, long r5, long r6, long r7, long r8, unsigned long r0, struct pt_regs *regs) { - unsigned long ti_flags; syscall_fn f; BUG_ON(!(regs->msr & MSR_PR)); @@ -83,8 +82,7 @@ long system_call_exception(long r3, long r4, long r5, long r6, long r7, long r8,
[PATCH v7 3/6] powerpc/perf: consolidate read_user_stack_32
There are two almost identical copies for 32bit and 64bit. The function is used only in 32bit code which will be split out in next patch so consolidate to one function. Signed-off-by: Michal Suchanek Reviewed-by: Christophe Leroy --- new patch in v6 --- arch/powerpc/perf/callchain.c | 25 + 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/arch/powerpc/perf/callchain.c b/arch/powerpc/perf/callchain.c index c84bbd4298a0..b7cdcce20280 100644 --- a/arch/powerpc/perf/callchain.c +++ b/arch/powerpc/perf/callchain.c @@ -165,22 +165,6 @@ static int read_user_stack_64(unsigned long __user *ptr, unsigned long *ret) return read_user_stack_slow(ptr, ret, 8); } -static int read_user_stack_32(unsigned int __user *ptr, unsigned int *ret) -{ - if ((unsigned long)ptr > TASK_SIZE - sizeof(unsigned int) || - ((unsigned long)ptr & 3)) - return -EFAULT; - - pagefault_disable(); - if (!__get_user_inatomic(*ret, ptr)) { - pagefault_enable(); - return 0; - } - pagefault_enable(); - - return read_user_stack_slow(ptr, ret, 4); -} - static inline int valid_user_sp(unsigned long sp, int is_64) { if (!sp || (sp & 7) || sp > (is_64 ? TASK_SIZE : 0x1UL) - 32) @@ -295,6 +279,12 @@ static inline int current_is_64bit(void) } #else /* CONFIG_PPC64 */ +static int read_user_stack_slow(void __user *ptr, void *buf, int nb) +{ + return 0; +} +#endif /* CONFIG_PPC64 */ + /* * On 32-bit we just access the address and let hash_page create a * HPTE if necessary, so there is no need to fall back to reading @@ -313,9 +303,12 @@ static int read_user_stack_32(unsigned int __user *ptr, unsigned int *ret) rc = __get_user_inatomic(*ret, ptr); pagefault_enable(); + if (IS_ENABLED(CONFIG_PPC64) && rc) + return read_user_stack_slow(ptr, ret, 4); return rc; } +#ifndef CONFIG_PPC64 static inline void perf_callchain_user_64(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs) { -- 2.22.0
[PATCH v7 2/6] powerpc: move common register copy functions from signal_32.c to signal.c
These functions are required for 64bit as well. Signed-off-by: Michal Suchanek Reviewed-by: Christophe Leroy --- arch/powerpc/kernel/signal.c| 141 arch/powerpc/kernel/signal_32.c | 140 --- 2 files changed, 141 insertions(+), 140 deletions(-) diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c index e6c30cee6abf..60436432399f 100644 --- a/arch/powerpc/kernel/signal.c +++ b/arch/powerpc/kernel/signal.c @@ -18,12 +18,153 @@ #include #include #include +#include #include #include #include #include "signal.h" +#ifdef CONFIG_VSX +unsigned long copy_fpr_to_user(void __user *to, + struct task_struct *task) +{ + u64 buf[ELF_NFPREG]; + int i; + + /* save FPR copy to local buffer then write to the thread_struct */ + for (i = 0; i < (ELF_NFPREG - 1) ; i++) + buf[i] = task->thread.TS_FPR(i); + buf[i] = task->thread.fp_state.fpscr; + return __copy_to_user(to, buf, ELF_NFPREG * sizeof(double)); +} + +unsigned long copy_fpr_from_user(struct task_struct *task, +void __user *from) +{ + u64 buf[ELF_NFPREG]; + int i; + + if (__copy_from_user(buf, from, ELF_NFPREG * sizeof(double))) + return 1; + for (i = 0; i < (ELF_NFPREG - 1) ; i++) + task->thread.TS_FPR(i) = buf[i]; + task->thread.fp_state.fpscr = buf[i]; + + return 0; +} + +unsigned long copy_vsx_to_user(void __user *to, + struct task_struct *task) +{ + u64 buf[ELF_NVSRHALFREG]; + int i; + + /* save FPR copy to local buffer then write to the thread_struct */ + for (i = 0; i < ELF_NVSRHALFREG; i++) + buf[i] = task->thread.fp_state.fpr[i][TS_VSRLOWOFFSET]; + return __copy_to_user(to, buf, ELF_NVSRHALFREG * sizeof(double)); +} + +unsigned long copy_vsx_from_user(struct task_struct *task, +void __user *from) +{ + u64 buf[ELF_NVSRHALFREG]; + int i; + + if (__copy_from_user(buf, from, ELF_NVSRHALFREG * sizeof(double))) + return 1; + for (i = 0; i < ELF_NVSRHALFREG ; i++) + task->thread.fp_state.fpr[i][TS_VSRLOWOFFSET] = buf[i]; + return 0; +} + +#ifdef CONFIG_PPC_TRANSACTIONAL_MEM +unsigned long copy_ckfpr_to_user(void __user *to, + struct task_struct *task) +{ + u64 buf[ELF_NFPREG]; + int i; + + /* save FPR copy to local buffer then write to the thread_struct */ + for (i = 0; i < (ELF_NFPREG - 1) ; i++) + buf[i] = task->thread.TS_CKFPR(i); + buf[i] = task->thread.ckfp_state.fpscr; + return __copy_to_user(to, buf, ELF_NFPREG * sizeof(double)); +} + +unsigned long copy_ckfpr_from_user(struct task_struct *task, + void __user *from) +{ + u64 buf[ELF_NFPREG]; + int i; + + if (__copy_from_user(buf, from, ELF_NFPREG * sizeof(double))) + return 1; + for (i = 0; i < (ELF_NFPREG - 1) ; i++) + task->thread.TS_CKFPR(i) = buf[i]; + task->thread.ckfp_state.fpscr = buf[i]; + + return 0; +} + +unsigned long copy_ckvsx_to_user(void __user *to, + struct task_struct *task) +{ + u64 buf[ELF_NVSRHALFREG]; + int i; + + /* save FPR copy to local buffer then write to the thread_struct */ + for (i = 0; i < ELF_NVSRHALFREG; i++) + buf[i] = task->thread.ckfp_state.fpr[i][TS_VSRLOWOFFSET]; + return __copy_to_user(to, buf, ELF_NVSRHALFREG * sizeof(double)); +} + +unsigned long copy_ckvsx_from_user(struct task_struct *task, + void __user *from) +{ + u64 buf[ELF_NVSRHALFREG]; + int i; + + if (__copy_from_user(buf, from, ELF_NVSRHALFREG * sizeof(double))) + return 1; + for (i = 0; i < ELF_NVSRHALFREG ; i++) + task->thread.ckfp_state.fpr[i][TS_VSRLOWOFFSET] = buf[i]; + return 0; +} +#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */ +#else +inline unsigned long copy_fpr_to_user(void __user *to, + struct task_struct *task) +{ + return __copy_to_user(to, task->thread.fp_state.fpr, + ELF_NFPREG * sizeof(double)); +} + +inline unsigned long copy_fpr_from_user(struct task_struct *task, + void __user *from) +{ + return __copy_from_user(task->thread.fp_state.fpr, from, + ELF_NFPREG * sizeof(double)); +} + +#ifdef CONFIG_PPC_TRANSACTIONAL_MEM +inline unsigned long copy_ckfpr_to_user(void __user *to, +struct task_struct *task) +{ + return __copy_to_user(to, task->thread.ckfp_state.fpr, + ELF_NFPREG * sizeof(double)); +} +
[PATCH v7 1/6] powerpc: Add back __ARCH_WANT_SYS_LLSEEK macro
This partially reverts commit caf6f9c8a326 ("asm-generic: Remove unneeded __ARCH_WANT_SYS_LLSEEK macro") When CONFIG_COMPAT is disabled on ppc64 the kernel does not build. There is resistance to both removing the llseek syscall from the 64bit syscall tables and building the llseek interface unconditionally. Link: https://lore.kernel.org/lkml/20190828151552.ga16...@infradead.org/ Link: https://lore.kernel.org/lkml/20190829214319.498c7de2@naga/ Signed-off-by: Michal Suchanek Reviewed-by: Arnd Bergmann --- arch/powerpc/include/asm/unistd.h | 1 + fs/read_write.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/include/asm/unistd.h b/arch/powerpc/include/asm/unistd.h index b0720c7c3fcf..700fcdac2e3c 100644 --- a/arch/powerpc/include/asm/unistd.h +++ b/arch/powerpc/include/asm/unistd.h @@ -31,6 +31,7 @@ #define __ARCH_WANT_SYS_SOCKETCALL #define __ARCH_WANT_SYS_FADVISE64 #define __ARCH_WANT_SYS_GETPGRP +#define __ARCH_WANT_SYS_LLSEEK #define __ARCH_WANT_SYS_NICE #define __ARCH_WANT_SYS_OLD_GETRLIMIT #define __ARCH_WANT_SYS_OLD_UNAME diff --git a/fs/read_write.c b/fs/read_write.c index 5bbf587f5bc1..89aa2701dbeb 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -331,7 +331,8 @@ COMPAT_SYSCALL_DEFINE3(lseek, unsigned int, fd, compat_off_t, offset, unsigned i } #endif -#if !defined(CONFIG_64BIT) || defined(CONFIG_COMPAT) +#if !defined(CONFIG_64BIT) || defined(CONFIG_COMPAT) || \ + defined(__ARCH_WANT_SYS_LLSEEK) SYSCALL_DEFINE5(llseek, unsigned int, fd, unsigned long, offset_high, unsigned long, offset_low, loff_t __user *, result, unsigned int, whence) -- 2.22.0
[PATCH v7 0/6] Disable compat cruft on ppc64le v7
Less code means less bugs so add a knob to skip the compat stuff. This is tested on ppc64le top of https://patchwork.ozlabs.org/cover/1153556/ Changes in v2: saner CONFIG_COMPAT ifdefs Changes in v3: - change llseek to 32bit instead of builing it unconditionally in fs - clanup the makefile conditionals - remove some ifdefs or convert to IS_DEFINED where possible Changes in v4: - cleanup is_32bit_task and current_is_64bit - more makefile cleanup Changes in v5: - more current_is_64bit cleanup - split off callchain.c 32bit and 64bit parts Changes in v6: - cleanup makefile after split - consolidate read_user_stack_32 - fix some checkpatch warnings Changes in v7: - add back __ARCH_WANT_SYS_LLSEEK to fix build with llseek - remove leftover hunk - add review tags Michal Suchanek (6): powerpc: Add back __ARCH_WANT_SYS_LLSEEK macro powerpc: move common register copy functions from signal_32.c to signal.c powerpc/perf: consolidate read_user_stack_32 powerpc/64: make buildable without CONFIG_COMPAT powerpc/64: Make COMPAT user-selectable disabled on littleendian by default. powerpc/perf: split callchain.c by bitness arch/powerpc/Kconfig | 5 +- arch/powerpc/include/asm/thread_info.h | 4 +- arch/powerpc/include/asm/unistd.h | 1 + arch/powerpc/kernel/Makefile | 7 +- arch/powerpc/kernel/entry_64.S | 2 + arch/powerpc/kernel/signal.c | 144 +- arch/powerpc/kernel/signal_32.c| 140 - arch/powerpc/kernel/syscall_64.c | 6 +- arch/powerpc/kernel/vdso.c | 5 +- arch/powerpc/perf/Makefile | 5 +- arch/powerpc/perf/callchain.c | 377 + arch/powerpc/perf/callchain.h | 11 + arch/powerpc/perf/callchain_32.c | 204 + arch/powerpc/perf/callchain_64.c | 185 fs/read_write.c| 3 +- 15 files changed, 566 insertions(+), 533 deletions(-) create mode 100644 arch/powerpc/perf/callchain.h create mode 100644 arch/powerpc/perf/callchain_32.c create mode 100644 arch/powerpc/perf/callchain_64.c -- 2.22.0
Re: [PATCH 1/2] ftrace: Fix NULL pointer dereference in t_probe_next()
On Thu, 4 Jul 2019 20:04:41 +0530 "Naveen N. Rao" wrote: > kernel/trace/ftrace.c | 4 > 1 file changed, 4 insertions(+) > > diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c > index 7b037295a1f1..0791eafb693d 100644 > --- a/kernel/trace/ftrace.c > +++ b/kernel/trace/ftrace.c > @@ -3093,6 +3093,10 @@ t_probe_next(struct seq_file *m, loff_t *pos) > hnd = &iter->probe_entry->hlist; > > hash = iter->probe->ops.func_hash->filter_hash; > + > + if (!hash) > + return NULL; > + > size = 1 << hash->size_bits; > > retry: OK, I added this, but I'm also adding this on top: -- Steve From 372e0d01da71c84dcecf7028598a33813b0d5256 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Fri, 30 Aug 2019 16:30:01 -0400 Subject: [PATCH] ftrace: Check for empty hash and comment the race with registering probes The race between adding a function probe and reading the probes that exist is very subtle. It needs a comment. Also, the issue can also happen if the probe has has the EMPTY_HASH as its func_hash. Cc: sta...@vger.kernel.org Fixes: 7b60f3d876156 ("ftrace: Dynamically create the probe ftrace_ops for the trace_array") Signed-off-by: Steven Rostedt (VMware) --- kernel/trace/ftrace.c | 10 +- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 80beed2cf0da..6200a6fe10e3 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -3096,7 +3096,11 @@ t_probe_next(struct seq_file *m, loff_t *pos) hash = iter->probe->ops.func_hash->filter_hash; - if (!hash) + /* +* A probe being registered may temporarily have an empty hash +* and it's at the end of the func_probes list. +*/ + if (!hash || hash == EMPTY_HASH) return NULL; size = 1 << hash->size_bits; @@ -4324,6 +4328,10 @@ register_ftrace_function_probe(char *glob, struct trace_array *tr, mutex_unlock(&ftrace_lock); + /* +* Note, there's a small window here that the func_hash->filter_hash +* may be NULL or empty. Need to be carefule when reading the loop. +*/ mutex_lock(&probe->ops.func_hash->regex_lock); orig_hash = &probe->ops.func_hash->filter_hash; -- 2.20.1
Re: [PATCH] Revert "asm-generic: Remove unneeded __ARCH_WANT_SYS_LLSEEK macro"
On Fri, Aug 30, 2019 at 10:13 PM Michal Suchánek wrote: > On Fri, 30 Aug 2019 21:54:43 +0200 > Arnd Bergmann wrote: > > > index 5bbf587f5bc1..2f3c4bb138c4 100644 > > > --- a/fs/read_write.c > > > +++ b/fs/read_write.c > > > @@ -331,7 +331,7 @@ COMPAT_SYSCALL_DEFINE3(lseek, unsigned int, fd, > > > compat_off_t, offset, unsigned i > > > } > > > #endif > > > > > > -#if !defined(CONFIG_64BIT) || defined(CONFIG_COMPAT) > > > +#ifdef __ARCH_WANT_SYS_LLSEEK > > > SYSCALL_DEFINE5(llseek, unsigned int, fd, unsigned long, offset_high, > > > unsigned long, offset_low, loff_t __user *, result, > > > unsigned int, whence) > > > > However, only reverting the patch will now break all newly added > > 32-bit architectures that don't define __ARCH_WANT_SYS_LLSEEK: > > at least nds32 and riscv32 come to mind, not sure if there is another. > > AFAICT nds32 never had the syscall. Its headers were added without > __ARCH_WANT_SYS_LLSEEK before the define was removed. nds32 got it from include/asm-generic/unistd.h Arnd
Re: [PATCH v6 4/6] powerpc/64: make buildable without CONFIG_COMPAT
On Fri, 30 Aug 2019 22:21:09 +0200 Christophe Leroy wrote: > Le 30/08/2019 à 20:57, Michal Suchanek a écrit : > > There are numerous references to 32bit functions in generic and 64bit > > code so ifdef them out. > > > > Signed-off-by: Michal Suchanek > > --- > > v2: > > - fix 32bit ifdef condition in signal.c > > - simplify the compat ifdef condition in vdso.c - 64bit is redundant > > - simplify the compat ifdef condition in callchain.c - 64bit is redundant > > v3: > > - use IS_ENABLED and maybe_unused where possible > > - do not ifdef declarations > > - clean up Makefile > > v4: > > - further makefile cleanup > > - simplify is_32bit_task conditions > > - avoid ifdef in condition by using return > > v5: > > - avoid unreachable code on 32bit > > - make is_current_64bit constant on !COMPAT > > - add stub perf_callchain_user_32 to avoid some ifdefs > > v6: > > - consolidate current_is_64bit > > --- > > arch/powerpc/include/asm/thread_info.h | 4 +-- > > arch/powerpc/kernel/Makefile | 7 +++-- > > arch/powerpc/kernel/entry_64.S | 2 ++ > > arch/powerpc/kernel/signal.c | 3 +-- > > arch/powerpc/kernel/syscall_64.c | 6 ++--- > > arch/powerpc/kernel/vdso.c | 5 ++-- > > arch/powerpc/perf/callchain.c | 37 +++--- > > 7 files changed, 33 insertions(+), 31 deletions(-) > > > > [...] > > > diff --git a/arch/powerpc/perf/callchain.c b/arch/powerpc/perf/callchain.c > > index b7cdcce20280..788ad2c63f18 100644 > > --- a/arch/powerpc/perf/callchain.c > > +++ b/arch/powerpc/perf/callchain.c > > @@ -15,7 +15,7 @@ > > #include > > #include > > #include > > -#ifdef CONFIG_PPC64 > > +#ifdef CONFIG_COMPAT > > #include "../kernel/ppc32.h" > > #endif > > #include > > @@ -268,16 +268,6 @@ static void perf_callchain_user_64(struct > > perf_callchain_entry_ctx *entry, > > } > > } > > > > -static inline int current_is_64bit(void) > > -{ > > - /* > > -* We can't use test_thread_flag() here because we may be on an > > -* interrupt stack, and the thread flags don't get copied over > > -* from the thread_info on the main stack to the interrupt stack. > > -*/ > > - return !test_ti_thread_flag(task_thread_info(current), TIF_32BIT); > > -} > > - > > #else /* CONFIG_PPC64 */ > > static int read_user_stack_slow(void __user *ptr, void *buf, int nb) > > { > > @@ -314,11 +304,6 @@ static inline void perf_callchain_user_64(struct > > perf_callchain_entry_ctx *entry > > { > > } > > > > -static inline int current_is_64bit(void) > > -{ > > - return 0; > > -} > > - > > static inline int valid_user_sp(unsigned long sp, int is_64) > > { > > if (!sp || (sp & 7) || sp > TASK_SIZE - 32) > > @@ -334,6 +319,7 @@ static inline int valid_user_sp(unsigned long sp, int > > is_64) > > > > #endif /* CONFIG_PPC64 */ > > > > +#if defined(CONFIG_PPC32) || defined(CONFIG_COMPAT) > > /* > >* Layout for non-RT signal frames > >*/ > > @@ -475,6 +461,25 @@ static void perf_callchain_user_32(struct > > perf_callchain_entry_ctx *entry, > > sp = next_sp; > > } > > } > > +#else /* 32bit */ > > +static void perf_callchain_user_32(struct perf_callchain_entry_ctx *entry, > > + struct pt_regs *regs) > > +{ > > + (void)&read_user_stack_32; /* unused if !COMPAT */ > > You don't need that anymore do you ? Yes, this part is not needed. It was removed later anyway but this state is broken. Thanks Michal > > Christophe > > > +} > > +#endif /* 32bit */ > > + > > +static inline int current_is_64bit(void) > > +{ > > + if (!IS_ENABLED(CONFIG_COMPAT)) > > + return IS_ENABLED(CONFIG_PPC64); > > + /* > > +* We can't use test_thread_flag() here because we may be on an > > +* interrupt stack, and the thread flags don't get copied over > > +* from the thread_info on the main stack to the interrupt stack. > > +*/ > > + return !test_ti_thread_flag(task_thread_info(current), TIF_32BIT); > > +} > > > > void > > perf_callchain_user(struct perf_callchain_entry_ctx *entry, struct > > pt_regs *regs) > >
Re:
On Fri, Aug 30, 2019 at 10:30 PM Michal Suchanek wrote: > > Subject: [PATCH] powerpc: Add back __ARCH_WANT_SYS_LLSEEK macro > > This partially reverts commit caf6f9c8a326 ("asm-generic: Remove > unneeded __ARCH_WANT_SYS_LLSEEK macro") > > When CONFIG_COMPAT is disabled on ppc64 the kernel does not build. > > There is resistance to both removing the llseek syscall from the 64bit > syscall tables and building the llseek interface unconditionally. > > Link: https://lore.kernel.org/lkml/20190828151552.ga16...@infradead.org/ > Link: https://lore.kernel.org/lkml/20190829214319.498c7de2@naga/ > > Signed-off-by: Michal Suchanek Reviewed-by: Arnd Bergmann
[no subject]
Subject: [PATCH] powerpc: Add back __ARCH_WANT_SYS_LLSEEK macro This partially reverts commit caf6f9c8a326 ("asm-generic: Remove unneeded __ARCH_WANT_SYS_LLSEEK macro") When CONFIG_COMPAT is disabled on ppc64 the kernel does not build. There is resistance to both removing the llseek syscall from the 64bit syscall tables and building the llseek interface unconditionally. Link: https://lore.kernel.org/lkml/20190828151552.ga16...@infradead.org/ Link: https://lore.kernel.org/lkml/20190829214319.498c7de2@naga/ Signed-off-by: Michal Suchanek --- arch/powerpc/include/asm/unistd.h | 1 + fs/read_write.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/include/asm/unistd.h b/arch/powerpc/include/asm/unistd.h index b0720c7c3fcf..700fcdac2e3c 100644 --- a/arch/powerpc/include/asm/unistd.h +++ b/arch/powerpc/include/asm/unistd.h @@ -31,6 +31,7 @@ #define __ARCH_WANT_SYS_SOCKETCALL #define __ARCH_WANT_SYS_FADVISE64 #define __ARCH_WANT_SYS_GETPGRP +#define __ARCH_WANT_SYS_LLSEEK #define __ARCH_WANT_SYS_NICE #define __ARCH_WANT_SYS_OLD_GETRLIMIT #define __ARCH_WANT_SYS_OLD_UNAME diff --git a/fs/read_write.c b/fs/read_write.c index 5bbf587f5bc1..89aa2701dbeb 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -331,7 +331,8 @@ COMPAT_SYSCALL_DEFINE3(lseek, unsigned int, fd, compat_off_t, offset, unsigned i } #endif -#if !defined(CONFIG_64BIT) || defined(CONFIG_COMPAT) +#if !defined(CONFIG_64BIT) || defined(CONFIG_COMPAT) || \ + defined(__ARCH_WANT_SYS_LLSEEK) SYSCALL_DEFINE5(llseek, unsigned int, fd, unsigned long, offset_high, unsigned long, offset_low, loff_t __user *, result, unsigned int, whence) -- 2.22.0
Re: [PATCH v6 6/6] powerpc/perf: split callchain.c by bitness
Le 30/08/2019 à 20:57, Michal Suchanek a écrit : Building callchain.c with !COMPAT proved quite ugly with all the defines. Splitting out the 32bit and 64bit parts looks better. No code change intended. Signed-off-by: Michal Suchanek Reviewed-by: Christophe Leroy --- v6: - move current_is_64bit consolidetaion to earlier patch - move defines to the top of callchain_32.c - Makefile cleanup --- arch/powerpc/perf/Makefile | 5 +- arch/powerpc/perf/callchain.c| 371 +-- arch/powerpc/perf/callchain.h| 11 + arch/powerpc/perf/callchain_32.c | 204 + arch/powerpc/perf/callchain_64.c | 185 +++ 5 files changed, 405 insertions(+), 371 deletions(-) create mode 100644 arch/powerpc/perf/callchain.h create mode 100644 arch/powerpc/perf/callchain_32.c create mode 100644 arch/powerpc/perf/callchain_64.c diff --git a/arch/powerpc/perf/Makefile b/arch/powerpc/perf/Makefile index c155dcbb8691..53d614e98537 100644 --- a/arch/powerpc/perf/Makefile +++ b/arch/powerpc/perf/Makefile @@ -1,6 +1,9 @@ # SPDX-License-Identifier: GPL-2.0 -obj-$(CONFIG_PERF_EVENTS) += callchain.o perf_regs.o +obj-$(CONFIG_PERF_EVENTS) += callchain.o callchain_$(BITS).o perf_regs.o +ifdef CONFIG_COMPAT +obj-$(CONFIG_PERF_EVENTS) += callchain_32.o +endif obj-$(CONFIG_PPC_PERF_CTRS) += core-book3s.o bhrb.o obj64-$(CONFIG_PPC_PERF_CTRS) += ppc970-pmu.o power5-pmu.o \ diff --git a/arch/powerpc/perf/callchain.c b/arch/powerpc/perf/callchain.c index 788ad2c63f18..8f30f1b47c78 100644 --- a/arch/powerpc/perf/callchain.c +++ b/arch/powerpc/perf/callchain.c @@ -15,11 +15,9 @@ #include #include #include -#ifdef CONFIG_COMPAT -#include "../kernel/ppc32.h" -#endif #include +#include "callchain.h" /* * Is sp valid as the address of the next kernel stack frame after prev_sp? @@ -102,373 +100,6 @@ perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, struct pt_regs *re } } -#ifdef CONFIG_PPC64 -/* - * On 64-bit we don't want to invoke hash_page on user addresses from - * interrupt context, so if the access faults, we read the page tables - * to find which page (if any) is mapped and access it directly. - */ -static int read_user_stack_slow(void __user *ptr, void *buf, int nb) -{ - int ret = -EFAULT; - pgd_t *pgdir; - pte_t *ptep, pte; - unsigned shift; - unsigned long addr = (unsigned long) ptr; - unsigned long offset; - unsigned long pfn, flags; - void *kaddr; - - pgdir = current->mm->pgd; - if (!pgdir) - return -EFAULT; - - local_irq_save(flags); - ptep = find_current_mm_pte(pgdir, addr, NULL, &shift); - if (!ptep) - goto err_out; - if (!shift) - shift = PAGE_SHIFT; - - /* align address to page boundary */ - offset = addr & ((1UL << shift) - 1); - - pte = READ_ONCE(*ptep); - if (!pte_present(pte) || !pte_user(pte)) - goto err_out; - pfn = pte_pfn(pte); - if (!page_is_ram(pfn)) - goto err_out; - - /* no highmem to worry about here */ - kaddr = pfn_to_kaddr(pfn); - memcpy(buf, kaddr + offset, nb); - ret = 0; -err_out: - local_irq_restore(flags); - return ret; -} - -static int read_user_stack_64(unsigned long __user *ptr, unsigned long *ret) -{ - if ((unsigned long)ptr > TASK_SIZE - sizeof(unsigned long) || - ((unsigned long)ptr & 7)) - return -EFAULT; - - pagefault_disable(); - if (!__get_user_inatomic(*ret, ptr)) { - pagefault_enable(); - return 0; - } - pagefault_enable(); - - return read_user_stack_slow(ptr, ret, 8); -} - -static inline int valid_user_sp(unsigned long sp, int is_64) -{ - if (!sp || (sp & 7) || sp > (is_64 ? TASK_SIZE : 0x1UL) - 32) - return 0; - return 1; -} - -/* - * 64-bit user processes use the same stack frame for RT and non-RT signals. - */ -struct signal_frame_64 { - chardummy[__SIGNAL_FRAMESIZE]; - struct ucontext uc; - unsigned long unused[2]; - unsigned inttramp[6]; - struct siginfo *pinfo; - void*puc; - struct siginfo info; - charabigap[288]; -}; - -static int is_sigreturn_64_address(unsigned long nip, unsigned long fp) -{ - if (nip == fp + offsetof(struct signal_frame_64, tramp)) - return 1; - if (vdso64_rt_sigtramp && current->mm->context.vdso_base && - nip == current->mm->context.vdso_base + vdso64_rt_sigtramp) - return 1; - return 0; -} - -/* - * Do some sanity checking on the signal frame pointed to by sp. - * We check the pinfo and puc pointers in the frame. - */ -static int sane_signal_64_frame(unsigned long sp) -{ - struct signal_frame_64 __user *sf; - unsigned
Re: [PATCH v6 5/6] powerpc/64: Make COMPAT user-selectable disabled on littleendian by default.
Le 30/08/2019 à 20:57, Michal Suchanek a écrit : On bigendian ppc64 it is common to have 32bit legacy binaries but much less so on littleendian. Signed-off-by: Michal Suchanek Reviewed-by: Christophe Leroy --- v3: make configurable --- arch/powerpc/Kconfig | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 5bab0bb6b833..b0339e892329 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -264,8 +264,9 @@ config PANIC_TIMEOUT default 180 config COMPAT - bool - default y if PPC64 + bool "Enable support for 32bit binaries" + depends on PPC64 + default y if !CPU_LITTLE_ENDIAN select COMPAT_BINFMT_ELF select ARCH_WANT_OLD_COMPAT_IPC select COMPAT_OLD_SIGACTION
Re: [PATCH v6 2/6] powerpc: move common register copy functions from signal_32.c to signal.c
Le 30/08/2019 à 20:57, Michal Suchanek a écrit : These functions are required for 64bit as well. Signed-off-by: Michal Suchanek Reviewed-by: christophe.le...@c-s.fr --- arch/powerpc/kernel/signal.c| 141 arch/powerpc/kernel/signal_32.c | 140 --- 2 files changed, 141 insertions(+), 140 deletions(-) diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c index e6c30cee6abf..60436432399f 100644 --- a/arch/powerpc/kernel/signal.c +++ b/arch/powerpc/kernel/signal.c @@ -18,12 +18,153 @@ #include #include #include +#include #include #include #include #include "signal.h" +#ifdef CONFIG_VSX +unsigned long copy_fpr_to_user(void __user *to, + struct task_struct *task) +{ + u64 buf[ELF_NFPREG]; + int i; + + /* save FPR copy to local buffer then write to the thread_struct */ + for (i = 0; i < (ELF_NFPREG - 1) ; i++) + buf[i] = task->thread.TS_FPR(i); + buf[i] = task->thread.fp_state.fpscr; + return __copy_to_user(to, buf, ELF_NFPREG * sizeof(double)); +} + +unsigned long copy_fpr_from_user(struct task_struct *task, +void __user *from) +{ + u64 buf[ELF_NFPREG]; + int i; + + if (__copy_from_user(buf, from, ELF_NFPREG * sizeof(double))) + return 1; + for (i = 0; i < (ELF_NFPREG - 1) ; i++) + task->thread.TS_FPR(i) = buf[i]; + task->thread.fp_state.fpscr = buf[i]; + + return 0; +} + +unsigned long copy_vsx_to_user(void __user *to, + struct task_struct *task) +{ + u64 buf[ELF_NVSRHALFREG]; + int i; + + /* save FPR copy to local buffer then write to the thread_struct */ + for (i = 0; i < ELF_NVSRHALFREG; i++) + buf[i] = task->thread.fp_state.fpr[i][TS_VSRLOWOFFSET]; + return __copy_to_user(to, buf, ELF_NVSRHALFREG * sizeof(double)); +} + +unsigned long copy_vsx_from_user(struct task_struct *task, +void __user *from) +{ + u64 buf[ELF_NVSRHALFREG]; + int i; + + if (__copy_from_user(buf, from, ELF_NVSRHALFREG * sizeof(double))) + return 1; + for (i = 0; i < ELF_NVSRHALFREG ; i++) + task->thread.fp_state.fpr[i][TS_VSRLOWOFFSET] = buf[i]; + return 0; +} + +#ifdef CONFIG_PPC_TRANSACTIONAL_MEM +unsigned long copy_ckfpr_to_user(void __user *to, + struct task_struct *task) +{ + u64 buf[ELF_NFPREG]; + int i; + + /* save FPR copy to local buffer then write to the thread_struct */ + for (i = 0; i < (ELF_NFPREG - 1) ; i++) + buf[i] = task->thread.TS_CKFPR(i); + buf[i] = task->thread.ckfp_state.fpscr; + return __copy_to_user(to, buf, ELF_NFPREG * sizeof(double)); +} + +unsigned long copy_ckfpr_from_user(struct task_struct *task, + void __user *from) +{ + u64 buf[ELF_NFPREG]; + int i; + + if (__copy_from_user(buf, from, ELF_NFPREG * sizeof(double))) + return 1; + for (i = 0; i < (ELF_NFPREG - 1) ; i++) + task->thread.TS_CKFPR(i) = buf[i]; + task->thread.ckfp_state.fpscr = buf[i]; + + return 0; +} + +unsigned long copy_ckvsx_to_user(void __user *to, + struct task_struct *task) +{ + u64 buf[ELF_NVSRHALFREG]; + int i; + + /* save FPR copy to local buffer then write to the thread_struct */ + for (i = 0; i < ELF_NVSRHALFREG; i++) + buf[i] = task->thread.ckfp_state.fpr[i][TS_VSRLOWOFFSET]; + return __copy_to_user(to, buf, ELF_NVSRHALFREG * sizeof(double)); +} + +unsigned long copy_ckvsx_from_user(struct task_struct *task, + void __user *from) +{ + u64 buf[ELF_NVSRHALFREG]; + int i; + + if (__copy_from_user(buf, from, ELF_NVSRHALFREG * sizeof(double))) + return 1; + for (i = 0; i < ELF_NVSRHALFREG ; i++) + task->thread.ckfp_state.fpr[i][TS_VSRLOWOFFSET] = buf[i]; + return 0; +} +#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */ +#else +inline unsigned long copy_fpr_to_user(void __user *to, + struct task_struct *task) +{ + return __copy_to_user(to, task->thread.fp_state.fpr, + ELF_NFPREG * sizeof(double)); +} + +inline unsigned long copy_fpr_from_user(struct task_struct *task, + void __user *from) +{ + return __copy_from_user(task->thread.fp_state.fpr, from, + ELF_NFPREG * sizeof(double)); +} + +#ifdef CONFIG_PPC_TRANSACTIONAL_MEM +inline unsigned long copy_ckfpr_to_user(void __user *to, +struct task_struct *task) +{ + return __copy_to_user(to, task->thread.ckf
Re: [PATCH v6 3/6] powerpc/perf: consolidate read_user_stack_32
Le 30/08/2019 à 20:57, Michal Suchanek a écrit : There are two almost identical copies for 32bit and 64bit. The function is used only in 32bit code which will be split out in next patch so consolidate to one function. Signed-off-by: Michal Suchanek Reviewed-by: christophe.le...@c-s.fr --- new patch in v6 --- arch/powerpc/perf/callchain.c | 25 + 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/arch/powerpc/perf/callchain.c b/arch/powerpc/perf/callchain.c index c84bbd4298a0..b7cdcce20280 100644 --- a/arch/powerpc/perf/callchain.c +++ b/arch/powerpc/perf/callchain.c @@ -165,22 +165,6 @@ static int read_user_stack_64(unsigned long __user *ptr, unsigned long *ret) return read_user_stack_slow(ptr, ret, 8); } -static int read_user_stack_32(unsigned int __user *ptr, unsigned int *ret) -{ - if ((unsigned long)ptr > TASK_SIZE - sizeof(unsigned int) || - ((unsigned long)ptr & 3)) - return -EFAULT; - - pagefault_disable(); - if (!__get_user_inatomic(*ret, ptr)) { - pagefault_enable(); - return 0; - } - pagefault_enable(); - - return read_user_stack_slow(ptr, ret, 4); -} - static inline int valid_user_sp(unsigned long sp, int is_64) { if (!sp || (sp & 7) || sp > (is_64 ? TASK_SIZE : 0x1UL) - 32) @@ -295,6 +279,12 @@ static inline int current_is_64bit(void) } #else /* CONFIG_PPC64 */ +static int read_user_stack_slow(void __user *ptr, void *buf, int nb) +{ + return 0; +} +#endif /* CONFIG_PPC64 */ + /* * On 32-bit we just access the address and let hash_page create a * HPTE if necessary, so there is no need to fall back to reading @@ -313,9 +303,12 @@ static int read_user_stack_32(unsigned int __user *ptr, unsigned int *ret) rc = __get_user_inatomic(*ret, ptr); pagefault_enable(); + if (IS_ENABLED(CONFIG_PPC64) && rc) + return read_user_stack_slow(ptr, ret, 4); return rc; } +#ifndef CONFIG_PPC64 static inline void perf_callchain_user_64(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs) {
Re: [PATCH v6 4/6] powerpc/64: make buildable without CONFIG_COMPAT
Le 30/08/2019 à 20:57, Michal Suchanek a écrit : There are numerous references to 32bit functions in generic and 64bit code so ifdef them out. Signed-off-by: Michal Suchanek --- v2: - fix 32bit ifdef condition in signal.c - simplify the compat ifdef condition in vdso.c - 64bit is redundant - simplify the compat ifdef condition in callchain.c - 64bit is redundant v3: - use IS_ENABLED and maybe_unused where possible - do not ifdef declarations - clean up Makefile v4: - further makefile cleanup - simplify is_32bit_task conditions - avoid ifdef in condition by using return v5: - avoid unreachable code on 32bit - make is_current_64bit constant on !COMPAT - add stub perf_callchain_user_32 to avoid some ifdefs v6: - consolidate current_is_64bit --- arch/powerpc/include/asm/thread_info.h | 4 +-- arch/powerpc/kernel/Makefile | 7 +++-- arch/powerpc/kernel/entry_64.S | 2 ++ arch/powerpc/kernel/signal.c | 3 +-- arch/powerpc/kernel/syscall_64.c | 6 ++--- arch/powerpc/kernel/vdso.c | 5 ++-- arch/powerpc/perf/callchain.c | 37 +++--- 7 files changed, 33 insertions(+), 31 deletions(-) [...] diff --git a/arch/powerpc/perf/callchain.c b/arch/powerpc/perf/callchain.c index b7cdcce20280..788ad2c63f18 100644 --- a/arch/powerpc/perf/callchain.c +++ b/arch/powerpc/perf/callchain.c @@ -15,7 +15,7 @@ #include #include #include -#ifdef CONFIG_PPC64 +#ifdef CONFIG_COMPAT #include "../kernel/ppc32.h" #endif #include @@ -268,16 +268,6 @@ static void perf_callchain_user_64(struct perf_callchain_entry_ctx *entry, } } -static inline int current_is_64bit(void) -{ - /* -* We can't use test_thread_flag() here because we may be on an -* interrupt stack, and the thread flags don't get copied over -* from the thread_info on the main stack to the interrupt stack. -*/ - return !test_ti_thread_flag(task_thread_info(current), TIF_32BIT); -} - #else /* CONFIG_PPC64 */ static int read_user_stack_slow(void __user *ptr, void *buf, int nb) { @@ -314,11 +304,6 @@ static inline void perf_callchain_user_64(struct perf_callchain_entry_ctx *entry { } -static inline int current_is_64bit(void) -{ - return 0; -} - static inline int valid_user_sp(unsigned long sp, int is_64) { if (!sp || (sp & 7) || sp > TASK_SIZE - 32) @@ -334,6 +319,7 @@ static inline int valid_user_sp(unsigned long sp, int is_64) #endif /* CONFIG_PPC64 */ +#if defined(CONFIG_PPC32) || defined(CONFIG_COMPAT) /* * Layout for non-RT signal frames */ @@ -475,6 +461,25 @@ static void perf_callchain_user_32(struct perf_callchain_entry_ctx *entry, sp = next_sp; } } +#else /* 32bit */ +static void perf_callchain_user_32(struct perf_callchain_entry_ctx *entry, + struct pt_regs *regs) +{ + (void)&read_user_stack_32; /* unused if !COMPAT */ You don't need that anymore do you ? Christophe +} +#endif /* 32bit */ + +static inline int current_is_64bit(void) +{ + if (!IS_ENABLED(CONFIG_COMPAT)) + return IS_ENABLED(CONFIG_PPC64); + /* +* We can't use test_thread_flag() here because we may be on an +* interrupt stack, and the thread flags don't get copied over +* from the thread_info on the main stack to the interrupt stack. +*/ + return !test_ti_thread_flag(task_thread_info(current), TIF_32BIT); +} void perf_callchain_user(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs)
Re: [PATCH 1/2] ftrace: Fix NULL pointer dereference in t_probe_next()
On Thu, 4 Jul 2019 20:04:41 +0530 "Naveen N. Rao" wrote: > LTP testsuite on powerpc results in the below crash: > > Unable to handle kernel paging request for data at address 0x > Faulting instruction address: 0xc029d800 > Oops: Kernel access of bad area, sig: 11 [#1] > LE SMP NR_CPUS=2048 NUMA PowerNV > ... > CPU: 68 PID: 96584 Comm: cat Kdump: loaded Tainted: GW > NIP: c029d800 LR: c029dac4 CTR: c01e6ad0 > REGS: c0002017fae8ba10 TRAP: 0300 Tainted: GW > MSR: 90009033 CR: 28022422 XER: > 2004 > CFAR: c029d90c DAR: DSISR: 4000 IRQMASK: 0 > ... > NIP [c029d800] t_probe_next+0x60/0x180 > LR [c029dac4] t_mod_start+0x1a4/0x1f0 > Call Trace: > [c0002017fae8bc90] [c0cdbc40] _cond_resched+0x10/0xb0 (unreliable) > [c0002017fae8bce0] [c02a15b0] t_start+0xf0/0x1c0 > [c0002017fae8bd30] [c04ec2b4] seq_read+0x184/0x640 > [c0002017fae8bdd0] [c04a57bc] sys_read+0x10c/0x300 > [c0002017fae8be30] [c000b388] system_call+0x5c/0x70 > > The test (ftrace_set_ftrace_filter.sh) is part of ftrace stress tests > and the crash happens when the test does 'cat > $TRACING_PATH/set_ftrace_filter'. > > The address points to the second line below, in t_probe_next(), where > filter_hash is dereferenced: > hash = iter->probe->ops.func_hash->filter_hash; > size = 1 << hash->size_bits; > > This happens due to a race with register_ftrace_function_probe(). A new > ftrace_func_probe is created and added into the func_probes list in > trace_array under ftrace_lock. However, before initializing the filter, > we drop ftrace_lock, and re-acquire it after acquiring regex_lock. If > another process is trying to read set_ftrace_filter, it will be able to > acquire ftrace_lock during this window and it will end up seeing a NULL > filter_hash. > > Fix this by just checking for a NULL filter_hash in t_probe_next(). If > the filter_hash is NULL, then this probe is just being added and we can > simply return from here. Hmm, this is very subtle. I'll take a deeper look at this to see if we can keep the race from happening. Thanks! -- Steve > > Signed-off-by: Naveen N. Rao > --- > kernel/trace/ftrace.c | 4 > 1 file changed, 4 insertions(+) > > diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c > index 7b037295a1f1..0791eafb693d 100644 > --- a/kernel/trace/ftrace.c > +++ b/kernel/trace/ftrace.c > @@ -3093,6 +3093,10 @@ t_probe_next(struct seq_file *m, loff_t *pos) > hnd = &iter->probe_entry->hlist; > > hash = iter->probe->ops.func_hash->filter_hash; > + > + if (!hash) > + return NULL; > + > size = 1 << hash->size_bits; > > retry:
Re: [PATCH 0/2] ftrace: two fixes with func_probes handling
On Thu, 08 Aug 2019 20:45:04 +0530 "Naveen N. Rao" wrote: > Naveen N. Rao wrote: > > Two patches addressing bugs in ftrace function probe handling. The first > > patch addresses a NULL pointer dereference reported by LTP tests, while > > the second one is a trivial patch to address a missing check for return > > value, found by code inspection. > > Steven, > Can you please take a look at these patches? > Sorry for the late reply, I've been traveling a lot lately. I'm looking at these now. I'm trying to see how they triggered a bug. -- Steve
Re: [PATCH] Revert "asm-generic: Remove unneeded __ARCH_WANT_SYS_LLSEEK macro"
On Fri, 30 Aug 2019 21:54:43 +0200 Arnd Bergmann wrote: > On Fri, Aug 30, 2019 at 9:46 PM Michal Suchanek wrote: > > > > This reverts commit caf6f9c8a326cffd1d4b3ff3f1cfba75d159d70b. > > > > Maybe it was needed after all. > > > > When CONFIG_COMPAT is disabled on ppc64 the kernel does not build. > > > > There is resistance to both removing the llseek syscall from the 64bit > > syscall tables and building the llseek interface unconditionally. > > > > Link: https://lore.kernel.org/lkml/20190828151552.ga16...@infradead.org/ > > Link: https://lore.kernel.org/lkml/20190829214319.498c7de2@naga/ > > > > Signed-off-by: Michal Suchanek > > This seems like the right idea in principle. > > > index 5bbf587f5bc1..2f3c4bb138c4 100644 > > --- a/fs/read_write.c > > +++ b/fs/read_write.c > > @@ -331,7 +331,7 @@ COMPAT_SYSCALL_DEFINE3(lseek, unsigned int, fd, > > compat_off_t, offset, unsigned i > > } > > #endif > > > > -#if !defined(CONFIG_64BIT) || defined(CONFIG_COMPAT) > > +#ifdef __ARCH_WANT_SYS_LLSEEK > > SYSCALL_DEFINE5(llseek, unsigned int, fd, unsigned long, offset_high, > > unsigned long, offset_low, loff_t __user *, result, > > unsigned int, whence) > > However, only reverting the patch will now break all newly added > 32-bit architectures that don't define __ARCH_WANT_SYS_LLSEEK: > at least nds32 and riscv32 come to mind, not sure if there is another. AFAICT nds32 never had the syscall. Its headers were added without __ARCH_WANT_SYS_LLSEEK before the define was removed. The new architecture csky should be handled. > > I think the easiest way however would be to combine the two checks > above and make it > > #if !defined(CONFIG_64BIT) || defined(CONFIG_COMPAT) || > defined(__ARCH_WANT_SYS_LLSEEK) > > and then only set __ARCH_WANT_SYS_LLSEEK for powerpc. Yes, that limits the use of __ARCH_WANT_SYS_LLSEEK, does not require resurrecting the old headers, and may fix some architectures like nds32 that forgot to add it. Thanks Michal
Re: [PATCH v2 4/4] powerpc/64: system call implement the bulk of the logic in C
On Sat, 31 Aug 2019 02:48:26 +0800 kbuild test robot wrote: > Hi Nicholas, > > I love your patch! Yet something to improve: > > [auto build test ERROR on linus/master] > [cannot apply to v5.3-rc6 next-20190830] > [if your patch is applied to the wrong git tree, please drop us a note to > help improve the system] > > url: > https://github.com/0day-ci/linux/commits/Nicholas-Piggin/powerpc-64-syscalls-in-C/20190828-064221 > config: powerpc64-defconfig (attached as .config) > compiler: powerpc64-linux-gcc (GCC) 7.4.0 > reproduce: > wget > https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O > ~/bin/make.cross > chmod +x ~/bin/make.cross > # save the attached .config to linux build tree > GCC_VERSION=7.4.0 make.cross ARCH=powerpc64 > > If you fix the issue, kindly add following tag > Reported-by: kbuild test robot > > All errors (new ones prefixed by >>): > >powerpc64-linux-ld: warning: orphan section `.gnu.hash' from `linker > stubs' being placed in section `.gnu.hash'. >arch/powerpc/kernel/syscall_64.o: In function `.system_call_exception': > >> syscall_64.c:(.text+0x180): undefined reference to `.tabort_syscall' Interestingly it builds and boots for me. Is this something about dotted vs dotless symbols depending on some config options? I see there is _GLOBAL(ret_from_fork) just below so maybe we need _GLOBAL(tabort_syscall) instead of .globl tabort_syscall as well. Thanks Michal
Re: [PATCH] Revert "asm-generic: Remove unneeded __ARCH_WANT_SYS_LLSEEK macro"
On Fri, Aug 30, 2019 at 9:46 PM Michal Suchanek wrote: > > This reverts commit caf6f9c8a326cffd1d4b3ff3f1cfba75d159d70b. > > Maybe it was needed after all. > > When CONFIG_COMPAT is disabled on ppc64 the kernel does not build. > > There is resistance to both removing the llseek syscall from the 64bit > syscall tables and building the llseek interface unconditionally. > > Link: https://lore.kernel.org/lkml/20190828151552.ga16...@infradead.org/ > Link: https://lore.kernel.org/lkml/20190829214319.498c7de2@naga/ > > Signed-off-by: Michal Suchanek This seems like the right idea in principle. > index 5bbf587f5bc1..2f3c4bb138c4 100644 > --- a/fs/read_write.c > +++ b/fs/read_write.c > @@ -331,7 +331,7 @@ COMPAT_SYSCALL_DEFINE3(lseek, unsigned int, fd, > compat_off_t, offset, unsigned i > } > #endif > > -#if !defined(CONFIG_64BIT) || defined(CONFIG_COMPAT) > +#ifdef __ARCH_WANT_SYS_LLSEEK > SYSCALL_DEFINE5(llseek, unsigned int, fd, unsigned long, offset_high, > unsigned long, offset_low, loff_t __user *, result, > unsigned int, whence) However, only reverting the patch will now break all newly added 32-bit architectures that don't define __ARCH_WANT_SYS_LLSEEK: at least nds32 and riscv32 come to mind, not sure if there is another. I think the easiest way however would be to combine the two checks above and make it #if !defined(CONFIG_64BIT) || defined(CONFIG_COMPAT) || defined(__ARCH_WANT_SYS_LLSEEK) and then only set __ARCH_WANT_SYS_LLSEEK for powerpc. Arnd
[PATCH] Revert "asm-generic: Remove unneeded __ARCH_WANT_SYS_LLSEEK macro"
This reverts commit caf6f9c8a326cffd1d4b3ff3f1cfba75d159d70b. Maybe it was needed after all. When CONFIG_COMPAT is disabled on ppc64 the kernel does not build. There is resistance to both removing the llseek syscall from the 64bit syscall tables and building the llseek interface unconditionally. Link: https://lore.kernel.org/lkml/20190828151552.ga16...@infradead.org/ Link: https://lore.kernel.org/lkml/20190829214319.498c7de2@naga/ Signed-off-by: Michal Suchanek --- arch/arm/include/asm/unistd.h| 1 + arch/arm64/include/asm/unistd.h | 1 + arch/csky/include/asm/unistd.h | 2 +- arch/m68k/include/asm/unistd.h | 1 + arch/microblaze/include/asm/unistd.h | 1 + arch/mips/include/asm/unistd.h | 1 + arch/parisc/include/asm/unistd.h | 1 + arch/powerpc/include/asm/unistd.h| 1 + arch/s390/include/asm/unistd.h | 1 + arch/sh/include/asm/unistd.h | 1 + arch/sparc/include/asm/unistd.h | 1 + arch/x86/include/asm/unistd.h| 1 + arch/xtensa/include/asm/unistd.h | 1 + fs/read_write.c | 2 +- include/asm-generic/unistd.h | 12 15 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 include/asm-generic/unistd.h diff --git a/arch/arm/include/asm/unistd.h b/arch/arm/include/asm/unistd.h index 3676e82cf95c..e35ec8100a21 100644 --- a/arch/arm/include/asm/unistd.h +++ b/arch/arm/include/asm/unistd.h @@ -18,6 +18,7 @@ #define __ARCH_WANT_SYS_GETHOSTNAME #define __ARCH_WANT_SYS_PAUSE #define __ARCH_WANT_SYS_GETPGRP +#define __ARCH_WANT_SYS_LLSEEK #define __ARCH_WANT_SYS_NICE #define __ARCH_WANT_SYS_SIGPENDING #define __ARCH_WANT_SYS_SIGPROCMASK diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h index 2629a68b8724..2c9d8d91e347 100644 --- a/arch/arm64/include/asm/unistd.h +++ b/arch/arm64/include/asm/unistd.h @@ -7,6 +7,7 @@ #define __ARCH_WANT_SYS_GETHOSTNAME #define __ARCH_WANT_SYS_PAUSE #define __ARCH_WANT_SYS_GETPGRP +#define __ARCH_WANT_SYS_LLSEEK #define __ARCH_WANT_SYS_NICE #define __ARCH_WANT_SYS_SIGPENDING #define __ARCH_WANT_SYS_SIGPROCMASK diff --git a/arch/csky/include/asm/unistd.h b/arch/csky/include/asm/unistd.h index da7a18295615..bee8ba8309e7 100644 --- a/arch/csky/include/asm/unistd.h +++ b/arch/csky/include/asm/unistd.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ // Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. -#include +#include #define NR_syscalls (__NR_syscalls) diff --git a/arch/m68k/include/asm/unistd.h b/arch/m68k/include/asm/unistd.h index 2e0047cf86f8..54c04eb4495a 100644 --- a/arch/m68k/include/asm/unistd.h +++ b/arch/m68k/include/asm/unistd.h @@ -21,6 +21,7 @@ #define __ARCH_WANT_SYS_SOCKETCALL #define __ARCH_WANT_SYS_FADVISE64 #define __ARCH_WANT_SYS_GETPGRP +#define __ARCH_WANT_SYS_LLSEEK #define __ARCH_WANT_SYS_NICE #define __ARCH_WANT_SYS_OLD_GETRLIMIT #define __ARCH_WANT_SYS_OLD_MMAP diff --git a/arch/microblaze/include/asm/unistd.h b/arch/microblaze/include/asm/unistd.h index d79d35ac6253..c5fcbce1f997 100644 --- a/arch/microblaze/include/asm/unistd.h +++ b/arch/microblaze/include/asm/unistd.h @@ -27,6 +27,7 @@ #define __ARCH_WANT_SYS_SOCKETCALL #define __ARCH_WANT_SYS_FADVISE64 #define __ARCH_WANT_SYS_GETPGRP +#define __ARCH_WANT_SYS_LLSEEK #define __ARCH_WANT_SYS_NICE /* #define __ARCH_WANT_SYS_OLD_GETRLIMIT */ #define __ARCH_WANT_SYS_OLDUMOUNT diff --git a/arch/mips/include/asm/unistd.h b/arch/mips/include/asm/unistd.h index 071053ece677..8e8c7cab95ca 100644 --- a/arch/mips/include/asm/unistd.h +++ b/arch/mips/include/asm/unistd.h @@ -38,6 +38,7 @@ #define __ARCH_WANT_SYS_WAITPID #define __ARCH_WANT_SYS_SOCKETCALL #define __ARCH_WANT_SYS_GETPGRP +#define __ARCH_WANT_SYS_LLSEEK #define __ARCH_WANT_SYS_NICE #define __ARCH_WANT_SYS_OLD_UNAME #define __ARCH_WANT_SYS_OLDUMOUNT diff --git a/arch/parisc/include/asm/unistd.h b/arch/parisc/include/asm/unistd.h index cd438e4150f6..29bd46381f2e 100644 --- a/arch/parisc/include/asm/unistd.h +++ b/arch/parisc/include/asm/unistd.h @@ -159,6 +159,7 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \ #define __ARCH_WANT_SYS_SOCKETCALL #define __ARCH_WANT_SYS_FADVISE64 #define __ARCH_WANT_SYS_GETPGRP +#define __ARCH_WANT_SYS_LLSEEK #define __ARCH_WANT_SYS_NICE #define __ARCH_WANT_SYS_OLDUMOUNT #define __ARCH_WANT_SYS_SIGPENDING diff --git a/arch/powerpc/include/asm/unistd.h b/arch/powerpc/include/asm/unistd.h index b0720c7c3fcf..700fcdac2e3c 100644 --- a/arch/powerpc/include/asm/unistd.h +++ b/arch/powerpc/include/asm/unistd.h @@ -31,6 +31,7 @@ #define __ARCH_WANT_SYS_SOCKETCALL #define __ARCH_WANT_SYS_FADVISE64 #define __ARCH_WANT_SYS_GETPGRP +#define __ARCH_WANT_SYS_LLSEEK #define __ARCH_WANT_SYS_NICE #define __ARCH_WANT_SYS_OLD_GETRLIMIT #define __ARCH_WANT_SYS_OLD_UNAME diff --git a/arch/s390/include/asm/unistd.h b/arch/s390/include/asm/unistd.h index 9e9f75ef046a..52e9e2fe37
Re: [PATCH v6 6/6] powerpc/perf: split callchain.c by bitness
On Fri, 30 Aug 2019 20:57:57 +0200 Michal Suchanek wrote: > Building callchain.c with !COMPAT proved quite ugly with all the > defines. Splitting out the 32bit and 64bit parts looks better. > BTW the powerpc callchain.c does not match any of the patterns of PERF CORE in MAINTAINERS (unlike callchain implementation on other platforms). Is that intentional? Thanks Michal
[PATCH v6 6/6] powerpc/perf: split callchain.c by bitness
Building callchain.c with !COMPAT proved quite ugly with all the defines. Splitting out the 32bit and 64bit parts looks better. No code change intended. Signed-off-by: Michal Suchanek --- v6: - move current_is_64bit consolidetaion to earlier patch - move defines to the top of callchain_32.c - Makefile cleanup --- arch/powerpc/perf/Makefile | 5 +- arch/powerpc/perf/callchain.c| 371 +-- arch/powerpc/perf/callchain.h| 11 + arch/powerpc/perf/callchain_32.c | 204 + arch/powerpc/perf/callchain_64.c | 185 +++ 5 files changed, 405 insertions(+), 371 deletions(-) create mode 100644 arch/powerpc/perf/callchain.h create mode 100644 arch/powerpc/perf/callchain_32.c create mode 100644 arch/powerpc/perf/callchain_64.c diff --git a/arch/powerpc/perf/Makefile b/arch/powerpc/perf/Makefile index c155dcbb8691..53d614e98537 100644 --- a/arch/powerpc/perf/Makefile +++ b/arch/powerpc/perf/Makefile @@ -1,6 +1,9 @@ # SPDX-License-Identifier: GPL-2.0 -obj-$(CONFIG_PERF_EVENTS) += callchain.o perf_regs.o +obj-$(CONFIG_PERF_EVENTS) += callchain.o callchain_$(BITS).o perf_regs.o +ifdef CONFIG_COMPAT +obj-$(CONFIG_PERF_EVENTS) += callchain_32.o +endif obj-$(CONFIG_PPC_PERF_CTRS)+= core-book3s.o bhrb.o obj64-$(CONFIG_PPC_PERF_CTRS) += ppc970-pmu.o power5-pmu.o \ diff --git a/arch/powerpc/perf/callchain.c b/arch/powerpc/perf/callchain.c index 788ad2c63f18..8f30f1b47c78 100644 --- a/arch/powerpc/perf/callchain.c +++ b/arch/powerpc/perf/callchain.c @@ -15,11 +15,9 @@ #include #include #include -#ifdef CONFIG_COMPAT -#include "../kernel/ppc32.h" -#endif #include +#include "callchain.h" /* * Is sp valid as the address of the next kernel stack frame after prev_sp? @@ -102,373 +100,6 @@ perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, struct pt_regs *re } } -#ifdef CONFIG_PPC64 -/* - * On 64-bit we don't want to invoke hash_page on user addresses from - * interrupt context, so if the access faults, we read the page tables - * to find which page (if any) is mapped and access it directly. - */ -static int read_user_stack_slow(void __user *ptr, void *buf, int nb) -{ - int ret = -EFAULT; - pgd_t *pgdir; - pte_t *ptep, pte; - unsigned shift; - unsigned long addr = (unsigned long) ptr; - unsigned long offset; - unsigned long pfn, flags; - void *kaddr; - - pgdir = current->mm->pgd; - if (!pgdir) - return -EFAULT; - - local_irq_save(flags); - ptep = find_current_mm_pte(pgdir, addr, NULL, &shift); - if (!ptep) - goto err_out; - if (!shift) - shift = PAGE_SHIFT; - - /* align address to page boundary */ - offset = addr & ((1UL << shift) - 1); - - pte = READ_ONCE(*ptep); - if (!pte_present(pte) || !pte_user(pte)) - goto err_out; - pfn = pte_pfn(pte); - if (!page_is_ram(pfn)) - goto err_out; - - /* no highmem to worry about here */ - kaddr = pfn_to_kaddr(pfn); - memcpy(buf, kaddr + offset, nb); - ret = 0; -err_out: - local_irq_restore(flags); - return ret; -} - -static int read_user_stack_64(unsigned long __user *ptr, unsigned long *ret) -{ - if ((unsigned long)ptr > TASK_SIZE - sizeof(unsigned long) || - ((unsigned long)ptr & 7)) - return -EFAULT; - - pagefault_disable(); - if (!__get_user_inatomic(*ret, ptr)) { - pagefault_enable(); - return 0; - } - pagefault_enable(); - - return read_user_stack_slow(ptr, ret, 8); -} - -static inline int valid_user_sp(unsigned long sp, int is_64) -{ - if (!sp || (sp & 7) || sp > (is_64 ? TASK_SIZE : 0x1UL) - 32) - return 0; - return 1; -} - -/* - * 64-bit user processes use the same stack frame for RT and non-RT signals. - */ -struct signal_frame_64 { - chardummy[__SIGNAL_FRAMESIZE]; - struct ucontext uc; - unsigned long unused[2]; - unsigned inttramp[6]; - struct siginfo *pinfo; - void*puc; - struct siginfo info; - charabigap[288]; -}; - -static int is_sigreturn_64_address(unsigned long nip, unsigned long fp) -{ - if (nip == fp + offsetof(struct signal_frame_64, tramp)) - return 1; - if (vdso64_rt_sigtramp && current->mm->context.vdso_base && - nip == current->mm->context.vdso_base + vdso64_rt_sigtramp) - return 1; - return 0; -} - -/* - * Do some sanity checking on the signal frame pointed to by sp. - * We check the pinfo and puc pointers in the frame. - */ -static int sane_signal_64_frame(unsigned long sp) -{ - struct signal_frame_64 __user *sf; - unsigned long pinfo, puc; - - sf = (struct signal_frame_64 __user *) sp; - if (read_user_stack_64((unsigned
[PATCH v6 5/6] powerpc/64: Make COMPAT user-selectable disabled on littleendian by default.
On bigendian ppc64 it is common to have 32bit legacy binaries but much less so on littleendian. Signed-off-by: Michal Suchanek --- v3: make configurable --- arch/powerpc/Kconfig | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 5bab0bb6b833..b0339e892329 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -264,8 +264,9 @@ config PANIC_TIMEOUT default 180 config COMPAT - bool - default y if PPC64 + bool "Enable support for 32bit binaries" + depends on PPC64 + default y if !CPU_LITTLE_ENDIAN select COMPAT_BINFMT_ELF select ARCH_WANT_OLD_COMPAT_IPC select COMPAT_OLD_SIGACTION -- 2.22.0
[PATCH v6 4/6] powerpc/64: make buildable without CONFIG_COMPAT
There are numerous references to 32bit functions in generic and 64bit code so ifdef them out. Signed-off-by: Michal Suchanek --- v2: - fix 32bit ifdef condition in signal.c - simplify the compat ifdef condition in vdso.c - 64bit is redundant - simplify the compat ifdef condition in callchain.c - 64bit is redundant v3: - use IS_ENABLED and maybe_unused where possible - do not ifdef declarations - clean up Makefile v4: - further makefile cleanup - simplify is_32bit_task conditions - avoid ifdef in condition by using return v5: - avoid unreachable code on 32bit - make is_current_64bit constant on !COMPAT - add stub perf_callchain_user_32 to avoid some ifdefs v6: - consolidate current_is_64bit --- arch/powerpc/include/asm/thread_info.h | 4 +-- arch/powerpc/kernel/Makefile | 7 +++-- arch/powerpc/kernel/entry_64.S | 2 ++ arch/powerpc/kernel/signal.c | 3 +-- arch/powerpc/kernel/syscall_64.c | 6 ++--- arch/powerpc/kernel/vdso.c | 5 ++-- arch/powerpc/perf/callchain.c | 37 +++--- 7 files changed, 33 insertions(+), 31 deletions(-) diff --git a/arch/powerpc/include/asm/thread_info.h b/arch/powerpc/include/asm/thread_info.h index 8e1d0195ac36..c128d8a48ea3 100644 --- a/arch/powerpc/include/asm/thread_info.h +++ b/arch/powerpc/include/asm/thread_info.h @@ -144,10 +144,10 @@ static inline bool test_thread_local_flags(unsigned int flags) return (ti->local_flags & flags) != 0; } -#ifdef CONFIG_PPC64 +#ifdef CONFIG_COMPAT #define is_32bit_task()(test_thread_flag(TIF_32BIT)) #else -#define is_32bit_task()(1) +#define is_32bit_task()(IS_ENABLED(CONFIG_PPC32)) #endif #if defined(CONFIG_PPC64) diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 1d646a94d96c..9d8772e863b9 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile @@ -44,16 +44,15 @@ CFLAGS_btext.o += -DDISABLE_BRANCH_PROFILING endif obj-y := cputable.o ptrace.o syscalls.o \ - irq.o align.o signal_32.o pmc.o vdso.o \ + irq.o align.o signal_$(BITS).o pmc.o vdso.o \ process.o systbl.o idle.o \ signal.o sysfs.o cacheinfo.o time.o \ prom.o traps.o setup-common.o \ udbg.o misc.o io.o misc_$(BITS).o \ of_platform.o prom_parse.o -obj-$(CONFIG_PPC64)+= setup_64.o sys_ppc32.o \ - signal_64.o ptrace32.o \ - paca.o nvram_64.o firmware.o \ +obj-$(CONFIG_PPC64)+= setup_64.o paca.o nvram_64.o firmware.o \ syscall_64.o +obj-$(CONFIG_COMPAT) += sys_ppc32.o ptrace32.o signal_32.o obj-$(CONFIG_VDSO32) += vdso32/ obj-$(CONFIG_PPC_WATCHDOG) += watchdog.o obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 2ec825a85f5b..a2dbf216f607 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -51,8 +51,10 @@ SYS_CALL_TABLE: .tc sys_call_table[TC],sys_call_table +#ifdef CONFIG_COMPAT COMPAT_SYS_CALL_TABLE: .tc compat_sys_call_table[TC],compat_sys_call_table +#endif /* This value is used to mark exception frames on the stack. */ exception_marker: diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c index 60436432399f..61678cb0e6a1 100644 --- a/arch/powerpc/kernel/signal.c +++ b/arch/powerpc/kernel/signal.c @@ -247,7 +247,6 @@ static void do_signal(struct task_struct *tsk) sigset_t *oldset = sigmask_to_save(); struct ksignal ksig = { .sig = 0 }; int ret; - int is32 = is_32bit_task(); BUG_ON(tsk != current); @@ -277,7 +276,7 @@ static void do_signal(struct task_struct *tsk) rseq_signal_deliver(&ksig, tsk->thread.regs); - if (is32) { + if (is_32bit_task()) { if (ksig.ka.sa.sa_flags & SA_SIGINFO) ret = handle_rt_signal32(&ksig, oldset, tsk); else diff --git a/arch/powerpc/kernel/syscall_64.c b/arch/powerpc/kernel/syscall_64.c index 98ed970796d5..0d5cbbe54cf1 100644 --- a/arch/powerpc/kernel/syscall_64.c +++ b/arch/powerpc/kernel/syscall_64.c @@ -38,7 +38,6 @@ typedef long (*syscall_fn)(long, long, long, long, long, long); long system_call_exception(long r3, long r4, long r5, long r6, long r7, long r8, unsigned long r0, struct pt_regs *regs) { - unsigned long ti_flags; syscall_fn f; BUG_ON(!(regs->msr & MSR_PR)); @@ -83,8 +82,7 @@ long system_call_exception(long r3, long r4, long r5, long r6, long r7, long r8, */ regs->softe = IRQS_ENABLED; - ti_flags = current_thread_info
[PATCH v6 3/6] powerpc/perf: consolidate read_user_stack_32
There are two almost identical copies for 32bit and 64bit. The function is used only in 32bit code which will be split out in next patch so consolidate to one function. Signed-off-by: Michal Suchanek --- new patch in v6 --- arch/powerpc/perf/callchain.c | 25 + 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/arch/powerpc/perf/callchain.c b/arch/powerpc/perf/callchain.c index c84bbd4298a0..b7cdcce20280 100644 --- a/arch/powerpc/perf/callchain.c +++ b/arch/powerpc/perf/callchain.c @@ -165,22 +165,6 @@ static int read_user_stack_64(unsigned long __user *ptr, unsigned long *ret) return read_user_stack_slow(ptr, ret, 8); } -static int read_user_stack_32(unsigned int __user *ptr, unsigned int *ret) -{ - if ((unsigned long)ptr > TASK_SIZE - sizeof(unsigned int) || - ((unsigned long)ptr & 3)) - return -EFAULT; - - pagefault_disable(); - if (!__get_user_inatomic(*ret, ptr)) { - pagefault_enable(); - return 0; - } - pagefault_enable(); - - return read_user_stack_slow(ptr, ret, 4); -} - static inline int valid_user_sp(unsigned long sp, int is_64) { if (!sp || (sp & 7) || sp > (is_64 ? TASK_SIZE : 0x1UL) - 32) @@ -295,6 +279,12 @@ static inline int current_is_64bit(void) } #else /* CONFIG_PPC64 */ +static int read_user_stack_slow(void __user *ptr, void *buf, int nb) +{ + return 0; +} +#endif /* CONFIG_PPC64 */ + /* * On 32-bit we just access the address and let hash_page create a * HPTE if necessary, so there is no need to fall back to reading @@ -313,9 +303,12 @@ static int read_user_stack_32(unsigned int __user *ptr, unsigned int *ret) rc = __get_user_inatomic(*ret, ptr); pagefault_enable(); + if (IS_ENABLED(CONFIG_PPC64) && rc) + return read_user_stack_slow(ptr, ret, 4); return rc; } +#ifndef CONFIG_PPC64 static inline void perf_callchain_user_64(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs) { -- 2.22.0
[PATCH v6 2/6] powerpc: move common register copy functions from signal_32.c to signal.c
These functions are required for 64bit as well. Signed-off-by: Michal Suchanek --- arch/powerpc/kernel/signal.c| 141 arch/powerpc/kernel/signal_32.c | 140 --- 2 files changed, 141 insertions(+), 140 deletions(-) diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c index e6c30cee6abf..60436432399f 100644 --- a/arch/powerpc/kernel/signal.c +++ b/arch/powerpc/kernel/signal.c @@ -18,12 +18,153 @@ #include #include #include +#include #include #include #include #include "signal.h" +#ifdef CONFIG_VSX +unsigned long copy_fpr_to_user(void __user *to, + struct task_struct *task) +{ + u64 buf[ELF_NFPREG]; + int i; + + /* save FPR copy to local buffer then write to the thread_struct */ + for (i = 0; i < (ELF_NFPREG - 1) ; i++) + buf[i] = task->thread.TS_FPR(i); + buf[i] = task->thread.fp_state.fpscr; + return __copy_to_user(to, buf, ELF_NFPREG * sizeof(double)); +} + +unsigned long copy_fpr_from_user(struct task_struct *task, +void __user *from) +{ + u64 buf[ELF_NFPREG]; + int i; + + if (__copy_from_user(buf, from, ELF_NFPREG * sizeof(double))) + return 1; + for (i = 0; i < (ELF_NFPREG - 1) ; i++) + task->thread.TS_FPR(i) = buf[i]; + task->thread.fp_state.fpscr = buf[i]; + + return 0; +} + +unsigned long copy_vsx_to_user(void __user *to, + struct task_struct *task) +{ + u64 buf[ELF_NVSRHALFREG]; + int i; + + /* save FPR copy to local buffer then write to the thread_struct */ + for (i = 0; i < ELF_NVSRHALFREG; i++) + buf[i] = task->thread.fp_state.fpr[i][TS_VSRLOWOFFSET]; + return __copy_to_user(to, buf, ELF_NVSRHALFREG * sizeof(double)); +} + +unsigned long copy_vsx_from_user(struct task_struct *task, +void __user *from) +{ + u64 buf[ELF_NVSRHALFREG]; + int i; + + if (__copy_from_user(buf, from, ELF_NVSRHALFREG * sizeof(double))) + return 1; + for (i = 0; i < ELF_NVSRHALFREG ; i++) + task->thread.fp_state.fpr[i][TS_VSRLOWOFFSET] = buf[i]; + return 0; +} + +#ifdef CONFIG_PPC_TRANSACTIONAL_MEM +unsigned long copy_ckfpr_to_user(void __user *to, + struct task_struct *task) +{ + u64 buf[ELF_NFPREG]; + int i; + + /* save FPR copy to local buffer then write to the thread_struct */ + for (i = 0; i < (ELF_NFPREG - 1) ; i++) + buf[i] = task->thread.TS_CKFPR(i); + buf[i] = task->thread.ckfp_state.fpscr; + return __copy_to_user(to, buf, ELF_NFPREG * sizeof(double)); +} + +unsigned long copy_ckfpr_from_user(struct task_struct *task, + void __user *from) +{ + u64 buf[ELF_NFPREG]; + int i; + + if (__copy_from_user(buf, from, ELF_NFPREG * sizeof(double))) + return 1; + for (i = 0; i < (ELF_NFPREG - 1) ; i++) + task->thread.TS_CKFPR(i) = buf[i]; + task->thread.ckfp_state.fpscr = buf[i]; + + return 0; +} + +unsigned long copy_ckvsx_to_user(void __user *to, + struct task_struct *task) +{ + u64 buf[ELF_NVSRHALFREG]; + int i; + + /* save FPR copy to local buffer then write to the thread_struct */ + for (i = 0; i < ELF_NVSRHALFREG; i++) + buf[i] = task->thread.ckfp_state.fpr[i][TS_VSRLOWOFFSET]; + return __copy_to_user(to, buf, ELF_NVSRHALFREG * sizeof(double)); +} + +unsigned long copy_ckvsx_from_user(struct task_struct *task, + void __user *from) +{ + u64 buf[ELF_NVSRHALFREG]; + int i; + + if (__copy_from_user(buf, from, ELF_NVSRHALFREG * sizeof(double))) + return 1; + for (i = 0; i < ELF_NVSRHALFREG ; i++) + task->thread.ckfp_state.fpr[i][TS_VSRLOWOFFSET] = buf[i]; + return 0; +} +#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */ +#else +inline unsigned long copy_fpr_to_user(void __user *to, + struct task_struct *task) +{ + return __copy_to_user(to, task->thread.fp_state.fpr, + ELF_NFPREG * sizeof(double)); +} + +inline unsigned long copy_fpr_from_user(struct task_struct *task, + void __user *from) +{ + return __copy_from_user(task->thread.fp_state.fpr, from, + ELF_NFPREG * sizeof(double)); +} + +#ifdef CONFIG_PPC_TRANSACTIONAL_MEM +inline unsigned long copy_ckfpr_to_user(void __user *to, +struct task_struct *task) +{ + return __copy_to_user(to, task->thread.ckfp_state.fpr, + ELF_NFPREG * sizeof(double)); +} + +inline unsigned long copy_ckfp
[PATCH v6 1/6] powerpc: make llseek 32bit-only.
The llseek syscall is not built in fs/read_write.c when !64bit && !COMPAT With the syscall marked as common in syscall.tbl build fails in this case. The llseek interface does not make sense on 64bit and it is explicitly described as 32bit interface. Use on 64bit is not well-defined so just drop it for 64bit. Fixes: caf6f9c8a326 ("asm-generic: Remove unneeded __ARCH_WANT_SYS_LLSEEK macro") Link: https://lore.kernel.org/lkml/20190828151552.ga16...@infradead.org/ Link: https://lore.kernel.org/lkml/20190829214319.498c7de2@naga/ Signed-off-by: Michal Suchanek --- v5: update commit message. --- arch/powerpc/kernel/syscalls/syscall.tbl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/kernel/syscalls/syscall.tbl b/arch/powerpc/kernel/syscalls/syscall.tbl index 010b9f445586..53e427606f6c 100644 --- a/arch/powerpc/kernel/syscalls/syscall.tbl +++ b/arch/powerpc/kernel/syscalls/syscall.tbl @@ -188,7 +188,7 @@ 137common afs_syscall sys_ni_syscall 138common setfsuidsys_setfsuid 139common setfsgidsys_setfsgid -140common _llseek sys_llseek +14032 _llseek sys_llseek 141common getdentssys_getdents compat_sys_getdents 142common _newselect sys_select compat_sys_select 143common flock sys_flock -- 2.22.0
[PATCH v6 0/6] Disable compat cruft on ppc64le v6
Less code means less bugs so add a knob to skip the compat stuff. This is tested on ppc64le top of https://patchwork.ozlabs.org/cover/1153556/ Changes in v2: saner CONFIG_COMPAT ifdefs Changes in v3: - change llseek to 32bit instead of builing it unconditionally in fs - clanup the makefile conditionals - remove some ifdefs or convert to IS_DEFINED where possible Changes in v4: - cleanup is_32bit_task and current_is_64bit - more makefile cleanup Changes in v5: - more current_is_64bit cleanup - split off callchain.c 32bit and 64bit parts Changes in v6: - cleanup makefile after split - consolidate read_user_stack_32 - fix some checkpatch warnings Michal Suchanek (6): powerpc: make llseek 32bit-only. powerpc: move common register copy functions from signal_32.c to signal.c powerpc/perf: consolidate read_user_stack_32 powerpc/64: make buildable without CONFIG_COMPAT powerpc/64: Make COMPAT user-selectable disabled on littleendian by default. powerpc/perf: split callchain.c by bitness arch/powerpc/Kconfig | 5 +- arch/powerpc/include/asm/thread_info.h | 4 +- arch/powerpc/kernel/Makefile | 7 +- arch/powerpc/kernel/entry_64.S | 2 + arch/powerpc/kernel/signal.c | 144 - arch/powerpc/kernel/signal_32.c | 140 - arch/powerpc/kernel/syscall_64.c | 6 +- arch/powerpc/kernel/syscalls/syscall.tbl | 2 +- arch/powerpc/kernel/vdso.c | 5 +- arch/powerpc/perf/Makefile | 5 +- arch/powerpc/perf/callchain.c| 377 +-- arch/powerpc/perf/callchain.h| 11 + arch/powerpc/perf/callchain_32.c | 204 arch/powerpc/perf/callchain_64.c | 185 +++ 14 files changed, 564 insertions(+), 533 deletions(-) create mode 100644 arch/powerpc/perf/callchain.h create mode 100644 arch/powerpc/perf/callchain_32.c create mode 100644 arch/powerpc/perf/callchain_64.c -- 2.22.0
Re: [PATCH v2 4/4] powerpc/64: system call implement the bulk of the logic in C
Hi Nicholas, I love your patch! Yet something to improve: [auto build test ERROR on linus/master] [cannot apply to v5.3-rc6 next-20190830] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] url: https://github.com/0day-ci/linux/commits/Nicholas-Piggin/powerpc-64-syscalls-in-C/20190828-064221 config: powerpc64-defconfig (attached as .config) compiler: powerpc64-linux-gcc (GCC) 7.4.0 reproduce: wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # save the attached .config to linux build tree GCC_VERSION=7.4.0 make.cross ARCH=powerpc64 If you fix the issue, kindly add following tag Reported-by: kbuild test robot All errors (new ones prefixed by >>): powerpc64-linux-ld: warning: orphan section `.gnu.hash' from `linker stubs' being placed in section `.gnu.hash'. arch/powerpc/kernel/syscall_64.o: In function `.system_call_exception': >> syscall_64.c:(.text+0x180): undefined reference to `.tabort_syscall' --- 0-DAY kernel test infrastructureOpen Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation .config.gz Description: application/gzip
Re: Oops (request_key_auth_describe) while running cve-2016-7042 from LTP
Can you try this patch instead of Hillf's? David --- commit df882ad6d4e24a3763719c1798ea58e87d56c2d7 Author: Hillf Danton Date: Fri Aug 30 15:54:33 2019 +0100 keys: Fix missing null pointer check in request_key_auth_describe() If a request_key authentication token key gets revoked, there's a window in which request_key_auth_describe() can see it with a NULL payload - but it makes no check for this and something like the following oops may occur: BUG: Kernel NULL pointer dereference at 0x0038 Faulting instruction address: 0xc04ddf30 Oops: Kernel access of bad area, sig: 11 [#1] ... NIP [...] request_key_auth_describe+0x90/0xd0 LR [...] request_key_auth_describe+0x54/0xd0 Call Trace: [...] request_key_auth_describe+0x54/0xd0 (unreliable) [...] proc_keys_show+0x308/0x4c0 [...] seq_read+0x3d0/0x540 [...] proc_reg_read+0x90/0x110 [...] __vfs_read+0x3c/0x70 [...] vfs_read+0xb4/0x1b0 [...] ksys_read+0x7c/0x130 [...] system_call+0x5c/0x70 Fix this by checking for a NULL pointer when describing such a key. Also make the read routine check for a NULL pointer to be on the safe side. Fixes: 04c567d9313e ("[PATCH] Keys: Fix race between two instantiators of a key") Reported-by: Sachin Sant Signed-off-by: David Howells diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c index e73ec040e250..ecba39c93fd9 100644 --- a/security/keys/request_key_auth.c +++ b/security/keys/request_key_auth.c @@ -66,6 +66,9 @@ static void request_key_auth_describe(const struct key *key, { struct request_key_auth *rka = dereference_key_rcu(key); + if (!rka) + return; + seq_puts(m, "key:"); seq_puts(m, key->description); if (key_is_positive(key)) @@ -83,6 +86,9 @@ static long request_key_auth_read(const struct key *key, size_t datalen; long ret; + if (!rka) + return -EKEYREVOKED; + datalen = rka->callout_len; ret = datalen;
Re: Oops (request_key_auth_describe) while running cve-2016-7042 from LTP
Hillf Danton wrote: > 1, callee has no pre defined duty to help caller in general; they should not > try to do anything, however, to help their callers in principle due to > limited info on their hands IMO. Ah, no. It's entirely reasonable for an API to specify that one of its methods will be called with one or more locks held - and that the method must be aware of this and may make use of this. > 3, no comment can be found in security/keys/request_key_auth.c about > the rcu already documented. There is API documentation in Documentation/security/keys/core.rst. If you look at about line 1538 onwards: * ``void (*describe)(const struct key *key, struct seq_file *p);`` This method is optional. It is called during /proc/keys reading to summarise a key's description and payload in text form. This method will be called with the RCU read lock held. rcu_dereference() should be used to read the payload pointer if the payload is to be accessed. key->datalen cannot be trusted to stay consistent with the contents of the payload. The description will not change, though the key's state may. It is not safe to sleep in this method; the RCU read lock is held by the caller. David
Re: [PATCH v5 1/5] kasan: support backing vmalloc space with real shadow memory
Hi all, > +static int kasan_depopulate_vmalloc_pte(pte_t *ptep, unsigned long addr, > + void *unused) > +{ > + unsigned long page; > + > + page = (unsigned long)__va(pte_pfn(*ptep) << PAGE_SHIFT); > + > + spin_lock(&init_mm.page_table_lock); > + > + /* > + * we want to catch bugs where we end up clearing a pte that wasn't > + * set. This will unfortunately also fire if we are releasing a region > + * where we had a failure allocating the shadow region. > + */ > + WARN_ON_ONCE(pte_none(*ptep)); > + > + pte_clear(&init_mm, addr, ptep); > + free_page(page); > + spin_unlock(&init_mm.page_table_lock); It's just occurred to me that the free_page really needs to be guarded by an 'if (likely(!pte_none(*pte))) {' - there won't be a page to free if there's no pte. I'll spin v6 on Monday. Regards, Daniel > + > + return 0; > +} > + > +/* > + * Release the backing for the vmalloc region [start, end), which > + * lies within the free region [free_region_start, free_region_end). > + * > + * This can be run lazily, long after the region was freed. It runs > + * under vmap_area_lock, so it's not safe to interact with the vmalloc/vmap > + * infrastructure. > + */ > +void kasan_release_vmalloc(unsigned long start, unsigned long end, > +unsigned long free_region_start, > +unsigned long free_region_end) > +{ > + void *shadow_start, *shadow_end; > + unsigned long region_start, region_end; > + > + /* we start with shadow entirely covered by this region */ > + region_start = ALIGN(start, PAGE_SIZE * KASAN_SHADOW_SCALE_SIZE); > + region_end = ALIGN_DOWN(end, PAGE_SIZE * KASAN_SHADOW_SCALE_SIZE); > + > + /* > + * We don't want to extend the region we release to the entire free > + * region, as the free region might cover huge chunks of vmalloc space > + * where we never allocated anything. We just want to see if we can > + * extend the [start, end) range: if start or end fall part way through > + * a shadow page, we want to check if we can free that entire page. > + */ > + > + free_region_start = ALIGN(free_region_start, > + PAGE_SIZE * KASAN_SHADOW_SCALE_SIZE); > + > + if (start != region_start && > + free_region_start < region_start) > + region_start -= PAGE_SIZE * KASAN_SHADOW_SCALE_SIZE; > + > + free_region_end = ALIGN_DOWN(free_region_end, > + PAGE_SIZE * KASAN_SHADOW_SCALE_SIZE); > + > + if (end != region_end && > + free_region_end > region_end) > + region_end += PAGE_SIZE * KASAN_SHADOW_SCALE_SIZE; > + > + shadow_start = kasan_mem_to_shadow((void *)region_start); > + shadow_end = kasan_mem_to_shadow((void *)region_end); > + > + if (shadow_end > shadow_start) > + apply_to_page_range(&init_mm, (unsigned long)shadow_start, > + (unsigned long)(shadow_end - shadow_start), > + kasan_depopulate_vmalloc_pte, NULL); > +} > +#endif > diff --git a/mm/kasan/generic_report.c b/mm/kasan/generic_report.c > index 36c645939bc9..2d97efd4954f 100644 > --- a/mm/kasan/generic_report.c > +++ b/mm/kasan/generic_report.c > @@ -86,6 +86,9 @@ static const char *get_shadow_bug_type(struct > kasan_access_info *info) > case KASAN_ALLOCA_RIGHT: > bug_type = "alloca-out-of-bounds"; > break; > + case KASAN_VMALLOC_INVALID: > + bug_type = "vmalloc-out-of-bounds"; > + break; > } > > return bug_type; > diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h > index 35cff6bbb716..3a083274628e 100644 > --- a/mm/kasan/kasan.h > +++ b/mm/kasan/kasan.h > @@ -25,6 +25,7 @@ > #endif > > #define KASAN_GLOBAL_REDZONE0xFA /* redzone for global variable */ > +#define KASAN_VMALLOC_INVALID 0xF9 /* unallocated space in vmapped page */ > > /* > * Stack redzone shadow values > diff --git a/mm/vmalloc.c b/mm/vmalloc.c > index b8101030f79e..bf806566cad0 100644 > --- a/mm/vmalloc.c > +++ b/mm/vmalloc.c > @@ -690,8 +690,19 @@ merge_or_add_vmap_area(struct vmap_area *va, > struct list_head *next; > struct rb_node **link; > struct rb_node *parent; > + unsigned long orig_start, orig_end; > bool merged = false; > > + /* > + * To manage KASAN vmalloc memory usage, we use this opportunity to > + * clean up the shadow memory allocated to back this allocation. > + * Because a vmalloc shadow page covers several pages, the start or end > + * of an allocation might not align with a shadow page. Use the merging > + * opportunities to try to extend the region we can release. > + */ > + orig_start = va->va_start; > + orig_end = va->va_end; > + > /* >* Find a place in the tree where VA potentially will be >* inserted
Re: Oops (request_key_auth_describe) while running cve-2016-7042 from LTP
Hillf Danton wrote: > - struct request_key_auth *rka = dereference_key_rcu(key); > + struct request_key_auth *rka; > + > + rcu_read_lock(); > + rka = dereference_key_rcu(key); This shouldn't help as the caller, proc_keys_show(), is holding the RCU read lock across the call. The end of the function reads: if (key->type->describe) key->type->describe(key, m); seq_putc(m, '\n'); rcu_read_unlock(); return 0; } and the documentation says "This method will be called with the RCU read lock held". I suspect the actual bugfix is this bit: > + if (!rka) > + goto out; David
[PATCH 3/3] powerpc/mm: call H_BLOCK_REMOVE when supported
Instead of calling H_BLOCK_REMOVE all the time when the feature is exhibited, call this hcall only when the couple base page size, page size is supported as reported by the TLB Invalidate Characteristics. For regular pages and hugetlb, the assumption is made that the page size is equal to the base page size. For THP the page size is assumed to be 16M. Signed-off-by: Laurent Dufour --- arch/powerpc/platforms/pseries/lpar.c | 11 +-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index 375e19b3cf53..ef3dbf108a65 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c @@ -1143,7 +1143,11 @@ static inline void __pSeries_lpar_hugepage_invalidate(unsigned long *slot, if (lock_tlbie) spin_lock_irqsave(&pSeries_lpar_tlbie_lock, flags); - if (firmware_has_feature(FW_FEATURE_BLOCK_REMOVE)) + /* +* Assuming THP size is 16M, and we only support 8 bytes size buffer +* for the momment. +*/ + if (mmu_psize_defs[psize].hblk[MMU_PAGE_16M] == 8) hugepage_block_invalidate(slot, vpn, count, psize, ssize); else hugepage_bulk_invalidate(slot, vpn, count, psize, ssize); @@ -1437,7 +1441,10 @@ static void pSeries_lpar_flush_hash_range(unsigned long number, int local) if (lock_tlbie) spin_lock_irqsave(&pSeries_lpar_tlbie_lock, flags); - if (firmware_has_feature(FW_FEATURE_BLOCK_REMOVE)) { + /* +* Currently, we only support 8 bytes size buffer in do_block_remove(). +*/ + if (mmu_psize_defs[batch->psize].hblk[batch->psize] == 8) { do_block_remove(number, batch, param); goto out; } -- 2.23.0
[PATCH 2/3] powperc/mm: read TLB Block Invalidate Characteristics
The PAPR document specifies the TLB Block Invalidate Characteristics which is telling which couple base page size / page size is supported by the H_BLOCK_REMOVE hcall. A new set of feature is added to the mmu_psize_def structure to record per base page size which page size is supported by H_BLOCK_REMOVE. A new init service is added to read the characteristics. The size of the buffer is set to twice the number of known page size, plus 10 bytes to ensure we have enough place. Signed-off-by: Laurent Dufour --- arch/powerpc/include/asm/book3s/64/mmu.h | 3 + arch/powerpc/platforms/pseries/lpar.c| 107 +++ 2 files changed, 110 insertions(+) diff --git a/arch/powerpc/include/asm/book3s/64/mmu.h b/arch/powerpc/include/asm/book3s/64/mmu.h index 23b83d3593e2..675895dfe39f 100644 --- a/arch/powerpc/include/asm/book3s/64/mmu.h +++ b/arch/powerpc/include/asm/book3s/64/mmu.h @@ -12,11 +12,14 @@ *sllp : is a bit mask with the value of SLB L || LP to be or'ed *directly to a slbmte "vsid" value *penc : is the HPTE encoding mask for the "LP" field: + *hblk : H_BLOCK_REMOVE supported block size for this page size in + *segment who's base page size is that page size. * */ struct mmu_psize_def { unsigned intshift; /* number of bits */ int penc[MMU_PAGE_COUNT]; /* HPTE encoding */ + int hblk[MMU_PAGE_COUNT]; /* H_BLOCK_REMOVE support */ unsigned inttlbiel; /* tlbiel supported for that page size */ unsigned long avpnm; /* bits to mask out in AVPN in the HPTE */ union { diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index 4f76e5f30c97..375e19b3cf53 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c @@ -1311,6 +1311,113 @@ static void do_block_remove(unsigned long number, struct ppc64_tlb_batch *batch, (void)call_block_remove(pix, param, true); } +static inline void __init set_hblk_bloc_size(int bpsize, int psize, +unsigned int block_size) +{ + struct mmu_psize_def *def = &mmu_psize_defs[bpsize]; + + if (block_size > def->hblk[psize]) + def->hblk[psize] = block_size; +} + +static inline void __init check_lp_set_hblk(unsigned int lp, + unsigned int block_size) +{ + unsigned int bpsize, psize; + + + /* First, check the L bit, if not set, this means 4K */ + if ((lp & 0x80) == 0) { + set_hblk_bloc_size(MMU_PAGE_4K, MMU_PAGE_4K, block_size); + return; + } + + /* PAPR says to look at bits 2-7 (0 = MSB) */ + lp &= 0x3f; + for (bpsize = 0; bpsize < MMU_PAGE_COUNT; bpsize++) { + struct mmu_psize_def *def = &mmu_psize_defs[bpsize]; + + for (psize = 0; psize < MMU_PAGE_COUNT; psize++) { + if (def->penc[psize] == lp) { + set_hblk_bloc_size(bpsize, psize, block_size); + return; + } + } + } +} + +#define SPLPAR_TLB_BIC_TOKEN 50 +#define SPLPAR_TLB_BIC_MAXLENGTH (MMU_PAGE_COUNT*2 + 10) +static int __init read_tlbbi_characteristics(void) +{ + int call_status; + unsigned char local_buffer[SPLPAR_TLB_BIC_MAXLENGTH]; + int len, idx, bpsize; + + if (!firmware_has_feature(FW_FEATURE_BLOCK_REMOVE)) { + pr_info("H_BLOCK_REMOVE is not supported"); + return 0; + } + + memset(local_buffer, 0, SPLPAR_TLB_BIC_MAXLENGTH); + + spin_lock(&rtas_data_buf_lock); + memset(rtas_data_buf, 0, RTAS_DATA_BUF_SIZE); + call_status = rtas_call(rtas_token("ibm,get-system-parameter"), 3, 1, + NULL, + SPLPAR_TLB_BIC_TOKEN, + __pa(rtas_data_buf), + RTAS_DATA_BUF_SIZE); + memcpy(local_buffer, rtas_data_buf, SPLPAR_TLB_BIC_MAXLENGTH); + local_buffer[SPLPAR_TLB_BIC_MAXLENGTH - 1] = '\0'; + spin_unlock(&rtas_data_buf_lock); + + if (call_status != 0) { + pr_warn("%s %s Error calling get-system-parameter (0x%x)\n", + __FILE__, __func__, call_status); + return 0; + } + + /* +* The first two (2) bytes of the data in the buffer are the length of +* the returned data, not counting these first two (2) bytes. +*/ + len = local_buffer[0] * 256 + local_buffer[1] + 2; + if (len >= SPLPAR_TLB_BIC_MAXLENGTH) { + pr_warn("%s too large returned buffer %d", __func__, len); + return 0; + } + + idx = 2; + while (idx < len) { + unsigned int block_size = local_buffer[idx++]; + unsigned int np
[PATCH 1/3] powerpc/mm: Initialize the HPTE encoding values
Before reading the HPTE encoding values we initialize all of them to -1 (an invalid value) to later being able to detect the initialized ones. Signed-off-by: Laurent Dufour --- arch/powerpc/mm/book3s64/hash_utils.c | 8 ++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/mm/book3s64/hash_utils.c b/arch/powerpc/mm/book3s64/hash_utils.c index c3bfef08dcf8..2039bc315459 100644 --- a/arch/powerpc/mm/book3s64/hash_utils.c +++ b/arch/powerpc/mm/book3s64/hash_utils.c @@ -408,7 +408,7 @@ static int __init htab_dt_scan_page_sizes(unsigned long node, { const char *type = of_get_flat_dt_prop(node, "device_type", NULL); const __be32 *prop; - int size = 0; + int size = 0, idx, base_idx; /* We are scanning "cpu" nodes only */ if (type == NULL || strcmp(type, "cpu") != 0) @@ -418,6 +418,11 @@ static int __init htab_dt_scan_page_sizes(unsigned long node, if (!prop) return 0; + /* Set all the penc values to invalid */ + for (base_idx = 0; base_idx < MMU_PAGE_COUNT; base_idx++) + for (idx = 0; idx < MMU_PAGE_COUNT; idx++) + mmu_psize_defs[base_idx].penc[idx] = -1; + pr_info("Page sizes from device-tree:\n"); size /= 4; cur_cpu_spec->mmu_features &= ~(MMU_FTR_16M_PAGE); @@ -426,7 +431,6 @@ static int __init htab_dt_scan_page_sizes(unsigned long node, unsigned int slbenc = be32_to_cpu(prop[1]); unsigned int lpnum = be32_to_cpu(prop[2]); struct mmu_psize_def *def; - int idx, base_idx; size -= 3; prop += 3; base_idx = get_idx_from_shift(base_shift); -- 2.23.0
[PATCH 0/3] powerpc/mm: Conditionally call H_BLOCK_REMOVE
Since the commit ba2dd8a26baa ("powerpc/pseries/mm: call H_BLOCK_REMOVE"), the call to H_BLOCK_REMOVE is always done if the feature is exhibited. On some system, the hypervisor may not support all the combination of segment base page size and page size. When this happens the hcall is returning H_PARAM, which is triggering a BUG_ON check leading to a panic. The PAPR document is specifying a TLB Block Invalidate Characteristics item detailing which couple base page size, page size the hypervisor is supporting through H_BLOCK_REMOVE. Furthermore, the characteristics are also providing the size of the block the hcall could process. Supporting various block size seems not needed as all systems I was able to play with was support an 8 addresses block size, which is the maximum through the hcall. Supporting various size may complexify the algorithm in call_block_remove() so unless this is required, this is not done. In the case of block size different from 8, a warning message is displayed at boot time and that block size will be ignored checking for the H_BLOCK_REMOVE support. Due to the minimal amount of hardware showing a limited set of H_BLOCK_REMOVE supported page size, I don't think there is a need to push this series to the stable mailing list. The first patch is initializing the penc values for each page size to an invalid value to be able to detect those which have been initialized as 0 is a valid value. The second patch is reading the characteristic through the hcall ibm,get-system-parameter and record the supported block size for each page size. The third patch is changing the check used to detect the H_BLOCK_REMOVE availability to take care of the base page size and page size couple. Laurent Dufour (3): powerpc/mm: Initialize the HPTE encoding values powperc/mm: read TLB Block Invalidate Characteristics powerpc/mm: call H_BLOCK_REMOVE when supported arch/powerpc/include/asm/book3s/64/mmu.h | 3 + arch/powerpc/mm/book3s64/hash_utils.c| 8 +- arch/powerpc/platforms/pseries/lpar.c| 118 ++- 3 files changed, 125 insertions(+), 4 deletions(-) -- 2.23.0
Applied "ASoC: fsl_ssi: Fix clock control issue in master mode" to the asoc tree
The patch ASoC: fsl_ssi: Fix clock control issue in master mode has been applied to the asoc tree at https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-5.3 All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted. You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed. If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced. Please add any relevant lists and maintainers to the CCs when replying to this mail. Thanks, Mark >From 696d05225cebffd172008d212657be90e823eac0 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Wed, 28 Aug 2019 13:20:17 -0400 Subject: [PATCH] ASoC: fsl_ssi: Fix clock control issue in master mode The test case is arecord -Dhw:0 -d 10 -f S16_LE -r 48000 -c 2 temp.wav & aplay -Dhw:0 -d 30 -f S16_LE -r 48000 -c 2 test.wav There will be error after end of arecord: aplay: pcm_write:2051: write error: Input/output error Capture and Playback work in parallel in master mode, one substream stops, the other substream is impacted, the reason is that clock is disabled wrongly. The clock's reference count is not increased when second substream starts, the hw_param() function returns in the beginning because first substream is enabled, then in end of first substream, the hw_free() disables the clock. This patch is to move the clock enablement to the place before checking of the device enablement in hw_param(). Signed-off-by: Shengjiu Wang Link: https://lore.kernel.org/r/1567012817-12625-1-git-send-email-shengjiu.w...@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_ssi.c | 18 +- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index fa862af25c1a..085855f9b08d 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -799,15 +799,6 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream, u32 wl = SSI_SxCCR_WL(sample_size); int ret; - /* -* SSI is properly configured if it is enabled and running in -* the synchronous mode; Note that AC97 mode is an exception -* that should set separate configurations for STCCR and SRCCR -* despite running in the synchronous mode. -*/ - if (ssi->streams && ssi->synchronous) - return 0; - if (fsl_ssi_is_i2s_master(ssi)) { ret = fsl_ssi_set_bclk(substream, dai, hw_params); if (ret) @@ -823,6 +814,15 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream, } } + /* +* SSI is properly configured if it is enabled and running in +* the synchronous mode; Note that AC97 mode is an exception +* that should set separate configurations for STCCR and SRCCR +* despite running in the synchronous mode. +*/ + if (ssi->streams && ssi->synchronous) + return 0; + if (!fsl_ssi_is_ac97(ssi)) { /* * Keep the ssi->i2s_net intact while having a local variable -- 2.20.1
Re: [PATCH v7 1/7] kvmppc: Driver to manage pages of secure guest
On Thu, Aug 29, 2019 at 12:39:11PM -0700, Sukadev Bhattiprolu wrote: > Bharata B Rao [bhar...@linux.ibm.com] wrote: > > On Wed, Aug 28, 2019 at 08:02:19PM -0700, Sukadev Bhattiprolu wrote: > Where do we serialize two threads attempting to H_SVM_PAGE_IN the same gfn > at the same time? Or one thread issuing a H_SVM_PAGE_IN and another a > H_SVM_PAGE_OUT for the same page? I am not not serializing page-in/out calls on same gfn, I thought you take care of that in UV, guess UV doesn't yet. I can probably use rmap_lock() and serialize such calls in HV if UV can't prevent such calls easily. > > > > + > > > > + if (!trylock_page(dpage)) > > > > + goto out_clear; > > > > + > > > > + *rmap = devm_pfn | KVMPPC_RMAP_DEVM_PFN; > > > > + pvt = kzalloc(sizeof(*pvt), GFP_ATOMIC); > > > > + if (!pvt) > > > > + goto out_unlock; > > If we fail to alloc, we don't clear the KVMPPC_RMAP_DEVM_PFN? Right, I will move the assignment to *rmap to after kzalloc. > > Also, when/where do we clear this flag on an uv-page-out? > kvmppc_devm_drop_pages() drops the flag on a local variable but not > in the rmap? If we don't clear the flag on page-out, would the > subsequent H_SVM_PAGE_IN of this page fail? It gets cleared in kvmppc_devm_page_free(). > > Ok. Nit. thought we can drop the "_fault" in the function name but would > collide the other "alloc_and_copy" function used during H_SVM_PAGE_IN. > If the two alloc_and_copy functions are symmetric, maybe they could > have "page_in" and "page_out" in the (already long) names. Christoph also suggested to reorganize these two calls. Will take care. Regards, Bharata.
Re: Oops (request_key_auth_describe) while running cve-2016-7042 from LTP
> On 30-Aug-2019, at 2:26 PM, Hillf Danton wrote: > > > On Fri, 30 Aug 2019 12:18:07 +0530 Sachin Sant wrote: >> >> [ 8074.351033] BUG: Kernel NULL pointer dereference at 0x0038 >> [ 8074.351046] Faulting instruction address: 0xc04ddf30 >> [ 8074.351052] Oops: Kernel access of bad area, sig: 11 [#1] >> [ 8074.351056] LE PAGE_SIZE=64K MMU=Hash SMP NR_CPUS=2048 NUMA pSeries > > Add rcu gp. > > --- a/security/keys/request_key_auth.c > +++ b/security/keys/request_key_auth.c > @@ -64,12 +64,19 @@ static int request_key_auth_instantiate( > static void request_key_auth_describe(const struct key *key, > struct seq_file *m) > { > - struct request_key_auth *rka = dereference_key_rcu(key); > + struct request_key_auth *rka; > + > + rcu_read_lock(); > + rka = dereference_key_rcu(key); > + if (!rka) > + goto out; > Thanks for the patch. Works for me. Test ran fine without any problems. Tested-by: Sachin Sant Thanks -Sachin
[PATCH v4 3/8] mm/memory_hotplug: Shrink zones when offlining memory
We currently try to shrink a single zone when removing memory. We use the zone of the first page of the memory we are removing. If that memmap was never initialized (e.g., memory was never onlined), we will read garbage and can trigger kernel BUGs (due to a stale pointer): :/# [ 23.912993] BUG: unable to handle page fault for address: 353d [ 23.914219] #PF: supervisor write access in kernel mode [ 23.915199] #PF: error_code(0x0002) - not-present page [ 23.916160] PGD 0 P4D 0 [ 23.916627] Oops: 0002 [#1] SMP PTI [ 23.917256] CPU: 1 PID: 7 Comm: kworker/u8:0 Not tainted 5.3.0-rc5-next-20190820+ #317 [ 23.918900] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.12.1-0-ga5cab58e9a3f-prebuilt.qemu.4 [ 23.921194] Workqueue: kacpi_hotplug acpi_hotplug_work_fn [ 23.922249] RIP: 0010:clear_zone_contiguous+0x5/0x10 [ 23.923173] Code: 48 89 c6 48 89 c3 e8 2a fe ff ff 48 85 c0 75 cf 5b 5d c3 c6 85 fd 05 00 00 01 5b 5d c3 0f 1f 840 [ 23.926876] RSP: 0018:ad2400043c98 EFLAGS: 00010246 [ 23.927928] RAX: RBX: 0002 RCX: [ 23.929458] RDX: 0020 RSI: 0014 RDI: 2f40 [ 23.930899] RBP: 00014000 R08: R09: 0001 [ 23.932362] R10: R11: R12: 0014 [ 23.933603] R13: 0014 R14: 2f40 R15: 9e3e7aff3680 [ 23.934913] FS: () GS:9e3e7bb0() knlGS: [ 23.936294] CS: 0010 DS: ES: CR0: 80050033 [ 23.937481] CR2: 353d CR3: 5861 CR4: 06e0 [ 23.938687] DR0: DR1: DR2: [ 23.939889] DR3: DR6: fffe0ff0 DR7: 0400 [ 23.941168] Call Trace: [ 23.941580] __remove_pages+0x4b/0x640 [ 23.942303] ? mark_held_locks+0x49/0x70 [ 23.943149] arch_remove_memory+0x63/0x8d [ 23.943921] try_remove_memory+0xdb/0x130 [ 23.944766] ? walk_memory_blocks+0x7f/0x9e [ 23.945616] __remove_memory+0xa/0x11 [ 23.946274] acpi_memory_device_remove+0x70/0x100 [ 23.947308] acpi_bus_trim+0x55/0x90 [ 23.947914] acpi_device_hotplug+0x227/0x3a0 [ 23.948714] acpi_hotplug_work_fn+0x1a/0x30 [ 23.949433] process_one_work+0x221/0x550 [ 23.950190] worker_thread+0x50/0x3b0 [ 23.950993] kthread+0x105/0x140 [ 23.951644] ? process_one_work+0x550/0x550 [ 23.952508] ? kthread_park+0x80/0x80 [ 23.953367] ret_from_fork+0x3a/0x50 [ 23.954025] Modules linked in: [ 23.954613] CR2: 353d [ 23.955248] ---[ end trace 93d982b1fb3e1a69 ]--- Instead, shrink the zones when offlining memory or when onlining failed. Introduce and use remove_pfn_range_from_zone(() for that. We now properly shrink the zones, even if we have DIMMs whereby - Some memory blocks fall into no zone (never onlined) - Some memory blocks fall into multiple zones (offlined+re-onlined) - Multiple memory blocks that fall into different zones Drop the zone parameter (with a potential dubious value) from __remove_pages() and __remove_section(). Cc: Catalin Marinas Cc: Will Deacon Cc: Tony Luck Cc: Fenghua Yu Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Michael Ellerman Cc: Heiko Carstens Cc: Vasily Gorbik Cc: Christian Borntraeger Cc: Yoshinori Sato Cc: Rich Felker Cc: Dave Hansen Cc: Andy Lutomirski Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Ingo Molnar Cc: Borislav Petkov Cc: "H. Peter Anvin" Cc: x...@kernel.org Cc: Andrew Morton Cc: Mark Rutland Cc: Steve Capper Cc: Mike Rapoport Cc: Anshuman Khandual Cc: Yu Zhao Cc: Jun Yao Cc: Robin Murphy Cc: Michal Hocko Cc: Oscar Salvador Cc: "Matthew Wilcox (Oracle)" Cc: Christophe Leroy Cc: "Aneesh Kumar K.V" Cc: Pavel Tatashin Cc: Gerald Schaefer Cc: Halil Pasic Cc: Tom Lendacky Cc: Greg Kroah-Hartman Cc: Masahiro Yamada Cc: Dan Williams Cc: Wei Yang Cc: Qian Cai Cc: Jason Gunthorpe Cc: Logan Gunthorpe Cc: Ira Weiny Cc: linux-arm-ker...@lists.infradead.org Cc: linux-i...@vger.kernel.org Cc: linuxppc-dev@lists.ozlabs.org Cc: linux-s...@vger.kernel.org Cc: linux...@vger.kernel.org Fixes: d0dc12e86b31 ("mm/memory_hotplug: optimize memory hotplug") Signed-off-by: David Hildenbrand --- arch/arm64/mm/mmu.c| 4 +--- arch/ia64/mm/init.c| 4 +--- arch/powerpc/mm/mem.c | 3 +-- arch/s390/mm/init.c| 4 +--- arch/sh/mm/init.c | 4 +--- arch/x86/mm/init_32.c | 4 +--- arch/x86/mm/init_64.c | 4 +--- include/linux/memory_hotplug.h | 7 +-- mm/memory_hotplug.c| 31 --- mm/memremap.c | 3 +-- 10 files changed, 29 insertions(+), 39 deletions(-) diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c index 60c929f3683b..d10247fab0fd 100644 --- a/arch/arm64/mm/mmu.c +++ b/arch/arm64/mm/mmu.c @@ -1069,7 +10
Re: Oops (request_key_auth_describe) while running cve-2016-7042 from LTP
On Fri, 30 Aug 2019 12:18:07 +0530 Sachin Sant wrote: > > [ 8074.351033] BUG: Kernel NULL pointer dereference at 0x0038 > [ 8074.351046] Faulting instruction address: 0xc04ddf30 > [ 8074.351052] Oops: Kernel access of bad area, sig: 11 [#1] > [ 8074.351056] LE PAGE_SIZE=64K MMU=Hash SMP NR_CPUS=2048 NUMA pSeries Add rcu gp. --- a/security/keys/request_key_auth.c +++ b/security/keys/request_key_auth.c @@ -64,12 +64,19 @@ static int request_key_auth_instantiate( static void request_key_auth_describe(const struct key *key, struct seq_file *m) { - struct request_key_auth *rka = dereference_key_rcu(key); + struct request_key_auth *rka; + + rcu_read_lock(); + rka = dereference_key_rcu(key); + if (!rka) + goto out; seq_puts(m, "key:"); seq_puts(m, key->description); if (key_is_positive(key)) seq_printf(m, " pid:%d ci:%zu", rka->pid, rka->callout_len); +out: + rcu_read_unlock(); } /*
Re: [PATCH -next] crypto: nx - remove unused variables 'nx_driver_string' and 'nx_driver_version'
On Thu, Aug 22, 2019 at 10:46:49PM +0800, YueHaibing wrote: > drivers/crypto/nx/nx.h:12:19: warning: > nx_driver_string defined but not used [-Wunused-const-variable=] > drivers/crypto/nx/nx.h:13:19: warning: > nx_driver_version defined but not used [-Wunused-const-variable=] > > They are never used, so just remove it. > > Reported-by: Hulk Robot > Signed-off-by: YueHaibing > --- > drivers/crypto/nx/nx.h | 3 --- > 1 file changed, 3 deletions(-) Patch applied. Thanks. -- Email: Herbert Xu Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
Re: [PATCH v5 3/5] powerpc/64: make buildable without CONFIG_COMPAT
Le 30/08/2019 à 09:54, Michal Suchánek a écrit : On Fri, 30 Aug 2019 06:35:13 + (UTC) Christophe Leroy wrote: On 08/29/2019 10:28 PM, Michal Suchanek wrote: There are numerous references to 32bit functions in generic and 64bit code so ifdef them out. Signed-off-by: Michal Suchanek --- v2: - fix 32bit ifdef condition in signal.c - simplify the compat ifdef condition in vdso.c - 64bit is redundant - simplify the compat ifdef condition in callchain.c - 64bit is redundant v3: - use IS_ENABLED and maybe_unused where possible - do not ifdef declarations - clean up Makefile v4: - further makefile cleanup - simplify is_32bit_task conditions - avoid ifdef in condition by using return v5: - avoid unreachable code on 32bit - make is_current_64bit constant on !COMPAT - add stub perf_callchain_user_32 to avoid some ifdefs --- arch/powerpc/include/asm/thread_info.h | 4 ++-- arch/powerpc/kernel/Makefile | 7 +++ arch/powerpc/kernel/entry_64.S | 2 ++ arch/powerpc/kernel/signal.c | 3 +-- arch/powerpc/kernel/syscall_64.c | 6 ++ arch/powerpc/kernel/vdso.c | 5 ++--- arch/powerpc/perf/callchain.c | 13 +++-- 7 files changed, 23 insertions(+), 17 deletions(-) [...] diff --git a/arch/powerpc/perf/callchain.c b/arch/powerpc/perf/callchain.c index c84bbd4298a0..881be5c4e9bb 100644 --- a/arch/powerpc/perf/callchain.c +++ b/arch/powerpc/perf/callchain.c @@ -15,7 +15,7 @@ #include #include #include -#ifdef CONFIG_PPC64 +#ifdef CONFIG_COMPAT #include "../kernel/ppc32.h" #endif #include @@ -291,7 +291,8 @@ static inline int current_is_64bit(void) * interrupt stack, and the thread flags don't get copied over * from the thread_info on the main stack to the interrupt stack. */ - return !test_ti_thread_flag(task_thread_info(current), TIF_32BIT); + return !IS_ENABLED(CONFIG_COMPAT) || + !test_ti_thread_flag(task_thread_info(current), TIF_32BIT); } #else /* CONFIG_PPC64 */ @@ -341,6 +342,7 @@ static inline int valid_user_sp(unsigned long sp, int is_64) #endif /* CONFIG_PPC64 */ +#if defined(CONFIG_PPC32) || defined(CONFIG_COMPAT) /* * Layout for non-RT signal frames */ @@ -482,6 +484,13 @@ static void perf_callchain_user_32(struct perf_callchain_entry_ctx *entry, sp = next_sp; } } +#else /* 32bit */ +static void perf_callchain_user_32(struct perf_callchain_entry_ctx *entry, + struct pt_regs *regs) +{ + (void)&read_user_stack_32; /* unused if !COMPAT */ That looks pretty much like a hack. See possible alternative below. +} +#endif /* 32bit */ void perf_callchain_user(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs) --- arch/powerpc/perf/callchain.c | 62 +++ 1 file changed, 27 insertions(+), 35 deletions(-) diff --git a/arch/powerpc/perf/callchain.c b/arch/powerpc/perf/callchain.c index 881be5c4e9bb..1b169b32776a 100644 --- a/arch/powerpc/perf/callchain.c +++ b/arch/powerpc/perf/callchain.c @@ -165,22 +165,6 @@ static int read_user_stack_64(unsigned long __user *ptr, unsigned long *ret) return read_user_stack_slow(ptr, ret, 8); } -static int read_user_stack_32(unsigned int __user *ptr, unsigned int *ret) -{ - if ((unsigned long)ptr > TASK_SIZE - sizeof(unsigned int) || - ((unsigned long)ptr & 3)) - return -EFAULT; - - pagefault_disable(); - if (!__get_user_inatomic(*ret, ptr)) { - pagefault_enable(); - return 0; - } - pagefault_enable(); - - return read_user_stack_slow(ptr, ret, 4); -} - static inline int valid_user_sp(unsigned long sp, int is_64) { if (!sp || (sp & 7) || sp > (is_64 ? TASK_SIZE : 0x1UL) - 32) @@ -296,25 +280,10 @@ static inline int current_is_64bit(void) } #else /* CONFIG_PPC64 */ -/* - * On 32-bit we just access the address and let hash_page create a - * HPTE if necessary, so there is no need to fall back to reading - * the page tables. Since this is called at interrupt level, - * do_page_fault() won't treat a DSI as a page fault. - */ -static int read_user_stack_32(unsigned int __user *ptr, unsigned int *ret) -{ - int rc; - - if ((unsigned long)ptr > TASK_SIZE - sizeof(unsigned int) || - ((unsigned long)ptr & 3)) - return -EFAULT; - pagefault_disable(); - rc = __get_user_inatomic(*ret, ptr); - pagefault_enable(); - - return rc; +static int read_user_stack_slow(void __user *ptr, void *buf, int nb) +{ + return 0; Here it is } static inline void perf_callchain_user_64(struct perf_callchain_entry_ctx *entry, @@ -344,6 +313,30 @@ static inline int valid_user_sp(unsigned long sp, int is_64) #if defined(CONFIG_PPC32) || defined(CONFIG_COMPAT)
Re: [PATCH v5 3/5] powerpc/64: make buildable without CONFIG_COMPAT
On Fri, 30 Aug 2019 06:35:13 + (UTC) Christophe Leroy wrote: > On 08/29/2019 10:28 PM, Michal Suchanek wrote: > > There are numerous references to 32bit functions in generic and 64bit > > code so ifdef them out. > > > > Signed-off-by: Michal Suchanek > > --- > > v2: > > - fix 32bit ifdef condition in signal.c > > - simplify the compat ifdef condition in vdso.c - 64bit is redundant > > - simplify the compat ifdef condition in callchain.c - 64bit is redundant > > v3: > > - use IS_ENABLED and maybe_unused where possible > > - do not ifdef declarations > > - clean up Makefile > > v4: > > - further makefile cleanup > > - simplify is_32bit_task conditions > > - avoid ifdef in condition by using return > > v5: > > - avoid unreachable code on 32bit > > - make is_current_64bit constant on !COMPAT > > - add stub perf_callchain_user_32 to avoid some ifdefs > > --- > > arch/powerpc/include/asm/thread_info.h | 4 ++-- > > arch/powerpc/kernel/Makefile | 7 +++ > > arch/powerpc/kernel/entry_64.S | 2 ++ > > arch/powerpc/kernel/signal.c | 3 +-- > > arch/powerpc/kernel/syscall_64.c | 6 ++ > > arch/powerpc/kernel/vdso.c | 5 ++--- > > arch/powerpc/perf/callchain.c | 13 +++-- > > 7 files changed, 23 insertions(+), 17 deletions(-) > > > [...] > > > diff --git a/arch/powerpc/perf/callchain.c b/arch/powerpc/perf/callchain.c > > index c84bbd4298a0..881be5c4e9bb 100644 > > --- a/arch/powerpc/perf/callchain.c > > +++ b/arch/powerpc/perf/callchain.c > > @@ -15,7 +15,7 @@ > > #include > > #include > > #include > > -#ifdef CONFIG_PPC64 > > +#ifdef CONFIG_COMPAT > > #include "../kernel/ppc32.h" > > #endif > > #include > > @@ -291,7 +291,8 @@ static inline int current_is_64bit(void) > > * interrupt stack, and the thread flags don't get copied over > > * from the thread_info on the main stack to the interrupt stack. > > */ > > - return !test_ti_thread_flag(task_thread_info(current), TIF_32BIT); > > + return !IS_ENABLED(CONFIG_COMPAT) || > > + !test_ti_thread_flag(task_thread_info(current), TIF_32BIT); > > } > > > > #else /* CONFIG_PPC64 */ > > @@ -341,6 +342,7 @@ static inline int valid_user_sp(unsigned long sp, int > > is_64) > > > > #endif /* CONFIG_PPC64 */ > > > > +#if defined(CONFIG_PPC32) || defined(CONFIG_COMPAT) > > /* > >* Layout for non-RT signal frames > >*/ > > @@ -482,6 +484,13 @@ static void perf_callchain_user_32(struct > > perf_callchain_entry_ctx *entry, > > sp = next_sp; > > } > > } > > +#else /* 32bit */ > > +static void perf_callchain_user_32(struct perf_callchain_entry_ctx *entry, > > + struct pt_regs *regs) > > +{ > > + (void)&read_user_stack_32; /* unused if !COMPAT */ > > That looks pretty much like a hack. > > See possible alternative below. > > > +} > > +#endif /* 32bit */ > > > > void > > perf_callchain_user(struct perf_callchain_entry_ctx *entry, struct > > pt_regs *regs) > > > > --- > arch/powerpc/perf/callchain.c | 62 > +++ > 1 file changed, 27 insertions(+), 35 deletions(-) > > diff --git a/arch/powerpc/perf/callchain.c b/arch/powerpc/perf/callchain.c > index 881be5c4e9bb..1b169b32776a 100644 > --- a/arch/powerpc/perf/callchain.c > +++ b/arch/powerpc/perf/callchain.c > @@ -165,22 +165,6 @@ static int read_user_stack_64(unsigned long __user *ptr, > unsigned long *ret) > return read_user_stack_slow(ptr, ret, 8); > } > > -static int read_user_stack_32(unsigned int __user *ptr, unsigned int *ret) > -{ > - if ((unsigned long)ptr > TASK_SIZE - sizeof(unsigned int) || > - ((unsigned long)ptr & 3)) > - return -EFAULT; > - > - pagefault_disable(); > - if (!__get_user_inatomic(*ret, ptr)) { > - pagefault_enable(); > - return 0; > - } > - pagefault_enable(); > - > - return read_user_stack_slow(ptr, ret, 4); > -} > - > static inline int valid_user_sp(unsigned long sp, int is_64) > { > if (!sp || (sp & 7) || sp > (is_64 ? TASK_SIZE : 0x1UL) - 32) > @@ -296,25 +280,10 @@ static inline int current_is_64bit(void) > } > > #else /* CONFIG_PPC64 */ > -/* > - * On 32-bit we just access the address and let hash_page create a > - * HPTE if necessary, so there is no need to fall back to reading > - * the page tables. Since this is called at interrupt level, > - * do_page_fault() won't treat a DSI as a page fault. > - */ > -static int read_user_stack_32(unsigned int __user *ptr, unsigned int *ret) > -{ > - int rc; > - > - if ((unsigned long)ptr > TASK_SIZE - sizeof(unsigned int) || > - ((unsigned long)ptr & 3)) > - return -EFAULT; > > - pagefault_disable(); > - rc = __get_user_inatomic(*ret, ptr); > - pagefault_enable(); > - > - return rc; > +static int read_user_stack_slow(void __user *ptr, void *buf, int n
Re: [PATCH] powerpc/mm: tell if a bad page fault on data is read or write.
Le 29/08/2019 à 14:14, Michael Ellerman a écrit : Christophe Leroy writes: DSISR has a bit to tell if the fault is due to a read or a write. Except some CPUs don't have a DSISR? Which is why we have page_fault_is_write() that's used in __do_page_fault(). And that's why I'm also using page_fault_is_write() in my patch. Or is that old cruft? I see eg. in head_40x.S we pass r5=0 for error code, and we don't set regs->dsisr anywhere AFAICS. So it might just contain some junk. We pass r5=0 in ISI but r5=SPRN_ESR in DSI. And r5 is also saved into _ESR(r11) And in asm-offset.c, we have: STACK_PT_REGS_OFFSET(_ESR, dsisr); So regs->dsisr has the expected content. Christophe cheers diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c index 8432c281de92..b5047f9b5dec 100644 --- a/arch/powerpc/mm/fault.c +++ b/arch/powerpc/mm/fault.c @@ -645,6 +645,7 @@ NOKPROBE_SYMBOL(do_page_fault); void bad_page_fault(struct pt_regs *regs, unsigned long address, int sig) { const struct exception_table_entry *entry; + int is_write = page_fault_is_write(regs->dsisr); /* Are we prepared to handle this fault? */ if ((entry = search_exception_tables(regs->nip)) != NULL) { @@ -658,9 +659,10 @@ void bad_page_fault(struct pt_regs *regs, unsigned long address, int sig) case 0x300: case 0x380: case 0xe00: - pr_alert("BUG: %s at 0x%08lx\n", + pr_alert("BUG: %s on %s at 0x%08lx\n", regs->dar < PAGE_SIZE ? "Kernel NULL pointer dereference" : -"Unable to handle kernel data access", regs->dar); +"Unable to handle kernel data access", +is_write ? "write" : "read", regs->dar); break; case 0x400: case 0x480: -- 2.13.3
Re: [PATCH v5 5/5] powerpc/perf: split callchain.c by bitness
Le 30/08/2019 à 09:12, Michal Suchánek a écrit : On Fri, 30 Aug 2019 08:42:25 +0200 Michal Suchánek wrote: On Fri, 30 Aug 2019 06:35:11 + (UTC) Christophe Leroy wrote: On 08/29/2019 10:28 PM, Michal Suchanek wrote: obj-$(CONFIG_PPC_PERF_CTRS) += core-book3s.o bhrb.o diff --git a/arch/powerpc/perf/callchain_32.c b/arch/powerpc/perf/callchain_32.c index 0bd4484eddaa..17c43ae03084 100644 --- a/arch/powerpc/perf/callchain_32.c +++ b/arch/powerpc/perf/callchain_32.c @@ -15,50 +15,13 @@ #include #include #include -#ifdef CONFIG_PPC64 -#include "../kernel/ppc32.h" -#endif #include #include "callchain.h" #ifdef CONFIG_PPC64 -static int read_user_stack_32(unsigned int __user *ptr, unsigned int *ret) -{ - if ((unsigned long)ptr > TASK_SIZE - sizeof(unsigned int) || - ((unsigned long)ptr & 3)) - return -EFAULT; - - pagefault_disable(); - if (!__get_user_inatomic(*ret, ptr)) { - pagefault_enable(); - return 0; - } - pagefault_enable(); - - return read_user_stack_slow(ptr, ret, 4); -} -#else /* CONFIG_PPC64 */ -/* - * On 32-bit we just access the address and let hash_page create a - * HPTE if necessary, so there is no need to fall back to reading - * the page tables. Since this is called at interrupt level, - * do_page_fault() won't treat a DSI as a page fault. - */ -static int read_user_stack_32(unsigned int __user *ptr, unsigned int *ret) -{ - int rc; - - if ((unsigned long)ptr > TASK_SIZE - sizeof(unsigned int) || - ((unsigned long)ptr & 3)) - return -EFAULT; - - pagefault_disable(); - rc = __get_user_inatomic(*ret, ptr); - pagefault_enable(); - - return rc; -} +#include "../kernel/ppc32.h" +#else #define __SIGNAL_FRAMESIZE32 __SIGNAL_FRAMESIZE #define sigcontext32 sigcontext @@ -95,6 +58,30 @@ struct rt_signal_frame_32 { int abigap[56]; }; +/* + * On 32-bit we just access the address and let hash_page create a + * HPTE if necessary, so there is no need to fall back to reading + * the page tables. Since this is called at interrupt level, + * do_page_fault() won't treat a DSI as a page fault. + */ +static int read_user_stack_32(unsigned int __user *ptr, unsigned int *ret) +{ + int rc; + + if ((unsigned long)ptr > TASK_SIZE - sizeof(unsigned int) || + ((unsigned long)ptr & 3)) + return -EFAULT; + + pagefault_disable(); + rc = __get_user_inatomic(*ret, ptr); + pagefault_enable(); + + if (IS_ENABLED(CONFIG_PPC32) || !rc) + return rc; + + return read_user_stack_slow(ptr, ret, 4); +} + static int is_sigreturn_32_address(unsigned int nip, unsigned int fp) { if (nip == fp + offsetof(struct signal_frame_32, mctx.mc_pad)) I will leave consolidating this function to somebody who knows what the desired semantic is. With a short ifdef section at the top of the file it is a low-hanging fruit. It looks ok if done as a separate patch. Yes, doing it as a separate patch is good. And if you do it before patch 3, then you don't need anymore this ugly hack to hide read_user_stack_32() Christphe Thanks Michal
Re: [PATCH v5 5/5] powerpc/perf: split callchain.c by bitness
On Fri, 30 Aug 2019 08:42:25 +0200 Michal Suchánek wrote: > On Fri, 30 Aug 2019 06:35:11 + (UTC) > Christophe Leroy wrote: > > > On 08/29/2019 10:28 PM, Michal Suchanek wrote: > > obj-$(CONFIG_PPC_PERF_CTRS)+= core-book3s.o bhrb.o > > diff --git a/arch/powerpc/perf/callchain_32.c > > b/arch/powerpc/perf/callchain_32.c > > index 0bd4484eddaa..17c43ae03084 100644 > > --- a/arch/powerpc/perf/callchain_32.c > > +++ b/arch/powerpc/perf/callchain_32.c > > @@ -15,50 +15,13 @@ > > #include > > #include > > #include > > -#ifdef CONFIG_PPC64 > > -#include "../kernel/ppc32.h" > > -#endif > > #include > > > > #include "callchain.h" > > > > #ifdef CONFIG_PPC64 > > -static int read_user_stack_32(unsigned int __user *ptr, unsigned int *ret) > > -{ > > - if ((unsigned long)ptr > TASK_SIZE - sizeof(unsigned int) || > > - ((unsigned long)ptr & 3)) > > - return -EFAULT; > > - > > - pagefault_disable(); > > - if (!__get_user_inatomic(*ret, ptr)) { > > - pagefault_enable(); > > - return 0; > > - } > > - pagefault_enable(); > > - > > - return read_user_stack_slow(ptr, ret, 4); > > -} > > -#else /* CONFIG_PPC64 */ > > -/* > > - * On 32-bit we just access the address and let hash_page create a > > - * HPTE if necessary, so there is no need to fall back to reading > > - * the page tables. Since this is called at interrupt level, > > - * do_page_fault() won't treat a DSI as a page fault. > > - */ > > -static int read_user_stack_32(unsigned int __user *ptr, unsigned int *ret) > > -{ > > - int rc; > > - > > - if ((unsigned long)ptr > TASK_SIZE - sizeof(unsigned int) || > > - ((unsigned long)ptr & 3)) > > - return -EFAULT; > > - > > - pagefault_disable(); > > - rc = __get_user_inatomic(*ret, ptr); > > - pagefault_enable(); > > - > > - return rc; > > -} > > +#include "../kernel/ppc32.h" > > +#else > > > > #define __SIGNAL_FRAMESIZE32 __SIGNAL_FRAMESIZE > > #define sigcontext32 sigcontext > > @@ -95,6 +58,30 @@ struct rt_signal_frame_32 { > > int abigap[56]; > > }; > > > > +/* > > + * On 32-bit we just access the address and let hash_page create a > > + * HPTE if necessary, so there is no need to fall back to reading > > + * the page tables. Since this is called at interrupt level, > > + * do_page_fault() won't treat a DSI as a page fault. > > + */ > > +static int read_user_stack_32(unsigned int __user *ptr, unsigned int *ret) > > +{ > > + int rc; > > + > > + if ((unsigned long)ptr > TASK_SIZE - sizeof(unsigned int) || > > + ((unsigned long)ptr & 3)) > > + return -EFAULT; > > + > > + pagefault_disable(); > > + rc = __get_user_inatomic(*ret, ptr); > > + pagefault_enable(); > > + > > + if (IS_ENABLED(CONFIG_PPC32) || !rc) > > + return rc; > > + > > + return read_user_stack_slow(ptr, ret, 4); > > +} > > + > > static int is_sigreturn_32_address(unsigned int nip, unsigned int fp) > > { > > if (nip == fp + offsetof(struct signal_frame_32, mctx.mc_pad)) > > I will leave consolidating this function to somebody who knows what the > desired semantic is. With a short ifdef section at the top of the file > it is a low-hanging fruit. It looks ok if done as a separate patch. Thanks Michal