summaryrefslogtreecommitdiff
path: root/arch/xtensa
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-05-08 12:29:46 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2017-05-08 12:29:46 -0700
commitd9dc089583ebf28d6f02b995e2d71c85965660f9 (patch)
tree8e2beb1719d8891d6eec2bbdc809fc0997ba29f6 /arch/xtensa
parent70ef8f0d37573079e093305214d0cc9eb71100f7 (diff)
parent2a4e669dd611855d89d938063c10f44cb67ce65d (diff)
Merge tag 'xtensa-20170507' of git://github.com/jcmvbkbc/linux-xtensa
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
Diffstat (limited to 'arch/xtensa')
-rw-r--r--arch/xtensa/include/asm/processor.h15
-rw-r--r--arch/xtensa/include/asm/ptrace.h39
-rw-r--r--arch/xtensa/include/uapi/asm/ptrace.h40
-rw-r--r--arch/xtensa/kernel/coprocessor.S24
-rw-r--r--arch/xtensa/kernel/entry.S3
-rw-r--r--arch/xtensa/kernel/process.c8
-rw-r--r--arch/xtensa/kernel/ptrace.c170
-rw-r--r--arch/xtensa/kernel/setup.c9
-rw-r--r--arch/xtensa/kernel/signal.c10
-rw-r--r--arch/xtensa/kernel/stacktrace.c35
-rw-r--r--arch/xtensa/platforms/iss/include/platform/simcall.h20
-rw-r--r--arch/xtensa/platforms/iss/setup.c43
12 files changed, 197 insertions, 219 deletions
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/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/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/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 197e75b400b1..394ef08300b6 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),
- &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. */
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/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);
}