diff options
Diffstat (limited to 'arch/xtensa')
-rw-r--r-- | arch/xtensa/include/asm/Kbuild | 1 | ||||
-rw-r--r-- | arch/xtensa/include/asm/asm-uaccess.h | 3 | ||||
-rw-r--r-- | arch/xtensa/include/asm/pci.h | 7 | ||||
-rw-r--r-- | arch/xtensa/include/asm/processor.h | 15 | ||||
-rw-r--r-- | arch/xtensa/include/asm/ptrace.h | 39 | ||||
-rw-r--r-- | arch/xtensa/include/asm/uaccess.h | 67 | ||||
-rw-r--r-- | arch/xtensa/include/uapi/asm/Kbuild | 23 | ||||
-rw-r--r-- | arch/xtensa/include/uapi/asm/ptrace.h | 40 | ||||
-rw-r--r-- | arch/xtensa/include/uapi/asm/socket.h | 6 | ||||
-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 | ||||
-rw-r--r-- | arch/xtensa/lib/usercopy.S | 116 | ||||
-rw-r--r-- | arch/xtensa/platforms/iss/include/platform/simcall.h | 20 | ||||
-rw-r--r-- | arch/xtensa/platforms/iss/setup.c | 43 |
20 files changed, 266 insertions, 397 deletions
diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild index f41408c53fe1..cc23e9ecc6bb 100644 --- a/arch/xtensa/include/asm/Kbuild +++ b/arch/xtensa/include/asm/Kbuild @@ -6,6 +6,7 @@ generic-y += dma-contiguous.h generic-y += emergency-restart.h generic-y += errno.h generic-y += exec.h +generic-y += extable.h generic-y += fcntl.h generic-y += hardirq.h generic-y += ioctl.h diff --git a/arch/xtensa/include/asm/asm-uaccess.h b/arch/xtensa/include/asm/asm-uaccess.h index a7a110039786..dfdf9fae1f84 100644 --- a/arch/xtensa/include/asm/asm-uaccess.h +++ b/arch/xtensa/include/asm/asm-uaccess.h @@ -19,9 +19,6 @@ #include <linux/errno.h> #include <asm/types.h> -#define VERIFY_READ 0 -#define VERIFY_WRITE 1 - #include <asm/current.h> #include <asm/asm-offsets.h> #include <asm/processor.h> diff --git a/arch/xtensa/include/asm/pci.h b/arch/xtensa/include/asm/pci.h index 5d6bd932ba4e..e4f366a488d3 100644 --- a/arch/xtensa/include/asm/pci.h +++ b/arch/xtensa/include/asm/pci.h @@ -46,12 +46,9 @@ struct pci_dev; #define PCI_DMA_BUS_IS_PHYS (1) -/* Map a range of PCI memory or I/O space for a device into user space */ -int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma, - enum pci_mmap_state mmap_state, int write_combine); - /* Tell drivers/pci/proc.c that we have pci_mmap_page_range() */ -#define HAVE_PCI_MMAP 1 +#define HAVE_PCI_MMAP 1 +#define arch_can_pci_mmap_io() 1 #endif /* __KERNEL__ */ diff --git a/arch/xtensa/include/asm/processor.h b/arch/xtensa/include/asm/processor.h index 86ffcd68e496..003eeee3fbc6 100644 --- a/arch/xtensa/include/asm/processor.h +++ b/arch/xtensa/include/asm/processor.h @@ -113,6 +113,21 @@ */ #define MAKE_PC_FROM_RA(ra,sp) (((ra) & 0x3fffffff) | ((sp) & 0xc0000000)) +/* Spill slot location for the register reg in the spill area under the stack + * pointer sp. reg must be in the range [0..4). + */ +#define SPILL_SLOT(sp, reg) (*(((unsigned long *)(sp)) - 4 + (reg))) + +/* Spill slot location for the register reg in the spill area under the stack + * pointer sp for the call8. reg must be in the range [4..8). + */ +#define SPILL_SLOT_CALL8(sp, reg) (*(((unsigned long *)(sp)) - 12 + (reg))) + +/* Spill slot location for the register reg in the spill area under the stack + * pointer sp for the call12. reg must be in the range [4..12). + */ +#define SPILL_SLOT_CALL12(sp, reg) (*(((unsigned long *)(sp)) - 16 + (reg))) + typedef struct { unsigned long seg; } mm_segment_t; diff --git a/arch/xtensa/include/asm/ptrace.h b/arch/xtensa/include/asm/ptrace.h index 598e752dcbcd..e2d9c5eb10bd 100644 --- a/arch/xtensa/include/asm/ptrace.h +++ b/arch/xtensa/include/asm/ptrace.h @@ -12,6 +12,45 @@ #include <uapi/asm/ptrace.h> +/* + * Kernel stack + * + * +-----------------------+ -------- STACK_SIZE + * | register file | | + * +-----------------------+ | + * | struct pt_regs | | + * +-----------------------+ | ------ PT_REGS_OFFSET + * double : 16 bytes spill area : | ^ + * excetion :- - - - - - - - - - - -: | | + * frame : struct pt_regs : | | + * :- - - - - - - - - - - -: | | + * | | | | + * | memory stack | | | + * | | | | + * ~ ~ ~ ~ + * ~ ~ ~ ~ + * | | | | + * | | | | + * +-----------------------+ | | --- STACK_BIAS + * | struct task_struct | | | ^ + * current --> +-----------------------+ | | | + * | struct thread_info | | | | + * +-----------------------+ -------- + */ + +#define KERNEL_STACK_SIZE (2 * PAGE_SIZE) + +/* Offsets for exception_handlers[] (3 x 64-entries x 4-byte tables). */ + +#define EXC_TABLE_KSTK 0x004 /* Kernel Stack */ +#define EXC_TABLE_DOUBLE_SAVE 0x008 /* Double exception save area for a0 */ +#define EXC_TABLE_FIXUP 0x00c /* Fixup handler */ +#define EXC_TABLE_PARAM 0x010 /* For passing a parameter to fixup */ +#define EXC_TABLE_SYSCALL_SAVE 0x014 /* For fast syscall handler */ +#define EXC_TABLE_FAST_USER 0x100 /* Fast user exception handler */ +#define EXC_TABLE_FAST_KERNEL 0x200 /* Fast kernel exception handler */ +#define EXC_TABLE_DEFAULT 0x300 /* Default C-Handler */ +#define EXC_TABLE_SIZE 0x400 #ifndef __ASSEMBLY__ diff --git a/arch/xtensa/include/asm/uaccess.h b/arch/xtensa/include/asm/uaccess.h index 848a3d736bcb..2e7bac0d4b2c 100644 --- a/arch/xtensa/include/asm/uaccess.h +++ b/arch/xtensa/include/asm/uaccess.h @@ -16,14 +16,9 @@ #ifndef _XTENSA_UACCESS_H #define _XTENSA_UACCESS_H -#include <linux/errno.h> #include <linux/prefetch.h> #include <asm/types.h> - -#define VERIFY_READ 0 -#define VERIFY_WRITE 1 - -#include <linux/sched.h> +#include <asm/extable.h> /* * The fs value determines whether argument validity checking should @@ -43,7 +38,7 @@ #define segment_eq(a, b) ((a).seg == (b).seg) -#define __kernel_ok (segment_eq(get_fs(), KERNEL_DS)) +#define __kernel_ok (uaccess_kernel()) #define __user_ok(addr, size) \ (((size) <= TASK_SIZE)&&((addr) <= TASK_SIZE-(size))) #define __access_ok(addr, size) (__kernel_ok || __user_ok((addr), (size))) @@ -239,60 +234,22 @@ __asm__ __volatile__( \ * Copy to/from user space */ -/* - * We use a generic, arbitrary-sized copy subroutine. The Xtensa - * architecture would cause heavy code bloat if we tried to inline - * these functions and provide __constant_copy_* equivalents like the - * i386 versions. __xtensa_copy_user is quite efficient. See the - * .fixup section of __xtensa_copy_user for a discussion on the - * X_zeroing equivalents for Xtensa. - */ - extern unsigned __xtensa_copy_user(void *to, const void *from, unsigned n); -#define __copy_user(to, from, size) __xtensa_copy_user(to, from, size) - static inline unsigned long -__generic_copy_from_user_nocheck(void *to, const void *from, unsigned long n) +raw_copy_from_user(void *to, const void __user *from, unsigned long n) { - return __copy_user(to, from, n); -} - -static inline unsigned long -__generic_copy_to_user_nocheck(void *to, const void *from, unsigned long n) -{ - return __copy_user(to, from, n); + prefetchw(to); + return __xtensa_copy_user(to, (__force const void *)from, n); } - static inline unsigned long -__generic_copy_to_user(void *to, const void *from, unsigned long n) +raw_copy_to_user(void __user *to, const void *from, unsigned long n) { prefetch(from); - if (access_ok(VERIFY_WRITE, to, n)) - return __copy_user(to, from, n); - return n; -} - -static inline unsigned long -__generic_copy_from_user(void *to, const void *from, unsigned long n) -{ - prefetchw(to); - if (access_ok(VERIFY_READ, from, n)) - return __copy_user(to, from, n); - else - memset(to, 0, n); - return n; + return __xtensa_copy_user((__force void *)to, from, n); } - -#define copy_to_user(to, from, n) __generic_copy_to_user((to), (from), (n)) -#define copy_from_user(to, from, n) __generic_copy_from_user((to), (from), (n)) -#define __copy_to_user(to, from, n) \ - __generic_copy_to_user_nocheck((to), (from), (n)) -#define __copy_from_user(to, from, n) \ - __generic_copy_from_user_nocheck((to), (from), (n)) -#define __copy_to_user_inatomic __copy_to_user -#define __copy_from_user_inatomic __copy_from_user - +#define INLINE_COPY_FROM_USER +#define INLINE_COPY_TO_USER /* * We need to return the number of bytes not cleared. Our memset() @@ -348,10 +305,4 @@ static inline long strnlen_user(const char *str, long len) return __strnlen_user(str, len); } - -struct exception_table_entry -{ - unsigned long insn, fixup; -}; - #endif /* _XTENSA_UACCESS_H */ diff --git a/arch/xtensa/include/uapi/asm/Kbuild b/arch/xtensa/include/uapi/asm/Kbuild index 56aad54e7fb7..b15bf6bc0e94 100644 --- a/arch/xtensa/include/uapi/asm/Kbuild +++ b/arch/xtensa/include/uapi/asm/Kbuild @@ -1,25 +1,2 @@ # UAPI Header export list include include/uapi/asm-generic/Kbuild.asm - -header-y += auxvec.h -header-y += byteorder.h -header-y += ioctls.h -header-y += ipcbuf.h -header-y += mman.h -header-y += msgbuf.h -header-y += param.h -header-y += poll.h -header-y += posix_types.h -header-y += ptrace.h -header-y += sembuf.h -header-y += setup.h -header-y += shmbuf.h -header-y += sigcontext.h -header-y += signal.h -header-y += socket.h -header-y += sockios.h -header-y += stat.h -header-y += swab.h -header-y += termbits.h -header-y += types.h -header-y += unistd.h diff --git a/arch/xtensa/include/uapi/asm/ptrace.h b/arch/xtensa/include/uapi/asm/ptrace.h index 6ccbd9e38e35..8853a0d544c8 100644 --- a/arch/xtensa/include/uapi/asm/ptrace.h +++ b/arch/xtensa/include/uapi/asm/ptrace.h @@ -11,46 +11,6 @@ #ifndef _UAPI_XTENSA_PTRACE_H #define _UAPI_XTENSA_PTRACE_H -/* - * Kernel stack - * - * +-----------------------+ -------- STACK_SIZE - * | register file | | - * +-----------------------+ | - * | struct pt_regs | | - * +-----------------------+ | ------ PT_REGS_OFFSET - * double : 16 bytes spill area : | ^ - * excetion :- - - - - - - - - - - -: | | - * frame : struct pt_regs : | | - * :- - - - - - - - - - - -: | | - * | | | | - * | memory stack | | | - * | | | | - * ~ ~ ~ ~ - * ~ ~ ~ ~ - * | | | | - * | | | | - * +-----------------------+ | | --- STACK_BIAS - * | struct task_struct | | | ^ - * current --> +-----------------------+ | | | - * | struct thread_info | | | | - * +-----------------------+ -------- - */ - -#define KERNEL_STACK_SIZE (2 * PAGE_SIZE) - -/* Offsets for exception_handlers[] (3 x 64-entries x 4-byte tables). */ - -#define EXC_TABLE_KSTK 0x004 /* Kernel Stack */ -#define EXC_TABLE_DOUBLE_SAVE 0x008 /* Double exception save area for a0 */ -#define EXC_TABLE_FIXUP 0x00c /* Fixup handler */ -#define EXC_TABLE_PARAM 0x010 /* For passing a parameter to fixup */ -#define EXC_TABLE_SYSCALL_SAVE 0x014 /* For fast syscall handler */ -#define EXC_TABLE_FAST_USER 0x100 /* Fast user exception handler */ -#define EXC_TABLE_FAST_KERNEL 0x200 /* Fast kernel exception handler */ -#define EXC_TABLE_DEFAULT 0x300 /* Default C-Handler */ -#define EXC_TABLE_SIZE 0x400 - /* Registers used by strace */ #define REG_A_BASE 0x0000 diff --git a/arch/xtensa/include/uapi/asm/socket.h b/arch/xtensa/include/uapi/asm/socket.h index 9fdbe1fe0473..1eb6d2fe70d3 100644 --- a/arch/xtensa/include/uapi/asm/socket.h +++ b/arch/xtensa/include/uapi/asm/socket.h @@ -103,4 +103,10 @@ #define SCM_TIMESTAMPING_OPT_STATS 54 +#define SO_MEMINFO 55 + +#define SO_INCOMING_NAPI_ID 56 + +#define SO_COOKIE 57 + #endif /* _XTENSA_SOCKET_H */ 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; diff --git a/arch/xtensa/lib/usercopy.S b/arch/xtensa/lib/usercopy.S index 7ea4dd68893e..d9cd766bde3e 100644 --- a/arch/xtensa/lib/usercopy.S +++ b/arch/xtensa/lib/usercopy.S @@ -102,9 +102,9 @@ __xtensa_copy_user: bltui a4, 7, .Lbytecopy # do short copies byte by byte # copy 1 byte - EX(l8ui, a6, a3, 0, l_fixup) + EX(l8ui, a6, a3, 0, fixup) addi a3, a3, 1 - EX(s8i, a6, a5, 0, s_fixup) + EX(s8i, a6, a5, 0, fixup) addi a5, a5, 1 addi a4, a4, -1 bbci.l a5, 1, .Ldstaligned # if dst is now aligned, then @@ -112,11 +112,11 @@ __xtensa_copy_user: .Ldst2mod4: # dst 16-bit aligned # copy 2 bytes bltui a4, 6, .Lbytecopy # do short copies byte by byte - EX(l8ui, a6, a3, 0, l_fixup) - EX(l8ui, a7, a3, 1, l_fixup) + EX(l8ui, a6, a3, 0, fixup) + EX(l8ui, a7, a3, 1, fixup) addi a3, a3, 2 - EX(s8i, a6, a5, 0, s_fixup) - EX(s8i, a7, a5, 1, s_fixup) + EX(s8i, a6, a5, 0, fixup) + EX(s8i, a7, a5, 1, fixup) addi a5, a5, 2 addi a4, a4, -2 j .Ldstaligned # dst is now aligned, return to main algorithm @@ -135,9 +135,9 @@ __xtensa_copy_user: add a7, a3, a4 # a7 = end address for source #endif /* !XCHAL_HAVE_LOOPS */ .Lnextbyte: - EX(l8ui, a6, a3, 0, l_fixup) + EX(l8ui, a6, a3, 0, fixup) addi a3, a3, 1 - EX(s8i, a6, a5, 0, s_fixup) + EX(s8i, a6, a5, 0, fixup) addi a5, a5, 1 #if !XCHAL_HAVE_LOOPS blt a3, a7, .Lnextbyte @@ -161,15 +161,15 @@ __xtensa_copy_user: add a8, a8, a3 # a8 = end of last 16B source chunk #endif /* !XCHAL_HAVE_LOOPS */ .Loop1: - EX(l32i, a6, a3, 0, l_fixup) - EX(l32i, a7, a3, 4, l_fixup) - EX(s32i, a6, a5, 0, s_fixup) - EX(l32i, a6, a3, 8, l_fixup) - EX(s32i, a7, a5, 4, s_fixup) - EX(l32i, a7, a3, 12, l_fixup) - EX(s32i, a6, a5, 8, s_fixup) + EX(l32i, a6, a3, 0, fixup) + EX(l32i, a7, a3, 4, fixup) + EX(s32i, a6, a5, 0, fixup) + EX(l32i, a6, a3, 8, fixup) + EX(s32i, a7, a5, 4, fixup) + EX(l32i, a7, a3, 12, fixup) + EX(s32i, a6, a5, 8, fixup) addi a3, a3, 16 - EX(s32i, a7, a5, 12, s_fixup) + EX(s32i, a7, a5, 12, fixup) addi a5, a5, 16 #if !XCHAL_HAVE_LOOPS blt a3, a8, .Loop1 @@ -177,31 +177,31 @@ __xtensa_copy_user: .Loop1done: bbci.l a4, 3, .L2 # copy 8 bytes - EX(l32i, a6, a3, 0, l_fixup) - EX(l32i, a7, a3, 4, l_fixup) + EX(l32i, a6, a3, 0, fixup) + EX(l32i, a7, a3, 4, fixup) addi a3, a3, 8 - EX(s32i, a6, a5, 0, s_fixup) - EX(s32i, a7, a5, 4, s_fixup) + EX(s32i, a6, a5, 0, fixup) + EX(s32i, a7, a5, 4, fixup) addi a5, a5, 8 .L2: bbci.l a4, 2, .L3 # copy 4 bytes - EX(l32i, a6, a3, 0, l_fixup) + EX(l32i, a6, a3, 0, fixup) addi a3, a3, 4 - EX(s32i, a6, a5, 0, s_fixup) + EX(s32i, a6, a5, 0, fixup) addi a5, a5, 4 .L3: bbci.l a4, 1, .L4 # copy 2 bytes - EX(l16ui, a6, a3, 0, l_fixup) + EX(l16ui, a6, a3, 0, fixup) addi a3, a3, 2 - EX(s16i, a6, a5, 0, s_fixup) + EX(s16i, a6, a5, 0, fixup) addi a5, a5, 2 .L4: bbci.l a4, 0, .L5 # copy 1 byte - EX(l8ui, a6, a3, 0, l_fixup) - EX(s8i, a6, a5, 0, s_fixup) + EX(l8ui, a6, a3, 0, fixup) + EX(s8i, a6, a5, 0, fixup) .L5: movi a2, 0 # return success for len bytes copied retw @@ -217,7 +217,7 @@ __xtensa_copy_user: # copy 16 bytes per iteration for word-aligned dst and unaligned src and a10, a3, a8 # save unalignment offset for below sub a3, a3, a10 # align a3 (to avoid sim warnings only; not needed for hardware) - EX(l32i, a6, a3, 0, l_fixup) # load first word + EX(l32i, a6, a3, 0, fixup) # load first word #if XCHAL_HAVE_LOOPS loopnez a7, .Loop2done #else /* !XCHAL_HAVE_LOOPS */ @@ -226,19 +226,19 @@ __xtensa_copy_user: add a12, a12, a3 # a12 = end of last 16B source chunk #endif /* !XCHAL_HAVE_LOOPS */ .Loop2: - EX(l32i, a7, a3, 4, l_fixup) - EX(l32i, a8, a3, 8, l_fixup) + EX(l32i, a7, a3, 4, fixup) + EX(l32i, a8, a3, 8, fixup) ALIGN( a6, a6, a7) - EX(s32i, a6, a5, 0, s_fixup) - EX(l32i, a9, a3, 12, l_fixup) + EX(s32i, a6, a5, 0, fixup) + EX(l32i, a9, a3, 12, fixup) ALIGN( a7, a7, a8) - EX(s32i, a7, a5, 4, s_fixup) - EX(l32i, a6, a3, 16, l_fixup) + EX(s32i, a7, a5, 4, fixup) + EX(l32i, a6, a3, 16, fixup) ALIGN( a8, a8, a9) - EX(s32i, a8, a5, 8, s_fixup) + EX(s32i, a8, a5, 8, fixup) addi a3, a3, 16 ALIGN( a9, a9, a6) - EX(s32i, a9, a5, 12, s_fixup) + EX(s32i, a9, a5, 12, fixup) addi a5, a5, 16 #if !XCHAL_HAVE_LOOPS blt a3, a12, .Loop2 @@ -246,39 +246,39 @@ __xtensa_copy_user: .Loop2done: bbci.l a4, 3, .L12 # copy 8 bytes - EX(l32i, a7, a3, 4, l_fixup) - EX(l32i, a8, a3, 8, l_fixup) + EX(l32i, a7, a3, 4, fixup) + EX(l32i, a8, a3, 8, fixup) ALIGN( a6, a6, a7) - EX(s32i, a6, a5, 0, s_fixup) + EX(s32i, a6, a5, 0, fixup) addi a3, a3, 8 ALIGN( a7, a7, a8) - EX(s32i, a7, a5, 4, s_fixup) + EX(s32i, a7, a5, 4, fixup) addi a5, a5, 8 mov a6, a8 .L12: bbci.l a4, 2, .L13 # copy 4 bytes - EX(l32i, a7, a3, 4, l_fixup) + EX(l32i, a7, a3, 4, fixup) addi a3, a3, 4 ALIGN( a6, a6, a7) - EX(s32i, a6, a5, 0, s_fixup) + EX(s32i, a6, a5, 0, fixup) addi a5, a5, 4 mov a6, a7 .L13: add a3, a3, a10 # readjust a3 with correct misalignment bbci.l a4, 1, .L14 # copy 2 bytes - EX(l8ui, a6, a3, 0, l_fixup) - EX(l8ui, a7, a3, 1, l_fixup) + EX(l8ui, a6, a3, 0, fixup) + EX(l8ui, a7, a3, 1, fixup) addi a3, a3, 2 - EX(s8i, a6, a5, 0, s_fixup) - EX(s8i, a7, a5, 1, s_fixup) + EX(s8i, a6, a5, 0, fixup) + EX(s8i, a7, a5, 1, fixup) addi a5, a5, 2 .L14: bbci.l a4, 0, .L15 # copy 1 byte - EX(l8ui, a6, a3, 0, l_fixup) - EX(s8i, a6, a5, 0, s_fixup) + EX(l8ui, a6, a3, 0, fixup) + EX(s8i, a6, a5, 0, fixup) .L15: movi a2, 0 # return success for len bytes copied retw @@ -291,30 +291,10 @@ __xtensa_copy_user: * bytes_copied = a5 - a2 * retval = bytes_not_copied = original len - bytes_copied * retval = a11 - (a5 - a2) - * - * Clearing the remaining pieces of kernel memory plugs security - * holes. This functionality is the equivalent of the *_zeroing - * functions that some architectures provide. */ -.Lmemset: - .word memset -s_fixup: +fixup: sub a2, a5, a2 /* a2 <-- bytes copied */ sub a2, a11, a2 /* a2 <-- bytes not copied */ retw - -l_fixup: - sub a2, a5, a2 /* a2 <-- bytes copied */ - sub a2, a11, a2 /* a2 <-- bytes not copied == return value */ - - /* void *memset(void *s, int c, size_t n); */ - mov a6, a5 /* s */ - movi a7, 0 /* c */ - mov a8, a2 /* n */ - l32r a4, .Lmemset - callx4 a4 - /* Ignore memset return value in a6. */ - /* a2 still contains bytes not copied. */ - retw diff --git a/arch/xtensa/platforms/iss/include/platform/simcall.h b/arch/xtensa/platforms/iss/include/platform/simcall.h index 27d7a528b41a..2ba45858e50a 100644 --- a/arch/xtensa/platforms/iss/include/platform/simcall.h +++ b/arch/xtensa/platforms/iss/include/platform/simcall.h @@ -6,6 +6,7 @@ * for more details. * * Copyright (C) 2001 Tensilica Inc. + * Copyright (C) 2017 Cadence Design Systems Inc. */ #ifndef _XTENSA_PLATFORM_ISS_SIMCALL_H @@ -49,6 +50,10 @@ #define SYS_bind 30 #define SYS_ioctl 31 +#define SYS_iss_argc 1000 /* returns value of argc */ +#define SYS_iss_argv_size 1001 /* bytes needed for argv & arg strings */ +#define SYS_iss_set_argv 1002 /* saves argv & arg strings at given addr */ + /* * SYS_select_one specifiers */ @@ -118,5 +123,20 @@ static inline int simc_lseek(int fd, uint32_t off, int whence) return __simc(SYS_lseek, fd, off, whence); } +static inline int simc_argc(void) +{ + return __simc(SYS_iss_argc, 0, 0, 0); +} + +static inline int simc_argv_size(void) +{ + return __simc(SYS_iss_argv_size, 0, 0, 0); +} + +static inline void simc_argv(void *buf) +{ + __simc(SYS_iss_set_argv, (int)buf, 0, 0); +} + #endif /* _XTENSA_PLATFORM_ISS_SIMCALL_H */ diff --git a/arch/xtensa/platforms/iss/setup.c b/arch/xtensa/platforms/iss/setup.c index 379aeddcc638..f4bbb28026f8 100644 --- a/arch/xtensa/platforms/iss/setup.c +++ b/arch/xtensa/platforms/iss/setup.c @@ -8,6 +8,7 @@ * Joe Taylor <joe@tensilica.com> * * Copyright 2001 - 2005 Tensilica Inc. + * Copyright 2017 Cadence Design Systems Inc. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -15,6 +16,7 @@ * option) any later version. * */ +#include <linux/bootmem.h> #include <linux/stddef.h> #include <linux/kernel.h> #include <linux/init.h> @@ -31,13 +33,13 @@ #include <asm/platform.h> #include <asm/bootparam.h> +#include <asm/setup.h> #include <platform/simcall.h> void __init platform_init(bp_tag_t* bootparam) { - } void platform_halt(void) @@ -59,26 +61,10 @@ void platform_restart(void) /* control never gets here */ } -extern void iss_net_poll(void); - -const char twirl[]="|/-\\|/-\\"; - void platform_heartbeat(void) { -#if 0 - static int i = 0, j = 0; - - if (--i < 0) { - i = 99; - printk("\r%c\r", twirl[j++]); - if (j == 8) - j = 0; - } -#endif } - - static int iss_panic_event(struct notifier_block *this, unsigned long event, void *ptr) { @@ -87,12 +73,29 @@ iss_panic_event(struct notifier_block *this, unsigned long event, void *ptr) } static struct notifier_block iss_panic_block = { - iss_panic_event, - NULL, - 0 + .notifier_call = iss_panic_event, }; void __init platform_setup(char **p_cmdline) { + int argc = simc_argc(); + int argv_size = simc_argv_size(); + + if (argc > 1) { + void **argv = alloc_bootmem(argv_size); + char *cmdline = alloc_bootmem(argv_size); + int i; + + cmdline[0] = 0; + simc_argv((void *)argv); + + for (i = 1; i < argc; ++i) { + if (i > 1) + strcat(cmdline, " "); + strcat(cmdline, argv[i]); + } + *p_cmdline = cmdline; + } + atomic_notifier_chain_register(&panic_notifier_list, &iss_panic_block); } |