mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-17 09:43:59 +08:00
Xtensa updates for v4.12
- 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. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJZD1w5AAoJEFH5zJH4P6BEFAwP+gM22rd9BA5QVHbosqlGVwiv /GLfMSTbeO9OEIF9+YOakfzwYWFUXMrT3SjQ8WPE1e7sY61rdggUMfIvXafbgXiE Rj/pNXSQmN4jQpeDvRuGBgdl0V5QCsQ+czmQupv3xREgt/Q5iJiFQKvPprawaFMe HlXS8+RV6n0D+8C7xxyDqYuahfXmqPZB9fwV/AB2z/ccnARnIs72C6qzOQlffTKF mTxQWPQ6bvTTgHdNozWNVUfCNfy9Npf6sFg9jrx317r0CW1dBcaaNokFHYD+UGcC HBKMtmHBdV1KpwNwBl5Ucj7efsVj0JdQOhM37WCfQhx+GPhPbyw4JQ5Cr4JvFHCA PmYj1AaeCaeQfAfSqZQcORSFJUCFAkk8uydzWTIzp9pzItwTsYnkG2ETNRbHABPv puTPnvrfGvkY8VFm6DdaF+ga470rUnHWtDE+BcmPImpG2bj/LGW7NaOtR0xrxRKe ztQbNAN9w8n1J00FGnEc6UO0sroLFObzP0AujHEdjaCozC2HpI0H1nuiAPtEHTTs MSynWyPaE/lA9DsRknfe3BiPVYXCK5BKSCorKZhzMFydpLHD7AxlqPJBnpaSK0aG xZ6umtZ2bGrnXWXRrFREZ6YfrjQbQ1Ffv+NTYZsLREPWDa3gE3/jDmhWkETnz1iN u+DcKJnTh0gYDAV/B98q =Jcjj -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
d9dc089583
@ -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;
|
||||
|
@ -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__
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
/*
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
unsigned long do_syscall_trace_enter(struct pt_regs *regs)
|
||||
{
|
||||
/*
|
||||
* 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));
|
||||
if (test_thread_flag(TIF_SYSCALL_TRACE) &&
|
||||
tracehook_report_syscall_entry(regs))
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
if (test_thread_flag(TIF_SYSCALL_TRACE)
|
||||
&& (current->ptrace & PT_PTRACED))
|
||||
do_syscall_trace();
|
||||
|
||||
#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);
|
||||
}
|
||||
|
@ -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));
|
||||
|
||||
/*
|
||||
|
@ -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. */
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user