diff options
Diffstat (limited to 'arch/xtensa/kernel')
-rw-r--r-- | arch/xtensa/kernel/coprocessor.S | 24 | ||||
-rw-r--r-- | arch/xtensa/kernel/entry.S | 3 | ||||
-rw-r--r-- | arch/xtensa/kernel/pci.c | 24 | ||||
-rw-r--r-- | arch/xtensa/kernel/process.c | 8 | ||||
-rw-r--r-- | arch/xtensa/kernel/ptrace.c | 170 | ||||
-rw-r--r-- | arch/xtensa/kernel/setup.c | 9 | ||||
-rw-r--r-- | arch/xtensa/kernel/signal.c | 10 | ||||
-rw-r--r-- | arch/xtensa/kernel/stacktrace.c | 35 |
8 files changed, 103 insertions, 180 deletions
diff --git a/arch/xtensa/kernel/coprocessor.S b/arch/xtensa/kernel/coprocessor.S index 6911e384f608..3a98503ad11a 100644 --- a/arch/xtensa/kernel/coprocessor.S +++ b/arch/xtensa/kernel/coprocessor.S @@ -26,30 +26,6 @@ #include <asm/signal.h> #include <asm/tlbflush.h> -/* - * Entry condition: - * - * a0: trashed, original value saved on stack (PT_AREG0) - * a1: a1 - * a2: new stack pointer, original in DEPC - * a3: a3 - * depc: a2, original value saved on stack (PT_DEPC) - * excsave_1: dispatch table - * - * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC - * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception - */ - -/* IO protection is currently unsupported. */ - -ENTRY(fast_io_protect) - - wsr a0, excsave1 - movi a0, unrecoverable_exception - callx0 a0 - -ENDPROC(fast_io_protect) - #if XTENSA_HAVE_COPROCESSORS /* diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S index f5ef3cc0497c..37a239556889 100644 --- a/arch/xtensa/kernel/entry.S +++ b/arch/xtensa/kernel/entry.S @@ -1899,10 +1899,11 @@ ENTRY(system_call) movi a4, do_syscall_trace_enter s32i a3, a2, PT_SYSCALL callx4 a4 + mov a3, a6 /* syscall = sys_call_table[syscall_nr] */ - movi a4, sys_call_table; + movi a4, sys_call_table movi a5, __NR_syscall_count movi a6, -ENOSYS bgeu a3, a5, 1f diff --git a/arch/xtensa/kernel/pci.c b/arch/xtensa/kernel/pci.c index b848cc3dc913..903963ee495d 100644 --- a/arch/xtensa/kernel/pci.c +++ b/arch/xtensa/kernel/pci.c @@ -334,25 +334,6 @@ __pci_mmap_make_offset(struct pci_dev *dev, struct vm_area_struct *vma, } /* - * Set vm_page_prot of VMA, as appropriate for this architecture, for a pci - * device mapping. - */ -static __inline__ void -__pci_mmap_set_pgprot(struct pci_dev *dev, struct vm_area_struct *vma, - enum pci_mmap_state mmap_state, int write_combine) -{ - int prot = pgprot_val(vma->vm_page_prot); - - /* Set to write-through */ - prot = (prot & _PAGE_CA_MASK) | _PAGE_CA_WT; -#if 0 - if (!write_combine) - prot |= _PAGE_WRITETHRU; -#endif - vma->vm_page_prot = __pgprot(prot); -} - -/* * Perform the actual remap of the pages for a PCI device mapping, as * appropriate for this architecture. The region in the process to map * is described by vm_start and vm_end members of VMA, the base physical @@ -362,7 +343,8 @@ __pci_mmap_set_pgprot(struct pci_dev *dev, struct vm_area_struct *vma, * * Returns a negative error code on failure, zero on success. */ -int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, +int pci_mmap_page_range(struct pci_dev *dev, int bar, + struct vm_area_struct *vma, enum pci_mmap_state mmap_state, int write_combine) { @@ -372,7 +354,7 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, if (ret < 0) return ret; - __pci_mmap_set_pgprot(dev, vma, mmap_state, write_combine); + vma->vm_page_prot = pgprot_device(vma->vm_page_prot); ret = io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, vma->vm_end - vma->vm_start,vma->vm_page_prot); diff --git a/arch/xtensa/kernel/process.c b/arch/xtensa/kernel/process.c index 58f96d1230d4..ff4f0ecb03dd 100644 --- a/arch/xtensa/kernel/process.c +++ b/arch/xtensa/kernel/process.c @@ -204,8 +204,8 @@ int copy_thread(unsigned long clone_flags, unsigned long usp_thread_fn, #endif /* Create a call4 dummy-frame: a0 = 0, a1 = childregs. */ - *((int*)childregs - 3) = (unsigned long)childregs; - *((int*)childregs - 4) = 0; + SPILL_SLOT(childregs, 1) = (unsigned long)childregs; + SPILL_SLOT(childregs, 0) = 0; p->thread.sp = (unsigned long)childregs; @@ -266,8 +266,8 @@ int copy_thread(unsigned long clone_flags, unsigned long usp_thread_fn, /* pass parameters to ret_from_kernel_thread: * a2 = thread_fn, a3 = thread_fn arg */ - *((int *)childregs - 1) = thread_fn_arg; - *((int *)childregs - 2) = usp_thread_fn; + SPILL_SLOT(childregs, 3) = thread_fn_arg; + SPILL_SLOT(childregs, 2) = usp_thread_fn; /* Childregs are only used when we're going to userspace * in which case start_thread will set them up. diff --git a/arch/xtensa/kernel/ptrace.c b/arch/xtensa/kernel/ptrace.c index e0f583fed06a..e2461968efb2 100644 --- a/arch/xtensa/kernel/ptrace.c +++ b/arch/xtensa/kernel/ptrace.c @@ -1,4 +1,3 @@ -// TODO some minor issues /* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -24,13 +23,14 @@ #include <linux/security.h> #include <linux/signal.h> #include <linux/smp.h> +#include <linux/tracehook.h> +#include <linux/uaccess.h> #include <asm/coprocessor.h> #include <asm/elf.h> #include <asm/page.h> #include <asm/pgtable.h> #include <asm/ptrace.h> -#include <linux/uaccess.h> void user_enable_single_step(struct task_struct *child) @@ -52,7 +52,7 @@ void ptrace_disable(struct task_struct *child) /* Nothing to do.. */ } -int ptrace_getregs(struct task_struct *child, void __user *uregs) +static int ptrace_getregs(struct task_struct *child, void __user *uregs) { struct pt_regs *regs = task_pt_regs(child); xtensa_gregset_t __user *gregset = uregs; @@ -73,12 +73,12 @@ int ptrace_getregs(struct task_struct *child, void __user *uregs) for (i = 0; i < XCHAL_NUM_AREGS; i++) __put_user(regs->areg[i], - gregset->a + ((wb * 4 + i) % XCHAL_NUM_AREGS)); + gregset->a + ((wb * 4 + i) % XCHAL_NUM_AREGS)); return 0; } -int ptrace_setregs(struct task_struct *child, void __user *uregs) +static int ptrace_setregs(struct task_struct *child, void __user *uregs) { struct pt_regs *regs = task_pt_regs(child); xtensa_gregset_t *gregset = uregs; @@ -107,7 +107,7 @@ int ptrace_setregs(struct task_struct *child, void __user *uregs) unsigned long rotws, wmask; rotws = (((ws | (ws << WSBITS)) >> wb) & - ((1 << WSBITS) - 1)) & ~1; + ((1 << WSBITS) - 1)) & ~1; wmask = ((rotws ? WSBITS + 1 - ffs(rotws) : 0) << 4) | (rotws & 0xF) | 1; regs->windowbase = wb; @@ -115,19 +115,19 @@ int ptrace_setregs(struct task_struct *child, void __user *uregs) regs->wmask = wmask; } - if (wb != 0 && __copy_from_user(regs->areg + XCHAL_NUM_AREGS - wb * 4, - gregset->a, wb * 16)) + if (wb != 0 && __copy_from_user(regs->areg + XCHAL_NUM_AREGS - wb * 4, + gregset->a, wb * 16)) return -EFAULT; if (__copy_from_user(regs->areg, gregset->a + wb * 4, - (WSBITS - wb) * 16)) + (WSBITS - wb) * 16)) return -EFAULT; return 0; } -int ptrace_getxregs(struct task_struct *child, void __user *uregs) +static int ptrace_getxregs(struct task_struct *child, void __user *uregs) { struct pt_regs *regs = task_pt_regs(child); struct thread_info *ti = task_thread_info(child); @@ -151,7 +151,7 @@ int ptrace_getxregs(struct task_struct *child, void __user *uregs) return ret ? -EFAULT : 0; } -int ptrace_setxregs(struct task_struct *child, void __user *uregs) +static int ptrace_setxregs(struct task_struct *child, void __user *uregs) { struct thread_info *ti = task_thread_info(child); struct pt_regs *regs = task_pt_regs(child); @@ -177,7 +177,8 @@ int ptrace_setxregs(struct task_struct *child, void __user *uregs) return ret ? -EFAULT : 0; } -int ptrace_peekusr(struct task_struct *child, long regno, long __user *ret) +static int ptrace_peekusr(struct task_struct *child, long regno, + long __user *ret) { struct pt_regs *regs; unsigned long tmp; @@ -186,86 +187,87 @@ int ptrace_peekusr(struct task_struct *child, long regno, long __user *ret) tmp = 0; /* Default return value. */ switch(regno) { + case REG_AR_BASE ... REG_AR_BASE + XCHAL_NUM_AREGS - 1: + tmp = regs->areg[regno - REG_AR_BASE]; + break; - case REG_AR_BASE ... REG_AR_BASE + XCHAL_NUM_AREGS - 1: - tmp = regs->areg[regno - REG_AR_BASE]; - break; - - case REG_A_BASE ... REG_A_BASE + 15: - tmp = regs->areg[regno - REG_A_BASE]; - break; + case REG_A_BASE ... REG_A_BASE + 15: + tmp = regs->areg[regno - REG_A_BASE]; + break; - case REG_PC: - tmp = regs->pc; - break; + case REG_PC: + tmp = regs->pc; + break; - case REG_PS: - /* Note: PS.EXCM is not set while user task is running; - * its being set in regs is for exception handling - * convenience. */ - tmp = (regs->ps & ~(1 << PS_EXCM_BIT)); - break; + case REG_PS: + /* Note: PS.EXCM is not set while user task is running; + * its being set in regs is for exception handling + * convenience. + */ + tmp = (regs->ps & ~(1 << PS_EXCM_BIT)); + break; - case REG_WB: - break; /* tmp = 0 */ + case REG_WB: + break; /* tmp = 0 */ - case REG_WS: + case REG_WS: { unsigned long wb = regs->windowbase; unsigned long ws = regs->windowstart; - tmp = ((ws>>wb) | (ws<<(WSBITS-wb))) & ((1<<WSBITS)-1); + tmp = ((ws >> wb) | (ws << (WSBITS - wb))) & + ((1 << WSBITS) - 1); break; } - case REG_LBEG: - tmp = regs->lbeg; - break; + case REG_LBEG: + tmp = regs->lbeg; + break; - case REG_LEND: - tmp = regs->lend; - break; + case REG_LEND: + tmp = regs->lend; + break; - case REG_LCOUNT: - tmp = regs->lcount; - break; + case REG_LCOUNT: + tmp = regs->lcount; + break; - case REG_SAR: - tmp = regs->sar; - break; + case REG_SAR: + tmp = regs->sar; + break; - case SYSCALL_NR: - tmp = regs->syscall; - break; + case SYSCALL_NR: + tmp = regs->syscall; + break; - default: - return -EIO; + default: + return -EIO; } return put_user(tmp, ret); } -int ptrace_pokeusr(struct task_struct *child, long regno, long val) +static int ptrace_pokeusr(struct task_struct *child, long regno, long val) { struct pt_regs *regs; regs = task_pt_regs(child); switch (regno) { - case REG_AR_BASE ... REG_AR_BASE + XCHAL_NUM_AREGS - 1: - regs->areg[regno - REG_AR_BASE] = val; - break; + case REG_AR_BASE ... REG_AR_BASE + XCHAL_NUM_AREGS - 1: + regs->areg[regno - REG_AR_BASE] = val; + break; - case REG_A_BASE ... REG_A_BASE + 15: - regs->areg[regno - REG_A_BASE] = val; - break; + case REG_A_BASE ... REG_A_BASE + 15: + regs->areg[regno - REG_A_BASE] = val; + break; - case REG_PC: - regs->pc = val; - break; + case REG_PC: + regs->pc = val; + break; - case SYSCALL_NR: - regs->syscall = val; - break; + case SYSCALL_NR: + regs->syscall = val; + break; - default: - return -EIO; + default: + return -EIO; } return 0; } @@ -467,39 +469,21 @@ long arch_ptrace(struct task_struct *child, long request, return ret; } -void do_syscall_trace(void) -{ - /* - * The 0x80 provides a way for the tracing parent to distinguish - * between a syscall stop and SIGTRAP delivery - */ - ptrace_notify(SIGTRAP|((current->ptrace & PT_TRACESYSGOOD) ? 0x80 : 0)); - - /* - * this isn't the same as continuing with a signal, but it will do - * for normal use. strace only continues with a signal if the - * stopping signal is not SIGTRAP. -brl - */ - if (current->exit_code) { - send_sig(current->exit_code, current, 1); - current->exit_code = 0; - } -} - -void do_syscall_trace_enter(struct pt_regs *regs) +unsigned long do_syscall_trace_enter(struct pt_regs *regs) { - if (test_thread_flag(TIF_SYSCALL_TRACE) - && (current->ptrace & PT_PTRACED)) - do_syscall_trace(); + if (test_thread_flag(TIF_SYSCALL_TRACE) && + tracehook_report_syscall_entry(regs)) + return -1; -#if 0 - audit_syscall_entry(...); -#endif + return regs->areg[2]; } void do_syscall_trace_leave(struct pt_regs *regs) { - if ((test_thread_flag(TIF_SYSCALL_TRACE)) - && (current->ptrace & PT_PTRACED)) - do_syscall_trace(); + int step; + + step = test_thread_flag(TIF_SINGLESTEP); + + if (step || test_thread_flag(TIF_SYSCALL_TRACE)) + tracehook_report_syscall_exit(regs, step); } diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c index 460a226699b4..33bfa5270d95 100644 --- a/arch/xtensa/kernel/setup.c +++ b/arch/xtensa/kernel/setup.c @@ -317,8 +317,9 @@ static inline int mem_reserve(unsigned long start, unsigned long end) void __init setup_arch(char **cmdline_p) { - strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE); *cmdline_p = command_line; + platform_setup(cmdline_p); + strlcpy(boot_command_line, *cmdline_p, COMMAND_LINE_SIZE); /* Reserve some memory regions */ @@ -382,8 +383,6 @@ void __init setup_arch(char **cmdline_p) unflatten_and_copy_device_tree(); - platform_setup(cmdline_p); - #ifdef CONFIG_SMP smp_init_cpus(); #endif @@ -453,9 +452,9 @@ void cpu_reset(void) tmpaddr += SZ_512M; /* Invalidate mapping in the selected temporary area */ - if (itlb_probe(tmpaddr) & 0x8) + if (itlb_probe(tmpaddr) & BIT(ITLB_HIT_BIT)) invalidate_itlb_entry(itlb_probe(tmpaddr)); - if (itlb_probe(tmpaddr + PAGE_SIZE) & 0x8) + if (itlb_probe(tmpaddr + PAGE_SIZE) & BIT(ITLB_HIT_BIT)) invalidate_itlb_entry(itlb_probe(tmpaddr + PAGE_SIZE)); /* diff --git a/arch/xtensa/kernel/signal.c b/arch/xtensa/kernel/signal.c index 70a131945443..d427e784ab44 100644 --- a/arch/xtensa/kernel/signal.c +++ b/arch/xtensa/kernel/signal.c @@ -91,14 +91,14 @@ flush_window_regs_user(struct pt_regs *regs) inc = 1; } else if (m & 4) { /* call8 */ - if (copy_to_user((void*)(sp - 32), - ®s->areg[(base + 1) * 4], 16)) + if (copy_to_user(&SPILL_SLOT_CALL8(sp, 4), + ®s->areg[(base + 1) * 4], 16)) goto errout; inc = 2; } else if (m & 8) { /* call12 */ - if (copy_to_user((void*)(sp - 48), - ®s->areg[(base + 1) * 4], 32)) + if (copy_to_user(&SPILL_SLOT_CALL12(sp, 4), + ®s->areg[(base + 1) * 4], 32)) goto errout; inc = 3; } @@ -106,7 +106,7 @@ flush_window_regs_user(struct pt_regs *regs) /* Save current frame a0..a3 under next SP */ sp = regs->areg[((base + inc) * 4 + 1) % XCHAL_NUM_AREGS]; - if (copy_to_user((void*)(sp - 16), ®s->areg[base * 4], 16)) + if (copy_to_user(&SPILL_SLOT(sp, 0), ®s->areg[base * 4], 16)) goto errout; /* Get current stack pointer for next loop iteration. */ diff --git a/arch/xtensa/kernel/stacktrace.c b/arch/xtensa/kernel/stacktrace.c index e7d30ee0fd48..0df4080fa20f 100644 --- a/arch/xtensa/kernel/stacktrace.c +++ b/arch/xtensa/kernel/stacktrace.c @@ -23,14 +23,6 @@ */ extern int common_exception_return; -/* A struct that maps to the part of the frame containing the a0 and - * a1 registers. - */ -struct frame_start { - unsigned long a0; - unsigned long a1; -}; - void xtensa_backtrace_user(struct pt_regs *regs, unsigned int depth, int (*ufn)(struct stackframe *frame, void *data), void *data) @@ -96,26 +88,16 @@ void xtensa_backtrace_user(struct pt_regs *regs, unsigned int depth, /* Start from the a1 register. */ /* a1 = regs->areg[1]; */ while (a0 != 0 && depth--) { - struct frame_start frame_start; - /* Get the location for a1, a0 for the - * previous frame from the current a1. - */ - unsigned long *psp = (unsigned long *)a1; - - psp -= 4; + pc = MAKE_PC_FROM_RA(a0, pc); /* Check if the region is OK to access. */ - if (!access_ok(VERIFY_READ, psp, sizeof(frame_start))) + if (!access_ok(VERIFY_READ, &SPILL_SLOT(a1, 0), 8)) return; /* Copy a1, a0 from user space stack frame. */ - if (__copy_from_user_inatomic(&frame_start, psp, - sizeof(frame_start))) + if (__get_user(a0, &SPILL_SLOT(a1, 0)) || + __get_user(a1, &SPILL_SLOT(a1, 1))) return; - pc = MAKE_PC_FROM_RA(a0, pc); - a0 = frame_start.a0; - a1 = frame_start.a1; - frame.pc = pc; frame.sp = a1; @@ -147,7 +129,6 @@ void xtensa_backtrace_kernel(struct pt_regs *regs, unsigned int depth, */ while (a1 > sp_start && a1 < sp_end && depth--) { struct stackframe frame; - unsigned long *psp = (unsigned long *)a1; frame.pc = pc; frame.sp = a1; @@ -171,8 +152,8 @@ void xtensa_backtrace_kernel(struct pt_regs *regs, unsigned int depth, sp_start = a1; pc = MAKE_PC_FROM_RA(a0, pc); - a0 = *(psp - 4); - a1 = *(psp - 3); + a0 = SPILL_SLOT(a1, 0); + a1 = SPILL_SLOT(a1, 1); } } EXPORT_SYMBOL(xtensa_backtrace_kernel); @@ -196,8 +177,8 @@ void walk_stackframe(unsigned long *sp, sp = (unsigned long *)a1; - a0 = *(sp - 4); - a1 = *(sp - 3); + a0 = SPILL_SLOT(a1, 0); + a1 = SPILL_SLOT(a1, 1); if (a1 <= (unsigned long)sp) break; |