From 320c90be7ba1c371e882edff57272a89b213d136 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 5 Sep 2013 11:33:15 +0200 Subject: [PATCH 1/7] parisc: Export flush_cache_page() (needed by lustre) ERROR: "flush_cache_page" [drivers/staging/lustre/lustre/libcfs/libcfs.ko] undefined! Signed-off-by: Geert Uytterhoeven Signed-off-by: Helge Deller --- arch/parisc/kernel/cache.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c index c035673209f7..b521c0adf4ec 100644 --- a/arch/parisc/kernel/cache.c +++ b/arch/parisc/kernel/cache.c @@ -602,6 +602,7 @@ flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long __flush_cache_page(vma, vmaddr, PFN_PHYS(pfn)); } } +EXPORT_SYMBOL_GPL(flush_cache_page); #ifdef CONFIG_PARISC_TMPALIAS From 528d8eb20a3053d72cb0cea486418aa602d9e1f1 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Thu, 12 Sep 2013 00:07:18 +0800 Subject: [PATCH 2/7] parisc: kill SMP single function call interrupt Commit 9a46ad6d6df3b54 "smp: make smp_call_function_many() use logic similar to smp_call_function_single()" has unified the way to handle single and multiple cross-CPU function calls. Now only one interrupt is needed for architecture specific code to support generic SMP function call interfaces, so kill the redundant single function call interrupt. Signed-off-by: Jiang Liu Cc: Jiang Liu Signed-off-by: Helge Deller --- arch/parisc/kernel/smp.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c index 8a252f2d6c08..2b96602e812f 100644 --- a/arch/parisc/kernel/smp.c +++ b/arch/parisc/kernel/smp.c @@ -72,7 +72,6 @@ enum ipi_message_type { IPI_NOP=0, IPI_RESCHEDULE=1, IPI_CALL_FUNC, - IPI_CALL_FUNC_SINGLE, IPI_CPU_START, IPI_CPU_STOP, IPI_CPU_TEST @@ -164,11 +163,6 @@ ipi_interrupt(int irq, void *dev_id) generic_smp_call_function_interrupt(); break; - case IPI_CALL_FUNC_SINGLE: - smp_debug(100, KERN_DEBUG "CPU%d IPI_CALL_FUNC_SINGLE\n", this_cpu); - generic_smp_call_function_single_interrupt(); - break; - case IPI_CPU_START: smp_debug(100, KERN_DEBUG "CPU%d IPI_CPU_START\n", this_cpu); break; @@ -260,7 +254,7 @@ void arch_send_call_function_ipi_mask(const struct cpumask *mask) void arch_send_call_function_single_ipi(int cpu) { - send_IPI_single(cpu, IPI_CALL_FUNC_SINGLE); + send_IPI_single(cpu, IPI_CALL_FUNC); } /* From ec7c241953d14af097d941de56348c55e4e9ac5d Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Wed, 9 Oct 2013 23:10:14 +0200 Subject: [PATCH 3/7] parisc: remove unused syscall_ipi() function. Signed-off-by: Helge Deller --- arch/parisc/kernel/traps.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c index 04e47c6a4562..ebc877c28583 100644 --- a/arch/parisc/kernel/traps.c +++ b/arch/parisc/kernel/traps.c @@ -291,11 +291,6 @@ void die_if_kernel(char *str, struct pt_regs *regs, long err) do_exit(SIGSEGV); } -int syscall_ipi(int (*syscall) (struct pt_regs *), struct pt_regs *regs) -{ - return syscall(regs); -} - /* gdb uses break 4,8 */ #define GDB_BREAK_INSN 0x10004 static void handle_gdb_break(struct pt_regs *regs, int wot) From a60ac4b5f0b630889a01293db52ac65003a01e98 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Wed, 9 Oct 2013 23:12:46 +0200 Subject: [PATCH 4/7] parisc: mark parisc_terminate() noreturn and cold. Signed-off-by: Helge Deller --- arch/parisc/include/asm/traps.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/parisc/include/asm/traps.h b/arch/parisc/include/asm/traps.h index 1945f995f2df..4736020ba5ea 100644 --- a/arch/parisc/include/asm/traps.h +++ b/arch/parisc/include/asm/traps.h @@ -6,7 +6,7 @@ struct pt_regs; /* traps.c */ void parisc_terminate(char *msg, struct pt_regs *regs, - int code, unsigned long offset); + int code, unsigned long offset) __noreturn __cold; /* mm/fault.c */ void do_page_fault(struct pt_regs *regs, unsigned long code, From 59b33f148cc08fb33cbe823fca1e34f7f023765e Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Tue, 1 Oct 2013 21:54:46 +0200 Subject: [PATCH 5/7] parisc: fix interruption handler to respect pagefault_disable() Running an "echo t > /proc/sysrq-trigger" crashes the parisc kernel. The problem is, that in print_worker_info() we try to read the workqueue info via the probe_kernel_read() functions which use pagefault_disable() to avoid crashes like this: probe_kernel_read(&pwq, &worker->current_pwq, sizeof(pwq)); probe_kernel_read(&wq, &pwq->wq, sizeof(wq)); probe_kernel_read(name, wq->name, sizeof(name) - 1); The problem here is, that the first probe_kernel_read(&pwq) might return zero in pwq and as such the following probe_kernel_reads() try to access contents of the page zero which is read protected and generate a kernel segfault. With this patch we fix the interruption handler to call parisc_terminate() directly only if pagefault_disable() was not called (in which case preempt_count()==0). Otherwise we hand over to the pagefault handler which will try to look up the faulting address in the fixup tables. Signed-off-by: Helge Deller Cc: # v3.0+ Signed-off-by: John David Anglin Signed-off-by: Helge Deller --- arch/parisc/kernel/traps.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c index ebc877c28583..1cd1d0c83b6d 100644 --- a/arch/parisc/kernel/traps.c +++ b/arch/parisc/kernel/traps.c @@ -800,14 +800,14 @@ void notrace handle_interruption(int code, struct pt_regs *regs) else { /* - * The kernel should never fault on its own address space. + * The kernel should never fault on its own address space, + * unless pagefault_disable() was called before. */ - if (fault_space == 0) + if (fault_space == 0 && !in_atomic()) { pdc_chassis_send_status(PDC_CHASSIS_DIRECT_PANIC); parisc_terminate("Kernel Fault", regs, code, fault_address); - } } From 2d8b22de6e5241a6f27f7f290f027223156a7d3f Mon Sep 17 00:00:00 2001 From: John David Anglin Date: Sat, 5 Oct 2013 10:55:36 -0400 Subject: [PATCH 6/7] parisc: optimize variable initialization in do_page_fault The attached change defers the initialization of the variables tsk, mm and flags until they are needed. As a result, the code won't crash if a kernel probe is done with a corrupt context and the code will be better optimized. Signed-off-by: John David Anglin Signed-off-by: Helge Deller --- arch/parisc/mm/fault.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/arch/parisc/mm/fault.c b/arch/parisc/mm/fault.c index 00c0ed333a3d..0293588d5b8c 100644 --- a/arch/parisc/mm/fault.c +++ b/arch/parisc/mm/fault.c @@ -171,20 +171,25 @@ void do_page_fault(struct pt_regs *regs, unsigned long code, unsigned long address) { struct vm_area_struct *vma, *prev_vma; - struct task_struct *tsk = current; - struct mm_struct *mm = tsk->mm; + struct task_struct *tsk; + struct mm_struct *mm; unsigned long acc_type; int fault; - unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; + unsigned int flags; - if (in_atomic() || !mm) + if (in_atomic()) goto no_context; + tsk = current; + mm = tsk->mm; + if (!mm) + goto no_context; + + flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; if (user_mode(regs)) flags |= FAULT_FLAG_USER; acc_type = parisc_acctyp(code, regs->iir); - if (acc_type & VM_WRITE) flags |= FAULT_FLAG_WRITE; retry: From db080f9c530f78dad661257885a1893506077068 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Wed, 9 Oct 2013 23:47:03 +0200 Subject: [PATCH 7/7] parisc: let probe_kernel_read() capture access to page zero Signed-off-by: Helge Deller --- arch/parisc/lib/memcpy.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/arch/parisc/lib/memcpy.c b/arch/parisc/lib/memcpy.c index ac4370b1ca40..b5507ec06b84 100644 --- a/arch/parisc/lib/memcpy.c +++ b/arch/parisc/lib/memcpy.c @@ -56,7 +56,7 @@ #ifdef __KERNEL__ #include #include -#include +#include #define s_space "%%sr1" #define d_space "%%sr2" #else @@ -524,4 +524,17 @@ EXPORT_SYMBOL(copy_to_user); EXPORT_SYMBOL(copy_from_user); EXPORT_SYMBOL(copy_in_user); EXPORT_SYMBOL(memcpy); + +long probe_kernel_read(void *dst, const void *src, size_t size) +{ + unsigned long addr = (unsigned long)src; + + if (size < 0 || addr < PAGE_SIZE) + return -EFAULT; + + /* check for I/O space F_EXTEND(0xfff00000) access as well? */ + + return __probe_kernel_read(dst, src, size); +} + #endif