Merge tag 'xtensa-20170507' of git://github.com/jcmvbkbc/linux-xtensa
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 8 May 2017 19:29:46 +0000 (12:29 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 8 May 2017 19:29:46 +0000 (12:29 -0700)
Pull Xtensa updates from Max Filippov:

 - clearly mark references to spilled register locations with SPILL_SLOT
   macros

 - clean up xtensa ptrace: use generic tracehooks, move internal kernel
   definitions from uapi/asm to asm, make locally-used functions static,
   fix code style and alignment

 - use command line parameters passed to ISS as kernel command line.

* tag 'xtensa-20170507' of git://github.com/jcmvbkbc/linux-xtensa:
  xtensa: clean up access to spilled registers locations
  xtensa: use generic tracehooks
  xtensa: move internal ptrace definitions from uapi/asm to asm
  xtensa: clean up xtensa/kernel/ptrace.c
  xtensa: drop unused fast_io_protect function
  xtensa: use ITLB_HIT_BIT instead of hardcoded number
  xtensa: ISS: update kernel command line in platform_setup
  xtensa: ISS: add argc/argv simcall definitions
  xtensa: ISS: cleanup setup.c

12 files changed:
arch/xtensa/include/asm/processor.h
arch/xtensa/include/asm/ptrace.h
arch/xtensa/include/uapi/asm/ptrace.h
arch/xtensa/kernel/coprocessor.S
arch/xtensa/kernel/entry.S
arch/xtensa/kernel/process.c
arch/xtensa/kernel/ptrace.c
arch/xtensa/kernel/setup.c
arch/xtensa/kernel/signal.c
arch/xtensa/kernel/stacktrace.c
arch/xtensa/platforms/iss/include/platform/simcall.h
arch/xtensa/platforms/iss/setup.c

index 86ffcd68e49616e62d693bad4cae85ffbae0582e..003eeee3fbc636d91aed849aaa39bb0c24370227 100644 (file)
  */
 #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;
index 598e752dcbcd009392230869af2851afd14e4085..e2d9c5eb10bdf2356c1404cb02c212c90f5cb556 100644 (file)
 
 #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__
 
index 6ccbd9e38e3516e6f89f70518bf2a43aa4657985..8853a0d544c842c3135ee6a4d97e883be2199d22 100644 (file)
 #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
index 6911e384f6080dd27bc910f80b98c415eb379140..3a98503ad11a66ab553075a9dd00b0f3314cf5e6 100644 (file)
 #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
 
 /*
index f5ef3cc0497c39272904dd09f3690dad03f1f565..37a239556889c0cc3912d921585879c4abd98876 100644 (file)
@@ -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
index 58f96d1230d4d57e8bebb6417834581690b61f1a..ff4f0ecb03dd1e9dfcab581eaa2afd55d7a1b374 100644 (file)
@@ -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.
index e0f583fed06a4067bca403ee4331c45d2082d348..e2461968efb244c93e2f315056b9431d4421ee12 100644 (file)
@@ -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
 #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);
 }
index 197e75b400b169f6014e801744cdd4030f11f370..394ef08300b6a3188b196155e0863bf2360fef93 100644 (file)
@@ -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));
 
                /*
index 70a131945443841358c56b35fd157e66b2d22290..d427e784ab44cd018b4a3b1aaa7739987e51b6cd 100644 (file)
@@ -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),
-                                          &regs->areg[(base + 1) * 4], 16))
+                       if (copy_to_user(&SPILL_SLOT_CALL8(sp, 4),
+                                        &regs->areg[(base + 1) * 4], 16))
                                goto errout;
                        inc = 2;
 
                } else if (m & 8) {     /* call12 */
-                       if (copy_to_user((void*)(sp - 48),
-                                          &regs->areg[(base + 1) * 4], 32))
+                       if (copy_to_user(&SPILL_SLOT_CALL12(sp, 4),
+                                        &regs->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), &regs->areg[base * 4], 16))
+               if (copy_to_user(&SPILL_SLOT(sp, 0), &regs->areg[base * 4], 16))
                        goto errout;
 
                /* Get current stack pointer for next loop iteration. */
index e7d30ee0fd482794a21f72c85ca2feb2ec4b5500..0df4080fa20f2276563eb64f8694959548a3f557 100644 (file)
  */
 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;
index 27d7a528b41ae53d35c9ac24f0d75b4046a7de53..2ba45858e50a3db125b1e30b730739ffb667cb55 100644 (file)
@@ -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
 #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 */
 
index 379aeddcc63886c9368bfab1d4189ef8f21837da..f4bbb28026f8be3006890fe236989db791c79e1d 100644 (file)
@@ -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>
 
 #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);
 }