Commit d9dc0895 authored by Linus Torvalds's avatar Linus Torvalds

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
parents 70ef8f0d 2a4e669d
...@@ -113,6 +113,21 @@ ...@@ -113,6 +113,21 @@
*/ */
#define MAKE_PC_FROM_RA(ra,sp) (((ra) & 0x3fffffff) | ((sp) & 0xc0000000)) #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 { typedef struct {
unsigned long seg; unsigned long seg;
} mm_segment_t; } mm_segment_t;
......
...@@ -12,6 +12,45 @@ ...@@ -12,6 +12,45 @@
#include <uapi/asm/ptrace.h> #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__ #ifndef __ASSEMBLY__
......
...@@ -11,46 +11,6 @@ ...@@ -11,46 +11,6 @@
#ifndef _UAPI_XTENSA_PTRACE_H #ifndef _UAPI_XTENSA_PTRACE_H
#define _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 */ /* Registers used by strace */
#define REG_A_BASE 0x0000 #define REG_A_BASE 0x0000
......
...@@ -26,30 +26,6 @@ ...@@ -26,30 +26,6 @@
#include <asm/signal.h> #include <asm/signal.h>
#include <asm/tlbflush.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 #if XTENSA_HAVE_COPROCESSORS
/* /*
......
...@@ -1899,10 +1899,11 @@ ENTRY(system_call) ...@@ -1899,10 +1899,11 @@ ENTRY(system_call)
movi a4, do_syscall_trace_enter movi a4, do_syscall_trace_enter
s32i a3, a2, PT_SYSCALL s32i a3, a2, PT_SYSCALL
callx4 a4 callx4 a4
mov a3, a6
/* syscall = sys_call_table[syscall_nr] */ /* syscall = sys_call_table[syscall_nr] */
movi a4, sys_call_table; movi a4, sys_call_table
movi a5, __NR_syscall_count movi a5, __NR_syscall_count
movi a6, -ENOSYS movi a6, -ENOSYS
bgeu a3, a5, 1f bgeu a3, a5, 1f
......
...@@ -204,8 +204,8 @@ int copy_thread(unsigned long clone_flags, unsigned long usp_thread_fn, ...@@ -204,8 +204,8 @@ int copy_thread(unsigned long clone_flags, unsigned long usp_thread_fn,
#endif #endif
/* Create a call4 dummy-frame: a0 = 0, a1 = childregs. */ /* Create a call4 dummy-frame: a0 = 0, a1 = childregs. */
*((int*)childregs - 3) = (unsigned long)childregs; SPILL_SLOT(childregs, 1) = (unsigned long)childregs;
*((int*)childregs - 4) = 0; SPILL_SLOT(childregs, 0) = 0;
p->thread.sp = (unsigned long)childregs; p->thread.sp = (unsigned long)childregs;
...@@ -266,8 +266,8 @@ int copy_thread(unsigned long clone_flags, unsigned long usp_thread_fn, ...@@ -266,8 +266,8 @@ int copy_thread(unsigned long clone_flags, unsigned long usp_thread_fn,
/* pass parameters to ret_from_kernel_thread: /* pass parameters to ret_from_kernel_thread:
* a2 = thread_fn, a3 = thread_fn arg * a2 = thread_fn, a3 = thread_fn arg
*/ */
*((int *)childregs - 1) = thread_fn_arg; SPILL_SLOT(childregs, 3) = thread_fn_arg;
*((int *)childregs - 2) = usp_thread_fn; SPILL_SLOT(childregs, 2) = usp_thread_fn;
/* Childregs are only used when we're going to userspace /* Childregs are only used when we're going to userspace
* in which case start_thread will set them up. * in which case start_thread will set them up.
......
// TODO some minor issues
/* /*
* This file is subject to the terms and conditions of the GNU General Public * 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 * License. See the file "COPYING" in the main directory of this archive
...@@ -24,13 +23,14 @@ ...@@ -24,13 +23,14 @@
#include <linux/security.h> #include <linux/security.h>
#include <linux/signal.h> #include <linux/signal.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/tracehook.h>
#include <linux/uaccess.h>
#include <asm/coprocessor.h> #include <asm/coprocessor.h>
#include <asm/elf.h> #include <asm/elf.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/ptrace.h> #include <asm/ptrace.h>
#include <linux/uaccess.h>
void user_enable_single_step(struct task_struct *child) void user_enable_single_step(struct task_struct *child)
...@@ -52,7 +52,7 @@ void ptrace_disable(struct task_struct *child) ...@@ -52,7 +52,7 @@ void ptrace_disable(struct task_struct *child)
/* Nothing to do.. */ /* 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); struct pt_regs *regs = task_pt_regs(child);
xtensa_gregset_t __user *gregset = uregs; xtensa_gregset_t __user *gregset = uregs;
...@@ -78,7 +78,7 @@ int ptrace_getregs(struct task_struct *child, void __user *uregs) ...@@ -78,7 +78,7 @@ int ptrace_getregs(struct task_struct *child, void __user *uregs)
return 0; 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); struct pt_regs *regs = task_pt_regs(child);
xtensa_gregset_t *gregset = uregs; xtensa_gregset_t *gregset = uregs;
...@@ -127,7 +127,7 @@ int ptrace_setregs(struct task_struct *child, void __user *uregs) ...@@ -127,7 +127,7 @@ int ptrace_setregs(struct task_struct *child, void __user *uregs)
} }
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 pt_regs *regs = task_pt_regs(child);
struct thread_info *ti = task_thread_info(child); struct thread_info *ti = task_thread_info(child);
...@@ -151,7 +151,7 @@ int ptrace_getxregs(struct task_struct *child, void __user *uregs) ...@@ -151,7 +151,7 @@ int ptrace_getxregs(struct task_struct *child, void __user *uregs)
return ret ? -EFAULT : 0; 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 thread_info *ti = task_thread_info(child);
struct pt_regs *regs = task_pt_regs(child); struct pt_regs *regs = task_pt_regs(child);
...@@ -177,7 +177,8 @@ int ptrace_setxregs(struct task_struct *child, void __user *uregs) ...@@ -177,7 +177,8 @@ int ptrace_setxregs(struct task_struct *child, void __user *uregs)
return ret ? -EFAULT : 0; 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; struct pt_regs *regs;
unsigned long tmp; unsigned long tmp;
...@@ -186,7 +187,6 @@ int ptrace_peekusr(struct task_struct *child, long regno, long __user *ret) ...@@ -186,7 +187,6 @@ int ptrace_peekusr(struct task_struct *child, long regno, long __user *ret)
tmp = 0; /* Default return value. */ tmp = 0; /* Default return value. */
switch(regno) { switch(regno) {
case REG_AR_BASE ... REG_AR_BASE + XCHAL_NUM_AREGS - 1: case REG_AR_BASE ... REG_AR_BASE + XCHAL_NUM_AREGS - 1:
tmp = regs->areg[regno - REG_AR_BASE]; tmp = regs->areg[regno - REG_AR_BASE];
break; break;
...@@ -202,7 +202,8 @@ int ptrace_peekusr(struct task_struct *child, long regno, long __user *ret) ...@@ -202,7 +202,8 @@ int ptrace_peekusr(struct task_struct *child, long regno, long __user *ret)
case REG_PS: case REG_PS:
/* Note: PS.EXCM is not set while user task is running; /* Note: PS.EXCM is not set while user task is running;
* its being set in regs is for exception handling * its being set in regs is for exception handling
* convenience. */ * convenience.
*/
tmp = (regs->ps & ~(1 << PS_EXCM_BIT)); tmp = (regs->ps & ~(1 << PS_EXCM_BIT));
break; break;
...@@ -213,7 +214,8 @@ int ptrace_peekusr(struct task_struct *child, long regno, long __user *ret) ...@@ -213,7 +214,8 @@ int ptrace_peekusr(struct task_struct *child, long regno, long __user *ret)
{ {
unsigned long wb = regs->windowbase; unsigned long wb = regs->windowbase;
unsigned long ws = regs->windowstart; unsigned long ws = regs->windowstart;
tmp = ((ws>>wb) | (ws<<(WSBITS-wb))) & ((1<<WSBITS)-1); tmp = ((ws >> wb) | (ws << (WSBITS - wb))) &
((1 << WSBITS) - 1);
break; break;
} }
case REG_LBEG: case REG_LBEG:
...@@ -242,7 +244,7 @@ int ptrace_peekusr(struct task_struct *child, long regno, long __user *ret) ...@@ -242,7 +244,7 @@ int ptrace_peekusr(struct task_struct *child, long regno, long __user *ret)
return put_user(tmp, ret); 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; struct pt_regs *regs;
regs = task_pt_regs(child); regs = task_pt_regs(child);
...@@ -467,39 +469,21 @@ long arch_ptrace(struct task_struct *child, long request, ...@@ -467,39 +469,21 @@ long arch_ptrace(struct task_struct *child, long request,
return ret; return ret;
} }
void do_syscall_trace(void) unsigned long do_syscall_trace_enter(struct pt_regs *regs)
{ {
/* if (test_thread_flag(TIF_SYSCALL_TRACE) &&
* The 0x80 provides a way for the tracing parent to distinguish tracehook_report_syscall_entry(regs))
* between a syscall stop and SIGTRAP delivery return -1;
*/
ptrace_notify(SIGTRAP|((current->ptrace & PT_TRACESYSGOOD) ? 0x80 : 0));
/* return regs->areg[2];
* 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) void do_syscall_trace_leave(struct pt_regs *regs)
{ {
if (test_thread_flag(TIF_SYSCALL_TRACE) int step;
&& (current->ptrace & PT_PTRACED))
do_syscall_trace();
#if 0 step = test_thread_flag(TIF_SINGLESTEP);
audit_syscall_entry(...);
#endif
}
void do_syscall_trace_leave(struct pt_regs *regs) if (step || test_thread_flag(TIF_SYSCALL_TRACE))
{ tracehook_report_syscall_exit(regs, step);
if ((test_thread_flag(TIF_SYSCALL_TRACE))
&& (current->ptrace & PT_PTRACED))
do_syscall_trace();
} }
...@@ -317,8 +317,9 @@ static inline int mem_reserve(unsigned long start, unsigned long end) ...@@ -317,8 +317,9 @@ static inline int mem_reserve(unsigned long start, unsigned long end)
void __init setup_arch(char **cmdline_p) void __init setup_arch(char **cmdline_p)
{ {
strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
*cmdline_p = command_line; *cmdline_p = command_line;
platform_setup(cmdline_p);
strlcpy(boot_command_line, *cmdline_p, COMMAND_LINE_SIZE);
/* Reserve some memory regions */ /* Reserve some memory regions */
...@@ -382,8 +383,6 @@ void __init setup_arch(char **cmdline_p) ...@@ -382,8 +383,6 @@ void __init setup_arch(char **cmdline_p)
unflatten_and_copy_device_tree(); unflatten_and_copy_device_tree();
platform_setup(cmdline_p);
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
smp_init_cpus(); smp_init_cpus();
#endif #endif
...@@ -453,9 +452,9 @@ void cpu_reset(void) ...@@ -453,9 +452,9 @@ void cpu_reset(void)
tmpaddr += SZ_512M; tmpaddr += SZ_512M;
/* Invalidate mapping in the selected temporary area */ /* 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)); 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)); invalidate_itlb_entry(itlb_probe(tmpaddr + PAGE_SIZE));
/* /*
......
...@@ -91,13 +91,13 @@ flush_window_regs_user(struct pt_regs *regs) ...@@ -91,13 +91,13 @@ flush_window_regs_user(struct pt_regs *regs)
inc = 1; inc = 1;
} else if (m & 4) { /* call8 */ } else if (m & 4) { /* call8 */
if (copy_to_user((void*)(sp - 32), if (copy_to_user(&SPILL_SLOT_CALL8(sp, 4),
&regs->areg[(base + 1) * 4], 16)) &regs->areg[(base + 1) * 4], 16))
goto errout; goto errout;
inc = 2; inc = 2;
} else if (m & 8) { /* call12 */ } else if (m & 8) { /* call12 */
if (copy_to_user((void*)(sp - 48), if (copy_to_user(&SPILL_SLOT_CALL12(sp, 4),
&regs->areg[(base + 1) * 4], 32)) &regs->areg[(base + 1) * 4], 32))
goto errout; goto errout;
inc = 3; inc = 3;
...@@ -106,7 +106,7 @@ flush_window_regs_user(struct pt_regs *regs) ...@@ -106,7 +106,7 @@ flush_window_regs_user(struct pt_regs *regs)
/* Save current frame a0..a3 under next SP */ /* Save current frame a0..a3 under next SP */
sp = regs->areg[((base + inc) * 4 + 1) % XCHAL_NUM_AREGS]; 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; goto errout;
/* Get current stack pointer for next loop iteration. */ /* Get current stack pointer for next loop iteration. */
......
...@@ -23,14 +23,6 @@ ...@@ -23,14 +23,6 @@
*/ */
extern int common_exception_return; 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, void xtensa_backtrace_user(struct pt_regs *regs, unsigned int depth,
int (*ufn)(struct stackframe *frame, void *data), int (*ufn)(struct stackframe *frame, void *data),
void *data) void *data)
...@@ -96,26 +88,16 @@ void xtensa_backtrace_user(struct pt_regs *regs, unsigned int depth, ...@@ -96,26 +88,16 @@ void xtensa_backtrace_user(struct pt_regs *regs, unsigned int depth,
/* Start from the a1 register. */ /* Start from the a1 register. */
/* a1 = regs->areg[1]; */ /* a1 = regs->areg[1]; */
while (a0 != 0 && depth--) { while (a0 != 0 && depth--) {
struct frame_start frame_start; pc = MAKE_PC_FROM_RA(a0, pc);
/* Get the location for a1, a0 for the
* previous frame from the current a1.
*/
unsigned long *psp = (unsigned long *)a1;
psp -= 4;
/* Check if the region is OK to access. */ /* 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; return;
/* Copy a1, a0 from user space stack frame. */ /* Copy a1, a0 from user space stack frame. */
if (__copy_from_user_inatomic(&frame_start, psp, if (__get_user(a0, &SPILL_SLOT(a1, 0)) ||
sizeof(frame_start))) __get_user(a1, &SPILL_SLOT(a1, 1)))
return; return;
pc = MAKE_PC_FROM_RA(a0, pc);
a0 = frame_start.a0;
a1 = frame_start.a1;
frame.pc = pc; frame.pc = pc;
frame.sp = a1; frame.sp = a1;
...@@ -147,7 +129,6 @@ void xtensa_backtrace_kernel(struct pt_regs *regs, unsigned int depth, ...@@ -147,7 +129,6 @@ void xtensa_backtrace_kernel(struct pt_regs *regs, unsigned int depth,
*/ */
while (a1 > sp_start && a1 < sp_end && depth--) { while (a1 > sp_start && a1 < sp_end && depth--) {
struct stackframe frame; struct stackframe frame;
unsigned long *psp = (unsigned long *)a1;
frame.pc = pc; frame.pc = pc;
frame.sp = a1; frame.sp = a1;
...@@ -171,8 +152,8 @@ void xtensa_backtrace_kernel(struct pt_regs *regs, unsigned int depth, ...@@ -171,8 +152,8 @@ void xtensa_backtrace_kernel(struct pt_regs *regs, unsigned int depth,
sp_start = a1; sp_start = a1;
pc = MAKE_PC_FROM_RA(a0, pc); pc = MAKE_PC_FROM_RA(a0, pc);
a0 = *(psp - 4); a0 = SPILL_SLOT(a1, 0);
a1 = *(psp - 3); a1 = SPILL_SLOT(a1, 1);
} }
} }
EXPORT_SYMBOL(xtensa_backtrace_kernel); EXPORT_SYMBOL(xtensa_backtrace_kernel);
...@@ -196,8 +177,8 @@ void walk_stackframe(unsigned long *sp, ...@@ -196,8 +177,8 @@ void walk_stackframe(unsigned long *sp,
sp = (unsigned long *)a1; sp = (unsigned long *)a1;
a0 = *(sp - 4); a0 = SPILL_SLOT(a1, 0);
a1 = *(sp - 3); a1 = SPILL_SLOT(a1, 1);
if (a1 <= (unsigned long)sp) if (a1 <= (unsigned long)sp)
break; break;
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
* for more details. * for more details.
* *
* Copyright (C) 2001 Tensilica Inc. * Copyright (C) 2001 Tensilica Inc.
* Copyright (C) 2017 Cadence Design Systems Inc.
*/ */
#ifndef _XTENSA_PLATFORM_ISS_SIMCALL_H #ifndef _XTENSA_PLATFORM_ISS_SIMCALL_H
...@@ -49,6 +50,10 @@ ...@@ -49,6 +50,10 @@
#define SYS_bind 30 #define SYS_bind 30
#define SYS_ioctl 31 #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 * SYS_select_one specifiers
*/ */
...@@ -118,5 +123,20 @@ static inline int simc_lseek(int fd, uint32_t off, int whence) ...@@ -118,5 +123,20 @@ static inline int simc_lseek(int fd, uint32_t off, int whence)
return __simc(SYS_lseek, fd, off, 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 */ #endif /* _XTENSA_PLATFORM_ISS_SIMCALL_H */
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
* Joe Taylor <joe@tensilica.com> * Joe Taylor <joe@tensilica.com>
* *
* Copyright 2001 - 2005 Tensilica Inc. * Copyright 2001 - 2005 Tensilica Inc.
* Copyright 2017 Cadence Design Systems Inc.
* *
* This program is free software; you can redistribute it and/or modify it * 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 * under the terms of the GNU General Public License as published by the
...@@ -15,6 +16,7 @@ ...@@ -15,6 +16,7 @@
* option) any later version. * option) any later version.
* *
*/ */
#include <linux/bootmem.h>
#include <linux/stddef.h> #include <linux/stddef.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/init.h> #include <linux/init.h>
...@@ -31,13 +33,13 @@ ...@@ -31,13 +33,13 @@
#include <asm/platform.h> #include <asm/platform.h>
#include <asm/bootparam.h> #include <asm/bootparam.h>
#include <asm/setup.h>
#include <platform/simcall.h> #include <platform/simcall.h>
void __init platform_init(bp_tag_t* bootparam) void __init platform_init(bp_tag_t* bootparam)
{ {
} }
void platform_halt(void) void platform_halt(void)
...@@ -59,26 +61,10 @@ void platform_restart(void) ...@@ -59,26 +61,10 @@ void platform_restart(void)
/* control never gets here */ /* control never gets here */
} }
extern void iss_net_poll(void);
const char twirl[]="|/-\\|/-\\";
void platform_heartbeat(void) 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 static int
iss_panic_event(struct notifier_block *this, unsigned long event, void *ptr) 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) ...@@ -87,12 +73,29 @@ iss_panic_event(struct notifier_block *this, unsigned long event, void *ptr)
} }
static struct notifier_block iss_panic_block = { static struct notifier_block iss_panic_block = {
iss_panic_event, .notifier_call = iss_panic_event,
NULL,
0
}; };
void __init platform_setup(char **p_cmdline) 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); atomic_notifier_chain_register(&panic_notifier_list, &iss_panic_block);
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment